Self-Hosted Gateway

Self-Hosted + Control Plane: Your gateway runs on your own infrastructure and is managed from the Axemere cloud: policies, credentials, and analytics synchronized automatically. For the standalone gateway with no cloud connectivity, see Free Gateway.

Target time: under 5 minutes from cold start to first proxied request.

Prerequisites


Step 1: Generate an Enrollment Token

  1. Go to console.axemere.ai/gateways and click Enroll Node
  2. Enter a label for this node (e.g. prod-us-east, local-dev, bst-keith-dev)
  3. Click Generate Token

The dialog shows everything you need pre-filled. Click the .env file tab, then click Copy to copy the entire block.

The token is shown once and cannot be retrieved again. If you close the dialog before copying, generate a new token.

Tokens expire in 24 hours. If the gateway fails to start before the token is used, generate a new one.


Step 2: Start the Gateway with Docker

There are two Compose files:

  • docker-compose.postgres.yaml: includes a bundled PostgreSQL container. Use this one unless you already have a PostgreSQL 15+ instance you want to point the gateway at.
  • docker-compose.yaml: gateway only. Requires you to set DATABASE_URL in .env pointing at your existing PostgreSQL 15+ instance.

Download the Compose file, then paste the .env content you copied in Step 1:

curl -fsSL https://github.com/Axemere-LLC/mvgc-releases/releases/latest/download/docker-compose.postgres.yaml \
  -o docker-compose.yaml

Paste your copied .env content into a file named .env in the same directory, then start the gateway:

docker compose up -d

Wait a few seconds for the database to initialize, then verify:

curl -s http://localhost:7080/healthz | jq '{status, cp_status}'

Expected:

{"status": "ok", "cp_status": "connected"}

If cp_status is "offline" or "unconfigured", see Troubleshooting.

console.axemere.aiAxemere Control PlaneYour Gatewayconsole.axemere.aiAxemere Control PlaneYour Gatewayhealthz cp_status: connectedRegister(node_id, bootstrap_token)org confirmed + mTLS certificatePull policy bundlebundle YAMLPull credentialsresolved credential setnode heartbeat visible

Step 3: Verify the Node Appears in the Console

  1. Go to console.axemere.ai/gateways
  2. Your node should appear with a green Connected status badge

If the node does not appear after 30 seconds, check the gateway logs:

docker compose logs gateway --tail=50

Step 4: Send Your First Request

4a. Add a Credential

The gateway uses this to authenticate to your AI provider on your behalf.

  1. Go to console.axemere.ai/credentials
  2. Click Add Credential
  3. Select your provider (e.g. Anthropic or OpenAI), enter your API key, enable Org Default, and save

Org Default makes the credential available to all gateway requests. Without it, the transparent proxy URL below (which carries no workload context) will fail to resolve a key.

The Control Plane syncs the credential to your gateway automatically. No restart needed.

4b. Send Your First Request

# The gateway resolves your credential from the Control Plane automatically
curl -s -X POST http://localhost:7080/proxy/anthropic/v1/messages \
-H "Content-Type: application/json" \
-H "anthropic-version: 2023-06-01" \
-d '{
  "model": "claude-haiku-4-5",
  "max_tokens": 64,
  "messages": [{"role": "user", "content": "Hello"}]
}' | jq .

Check the Dashboard at console.axemere.ai. Your request appears in the traffic chart within a few seconds. For the full record (provider, model, tokens, latency, and policy decision), open the Records page.

To test policy enforcement (no API key needed):

curl -s -X POST http://localhost:7080/v1/actions:execute \
  -H "MVGC-Admin-Token: $MVGC_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "schema": "mvgc.action_request.v2",
    "org_id": "'"$ORG_ID"'",
    "action": {
      "type": "ai.infer",
      "method": "POST",
      "target_host": "api.example-blocked.com",
      "params": {"model": "test"}
    }
  }' | jq .

This should return decision: "deny", confirming the gateway's default policy blocks unknown targets.


Install on your platform

Running somewhere other than Docker? Choose your platform:


Troubleshooting

cp_status: "offline" after startup

  • Verify MVGC_CP_ADDR is us.cp.axemere.ai:9090
  • Verify MVGC_ORG_ID matches your Org ID (visible under Settings)
  • Verify MVGC_BOOTSTRAP_TOKEN was copied in full and has not expired; manage tokens on the Gateways page
  • Check that port 9090 outbound is not blocked by a firewall
  • Check the gateway logs: docker compose logs gateway --tail=50

cp_status: "unconfigured"

The gateway started without MVGC_BOOTSTRAP_TOKEN set in .env. Stop the stack, set the variable, and restart.

Node appears in console but shows Degraded

The gateway is connected but the last heartbeat took longer than usual. This clears automatically. If it persists, check the gateway logs for CP sync errors.

cp_status: "connected" but no data in the dashboard

The gateway is connected. Dashboard data appears after the first request is processed. Check that the request returned decision: "allow" (not "deny") and that org_id in the request body matches your Org ID.


Next Steps

GoalResource
Add team members to your orgTeam Guide
Configure provider credentials via the consoleCredentials Guide
Write policies to allow/deny by workload or costPolicies Guide
Deploy on GCP, AWS, or bare-metalInstall Guides
Monitor gateway health and request trafficNetwork Operations Guide