Skip to content

Cloud Deployment (Scaleway)

This runbook uses OpenTofu to provision infrastructure and Helm to deploy the chart on Scaleway Kapsule (mutualized). All just commands should be run from the repository root. Steps that require manual commands specify their working directory explicitly.

If you are new to Kubernetes, read the Kubernetes primer first. It explains each concept next to its Docker Compose equivalent.

What OpenTofu provisions

OpenTofu creates the following resources on Scaleway (nl-ams region): - A VPC and private network - A Kapsule cluster (mutualized, k8s v1.32) with an autoscaling node pool (PLAY2-MICRO, 1-3 nodes) - A security group allowing HTTP/HTTPS traffic

PostgreSQL runs in-cluster via the Bitnami Helm chart (not as a Scaleway managed database). The container registry (srdp-registry) must be created beforehand via the Scaleway Console.

1) Prepare cloud credentials

  • Copy deploy/opentofu/scaleway/secrets.sh.example to deploy/opentofu/scaleway/secrets.sh and fill in your Scaleway credentials (SCW_ACCESS_KEY, SCW_SECRET_KEY, SCW_DEFAULT_PROJECT_ID).
  • Load them before running OpenTofu:
    cd deploy/opentofu/scaleway
    source ./secrets.sh
    

2) Build and push container images

Run the build recipe from the repository root. It sources deploy/opentofu/scaleway/secrets.sh for the credentials and logs into the registry:

just build-and-push
This builds and pushes Marimo, srdp-etl (Dagster user code) and srdp-setup to the registry in srdp.toml under [deploy] registry. Quarto is disabled by default (quarto.enabled: false). docs/02-configuration.md explains why.

3) Provision infrastructure with OpenTofu

cd deploy/opentofu/scaleway
tofu init -upgrade        # first run only, from deploy/opentofu/scaleway/
cd ../..                  # back to repo root
just prod-apply

4) Export kubeconfig

just prod-use-kubeconfig   # from repo root

5) Prepare production Helm values

  • Copy deploy/kubernetes/srdp-chart/values-prod.example.yaml to deploy/kubernetes/srdp-chart/values-prod.yaml if you are starting fresh.
  • Fill in global.domain, the oauth2-proxy cookie and whitelist domains, and the ACME email for Traefik. Use a real domain or <lb-ip>.nip.io once you know the load balancer IP. Let's Encrypt's HTTP and TLS challenges need the machine to be publicly reachable on that domain. A machine that isn't reachable can still use Let's Encrypt through a DNS challenge, if the organisation controls the public DNS of a real domain. A machine with only an internal name needs the organisation's own certificate.
  • Set the registry in srdp.toml under [deploy] registry. The prod-* recipes pass it to the chart as global.srdpRegistry and as the srdp-etl repository.
  • The values files hold no passwords or keys. Before you install, create these Secrets in the srdp namespace, for example with External Secrets. Every consumer reads them by these fixed names.
Secret Keys
srdp-postgres postgres-password (superuser), password (zitadel user), replication-password (replication only)
srdp-zitadel masterkey, config-yaml
srdp-oauth2-proxy client-id, client-secret, cookie-secret
srdp-dagster-postgresql postgresql-password
srdp-marquez db-password
  • config-yaml in srdp-zitadel is a Zitadel config fragment with Database.Postgres.User.Password, Database.Postgres.Admin.Password and FirstInstance.Org.Human.Password. The two database passwords must match password and postgres-password in srdp-postgres.
  • The srdp-setup Job reads srdp-dagster-postgresql and srdp-marquez too, and applies them to their roles on every install and upgrade.
  • Changing an internal password: these are service-to-service credentials, so change one only as a deliberate rotation. Change the value in its Secret, run helm upgrade, then restart the services that use it. Marquez restarts by itself. For Dagster, run kubectl -n srdp rollout restart deploy/srdp-dagster-webserver deploy/srdp-dagster-webserver-read-only deploy/srdp-dagster-daemon deploy/srdp-dagster-user-deployments-srdp-etl.
  • Master key format: ZITADEL expects a 32-character master key string. Generate one, for example, with `tr -dc 'A-Za-z0-9'