Skip to content

How to Set Up SSL for Odoo with Let's Encrypt

DeployMonkey Team · March 11, 2026 8 min read

Running Odoo without SSL is a security risk you cannot afford — login credentials, customer data, and invoice details all transit in plaintext over HTTP. Let's Encrypt provides free, trusted SSL certificates that auto-renew every 90 days. Here's how to set it up in under 20 minutes.

Prerequisites

  • A Linux server with Nginx installed (see Odoo Nginx reverse proxy setup)
  • A domain name pointing to your server's IP (DNS must be propagated before running Certbot)
  • Ports 80 and 443 open in your firewall
  • Odoo running on localhost (typically port 8069)

Step 1: Install Certbot

# Ubuntu/Debian
sudo apt update
sudo apt install -y certbot python3-certbot-nginx

# RHEL/AlmaLinux/Rocky
sudo dnf install -y certbot python3-certbot-nginx

Step 2: Basic HTTP Nginx Config (Pre-SSL)

Before running Certbot, you need a working Nginx server block for your domain. Create /etc/nginx/sites-available/odoo:

server {
listen 80;
server_name yourdomain.com www.yourdomain.com;

# Required for Certbot ACME challenge
location /.well-known/acme-challenge/ {
    root /var/www/html;
}

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;
}
}
sudo ln -s /etc/nginx/sites-available/odoo /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Step 3: Obtain the SSL Certificate

sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

Certbot will:

  1. Verify you control the domain via an HTTP challenge
  2. Issue a certificate from Let's Encrypt
  3. Automatically modify your Nginx config to enable HTTPS
  4. Redirect HTTP to HTTPS

Step 4: Full Nginx HTTPS Config for Odoo

After Certbot runs, your Nginx config will be updated. Review and enhance it to include Odoo-specific settings and strong SSL parameters:

server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;

ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/yourdomain.com/chain.pem;

# Modern SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_stapling on;
ssl_stapling_verify on;

# Security headers
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;

# Odoo proxy settings
proxy_read_timeout 720s;
proxy_connect_timeout 720s;
proxy_send_timeout 720s;
client_max_body_size 100m;

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 /longpolling {
    proxy_pass http://127.0.0.1:8072;
    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;
}
}

server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$host$request_uri;
}

Step 5: Enable proxy_mode in Odoo

Odoo must be told it's running behind a reverse proxy. In /etc/odoo/odoo.conf:

proxy_mode = True

Without this, Odoo generates HTTP links instead of HTTPS in emails, payment redirects, and portal URLs. Restart Odoo after this change.

Step 6: Configure Auto-Renewal

Certbot automatically installs a systemd timer or cron job on installation. Verify it:

# Check the timer
systemctl status certbot.timer

# Test renewal (dry run)
sudo certbot renew --dry-run

If the dry run succeeds, your certificates will renew automatically every 60 days (well before the 90-day expiry). Add a post-renewal hook to reload Nginx after each renewal:

sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
#!/bin/bash
systemctl reload nginx
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Step 7: Validate with SSL Labs

After completing the setup, test your SSL configuration at SSL Labs SSL Test. Enter your domain and aim for an A or A+ rating. The configuration above should achieve A+.

Common issues flagged by SSL Labs:

  • TLS 1.0/1.1 enabled: Disable in ssl_protocols
  • HSTS not set: Add the Strict-Transport-Security header
  • OCSP stapling misconfigured: Verify ssl_stapling on and that ssl_trusted_certificate points to the chain file

How DeployMonkey Handles SSL

DeployMonkey automatically provisions and renews Let's Encrypt certificates for every managed Odoo instance. SSL is enabled the moment you add a custom domain — no Certbot commands, no Nginx config editing, no renewal cron jobs. Certificates renew silently in the background, and you're alerted if a renewal fails. Get started free.

Frequently Asked Questions

How often do Let's Encrypt certificates expire?

Let's Encrypt certificates expire every 90 days. Certbot auto-renews them at the 60-day mark. You should never need to manually renew unless auto-renewal is broken.

What happens if Certbot auto-renewal fails?

Let's Encrypt sends a reminder email 20 days before expiry. If renewal still fails, your certificate expires and browsers show a security warning to visitors. Monitor with certbot renew --dry-run in a cron job that sends alerts on failure.

Can I use Let's Encrypt with a wildcard certificate?

Yes, but wildcard certificates (*.yourdomain.com) require DNS-01 challenge validation rather than HTTP-01. This requires API access to your DNS provider. Certbot supports this via DNS plugins (e.g., certbot-dns-cloudflare).

Why does Odoo still show HTTP links in emails after enabling SSL?

Two likely causes: (1) proxy_mode = True is not set in odoo.conf, or (2) web.base.url in Settings > Technical > System Parameters still starts with http://. Update both. See also our guide on fixing Odoo HTTPS errors.

Does this work for Odoo running in Docker?

Yes. Run Certbot on the host machine (not inside the container), mount the certificate directory into the Nginx container, and expose port 443 from the Nginx container. Alternatively, use a Nginx container with automatic Let's Encrypt support such as nginx-proxy with acme-companion.