Certbot
What is Certbot?
Certbot is the standard client for Let's Encrypt, issuing free, automated TLS/SSL certificates. Laradock runs it as a one-shot container that requests a certificate via the HTTP-01 "webroot" challenge, it doesn't serve traffic itself, it just proves domain ownership through your existing web server and writes out the certificate files.
Start Certbot
docker compose up -d certbot
Certbot needs a domain that already resolves to your server and a web server (nginx, apache2, or caddy) listening on port 80 to serve the challenge, since the webroot method requires Let's Encrypt to fetch a file over plain HTTP before it will issue a certificate.
Stop Certbot
docker compose stop certbot
Certbot's run-certbot.sh runs once at container start and then the container just sleeps, so stopping it is safe at any time and doesn't affect certificates already issued.
Configuration
certbot/defaults.env is empty. The two values Certbot needs, domain and email, are hardcoded directly in certbot/compose.yml:
environment:
- CN="fake.domain.com"
Edit certbot/compose.yml and replace CN with your real domain and EMAIL with your real address, then rebuild:
docker compose build certbot
How the certificate is issued
certbot/Dockerfile builds on phusion/baseimage:bionic-1.0.0, installs the letsencrypt apt package, and runs certbot/run-certbot.sh as its entrypoint:
letsencrypt certonly --webroot -w /var/www/letsencrypt -d "$CN" --agree-tos --email "$EMAIL" --non-interactive --text
/var/www/letsencrypt inside the container is bind-mounted from ./certbot/letsencrypt/ on your host. For the challenge to succeed, your web server must serve that same folder at http://your-domain/.well-known/acme-challenge/. Laradock's shipped nginx/sites/*.conf files already include that location block pointing at /var/www/letsencrypt/, but as of this writing nginx/compose.yml does not itself mount ./certbot/letsencrypt/ into the nginx container, so you need to add that volume mapping to nginx/compose.yml (or your apache2/caddy equivalent) yourself before Certbot's challenge can be reached.
On success, run-certbot.sh copies the issued files into ./data/certbot/certs/ on your host:
<domain>-cert1.pemchain1.pemfullchain1.pem<domain>-privkey1.pem
Point your web server's SSL config at those files.
Common issues
- Challenge fails / "Invalid response" from Let's Encrypt. Almost always means the web server isn't serving
./certbot/letsencrypt/at/.well-known/acme-challenge/on port 80, or the domain doesn't resolve to this server yet. Confirm the volume mapping and DNS before retrying. - Still using
fake.domain.com/[email protected]. These are placeholders incertbot/compose.yml. Certbot will fail (or issue a cert nobody can use) until you set them to real values and rebuild. - Rate limited by Let's Encrypt. Let's Encrypt caps retries per domain per week. Test with their staging environment first if you're iterating on config, this Dockerfile's script doesn't include a
--stagingflag by default, so you'd need to add one temporarily. - Certificate doesn't renew automatically.
run-certbot.shonly runs once, at container start, it doesn't set up a renewal cron. Re-rundocker compose up -d certbot(ordocker compose restart certbot) periodically, or wire up your own renewal schedule.
Pair this with nginx or Apache2 to actually serve HTTPS traffic. New to Laradock? Start at Getting Started.