If you’re self-hosting Odoo behind Nginx with HTTPS and you’re struggling with broken stylesheets, missing JavaScript, or a website editor that refuses to load properly, this guide is for you. We recently went through this painful journey while deploying Odoo 18 Community Edition on a Hostinger VPS. The symptoms were frustrating, but the root cause was ultimately misconfiguration in the reverse proxy and asset routing.
In this post, I’ll walk you through the exact symptoms we faced, why they occur, and the comprehensive solution that fixed everything. If you’re seeing mixed content warnings, 404s on JS/CSS files, or an iframe that simply won’t load — you’re in the right place.
Symptoms We Encountered
- The Odoo Website Editor showed a blank white screen with a popup:
“No website domain configured for this website”
Clicking “New Page” triggered a popup error:
Odoo Client Error: Uncaught Promise Error > TypeError: Failed to fetch
- Browser DevTools Console showed errors like:
Mixed Content: The page at ‘https://yourdomain.com/odoo/website’ was loaded over HTTPS,
but requested an insecure frame ‘http://yourdomain.com/’.
This request has been blocked; the content must be served over HTTPS.
- Visiting URLs like:
https://yourdomain.com/web/assets/3/xyz123/web.assets_web.min.js
- returned a 404 Not Found.
- Website preview in the backend editor (iframe) failed to load.
Root Causes
The issue was a combination of:
- Incorrect Nginx reverse proxy configuration
- Odoo not receiving X-Forwarded headers
- Mixed content due to Odoo generating HTTP links while the main site is served over HTTPS
- Static assets not being routed properly through Nginx
- proxy_mode set but not fully effective without supporting headers
Solution (Step-by-Step)
Step 1: Enable proxy_mode in Odoo Config
Open your Odoo config file:
sudo nano /etc/odoo/odoo.conf
Make sure the following is present:
proxy_mode = True
This tells Odoo to trust the proxy headers passed from Nginx.
Step 2: Update Nginx Configuration
Open your Nginx site configuration:
sudo nano /etc/nginx/sites-available/odoo
Ensure the config includes these key directives:
server {
listen 80;
server_name yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
add_header Content-Security-Policy "upgrade-insecure-requests;";
location / {
proxy_pass http://127.0.0.1:8069;
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;
}
location /web/assets/ {
proxy_pass http://127.0.0.1:8069;
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;
expires 864000;
}
location /web/static/ {
proxy_pass http://127.0.0.1:8069;
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;
expires 864000;
}
}
Then test and reload Nginx:
sudo nginx -t && sudo systemctl reload nginx
Step 3: Restart Odoo
After making config changes, restart Odoo:
sudo systemctl restart odoo
Optional: Clear asset cache to force regeneration:
sudo rm -rf /var/lib/odoo/.local/share/Odoo/web/assets/*
Step 4: Set web.base.url (Optional)
Inside Odoo:
- Go to: Settings > Technical > Parameters > System Parameters
- Add:
- web.base.url: https://yourdomain.com
- web.base.url.freeze: True
- web.base.url: https://yourdomain.com
This prevents Odoo from defaulting back to http://localhost:8069 in asset links.
Why This Happens (Odoo 16+)
In Odoo 15 and earlier, the website editor opened in a new browser tab. But starting with Odoo 16, the editor is embedded in an iframe. This means any HTTP vs HTTPS mismatch between the parent and iframe causes content to be blocked for security reasons.
Also, Odoo dynamically serves web assets using hashed paths like:
/web/assets/3/somehash/web.assets_web.min.js
If Nginx isn’t set to route /web/assets/ and /web/static/ correctly to Odoo, you’ll see endless 404s.
Bonus: Mixed Content Warning Fix
Mixed content warnings are triggered when some resources load over HTTP in an HTTPS page. To force all URLs to upgrade:
add_header Content-Security-Policy “upgrade-insecure-requests;”;
This single line fixes a lot of iframe and asset issues in the Odoo backend.
Conclusion
Odoo’s flexibility is powerful, but its reverse proxy requirements can cause frustrating issues when misconfigured. Once we got the headers, proxy mode, and asset routing right, the site editor loaded instantly, assets were served over HTTPS, and all the 404s vanished.
If you’re running into this same wall, follow the steps above exactly. It took us hours of troubleshooting, reading through GitHub threads, and testing config changes to get this stable. Hopefully this guide saves you that pain.
If you’d like help deploying or debugging your Odoo instance, reach out to our team or leave a comment below.
Happy deploying!