Saltar al contenido principal

ArgoCD Deployment

An alternative to the Helm CLI, not a different product

Production Installation is the standard deployment procedure and installs the same chart, the same images and the same configuration. This page is for teams that already run ArgoCD and want the platform reconciled from Git instead of installed by hand. If that is not you, you do not need this page.

Read the Helm guide first — the prerequisites, secrets and values it describes apply here unchanged. This page only replaces the helm install at the end.

The reference manifests ship inside the chart

Complete, versioned ArgoCD manifests live in the chart artifact at argocd/application.yaml. Extract them with helm pull … --untar and adapt them, rather than copying from this page — they track the chart release you are actually installing.

If you manage your cluster with ArgoCD, you can drive the Plexicus chart directly from OCI instead of the Helm CLI. The recommended pattern is a single Application per environment that uses the umbrella chart with bundled infrastructure subcharts enabled — no separate MongoDB / Redis / PostgreSQL / Temporal Applications needed.

Validated end-to-end

The procedure below was validated on k3s + ArgoCD v3, Helm chart 1.2.19; it applies unchanged through the current 1.2.41 release. The reference manifests live inside the chart artifact at argocd/application.yaml — extract with helm pull --untar and adapt to your environment. Key gotchas:

  • The AppProject's sourceRepos list must include every chart source you reference. When using bundled subcharts, you only need the OCI GAR registry and your GitOps Git repo — the Bitnami and Temporal repositories are not required.
  • ArgoCD ≤ 2.12 does not support semver ranges for OCI sources. Always pin targetRevision to an exact version string (e.g. "1.2.41").
  • Image-tag drift. The chart pins <service>.image.tag to the chart version, but GAR images use independent build numbers. Override <service>.image.tag: latest for evaluation or pin specific build tags for reproducible production deployments.
1

Create the GitOps repository and AppProject

ArgoCD pulls Application manifests from a Git repository. Even when the chart lives in OCI, the Application manifest and any environment-specific values live in Git so every change is auditable, peer-reviewable, and revertable.

Recommended layout for a single-environment deployment:

plexicus-gitops/
├── README.md
├── projects/
│ └── plexicus-appproject.yaml # Restricts allowed sources/destinations
├── apps/
│ ├── root-app.yaml # App-of-Apps root (optional, see tip below)
│ ├── plexicus-app.yaml # Umbrella Application
│ └── secrets-app.yaml # Sibling Application for SealedSecrets
├── environments/
│ └── prod/
│ └── values.yaml # Non-sensitive overlay (committed to Git)
└── secrets/
└── README.md # Pointer to sealed secret YAML files

Initialize and push the repo from your operator workstation:

cd ~/plexicus-deploy
mkdir -p plexicus-gitops/{projects,apps,environments/prod,secrets}
cd plexicus-gitops
git init -b main
cat > .gitignore <<'EOF'
repo-gar.yaml
keys.json
*.key
EOF
git add .gitignore && git commit -m "chore: bootstrap plexicus GitOps repo"
git remote add origin git@github.com:<your-org>/plexicus-gitops.git
git push -u origin main

Register the Git repo with ArgoCD. Apply a Secret in the argocd namespace — do NOT commit this file (it contains credentials):

kubectl apply -f - <<'EOF'
apiVersion: v1
kind: Secret
metadata:
name: plexicus-gitops-repo
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
type: Opaque
stringData:
type: git
url: git@github.com:<your-org>/plexicus-gitops.git
sshPrivateKey: |
-----BEGIN OPENSSH PRIVATE KEY-----
<paste deploy key>
-----END OPENSSH PRIVATE KEY-----
EOF

AppProject — restrict allowed sources. When using bundled infrastructure subcharts, you only need two source entries — the OCI registry and your Git repo. The Bitnami and Temporal chart repositories are not needed.

Save as projects/plexicus-appproject.yaml:

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: plexicus
namespace: argocd
spec:
description: Plexicus platform deployment
sourceRepos:
- https://github.com/<your-org>/plexicus-gitops.git
- europe-west3-docker.pkg.dev/plexicus-registry/charts
destinations:
- namespace: plexicus
server: https://kubernetes.default.svc
- namespace: argocd
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: ""
kind: Namespace
- group: cert-manager.io
kind: ClusterIssuer
namespaceResourceWhitelist:
- group: "*"
kind: "*"

Secrets handling — never commit raw Secret YAML. Pick one approach:

  • Sealed Secrets — encrypt with a cluster-specific public key, commit the SealedSecret ciphertext, controller decrypts in-cluster. Simplest for a single cluster. See step 3 for the critical key-backup procedure.
  • External Secrets Operator (ESO) — ExternalSecret CRD pulls from Vault, AWS Secrets Manager, GCP Secret Manager, etc.
  • SOPS with helm-secrets or argocd-vault-plugin.

Every Application manifest lives under apps/, committed and pushed before applying.

2

Configure the OCI repository secret

The Plexicus chart lives in OCI, so ArgoCD needs GAR credentials. Create repo-gar.yaml — do NOT commit it:

apiVersion: v1
kind: Secret
metadata:
name: plexicus-gar
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
type: Opaque
stringData:
type: helm
name: plexicus-gar
url: europe-west3-docker.pkg.dev/plexicus-registry/charts
enableOCI: "true"
username: _json_key
password: |
<CONTENTS OF keys.json>
kubectl apply -f repo-gar.yaml
3

Deploy application secrets

The nine plexicus-* Secrets from step 5 of the Production Installation must exist before the Application syncs. Bootstrap them out-of-band with kubectl create secret (as in that step), or manage them declaratively via Sealed Secrets.

