See my other guides for SSL certificates on Pi-hole v6:
Pi-hole v6 introduces changes to its web server:
- Embedded Web Server – Pi-hole no longer relies on
lighttpd
. - TLS Configuration – Certificates must be in PEM format containing both the private key and certificate.
By default, Pi-hole v6 provides a self-signed SSL certificate, but you can automate certificate renewal with acme.sh, Cloudflare and Let's Encrypt.
This guide uses:
- acme.sh: An ACME shell script.
- Cloudflare DNS.
- Let’s Encrypt.
- Pi-hole v6 installed and running on your system.
- A Cloudflare account that manages your domain’s DNS records.
- Control of a registered domain (e.g.,
mydomain.com
).
These prerequisites ensure that you can successfully request and install an SSL certificate using Cloudflare DNS validation with acme.sh
.
This guide uses Cloudflare DNS and Let’s Encrypt. These instructions can be adapted for any DNS provider and Certificate Authority (CA) that acme.sh
supports, including ZeroSSL. Simply update the --dns
and --server
flags accordingly when issuing your certificate.
Note: This guide assumes that acme.sh
runs under the root
user. The --reloadcmd
contains commands that require sudo
,
such as removing old certificates, writing the new certificate, and restarting Pi-hole FTL. If you prefer to run acme.sh
as a
regular user, additional configuration is required to allow these commands to execute without a password. Methods for achieving
this, such as configuring sudo
rules, are beyond the scope of this article.
Run a login shell as root:
sudo -i
Install it:
curl https://get.acme.sh | sh -s [email protected]
Reload .bashrc to register the acme.sh alias:
source .bashrc
Verify installation:
acme.sh --version
For DNS-based domain verification, export your Cloudflare API token:
export CF_Token="ofz...xxC"
export CF_Email="[email protected]"
This allows acme.sh
to create the required DNS records automatically.
Run:
acme.sh --issue --dns dns_cf -d ns1.mydomain.com --server letsencrypt
This generates:
- Private key:
ns1.mydomain.com.key
- Full-chain certificate:
fullchain.cer
(includesns1.mydomain.com.cer
+ca.cer
, in that order)
You do not need these other certificate files:
- Server certificate:
ns1.mydomain.com.cer
(included infullchain.cer
) - Intermediate CA cert:
ca.cer
(included infullchain.cer
)
Pi-hole requires a PEM file containing both the private key and server certificate.
Install the certificate:
acme.sh --install-cert -d ns1.mydomain.com \
--reloadcmd "sudo rm -f /etc/pihole/tls* && \
sudo cat fullchain.cer ns1.mydomain.com.key | sudo tee /etc/pihole/tls.pem && /
sudo service pihole-FTL restart"
This:
- Deletes old certificates (
/etc/pihole/tls*
). - Creates
tls.pem
with both the full-chain certificate file and private key, in that order. - Restarts Pi-hole FTL to apply the new certificate.
To avoid domain mismatch warnings (CERTIFICATE_DOMAIN_MISMATCH
), set the correct hostname:
sudo pihole-FTL --config webserver.domain 'ns1.mydomain.com'
sudo service pihole-FTL restart
Fixes:
CERTIFICATE_DOMAIN_MISMATCH SSL/TLS certificate /etc/pihole/tls.pem does not match domain pi.hole!
- Your certificate renews automatically via
acme.sh
's cron job. - You can manually renew with:
acme.sh --renew -d ns1.mydomain.com --force
- To check your certificate:
sudo openssl x509 -in /etc/pihole/tls.pem -text -noout
Hey thanks for responding, I am not getting an error the problem is the chrome just will not accept the certificate, it looks valid but pihole v6 is responding with an SSL protocol error, which is strange