Skip to main content
Security Guide

Odoo SSL Certificate & Custom Domain Setup

Secure your Odoo installation with SSL/TLS encryption. This guide covers Let's Encrypt setup, Nginx configuration, custom domain setup, and troubleshooting common HTTPS issues.

15-20 min read
Updated December 2024
TLS 1.2/1.3 Compatible

Why SSL Matters for Odoo

SSL (Secure Sockets Layer) and its successor TLS (Transport Layer Security) encrypt the connection between your users and your Odoo server. This encryption is essential for protecting sensitive business data transmitted through your ERP system. Whether you're deploying Odoo from scratch or securing an existing installation, SSL configuration is a critical security step.

Data Security

Encrypts login credentials, customer data, financial records, and all business communications between browser and server.

SEO Benefits

Google uses HTTPS as a ranking signal. SSL-secured sites rank higher in search results, improving visibility for your Odoo e-commerce or website.

User Trust

The padlock icon and "https://" in the address bar signal security to users. Without SSL, browsers display "Not Secure" warnings.

Compliance Requirement

Many regulations including GDPR, PCI DSS, and HIPAA require encryption of data in transit. Running Odoo without SSL may put your organization at legal risk when handling customer data or payment information.

SSL Certificate Options

There are several ways to obtain SSL certificates for your Odoo deployment. Choose based on your security requirements, budget, and technical expertise.

Recommended

Let's Encrypt (Free)

Free, automated, and trusted SSL certificates. Let's Encrypt is the most popular choice for Odoo deployments, providing industry-standard encryption at no cost.

Pros

  • Completely free
  • Automated renewal with Certbot
  • Trusted by all browsers
  • Supports wildcard certificates

Cons

  • 90-day validity (auto-renew recommended)
  • No warranty coverage
  • Domain validation only (no EV)

Commercial Certificates

Paid certificates from Certificate Authorities like DigiCert, Sectigo, or GlobalSign. Consider these for Extended Validation (EV) requirements or warranty needs.

Domain Validated (DV)

Basic encryption, fastest issuance

$10-50/year

Organization Validated (OV)

Verifies organization identity

$50-200/year

Extended Validation (EV)

Green bar with company name

$200-500/year

Wildcard Certificates

A single certificate covering all subdomains (*.yourdomain.com). Ideal when running multiple Odoo instances on different subdomains.

# One wildcard certificate covers:
*.company.com

# Including:
erp.company.com       # Production Odoo
staging.company.com   # Staging environment
dev.company.com       # Development
portal.company.com    # Customer portal

Let's Encrypt Wildcard Support

Let's Encrypt supports wildcard certificates but requires DNS-01 validation (adding a TXT record to your DNS). This is more complex than HTTP validation but enables automatic renewal with DNS API integration.

Let's Encrypt Setup with Certbot

Certbot is the recommended tool for obtaining and managing Let's Encrypt certificates. Follow these steps to secure your Odoo installation.

Step 1: Install Certbot

Install Certbot on Ubuntu/Debianbash
# Update package list
sudo apt update

# Install Certbot and Nginx plugin
sudo apt install certbot python3-certbot-nginx -y

# Verify installation
certbot --version
Install Certbot on CentOS/RHELbash
# Enable EPEL repository
sudo dnf install epel-release -y

# Install Certbot
sudo dnf install certbot python3-certbot-nginx -y

# Verify installation
certbot --version

Step 2: Obtain Certificate (Standalone Method)

The standalone method runs its own temporary web server for validation. Use this if Nginx is not yet configured.

# Stop any service using port 80
sudo systemctl stop nginx

# Obtain certificate using standalone mode
sudo certbot certonly --standalone \
  -d erp.yourdomain.com \
  --email [email protected] \
  --agree-tos \
  --non-interactive

# Certificate files are saved to:
# /etc/letsencrypt/live/erp.yourdomain.com/fullchain.pem
# /etc/letsencrypt/live/erp.yourdomain.com/privkey.pem

Step 3: Obtain Certificate (Webroot Method)

The webroot method uses an existing web server. This is the preferred method when Nginx is already running.

# Create webroot directory for ACME challenge
sudo mkdir -p /var/www/certbot

# Ensure Nginx serves the challenge directory
# (Add this to your nginx config first - see next section)

# Obtain certificate using webroot mode
sudo certbot certonly --webroot \
  -w /var/www/certbot \
  -d erp.yourdomain.com \
  --email [email protected] \
  --agree-tos \
  --non-interactive

