00:00:00

Share Your Feedback 🏝️

Post | Nginx + SSL + Flask on Ubuntu 22.04

Post | Nginx + SSL + Flask on Ubuntu 22.04

MinWoo(Daniel) Park | Tech Blog

Read more
Previous: Post | Ruby + Gem + Jekyll on Ubuntu 22.04 Next: Google | Compute Optimal

Post | Nginx + SSL + Flask on Ubuntu 22.04

  • Related Project: Private
  • Category: Paper Review
  • Date: 2024-05-08

Step-by-Step Guide to Setting Up SSL with Nginx on Ubuntu 22.04

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.

  1. Install Nginx and necessary packages:
     sudo apt update
     sudo apt install nginx openssl curl socat
    
  2. Generate an OpenSSL key and certificate:
     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.

  3. Install acme.sh:
     curl https://get.acme.sh | sh
    
  4. Set up Cloudflare API credentials for acme.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
    
  5. Issue certificate using acme.sh:
     ~/.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
    
  6. Install the certificate:
     ~/.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"
    
  7. Configure Nginx:
     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)
             }
         }
     }
    
  8. Restart Nginx:
     sudo nginx -t
     sudo systemctl restart nginx
    
  9. Flask 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)
    
  10. Debugging and troubleshooting:
    ~/.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.*
    









Details

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.

TL;DR

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.

What is this program?

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.

How does it work?

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.



Prerequisites:

  • DNS Configuration: Ensure your DNS settings are mapped to your public IP. In this setup, Cloudflare DNS is used.
  • SSL Certification: SSL certification is performed through Cloudflare.



Step 1: Install Nginx and Necessary Packages

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


Step 2: Generate an OpenSSL Key and Certificate

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.


Step 3: Install acme.sh

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


Step 4: Setup Cloudflare API Credentials for acme.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


Step 5: Issue Certificate Using acme.sh

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.


Step 6: Install the Certificate

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


Step 7: Configure Nginx

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.


Step 8: Restart Nginx

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.


Step 9: Flask Example Code

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)



Debugging and Troubleshooting

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: Connect

Ensure 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.*



Background running using tmux Session Management

To detach a tmux session and run it in the background:

  1. Start tmux session:
    tmux new -s my_flask_app
    
  2. Run Flask application within the session:
    python main.py
    
  3. Detach the session:
    Ctrl+b, d
    

    This keeps the tmux session running in the background even if the terminal is closed.

Reattach to tmux Session

To reattach to the tmux session:

tmux attach -t my_flask_app

List Running tmux Sessions

To list all running tmux sessions:

tmux ls

Terminate Process on Port 7888

To terminate a process running on port 7888:

  1. Find the process:
    lsof -i :7888
    
  2. Kill the process:
    kill <PID>
    

    If the process doesn’t terminate, use:

    kill -9 <PID>
    

</details>

Previous: Post | Ruby + Gem + Jekyll on Ubuntu 22.04 Next: Google | Compute Optimal

post contain ""

    No matching posts found containing ""