SSL for Nginx in Docker: How to Set Up PFX Certificates Correctly
Convert PFX certificates to PEM and set up SSL/TLS for your Nginx container in Docker. A practical, step-by-step guide for self-hosters to secure their web apps.
Table of Contents
Introduction
Securing web applications with SSL/TLS is often essential. An encrypted connection via HTTPS not only protects your users’ data but also builds trust. While services like Let’s Encrypt automate the process, some certificate authorities or internal networks provide certificates in the PFX format (.pfx or .p12).
This format bundles the certificate and private key into a single, password-protected file, which is convenient for Windows servers. However, Nginx, the most popular web server in the Docker ecosystem, prefers the PEM format with separate files.
This article will show you, step-by-step, how to prepare and configure a PFX certificate using OpenSSL for use with an Nginx container.
Glossary: Key SSL Terms
| Term | Description |
|---|---|
| SSL/TLS | Secure Sockets Layer / Transport Layer Security. Protocols for encrypting data transmission over the internet. TLS is the modern successor to SSL. |
| PFX/PKCS#12 | A binary file format that bundles an SSL certificate, intermediate certificates, and the private key into a single, password-protected file. Extensions are often .pfx or .p12. |
| PEM | Privacy Enhanced Mail. A text-based file format that encodes cryptographic information (like certificates or keys) in Base64. Nginx and Apache prefer this format. |
| OpenSSL | A powerful command-line tool for working with SSL/TLS certificates. We will use it for the conversion. |
| Private Key | The private key (.key or .pem). It must be kept secret and is used by the server to decrypt data sent to it. |
| Certificate | The public certificate (.crt or .pem). It is sent from the server to the client (browser) to prove its identity. |
| CA Chain | Certificate Authority Chain. A chain of intermediate certificates that proves the trustworthiness of your certificate up to a root CA. Essential for avoiding browser warnings. |
| Nginx | A high-performance, resource-efficient web server and reverse proxy, commonly used in Docker setups. |
| Docker Compose | A tool for defining and running multi-container Docker applications using a single YAML file. |
Step 1: Prepare the PFX Certificate for Nginx
The conversion of a PFX file can be done entirely with the openssl command-line tool, which is pre-installed on most Linux systems. Execute the following commands in your terminal from the root directory of your Docker project.
1. Create a Directory for SSL Certificates
First, let’s create a clean directory structure. An ssl subdirectory inside your Nginx configuration folder is a good and common place for your certificate files.
mkdir -p nginx/ssl
cd nginx/ssl
2. Copy the PFX File
Copy your PFX file (e.g., certificate.pfx) into this newly created nginx/ssl directory.
3. Extract the Private Key
This command extracts the private key from the PFX file. You will be prompted to enter the password for the PFX file. The result is a PEM file that is still password-protected.
openssl pkcs12 -in certificate.pfx -nocerts -out private-key-encrypted.pem
# Enter your PFX password
4. Extract the Certificate
Next, the public certificate is extracted from the PFX file.
openssl pkcs12 -in certificate.pfx -clcerts -nokeys -out certificate.pem
5. Extract the CA Certificate Chain (if present)
Modern certificates often include the chain of intermediate certificates. These should also be extracted to avoid trust issues in browsers.
openssl pkcs12 -in certificate.pfx -cacerts -nokeys -out ca-chain.pem
6. Remove Password Protection from the Private Key
The extracted private key is still protected by a passphrase. To allow Nginx to start automatically without asking for a password, we need to remove this protection.
openssl rsa -in private-key-encrypted.pem -out private-key.pem
7. Clean Up
The encrypted version of the private key is no longer needed and should be removed for security reasons.
rm private-key-encrypted.pem
8. Set Permissions
Protecting the private key is crucial. Ensure that only the owner can read the file. Public certificates can be read by everyone.
chmod 600 private-key.pem
chmod 644 certificate.pem ca-chain.pem
9. Create the Full Certificate Chain (Recommended)
For optimal compatibility with all browsers and easier configuration in Nginx, it is advisable to combine your certificate and the CA chain into a single file. Nginx can then use this fullchain.pem directly.
cat certificate.pem ca-chain.pem > fullchain.pem
After these steps, your nginx/ssl directory should contain the two essential files: private-key.pem and fullchain.pem. We can now adjust the Nginx configuration.
cd ../.. # Back to the root directory
Step 2: Adjust the Nginx Configuration for SSL
Now we need to tell Nginx where to find the certificate files and that the server should listen on the HTTPS port 443.
Create a configuration file, e.g., nginx/nginx.conf. A typical configuration that redirects HTTP requests to HTTPS and uses SSL looks like this:
cd nginx
touch nginx.conf
server {
listen 80;
server_name your-domain.com www.your-domain.com;
# Redirect all HTTP requests to HTTPS with a 301 status code (Permanent)
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name your-domain.com www.your-domain.com;
# Paths to the SSL certificate files INSIDE THE CONTAINER
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/private-key.pem;
# Additional SSL optimizations (Best Practices)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# Add HSTS Header (Strict Transport Security)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
location / {
# A reverse proxy to another application can be placed here
proxy_pass http://my-container:8080;
# Or serve static content
# root /usr/share/nginx/html;
# index index.html index.htm;
}
}
Important Notes on the Configuration:
- Replace
your-domain.comwith your actual domain. - The
ssl_certificateandssl_certificate_keypaths point to the location inside the Docker container, which we will provide via a volume mount in the next step.
Step 3: Docker Compose Setup for Nginx with SSL
To start the Nginx container and use our configuration and certificates, Docker Compose is ideal. Just like in my guides on Paperless-NGX on Synology or setting up a home server, we will use a compose.yaml file in the project’s root directory.
touch compose.yaml
services:
nginx:
image: nginx:latest
container_name: nginx_webserver
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
# Nginx configuration file
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
# SSL certificates (mount as read-only)
- ./nginx/ssl:/etc/nginx/ssl:ro
# Example for static content
# - ./html:/usr/share/nginx/html:ro
networks:
- web_network
networks:
web_network:
external: true
Explanation of the Volumes:
./nginx/nginx.conf:/etc/nginx/nginx.conf:ro: Binds our local configuration file into the container. The:ro(read-only) suffix is a good security practice, as the container should not be able to modify its configuration../nginx/ssl:/etc/nginx/ssl:ro: Makes our prepared SSL certificates available to Nginx inside the container, also in read-only mode.
After saving the compose.yaml file, you can start the Nginx container with a simple command:
docker compose up -d
Your web server is now accessible via https://your-domain.com, and the connection is securely encrypted. You can check the quality of your SSL configuration with tools like the SSL Labs Server Test.
Conclusion
The manual configuration of SSL certificates for Nginx in Docker is quickly accomplished with the right tools and steps. By correctly converting PFX files to the PEM format and maintaining a clean structure for your configuration and certificates, you create a robust and secure setup for your self-hosted services.
Why do I need to remove the password protection from the private key?
What is the difference between fullchain.pem and certificate.pem?
Can I automate this process?
Does this also work with other reverse proxies like Traefik or Caddy?
What happens when my certificate expires?
Related Articles
Reverse Proxy Benchmark 2025: NPM vs. NPM+ (HTTP/3) vs. Zoraxy
Performance benchmark: Nginx Proxy Manager vs. NPM+ (HTTP/3) vs. Zoraxy. Discover which reverse proxy is the fastest and easiest for your self-hosted setup.
Backups with Duplicati & Docker: Secure Data Protection
Protect your Docker data and databases reliably with Duplicati. Set up automated backups, including cloud storage. Open source, flexible, and easy to configure.
Install Claper: Self-Host Interactive Presentations with Docker
Create interactive presentations with Claper. This guide shows you step-by-step how to install and secure Claper on your own server using Docker and Docker Compose.
Installing Home Assistant with Docker on a Raspberry Pi
Install Home Assistant with Docker on a Raspberry Pi and build your own private smart home. Step-by-step guide for a powerful, self-hosted automation setup.