Quickstart: GCP (Compute Engine)

Axemere Gateway sits between your applications and AI providers (OpenAI, Anthropic, etc.), enforcing policies, tracking attribution, and recording every request. This guide deploys the gateway as a binary on a GCP Compute Engine VM with Cloud SQL PostgreSQL.

Table of Contents


Prerequisites

  • Google Cloud SDK (gcloud) configured with a project and credentials that can create Compute Engine VMs, Cloud SQL instances, VPCs, service accounts, and Secret Manager secrets
  • A GCP project with billing enabled
  • curl and jq for testing (installed on the VM in Step 3)
  • An OpenAI or Anthropic API key to store as a credential. You can skip this and test with a policy denial instead.

Architecture

HTTP :7080

proxied calls

optional

Your Application

Axemere Gateway
(Compute Engine VM)

Cloud SQL
PostgreSQL 15
(private IP)

AI Provider
(OpenAI / Anthropic)

Axemere Control Plane
(CP-connected mode)

The gateway runs as a systemd service on the VM. Cloud SQL is accessible over a private VPC IP; no public database endpoint is exposed.


Steps

Step 1: Provision the VPC and Cloud SQL Instance

Create a VPC with private service access so Cloud SQL uses an internal IP:

PROJECT_ID="your-gcp-project-id"
REGION="us-central1"
ZONE="us-central1-a"

gcloud config set project $PROJECT_ID

# Create a dedicated VPC
gcloud compute networks create axemere-vpc \
  --subnet-mode=custom \
  --project=$PROJECT_ID

# Create a subnet
gcloud compute networks subnets create axemere-subnet \
  --network=axemere-vpc \
  --region=$REGION \
  --range=10.0.0.0/24 \
  --project=$PROJECT_ID

# Enable Private Service Access for Cloud SQL
gcloud compute addresses create google-managed-services-axemere \
  --global \
  --purpose=VPC_PEERING \
  --prefix-length=16 \
  --network=axemere-vpc \
  --project=$PROJECT_ID

gcloud services vpc-peerings connect \
  --service=servicenetworking.googleapis.com \
  --ranges=google-managed-services-axemere \
  --network=axemere-vpc \
  --project=$PROJECT_ID

Create the Cloud SQL instance (private IP only):

DB_PASSWORD=$(openssl rand -hex 24)
echo "DB password: $DB_PASSWORD"   # save this

gcloud sql instances create axemere-db \
  --database-version=POSTGRES_15 \
  --tier=db-g1-small \
  --region=$REGION \
  --network=axemere-vpc \
  --no-assign-ip \
  --project=$PROJECT_ID

gcloud sql databases create mvgc_gateway \
  --instance=axemere-db \
  --project=$PROJECT_ID

gcloud sql users set-password postgres \
  --instance=axemere-db \
  --password="$DB_PASSWORD" \
  --project=$PROJECT_ID

Get the private IP:

DB_IP=$(gcloud sql instances describe axemere-db \
  --project=$PROJECT_ID \
  --format='value(ipAddresses[0].ipAddress)')
echo "Cloud SQL private IP: $DB_IP"

Step 2: Create the Compute Engine VM

Create a service account for the VM with minimal permissions:

gcloud iam service-accounts create axemere-gateway \
  --display-name="Axemere Gateway" \
  --project=$PROJECT_ID

# Grant access to Secret Manager (for reading credentials)
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:axemere-gateway@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role="roles/secretmanager.secretAccessor"

Create the VM on the same VPC:

gcloud compute instances create axemere-gateway \
  --project=$PROJECT_ID \
  --zone=$ZONE \
  --machine-type=e2-medium \
  --network=axemere-vpc \
  --subnet=axemere-subnet \
  --no-address \
  --service-account="axemere-gateway@${PROJECT_ID}.iam.gserviceaccount.com" \
  --scopes=cloud-platform \
  --image-family=debian-12 \
  --image-project=debian-cloud \
  --boot-disk-size=20GB \
  --tags=axemere-gateway

Add a firewall rule to allow inbound traffic on port 7080 from within the VPC:

gcloud compute firewall-rules create axemere-gateway-internal \
  --network=axemere-vpc \
  --allow=tcp:7080 \
  --source-ranges=10.0.0.0/24 \
  --target-tags=axemere-gateway \
  --project=$PROJECT_ID

For SSH access, add your IP to a firewall rule on port 22, or use gcloud compute ssh via IAP: gcloud compute ssh axemere-gateway --tunnel-through-iap --zone=$ZONE


Step 3: Install the Gateway Binary

SSH into the VM and install the gateway:

gcloud compute ssh axemere-gateway --tunnel-through-iap --zone=$ZONE

On the VM:

# Install the Axemere APT repository
curl -fsSL https://raw.githubusercontent.com/Axemere-LLC/mvgc-apt/main/gpg.key \
  | sudo gpg --dearmor -o /etc/apt/keyrings/mvgc.gpg

echo "deb [signed-by=/etc/apt/keyrings/mvgc.gpg arch=$(dpkg --print-architecture)] \
  https://raw.githubusercontent.com/Axemere-LLC/mvgc-apt/main stable main" \
  | sudo tee /etc/apt/sources.list.d/mvgc.list

sudo apt update && sudo apt install -y mvgc-gateway jq

Verify the install:

mvgc-gateway --version

Step 4: Store Secrets in Secret Manager

From your local machine (not the VM), store the admin token and database password in GCP Secret Manager:

ADMIN_TOKEN=$(openssl rand -hex 32)

# Admin token
echo -n "$ADMIN_TOKEN" | gcloud secrets create axemere-admin-token \
  --data-file=- --project=$PROJECT_ID

# Database URL
echo -n "postgres://postgres:${DB_PASSWORD}@${DB_IP}:5432/mvgc_gateway?sslmode=disable" \
  | gcloud secrets create axemere-db-url \
  --data-file=- --project=$PROJECT_ID

# AI provider key (optional — skip if testing with policy denial)
echo -n "sk-..." | gcloud secrets create axemere-openai-key \
  --data-file=- --project=$PROJECT_ID

Step 5: Configure and Start the Gateway

On the VM, create a startup script that reads secrets from Secret Manager at boot:

sudo mkdir -p /etc/mvgc

sudo tee /etc/mvgc/env-from-secrets.sh << 'EOF'
#!/bin/bash
# Reads secrets from GCP Secret Manager and exports them as env vars.
# Run as root at service start.

export_secret() {
  local name="$1"
  local var="$2"
  local val
  val=$(gcloud secrets versions access latest --secret="$name" 2>/dev/null)
  if [ -n "$val" ]; then
    export "$var"="$val"
  fi
}

export_secret axemere-db-url       DATABASE_URL
export_secret axemere-admin-token  MVGC_ADMIN_TOKEN
export_secret axemere-openai-key   OPENAI_API_KEY
EOF
sudo chmod 700 /etc/mvgc/env-from-secrets.sh

Create the systemd unit:

sudo tee /etc/systemd/system/mvgc-gateway.service << 'EOF'
[Unit]
Description=Axemere Gateway
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
EnvironmentFile=-/etc/mvgc/mvgc.env
ExecStartPre=/bin/bash /etc/mvgc/env-from-secrets.sh
ExecStart=/usr/bin/mvgc-gateway
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now mvgc-gateway

Check status:

sudo systemctl status mvgc-gateway
sudo journalctl -u mvgc-gateway -f

Step 6: Verify the Deployment

From within the VPC (or via port-forward through IAP):

# If testing locally via IAP tunnel:
gcloud compute start-iap-tunnel axemere-gateway 7080 --local-host-port=localhost:7080 --zone=$ZONE &

curl -s http://localhost:7080/healthz | jq .

Expected response:

{"status":"ok", "version":"...", "node_id":"...", ...}

