Docs · Servers

magpie in Docker

Run magpie on a server or a NAS that has no desktop: its gateway serves your models to agents on other computers, and you add providers and sign in to subscriptions from a page in your browser.

Imageghcr.io/wc7086/magpie, for linux/amd64 and linux/arm64
Tagslatest (the newest release), 0.1.1150 (one release), 0.1, edge (every change on main)
Ports3425 the gateway agents call; 3430 the browser UI, when the container runs magpie web; it answers the gateway’s /v1 routes too, so a reverse proxy needs only this port
Volume/config: providers, keys, sign-ins, plugins and usage
Usernonroot (uid 65532)

The image holds magpie’s terminal-only build on Debian 12 slim, with bash for a terminal in the container and curl for the installers of the CLIs some subscriptions sign in with (Cursor, Devin, Grok Build). It runs magpie serve (the gateway alone) unless given another command. The container finds no agents to wire, so magpie in it is a gateway: the agents that use it run elsewhere.

Run it

Run it with the browser UI, a key for that page you keep across restarts, and both ports on the host’s loopback only:

Shell
docker run -d --name magpie --restart unless-stopped \
  -p 127.0.0.1:3425:3425 -p 127.0.0.1:3430:3430 \
  -e MAGPIE_WEB_KEY=$(openssl rand -hex 16) \
  -v magpie-config:/config \
  ghcr.io/wc7086/magpie:latest web --addr 0.0.0.0:3430 --no-open

docker logs magpie

The log names the page with its key:

Output
● magpie web on http://127.0.0.1:3430/?k=0f3c9a1e…
  on the network http://172.17.0.2:3430/?k=0f3c9a1e…
  these are the container's own addresses: other machines use the host's, and MAGPIE_PUBLIC_URL=http://<host>:<port> puts it here
! anyone with the link can change magpie and see its keys, and the network carries it unencrypted
  the link carries MAGPIE_WEB_KEY · gateway http://127.0.0.1:3425 · Ctrl-C to stop
Agents outside the container need a gateway key. In the container any key works. A request from the host or another machine is answered only with an enabled gateway key, and gets 401 without one: make one as in Gateway keys. 127.0.0.1: in -p keeps a port on the host; leave it out, or name the host’s LAN or VPN address, for other machines to reach it.

Without web --addr 0.0.0.0:3430 --no-open the container runs the gateway alone, which you then set up from a terminal in it (docker exec -it magpie magpie provider add …). A folder bind-mounted at /config works in place of the named volume, if uid 65532 can write it: sudo chown -R 65532:65532 /volume1/docker/magpie/config.

The browser UI

Open the link from the log. The key in it is traded for a cookie and taken out of the address; a page opened without it is turned away (401). With MAGPIE_WEB_KEY set (16 or more letters, digits or - . _ ~; openssl rand -hex 16 makes one) the key stays the same across restarts and the browser stays signed in for 400 days. Without it, every start makes a new key and the cookie lasts the browser session.

The page is in gateway mode: Providers, Gateway, Routing, Usage, Plugins and Settings, with no Agents, Sessions or Library, since there are no agents in the container. Settings → General → Gateway mode turns it off.

On a NAS or a server you reach over SSH, open the page through a tunnel rather than publishing 3430: ssh -L 3430:127.0.0.1:3430 you@nas, then the log’s link on your own computer.

Anyone with the link can change magpie and see its keys. Keep 3430 on loopback or a VPN. Across the network, serve it over HTTPS: give magpie a certificate with MAGPIE_TLS_CERT and MAGPIE_TLS_KEY, or put it behind a reverse proxy with TLS, such as Caddy.

Sign in to subscriptions

Add API keys on Providers as on the desktop. A subscription’s sign-in (ChatGPT, Claude…) opens the vendor’s page in your browser, and when you are done the vendor sends that browser back to localhost, for ChatGPT http://localhost:1455/auth/callback?code=…. That is your own computer, not the container, so the page doesn’t load. Copy its whole address from the address bar and paste it into the sign-in’s Callback URL field.

The same from a terminal:

Shell
docker exec -it magpie magpie accounts add codex

Open the link it prints, sign in, then paste the address the browser ended on. The browser UI can also import sign-ins from a file.

A Claude subscription is signed in to and answered through Claude Code, which the image doesn’t have. Have magpie download Anthropic’s own build first: it says the version, where it comes from and where it goes, asks, and checks the download’s SHA-256 against Anthropic’s manifest. It is kept in /config/cache; run it again for a newer one. magpie accounts add claude offers it too when Claude Code is missing.

Shell
docker exec -it magpie magpie claude-code install

A Grok (SuperGrok) subscription signs in through xAI’s Grok Build CLI, which the image doesn’t have either. Its sign-in, in the browser UI or with magpie plugin login grok, installs it first, as xAI’s installer does: the stable version from x.ai/cli, kept in /config/home/.grok. To use a Grok Build binary you put on the volume yourself, set GROK_BIN_DIR to the folder holding it.

What is kept

Everything magpie writes is under /config, so a restart, or a new container on the same volume, keeps your providers, keys, sign-ins and plugins.

