SSL Lets Encrypt + NGINX + Docker Compose

My nginx.conf is:

events {
    worker_connections 1024;
}

http {
    server_tokens off;
    charset utf-8;

    server {
        listen 80 default_server;
        server_name _;

        location ~ /.well-know/acme-challenge/ {
            root /var/www/certbot;
        }

        return 301 https //$host$request_uri;
    }

    server {
        listen 443 ssl http2;
        ssl_certificate /etc/letsencrypt/live/dogyt.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/dogyt.com/privkey.pem;
        server_name dogyt.com;
        client_max_body_size 108M;
        access_log /var/log/nginx/application.access.log;

        root /var/www/html;
        index index.php index.html index.htm;

        # try to serve file directly, fallback to index.php
        location / {
            proxy_pass http://helloworld:8000/;
            # try_files $uri /index.php$is_args$args;
        }

        location ~ /.well-know/acme-challenge/ {
            root /var/www/certbot;
        }

        if (!-e $request_filename) {
            rewrite ^.*$ /index.php last;
        }

        location ~ \.php$ {
            fastcgi_pass php-fpm:9000;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PHP_VALUE "error_log=/var/log/nginx/application_php_errors.log";
            fastcgi_buffers 16 16k;
            fastcgi_buffer_size 32k;
            include fastcgi_params;
        }
    }
}

My Docker Compose is:

networks:
  mynetwork:
    driver: bridge
    ipam:
      config:
        - subnet: 1.1.1.0/16
          gateway: 1.1.1.1


services:
    postgres:
        image: 'postgres:14.12'
        working_dir: /application
        volumes:
            - '.:/application'
        environment:
            POSTGRES_USER: ${DB_USUARIO}
            POSTGRES_PASSWORD: ${DB_SENHA}
            POSTGRES_DB: ${DB_BANCO}
        ports:
            - '5432:5432'
        networks:
            mynetwork:
                ipv4_address: 1.1.1.3

    webserver:
        image: 'nginx:alpine'
        restart: unless-stopped
        working_dir: /application
        volumes:
            # - .:/application
            - ./phpdocker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
            - ./certbot/conf:/etc/letsencrypt
            - ./certbot/www:/var/www/certbot
        ports:
            - 80:80
            - 443:443
        networks:
            - mynetwork
        depends_on:
            - postgres
    
    certbot:
        image: 'certbot/certbot'
        volumes:
            - ./certbot/conf:/etc/letsencrypt
            - ./certbot/www:/var/www/certbot
        command: certonly --webroot -v -w /var/www/certbot --force-renewal --email igor.o.crisostomo@gmail.com -d dogyt.com --agree-tos
    
    php-fpm:
        build: phpdocker/php-fpm
        working_dir: /application
        volumes:
            - '.:/application'
            - './phpdocker/php-fpm/php-ini-overrides.ini:/etc/php/8.3/fpm/conf.d/99-overrides.ini'
        networks:
            - mynetwork

Why this error?

Certbot failed to authenticate some domains (authenticator: webroot). The Certificate Authority reported these problems:
certbot-1 | Domain: dogyt.com
certbot-1 | Type: connection
certbot-1 | Detail: 82.180.162.136: Fetching http://dogyt.com/.well-known/acme-challenge/6hcnkruIrA3EOD6Wn9BP8RLczrLZ3Cyx6ifzy9nT6HI: Connection refused
certbot-1 |
certbot-1 | Hint: The Certificate Authority failed to download the temporary challenge files created by Certbot. Ensure that the listed domains serve their content from the provided --webroot-path/-w and that files created there can be downloaded from the internet.
certbot-1 |
certbot-1 | Some challenges have failed.
certbot-1 | Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.

what do you see for this command?

docker compose logs webserver

1 Like

Please remove this immediately.

Also note that the IP range 1.1.0.0/16 is NOT a private IP range, but a public one. E.g. 1.1.1.1 is actually a well known public Cloudflare DNS resolver. Maybe you're mistaken with 10.0.0.0/8?

I also see that you've issued a certificate 3 days ago: crt.sh | 13457940646. Can't you use that one?

2 Likes

You need to wrap your return in a location block. Otherwise it occurs for each request.

Also, you mis-spelled the path for the challenge. It is well-known

And, as @osiris pointed out later, the syntax for your return 301 was wrong and should look like below:

        location /.well-known/acme-challenge/ {
            root /var/www/certbot;
        }
        location / {
            return 301 https://$host$request_uri;
        }

Once you correct that you can remove the location block in your port 443 server for /.well-know/acme-challenge. Your port 443 server block won't see the HTTP Challenge now that it will be handled by the port 80 server block.

These won't fix the "connection refused" problem. But, once you resolve that the above is needed to ensure the root folder matches what you stated in the Certbot command.

3 Likes

Also, shouldn't the second return parameter be just a complete URL? E.g., https://$host$request_uri;? Now there's a space where there, I think, should be a colon.

1 Like

Yes, good eye. I added that fix to my post so is now comprehensive and not potentially mis-leading to others.

3 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.