Skip to content

Reverse Proxy

For production deployments, you’ll want to put Frona AI behind a reverse proxy. This handles TLS termination, serves both the frontend and backend on a single domain, and provides additional security.

Here’s a basic Nginx configuration that proxies both the frontend and backend:

server {
listen 443 ssl http2;
server_name frona.example.com;
ssl_certificate /etc/ssl/certs/frona.pem;
ssl_certificate_key /etc/ssl/private/frona.key;
# Frontend
location / {
proxy_pass http://127.0.0.1:3000;
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;
}
# Backend API
location /api/ {
proxy_pass http://127.0.0.1:3001;
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;
# SSE streaming support
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 300s;
}
# Increase body size for file uploads
client_max_body_size 100M;
}

Agent responses stream via Server-Sent Events. Make sure your proxy:

  • Disables response buffering (proxy_buffering off)
  • Disables caching (proxy_cache off)
  • Has a long enough read timeout (proxy_read_timeout 300s)

Without these settings, responses will appear delayed or arrive all at once instead of streaming.

If you expose the Browserless debugger through the proxy, you’ll need WebSocket support:

location /ws/ {
proxy_pass http://127.0.0.1:3333;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

Set FRONA_SERVER_CORS_ORIGINS to match your domain:

FRONA_SERVER_CORS_ORIGINS=https://frona.example.com

Set FRONA_SERVER_BASE_URL to your public URL. This is used for generating callback URLs (e.g., for Twilio):

FRONA_SERVER_BASE_URL=https://frona.example.com

If you prefer Caddy, the configuration is simpler:

frona.example.com {
handle /api/* {
reverse_proxy localhost:3001 {
flush_interval -1
}
}
handle {
reverse_proxy localhost:3000
}
}

Caddy handles TLS automatically via Let’s Encrypt. The flush_interval -1 setting ensures SSE events stream immediately.