Generate a Self‑Signed SSL Certificate on Ubuntu (Nginx)
Step-by-step guide to creating a self-signed certificate with OpenSSL and configuring Nginx with secure defaults.
Generate a Self‑Signed SSL Certificate on Ubuntu (Nginx)
This guide shows you how to generate a self‑signed TLS certificate with OpenSSL and configure Nginx to serve HTTPS using secure defaults. Self‑signed certificates are great for internal environments, staging, and quick local testing. For public sites, use Let's Encrypt.
1) Generate Self‑Signed Certificate and Key
sudo openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout /etc/ssl/private/nginx-selfsigned.key \
-out /etc/ssl/certs/nginx-selfsigned.crt
Explanation of flags:
openssl req -x509: Create an X.509 certificate (self‑signed when using-x509).-nodes: Do not encrypt the private key (no passphrase, required for unattended Nginx reloads).-days 365: Certificate validity period.-newkey rsa:2048: Generate a new 2048‑bit RSA key.-keyout: Output path for the private key.-out: Output path for the certificate.
During prompts, set the Common Name (CN) to your domain or server IP (e.g., example.com or 203.0.113.10).
(Optional) Generate Strong DH Parameters
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
2) Configure Nginx
Edit your server block (e.g., /etc/nginx/sites-available/default):
server {
listen 80;
listen 443 ssl;
server_name your_domain_or_ip;
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
# Recommended SSL settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
# Uncomment if you created dhparam.pem
# ssl_dhparam /etc/ssl/certs/dhparam.pem;
# HSTS (enable only if sure, includes subdomains)
# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Example content (static)
location / {
root /var/www/html;
index index.html;
}
# Or reverse proxy example
# location /api/ {
# proxy_pass http://127.0.0.1:3000/;
# 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;
# }
}
Replace your_domain_or_ip with your domain (preferred) or IP.
3) Test and Reload Nginx
sudo nginx -t
sudo systemctl reload nginx
4) Trusting the Certificate (Local/Dev)
Browsers will show a warning for self‑signed certs. For internal use, you can trust the cert locally:
- Export
/etc/ssl/certs/nginx-selfsigned.crtand import into your OS/browser trust store. - For Chrome/Edge on Windows: import via "Manage computer certificates" → Trusted Root Certification Authorities.
- For macOS: Keychain Access → System → Certificates → import and set to Always Trust.
Troubleshooting
- Port 443 blocked:
sudo ufw allow 443(and 80 if redirecting HTTP). - Permissions: key file should be readable by root only (
chmod 600 /etc/ssl/private/nginx-selfsigned.key). - Wrong CN: regenerate with correct Common Name or use SubjectAltName (SAN) with an OpenSSL config.
Production Note
Use Let's Encrypt (Certbot) for public websites to get a free and trusted certificate:
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
This config gets you running securely for testing and internal services. For internet‑facing sites, switch to a trusted CA as soon as possible.
Post Details
Navigation
Related posts
Deploy Next.js on Ubuntu with Git, PM2, Nginx, and Certbot
Production-ready guide to deploy a Next.js app on Ubuntu using Git for code, PM2 for process management, Nginx as reverse proxy, and Certbot for HTTPS.
Read more →Essential Security Practices to Protect Your Web Applications
Practical, easy-to-apply security improvements for any online project — from security headers, rate limiting, login protection, to safe file uploads and more.
Read more →Automated MongoDB Backup to S3 with Shell Script on Ubuntu
Learn how to create an automated MongoDB backup system using shell scripts that dump databases, compress them, and upload to AWS S3 with automatic cleanup.
Read more →