Step 7: Register a Workload and Send Your First Request

Export your admin token (from Secret Manager):

export MVGC_ADMIN_TOKEN=$(gcloud secrets versions access latest --secret=axemere-admin-token)
GATEWAY_URL="http://localhost:7080"   # adjust to your VM's internal IP if calling from another VM

Register a workload:

curl -s -X PUT "${GATEWAY_URL}/v1/admin/workloads" \
  -H "MVGC-Admin-Token: $MVGC_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "workload_id": "wl-quickstart",
    "org_id": "org-quickstart",
    "name": "Quickstart Workload",
    "default_attribution": { "project_id": "proj-quickstart" },
    "allowed_connection_types": ["direct_api"]
  }' | jq .

Submit a request (or test a policy denial without a key):

# Option A: with an OpenAI key stored in the gateway
curl -s -X POST "${GATEWAY_URL}/v1/actions:execute" \
  -H "Content-Type: application/json" \
  -d '{
    "schema": "mvgc.action_request.v2",
    "org_id": "org-quickstart",
    "workload_id": "wl-quickstart",
    "action": {
      "type": "ai.infer",
      "method": "POST",
      "target_host": "api.openai.com",
      "target_path": "/v1/chat/completions",
      "params": {
        "model": "gpt-4o-mini",
        "messages": [{"role": "user", "content": "Say hello in one sentence."}],
        "max_tokens": 50
      }
    },
    "attribution": { "project_id": "proj-quickstart" }
  }' | jq .

# Option B: test a policy denial (no key needed)
curl -s -X POST "${GATEWAY_URL}/v1/actions:execute" \
  -H "Content-Type: application/json" \
  -d '{
    "schema": "mvgc.action_request.v2",
    "org_id": "org-quickstart",
    "workload_id": "wl-quickstart",
    "action": {
      "type": "ai.infer",
      "method": "POST",
      "target_host": "api.example-blocked.com",
      "params": {"model": "test"}
    },
    "attribution": { "project_id": "proj-quickstart" }
  }' | jq .

Production Considerations

  • Cloud SQL tier. The example uses db-g1-small. Use db-n1-standard-4 or larger for production workloads. Enable high availability in the Cloud SQL settings.
  • VM sizing. e2-medium handles light traffic. Use n2-standard-4 for sustained load.
  • Load balancing. For external access or multiple VMs, put an internal GCP Load Balancer in front. Use a managed SSL certificate for TLS termination.
  • Secret rotation. Rotate axemere-admin-token and provider keys in Secret Manager. The gateway reads secrets at startup; restart the service after rotation.
  • IAP for SSH. Use Identity-Aware Proxy (--tunnel-through-iap) instead of opening port 22 to the internet. No external IP is required on the VM.
  • VPC firewall. Keep the gateway port (7080) restricted to internal VPC ranges. Only expose it externally via a load balancer with TLS.
  • Connecting to the control plane. To manage this gateway from console.axemere.ai, see the Self-Hosted + CP Connected guide.

Next Steps

TaskWhere to look
Configure credentials and policiesConfiguration Reference
Connect to the Axemere control planeCP Connected Onboarding
Set up monitoring and observabilityNetwork Operations Guide
Integrate your applicationDeveloper Integration Guide
Use the managed gateway serviceManaged Gateway Guide

Cleanup

# Stop and remove the gateway service (on the VM)
sudo systemctl stop mvgc-gateway
sudo systemctl disable mvgc-gateway

# From your local machine:
gcloud compute instances delete axemere-gateway --zone=$ZONE --project=$PROJECT_ID
gcloud sql instances delete axemere-db --project=$PROJECT_ID
gcloud secrets delete axemere-admin-token --project=$PROJECT_ID
gcloud secrets delete axemere-db-url --project=$PROJECT_ID
gcloud secrets delete axemere-openai-key --project=$PROJECT_ID
gcloud compute networks delete axemere-vpc --project=$PROJECT_ID