Docs/Self-hosting/Reverse Proxy and SSL Setup for Self-Hosted Deployments

Reverse Proxy and SSL Setup for Self-Hosted Deployments

Configure nginx or Caddy as a reverse proxy in front of Pentographer with automatic SSL via Let's Encrypt for production self-hosted deployments.

A self-hosted Pentographer instance binds to port 3000 by default. In production, you need a reverse proxy to terminate TLS, expose the application on port 443, and forward requests to the application container. This guide covers two options: nginx with Certbot, and Caddy.

Setting NEXTAUTH_URL

Before configuring the proxy, update your NEXTAUTH_URL environment variable to the exact public URL of your deployment. NextAuth uses this value to construct OAuth callback URLs and validate redirect targets.

NEXTAUTH_URL=https://app.yourdomain.com

[!IMPORTANT] NEXTAUTH_URL must use HTTPS in production and must match the domain exactly, including the subdomain. A mismatch causes authentication callbacks to fail.

Update this in your docker-compose.yml environment section or in your .env.local file, then restart the stack.

Option 1: nginx with Certbot

Install nginx and Certbot on the host:

sudo apt install nginx certbot python3-certbot-nginx

Create a server block at /etc/nginx/sites-available/pentographer:

server {
    listen 80;
    server_name app.yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        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_cache_bypass $http_upgrade;
    }
}

Enable the config and obtain a certificate:

sudo ln -s /etc/nginx/sites-available/pentographer /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d app.yourdomain.com

Certbot modifies the nginx config to add SSL directives and configures automatic certificate renewal via a systemd timer.

[!NOTE] The Upgrade and Connection headers are required for Server-Sent Events (SSE), which Pentographer uses for streaming AI responses and MCP transport.

Option 2: Caddy

Caddy handles certificate provisioning automatically. Install Caddy on the host and create a Caddyfile:

app.yourdomain.com {
    reverse_proxy localhost:3000
}

Start Caddy:

sudo caddy start --config /path/to/Caddyfile

Caddy requests and renews Let's Encrypt certificates automatically on first request. No manual certificate management is required.

Docker Compose Adjustment

When running the application container, bind it to 127.0.0.1 so the port is not publicly accessible on the host — the proxy is the only ingress point:

services:
  app:
    ports:
      - "127.0.0.1:3000:3000"

This prevents direct access to port 3000 from outside the server while keeping the proxy-to-container path on localhost.

Verifying the Setup

After configuration, confirm that:

  1. https://app.yourdomain.com loads the Pentographer login page.
  2. The certificate is valid (no browser warning).
  3. AI streaming responses work — the SSE connection should produce token-by-token output in the finding editor. If it hangs or cuts off, check that the Upgrade and Connection proxy headers are set correctly.

Was this article helpful?

Help us improve the Pentographer documentation.

Subscribe to security audits for builders

Get technical write-ups on building deterministic AI pipelines, self-hosting secure apps, and automating pentesting workflows. No marketing spam.