Install with ArgoCD (GitOps)
Manage Marshal the way you manage the rest of your platform: commit an Application, sync it, and review every upgrade as a pull request. ArgoCD installs the same chart from the OCI registry onto a cluster you already run, on any cloud, with your own ingress controller, image cache and Postgres.
What you can do with it
- Keep Marshal in your GitOps repository. The chart version and every value live in git, so an upgrade is a one-line change your team reviews.
- Run it on any cloud. The Application does not depend on GKE or EKS. Point
ingress.classNameat whatever controller your cluster runs. - Let Terraform build the GKE cluster, and ArgoCD own the release. Set
install_marshal = falseon the GKE path and feed its computed values into this Application.
What you need
-
The Prerequisites.
-
ArgoCD in the cluster (namespace
argocd) and theargocdCLI signed in. -
A Postgres 16 connection string the cluster can reach.
-
Your image cache, if you run one: the Application points
global.registryat it. -
The installer clone, for
argocd/application.yaml:git clone --branch v<chart_version> https://github.com/marshal-org/marshal-install.git
Seed stable secrets first
ArgoCD renders the chart and applies the result. It never runs helm install, so the chart
cannot read back a Secret it generated earlier. With the chart’s default
secrets.provider: generated, every sync would create a new JWT_SECRET and KMS_LOCAL_KEY,
which signs everyone out and makes every stored credential unreadable. So the ArgoCD path uses
secrets.provider: existing: you create one stable Secret once, and ArgoCD only references it.
The steps below do this.
Install
Register the chart registry in ArgoCD
argocd repo add registry.marshal.codes/marshal-charts \
--type helm --enable-oci \
--username <deployment_id> --password '<registry_pull_token>'The registry authenticates on the mrpt_ token in the password. To do this declaratively, use
an ArgoCD repository Secret in the argocd namespace, and keep the token out of git with
Sealed Secrets, SOPS or External Secrets.
Create the secrets, once
kubectl create namespace marshal
# App secrets. Create them once and never rotate them. Back them up.
kubectl create secret generic marshal-app-secrets -n marshal \
--from-literal=JWT_SECRET="$(openssl rand -hex 32)" \
--from-literal=KMS_LOCAL_KEY="$(openssl rand -hex 32)" \
--from-literal=SETUP_TOKEN="$(openssl rand -hex 24)"
# License: your installation JWT.
kubectl create secret generic marshal-license -n marshal --from-literal=jwt="<installation_jwt>"
# Postgres connection string.
kubectl create secret generic marshal-db -n marshal \
--from-literal=database-url="postgres://marshal:PW@HOST:5432/marshal?sslmode=require"SETUP_TOKEN lets you claim the owner account after the install. If you lose
KMS_LOCAL_KEY, every stored credential becomes unreadable, so keep a copy somewhere safe.
Sealed Secrets or the External Secrets Operator work too, as long as the values stay stable.
Edit, commit and sync the Application
In argocd/application.yaml, set targetRevision (your chart version), global.registry (your
cache, or registry.marshal.codes/marshal), ingress.className (your ingress controller),
ingress.host, and the Redis choice. Then:
kubectl apply -f argocd/application.yaml
argocd app sync marshal
argocd app get marshal # Healthy and SyncedSync is manual by default. The shipped syncPolicy has no automated block, so the
install and every upgrade need an explicit sync, just as Terraform needs an explicit apply.
When you are ready for full GitOps, add automated: {prune: true, selfHeal: true}. With
selfHeal, ArgoCD also reverts any manual kubectl change made during an incident.
Check the install
kubectl get pods -n marshal
kubectl logs -n marshal -l app.kubernetes.io/component=api --tail=-1 | grep "license verified"What you should see
argocd app get marshal reports Healthy and Synced, every pod in the marshal namespace
is Running, and the api log contains a license verified line.
Claim your owner account
Read the setup token
kubectl get secret marshal-app-secrets -n marshal -o jsonpath='{.data.SETUP_TOKEN}' | base64 -dThe token works only until the first owner exists.
Open /setup
Go to your ingress.host with /setup at the end, for example
https://marshal.acme.com/setup. Paste the token, enter your email and a password, and select
Claim instance.
You are signed in as the owner. Next, follow Getting started as an owner to invite your team, then run your first task.
Upgrades and license renewal
- Upgrade: bump
targetRevisionin the Application, commit, thenargocd app sync marshal. Roll back by reverting the commit and syncing, or withargocd app rollback marshal. - Renew the license: update the
marshal-licenseSecret with the new JWT, then restart the api. The Application does not change. - Keep
secrets.provider: existingand keepmarshal-app-secretsfor the life of the install.
See Day-2 for the rest of running Marshal.
Values from a git file, instead of inline
To keep values in a committed values.yaml instead of inline helm.valuesObject, use a
multi-source Application: one source is the OCI chart, the other is your git repository, and
helm.valueFiles references $values/path/to/values.yaml. Keep secrets out of that file: they
stay in the Secrets you created.