
How to Create a Self-Signed SSL Certificate for Nginx on Ubuntu 24
Creating a self-signed SSL certificate for Nginx on Ubuntu 24 is essential for securing HTTP communications in development environments or internal services where obtaining a commercial certificate isn’t feasible. While self-signed certificates generate browser warnings since they’re not validated by a trusted Certificate Authority, they provide the same level of encryption as commercial certificates. This guide walks you through generating your own SSL certificate, configuring Nginx to use it, and addresses common deployment challenges you’ll encounter along the way.
How Self-Signed SSL Certificates Work
Self-signed certificates function identically to CA-signed certificates in terms of encryption strength, but they lack third-party validation. When you create a self-signed certificate, you’re essentially acting as your own Certificate Authority. The certificate contains a public key that browsers use to establish encrypted connections, while the corresponding private key remains on your server.
The main technical difference lies in the trust chain. Commercial certificates are signed by intermediate CAs, which are trusted by root CAs already installed in browsers and operating systems. Self-signed certificates break this chain, requiring manual trust configuration on client devices.
Prerequisites and Installation Requirements
Before generating SSL certificates, ensure you have the necessary tools installed on Ubuntu 24. OpenSSL comes pre-installed, but you’ll need Nginx and proper permissions.
sudo apt update
sudo apt install nginx openssl
sudo systemctl enable nginx
sudo systemctl start nginx
Verify your installations:
openssl version
nginx -v
sudo systemctl status nginx
Step-by-Step SSL Certificate Generation
The certificate generation process involves creating both a private key and the certificate file. Modern best practices recommend using at least 2048-bit RSA keys or 256-bit ECDSA keys for adequate security.
Method 1: Single Command Generation
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/ssl/private/nginx-selfsigned.key \
-out /etc/ssl/certs/nginx-selfsigned.crt
This command will prompt for certificate details:
Country Name (2 letter code) [AU]: US
State or Province Name (full name) [Some-State]: California
Locality Name (eg, city) []: San Francisco
Organization Name (eg, company) [Internet Widgits Pty Ltd]: MyCompany
Organizational Unit Name (eg, section) []: IT Department
Common Name (e.g. server FQDN or YOUR name) []: yourdomain.com
Email Address []: admin@yourdomain.com
Method 2: Separate Key and Certificate Generation
# Generate private key
sudo openssl genrsa -out /etc/ssl/private/nginx-selfsigned.key 2048
# Generate certificate signing request
sudo openssl req -new -key /etc/ssl/private/nginx-selfsigned.key \
-out /tmp/nginx-selfsigned.csr
# Generate self-signed certificate
sudo openssl x509 -req -days 365 \
-in /tmp/nginx-selfsigned.csr \
-signkey /etc/ssl/private/nginx-selfsigned.key \
-out /etc/ssl/certs/nginx-selfsigned.crt
# Clean up CSR file
rm /tmp/nginx-selfsigned.csr
Enhanced Security with ECDSA
For better performance and security, consider using ECDSA instead of RSA:
sudo openssl ecparam -genkey -name secp384r1 \
-out /etc/ssl/private/nginx-ecdsa.key
sudo openssl req -new -x509 -key /etc/ssl/private/nginx-ecdsa.key \
-out /etc/ssl/certs/nginx-ecdsa.crt -days 365
Nginx Configuration for SSL
Proper Nginx configuration requires modifying your site configuration to handle both HTTP and HTTPS traffic. Create or modify your site configuration:
sudo nano /etc/nginx/sites-available/your-site
Basic SSL configuration:
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
# SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
ssl_ecdh_curve secp384r1;
ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
# Security headers
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
location / {
try_files $uri $uri/ =404;
}
}
Performance Comparison: RSA vs ECDSA
Algorithm | Key Size | Equivalent Security | Handshake Performance | CPU Usage |
---|---|---|---|---|
RSA | 2048-bit | 112-bit | Baseline | High |
RSA | 4096-bit | 140-bit | 4x slower | Very High |
ECDSA | 256-bit | 128-bit | 2x faster | Low |
ECDSA | 384-bit | 192-bit | 1.5x faster | Medium |
Advanced Configuration Options
For production-like environments, consider creating a comprehensive SSL configuration snippet:
sudo nano /etc/nginx/snippets/ssl-params.conf
# SSL configuration snippet
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/dhparam.pem;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
ssl_ecdh_curve secp384r1;
ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
Generate strong Diffie-Hellman parameters:
sudo openssl dhparam -out /etc/nginx/dhparam.pem 4096
Then reference the snippet in your site configuration:
server {
listen 443 ssl http2;
server_name yourdomain.com;
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
include /etc/nginx/snippets/ssl-params.conf;
# Rest of your configuration
}
Testing and Validation
After configuration, test your SSL setup thoroughly:
# Test Nginx configuration syntax
sudo nginx -t
# Reload Nginx if test passes
sudo systemctl reload nginx
# Test SSL certificate
openssl s_client -connect localhost:443 -servername yourdomain.com
# Check certificate details
openssl x509 -in /etc/ssl/certs/nginx-selfsigned.crt -text -noout
Use online tools for comprehensive testing:
- SSL Labs Server Test for public sites
- Local testing with curl:
curl -k -I https://yourdomain.com
- Browser developer tools for detailed SSL information
Common Issues and Troubleshooting
Permission Issues
SSL certificate files require specific permissions for security:
sudo chmod 644 /etc/ssl/certs/nginx-selfsigned.crt
sudo chmod 600 /etc/ssl/private/nginx-selfsigned.key
sudo chown root:root /etc/ssl/certs/nginx-selfsigned.crt
sudo chown root:root /etc/ssl/private/nginx-selfsigned.key
Common Nginx Errors
Error: “SSL: error:02001002:system library:fopen:No such file or directory”
Solution: Verify certificate file paths in Nginx configuration match actual file locations.
Error: “SSL: error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch”
Solution: Ensure certificate and private key files match:
# Check certificate modulus
openssl x509 -noout -modulus -in /etc/ssl/certs/nginx-selfsigned.crt | openssl md5
# Check private key modulus
openssl rsa -noout -modulus -in /etc/ssl/private/nginx-selfsigned.key | openssl md5
Browser Trust Issues
Self-signed certificates will show security warnings in browsers. For development environments, you can:
- Add certificate to browser’s trusted certificate store
- Use –ignore-certificate-errors flag in Chrome for testing
- Configure applications to accept self-signed certificates
Real-World Use Cases and Applications
Self-signed certificates excel in specific scenarios:
- Development environments: Testing HTTPS functionality without CA costs
- Internal corporate applications: Securing intranet services where certificate warnings are acceptable
- IoT device interfaces: Embedded systems where custom certificate management is required
- Microservice communication: Service-to-service encryption in controlled environments
- Load balancer backends: Encrypting traffic between load balancers and application servers
Certificate Automation and Management
For environments requiring regular certificate rotation, create automation scripts:
#!/bin/bash
# Certificate renewal script
CERT_PATH="/etc/ssl/certs/nginx-selfsigned.crt"
KEY_PATH="/etc/ssl/private/nginx-selfsigned.key"
# Generate new certificate
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout $KEY_PATH \
-out $CERT_PATH \
-subj "/C=US/ST=CA/L=San Francisco/O=MyCompany/CN=yourdomain.com"
# Set proper permissions
chmod 644 $CERT_PATH
chmod 600 $KEY_PATH
# Test and reload Nginx
nginx -t && systemctl reload nginx
echo "Certificate renewed successfully"
Security Considerations and Best Practices
While self-signed certificates provide encryption, follow these security practices:
- Key length: Use minimum 2048-bit RSA or 256-bit ECDSA keys
- Certificate validity: Limit certificate lifetime to 1 year maximum
- Subject Alternative Names: Include all domain variants in certificate
- Private key protection: Store private keys with restrictive file permissions
- Protocol versions: Disable SSLv3, TLSv1.0, and TLSv1.1
- Cipher suites: Use strong, modern cipher suites only
Integration with Development Workflows
Self-signed certificates integrate well with modern development practices. For VPS deployments, you can automate certificate generation through configuration management tools like Ansible or Terraform. When scaling to production environments, consider migrating to dedicated servers with proper certificate management solutions.
For containerized applications, build certificate generation into your Docker images or use init containers to handle SSL setup. Many developers create separate SSL-enabled development environments that mirror production configurations without requiring commercial certificates.
Consider implementing certificate monitoring to track expiration dates and automate renewal processes. While self-signed certificates don’t require external validation, maintaining consistent certificate management practices prepares your infrastructure for eventual migration to CA-signed certificates.
For additional configuration guidance and SSL best practices, consult the official Nginx HTTPS documentation and OpenSSL documentation for advanced certificate management techniques.

This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.
This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.