Perfect! Since you want ssl_verify_client on;, we need a CA to verify client certificates, because Nginx cannot accept client certs without knowing which CA signed them. Let’s set it up step by step.


Step 1: Create a CA

This will be the authority that signs your client certificates.

mkdir -p /etc/nginx/ssl
cd /etc/nginx/ssl
 
# Generate CA private key
openssl genrsa -out ca.key 4096
 
# Generate CA certificate
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.crt \
    -subj "/C=US/ST=State/L=City/O=MyOrg/OU=IT/CN=MyRootCA"
  • ca.crt → used by Nginx as ssl_client_certificate.

  • ca.key → keep secure, used to sign client certs.


Step 2: Generate a client certificate

This is what your clients will use to connect.

# Client private key
openssl genrsa -out client.key 2048
 
# Client CSR
openssl req -new -key client.key -out client.csr \
    -subj "/C=US/ST=State/L=City/O=MyOrg/OU=IT/CN=client"
 
# Sign CSR with your CA
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
    -out client.crt -days 365 -sha256

Now you have:

  • client.crt → client certificate

  • client.key → client private key

  • ca.crt → CA certificate that Nginx will trust


Step 3: Update your Nginx config

server {
    listen 443 ssl;
    server_name remusic.servebeer.com;
 
    ssl_certificate /etc/letsencrypt/live/remusic.servebeer.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/remusic.servebeer.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
 
    # 🔒 Client certificate verification
    ssl_client_certificate /etc/nginx/ssl/ca.crt;  # <--- CA you just created
    ssl_verify_client on;
    ssl_verify_depth 2;  # optional
 
    location / {
        proxy_pass http://127.0.0.1:4533;
        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;
    }
}
 
server {
    listen 80;
    server_name remusic.servebeer.com;
    return 301 https://$host$request_uri;
}

Step 4: Test your setup

sudo nginx -t
sudo systemctl reload nginx

Then from a client machine:

curl -vk --cert client.crt --key client.key https://remusic.servebeer.com/
  • ✅ Works: if the client presents the valid certificate.

  • ❌ Fails: if no certificate or an invalid one is provided.


Perfect! Let’s create a simple client certificate that you can use to test your Nginx setup with ssl_verify_client on. I’ll guide you step by step in a safe way, keeping the CA private key secure.


Step 1: Work in your home folder

We don’t need root for client files. On your server:

mkdir -p ~/ssl-client
cd ~/ssl-client

Step 2: Generate the client private key

openssl genrsa -out client.key 2048
  • This is the client’s private key.

  • Keep this secret. Do not upload it to the server.


Step 3: Create a CSR (Certificate Signing Request)

openssl req -new -key client.key -out client.csr \
  -subj "/C=IE/ST=PHB/L=DUB/O=Re/OU=IT/CN=client1"
  • CN=client1 → identifies this client.

  • The CSR is what the CA will sign to create the certificate.


Step 4: Sign the client certificate with your CA

Your CA files are in /etc/nginx/ssl/. Sign the CSR:

sudo openssl x509 -req -in client.csr -CA /etc/nginx/ssl/ca.crt -CAkey /etc/nginx/ssl/ca.key \
  -CAcreateserial -out client.crt -days 365 -sha256

✅ Now you have:

  • client.crt → client certificate (can be given to the client)

  • client.key → client private key (client keeps this)

Note: Only the CA needs the private key (ca.key). You don’t share it.


Step 5: Test with curl

From the same machine or any client machine:

curl -vk --cert ~/ssl-client/client.crt --key ~/ssl-client/client.key https://remusic.servebeer.com/
  • ✅ Works if Nginx trusts the CA.

  • ❌ Fails if no certificate or wrong certificate is used.


Step 6: Configure Nginx (if not already)

ssl_client_certificate /etc/nginx/ssl/ca.crt;  # trust your CA
ssl_verify_client on;                           # require client cert
ssl_verify_depth 2;
  • Only clients with certificates signed by ca.crt can connect.

Back References: