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
StagingHigh-concurrency agentsPartialLow (setup-staging.sh)
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 (choose web or electron)
npm run dev

# Or directly:
npm run dev:web       # Web browser at localhost:3007
npm run dev:electron  # Desktop app

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 + Docker

For persistent server deployments, use systemd to manage Docker Compose.

1. Install Service File

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

# Edit for your environment
sudo nano /etc/systemd/system/automaker.service

2. Configure Service

Edit the service file:

ini
[Unit]
Description=protoLabs AI Development Studio
After=docker.service
Requires=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/home/youruser/automaker
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
ExecReload=/usr/bin/docker compose restart
TimeoutStartSec=120
TimeoutStopSec=60
Restart=on-failure
RestartSec=10

# Run as your user
User=youruser
Group=youruser

Environment=COMPOSE_PROJECT_NAME=automaker

[Install]
WantedBy=multi-user.target

3. Enable and Start

bash
# Reload systemd
sudo systemctl daemon-reload

# Enable on boot
sudo systemctl enable automaker

# Start now
sudo systemctl start automaker

# Check status
sudo systemctl status automaker

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)
DISCORD_WEBHOOK_INFRA(empty)Discord webhook URL for infrastructure alerts

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
VITE_SKIP_ELECTRONfalseBuild without Electron

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