Files
paperclip/doc/DOCKER.md
2026-03-18 07:59:32 -05:00

4.8 KiB

Docker Quickstart

Run Paperclip in Docker without installing Node or pnpm locally.

One-liner (build + run)

docker build -t paperclip-local . && \
docker run --name paperclip \
  -p 3100:3100 \
  -e HOST=0.0.0.0 \
  -e PAPERCLIP_HOME=/paperclip \
  -v "$(pwd)/data/docker-paperclip:/paperclip" \
  paperclip-local

Open: http://localhost:3100

Data persistence:

  • Embedded PostgreSQL data
  • uploaded assets
  • local secrets key
  • local agent workspace data

All persisted under your bind mount (./data/docker-paperclip in the example above).

Compose Quickstart

docker compose -f docker-compose.quickstart.yml up --build

Defaults:

  • host port: 3100
  • persistent data dir: ./data/docker-paperclip

Optional overrides:

PAPERCLIP_PORT=3200 PAPERCLIP_DATA_DIR=./data/pc docker compose -f docker-compose.quickstart.yml up --build

If you change host port or use a non-local domain, set PAPERCLIP_PUBLIC_URL to the external URL you will use in browser/auth flows.

Authenticated Compose (Single Public URL)

For authenticated deployments, set one canonical public URL and let Paperclip derive auth/callback defaults:

services:
  paperclip:
    environment:
      PAPERCLIP_DEPLOYMENT_MODE: authenticated
      PAPERCLIP_DEPLOYMENT_EXPOSURE: private
      PAPERCLIP_PUBLIC_URL: https://desk.koker.net

PAPERCLIP_PUBLIC_URL is used as the primary source for:

  • auth public base URL
  • Better Auth base URL defaults
  • bootstrap invite URL defaults
  • hostname allowlist defaults (hostname extracted from URL)

Granular overrides remain available if needed (PAPERCLIP_AUTH_PUBLIC_BASE_URL, BETTER_AUTH_URL, BETTER_AUTH_TRUSTED_ORIGINS, PAPERCLIP_ALLOWED_HOSTNAMES).

Set PAPERCLIP_ALLOWED_HOSTNAMES explicitly only when you need additional hostnames beyond the public URL host (for example Tailscale/LAN aliases or multiple private hostnames).

Claude + Codex Local Adapters in Docker

The image pre-installs:

  • claude (Anthropic Claude Code CLI)
  • codex (OpenAI Codex CLI)

If you want local adapter runs inside the container, pass API keys when starting the container:

docker run --name paperclip \
  -p 3100:3100 \
  -e HOST=0.0.0.0 \
  -e PAPERCLIP_HOME=/paperclip \
  -e OPENAI_API_KEY=... \
  -e ANTHROPIC_API_KEY=... \
  -v "$(pwd)/data/docker-paperclip:/paperclip" \
  paperclip-local

Notes:

  • Without API keys, the app still runs normally.
  • Adapter environment checks in Paperclip will surface missing auth/CLI prerequisites.

Untrusted PR Review Container

If you want a separate Docker environment for reviewing untrusted pull requests with codex or claude, use the dedicated review workflow in doc/UNTRUSTED-PR-REVIEW.md.

That setup keeps CLI auth state in Docker volumes instead of your host home directory and uses a separate scratch workspace for PR checkouts and preview runs.

Onboard Smoke Test (Ubuntu + npm only)

Use this when you want to mimic a fresh machine that only has Ubuntu + npm and verify:

  • npx paperclipai onboard --yes completes
  • the server binds to 0.0.0.0:3100 so host access works
  • onboard/run banners and startup logs are visible in your terminal

Build + run:

./scripts/docker-onboard-smoke.sh

Open: http://localhost:3131 (default smoke host port)

Useful overrides:

HOST_PORT=3200 PAPERCLIPAI_VERSION=latest ./scripts/docker-onboard-smoke.sh
PAPERCLIP_DEPLOYMENT_MODE=authenticated PAPERCLIP_DEPLOYMENT_EXPOSURE=private ./scripts/docker-onboard-smoke.sh
SMOKE_DETACH=true SMOKE_METADATA_FILE=/tmp/paperclip-smoke.env PAPERCLIPAI_VERSION=latest ./scripts/docker-onboard-smoke.sh

Notes:

  • Persistent data is mounted at ./data/docker-onboard-smoke by default.
  • Container runtime user id defaults to your local id -u so the mounted data dir stays writable while avoiding root runtime.
  • Smoke script defaults to authenticated/private mode so HOST=0.0.0.0 can be exposed to the host.
  • Smoke script defaults host port to 3131 to avoid conflicts with local Paperclip on 3100.
  • Smoke script also defaults PAPERCLIP_PUBLIC_URL to http://localhost:<HOST_PORT> so bootstrap invite URLs and auth callbacks use the reachable host port instead of the container's internal 3100.
  • In authenticated mode, the smoke script defaults SMOKE_AUTO_BOOTSTRAP=true and drives the real bootstrap path automatically: it signs up a real user, runs paperclipai auth bootstrap-ceo inside the container to mint a real bootstrap invite, accepts that invite over HTTP, and verifies board session access.
  • Run the script in the foreground to watch the onboarding flow; stop with Ctrl+C after validation.
  • Set SMOKE_DETACH=true to leave the container running for automation and optionally write shell-ready metadata to SMOKE_METADATA_FILE.
  • The image definition is in Dockerfile.onboard-smoke.