−25%

on annual Windows plans, until 31 Oct. See plans

EQVPS
Get started

Docker Compose for AI agents: a full self-hosted stack on one VPS

Sep 6, 2026 · 3 min read · EQVPS Team

An AI agent is rarely a single process. There's the agent loop itself, a vector store for memory, a cache, usually a database for state, and maybe a small dashboard. Running each of those by hand — starting them, restarting them after a reboot, remembering which port is which — gets old fast. Docker Compose describes the whole thing in one file and runs it with one command. This is the copy-paste stack for putting an agent on a VPS the tidy way.

If you just want the deploy-without-Docker version, the run an AI agent 24/7 guide covers systemd instead. This page is the container-native version.

The stack

A typical self-hosted agent wants four things next to it: the agent process, Qdrant (vector memory), Redis (cache / queues) and Postgres (state). Here's a docker-compose.yml that runs all of it, with internal services kept off the public internet:

# /opt/agent/docker-compose.yml
services:
  agent:
    build: .                      # your agent image (or image: your/agent:latest)
    restart: unless-stopped
    env_file: [.env]              # OPENAI/ANTHROPIC keys etc. — never in this file
    environment:
      QDRANT_URL: http://qdrant:6333
      REDIS_URL: redis://redis:6379
      DATABASE_URL: postgres://agent:${DB_PASSWORD}@postgres:5432/agent
    depends_on: [qdrant, redis, postgres]
    # no ports: — this agent only makes outbound calls. Publish one only if it serves webhooks.

  qdrant:
    image: qdrant/qdrant:latest
    restart: unless-stopped
    volumes: ["qdrant:/qdrant/storage"]   # internal only — not published

  redis:
    image: redis:7-alpine
    restart: unless-stopped
    command: ["redis-server", "--save", "60", "1"]
    volumes: ["redis:/data"]

  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: agent
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: agent
    volumes: ["pg:/var/lib/postgresql/data"]

volumes: { qdrant: {}, redis: {}, pg: {} }

Secrets live in .env, not the compose file:

# /opt/agent/.env  (chmod 600, never committed)
ANTHROPIC_API_KEY=sk-ant-...
DB_PASSWORD=a-long-random-string

Bring it up:

apt update && apt install -y docker.io docker-compose-v2
systemctl enable --now docker
cd /opt/agent && docker compose up -d
docker compose logs -f agent

Every internal service (Qdrant, Redis, Postgres) is reachable only on the compose network by service name — none of them are published to the internet. The agent talks to them over that private network, and nothing on those ports faces the world.

The details that matter

  • restart: unless-stopped on every service — that's what survives a reboot or a crash. Enable Docker on boot and the whole stack comes back on its own.
  • Keys in .env, not YAML. Reference them as env vars; keep .env at chmod 600 and out of git. A leaked compose file with a live key is the classic mistake.
  • Publish nothing you don't have to. An agent that only calls model APIs and its own services needs no inbound port at all — so a NAT plan works. Add a dedicated IP only if it serves webhooks or a dashboard.
  • Size for memory, not cores. API-backed agents are light. If Qdrant's index grows large or you add a local model, that's when you move up — see high-memory VPS for agents.

The part that's actually ours: the agent can build its own box

Because EQVPS exposes an MCP server, an agent running this stack can provision another clean VPS on its own — order it, get root, tear it down — paying from a prepaid crypto balance. A compose stack that needs a fresh sandbox can spin one up without a human in the loop.

Why EQVPS for a Dockerized agent

  • Clean images, root in ~60 seconds. Ubuntu/Debian; docker compose up and the stack is live.
  • No KYC, crypto payment. Email to register, USDC/USDT to pay — nothing tying the box to your identity.
  • NVMe + unmetered 1 Gbit/s, EU (Germany/Finland). Pulling images and shipping logs won't produce a surprise bill.

VPS for AI agents (the overview) → · VPS for Docker → · Host a vector DB for agent memory →

FAQ

Why run an AI agent with Docker Compose instead of bare processes?

An agent is rarely just one process — it's the agent loop plus a vector store, a cache and usually a database. Compose describes the whole stack in one file, brings it all up with one command, restarts each piece on crash or reboot, and keeps internal services (Postgres, Redis, Qdrant) on a private network so only what you choose is exposed. It's the tidiest way to self-host an agent that has moving parts.

What plan does an agent stack need?

For an API-backed agent (the model runs at your provider) the stack is light — the agent loop, Qdrant, Redis and Postgres fit comfortably on our Small ($8/mo) or the AI-Agent plan ($10/mo, 4 GB). You only need more RAM if you hold a large vector index in memory or run a local model, which is a different, heavier setup.

Where do I put the API keys — in the compose file?

No. Keep secrets in a .env file (git-ignored) and reference them as environment variables in compose, or use Docker secrets. Never commit keys into docker-compose.yml. Bind internal services to the compose network only; publish just the agent's port (or nothing, if it only makes outbound calls).

Do the containers come back after a reboot?

Only if you tell them to. Set restart: unless-stopped (or always) on each service and enable Docker on boot; then docker compose up -d survives reboots and crashes. Without a restart policy a container stays down after the server restarts.

Do you ask for KYC or a card?

No. Email to sign up, pay in USDC or USDT — no documents, no card. Root in about a minute.

Comments

No comments yet. Be the first.

Leave a comment

Comments are moderated before they appear.