aly badawy/homelab
all systems operational
// cluster · applications

Applications

All 14 ArgoCD Applications across the cluster — platform infrastructure and user-facing services. Each is GitOps-managed from k8s/apps/, pulling credentials from Vault via ESO, and exposed through ingress-nginx with the wildcard TLS cert.

All synced 14 applications Vault secrets wildcard TLS

Every app in this cluster follows the same pattern: GitOps-managed by ArgoCD, credentials injected at runtime by ESO from Vault, HTTPS provided by the shared wildcard cert. The 14 Applications break down into two groups — platform infrastructure (deployed at wave -1 to 1) and user-facing services (wave 2+).

01 Platform infrastructure

These Applications form the foundation the user-facing apps depend on. They deploy first, in sync-wave order, before any user workloads start.

ApplicationNamespaceWaveRole
vault security −1 Secrets backend — must be unsealed before ESO can sync.
argocd argocd 0 Self-managing GitOps controller. Adopts imperatively-bootstrapped install.
longhorn longhorn-system 0 Block storage for stateful workloads. Self-managing after bootstrap.
ingress-nginx networking 1 Cluster-wide ingress controller. Serves wildcard TLS on port 443.
cert-manager networking 1 Automated TLS — issues and renews the wildcard cert via DNS-01.
external-secrets security 1 Bridges Vault to Kubernetes Secrets. ClusterSecretStore k8s-secrets.
monitor monitor 2 kube-prometheus-stack: Prometheus, Grafana, Alertmanager.

02 User-facing services

These Applications deploy at wave 2 or later, after the platform is healthy. All are exposed via ingress-nginx with the wildcard cert.

ApplicationNamespaceURLDescription
auth security auth.in.alybadawy.com Authentik v2026.5.2 — SSO, OAuth2, LDAP proxy.
db db pgadmin.in.alybadawy.com PostgreSQL + Redis + pgAdmin + pg-dump CronJob.
cloud cloud cloud.in.alybadawy.com Nextcloud — self-hosted cloud storage and collaboration.
immich immich photos.in.alybadawy.com Immich — photo and video backup (Google Photos alternative).
whoami whoami whoami.in.alybadawy.com HTTP echo service for testing ingress and TLS.
aly websites aly.in.alybadawy.com Personal website (ghcr.io/alybadawy/aly:latest).
root argocd Root app-of-apps. Watches k8s/apps/ and manages all other Applications.

03 Database stack

PostgreSQL and Redis run in the db namespace as raw Deployments (not operators). A pg-dump CronJob runs periodic dumps of all databases to the NAS. pgAdmin provides a web UI for database management.

Shared database instance. Authentik, Nextcloud, and Immich all use separate databases within the same PostgreSQL instance — each app gets its own POSTGRES_DB. This simplifies operations: one set of backups, one PVC to restore on rebuild.
db namespace resources bash
# check all db namespace resources
$ kubectl get all -n db
NAME                          READY   STATUS    RESTARTS   AGE
pod/postgres-xxx              1/1     Running   0          5d
pod/pgadmin-xxx               1/1     Running   0          5d
pod/redis-xxx                 1/1     Running   0          5d

# check the pg-dump cronjob (dumps to NAS)
$ kubectl get cronjob -n db
$ kubectl get jobs -n db --sort-by=.metadata.creationTimestamp

04 Immich

Immich runs two containers in the immich namespace: immich-server (main API + web UI) and immich-ml (machine learning for face recognition and CLIP image search). Photos are stored on a Longhorn-backed PVC that is included in the NAS backup schedule.

Large body uploads. Immich and Nextcloud upload large files (photos, videos, documents). The ingress-nginx client-max-body-size: 100m setting is required — without it, nginx rejects uploads over 1 MiB with a 413 error. For very large Nextcloud uploads (>100 MB), the client must use chunked upload.

05 Adding a new app

The pattern is the same for every app:

  1. Create k8s/components/<name>/ with namespace, deployment, service, ingress, and optionally ExternalSecret + PVC.
  2. Create k8s/apps/<name>.yaml — copy any existing Application manifest and update path, destination.namespace, and name.
  3. Store credentials in Vault: vault kv put secret/<name>-secret KEY=value ...
  4. Commit and push. ArgoCD detects the new Application manifest (root app watches k8s/apps/) and syncs automatically.
minimal Application manifest (k8s/apps/myapp.yaml) yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
  annotations:
    argocd.argoproj.io/sync-wave: "3"  # after db and platform
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    repoURL: https://github.com/AlyBadawy/hl-beta
    targetRevision: main
    path: k8s/components/myapp
  destination:
    server: https://kubernetes.default.svc
    namespace: myapp
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
last updated 2026-06-08 · view source on GitHub