Skip to main content

Directus on Cloud Run — Lab Guide

📖 Configuration Guide

Overview

Estimated time: 1–2 hours

Directus is a real-time open-source data platform that wraps any SQL database with a dynamic REST and GraphQL API, and provides a no-code Data Studio for managing content. This lab deploys Directus on Google Cloud Run (gen2) with Cloud SQL (PostgreSQL 15 + PostGIS), Cloud Filestore NFS for shared asset storage, Redis caching, Serverless VPC Access, and full Cloud Logging and Monitoring integration.

What the Module Automates

  • Cloud Run service (gen2) with serverless auto-scaling
  • Cloud SQL PostgreSQL 15 instance with dedicated database user and secrets
  • Secret Manager secrets for Directus KEY, SECRET, ADMIN_PASSWORD, and REDIS credentials
  • Cloud Filestore (NFS) provisioning and GCS Fuse volume mounts for asset storage
  • Artifact Registry repository and Cloud Build container image build
  • Serverless VPC Access connector for private Cloud SQL connectivity
  • Cloud Run Jobs for database initialisation (migrations)
  • Cloud Monitoring uptime check and automated backup Cloud Run Job (daily at 02:00 UTC)
  • Optional Cloud Armor WAF and Cloud CDN via Global HTTPS Load Balancer

What You Do Manually

  • Retrieve the Directus admin password from Secret Manager
  • Note the Cloud Run service URL from the RAD UI deployment panel
  • Explore the Directus Data Studio (Collections, Content, Files, Insights, Settings)
  • Create a collection and add content items
  • Query the REST and GraphQL APIs
  • Upload files and verify GCS storage
  • Configure webhooks and observe WebSocket activity
  • Query Cloud Logging and Cloud Monitoring dashboards

CLI and REST API Overview

This lab uses three primary interfaces:

InterfacePurpose
gcloudRetrieve secrets, inspect service URL, query logs
Directus REST / GraphQL APIQuery and manipulate content programmatically

Prerequisites

  1. Services GCP deployed — this module depends on Services GCP. The VPC network, Cloud SQL instance, Artifact Registry, and shared service accounts must exist before deploying Directus CloudRun.
  2. GCP project with billing enabled.
  3. gcloud CLI authenticated: gcloud auth application-default login
  4. Sufficient IAM permissions: Owner or an equivalent custom role on the target project.
  5. Access to the RAD UI with permission to deploy modules in the target GCP project.

Phase 1 — Deploy [AUTOMATED]

Variables

Configure the following variables in the RAD UI deployment form before deploying.

VariableRequiredDefaultDescription
project_idYesGCP project ID for all resources
deployment_idNo"" (auto-generated)Short suffix appended to all resource names
regionNous-central1GCP region for resource deployment
application_nameNodirectusBase name used in resource naming
application_versionNo11.1.0Directus container image version tag
deploy_applicationNotrueSet to false to provision infra only
min_instance_countNo0Minimum Cloud Run instances (0 = scale to zero)
max_instance_countNo1Maximum Cloud Run instances (cost ceiling)
cpu_limitNo1000mCPU limit per instance
memory_limitNo2GiMemory limit per instance
db_nameNodirectusPostgreSQL database name
db_userNodirectusPostgreSQL database user
enable_redisNotrueEnable Redis cache and rate-limiting backend
redis_hostNo""Redis host IP (defaults to NFS server IP when empty)
redis_portNo6379Redis TCP port
enable_nfsNotrueProvision Cloud Filestore NFS for shared asset storage
nfs_mount_pathNo/mnt/nfsNFS mount path inside the container
ingress_settingsNoallTraffic sources: all, internal, or internal-and-cloud-load-balancing
vpc_egress_settingNoPRIVATE_RANGES_ONLYVPC egress routing mode
enable_cloud_armorNofalseEnable Cloud Armor WAF + Global HTTPS Load Balancer
enable_cdnNofalseEnable Cloud CDN (requires enable_cloud_armor = true)
backup_scheduleNo0 2 * * *Cron schedule for automated backups
backup_retention_daysNo7Days to retain backup files in GCS
tenant_deployment_idNodemoTenant identifier appended to resource names

Initiate Deployment

Deployment is initiated from the RAD UI. Fill in the variables form and click Deploy.

Deployment Duration

PhaseEstimated Time
Provider initialisation1–2 min
Cloud SQL instance creation8–12 min
Cloud Filestore NFS provisioning3–5 min
Artifact Registry + Cloud Build5–10 min
Cloud Run service deployment2–4 min
Database migration Cloud Run Job1–3 min
Total20–36 min

Key Outputs

After deployment completes, the following outputs are available in the RAD UI deployment panel.

OutputDescription
service_urlHTTPS URL of the Cloud Run service
service_nameCloud Run service name
deployment_summaryHuman-readable summary of all provisioned resources
database_password_secretSecret Manager secret name for the DB password

Set shell variables for use in later steps using gcloud discovery:

