Skip to content

Install on Google Cloud

infra-gcp/gcp.sh installs Axium in a Google Cloud project from Cloud Shell: a Cloud SQL (PostgreSQL 17) instance, and the core and the ui as two Cloud Run services. It is meant to be pasted and waited on, and it is idempotent: you can re-run it to upgrade versions without losing the database or the master key.

Run it

Open Cloud Shell in the target project and run:

wget https://raw.githubusercontent.com/axium-lab/infrastructure-documentation/refs/heads/main/infra-gcp/gcp.sh \
  && chmod +x gcp.sh \
  && TAG=v0.1.0 ./gcp.sh

The script asks for two things it cannot find on its own:

  • Your Axium license (40 hexadecimal characters). It is checked against the Axium Lab license API before anything is created, so a mistyped or expired license fails in seconds rather than after ten minutes of Cloud SQL provisioning. If the license API cannot be reached the script warns and continues: the core validates the license again at startup.
  • Your Quay user and token, unless a session already exists.

Plan for 10 to 15 minutes, most of it waiting for Cloud SQL.

Options

All options are environment variables:

Variable Default Effect
TAG latest Image tag to deploy. Pin a version in production: TAG=v0.1.0.
REGION europe-west1 Region for Cloud SQL, Artifact Registry and Cloud Run.
PROJECT_ID current gcloud project Target project.
AXIUM_LICENSE asked interactively License key. Pass it in pipelines; an invalid value aborts instead of prompting.
VERTEX_PROJECT PROJECT_ID Project where Vertex AI lives, if different. The IAM role is granted there.
DB_INSTANCE / DB_NAME / DB_USER axium-db / axium-api / axium Cloud SQL names.
AR_REPO axium Artifact Registry repository.
CORE_SERVICE / UI_SERVICE axium-core / axium-ui Cloud Run service names.
DEBUG unset 1 prints registry connectivity diagnostics and runs crane in verbose mode.
AXIUM_NO_CRANE unset 1 forces the Docker daemon for image copies instead of crane.

What it creates

flowchart LR
    B[Browser] -->|HTTPS| UI[Cloud Run<br/>axium-ui]
    B -->|HTTPS · API_URL| CORE[Cloud Run<br/>axium-core]
    CORE -->|Unix socket /cloudsql| SQL[(Cloud SQL<br/>PostgreSQL 17)]
    CORE -->|OAuth2 · roles/aiplatform.user| VX[Vertex AI]
    CORE -->|roles/storage.objectUser| GCS[(Cloud Storage)]
    Q[quay.io/axiumlab] -->|crane copy| AR[Artifact Registry<br/>REGION-docker.pkg.dev]
    AR --> UI
    AR --> CORE

Step by step:

  1. License check against https://meta.axium-lab.com/v1/license/check/<license>.
  2. APIs: sqladmin, run, artifactregistry, storage in the project, and aiplatform in VERTEX_PROJECT (a failure there only warns).
  3. Artifact Registry repository axium. Cloud Run can only deploy from Artifact Registry, so the images are copied from Quay with crane (falls back to the Docker daemon). Downloads of crane are cached in ~/.axium/bin.
  4. Cloud SQL: the cheapest configuration that exists, intended for a pilot. db-f1-micro, 10 GB HDD, single zone, no automatic backups. For production remove --no-backup and pick a bigger tier.
  5. Secrets: MASTER_ENCRYPTION_KEY and DATABASE_URL are read back from the deployed core if it exists and generated otherwise. The master key is never regenerated once it exists. The DSN uses the Cloud SQL Unix socket: postgresql://axium:<pass>@localhost/axium-api?host=/cloudsql/<connectionName>.
  6. IAM on the runtime service account (the project's default compute SA unless the service already uses another):

    Role Project Why
    roles/cloudsql.client deploy Connect through the /cloudsql socket.
    roles/storage.objectUser deploy Read, write and delete objects in buckets.
    roles/storage.bucketViewer deploy List buckets and read metadata; objectUser alone makes bucket.exists() return 403.
    roles/aiplatform.user VERTEX_PROJECT Call Google models through Vertex AI. Publisher models do not accept per-resource IAM, so the binding is project-wide.
  7. Core on Cloud Run: --allow-unauthenticated, 1 GiB RAM, 1 vCPU, concurrency 20, 0 to 4 instances, with DATABASE_URL, MASTER_ENCRYPTION_KEY, TRUST_PROXY=true and AXIUM_LICENSE. Memory and concurrency follow from the 50 MB upload ceiling, which is held in RAM per request.

  8. Ui on Cloud Run: 512 MiB, concurrency 80, API_URL=<core URL>/v1.
  9. Verification: waits for /v1/health, then requires /v1/install/status to answer installed.

The script ends with the console URL, the API URL, the initial credentials and the master key in clear text. Save it before closing the shell.

After installing

  • Change the admin password (First login).
  • Move the secrets to Secret Manager. The master key and the database password are in clear text in the Cloud Run service configuration, visible to anyone with read access to the project. Replace --set-env-vars with --set-secrets in the script to harden it.
  • Renewing the license does not require reinstalling:

    gcloud run services update axium-core --region europe-west1 \
      --update-env-vars AXIUM_LICENSE=<the new one>
    
  • Vertex AI in another project. The core calls Vertex with the project_id configured in the provider inside Axium. If that is not the deploy project, re-run with VERTEX_PROJECT=<that project> bash gcp.sh or grant roles/aiplatform.user there by hand, otherwise generation fails with 403 PERMISSION_DENIED.

  • Public services. If the deploy fails mentioning IAM or allUsers, your organization's domain-restricted-sharing policy forbids public Cloud Run services. Deploy with --no-allow-unauthenticated and put a load balancer or IAP in front.

Several environments in one project

infra-gcp/gcp-environments.sh is the same installer with an environment prefix. It asks for a name (dev, test, pre, …) and creates <env>-axium-core, <env>-axium-ui and a database <env>-axium-api inside the same Cloud SQL instance, which is the only piece that costs money to duplicate.

AXIUM_ENV=dev TAG=v0.1.0 bash gcp-environments.sh   # non-interactive
AXIUM_ENV= bash gcp-environments.sh                 # empty = no prefix, same as gcp.sh

Each environment gets its own master key and its own database user password, read back from its own Cloud Run service on re-runs.

Upgrading

Use infra-gcp/update.sh. It is covered in Upgrading.

Cost notes

With the defaults, idle cost is dominated by the Cloud SQL instance (db-f1-micro, always on). Both Cloud Run services scale to zero. The first request after a scale-to-zero pays a cold start of a few seconds; on the core that cold start also runs the schema check.