I'm trying to add SSL certs (generated with LetsEncrypt) to my nginx. The nginx is built from a docker-compose file where I create a volume from my host to the container so the containers can access the certs and private key.
volumes:
- /etc/nginx/certs/:/etc/nginx/certs/
When the nginx container starts and fails with the following error
[emerg] 1#1: BIO_new_file("/etc/nginx/certs/fullchain.pem") failed
(SSL: error:02001002:system library:fopen:No such file or
directory:fopen('/etc/nginx/certs/fullchain.pem','r')
error:2006D080:BIO routines:BIO_new_file:no such file)
My nginx config file looks like this:
server {
listen 80;
server_name server_blah www.server_blah;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name server_blah;
ssl_certificate /etc/nginx/certs/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
}
What am I missing/doing incorrectly?
Finally cracked this and was able to successfully repeat the process on my dev and production site to get SSL certs working!
Sorry for the length of the post!
In my setup I have docker docker-compose setup on an ubuntu 16 machine.
Anyone who's encountering this problem I'll detail the steps I did.
Go to the directory where your code lives
cd /opt/example_dir/
Make a directory for letsencrypt and it's site.
sudo mkdir -p /opt/example_dir/letsencrypt/letsencrypt-site
Create barebones docker-compose.yml file from the letsencrypt directory.
sudo nano /opt/example_dir/letsencrypt/docker-compose.yml
Add the following to it:
version: '2'
services:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./letsencrypt-site:/usr/share/nginx/html
networks:
- docker-network
networks:
docker-network:
driver: bridge
we start the simple nginx container.
Create an nginx.conf file in /opt/example_dir/letsencrypt
sudo nano /opt/example_dir/letsencrypt/nginx.conf
Put the following into it
server {
listen 80;
listen [::]:80;
server_name example_server.com;
location ~ /.well-known/acme-challenge {
allow all;
root /usr/share/nginx/html;
}
root /usr/share/nginx/html;
index index.html;
}
/opt/example_dir/letsencrypt/letsencrypt-site
sudo nano /opt/example_dir/letsencrypt/letsencrypt-site/index.html
Add the following to it
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>LetsEncrypt Setup</title>
</head>
<body>
<p>Test file for our http nginx server</p>
</body>
</html>
cd /opt/example_dir/letsencrypt
sudo docker-compose up -d
The nginx container is up and running now, visit the url you've defined and you should get the test index.html page back. At this point we're ready to run the certbot command to generate some certs
--email
with your emailsudo docker run -it --rm \
-v /docker-volumes/etc/letsencrypt:/etc/letsencrypt \
-v /docker-volumes/var/lib/letsencrypt:/var/lib/letsencrypt \
-v /opt/example_dir/letsencrypt/letsencrypt-site:/data/letsencrypt \
-v "/docker-volumes/var/log/letsencrypt:/var/log/letsencrypt" \
certbot/certbot \
certonly --webroot \
--email youremail@domain.com --agree-tos --no-eff-email \
--webroot-path=/data/letsencrypt \
-d example.com
If that command ran okay then we have generated certs for this web server. We can now use these in our production site and configure nginx to use the ssl and make use of these certs!
cd /opt/example_dir/letsencrypt/
sudo docker-compose down
Directory structure should look like this now. Where you have your code / web app project and then the letsencrypt folder that we created above.
/opt/example_dir
/ -> project_folder
/ -> letsencrypt
sudo mkdir -p /opt/example_dir/project_folder/dh-param
sudo openssl dhparam -out /opt/example_dir/project_folder/dhparam/dhparam-2048.pem 2048
/opt/example_dir/project_folder
The project_folder is where my source code lives so I create a production config file here for nginx and update the docker-compose.yml to mount my nginx config, dh-pharam exchange key as well as the certs themselves we created earlier.
nginx service in the docker-compose
nginx:
image: nginx:1.11.3
restart: always
ports:
- "80:80"
- "443:443"
- "8000:8000"
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
- ./dh-param/dhparam-2048.pem:/etc/ssl/certs/dhparam-2048.pem
- /docker-volumes/etc/letsencrypt/live/exampleserver.com/fullchain.pem:/etc/letsencrypt/live/exampleserver.com/fullchain.pem
- /docker-volumes/etc/letsencrypt/live/exampleserver.com/privkey.pem:/etc/letsencrypt/live/exampleserver.com/privkey.pem
networks:
- docker-network
volumes_from:
- flask
depends_on:
- flask
- falcon
links:
- datastore
nginx.conf within project_folder
error_log /var/log/nginx/error.log warn;
server {
listen 80;
listen [::]:80;
server_name exampleserver.com
location / {
rewrite ^ https://$host$request_uri? permanent;
}
#for certbot challenges (renewal process)
location ~ /.well-known/acme-challenge {
allow all;
root /data/letsencrypt;
}
}
#https://exampleserver.com
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name exampleserver.com;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/exampleserver.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/exampleserver.com/privkey.pem;
ssl_buffer_size 8k;
ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
ssl_ecdh_curve secp384r1;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
# Define the specified charset to the “Content-Type” response header field
charset utf-8;
}
At this point everything is setup! (finally)
cd /opt/example_dir/project_folder
sudo docker-compose up -d
# Check the docker log with:
sudo docker logs -f -t
I know it's a lot of steps but this is what I have done, it's worked for me and hope it helps someone else.