Skip to Content
Installing MarshalArgoCD (GitOps)

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.className at whatever controller your cluster runs.
  • Let Terraform build the GKE cluster, and ArgoCD own the release. Set install_marshal = false on the GKE path and feed its computed values into this Application.

What you need

  • The Prerequisites.

  • ArgoCD in the cluster (namespace argocd) and the argocd CLI signed in.

  • A Postgres 16 connection string the cluster can reach.

  • Your image cache, if you run one: the Application points global.registry at 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 Synced

Sync 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 -d

The 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 targetRevision in the Application, commit, then argocd app sync marshal. Roll back by reverting the commit and syncing, or with argocd app rollback marshal.
  • Renew the license: update the marshal-license Secret with the new JWT, then restart the api. The Application does not change.
  • Keep secrets.provider: existing and keep marshal-app-secrets for 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.