Skip to main content

Deployment Guide

Hitler uses a split deployment architecture:
  • Web app (Next.js) → deployed on Vercel at mako.devinagiffy.xyz
  • API + Bot + Databases → deployed via Docker Compose on a VPS at api.mako.devinagiffy.xyz

Architecture Overview


Part 1: VPS Deployment (API + Bot + Databases)

Prerequisites

  • A GCP Compute Engine instance running Ubuntu (22.04 or 24.04 LTS recommended) with at least 2 GB RAM
  • gcloud CLI installed and authenticated on your local machine
  • A domain pointing to the instance (api.mako.devinagiffy.xyz)

Step 1: SSH into Your Instance

GCP automatically creates a user matching your local username and manages SSH keys for you. You land as a non-root user with sudo access — no need to create a separate user.

Step 2: Initial Server Setup

Step 3: Create a Deploy User

Create a dedicated hitler user to keep application files separate from your personal account:
You can switch to the hitler user anytime:
From now on, all remaining steps are done as the hitler user (sudo su - hitler).

Step 4: Configure Firewall

GCP VPC firewall (run from your local machine):
OS-level firewall (on the instance, as hitler user):

Step 5: Install Docker

Reconnect as hitler (re-login to pick up the docker group):

Step 6: Install Node.js and pnpm (optional, for running migrations from host)

Step 7: Set Up GitHub SSH Key

Generate an SSH key on the server and add it to GitHub so you can clone private repos:
Copy the output, then add it to GitHub:
  1. Go to github.com/settings/keys
  2. Click New SSH key
  3. Title: Hitler Server (or whatever you like)
  4. Key type: Authentication
  5. Paste the public key and click Add SSH key
Verify the connection:

Step 8: Clone and Configure

Edit .env with your production values (see Environment Variables below):

Step 9: Deploy with Docker Compose

Or use the Makefile:
The docker-compose.deploy.yml starts API, Slack Bot, Postgres (pgvector/pgvector:pg16), and Redis. The web service is deployed separately on Vercel (see Part 2). The Postgres image uses pgvector/pgvector:pg16 instead of standard postgres:16-alpine to support the pgvector extension required by the context memory system.

Step 10: Run Database Migrations

Existing deployments: If you previously used postgres:16-alpine and switched to pgvector/pgvector:pg16, run REINDEX DATABASE hitler; inside the Postgres container to avoid index corruption. The must_change_password column on the users table is added automatically by migration — no manual steps needed.

Step 11: Point DNS to VPS

Add an A record at your domain registrar: Verify it resolves:

Step 12: Set Up Nginx Reverse Proxy

Install Nginx:
Create the site config:
Paste:
Enable the site and reload:

Step 13: Set Up SSL with Certbot

Install Certbot via snap (recommended by Certbot/EFF):
Generate and install the SSL certificate:
Certbot will auto-detect your Nginx server blocks and ask which domain to enable HTTPS for. Select api.mako.devinagiffy.xyz. Certbot will:
  1. Verify domain ownership via HTTP challenge
  2. Generate a Let’s Encrypt SSL certificate
  3. Automatically modify the Nginx config to add SSL
  4. Set up auto-renewal (runs twice daily via systemd timer)
Verify auto-renewal is active:
After Certbot runs, your Nginx config will automatically be updated to:

Step 14: Verify


Part 2: Vercel Deployment (Web App)

Step 1: Import to Vercel

  1. Go to vercel.com/new
  2. Import your Git repository
  3. Set the following:
    • Root Directory: apps/web
    • Framework Preset: Next.js
    • Build Command: cd ../.. && pnpm install && pnpm --filter @hitler/web build
    • Output Directory: .next

Step 2: Set Environment Variables

In Vercel project settings → Environment Variables:

Step 3: Configure Custom Domain

  1. In Vercel project settings → Domains
  2. Add mako.devinagiffy.xyz
  3. Add the DNS records Vercel provides to your domain registrar:
    • A record: 76.76.21.21 (or the IP Vercel gives you)
    • CNAME: cname.vercel-dns.com (for www subdomain, optional)

Step 4: Deploy

Push to your main branch — Vercel auto-deploys on every push.

Environment Variables

Required (VPS .env)

Slack Integration

LLM Provider

Secrets Storage (Production)

URLs and CORS

Full .env Example


DNS Configuration

Set up these DNS records at your domain registrar (devinagiffy.xyz):
DNS propagation can take up to 48 hours, but usually completes within minutes. Run dig api.mako.devinagiffy.xyz +short to verify before running Certbot — Certbot will fail if DNS hasn’t propagated yet.

Slack App Setup (Dev + Production)

We recommend two separate Slack apps — one for development and one for production. See Slack Setup for details.

Services Overview


Updating

API / Bot (VPS)

Web App (Vercel)

Push to main — Vercel auto-deploys:

Viewing Logs


Stopping and Cleaning Up


Using an External Database

If you already have Postgres and/or Redis:
Then start only app services:

Production Checklist

  • Strong JWT_SECRET (32+ random bytes)
  • Unique API_KEY (matching between API and bot .env)
  • POSTGRES_PASSWORD changed from default
  • NEXT_PUBLIC_API_URL set to https://api.mako.devinagiffy.xyz/api
  • WEB_APP_URL set to https://mako.devinagiffy.xyz
  • CORS_ORIGINS set to https://mako.devinagiffy.xyz
  • At least one LLM key configured (ANTHROPIC_API_KEY or OPENAI_API_KEY)
  • Slack app credentials configured (production app)
  • Nginx reverse proxy installed and configured for api.mako.devinagiffy.xyz
  • SSL certificate via Certbot (sudo certbot --nginx)
  • DNS records for api.mako.devinagiffy.xyz and mako.devinagiffy.xyz
  • Automated backups for the postgres_data Docker volume
  • Cloudflare KV configured for per-org secret storage