A Certbot webroot challenge is useful when an existing public HTTP site must keep serving traffic while ACME validation runs. Certbot writes a temporary challenge file below the site's document root, and the certificate authority must retrieve that exact file through the requested hostname on port 80.
The webroot plugin is an authenticator, not an installer. It can obtain certificate files under /etc/letsencrypt/live without stopping the web server or editing Nginx or Apache, but the web server configuration still needs to serve the challenge path during issuance and use the resulting certificate paths afterward.
The examples use one webroot for site.example.net and www.site.example.net. When hostnames use different document roots, place the matching -w option before the -d names that belong to that root, and use a DNS-01 challenge instead for wildcard names, private-only services, or sites where port 80 cannot be reached from the public Internet.
Related: Use a DNS challenge with Certbot
Related: Install a Certbot certificate for Nginx
Steps to use a Certbot webroot challenge:
- Confirm that each hostname resolves to the server that serves the HTTP site.
$ getent ahosts site.example.net 203.0.113.10 STREAM site.example.net 203.0.113.10 DGRAM 203.0.113.10 RAW
If the name also has an .AAAA record, that IPv6 address must serve the same challenge path or HTTP-01 validation can fail over IPv6.
- Confirm that the site answers over plain HTTP on port 80.
$ curl -I http://site.example.net/ HTTP/1.1 200 OK Server: nginx/1.28.0 ##### snipped #####
HTTP-01 starts on port 80. Redirects can work when they preserve the challenge URL and stay on ports 80 or 443, but redirects to login pages, other hosts, or blocked hidden directories will fail validation.
- Identify the document root used by the active virtual host.
$ sudo nginx -T nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful # configuration file /etc/nginx/sites-enabled/site.example.net: server { listen 80; server_name site.example.net www.site.example.net; root /var/www/site.example.net; } ##### snipped #####Use the directory served by the matching virtual host. On Apache, this is usually the matching DocumentRoot instead of the Nginx root directive.
- Create the challenge directory inside the webroot.
$ sudo mkdir -p /var/www/site.example.net/.well-known/acme-challenge
Certbot can create its own challenge files, but creating the directory first exposes hidden-directory and permission problems before the ACME request.
- Write a probe file into the challenge directory.
$ printf 'challenge-ok\n' | sudo tee /var/www/site.example.net/.well-known/acme-challenge/probe-token challenge-ok
- Request the probe file through the public challenge URL.
$ curl http://site.example.net/.well-known/acme-challenge/probe-token challenge-ok
The body should be only the probe text. Repeat the check from outside the origin network when a load balancer, CDN, WAF, or separate IPv6 listener can change the route.
Tool: ACME HTTP 01 Readiness Validator - Confirm that Certbot has the webroot authenticator.
$ sudo certbot plugins Saving debug log to /var/log/letsencrypt/letsencrypt.log ##### snipped ##### * webroot Description: Saves the necessary validation files to a .well-known/acme-challenge/ directory within the nominated webroot path. A separate HTTP server must be running and serving files from the webroot path. HTTP challenge only (wildcards not supported). Interfaces: Authenticator, Plugin ##### snipped #####
- Rehearse the certificate request with the staging service.
$ sudo certbot certonly --webroot -w /var/www/site.example.net -d site.example.net -d www.site.example.net -m admin@example.net --agree-tos --non-interactive --dry-run Saving debug log to /var/log/letsencrypt/letsencrypt.log Simulating a certificate request for site.example.net and www.site.example.net The dry run was successful.
For domains served from different document roots, place the matching -w option before the -d names that use that webroot. --dry-run uses the staging service and does not save a production certificate.
Related: Use the Certbot staging environment
- Request the production certificate after the dry run succeeds.
$ sudo certbot certonly --webroot -w /var/www/site.example.net -d site.example.net -d www.site.example.net -m admin@example.net --agree-tos --non-interactive Saving debug log to /var/log/letsencrypt/letsencrypt.log Requesting a certificate for site.example.net and www.site.example.net Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/site.example.net/fullchain.pem Key is saved at: /etc/letsencrypt/live/site.example.net/privkey.pem
This command obtains the certificate only. Install /etc/letsencrypt/live/site.example.net/fullchain.pem and /etc/letsencrypt/live/site.example.net/privkey.pem in the web server configuration before expecting HTTPS traffic to use the new certificate.
- Confirm that Certbot recorded the certificate with the expected names.
$ sudo certbot certificates --cert-name site.example.net Saving debug log to /var/log/letsencrypt/letsencrypt.log Found the following certs: Certificate Name: site.example.net Domains: site.example.net www.site.example.net Expiry Date: 2026-09-10 12:00:00+00:00 (VALID: 89 days) Certificate Path: /etc/letsencrypt/live/site.example.net/fullchain.pem Private Key Path: /etc/letsencrypt/live/site.example.net/privkey.pem - Test renewal with the saved webroot configuration.
$ sudo certbot renew --cert-name site.example.net --dry-run Saving debug log to /var/log/letsencrypt/letsencrypt.log Processing /etc/letsencrypt/renewal/site.example.net.conf Congratulations, all simulated renewals succeeded: /etc/letsencrypt/live/site.example.net/fullchain.pem (success)
A successful renewal dry run confirms that Certbot can reuse the saved webroot authenticator and challenge path later.
Related: Test Certbot certificate renewal
Related: Check the Certbot renewal timer - Remove the temporary probe file.
$ sudo rm /var/www/site.example.net/.well-known/acme-challenge/probe-token
Certbot removes its own ACME challenge files after validation. Removing the manual probe keeps the challenge directory from serving stale test content.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.