export PROJECT="your-gcp-project-id"   # set this first — your GCP project ID
export REGION="us-central1" # the region you deployed into
export TOKEN=$(gcloud auth print-access-token)

# Discover the Cloud Run service
export SERVICE=$(gcloud run services list \
--project=${PROJECT} \
--region=${REGION} \
--format="value(metadata.name)" \
--filter="metadata.name~directus" \
--limit=1)
export SERVICE_URL=$(gcloud run services describe ${SERVICE} \
--project=${PROJECT} \
--region=${REGION} \
--format="value(status.url)")

# Discover the database password secret
export DB_SECRET=$(gcloud secrets list \
--project=${PROJECT} \
--filter="name~directus" \
--format="value(name)" \
--limit=1)

Phase 2 — Get the Service URL [MANUAL]

  1. Retrieve the Cloud Run service URL with gcloud:

    gcloud run services describe ${SERVICE} \
    --region=${REGION} \
    --project=${PROJECT} \
    --format="value(status.url)"
  2. Verify the service is reachable:

    curl https://${SERVICE_URL}/server/health

    Expected result: JSON response {"status":"ok"} indicating Directus is running and connected to the database.

    REST API equivalent:

    gcloud run services list \
    --project=${PROJECT} \
    --region=${REGION} \
    --format="table(metadata.name,status.url,status.conditions[0].status)"

Phase 3 — Explore Directus Data Studio [MANUAL]

  1. Retrieve the Directus admin password from Secret Manager:

    gcloud secrets versions access latest \
    --secret="$(gcloud secrets list --project=${PROJECT} --filter='name~directus-admin-password' --format='value(name)' --limit=1)" \
    --project=${PROJECT}

    REST API equivalent:

    curl -X POST \
    "https://secretmanager.googleapis.com/v1/projects/${PROJECT}/secrets/${DB_SECRET}/versions/latest:access" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)"
  2. Open a browser and navigate to https://${SERVICE_URL}/admin.

  3. Log in with:

    • Email: admin@example.com (or the value configured at deploy time)
    • Password: retrieved from Secret Manager above
  4. Tour the Data Studio:

    • Content — view and manage content items across all collections
    • Users — manage user accounts and roles
    • Files — upload and manage media assets
    • Insights — build dashboards and analytics panels
    • Settings — configure the platform, data model, roles, and webhooks

Phase 4 — Create Collections and Content [MANUAL]

  1. In the Data Studio, navigate to Settings > Data Model.

  2. Click Create Collection and name it articles.

  3. Add the following fields:

    • title — Type: String
    • body — Type: Text
    • published_date — Type: DateTime
    • featured_image — Type: Image
  4. Click Save to apply the schema change (Directus writes to the database immediately — no container rebuild required).

  5. Switch to the Content module in the left sidebar. Select Articles.

  6. Click Create Item and populate the fields. Create two or three sample articles.

  7. Publish items by setting their status to Published.

    Expected result: Items appear in the Content list with a green Published badge.

    gcloud SQL verification:

    gcloud sql connect CLOUD_SQL_INSTANCE_NAME \
    --user=directus \
    --database=directus \
    --project=${PROJECT}
    # Inside psql:
    SELECT id, title, status FROM articles LIMIT 5;

Phase 5 — Explore the REST and GraphQL APIs [MANUAL]

  1. Create an API access token in Settings > Access Tokens. Click Create Token, give it a name, and copy the generated token value.

  2. Query the articles collection via the REST API:

    curl -H "Authorization: Bearer YOUR_TOKEN" \
    https://${SERVICE_URL}/items/articles

    Expected result: JSON response with an array of article objects.

  3. Filter published articles:

    curl -H "Authorization: Bearer YOUR_TOKEN" \
    "https://${SERVICE_URL}/items/articles?filter[status][_eq]=published"
  4. Explore the auto-generated GraphQL API at https://${SERVICE_URL}/graphql. Open this URL in a browser to access the interactive GraphQL Playground.

  5. Run a sample GraphQL query:

    query {
    articles {
    id
    title
    published_date
    status
    }
    }

    Expected result: GraphQL response with article data matching the REST result.

  6. Review the full API specification at https://${SERVICE_URL}/server/specs/oas (OpenAPI 3.0).


Phase 6 — File Management and GCS Integration [MANUAL]

  1. In the Data Studio, navigate to the Files module.

  2. Click Upload and select an image file from your local machine.

    Expected result: The file appears in the Files module with a thumbnail preview.

  3. Verify that the file is stored in the GCS bucket (via GCS Fuse mount):

    # List GCS buckets for this deployment
    gcloud storage ls --project=${PROJECT} | grep directus

    # List objects in the Directus data bucket
    BUCKET=$(gcloud storage buckets list --project=${PROJECT} --format="value(name)" --filter="name~directus" --limit=1)
    gcloud storage ls gs://${BUCKET}
  4. Retrieve the list of files via the Directus Files API:

    curl -H "Authorization: Bearer YOUR_TOKEN" \
    https://${SERVICE_URL}/files
  5. Explore image transformation by requesting a resized version:

    # Replace FILE_ID with the UUID from the Files API response
    curl -o resized.jpg \
    "https://${SERVICE_URL}/assets/FILE_ID?width=300&height=200&fit=cover"

    Expected result: A resized JPEG image is saved locally.


