Adding a New Application¶
This runbook walks through adding a new application to the cluster. All apps are deployed as ArgoCD Applications generated by an ApplicationSet. Each app has a config.yaml (metadata), values.yaml (Helm values), and optionally a kustomization.yaml (supporting resources). The ApplicationSet discovers new apps automatically.
Step 1: Create the Application Directory¶
Create a directory for the new app under the appropriate location:
- Media/arr apps:
k8s/clusters/homelabk8s01/apps/arr/<app-name>/ - Other apps:
k8s/clusters/homelabk8s01/apps/<app-name>/
mkdir -p k8s/clusters/homelabk8s01/apps/arr/<app-name>
Step 2: Create config.yaml¶
Create config.yaml with the app metadata. This is what the ApplicationSet discovers.
appName: arr-<app-name>
namespace: arr
sourceType: helm
chartRepo: https://bjw-s-labs.github.io/helm-charts
chartName: app-template
chartVersion: "4.6.2"
createNamespace: false
hasResources: false
syncOptions:
- ServerSideApply=true
- ServerSideDiff=true
Key Fields¶
| Field | Description |
|---|---|
appName |
Unique name for the ArgoCD Application (prefix with arr- for media apps) |
namespace |
Target namespace (arr for media apps, or set createNamespace: true for a new one) |
chartVersion |
Helm chart version -- always quote it ("4.6.2") |
hasResources |
Set to true if the app has supporting resources (PDBs, ExternalSecrets, HTTPRoutes) |
createNamespace |
true for single-app namespaces, false for arr (managed by arr-prereqs) |
Step 3: Create values.yaml¶
Create values.yaml with the Helm chart values.
Minimal Template¶
defaultPodOptions:
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
runAsNonRoot: true
controllers:
main:
containers:
main:
image:
repository: <image-repository>
tag: <image-tag>
envFrom:
- configMapRef:
name: arr-env
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 512Mi
probes:
liveness:
enabled: true
readiness:
enabled: true
startup:
enabled: true
service:
main:
controller: main
ports:
http:
port: <port>
route:
main:
enabled: true
kind: HTTPRoute
parentRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: homelab-gateway
namespace: default
sectionName: https
hostnames:
- <app-name>.homelab.local
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: arr-<app-name>
port: <port>
persistence:
tmp:
type: emptyDir
globalMounts:
- path: /tmp
config:
type: persistentVolumeClaim
storageClass: nfs-client
accessMode: ReadWriteOnce
size: 1Gi
globalMounts:
- path: /config
data:
type: persistentVolumeClaim
existingClaim: arr-data
globalMounts:
- path: /data
Replace the <placeholder> values with your application's specifics.
Tip
Use an existing app's values.yaml as a starting point. The Sonarr values at k8s/clusters/homelabk8s01/apps/arr/sonarr/values.yaml is a good reference for a typical arr-stack application.
linuxserver.io images
If the image is from linuxserver.io, you will need to remove readOnlyRootFilesystem: true and add SETUID/SETGID capabilities for the s6-overlay init system. See the Sonarr or Radarr values for examples.
Step 4: Add Secrets (If Needed)¶
If the application requires secrets (API keys, credentials, etc.):
-
Create an ExternalSecret manifest in the app directory (e.g.,
<app-name>-external-secret.yml):apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: name: <app-name>-secrets namespace: arr spec: refreshInterval: 1h secretStoreRef: kind: ClusterSecretStore name: vault-backend target: name: <app-name>-secrets data: - secretKey: API_KEY remoteRef: key: apps/<app-name> property: API_KEY conversionStrategy: Default decodingStrategy: None metadataPolicy: None -
Create a
kustomization.yamllisting the supporting resource:apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - <app-name>-external-secret.yml -
Set
hasResources: trueinconfig.yaml. -
Write the actual values to Vault:
vault kv put homelab/apps/<app-name> API_KEY=your_real_key -
Reference the secret in
values.yamlviaenvFromorenv.valueFrom.
Step 5: Add a DNS Entry¶
Add a DNS record for the new hostname (<app-name>.homelab.local) pointing to the Cilium L2 VIP assigned to the homelab-gateway. The gateway IP can be found with:
kubectl get gateway homelab-gateway -n default -o jsonpath='{.status.addresses[0].value}'
Step 6: Commit and Push¶
git add k8s/clusters/homelabk8s01/apps/arr/<app-name>/
git commit -m "add <app-name>"
git push
The ApplicationSet's Git File Generator automatically discovers the new config.yaml and generates an Application. Monitor the deployment in the ArgoCD UI at https://argocd.homelab.local.
Verification¶
-
Check that ArgoCD picked up the new application:
kubectl get application -n argocd arr-<app-name> -
Verify the pod is running:
kubectl get pods -n arr -l app.kubernetes.io/instance=arr-<app-name> -
Open the web UI at
https://<app-name>.homelab.localand confirm it loads.