Skip to content

Deployment Guide

This guide covers different deployment options for protoLabs.

Deployment Options

OptionBest ForIsolationSetup Complexity
Local DevelopmentDevelopmentNoneLow
Docker (Isolated)Testing, demosFullLow
Docker (Projects Mounted)Personal usePartialMedium
systemd + DockerProduction serverConfigurableMedium
Cloudflare PagesLanding page hostingFullLow

Landing Page (Cloudflare Pages)

The protoLabs.studio landing page (site/index.html) is deployed as a static site on Cloudflare Pages.

Architecture

site/index.html → Cloudflare Pages → protolabs.studio
                   (300+ edge nodes, serverless)

No build step. Cloudflare serves the static HTML directly from the site/ directory on the main branch.

Cloudflare Pages Configuration

SettingValue
Project nameprotolabs-studio
RepositoryprotoLabsAI/automaker
Production branchmain
Root directorysite
Build command(none)
Build output/
Watch pathssite/**

Custom Domains

DomainTypeBehavior
protolabs.studioApexPrimary (serves content)
www.protolabs.studioCNAME301 redirect to apex

Security & Performance

All configured in the protolabs.studio Cloudflare zone:

SettingValue
SSL modeFull (strict)
HSTSON, max-age=31536000, include subdomains
Min TLS Version1.2
Bot Fight ModeSuper Bot Fight Mode (Pro)
Auto MinifyHTML, CSS, JS
BrotliON
HTTP/3ON
Always OnlineON
Browser Cache TTL4 hours
Edge Cache TTL1 day

Newsletter Integration

The signup form posts directly to Buttondown (username: protoLabsAI). No server-side code or API keys required. Submissions are tagged launch-list for segmentation.

Deployment Trigger

Merging to main with changes in site/** triggers an automatic Cloudflare Pages deploy. No CI configuration needed — Cloudflare watches the repo directly.

Verification

bash
curl -I https://protolabs.studio      # 200 + CF-Ray header
curl -I https://www.protolabs.studio   # 301 → apex
curl -I http://protolabs.studio        # redirect → HTTPS

Local Development

For development, run protoLabs directly on your machine:

bash
# Install dependencies
npm install

# Interactive launcher
npm run dev

# Or directly:
npm run dev:full      # Web mode — starts UI (:3007) AND server (:3008) together
npm run dev:web       # UI only at localhost:3007 (requires server separately)

Requirements

  • Node.js 22+
  • Git
  • npm

Environment Variables

Create a .env file:

bash
ANTHROPIC_API_KEY=sk-ant-xxx
AUTOMAKER_API_KEY=your-local-key

Docker (Isolated)

Run protoLabs in complete isolation from your filesystem:

bash
docker compose up -d

Access at http://localhost:3007 (UI), http://localhost:3008 (API), http://localhost:3009 (Docs)

Characteristics

  • No access to host files - Only Docker volumes
  • Named volumes persist data - Survives container restarts
  • Projects created inside container - Use web UI to create projects

When to Use

  • Testing protoLabs safely
  • Demo environments
  • CI/CD testing

Docker (Projects Mounted)

Mount your projects directory for development use:

1. Create Override File

Create docker-compose.override.yml:

yaml
services:
  server:
    volumes:
      # Mount your projects directory
      # IMPORTANT: Container path MUST match host path
      - /home/youruser/dev:/home/youruser/dev:rw
    environment:
      - ALLOWED_ROOT_DIRECTORY=/home/youruser/dev
      - GH_TOKEN=${GH_TOKEN}

2. Build with Your UID/GID

bash
UID=$(id -u) GID=$(id -g) docker compose build

3. Start

bash
docker compose up -d

Path Mapping Rules

Critical: Container paths MUST match host paths for the MCP plugin to work:

yaml
# CORRECT - paths match
- /home/youruser/dev:/home/youruser/dev:rw

# WRONG - paths don't match (MCP plugin will fail)
- /projects:/home/youruser/dev

systemd

Two systemd units ship in the repo. Pick exactly one per host:

UnitRunsWhen to use
automaker-docker.servicedocker compose up -dContainerized prod, full filesystem isolation, no host CLI access from agents
automaker-host.servicenpm start (= start-automaker.mjs --production)Bare-metal prod. Agents can shell out to host CLIs (gh, codex, opencode, infisical, claude).

The host-process variant exists because agents spawn external tools via child_process; in containers those tools either aren't installed or can't see the host's auth files. If your operator workflow depends on gh auth login or codex login happening on the host, use automaker-host.service.

Install the host-process variant

bash
# Copy the service file
sudo cp automaker-host.service /etc/systemd/system/

# Edit for your environment if defaults don't match
sudo nano /etc/systemd/system/automaker-host.service
#   WorkingDirectory  = clone path (default: /opt/protomaker)
#   User / Group      = deploy user (default: automaker)
#   Environment=HOME  = $HOME for that user (default: /home/automaker)

sudo systemctl daemon-reload
sudo systemctl enable --now automaker-host.service
journalctl -u automaker-host -f

Install the Docker variant

bash
# Copy the service file
sudo cp automaker-docker.service /etc/systemd/system/

# Edit for your environment
sudo nano /etc/systemd/system/automaker-docker.service
#   WorkingDirectory = path containing the compose file
#   User / Group     = deploy user

The shipped file uses the default docker-compose.yml. For a prod deploy, set WorkingDirectory to the directory containing docker-compose.prod.yml and add Environment=COMPOSE_FILE=docker-compose.prod.yml to the [Service] block.

Enable and start

bash
sudo systemctl daemon-reload

# Pick exactly one:
sudo systemctl enable --now automaker-host.service
# OR
sudo systemctl enable --now automaker-docker.service

# Check status (substitute the unit you enabled):
sudo systemctl status automaker-host

4. Management Commands

bash
# View logs
sudo journalctl -u automaker -f

# Restart
sudo systemctl restart automaker

# Stop
sudo systemctl stop automaker

# Disable on boot
sudo systemctl disable automaker

Environment Variables Reference

Authentication

VariableRequiredDescription
ANTHROPIC_API_KEYYes*Anthropic API key
CLAUDE_OAUTH_CREDENTIALSYes*Claude CLI OAuth JSON
AUTOMAKER_API_KEYNoprotoLabs API key (default: protoLabs_studio_key)
CURSOR_AUTH_TOKENNoCursor CLI OAuth token
GH_TOKENNoGitHub CLI token

*At least one of ANTHROPIC_API_KEY or CLAUDE_OAUTH_CREDENTIALS is required.

Server Configuration

VariableDefaultDescription
PORT3008Server port
HOST0.0.0.0Host to bind to
HOSTNAMElocalhostHostname for user-facing URLs
DATA_DIR./data or /dataData storage directory
ALLOWED_ROOT_DIRECTORY/projectsRestrict file operations
CORS_ORIGINhttp://localhost:3007Allowed CORS origin

Feature Flags

VariableDefaultDescription
IS_CONTAINERIZEDfalseSkip sandbox confirmation dialogs
AUTOMAKER_MOCK_AGENTfalseUse mock agent (for testing)
AUTOMAKER_AUTO_LOGINfalseSkip login prompt (dev only)

Integrations

VariableRequiredDescription
DISCORD_TOKENNoDiscord bot token for event routing and notifications
DISCORD_GUILD_IDNoDiscord server (guild) ID
DISCORD_CHANNEL_SUGGESTIONSNoChannel ID for #suggestions — community feature ideas
DISCORD_CHANNEL_PROJECT_PLANNINGNoChannel ID for #project-planning — epic and milestone discussions
DISCORD_CHANNEL_AGENT_LOGSNoChannel ID for #agent-logs — agent start/stop/complete events
DISCORD_CHANNEL_CODE_REVIEWNoChannel ID for #code-review — PR reviews and architecture discussions
DISCORD_CHANNEL_INFRANoChannel ID for #infra — infrastructure alerts, health checks, Ava Gateway heartbeat monitoring

Monitoring (Grafana)

VariableDefaultDescription
GF_ADMIN_USERadminGrafana admin username (override in staging/prod)
GF_ADMIN_PASSWORDadminGrafana admin password (override in staging/prod)

Set these in your .env file to override the defaults for staging/production deployments:

bash
GF_ADMIN_USER=your-admin-username
GF_ADMIN_PASSWORD=a-strong-password

Note: Production deployments use Docker secrets for credential management. See docker-compose.prod.yml for the production pattern.

Frontend Configuration

VariableDefaultDescription
VITE_SERVER_URL''API server URL (empty = relative)
VITE_HOSTNAMElocalhostHostname for API URLs

Extracting OAuth Credentials

Claude CLI (macOS)

bash
# Extract from Keychain
./scripts/get-claude-token.sh

# Use in Docker
export CLAUDE_OAUTH_CREDENTIALS=$(./scripts/get-claude-token.sh)
docker compose up -d

Claude CLI (Linux)

bash
# On Linux, mount the directory directly
services:
  server:
    volumes:
      - ~/.claude:/home/automaker/.claude:ro

Cursor CLI (macOS)

bash
# Extract from Keychain
./scripts/get-cursor-token.sh

# Use in Docker
export CURSOR_AUTH_TOKEN=$(./scripts/get-cursor-token.sh)

Cursor CLI (Linux)

bash
# Extract from config file
export CURSOR_AUTH_TOKEN=$(jq -r '.accessToken' ~/.config/cursor/auth.json)

GitHub CLI

bash
# Extract existing token
export GH_TOKEN=$(gh auth token)

SSL/TLS Configuration

For production deployments with HTTPS, use a reverse proxy:

nginx Example

nginx
server {
    listen 443 ssl;
    server_name protolabs.example.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    location / {
        proxy_pass http://localhost:3007;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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;
        proxy_read_timeout 86400;
    }

    location /api {
        proxy_pass http://localhost:3008;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_read_timeout 86400;
    }
}

Update CORS

When using a custom domain:

yaml
services:
  server:
    environment:
      - CORS_ORIGIN=https://protolabs.example.com

Updating

Docker

bash
# Pull latest code
git pull

# Rebuild and restart
docker compose build --no-cache
docker compose up -d

systemd

bash
# Pull latest code
cd /path/to/protomaker
git pull

# Rebuild and restart
sudo systemctl restart automaker

Backup Before Updating

bash
# Backup Docker volumes
docker run --rm \
  -v automaker-data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/automaker-backup-$(date +%Y%m%d).tar.gz /data

See backup-recovery.md for detailed backup procedures.

Proxmox VM Specifications

Use CaseDiskRAMvCPUNotes
Minimum25 GB4 GB2Evaluation only, expect slowness
Baseline40 GB8 GB4Most users, comfortable operation
Heavy Use80-120 GB16 GB6-8Multiple concurrent agents, large repos

Proxmox-Specific Settings

Storage: Use thin provisioning, virtio-scsi with discard enabled, enable TRIM in guest OS.

Memory: Do NOT overcommit RAM. Disable ballooning (Node.js + Docker perform poorly with it).

CPU: Set CPU type to host. Enable NUMA only if >= 16 GB RAM.

Recommended Distro: Ubuntu 22.04 LTS or Debian 12.

Built by protoLabs — Open source on GitHub