Phase 7 — Webhooks and Real-time [MANUAL]

  1. In the Data Studio, navigate to Settings > Webhooks.

  2. Click Create Webhook:

    • Name: article-created
    • Method: POST
    • URL: https://webhook.site/YOUR_UNIQUE_ID (use webhook.site for testing)
    • Collections: articles
    • Trigger on: Create
  3. Return to Content > Articles and create a new article.

  4. Open your webhook.site page and verify a POST request was received with the new article payload.

    Expected result: A JSON payload with the new article's data appears on webhook.site within a few seconds.

  5. Test WebSocket real-time updates:

    • Open browser developer tools (F12) → Console
    • Run the following snippet to connect to the Directus WebSocket:
    const ws = new WebSocket('wss://SERVICE_URL/websocket');
    ws.onopen = () => {
    ws.send(JSON.stringify({
    type: 'auth',
    access_token: 'YOUR_TOKEN'
    }));
    };
    ws.onmessage = (e) => console.log('Received:', e.data);
    • Create or update an article in the Data Studio
    • Expected result: A real-time message appears in the browser console.
  6. Review the activity log in Settings > Activity Log to see all create, update, and delete events.


Phase 8 — Explore Cloud Logging [MANUAL]

  1. Open the Google Cloud Console Logs Explorer.

  2. Filter logs for the Directus Cloud Run service:

    resource.type="cloud_run_revision"
    resource.labels.service_name="${SERVICE}"
  3. Observe startup logs, API request logs, and any error messages from Directus.

  4. Search for a specific API request:

    resource.type="cloud_run_revision"
    resource.labels.service_name="${SERVICE}"
    httpRequest.requestUrl:"/items/articles"

    Expected result: Log entries matching the API calls you made in Phase 5.

  5. Use gcloud to query logs from the terminal:

    gcloud logging read \
    'resource.type="cloud_run_revision" AND resource.labels.service_name="'${SERVICE}'"' \
    --project=${PROJECT} \
    --limit=20 \
    --format="table(timestamp,httpRequest.requestUrl,httpRequest.status)"

Phase 9 — Explore Cloud Monitoring [MANUAL]

  1. Open the Google Cloud Console Monitoring.

  2. Navigate to Dashboards and open the Cloud Run dashboard for the Directus service.

  3. Review key metrics:

    • Request count — total requests served per minute
    • Request latency — P50, P95, P99 response times
    • Instance count — observe auto-scaling (should reach 0 when idle if min_instance_count = 0)
    • Container memory utilisation — compare against the memory_limit (2Gi)
    • Container CPU utilisation — compare against the cpu_limit (1000m)
  4. Navigate to Uptime Checks. The module provisions an uptime check automatically. Verify it shows a green status.

  5. Navigate to Alerting > Policies to review any configured alert policies.

  6. Use gcloud to list Cloud Run metrics:

    gcloud monitoring metrics list \
    --filter="metric.type:run.googleapis.com" \
    --project=${PROJECT} \
    --limit=10

Phase 10 — Undeploy [AUTOMATED]

When you are finished, return to the RAD UI, navigate to your deployment, and click Undeploy (or Delete) to remove all resources provisioned by this module.

Note: enable_purge = true (the default) ensures all resources including GCS buckets, the Cloud SQL instance, and Cloud Run services are deleted. Set enable_purge = false before undeploying if you want to retain data.

Expected result: The Cloud Run service, Cloud SQL instance, NFS Filestore, Secret Manager secrets, GCS buckets, and Artifact Registry images are all removed from the project.

Resources provisioned by the Services GCP module (VPC, Cloud SQL instance, GKE cluster) are managed separately and must be undeployed via their own RAD UI deployment entry.


Summary

PhaseTypeKey Action
Phase 1 — DeployAutomatedRAD UI deployment provisions Cloud Run, Cloud SQL, NFS, secrets
Phase 2 — Service URLManualRetrieve and verify Cloud Run service URL
Phase 3 — Data StudioManualLog in to Directus, tour Content/Users/Files/Insights/Settings
Phase 4 — CollectionsManualCreate Articles collection and add content items
Phase 5 — APIsManualQuery REST and GraphQL APIs with access token
Phase 6 — FilesManualUpload files, verify GCS storage, test image transformations
Phase 7 — WebhooksManualCreate webhook, test WebSocket real-time connection
Phase 8 — LoggingManualQuery Cloud Logging for Cloud Run request and application logs
Phase 9 — MonitoringManualReview Cloud Run metrics, uptime checks, and alert policies
Phase 10 — UndeployAutomatedRAD UI Undeploy removes all resources