Skip to content

Cloud-native Deployment

This guide is for Nexus admins and engineers running Proof of Concepts. It describes the cloud-native path: the platform is built, verified and torn down by Google Cloud Build inside your own project. No workstation runs Terraform, no laptop has to stay awake for an hour, and a colleague can start the same deployment from the Cloud Console without installing anything.

One configuration file — the .bootstrap_env — describes the environment you want. It lives in a bucket in your project, and every run reads it from there.

  1. Connect GitHub and Cloud Build A one-time step per project.

  2. Describe your environment Three lines are enough to start; the complete configuration follows below.

  3. Create the triggers Run setup-cloudbuild-triggers.sh once. It reads your configuration, uploads it to the project’s bucket and creates the triggers.

  4. Start a bootstrap From the Cloud Console or with one gcloud command.

  5. Read the result The run ends with a health check that judges the platform it just built.


Make sure you are signed in to both GCP and GitHub, then:

  1. Open the Cloud Build dashboard and click Create host connection. Cloud Build Repositories Dashboard

  2. Follow the prompts: a name for the connection, your GitHub account, and the region you want to deploy Nexus in. The name takes only lowercase letters, digits and hyphens — valtech-nexus-sdv, not Valtech Nexus SDV. Region and name prompts

  3. Install the Cloud Build GitHub app and grant it access to your Nexus fork only. Cloud Build GitHub App setup

  1. Open the Cloud Build dashboard and click Link repository. Cloud Build Repositories Dashboard
  2. Select the connection you just created and your Nexus fork. Link GitHub repo prompts

The setup script reads a .bootstrap_env. To create the triggers, three values are enough:

iac/bootstrapping/.bootstrap_env
GCP_PROJECT_ID="<your-gcp-project-id>"
GCP_REGION="europe-west4"
GITHUB_REPO="<owner>/<your-nexus-fork>"

GCP_PROJECT_ID falls back to your gcloud configuration and GITHUB_REPO to your git remote, so on a well-configured checkout the file may even be empty — but writing them down keeps the setup reproducible for the next person.

With the configuration file in place, run from the root of your fork:

Terminal window
./iac/bootstrapping/tools/setup-cloudbuild-triggers.sh

The script reads iac/bootstrapping/.bootstrap_env — or the file you pass with --env-file PATH. If none exists it starts the interactive create-bootstrap-env.sh and uses the result.

From that file it needs GCP_PROJECT_ID and GITHUB_REPO. Both have a fallback: the project from your gcloud configuration, and the repository derived from git remote origin. If neither is available the script stops.

It then uploads your configuration to gs://<PROJECT_ID>-bootstrap-envs/.bootstrap_env and creates four manual triggers:

TriggerPurpose
bootstrap-platformbuilds a complete platform
teardown-platformremoves it again
run-sample-clientssends real telemetry end to end
test-environmentsbootstraps and tears down several environments in sequence

A fifth trigger, platform-health-check, is created by Terraform during the bootstrap. A schedule that runs it three times a day comes with it only on this, the trigger path — the schedule invokes the trigger, so an install via gcloud builds submit gets the one-off check at the end of its bootstrap and nothing recurring.

When the script succeeds it prints:

Terminal window
[OK] ==================================================================
[OK] All Cloud Build triggers are ready!
[OK] ==================================================================

The three lines above create the triggers. A platform needs the complete file — this is it. Every run reads it from a bucket in your project rather than from your repository:

gs://<PROJECT_ID>-bootstrap-envs/.bootstrap_env

A trigger points at one file through the substitution _BOOTSTRAP_ENV_GCS_PATH, so several environments can live side by side as several files in the same bucket.

