Nginx configuration
Download the example configuration file
Nginx serves as the reverse proxy and SSL termination point for all application components. In a Standalone installation, nginx runs as a container from docker-compose; in an HA installation and in Kubernetes, the proxy role is handled by an external web server or an Ingress controller.
Domains and certificates
| Domain | Purpose | Certificate |
|---|---|---|
example.flip-chart.ru | Application (frontend, API, WebSocket, S3) | /etc/nginx/certificates/crt.pem, key.pem |
mcp.example.flip-chart.ru | MCP server | /etc/nginx/certificates/mcp-crt.pem, mcp-key.pem |
If you use one certificate for both domains (wildcard or SAN), specify the same files in both server blocks.
Routes
| Route | Purpose | Upstream | Notes |
|---|---|---|---|
/ | Redirect to /app | — | |
/app/api/v1/ws | WebSocket | flip-backend:9000 | proxy_read_timeout 86400s |
/app/api/v1/flip/backup/upload | Importing boards from backups | flip-backend:9000 | client_max_body_size 6G, 3600s timeouts |
/app/api | REST API | flip-backend:9000 | |
/app/s3/ | Proxying to S3 storage | flip-minio:9000 | the /app/s3/ prefix is stripped |
/app | Frontend | flip-frontend:80 | |
mcp.example.flip-chart.ru/ | MCP server | flip-mcp-server:8090 | separate server block |
Important
The upstream names (flip-backend, flip-frontend, flip-minio, flip-mcp-server) must match the docker-compose container names or the DNS names of the services in your environment. The backend port must match Server.Port in the backend configuration.
Example configuration
nginx
# flip reverse proxy (on-premise)
# example.flip-chart.ru, mcp.example.flip-chart.ru — replace with the domains of your installation.
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# Docker DNS: re-resolve upstream addresses when containers restart
resolver 127.0.0.11 valid=10s ipv6=off;
# HTTP -> HTTPS
server {
listen 80;
listen [::]:80;
server_name example.flip-chart.ru mcp.example.flip-chart.ru;
location / {
return 301 https://$host$request_uri;
}
}
# Main application
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name example.flip-chart.ru;
ssl_certificate /etc/nginx/certificates/crt.pem;
ssl_certificate_key /etc/nginx/certificates/key.pem;
client_max_body_size 500M;
set $backend http://flip-backend:9000;
set $frontend http://flip-frontend:80;
set $minio http://flip-minio:9000;
location = / {
return 302 https://$host/app;
}
# WebSocket
location = /app/api/v1/ws {
proxy_pass $backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $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_set_header X-Forwarded-Host $host;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_connect_timeout 60s;
}
# Import of board backups (.board)
location = /app/api/v1/flip/backup/upload {
proxy_pass $backend;
proxy_http_version 1.1;
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_set_header X-Forwarded-Host $host;
client_max_body_size 6G;
proxy_request_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_connect_timeout 3600s;
}
# REST API
location /app/api {
proxy_pass $backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
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_set_header X-Forwarded-Host $host;
proxy_read_timeout 120s;
proxy_send_timeout 60s;
proxy_connect_timeout 60s;
}
# S3 storage via the application domain
location /app/s3/ {
rewrite ^/app/s3/(.*)$ /$1 break;
proxy_pass $minio;
proxy_http_version 1.1;
proxy_redirect off;
proxy_set_header Connection "";
proxy_set_header Authorization "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_hide_header Set-Cookie;
proxy_ignore_headers Set-Cookie;
proxy_buffering off;
proxy_max_temp_file_size 0;
add_header Cache-Control max-age=31536000;
}
# Frontend
location /app {
proxy_pass $frontend;
proxy_http_version 1.1;
proxy_set_header Connection "";
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 240s;
proxy_send_timeout 60s;
proxy_connect_timeout 60s;
}
}
# MCP server — a separate domain
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name mcp.example.flip-chart.ru;
ssl_certificate /etc/nginx/certificates/mcp-crt.pem;
ssl_certificate_key /etc/nginx/certificates/mcp-key.pem;
set $mcp http://flip-mcp-server:8090;
location / {
proxy_pass $mcp;
proxy_http_version 1.1;
proxy_set_header Connection "";
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_set_header X-Forwarded-Host $host;
proxy_buffering off;
proxy_read_timeout 120s;
proxy_send_timeout 60s;
proxy_connect_timeout 60s;
}
}