If using Sealed Secrets:

Install the controller:

helm upgrade --install sealed-secrets \
oci://registry-1.docker.io/bitnamicharts/sealed-secrets \
--namespace kube-system --create-namespace
Back up your sealing key immediately

The sealing key is cluster-unique and generated once at controller startup. Every SealedSecret you commit can only be decrypted by the cluster that holds this key. If the cluster is lost and you have no key backup, all sealed secrets are permanently unreadable — you must re-seal every credential against the new cluster's key.

Back up the key immediately after installing the controller and store it offline:

kubectl -n kube-system get secret \
-l sealedsecrets.bitnami.com/sealed-secrets-key \
-o yaml > sealed-secrets-key.backup.yaml
# Store this file offline — never commit it to Git.

To restore a key to a replacement cluster, apply the backup YAML before the controller starts for the first time, so it picks up the existing key rather than generating a new one.

Version note: pin the sealed-secrets controller chart version before upgrading it. The sealing key is backward compatible across controller versions (a newer controller can decrypt secrets sealed by an older version), but verify the project's release notes for the version span you are crossing.

Seal each Secret:

kubectl create secret generic plexicus-fastapi \
--from-literal=DATABASE_PASSWORD="$DB_PASS" \
... \
--dry-run=client -o yaml | \
kubeseal --controller-namespace=kube-system --format=yaml \
> secrets/sealed-plexicus-fastapi.yaml
# Repeat for every plexicus-* secret including plexicus-license

Commit and push the sealed files; ArgoCD reconciles them before the platform syncs (use a sibling secrets-app.yaml Application with sync-wave -1).

4

Create the umbrella Application

The recommended pattern is a single Application pointing at the OCI chart, with all infrastructure subcharts bundled inside and values supplied inline (or from a valueFiles reference to your Git repo).

Save as apps/plexicus-app.yaml:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: plexicus
namespace: argocd
spec:
project: plexicus
source:
repoURL: europe-west3-docker.pkg.dev/plexicus-registry/charts
chart: plexicus
targetRevision: "1.2.41"
helm:
values: |
global:
domain: plexicus.yourdomain.com
scheme: https
wsScheme: wss
ingressClassName: "nginx"
certManager:
enabled: true
clusterIssuer: "letsencrypt-prod"
imagePullSecrets:
- name: gar-secret
required:
# Object storage — point at your S3-compatible service
# (hostname only, no https://, no trailing slash)
minio:
service: "<your-s3-host>"
buckets: "<your-bucket-name>"
rootUser: "<access-key-id>"
rootPassword: "<secret-access-key>"

# Bundled infrastructure subcharts — all enabled inside the umbrella chart.
# fullnameOverride pins the in-cluster Service names to the chart's defaults
# so no global.required.database.host / redis.host overrides are needed.
mongodb:
enabled: true
fullnameOverride: "mongodb"
auth:
rootPassword: "<mongo-root-password>" # use SealedSecret or ESO

redis:
enabled: true
fullnameOverride: "redis"
auth:
password: "<redis-password>" # use SealedSecret or ESO

minio:
enabled: false # disabled — using external S3 above

temporal-postgresql:
enabled: true
fullnameOverride: "temporal-postgresql"
auth:
postgresPassword: "<pg-password>" # use SealedSecret or ESO

temporal:
enabled: true
fullnameOverride: "temporal"

fastapi:
existingSecret: plexicus-fastapi
worker:
existingSecret: plexicus-worker
frontend:
existingSecret: plexicus-frontend
analysis-scheduler:
existingSecret: plexicus-analysis-scheduler
codex-remedium:
existingSecret: plexicus-codex-remedium
exporter:
existingSecret: plexicus-exporter
plexalyzer-code:
existingSecret: plexicus-plexalyzer-code
plexalyzer-prov:
existingSecret: plexicus-plexalyzer-prov
destination:
server: https://kubernetes.default.svc
namespace: plexicus
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
App-of-Apps

For a fully self-contained GitOps loop, define a single "root" Application pointing at apps/ in your Git repo (App-of-Apps pattern). Then the only kubectl apply you ever run manually is the root manifest — every subsequent change goes through git push.

Alternative: separate prereq Applications

The chart also ships reference manifests for a five-separate-Applications pattern (one each for MongoDB, Redis, MinIO, PostgreSQL, Temporal at sync-wave 0, umbrella at sync-wave 5). This gives independent lifecycle control over each infra service and mirrors the Helm-CLI separate-release path from step 6. Extract the manifests from the chart artifact:

helm pull oci://europe-west3-docker.pkg.dev/plexicus-registry/charts/plexicus \
--version $CHART_VERSION --untar
ls plexicus/argocd/prereqs/

When using this pattern, add the Bitnami and Temporal chart repos to your AppProject sourceRepos list. Note that the prereq release names get an ArgoCD-applied prefix (e.g. plexicus-mongodb), so you must override global.required.database.host etc. to match the prefixed service names, or set fullnameOverride on each prereq Application.

Commit and apply:

cd plexicus-gitops
git add projects/plexicus-appproject.yaml apps/plexicus-app.yaml
git commit -m "feat(argocd): add plexicus AppProject + umbrella Application"
git push

kubectl apply -f projects/plexicus-appproject.yaml
kubectl apply -f apps/plexicus-app.yaml
5

Verify the sync

Open the ArgoCD UI or run:

argocd app get plexicus

The application should reach Healthy and Synced status within a few minutes. Confirm the platform is up with the same smoke test as step 9.


Next steps