Our letsencrypt image is great for securely serving web pages and/or reverse proxying services. However, getting the container set up the first time with successful validation can be a challenge if one is having issues with their ports.
This article will focus on troubleshooting port mapping and forwarding. The rest of the set up instructions can be found in our previously published article.
Port Forwarding and Mapping
As described in the previous article, letsencrypt requires port 80 on the public IP (router) to end up at port 80 of the container for
http validation (
duckdns validation methods do not require port mapping/forwarding). And although not required, doing the same with port 443 is highly recommended so one can access their webserver via
https://domain.com (443 is the default port for https).
The easiest and the most straightforward way is to forward ports 80 and 443 on our router to ports 80 and 443 on our docker host IP. Portforward.com is a good resource to find out how to port forward correctly on various routers.
Keep in mind that many routers allow users to select
udp when forwarding ports. HTTP connections are made over
tcp so make sure to select either
both in the settings.
Sometimes, using ports 80 or 443 on the docker host may not be possible due to the host system's gui taking up those ports (ie. Unraid, QNAP, etc.). In those cases, we can go through different ports on the host as long as the outside (wan) ports and the container ports are 80 and 443. For instance, it is OK to forward port 80 on the router to port 81 on the docker host, and map port 81 to port 80 in docker run/create or compose (
-p 81:80). That way the docker host port 80 is not needed, but the requests from the internet at port 80 still end up at port 80 inside the container.
We also need to make sure that our DNS records are correct so that the requests for our domain reach our public IP correctly.
If we own our own domain name, we need to make sure that there is an
A record set for our domain and that it is pointing to our server's public IP. To find out the public IP through commandline, we can do
curl icanhazip.com and it will return our public IP. For any subdomains we would like to use, we need to create
CNAMEs that point to our
A record so they too get directed to our public IP. Certain DNS providers like Cloudflare allow wildcard CNAMES,
*, so any subdomain request gets directed automatically.
If we are using a dynamic dns like DuckDNS, we need to make sure that our custom subdomain is pointing to our public IP. Check on the provider's website to make sure thay have the correct IP address.
If we followed the above steps, but still having issues with either validation or access, there are a few steps we can take.
Unless Let's Encrypt validation is successful, nginx won't be running in our letsencrypt container.
That is by design. Our nginx config includes references to the Let's Encrypt certs and if they do not exist or are not valid, nginx will give an error and refuse to start. So we make sure that the validation process is completed successfully before we start nginx.
Also, http validation does not use nginx and therefore our nginx config does not affect the validation process. Certbot (the official Let's Encrypt client) puts up its own webserver during validation.
If validation is unsuccessful due to connection issues, the best way to check port forwarding and mapping is to fire up an nginx container with the same port mappings, and to try to access our domain.
Let's assume we are using the following compose yaml to create a letsencrypt container and failing:
--- version: "2" services: letsencrypt: image: linuxserver/letsencrypt container_name: letsencrypt cap_add: - NET_ADMIN environment: - PUID=1000 - PGID=1000 - TZ=Europe/London - URL=linuxserver-test.com - SUBDOMAINS=www,ombi - VALIDATION=http volumes: - /home/aptalca/appdata/letsencrypt:/config ports: - 444:443 - 81:80 restart: unless-stopped
We first stop that container with either
docker-compose down letsencrypt or
docker stop letsencrypt. Then we create an nginx container with the same port mappings:
--- version: "2" services: nginx: image: linuxserver/nginx container_name: nginx environment: - PUID=1000 - PGID=1000 - TZ=Europe/London ports: - 444:443 - 81:80 restart: unless-stopped
We don't need to define any folder mappings because this is just a temporary test container and we won't need to preserve its data.
Once started, the nginx container will fire up the nginx service right away and will be listening on both ports 80 and 443.
Now we can test whether our domain is directed to the container correctly.
The best way to test is to do it from outside of our lan because some routers block connections from going out to the internet only to come right back to the same IP (hairpin NAT or NAT loopback).
So let's take a cell phone, turn off wifi and navigate to
https://domain.com. If we see the nginx landing page, we're good (https version will have a browser warning about an invalid cert; that's OK; it's just the self signed cert that comes with our test nginx image). If not, we need to fix our port forwarding and/or mapping, or DNS settings as described above.
If you confirmed that the port forwarding, mapping and DNS entries are all correct but the nginx test method is still not working, your ISP might be blocking ports 80 and/or 443. You should be able to google for reports of that happening with your ISP.
Once fixed, we can stop and remove the nginx container and fire up the letsencrypt container.