Step 4: Obtain Wildcard Certificate (DNS Method)

# Wildcard certificates require DNS-01 validation
sudo certbot certonly --manual \
  --preferred-challenges dns \
  -d "*.yourdomain.com" \
  -d yourdomain.com \
  --email [email protected] \
  --agree-tos

# Certbot will prompt you to create a TXT record:
# _acme-challenge.yourdomain.com  ->  <random-string>

# Wait for DNS propagation, then press Enter to continue

Step 5: Configure Auto-Renewal

Set up automatic renewalbash
# Test renewal process
sudo certbot renew --dry-run

# Add cron job for automatic renewal
sudo crontab -e

# Add this line (runs twice daily):
0 0,12 * * * certbot renew --quiet --post-hook "systemctl reload nginx"

# Or use systemd timer (already installed on most systems)
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer

# Verify timer is active
sudo systemctl status certbot.timer

Certificate Renewal

Let's Encrypt certificates expire after 90 days. Certbot will only renew certificates within 30 days of expiration, so running the renew command frequently is safe. Always test renewal with --dry-run first.

Nginx Configuration for Odoo SSL

A properly configured Nginx reverse proxy handles SSL termination, redirects HTTP to HTTPS, and forwards requests to Odoo with the correct headers.

Complete Nginx Configuration

/etc/nginx/sites-available/odoonginx
# Odoo upstream servers
upstream odoo {
    server 127.0.0.1:8069;
}

upstream odoo-longpolling {
    server 127.0.0.1:8072;
}

# HTTP - Redirect all traffic to HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name erp.yourdomain.com;

    # Let's Encrypt ACME challenge
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    # Redirect all other requests to HTTPS
    location / {
        return 301 https://$server_name$request_uri;
    }
}

