Detailed Configuration Guide for the NGINX Directive ssl_password_file

Title: Using ssl_password_file in NGINX for SSL/TLS Private Key Management


Introduction

The ssl_password_file directive in NGINX specifies a file containing passwords used to unlock encrypted SSL/TLS private keys. When NGINX starts or reloads, it reads this file to load and decrypt the private key. Incorrect passwords in this file will prevent NGINX from starting or reloading successfully.


Syntax

Syntax:    ssl_password_file file;  
Default:   —  
Context:   http, server  
This directive appeared in version 1.7.3.  
  • file: Specifies the path to the password file. Each line in the file should contain a single password. When loading a private key, NGINX will try the passwords in sequence.

Default

By default, the ssl_password_file directive is not enabled, and no password file is set.


Use Cases

The ssl_password_file directive is commonly used in scenarios such as:

  1. Encrypted Private Keys: When SSL/TLS private keys are generated with password protection, NGINX needs the password to load these keys each time it starts.
  2. Automated Deployment: Using a password file allows NGINX to load encrypted keys without manual intervention, facilitating automated deployments.

Configuration Example

Example 1: Generating Certificates and Private Keys

The following script generates four self-signed certificates and private keys (two RSA and two ECC). Each algorithm includes one key with a password and one without a password.

Script

#!/bin/bash  

# Set the directory for certificates  
CERTS_DIR="/etc/nginx/ssl"  
mkdir -p $CERTS_DIR  

# Define passwords for keys  
PASSWORD_RSA="password123"  
PASSWORD_ECC="password789"  

