Deploy SkillFlaw behind Nginx and HTTPS
Deploy SkillFlaw on a Linux server by keeping the service split intact and placing Nginx in front of it.
This guide assumes the same runtime contract already used by docker/docker-compose.yml:
- backend API on
7860 - frontend UI on
3001 - optional standalone docs on
3002
Nginx then becomes the public edge for HTTPS, hostname routing, and request limits.
When this guide fits
Use this pattern when you want one of these deployment shapes:
- Full web deployment: frontend + backend, with docs on a separate hostname when required
- API-first deployment: backend only, optionally with docs exposed separately
If you are still bringing up the stack itself, start with Install SkillFlaw for deployment and SkillFlaw deployment architecture.
Prerequisites
- A running SkillFlaw deployment on the target machine
- A Debian- or Ubuntu-like Linux host with Nginx support
- A public domain name and permission to update DNS records
- DNS records that already point to the server's public IP
- Certbot available from your operating system packages
For the reference compose stack, the local upstreams are:
| Service | Local address | Purpose |
|---|---|---|
| Frontend | http://127.0.0.1:3001 | Web UI and shareable playground routes such as /playground/:id/ |
| Backend | http://127.0.0.1:7860 | /health, /api/*, /api/v1/mcp/streamable, webhook and run endpoints |
| Docs | http://127.0.0.1:3002 | Optional standalone documentation host |
Choose your public routing model
The cleanest production setup is to use separate hostnames:
app.example.com-> frontendapi.example.com-> backenddocs.example.com-> docs (optional)
This keeps browser UI traffic, programmatic API traffic, and docs traffic clearly separated.
Install Nginx and enable it
-
Install Nginx.
_10sudo apt update_10sudo apt install nginx -y -
Start and enable the service.
_10sudo systemctl enable --now nginx
Configure Nginx for SkillFlaw
The following example uses three virtual hosts. Remove the ones you do not need.
-
Create a site configuration file.
_10sudo nano /etc/nginx/sites-available/skillflaw.conf -
Paste a configuration like the following and replace the example domains with your real hostnames.
_53server {_53listen 80;_53server_name app.example.com;_53_53client_max_body_size 100M;_53_53location / {_53proxy_pass http://127.0.0.1:3001;_53proxy_http_version 1.1;_53proxy_set_header Host $host;_53proxy_set_header X-Real-IP $remote_addr;_53proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;_53proxy_set_header X-Forwarded-Proto $scheme;_53proxy_set_header Upgrade $http_upgrade;_53proxy_set_header Connection "upgrade";_53}_53}_53_53server {_53listen 80;_53server_name api.example.com;_53_53client_max_body_size 100M;_53_53location / {_53proxy_pass http://127.0.0.1:7860;_53proxy_http_version 1.1;_53proxy_set_header Host $host;_53proxy_set_header X-Real-IP $remote_addr;_53proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;_53proxy_set_header X-Forwarded-Proto $scheme;_53proxy_set_header Upgrade $http_upgrade;_53proxy_set_header Connection "upgrade";_53proxy_connect_timeout 60s;_53proxy_send_timeout 60s;_53proxy_read_timeout 300s;_53proxy_buffering off;_53proxy_request_buffering off;_53}_53}_53_53server {_53listen 80;_53server_name docs.example.com;_53_53location / {_53proxy_pass http://127.0.0.1:3002;_53proxy_set_header Host $host;_53proxy_set_header X-Real-IP $remote_addr;_53proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;_53proxy_set_header X-Forwarded-Proto $scheme;_53}_53} -
Enable the site and validate the syntax.
_10sudo ln -sf /etc/nginx/sites-available/skillflaw.conf /etc/nginx/sites-enabled/skillflaw.conf_10sudo nginx -t -
Reload Nginx.
_10sudo systemctl reload nginx
Obtain TLS certificates with Certbot
-
Install Certbot and the Nginx plugin.
_10sudo apt install certbot python3-certbot-nginx -y -
Request certificates for the hostnames you actually expose.
_10sudo certbot --nginx -d app.example.com -d api.example.com -d docs.example.comIf you expose fewer hostnames, remove the extra
-darguments. -
Let Certbot update the Nginx configuration and choose whether HTTP should redirect to HTTPS.
-
Verify that automatic renewal is present.
_10systemctl list-timers | grep certbot
Verify the public entrypoints
After TLS is enabled, verify the endpoints that match your deployment shape:
https://app.example.comhttps://api.example.com/healthhttps://api.example.com/api/v1/mcp/streamablehttps://docs.example.com
Operational notes
- Keep
SKILLFLAW_SECRET_KEY_FILEmounted as a real file in the backend runtime; Nginx does not change that requirement. - Keep
SKILLFLAW_CONFIG_DIRon persistent storage. - If you expose only API traffic, publish the backend hostname and leave the frontend/docs private or disabled.
- If you expose MCP publicly, secure it with the same authentication controls used for the rest of the backend API.