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
* This will pull down the latest nginx version
* Expose port 80
* Mount a config file (that i'll create later)
* Maps the site directory so that we can have a simple test index.html for when
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;
}
* This listens for requests on port 80 for the server with name example_server.com
* Gives the Certbot agent access to ./well-known/acme-challenge
* Sets the default root and file
/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>
Now we start up the nginx container.
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
Run the following to generate certs replacing --email
with your email
sudo 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 [email protected] --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!
Shut down the nginx container
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
Create a folder call dh-param
sudo mkdir -p /opt/example_dir/project_folder/dh-param
Generate a dh key
sudo openssl dhparam -out /opt/example_dir/project_folder/dh-param/dhparam-2048.pem 2048
Update docker-compose.yml and nginx.conf files within /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)
Spin up the docker container.
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.
I have mapped /etc/letsencrypt/live/mydomain.com/
to /etc/nginx/certs/
by:
volumes:
- /etc/letsencrypt/live/mydomain.com/:/etc/nginx/certs/
In this case, it has mapped the soft symbolic link.
lrwxrwxrwx 1 root root 38 Sep 15 00:21 chain.pem -> ../../archive/mydomain.com/chain1.pem
lrwxrwxrwx 1 root root 42 Sep 15 00:21 fullchain.pem -> ../../archive/mydomain.com/fullchain1.pem
lrwxrwxrwx 1 root root 40 Sep 15 00:21 privkey.pem -> ../../archive/mydomain.com/privkey1.pem
Finally, I changed the volume
section as the following:
volumes:
- /etc/letsencrypt/archive/mydomain.com/:/etc/nginx/certs/
I've got the exact same problem right now. Same error codes.
I tried different things on my .pem files:
Sadly, none of those solutions worked for me.
It really looks like nginx isn't able to find the files even if I'm able to list (ls) them when I connect to the container terminal.
To give some more details, I'm running Docker on a Synology DS918+ NAS.
I hope this will help to find the solution! I'll be experimenting and trying various things, I'll come back if I manage to get this working!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With