PathHolds
/config/magpiemagpie’s own files: settings.json, providers, gateway keys, routing groups
/config/homethe container’s HOME: sign-ins kept where their agent keeps them (~/.codex, ~/.claude…)
/config/cachethe model catalog, Bun, which plugins run on (downloaded the first time one is used), and the Claude Code magpie claude-code install downloaded
/config/data, /config/statethe rest of what magpie keeps

A volume made by an older image keeps working: magpie adds the folders it lacks when it starts. Only sign-ins made with that older image, which lived outside the volume, have to be made again.

Environment

VariableWhat it does
MAGPIE_ADDRwhere the gateway listens. The image sets 0.0.0.0:3425, so the published port reaches it.
MAGPIE_PUBLIC_URLthe address other machines reach the gateway at, such as http://192.168.1.20:3425 (the host’s or the NAS’s, on the published port), or a reverse proxy’s base URL. In the container magpie sees only Docker’s own 172.17.x address; with this set, the address it shows and prints is the one to use.
MAGPIE_WEB_KEYthe browser UI’s key, kept across restarts (16+ characters)
MAGPIE_TLS_CERT, MAGPIE_TLS_KEYa PEM certificate (its chain after it) and its key, mounted into the container: other machines then reach the gateway and the browser UI over https:// only, and plain HTTP from them gets 400. The files are read again when they change, so a renewal needs no restart. One without the other, or files that don’t load, stop magpie from starting. Use https:// in MAGPIE_PUBLIC_URL too.
MAGPIE_ALLOW_IPSthe only addresses other machines may reach the gateway and the browser UI from, as IPs and CIDR ranges: 203.0.113.7,10.0.0.0/8,2001:db8::/32. Any other address gets 403, even with a gateway key. Unset lets every address in, each with a key. See Allowed addresses.
HOME, XDG_CONFIG_HOME, XDG_CACHE_HOME, XDG_DATA_HOME, XDG_STATE_HOMEset by the image to the folders under /config above; leave them

Gateway keys and other machines

  1. Make a key for each clientGateway → Gateway keys, or in a terminal docker exec magpie magpie gateway-key add "Laptop", which prints the new sk-magpie-key-…. Every request from outside the container, the host’s own included, must carry an enabled gateway key, and one without gets 401. A key can have its own daily, weekly, monthly, every-N-days or every-N-hours limit and its own list of models (magpie gateway-key limit, magpie gateway-key models).
  2. Publish the portRecreate the container with -p 3425:3425, or bound to the NAS’s LAN or VPN address (-p 192.168.1.20:3425:3425), and with -e MAGPIE_PUBLIC_URL=http://192.168.1.20:3425.

On each other computer, point the agent at the gateway with one of those keys as its API key: http://192.168.1.20:3425/v1 for an OpenAI client, http://192.168.1.20:3425 for an Anthropic or Gemini one. Model ids are provider/model, or a routing group’s; GET /v1/models lists them. If that computer runs magpie itself, add the container as a Remote magpie instead, and magpie wires its agents for you.

Settings → Network and sharing → Share on local network isn’t needed in the container: turning it on also makes a gateway key named Magpie, and the gateway asks for a key from outside the container either way.

Upgrading from an earlier image. An agent outside the container that sends magpie, or any other key that isn’t an enabled gateway key, now gets 401 (“the API key sent is not an enabled magpie gateway key”). Make it a key as above and put that in the agent’s settings. Agents that already send a gateway key, and a Remote magpie set up with one, keep working.

Allowed addresses. On a public host, set -e MAGPIE_ALLOW_IPS=203.0.113.7,10.0.0.0/8 to the addresses your clients come from. A request from any other address is refused 403 before its key is looked at, so a key that leaks is no use from elsewhere; the refusal names the address it came from, as does the container’s log. magpie judges the address of the connection itself, never an X-Forwarded-For header, and a mistyped entry lets nothing in rather than everything. Docker’s default bridge network passes a client’s own address into the container, but a request from the host itself arrives from the bridge’s gateway (172.17.0.1), and Docker Desktop and rootless Docker show every client as one address of their own: add that, or check what the 403 says. Behind a reverse proxy or tunnel, every request comes from the proxy’s address, so limit who reaches magpie at the proxy. On the desktop app the same list is Settings → Network and sharing → Allowed addresses.

Over the internet, prefer a VPN such as Tailscale or WireGuard to opening 3425. A reverse proxy or tunnel in front of the container is the network too: its clients need a gateway key like any other machine’s.

Docker Compose on a NAS

compose.yaml
services:
  magpie:
    image: ghcr.io/wc7086/magpie:latest
    restart: unless-stopped
    ports:
      # 127.0.0.1: the host alone; every caller outside the container needs a gateway key
      - "127.0.0.1:3425:3425"
      - "127.0.0.1:3430:3430"
    environment:
      MAGPIE_PUBLIC_URL: http://<nas-address>:3425
      MAGPIE_WEB_KEY: <random-key>
    volumes:
      - ./config:/config
    command: [web, --addr, 0.0.0.0:3430, --no-open]

Then: sudo chown -R 65532:65532 ./config, docker compose up -d, open http://127.0.0.1:3430/?k=<random-key> through an SSH tunnel, add your providers and make a gateway key for each machine. For other machines to reach the gateway, change its line to "3425:3425" (or the NAS’s LAN or VPN address) and run docker compose up -d again.

Health, terminal, updates

Questions or a setup worth sharing? Ask on Discord. The reference has the details.