# Create password files  
echo $PASSWORD_RSA > "$CERTS_DIR/rsa_password.txt"  
echo $PASSWORD_ECC > "$CERTS_DIR/ecc_password.txt"  
chmod 600 "$CERTS_DIR"/*.txt  

# Generate RSA private keys and certificates  
openssl genpkey -algorithm RSA -aes256 -pass pass:$PASSWORD_RSA -out "$CERTS_DIR/rsa_key_with_password.pem"  
openssl genpkey -algorithm RSA -out "$CERTS_DIR/rsa_key_without_password.pem"  

openssl req -new -key "$CERTS_DIR/rsa_key_with_password.pem" -passin pass:$PASSWORD_RSA -out "$CERTS_DIR/rsa_csr_with_password.pem" \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=Test/OU=TestUnit/CN=example1.com/emailAddress=email@example.com"  
openssl req -new -key "$CERTS_DIR/rsa_key_without_password.pem" -out "$CERTS_DIR/rsa_csr_without_password.pem" \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=Test/OU=TestUnit/CN=example2.com/emailAddress=email@example.com"  

openssl x509 -req -in "$CERTS_DIR/rsa_csr_with_password.pem" -signkey "$CERTS_DIR/rsa_key_with_password.pem" -passin pass:$PASSWORD_RSA -out "$CERTS_DIR/rsa_cert_with_password.pem" -days 365  
openssl x509 -req -in "$CERTS_DIR/rsa_csr_without_password.pem" -signkey "$CERTS_DIR/rsa_key_without_password.pem" -out "$CERTS_DIR/rsa_cert_without_password.pem" -days 365  

# Generate ECC private keys and certificates  
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -aes256 -pass pass:$PASSWORD_ECC -out "$CERTS_DIR/ecc_key_with_password.pem"  
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out "$CERTS_DIR/ecc_key_without_password.pem"  

openssl req -new -key "$CERTS_DIR/ecc_key_with_password.pem" -passin pass:$PASSWORD_ECC -out "$CERTS_DIR/ecc_csr_with_password.pem" \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=Test/OU=TestUnit/CN=example3.com/emailAddress=email@example.com"  
openssl req -new -key "$CERTS_DIR/ecc_key_without_password.pem" -out "$CERTS_DIR/ecc_csr_without_password.pem" \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=Test/OU=TestUnit/CN=example4.com/emailAddress=email@example.com"  

openssl x509 -req -in "$CERTS_DIR/ecc_csr_with_password.pem" -signkey "$CERTS_DIR/ecc_key_with_password.pem" -passin pass:$PASSWORD_ECC -out "$CERTS_DIR/ecc_cert_with_password.pem" -days 365  
openssl x509 -req -in "$CERTS_DIR/ecc_csr_without_password.pem" -signkey "$CERTS_DIR/ecc_key_without_password.pem" -out "$CERTS_DIR/ecc_cert_without_password.pem" -days 365  

Example 2: NGINX Configuration Using ssl_password_file

Configuration

user nginx;  
worker_processes 1;  

error_log logs/error.log debug;  

events {  
    worker_connections 1024;  
}  

http {  
    # Specify the global SSL password file  
    ssl_password_file /etc/nginx/ssl/password_file.txt;  

    ssl_protocols TLSv1.2 TLSv1.3;  
    ssl_ciphers HIGH:!aNULL:!MD5;  

    # Example server block with RSA key  
    server {  
        listen 443 ssl;  
        server_name example1.com;  

        ssl_certificate /etc/nginx/ssl/rsa_cert_with_password.pem;  
        ssl_certificate_key /etc/nginx/ssl/rsa_key_with_password.pem;  

        location / {  
            return 200 "Welcome to example1.com\n";  
        }  
    }  

    # Example server block with ECC key  
    server {  
        listen 443 ssl;  
        server_name example3.com;  

        ssl_certificate /etc/nginx/ssl/ecc_cert_with_password.pem;  
        ssl_certificate_key /etc/nginx/ssl/ecc_key_with_password.pem;  

        location / {  
            return 200 "Welcome to example3.com\n";  
        }  
    }  
}  

Validation

You can validate the setup using curl commands:

curl --resolve example1.com:443:127.0.0.1 -H "Host: example1.com" https://example1.com -k -v
curl --resolve example2.com:443:127.0.0.1 -H "Host: example2.com" https://example2.com -k -v
curl --resolve example3.com:443:127.0.0.1 -H "Host: example3.com" https://example3.com -k -v
curl --resolve example4.com:443:127.0.0.1 -H "Host: example4.com" https://example4.com -k -v

Inspect the certificate details using the output of the curl commands.

[root@iZ8vbd88lmglnbsnad85q3Z nginx-quic]# curl --resolve example1.com:443:127.0.0.1 -H "Host: example1.com" https://example1.com -k -v
* Added example1.com:443:127.0.0.1 to DNS cache
* Hostname example1.com was found in DNS cache
*   Trying 127.0.0.1:443...
* Connected to example1.com (127.0.0.1) port 443
* ALPN: curl offers http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519 / RSASSA-PSS
* ALPN: server accepted http/1.1
* Server certificate:
*  subject: C=CN; ST=BEIJING; L=BEIJING; O=test; OU=test-unit; CN=example1.com; emailAddress=email@example.com
*  start date: Dec  1 12:54:50 2024 GMT
*  expire date: Dec  1 12:54:50 2025 GMT
*  issuer: C=CN; ST=BEIJING; L=BEIJING; O=test; OU=test-unit; CN=example1.com; emailAddress=email@example.com
*  SSL certificate verify result: self-signed certificate (18), continuing anyway.
*   Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* using HTTP/1.x
> GET / HTTP/1.1
> Host: example1.com
> User-Agent: curl/8.6.0
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
< HTTP/1.1 200 OK
< Server: nginx/1.25.4
< Date: Tue, 03 Dec 2024 13:53:19 GMT
< Content-Type: text/plain
< Content-Length: 38
< Connection: keep-alive
<
This is the response for example3.com
* Connection #0 to host example1.com left intact


Security Considerations

  1. Restrict File Permissions: Ensure that the password file is only readable by the NGINX user:
    bash
    chmod 600 /etc/nginx/ssl/password_file.txt
    chown nginx:nginx /etc/nginx/ssl/password_file.txt
  2. Avoid Storing Passwords in Plaintext: Use secure password management tools whenever possible.

Conclusion

  • The ssl_password_file directive simplifies the process of loading encrypted private keys, improving deployment automation.
  • Proper permission settings and security practices are essential to protect the password file.
  • Combining ssl_password_file with secure password management tools further enhances system security.

Comments are closed.