# Enabling HTTPS for your Pi-hole Web Interface with LE and CF DNS

**URL:** <https://discourse.pi-hole.net/t/enabling-https-for-your-pi-hole-web-interface-with-le-and-cf-dns/79526>\
**Category:** Community How-to's\
**Created:** [April 29, 2025, 5:38pm UTC](https://discourse.pi-hole.net/t/enabling-https-for-your-pi-hole-web-interface-with-le-and-cf-dns/79526 "2025-04-29T17:38:50Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Grandy](https://discourse-cdn.pi-hole.net/user_avatar/discourse.pi-hole.net/grandy/32/49606_2.png) [@Grandy](https://discourse.pi-hole.net/u/Grandy)\
**Post date:** [April 29, 2025, 5:38pm UTC](https://discourse.pi-hole.net/t/enabling-https-for-your-pi-hole-web-interface-with-le-and-cf-dns/79526/1 "2025-04-29T17:38:50Z")

</div>

Hello. I'd like to share information about installing an SSL LE (Let's Encrypt) certificate using CF (Cloudflare) DNS for a Pi-hole web server, based on how I did it. Perhaps this option will be useful to someone. P.S. I spent a lot of time searching for information, trying, and making mistakes, but nothing worked out.

Let's assume you already have the server and Pi-hole properly installed and configured, and you have SSH access (e.g., via PuTTY), but you want to add an auto-updating certificate to it. All steps were performed via PuTTY, and I had already added a Local DNS record in Pi-hole for the domain beforehand.

## Obtaining a Cloudflare API Token for Certbot

Before starting the installation, you will need to generate a Cloudflare API token with the necessary permissions to manage DNS records. This token will allow Certbot to automatically pass domain validation.

1. Log in to your Cloudflare dashboard.
2. Navigate to "My Profile" in the top right corner.
3. Select the "API Tokens" tab.
4. Click the "Create Token" button.
5. Find the "API Token Templates" section and choose the "Edit DNS records" template, or create a "Create Custom Token".
6. If you are creating a custom token, set the **following permissions** : 
  - **Permissions:**
    - Zone → DNS → **Edit**
    - Zone → DNS → **Read**

  - **Zone Resources:** Include → Specific zone → Select your domain for which you are requesting the certificate. _It is recommended to restrict the token to only the necessary domain for security._

7. Give the token a descriptive name, for example, "Certbot DNS CF".
8. Click "Continue to summary", then "Create Token".
9. **Important:** Copy the generated token. It will be shown only **once**. Store it securely; you will need it to create the credentials file in the following steps. Treat it like a password.

## Installation and Configuration

Now that you have the token, you can proceed with the installation and configuration:

1. Install Certbot and the Cloudflare plugin: 

```
sudo apt update
sudo apt install certbot python3-certbot-dns-cloudflare -y
```

2. Create a directory for secrets and the credentials file: 

```
sudo mkdir -p ~/.secrets
sudo nano ~/.secrets/cloudflare.ini
```

3. Add the content to `cloudflare.ini` and save (using the token copied in the previous step): 

```
dns_cloudflare_api_token = your_copied_token
```

_(To save in nano: Ctrl+O, Enter, Ctrl+X)_

4. Set strict permissions for the credentials file: 

```
sudo chmod 600 ~/.secrets/cloudflare.ini
```

5. Request the certificate (replace `your.domain.com` with your actual domain): 

```
sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials ~/.secrets/cloudflare.ini \
  -d your.domain.com \
  -d *.your.domain.com # Optional, for a Wildcard certificate
```

6. Change the ports that the Pihole-FTL web server will use: 

```
sudo nano /etc/pihole/pihole.toml
```

Change the value for the `port` parameter. Find the `[webserver]` section and change or add the line `port = "127.0.0.1:8080,[::1]:8080"`.

```
[webserver]
port = "127.0.0.1:8080,[::1]:8080"
```

_(To save in nano: Ctrl+O, Enter, Ctrl+X)_

7. Restart pihole-FTL: 

```
systemctl restart pihole-FTL
```