# HTTPS - Main server block
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name erp.yourdomain.com;

    # SSL Certificate
    ssl_certificate /etc/letsencrypt/live/erp.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/erp.yourdomain.com/privkey.pem;

    # SSL Session settings
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    # Modern SSL configuration (TLS 1.2 and 1.3 only)
    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:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/erp.yourdomain.com/chain.pem;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    # Security Headers
    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 Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # Logging
    access_log /var/log/nginx/odoo.access.log;
    error_log /var/log/nginx/odoo.error.log;

    # Proxy settings
    proxy_read_timeout 720s;
    proxy_connect_timeout 720s;
    proxy_send_timeout 720s;

    # Proxy headers for Odoo
    proxy_set_header Host $http_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;

    # Gzip compression
    gzip on;
    gzip_types text/css text/plain text/xml application/xml application/javascript application/json image/svg+xml;
    gzip_min_length 1000;

    # File upload size (adjust as needed)
    client_max_body_size 100M;

    # Longpolling (real-time features like chat, notifications)
    location /longpolling {
        proxy_pass http://odoo-longpolling;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    # WebSocket support (Odoo 16+)
    location /websocket {
        proxy_pass http://odoo-longpolling;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    # Static file caching
    location ~* /web/static/ {
        proxy_pass http://odoo;
        proxy_cache_valid 200 60m;
        expires 24h;
        add_header Cache-Control "public, immutable";
    }

    # Main Odoo application
    location / {
        proxy_pass http://odoo;
        proxy_redirect off;
    }
}

Enable and Test Configuration

# Create symbolic link to enable site
sudo ln -s /etc/nginx/sites-available/odoo /etc/nginx/sites-enabled/

# Test Nginx configuration
sudo nginx -t

# If test passes, reload Nginx
sudo systemctl reload nginx

# Check Nginx status
sudo systemctl status nginx

Update Odoo Configuration

Enable proxy mode in Odoo to properly handle forwarded headers and HTTPS detection.

/etc/odoo/odoo.confini
[options]
# Enable proxy mode (required when behind reverse proxy)
proxy_mode = True

# Other settings...
db_host = localhost
db_port = 5432
db_user = odoo
db_password = your_password
addons_path = /opt/odoo/addons
# Restart Odoo to apply changes
sudo systemctl restart odoo

# Update web.base.url in Odoo
# Go to Settings > System Parameters
# Set web.base.url to: https://erp.yourdomain.com

Proxy Mode Required

Without proxy_mode = True, Odoo will not correctly detect HTTPS connections when behind a reverse proxy. This can cause redirect loops and mixed content warnings.

Custom Domain Setup

Before obtaining SSL certificates, you need to configure DNS records to point your domain to your Odoo server.

DNS Record Configuration

TypeNameValueTTL
Aerp203.0.113.503600
AAAAerp2001:db8::13600
CNAMEwww.erperp.yourdomain.com3600
Verify DNS propagationbash
# Check A record
dig erp.yourdomain.com A +short

# Check AAAA record (IPv6)
dig erp.yourdomain.com AAAA +short

# Alternative: use nslookup
nslookup erp.yourdomain.com

# Check from multiple locations
# Visit: https://dnschecker.org

Multiple Domains/Subdomains

If you need to serve Odoo from multiple domains or want both www and non-www versions, update your Nginx configuration:

Multiple domains configurationnginx
server {
    listen 443 ssl http2;
    server_name erp.yourdomain.com
                erp.company.com
                odoo.company.com;

    # SSL certificates must cover all domains
    # Use a wildcard cert or separate certs with SNI
    ssl_certificate /etc/letsencrypt/live/erp.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/erp.yourdomain.com/privkey.pem;

    # ... rest of configuration
}

# Redirect www to non-www
server {
    listen 443 ssl http2;
    server_name www.erp.yourdomain.com;

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

    return 301 https://erp.yourdomain.com$request_uri;
}

Domain Verification

# Test SSL certificate
openssl s_client -connect erp.yourdomain.com:443 -servername erp.yourdomain.com

# Check certificate details
echo | openssl s_client -connect erp.yourdomain.com:443 2>/dev/null | openssl x509 -noout -dates

# Use SSL Labs for comprehensive testing
# Visit: https://www.ssllabs.com/ssltest/analyze.html?d=erp.yourdomain.com

DNS Propagation Time

DNS changes can take up to 48 hours to propagate globally, though most updates complete within 1-4 hours. Wait for propagation before attempting SSL certificate validation.

Troubleshooting Common Issues

SSL and domain configuration can encounter various issues. Here are solutions to the most common problems.

Mixed Content Warnings

Browser shows warnings about loading insecure (HTTP) resources on a secure (HTTPS) page.

Solutions:

  • 1. Update web.base.url in Odoo System Parameters to use https://
  • 2. Check custom modules for hardcoded http:// URLs
  • 3. Review email templates for http:// links
  • 4. Clear browser cache and Odoo assets cache
-- Fix web.base.url in database
UPDATE ir_config_parameter
SET value = 'https://erp.yourdomain.com'
WHERE key = 'web.base.url';

Certificate Not Trusted

Browser shows "Your connection is not private" or certificate errors.

Common causes:

  • - Certificate expired or not yet valid
  • - Using certificate for wrong domain
  • - Missing intermediate certificates (use fullchain.pem)
  • - Self-signed certificate (not trusted by browsers)
# Check certificate expiration
sudo certbot certificates

# Renew if needed
sudo certbot renew --force-renewal

# Verify certificate chain
openssl verify -CAfile /etc/letsencrypt/live/erp.yourdomain.com/chain.pem \
  /etc/letsencrypt/live/erp.yourdomain.com/cert.pem

Certificate Renewal Failures

Certbot renewal fails with connection or validation errors.

Troubleshooting steps:

# Check renewal logs
sudo cat /var/log/letsencrypt/letsencrypt.log

# Ensure ACME challenge path is accessible
curl -I http://erp.yourdomain.com/.well-known/acme-challenge/test

# Verify Nginx config serves challenge directory
nginx -T | grep -A 5 "acme-challenge"

# Test renewal with verbose output
sudo certbot renew --dry-run --verbose

# If using firewall, ensure port 80 is open
sudo ufw allow 80/tcp

Proxy Protocol Issues

Odoo shows wrong URLs, redirect loops, or fails to detect HTTPS.

Checklist:

  • 1. Ensure proxy_mode = True in odoo.conf
  • 2. Verify Nginx sends X-Forwarded-Proto header
  • 3. Check X-Forwarded-Host matches your domain
  • 4. Restart Odoo after config changes
# Test headers reaching Odoo
curl -I -H "Host: erp.yourdomain.com" https://erp.yourdomain.com

# Check Odoo logs for header values
sudo tail -f /var/log/odoo/odoo.log | grep -i "x-forwarded"

Skip the Complexity with Automatic SSL

Setting up SSL manually requires server configuration, certificate management, and ongoing maintenance. With OEC.sh's managed Odoo hosting, SSL is automatic and zero-configuration for all deployments. Focus on building your business, not managing certificates.

Zero-Config SSL

HTTPS enabled automatically for every deployment

Automatic Renewal

Certificates renewed automatically before expiration

Custom Domains in Seconds

Add your domain and SSL is provisioned instantly

A+ SSL Rating

Industry-best security configuration out of the box

Wildcard Support

Cover multiple subdomains with one certificate

No Nginx Configuration

SSL termination and proxy handled automatically

Manual SSL Setup

  • Install and configure Certbot
  • Write Nginx configuration
  • Set up renewal cron jobs
  • Debug certificate issues
  • Monitor expiration dates

Time: 1-3 hours + ongoing maintenance

OEC.sh SSL

  • Deploy your Odoo project
  • Add custom domain (optional)
  • SSL automatically provisioned
  • Renewals handled automatically
  • Zero maintenance required

Time: 5 minutes, no maintenance

Frequently Asked Questions

How do I add a custom domain to Odoo?

To add a custom domain to Odoo, first create an A record in your DNS pointing to your server's IP address. Wait for DNS propagation (1-4 hours), then update your Nginx configuration to include your domain name in the server_name directive. Finally, obtain an SSL certificate using Certbot with: sudo certbot --nginx -d yourdomain.com. Update Odoo's web.base.url system parameter to match your domain. For detailed steps, see the custom domain section of this guide.

Is SSL free with Odoo hosting?

Yes, SSL certificates can be completely free for Odoo using Let's Encrypt. Let's Encrypt provides trusted SSL certificates that work with all major browsers, auto-renew every 90 days, and support both single domains and wildcards. With OEC.sh, SSL is automatically provisioned and renewed for every deployment at no additional cost. If you self-host, you can use Certbot to obtain and manage free Let's Encrypt certificates.

How do I configure DNS for Odoo?

DNS configuration for Odoo requires creating an A record pointing your domain (e.g., erp.yourdomain.com) to your server's IP address. For IPv6, also add an AAAA record. If you want www subdomain support, add a CNAME record pointing www to your main domain. Use TTL of 3600 (1 hour) for flexibility. Verify DNS propagation using 'dig yourdomain.com A +short' or online tools like dnschecker.org before attempting SSL certificate issuance.

Can I use my own SSL certificate?

Yes, you can use your own commercial SSL certificate with Odoo instead of Let's Encrypt. After purchasing a certificate from providers like DigiCert, Sectigo, or GlobalSign, upload the certificate files to your server and update the Nginx configuration to point to your certificate and private key files. Use ssl_certificate for the full chain (cert + intermediate certs) and ssl_certificate_key for the private key. Commercial certificates offer benefits like extended validation (EV), organization name display, and warranty coverage.

How long does SSL take to provision?

SSL provisioning with Let's Encrypt takes 1-3 minutes once DNS is propagated. The main bottleneck is DNS propagation, which typically completes within 1-4 hours but can take up to 48 hours globally. Once DNS points to your server, Certbot can obtain and install the certificate in under a minute. With OEC.sh, SSL is provisioned automatically within 2-3 minutes of deploying your Odoo instance, as DNS is pre-configured.

What DNS records do I need for Odoo?

For basic Odoo hosting, you need: (1) An A record pointing your subdomain (e.g., erp) to your server's IPv4 address, (2) Optionally, an AAAA record for IPv6 support, (3) If using www, a CNAME record pointing www.erp to erp.yourdomain.com. For email integration, add MX records pointing to your mail server. For wildcard SSL certificates, you'll need to add a TXT record with _acme-challenge prefix during certificate validation. Set TTL to 3600 for standard configurations.

Is SSL/HTTPS required for Odoo?

While Odoo can technically run without SSL, HTTPS is strongly recommended for any production deployment. Without SSL, login credentials and sensitive business data are transmitted in plain text, vulnerable to interception. Additionally, modern browsers flag non-HTTPS sites as 'Not Secure', which erodes user trust and can impact SEO rankings. Many compliance regulations like GDPR, PCI DSS, and HIPAA require encryption of data in transit.

Why do I see mixed content warnings after enabling SSL?

Mixed content warnings occur when your HTTPS page loads resources (images, scripts, stylesheets) over HTTP. In Odoo, this often happens when system parameters still reference HTTP URLs. Update the web.base.url parameter in Settings > System Parameters to use https://. Also check for hardcoded HTTP URLs in custom modules or email templates. Clear browser cache and Odoo assets cache after making changes.

Secure Your Odoo with Zero Effort

Skip the SSL configuration complexity. OEC.sh provides automatic SSL certificates, custom domain support, and enterprise-grade security for all deployments.