This guide provides a detailed walkthrough on setting up SSL (Secure Sockets Layer) with Nginx using OpenSSL and acme.sh on Ubuntu 22.04. Each step is explained with key concepts and commands for a clear understanding.
Most errors occur due to incorrect paths. Know your path and create files and directories correctly before passing them as arguments.
sudo apt update
sudo apt install nginx openssl curl socat
sudo mkdir -p /etc/nginx/ssl
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt \
-subj "/C=US/ST=State/L=City/O=Organization/CN=your_domain.com"
You can set the key using the newkey
argument; in this code, we use RSA 2048. RSA 2048 is a widely-used cryptographic algorithm that ensures secure data encryption and decryption. It uses a 2048-bit key, which provides a high level of security.
curl https://get.acme.sh | sh
nano ~/.zshrc
Add your Cloudflare credentials: need Global API Key
export CF_Key="your_cloudflare_api_key"
export CF_Email="your_email_address"
Apply changes:
source ~/.zshrc
sudo systemctl restart nginx
~/.acme.sh/acme.sh --register-account -m your_email_address@gmail.com
~/.acme.sh/acme.sh --issue --dns dns_cf -d your_domain.com -d '*.your_domain.com' --debug
~/.acme.sh/acme.sh --install-cert -d your_domain.com \
--key-file /home/user/.acme.sh/your_domain.com_ecc/your_domain.com.key \
--fullchain-file /home/user/.acme.sh/your_domain.com_ecc/your_domain.com.cer \
--reloadcmd "sudo nginx -s reload"
sudo vim /etc/nginx/nginx.conf
Modify the server block to include SSL configuration:
worker_processes auto;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# Redirect HTTP to HTTPS
server {
listen 80;
server_name your_domain.com www.your_domain.com;
# Return a 301 redirect to force all HTTP requests to HTTPS
return 301 https://$host$request_uri;
}
# HTTPS server configuration
server {
listen 443 ssl; # Listen on port 443 for HTTPS traffic
server_name your_domain.com www.your_domain.com; # Define your server name
# Path to the SSL certificate and key files generated by acme.sh
ssl_certificate /home/user/.acme.sh/your_domain.com_ecc/your_domain.com.cer;
ssl_certificate_key /home/user/.acme.sh/your_domain.com_ecc/your_domain.com.key;
# Settings to optimize SSL performance
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
# Enable SSL protocols and specify the allowed ciphers
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Configuration for handling requests and proxying to a backend application
location / {
proxy_pass http://127.0.0.1:7888; # Proxy requests to the backend application running on port 7888
proxy_set_header Host $host; # Set the host header to the requested host
proxy_set_header X-Real-IP $remote_addr; # Forward the real client IP address
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # Forward the list of client IP addresses
proxy_set_header X-Forwarded-Proto $scheme; # Forward the original protocol (HTTP or HTTPS)
}
}
}
sudo nginx -t
sudo systemctl restart nginx
from flask import Flask
import ssl
app = Flask(__name__)
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
ssl_context.load_cert_chain(
certfile='/home/user/.acme.sh/your_domain.com_ecc/fullchain.cer',
keyfile='/home/user/.acme.sh/your_domain.com_ecc/your_domain.com.key'
)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=7888, debug=True, ssl_context=ssl_context)
~/.acme.sh/acme.sh --issue --dns dns_cf -d your_domain.com -d '*.your_domain.com' --debug
openssl s_client -connect your_domain.com:443 -tls1_2
sudo chown www-data:www-data /etc/nginx/ssl/your_domain.*
sudo chmod 644 /etc/nginx/ssl/your_domain.*
This guide provides a detailed walkthrough on setting up SSL (Secure Sockets Layer) with Nginx using OpenSSL and acme.sh on Ubuntu 22.04. Each step is explained with key concepts and commands for a clear understanding.
This guide walks you through configuring SSL for Nginx using OpenSSL and acme.sh on Ubuntu (22.04). It integrates Cloudflare for DNS and SSL certification, covering everything from initial package installation to final deployment and debugging of SSL configurations on a Flask application.
This program is a step-by-step guide that walks you through the process of setting up SSL (Secure Sockets Layer) encryption on an Nginx web server running on Ubuntu 22.04. SSL encryption is essential for securing web traffic and protecting sensitive data, such as login credentials and credit card information, from being intercepted by third parties.
The guide utilizes OpenSSL to generate self-signed SSL certificates initially, and then leverages acme.sh, an ACME protocol client, to obtain and manage free SSL certificates from Let’s Encrypt. It integrates with Cloudflare for DNS management and SSL verification. The guide covers various steps, including installing Nginx and required packages, generating SSL keys and certificates, configuring Nginx to use the SSL certificates, and automating the certificate renewal process with acme.sh. It also provides a Flask example code that demonstrates how to serve a Flask application with SSL encryption using the obtained certificates. Debugging and troubleshooting tips are included to help resolve any potential issues during the setup process.
Nginx is a high-performance web server. OpenSSL is a software library for secure communications over computer networks, and curl is a command-line tool for transferring data with URLs. socat, a tool for establishing bidirectional data streams.
sudo apt update
sudo apt install nginx openssl curl socat
OpenSSL is used to create self-signed SSL certificates, which encrypt data between the client and server.
sudo mkdir -p /etc/nginx/ssl
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt \
-subj "/C=US/ST=State/L=City/O=Organization/CN=your_domain.com"
openssl req -x509 -nodes -days 365 -newkey rsa:2048
: Generates a new self-signed certificate and key valid for 365 days. This uses a 2048-bit RSA key for encryption.acme.sh is a script that automates obtaining SSL certificates from Let’s Encrypt using the ACME protocol (Automated Certificate Management Environment).
curl https://get.acme.sh | sh
Cloudflare API credentials allow acme.sh to verify domain ownership and issue certificates.
Opens the .zshrc
file to add environment variables.
nano ~/.zshrc
Add your Cloudflare credentials:
export CF_Key="your_cloudflare_api_key"
export CF_Email="your_email_address"
export CF_Key="your_cloudflare_api_key"
: Sets your Cloudflare Global API key.export CF_Email="your_email_address"
: Sets your Cloudflare email address.Apply changes:
source ~/.zshrc
Restart Nginx to apply changes:
sudo systemctl restart nginx
acme.sh uses Cloudflare DNS to validate and issue SSL certificates.
Registers an account with Let’s Encrypt using your email.
~/.acme.sh/acme.sh --register-account -m your_email_address@gmail.com
Issue a wildcard certificate:
~/.acme.sh/acme.sh --issue --dns dns_cf -d your_domain.com -d '*.your_domain.com' --debug
acme.sh --issue --dns dns_cf -d your_domain.com -d '*.your_domain.com' --debug
: Issues a wildcard certificate for your domain using Cloudflare DNS for validation.The certificate needs to be installed and configured with Nginx.
Command Explanation:
~/.acme.sh/acme.sh --install-cert -d your_domain.com \
--key-file /home/user/.acme.sh/your_domain.com_ecc/your_domain.com.key \
--fullchain-file /home/user/.acme.sh/your_domain.com_ecc/your_domain.com.cer \
--reloadcmd "sudo nginx -s reload"
acme.sh --install-cert -d your_domain.com
: Installs the SSL certificate.--key-file /home/user/.acme.sh/your_domain.com_ecc/your_domain.com.key
: Specifies the key file.--fullchain-file /home/user/.acme.sh/your_domain.com_ecc/your_domain.com.cer
: Specifies the full certificate chain file.--reloadcmd "sudo nginx -s reload"
: Reloads Nginx to apply the new certificate.(Optional) Forces the renewal of the certificate for testing purposes.
~/.acme.sh/acme.sh --renew -d your_domain.com --force
Nginx needs to be configured to use the installed SSL certificate. This involves setting up Nginx to handle HTTPS traffic by pointing to the SSL certificate and key files, and configuring it to redirect HTTP traffic to HTTPS. This step ensures that all data transmitted between the server and clients is encrypted, enhancing security.
Command Explanation: Edit Nginx configuration:
sudo vim /etc/nginx/nginx.conf
Install the SSL certificate to be used with Nginx: Check the file path based on the settings in .acme.sh. It is not recommended to use sudo privileges; if necessary, refer to the following GitHub issue page: https://github.com/acmesh-official/acme.sh/wiki/sudo. If the path is not set correctly, permission errors may occur.
Modify the server block to include SSL configuration:
worker_processes auto;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# Redirect HTTP to HTTPS
server {
listen 80;
server_name your_domain.com www.your_domain.com;
# Return a 301 redirect to force all HTTP requests to HTTPS
return 301 https://$host$request_uri;
}
# HTTPS server configuration
server {
listen 443 ssl; # Listen on port 443 for HTTPS traffic
server_name your_domain.com www.your_domain.com; # Define your server name
# Path to the SSL certificate and key files generated by acme.sh
ssl_certificate /home/user/.acme.sh/your_domain.com_ecc/your_domain.com.cer;
ssl_certificate_key /home/user/.acme.sh/your_domain.com_ecc/your_domain.com.key;
# Settings to optimize SSL performance
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
# Enable SSL protocols and specify the allowed ciphers
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Configuration for handling requests and proxying to a backend application
location / {
proxy_pass http://127.0.0.1:7888; # Proxy requests to the backend application running on port 7888
proxy_set_header Host $host; # Set the host header to the requested host
proxy_set_header X-Real-IP $remote_addr; # Forward the real client IP address
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # Forward the list of client IP addresses
proxy_set_header X-Forwarded-Proto $scheme; # Forward the original protocol (HTTP or HTTPS)
}
}
}
worker_processes auto;
: Automatically sets the number of worker processes based on available CPU cores.events { worker_connections 1024; }
: Configures the maximum number of simultaneous connections that can be opened by each worker process.http { include mime.types; default_type application/octet-stream; }
: Includes MIME types and sets the default type for files.sendfile on; keepalive_timeout 65;
: Enables efficient file transfer and sets the timeout for keep-alive connections.server { listen 80; server_name your_domain.com www.your_domain.com; return 301 https://$host$request_uri; }
: Configures the server to listen on port 80 for HTTP traffic and redirect all requests to HTTPS.server { listen 443 ssl; server_name your_domain.com www.your_domain.com; }
: Configures the server to listen on port 443 for HTTPS traffic.ssl_certificate /home/user/.acme.sh/your_domain.com_ecc/your_domain.com.cer; ssl_certificate_key /home/user/.acme.sh/your_domain.com_ecc/your_domain.com.key;
: Specifies the paths to the SSL certificate and key files.ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m;
: Configures SSL session caching and timeout for performance optimization.ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on;
: Specifies the supported SSL/TLS protocols and ciphers, and prioritizes server ciphers.location / { proxy_pass http://127.0.0.1:7888; 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; }
: Configures the proxy settings for forwarding requests to a backend application running on port 7888.Restarting Nginx applies the new SSL configurations.
sudo nginx -t
sudo systemctl restart nginx
sudo nginx -t
: Tests the Nginx configuration for errors.sudo systemctl restart nginx
: Restarts Nginx to apply the new configuration.Flask application example configured to use the SSL certificate.
Example Code:
from flask import Flask
import ssl
app = Flask(__name__)
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
ssl_context.load_cert_chain(
certfile='/home/user/.acme.sh/your_domain.com_ecc/fullchain.cer',
keyfile='/home/user/.acme.sh/your_domain.com_ecc/your_domain.com.key'
)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=7888, debug=True, ssl_context=ssl_context)
Detailed logs help identify issues with SSL setup.
Command Explanation:
Use --debug
flag for detailed logs:
~/.acme.sh/acme.sh --issue --dns dns_cf -d your_domain.com -d '*.your_domain.com' --debug
acme.sh --debug
: Provides detailed logs for troubleshooting.Verify SSL installation using OpenSSL:
openssl s_client -connect your_domain.com:443 -tls1_2
openssl s_client -connect
: ConnectEnsure that permissions and ownership of the SSL files are correct, which might require adjustments depending on your server’s configuration. Typically, Nginx runs as the www-data
user, and the SSL files need to be accessible to it:
sudo chown www-data:www-data /etc/nginx/ssl/your_domain.*
sudo chmod 644 /etc/nginx/ssl/your_domain.*
tmux
Session ManagementTo detach a tmux
session and run it in the background:
tmux new -s my_flask_app
python main.py
Ctrl+b, d
This keeps the tmux
session running in the background even if the terminal is closed.
To reattach to the tmux
session:
tmux attach -t my_flask_app
To list all running tmux
sessions:
tmux ls
To terminate a process running on port 7888
:
lsof -i :7888
kill <PID>
If the process doesn’t terminate, use:
kill -9 <PID>
</details>