LCMD db logoLCMD[db]

ArgoCD Setup

GitOps deployment with ArgoCD and SOPS

ArgoCD handles GitOps deployments, automatically syncing Kubernetes manifests from Git.

Installation

kubectl create namespace argocd
kubectl apply -k infrastructure/kubernetes/argocd

Access the UI

# Port forward
kubectl port-forward svc/argocd-server -n argocd 8080:443

# Get admin password
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

Visit https://localhost:8080 with username admin.

After first login, change the admin password and delete the initial secret:

kubectl delete secret argocd-initial-admin-secret -n argocd

SOPS Integration

ArgoCD decrypts SOPS-encrypted secrets using an age key during deployment.

Configure the Age Key

Required: The age private key must be created manually as a secret in ArgoCD namespace. This is a one-time setup step.

# Create secret from age key file
kubectl create secret generic sops-age-key \
  --namespace argocd \
  --from-file=keys.txt=~/.config/sops/age/keys.txt

# The repo-server will automatically restart with KSOPS support

The ArgoCD repo-server is patched to:

  • Install KSOPS plugin (init container)
  • Mount the age key at /sops/age/keys.txt
  • Set SOPS_AGE_KEY_FILE environment variable
  • Enable --enable-alpha-plugins --enable-exec for kustomize

Verify the setup:

# Check if age key is mounted
kubectl -n argocd exec deployment/argocd-repo-server -- ls -la /sops/age/

# Check if KSOPS is available
kubectl -n argocd exec deployment/argocd-repo-server -- which ksops

Application Configuration

Our application is defined in infrastructure/kubernetes/argocd/applications/lcmd-app-prod.yaml:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: lcmd-app
  namespace: argocd
spec:
  source:
    repoURL: git@github.com:lcmd-epfl/db.git
    targetRevision: main
    path: infrastructure/kubernetes/app/overlays/prod
  destination:
    server: https://kubernetes.default.svc
    namespace: prod
  syncPolicy:
    automated:
      prune: true      # Remove deleted resources
      selfHeal: true   # Revert manual changes

Image Updater

ArgoCD doesn't poll container registries on its own. ArgoCD Image Updater is installed alongside it and handles tag promotion: every 2 minutes it scans ghcr.io for main-* tags newer than the current lcmd-app spec, then rewrites spec.source.kustomize.images in place. ArgoCD's automated sync reconciles.

The full operator runbook — pull-secret rotation, kubeseal steps, CRD config — lives in infrastructure/kubernetes/argocd/image-updater/README.md. See CI/CD for the end-to-end merge-to-prod flow.

Monitoring

# Check sync status
kubectl -n argocd get applications

# View application details
kubectl -n argocd describe application lcmd-app

# Check logs
kubectl -n argocd logs -l app.kubernetes.io/name=argocd-application-controller

Troubleshooting

Secrets not decrypting:

# Check if age key is mounted
kubectl -n argocd exec deployment/argocd-repo-server -- ls /sops/age/

# Check repo-server logs
kubectl -n argocd logs deployment/argocd-repo-server

Sync failing:

# Force refresh
kubectl -n argocd patch application lcmd-app --type merge -p '{"metadata":{"annotations":{"argocd.argoproj.io/refresh":"hard"}}}'

On this page