Local Development
For local development, simply run the Next.js dev server:Production Deployment with Docker Compose
The Pope Bot uses Docker Compose to orchestrate three services in production:Services Overview
| Service | Image | Purpose |
|---|---|---|
| traefik | traefik:v3 | Reverse proxy with automatic HTTPS (Let’s Encrypt) |
| event-handler | stephengpope/thepopebot:event-handler-${THEPOPEBOT_VERSION} | Node.js runtime + PM2, serves the bind-mounted Next.js app on port 80 |
| runner | myoung34/github-runner:latest | Self-hosted GitHub Actions runner for executing agent jobs |
run-job.yml to spin up Docker agent containers directly on your server. It also has a read-only volume mount (.:/project:ro) so upgrade-event-handler.yml can run docker compose commands against the project’s compose file.
Understanding the Docker Setup
Event Handler Image
The event handler Dockerfile (templates/docker/event-handler/Dockerfile) is not a self-contained application image. It uses a multi-stage build:
- First stage installs build tools (python3, make, g++) to compile native addons during
npm install - Final image keeps only runtime dependencies (git, gh, PM2) and the pre-compiled
node_modules - It does not contain the Next.js app code and does not run
next build
Volume Mount Strategy
Thedocker-compose.yml uses two volume mounts that work together:
- The bind mount (
.:/app) overlays the entire/appdirectory with the host’s project files — app pages, config,.next/,.env, everything - This would clobber the container’s
/app/node_moduleswith the host’s node_modules (which may be compiled for a different platform) - But the anonymous volume (
/app/node_modules) shields that specific path from the bind mount - Docker processes volume mounts so the anonymous volume “wins” for
/app/node_modules - The first time the container starts, Docker copies the image’s node_modules into the anonymous volume, and from then on it persists there independently
Why thepopebot is Installed Twice
The user runsnpm install on the host and the Docker image has its own npm install. Both are necessary:
Host installation:
- Needed because
next buildmust resolve allthepopebot/*imports to compile the app - Without thepopebot in local node_modules, the build fails immediately on unresolved imports
- The
.next/output is just bundled JavaScript — it’s platform-independent
- Next.js needs
node_modulesat runtime for native modules (likebetter-sqlite3) and server-side requires that aren’t bundled - Those native modules must be compiled for Linux
- Different purposes, different platforms, both necessary
Build Requirements
Before runningdocker compose up, you must run npm run build on the host to generate .next/.
- If the container starts without a valid
.next/build, PM2 will crash-loop with “Could not find a production build” until a build is available - After code changes,
rebuild-event-handler.ymlrunsnext buildinside the container viadocker exec(using the container’s node_modules)
VPS Deployment Guide
Deploy your agent to a cloud VPS with HTTPS.1. Server Prerequisites
You need a VPS (any provider — Hetzner, DigitalOcean, AWS, etc.) with:- Docker + Docker Compose
- Node.js 18+
- Git
- GitHub CLI (
gh)
mybot.example.com) to your server’s IP address with a DNS A record.
2. Scaffold and Configure
SSH into your server and scaffold the project:APP_URL, enter your production URL with https:// (e.g., https://mybot.example.com).
Set the RUNS_ON GitHub variable so workflows use your server’s self-hosted runner instead of GitHub-hosted runners:
3. Enable HTTPS with Let’s Encrypt
Thedocker-compose.yml has Let’s Encrypt support built in but commented out. Three edits to enable it:
a) Add your email to .env:
b) Uncomment TLS configuration in docker-compose.yml
In the traefik service command, remove the # from the TLS lines:
c) Switch event-handler to HTTPS entrypoint
In the event-handler labels, add a# to comment out the HTTP entrypoint, and remove the # from the two HTTPS lines:
4. Build and Launch
Domain Configuration
Point your domain to your server’s IP address with a DNS A record:Production Considerations
Monitoring
- Check service status:
docker compose ps - View logs:
docker compose logs -f event-handler - Check runner status:
docker compose logs -f runner
Updates
The framework includes automatic upgrade workflows:upgrade-event-handler.yml— Pulls latest image and restarts container- Agent can trigger upgrades via the
modify-selfskill
Backups
Back up these critical files:.env— Contains all secrets and configurationdata/thepopebot.sqlite— Database with API keys, sessions, chat historyconfig/— Custom configuration filesskills/— Custom skills
Resource Usage
- Event handler: ~200MB RAM
- Runner: ~100MB RAM
- Traefik: ~50MB RAM
- Agent job containers: 1-4GB RAM (ephemeral)