Published: 24.05.2021 | Edited: 24.05.2021 | Tags: 100daystooffload,nginx,docker

Certificate not found with Nginx under Docker

When trying to run a docker-compose with a Nginx inside and setting up TLS for a virtual host (subdomain), this error showed up:

nginx: [emerg] cannot load certificate "/etc/nginx/ssl/sub.peterbabic.dev.cer":
BIO_new_file() failed (SSL: error:02001002:system library:fopen:
No such file or directory:fopen('/etc/nginx/ssl/sub.peterbabic.dev.cer','r')
error:2006D080:BIO routines:BIO_new_file:no such file)

I tried to do all kinds of permissions and group changes believing that the docker user has insufficient privileges to access the files because they were very clearly present in the filesystem.

It took me far longer to resolve than I would like to admit. After many many search results that did not get off a clue about the problem, I have found this comment that finally nudged me in the right direction.

Docker compose volumes

The problem was I was instructing Nginx to access certificates generated by acme.sh that resided on the host, but they were not mounted by the container, so it could not access them. What a rookie mistake. The solution is on the last line in this excerpt of docker-compose.yml file:

version: "3"
services:
  nginx:
    container_name: nginx-server
    image: nginx
    restart: always
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - /etc/nginx/ssl:/etc/nginx/ssl

The last line mounts the /etc/nginx/ssl/ folder from the host inside the container, so Nginx there can access the certificates and enable TLS. For the completeness, an excerpt from the referenced nginx.conf could look like this:

server {
  listen 443 ssl http2;
  server_name sub.peterbabic.dev;

  ssl_certificate     /etc/nginx/ssl/sub.peterbabic.dev.cer;
  ssl_certificate_key /etc/nginx/ssl/sub.peterbabic.dev.key;
  ssl_protocols       TLSv1.1 TLSv1.2;
  ssl_ciphers         HIGH:!aNULL:!MD5;
}

This is a 75th post of #100daystooffload.