Why Nginx for Odoo?
Odoo should never be exposed directly to the internet. Nginx sits in front as a reverse proxy providing: SSL termination (HTTPS), static file caching, security headers, request buffering, file upload size control, and database manager access blocking. It is the standard production setup for any Odoo deployment.
Complete Nginx Configuration
# /etc/nginx/sites-available/odoo
# Redirect HTTP to HTTPS
server {
listen 80;
server_name your-domain.com;
return 301 https://$server_name$request_uri;
}
# Main HTTPS server
server {
listen 443 ssl http2;
server_name your-domain.com;
# SSL Certificate (Let's Encrypt)
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
# Security Headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Proxy Settings
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;
# File Upload Size
client_max_body_size 200m;
# Block Database Manager
location /web/database {
deny all;
return 404;
}
# WebSocket (Odoo 16+)
location /websocket {
proxy_pass http://127.0.0.1:8072;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
# Legacy Longpolling (Odoo 15 and earlier)
location /longpolling {
proxy_pass http://127.0.0.1:8072;
proxy_read_timeout 86400;
}
# Static Files (with caching)
location ~* /web/static/ {
proxy_pass http://127.0.0.1:8069;
expires 7d;
add_header Cache-Control "public, immutable";
access_log off;
}
# Main Application
location / {
proxy_pass http://127.0.0.1:8069;
proxy_read_timeout 720s;
proxy_connect_timeout 720s;
proxy_send_timeout 720s;
}
# Gzip Compression
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
gzip_min_length 1000;
# Access Log
access_log /var/log/nginx/odoo-access.log;
error_log /var/log/nginx/odoo-error.log;
}Key Sections Explained
SSL Termination
Nginx handles HTTPS — Odoo runs plain HTTP internally. This is more efficient than configuring SSL in Odoo directly.
WebSocket Proxy
Odoo 16+ uses WebSocket for real-time features (chat, notifications). The Upgrade and Connection headers are required for WebSocket to work through nginx.
Static File Caching
Static assets (CSS, JS, images) are cached for 7 days. This reduces Odoo server load and improves page load time.
Database Manager Blocking
The /web/database path allows unauthenticated database creation and deletion. Always block it in production.
File Upload Size
client_max_body_size 200m allows uploading files up to 200MB. Adjust based on your needs (default nginx is 1MB).
Common Mistakes
- Missing proxy_mode = True in odoo.conf — causes wrong URLs and broken redirects
- Missing WebSocket proxy — Live Chat and notifications do not work
- Missing X-Forwarded-Proto — Odoo generates HTTP URLs instead of HTTPS
- Too low proxy_read_timeout — Large reports time out (default 60s is too low)
- Not blocking /web/database — Security risk in production
Testing Configuration
# Test nginx config syntax
nginx -t
# Reload nginx
systemctl reload nginx
# Verify headers
curl -I https://your-domain.comDeployMonkey
DeployMonkey configures nginx automatically for every Odoo instance — SSL, WebSocket, caching, security headers, and database manager blocking. No manual nginx configuration needed.