Adding a New Application¶
Adding a new application to the cluster requires no ArgoCD configuration changes. Thanks to the ApplicationSet pattern, creating a directory in the right place is all it takes.
Quick Start¶
To deploy a new application, you need to:
- Choose the appropriate category for your app.
- Create a directory under
kubernetes/apps/pitower/<category>/<app-name>/. - Add a
kustomization.yamland (optionally) avalues.yaml. - Push to
main. - ArgoCD auto-discovers and syncs the new app.
flowchart LR
A[Create directory\nand manifests] --> B[Push to main]
B --> C[ApplicationSet\ndetects new dir]
C --> D[Application\ncreated]
D --> E[Resources synced\nto cluster]
style A fill:#7c3aed,color:#fff
style C fill:#18b7be,color:#fff
style D fill:#18b7be,color:#fff
style E fill:#326ce5,color:#fff Step-by-Step Guide¶
1. Choose a Category¶
Pick the category that best fits your application:
| Category | Use For |
|---|---|
ai | AI and machine learning workloads |
banking | Financial tools and services |
cert-manager | TLS certificate resources |
cloudnative-pg | PostgreSQL clusters and backups |
home-automation | Home Assistant, Zigbee2MQTT, MQTT brokers |
kube-system | Core cluster components |
media | Jellyfin, *arr apps, downloaders |
monitoring | Prometheus, Grafana, Loki, alerting |
networking | Envoy Gateway, Cilium, DNS, tunnels |
openebs | Local PV storage |
rook-ceph | Distributed storage |
security | Authentication, secrets, certificates |
selfhosted | General self-hosted applications |
system | System-level utilities |
When in Doubt
If your app does not clearly fit a category, selfhosted is a good default for general-purpose applications.
2. Create the Directory¶
The directory name becomes the app name in ArgoCD. Choose a name that is lowercase, uses hyphens for separation, and is descriptive:
echo-server(good)home-assistant(good)myApp(bad -- use lowercase with hyphens)
3. Create the Manifests¶
Most applications in the cluster use the bjw-s app-template Helm chart inflated through Kustomize. This pattern requires two files:
controllers:
<app-name>:
containers:
app:
image:
repository: <image-repo>
tag: <image-tag>
env:
TZ: Europe/Zurich
resources:
requests:
cpu: 10m
memory: 64Mi
limits:
memory: 256Mi
probes:
liveness:
enabled: true
readiness:
enabled: true
service:
app:
ports:
http:
port: 8080
route:
app:
enabled: true
hostnames:
- <app-name>.pitower.link
parentRefs:
- name: envoy-internal
namespace: networking
sectionName: https
Gateway Selection
Choose the appropriate gateway in parentRefs based on how the app should be accessed:
| Gateway | Use Case |
|---|---|
envoy-external | Accessible via Cloudflare tunnel (*.pitower.link proxied) |
envoy-internal | Internal-only access (VPN/LAN via internal.pitower.link) |
envoy-direct | Direct public IP access (non-proxied, via ip.pitower.link) |
4. Push and Verify¶
git add kubernetes/apps/pitower/<category>/<app-name>/
git commit -m "feat(<category>): add <app-name>"
git push origin main
After pushing, verify in ArgoCD:
# Check that the Application was created
kubectl get app -n argocd -l app.kubernetes.io/name=<app-name>
# Watch the sync status
kubectl get app -n argocd pitower-<category>-<app-name> -w
# Filter by category
kubectl get app -n argocd -l home-ops/category=<category>
Advanced Patterns¶
Apps with VolSync Backups¶
To enable automated backups for an app with persistent data, include the volsync component:
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: <category>
components:
- ../../../../components/volsync
helmCharts:
- name: app-template
repo: oci://ghcr.io/bjw-s-labs/helm
version: 4.6.2
releaseName: <app-name>
namespace: <category>
valuesFile: values.yaml
configMapGenerator:
- name: volsync-config
literals:
- APP_NAME=<app-name>
- CLAIM_NAME=<pvc-name>
- SECRET_NAME=<app-name>-volsync
- STORAGE_SIZE=<size>
- RESTIC_REPO=s3:https://s3.eu-central-2.amazonaws.com/pitower-volsync-backups/<category>/<app-name>
See Backup & Restore for restore procedures.
Apps with Extra Resources¶
Some apps need additional Kubernetes resources beyond what the Helm chart provides:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: networking
resources:
- certificate.yaml
- externalsecret.yaml
helmCharts:
- name: app-template
repo: oci://ghcr.io/bjw-s-labs/helm
version: 4.6.2
releaseName: envoy-gateway
namespace: networking
valuesFile: values.yaml
Apps Without Helm¶
If your app does not use a Helm chart, you can use plain manifests with Kustomize:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: <category>
resources:
- deployment.yaml
- service.yaml
- httproute.yaml
Per-Cluster App Variants¶
For apps that need different configuration per cluster, create a subdirectory per cluster:
kubernetes/apps/pitower/networking/envoy-gateway/pitower/
kubernetes/apps/pistack/networking/envoy-gateway/pistack/
Each cluster's ApplicationSet only scans its own directory tree, so each cluster gets its own configuration.
Removing an Application¶
To remove an application from the cluster:
- Delete the app directory:
- Push to
main: - The ApplicationSet detects the missing directory and deletes the Application.
- The
resources-finalizer.argocd.argoproj.iofinalizer ensures all managed resources are cleaned up from the cluster.
Checklist¶
Use this checklist when adding a new app:
- Directory created at
kubernetes/apps/pitower/<category>/<app-name>/ -
kustomization.yamlwith correctnamespaceand chart configuration -
values.yamlwith image, resources, probes, and service defined - HTTPRoute configured with the correct gateway
- Resource requests and limits set appropriately
- VolSync component included (if app has persistent data)
- Secrets managed via ExternalSecret (if applicable)
- Pushed to
mainand verified in ArgoCD