KeyMeaning
GCP_PROJECT_IDthe project everything is created in
GCP_REGIONregion for GKE, Cloud SQL, BigTable and the CA pools
DEPLOY_MODEcloudbuild for this path
GITHUB_REPOyour fork as owner/name; the trigger setup needs it and falls back to your git remote
ENVshort name of the environment; it prefixes the cluster, the VPC and the database
PKI_STRATEGYremote or local — see below
BASE_DOMAINthe domain the services are published under (remote PKI)
EXISTING_DNS_ZONEname of an existing Cloud DNS zone for that domain
KEYCLOAK_HOSTNAMEhost part for Keycloak, default keycloak
NATS_HOSTNAMEhost part for NATS, default nats
REGISTRATION_HOSTNAMEhost part for the registration server
FLEETVIEW_HOSTNAMEhost part for FleetView
EXISTING_SERVER_CA, EXISTING_SERVER_CA_POOLreuse an existing server CA; empty means create a new one
EXISTING_FACTORY_CA, EXISTING_FACTORY_CA_POOLthe same for the factory CA
EXISTING_REG_CA, EXISTING_REG_CA_POOLthe same for the registration CA
ARCHarm64 or amd64 — the node architecture of the cluster
OPERATIONAL_CERT_VALIDITYhow long a vehicle’s operational certificate is valid, as 90d, 12h, 5m; optional, default 90d
FACTORY_HELPER_CERT_VALIDITY_DAYShow long an issued factory certificate is valid, in days; optional, default 730
DEPLOYMENT_SUFFIXleave empty; the bootstrap generates one and writes it back
NEXT_PUBLIC_GOOGLE_MAPS_API_KEYoptional; leave empty
NEXT_PUBLIC_GOOGLE_MAPS_MAP_IDoptional, belongs to the key above

Empty EXISTING_* values mean create new, exactly as leaving a prompt blank does in the interactive script.

Certificates come from Google Certificate Authority Service and the services are published under your domain, so BASE_DOMAIN and EXISTING_DNS_ZONE are required. Keycloak then answers under two names: keycloak-ui.<domain> on port 443 for browsers, keycloak.<domain> on port 8443 for vehicles.

Which one to choose, and what each costs you, is laid out under Platform Deployment.

ARCH decides whether the cluster runs on Arm or x86 nodes. Both are supported; availability differs between regions, so if a bootstrap fails while creating the cluster with a message about missing resources, try the other architecture or another region.


Open Cloud Build → Triggers in your project, find bootstrap-platform and click Run. Nothing else is needed — no local tools, no checkout. This is the path to use when a colleague should be able to deploy without setting anything up.

Running the bootstrap trigger from the Cloud Console

The run takes roughly 45 to 60 minutes and goes through three stages:

  1. Infrastructure Terraform creates the network, the GKE cluster, Cloud SQL, BigTable, the CA pools and the service accounts, and stores the platform’s secrets in Secret Manager.

  2. Services Cloud Build deploys Keycloak, NATS, the registration server, the Data API, the connector, the Vehicle Registry, FleetView and — with remote PKI — the Factory Helper. Each service is built and pushed from your fork.

  3. Verification The health check runs against the finished platform and, on this path, sends real telemetry end to end.

Follow the run in the Cloud Build history of your project. The child builds — one per service — appear there next to the parent run.

The last stage checks the enabled APIs, the infrastructure, certificate expiry, the endpoints of Keycloak, NATS and the registration server, and the state of each base service. It ends with a summary:

ENVIRONMENT PASS WARN FAIL
my-environment 41 0 0

A failure fails the build, so a green bootstrap means a platform that answered for itself. The number of checks depends on the platform — a local-PKI install runs fewer, because the DNS and certificate-authority checks do not apply — so read the WARN and FAIL columns rather than the total. The same counts are written to a Cloud Monitoring dashboard named Platform health, and where a trigger exists the scheduled run repeats the check three times a day. Without one there is no scheduled run — see above.

Like the bootstrap, the teardown is a trigger: click Run on teardown-platform under Cloud Build → Triggers, or start it from the command line.

Terminal window
gcloud builds triggers run teardown-platform \
--region=<REGION> --project=<PROJECT_ID>

The teardown removes everything the bootstrap created and clears the environment’s identity from Secret Manager, so the next platform in the same project starts clean. Two substitutions decide what survives:

SubstitutionDefaultEffect
_PRESERVE_CASYkeeps the CA pools — useful when the next environment should reuse the same vehicle trust chain
_PRESERVE_DNSYkeeps the Cloud DNS zone, so the domain delegation does not have to be set up again

Both preserve by default, because another environment in the same project may still be using them. A zone you named in EXISTING_DNS_ZONE is never deleted in any case — the teardown only removes a zone its own bootstrap created.

test-environments processes every file in the bucket, one after another: bootstrap, an observation window, teardown, then the next. One file per environment, and the run reports at the end which ones failed. This is how the platform is verified across the four combinations of PKI strategy and architecture.

It starts like the other two — Run on test-environments in the Console, or from the command line.

Terminal window
gcloud builds triggers run test-environments \
--region=<REGION> --project=<PROJECT_ID>