Production (VPS)
Prerequisites
Section titled “Prerequisites”- A VPS (Ubuntu/Debian) with root or sudo access
- A domain name with DNS A record pointed to the VPS
- Node.js 18+ or Docker installed
- Nginx installed (
sudo apt install nginx) - A
tollbooth.config.yamlready (see Getting Started)
1. Run tollbooth
Section titled “1. Run tollbooth”Docker (recommended)
Section titled “Docker (recommended)”docker run -d \ --name tollbooth \ --restart unless-stopped \ -p 127.0.0.1:3000:3000 \ -v $(pwd)/tollbooth.config.yaml:/app/tollbooth.config.yaml \ --env-file .env \ ghcr.io/loa212/x402-tollbooth:latestTip: Pin a specific image tag (e.g.
ghcr.io/loa212/x402-tollbooth:0.3.0) instead oflatestfor reproducible deploys.
npx tollbooth startIf using npx, you’ll need a process manager to keep tollbooth running — see the next section.
2. Process manager
Section titled “2. Process manager”Skip this if you’re using Docker with --restart unless-stopped.
systemd
Section titled “systemd”Create /etc/systemd/system/tollbooth.service:
[Unit]Description=tollbooth API gatewayAfter=network.target
[Service]Type=simpleUser=tollboothWorkingDirectory=/opt/tollboothExecStart=/usr/bin/npx tollbooth startRestart=on-failureEnvironmentFile=/opt/tollbooth/.env
[Install]WantedBy=multi-user.targetsudo systemctl enable tollboothsudo systemctl start tollboothPM2 (alternative)
Section titled “PM2 (alternative)”pm2 start "npx tollbooth start" --name tollboothpm2 savepm2 startup3. Nginx reverse proxy
Section titled “3. Nginx reverse proxy”Create /etc/nginx/sites-available/tollbooth:
server { listen 80; server_name tollbooth.example.com; return 301 https://$host$request_uri;}
server { listen 443 ssl http2; server_name tollbooth.example.com;
# TLS — managed by certbot (see step 4) ssl_certificate /etc/letsencrypt/live/tollbooth.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/tollbooth.example.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / { proxy_pass http://127.0.0.1:3000;
# Standard proxy headers proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;
# Streaming / SSE — tollbooth streams responses from upstream APIs, # so Nginx must not buffer them. proxy_buffering off; proxy_cache off; proxy_http_version 1.1; proxy_set_header Connection ''; chunked_transfer_encoding on; proxy_set_header X-Accel-Buffering no;
# Long timeout for streaming AI responses proxy_read_timeout 300s; proxy_send_timeout 300s; }}Enable the site and reload:
sudo ln -s /etc/nginx/sites-available/tollbooth /etc/nginx/sites-enabled/sudo nginx -tsudo systemctl reload nginx4. TLS with Let’s Encrypt
Section titled “4. TLS with Let’s Encrypt”sudo apt install certbot python3-certbot-nginxsudo certbot --nginx -d tollbooth.example.comCertbot will obtain the certificate and configure auto-renewal. If you run certbot before creating the Nginx config above, use certbot --nginx and it will scaffold the TLS directives for you.
5. Environment variables
Section titled “5. Environment variables”Create an .env file with any secrets your config references (e.g. ${API_KEY}):
ANTHROPIC_API_KEY=sk-ant-...OPENAI_API_KEY=sk-...Lock down permissions:
chmod 600 /opt/tollbooth/.envDocker reads this via --env-file .env. systemd reads it via EnvironmentFile=. See Configuration → Environment variables for the ${VAR} interpolation syntax.
6. Verify
Section titled “6. Verify”# Health checkcurl https://tollbooth.example.com/health# → {"status":"ok"}
# x402 discoverycurl https://tollbooth.example.com/.well-known/x402
# Test a paid route — should return 402curl -i https://tollbooth.example.com/weather# → HTTP/2 402- Logs:
journalctl -u tollbooth -f(systemd) ordocker logs -f tollbooth(Docker). - To run multiple tollbooth instances, add an
upstreamblock in Nginx with multipleserverentries and useproxy_pass http://upstream_name. Use shared Redis stores so rate limits/sessions/cache stay consistent: Scaling and Shared Stores. - If you put Cloudflare in front of Nginx, disable response buffering for streaming routes or use Cloudflare Tunnel.