8. Install nginx. Follow the instructions for your OS on the page: [https://nginx.org/en/linux\_packages.html](https://nginx.org/en/linux_packages.html)

(This usually involves adding a repository and then installing via `sudo apt update && sudo apt install nginx`)

9. Create a folder for generating the DH Key and generate the key: 

```
sudo mkdir /etc/nginx/ssl
sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048
```

10. Create and save the site configuration for Nginx (replace `your.domain.com` with your actual domain): 

```
sudo nano /etc/nginx/conf.d/your.domain.com.conf
```

```
server {
    listen 80;
    server_name your.domain.com; # Replace with your domain
    return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name your.domain.com; # Replace with your domain
add_header X-Robots-Tag "noindex, nofollow";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=(), fullscreen=(), payment=(), interest-cohort=()" always;

ssl_certificate /etc/letsencrypt/live/your.domain.com/fullchain.pem; # Replace with path to your certificate (your domain)
ssl_certificate_key /etc/letsencrypt/live/your.domain.com/privkey.pem; # Replace with path to your private key (your domain)
ssl_dhparam /etc/nginx/ssl/dhparam.pem;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE+AESGCM:CHACHA20:DHE+AESGCM:!aNULL:!eNULL:!LOW:!SSLv2:!SSLv3:!MD5:!RC4:!3DES';
ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1:x448;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
ssl_early_data off;
ssl_buffer_size 8k;

location ~ /\. {
    deny all;
}

location = / {
    return 301 /admin/;
}

location / {
    proxy_pass http://127.0.0.1:8080/;
    proxy_set_header Host $host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Connection "upgrade";
    proxy_hide_header X-Powered-By;
    proxy_hide_header Server;
    proxy_http_version 1.1;
    proxy_buffering off;
    # proxy_ssl_verify off; # Usually not needed when proxying to localhost HTTP
    proxy_connect_timeout 10s;
    proxy_send_timeout 30s;
    proxy_read_timeout 30s;
}

```

  

_(To save in nano: Ctrl+O, Enter, Ctrl+X)_

11. Check the nginx configuration: 

```
sudo nginx -t
```

12. Reload nginx: 

```
sudo systemctl reload nginx
```

13. After these steps, the Pi-hole web interface opens via the domain using the LE certificate for me.

---

<div class="post-metadata">

**Author:** ![samvv](https://discourse-cdn.pi-hole.net/user_avatar/discourse.pi-hole.net/samvv/32/56406_2.png) [@samvv](https://discourse.pi-hole.net/u/samvv)\
**Post date:** [September 30, 2026, 2:09pm UTC](https://discourse.pi-hole.net/t/enabling-https-for-your-pi-hole-web-interface-with-le-and-cf-dns/79526/2 "2026-09-30T14:09:31Z")

</div>

Just wanted to add that this can be made a bit more 'lightweight' by skipping the installation of nginx and directly installing the certificate in Pihole.

1. Add a Certbot renew hook to **/etc/letsencrypt/renewal-hooks/deploy/pihole-cert.sh**

```auto
#!/bin/bash
DOMAIN="yourdomain.com" # UPDATE THIS
CERT_DIR="/etc/letsencrypt/live/$DOMAIN"
DEST_FILE="/etc/pihole/tls.pem"

# Check if the certificates exist for the domain
if [-d "$CERT_DIR"]; then
    # 1. Combine fullchain and private key into a single PEM file (required by Pi-hole)
    cat "$CERT_DIR/fullchain.pem" "$CERT_DIR/privkey.pem" > "$DEST_FILE"

    # 2. Grant ownership to the pihole user and restrict access to 600
    chown pihole:pihole "$DEST_FILE"
    chmod 600 "$DEST_FILE"

    # 3. Restart Pi-hole FTL service to load the new certificate
    systemctl restart pihole-FTL
fi

```

1. Make the script executable:

```auto
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/pihole-cert.sh

```

1. Execute the hook once:

```auto
sudo /etc/letsencrypt/renewal-hooks/deploy/pihole-cert.sh

```

Done! Now the certificate will automatically be deployed to Pihole!

Note that for this to work `webserver.tls.cert` must be set to `/etc/pihole/tls.pem`, which is the default.
