diff --git a/docs/guides/ssl/automatic-renewal.md b/docs/guides/ssl/automatic-renewal.md new file mode 100644 index 000000000..b8abc55cc --- /dev/null +++ b/docs/guides/ssl/automatic-renewal.md @@ -0,0 +1,137 @@ +# Automating Certificate Renewal + +## Overview + +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](https://github.com/acmesh-official/acme.sh?tab=readme-ov-file#an-acme-shell-script-acmesh): An ACME shell script. +- [Cloudflare DNS](https://www.cloudflare.com/application-services/products/dns/). +- [Let’s Encrypt](https://letsencrypt.org/). + +## Prerequisites + +- **Pi-hole 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. 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. + +## **1. Install acme.sh as `root`** + +Run a login shell as root: + +```bash +sudo -i +``` + +Install it: + +```bash +curl https://get.acme.sh | sh -s email=my@example.com +``` + +Reload .bashrc to register the acme.sh alias: + +```bash +source .bashrc +``` + +Verify installation: + +```bash +acme.sh --version +``` + +--- + +## **2. Set Up Cloudflare DNS API** + +For **DNS-based domain verification**, export your **Cloudflare API token**: + +```bash +export CF_Token="ofz...xxC" +export CF_Email="me@mydomain.com" +``` + +This allows `acme.sh` to create the required DNS records automatically. + +--- + +## **3. Issue the SSL Certificate for Pi-hole** + +Run: + +```bash +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` (includes `ns1.mydomain.com.cer` + `ca.cer`, in that order) + +You do not need these other certificate files: + +- **Server certificate**: `ns1.mydomain.com.cer` (included in `fullchain.cer`) +- **Intermediate CA cert**: `ca.cer` (included in `fullchain.cer`) + +--- + +## **4. Install and Apply the SSL Certificate to Pi-hole** + +Pi-hole **requires a PEM file** containing **both the private key and server certificate**. + +Install the certificate: + +```bash +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. + +--- + +## **5. Configure Pi-hole** + +To avoid domain mismatch warnings (`CERTIFICATE_DOMAIN_MISMATCH`), set the **correct hostname**: + +```bash +sudo pihole-FTL --config webserver.domain 'ns1.mydomain.com' +sudo service pihole-FTL restart +``` + +Fixes: + +```text +CERTIFICATE_DOMAIN_MISMATCH SSL/TLS certificate /etc/pihole/tls.pem does not match domain pi.hole! +``` + +--- + +## **Notes** + +- Your **certificate renews automatically** via `acme.sh`'s cron job. +- You can manually renew with: + + ```bash + acme.sh --renew -d ns1.mydomain.com --force + ``` + +- To check your certificate: + + ```bash + sudo openssl x509 -in /etc/pihole/tls.pem -text -noout + ``` diff --git a/docs/guides/ssl/self-signed.md b/docs/guides/ssl/self-signed.md new file mode 100644 index 000000000..d4906ff85 --- /dev/null +++ b/docs/guides/ssl/self-signed.md @@ -0,0 +1,283 @@ +# Pi-hole v6: Creating Your Own Self-Signed SSL Certificates + +## Overview + +By default, Pi-hole v6 provides a self-signed SSL certificate, but you can create your own self-signed certificate for Pi-hole that specifies your desired hostnames, fully qualified domain names (FQDN), and IP addresses for your Pi-hole server using **openssl**. + +## Prerequisites + +Install `openssl`: + +```bash +sudo apt update && sudo apt install openssl -y # For Debian/Ubuntu +sudo yum install openssl -y # For RHEL/CentOS +sudo dnf install openssl -y # For Fedora +``` + +This guide assumes: + +- `openssl` is installed on the same machine that Pi-hole is installed on, but this is not a requirement - +`openssl` can be installed on a machine that is not running Pi-hole; `tls.pem` just needs to be copied to `/etc/pihole` on the target machine running Pi-hole. +- All shell commands are executed from the home directory (e.g., `/home/your_user` or `~/`). + +--- + +## Method 1: Use an Internal Certificate Authority CA (Recommended) + +- Pros: All future certificates are trusted once you install the CA cert. +- Cons: Requires setting up a CA. + +**Summary:** Set up a CA, sign certificates for each server, and install only one CA certificate instead of trusting multiple self-signed certificates. + +### Step 1: Create a directory to hold your cert, config, and key files: + +```bash +mkdir -p ~/crt && cd ~/crt +``` + +### Step 2: Create a Certificate Authority (CA) Key and Certificate + +The CA will be used to sign server certificates. + +```bash +openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -days 3650 -keyout homelabCA.key -out homelabCA.crt -subj "/C=US/O=My Homelab CA/CN=MyHomelabCA" +``` + +- `x509`: Generates a self-signed certificate (for a CA). +- `newkey ec`: Creates a new EC key. +- `pkeyopt ec_paramgen_curve:prime256v1`: Uses P-256 curve. +- `nodes`: Skips password protection (optional). +- `-days 3650`: Valid for 10 years. +- `keyout homelabCA.key`: Saves the private key. +- `out homelabCA.crt`: Saves the self-signed CA certificate. +- `subj`: Provides the Distinguished Name (DN) inline: + - `C=US`: Country + - `O=My Homelab CA`: Organization (CA) + - `CN=MyHomelabCA`: Common Name (CA) + +The **CA key** (homelabCA.key) and **CA certificate** (homelabCA.crt) is now ready to be used to sign server certificates. + +### Step 3: Create a Certificate Configuration File (`cert.cnf`) + +```bash +touch cert.cnf && nano cert.cnf +``` + +Add the following content to `~/crt/cert.cnf`: + +```ini +# Country Name (C) +#Organization Name (O) +#Common Name (CN) - Set this to your server’s hostname or IP address. + +# SAN (Subject Alternative Name), [alt-names] is required +# You can add as many hostname and IP entries as you wish + +[req] +default_md = sha256 +distinguished_name = req_distinguished_name +req_extensions = v3_ext +x509_extensions = v3_ext +prompt = no + +[req_distinguished_name] +C = US +O = My Homelab +CN = pi.hole + +[v3_ext] +subjectAltName = @alt_names + +[alt_names] +DNS.1 = pi.hole # Default pihole hostname +DNS.2 = pihole-test # Replace with your server's hostname +DNS.3 = pihole-test.home.arpa # Replace with your server's FQDN +IP.1 = 10.10.10.115 # Replace with your Pi-hole IP +IP.2 = 10.10.10.116 # Another local IP if needed +``` + +### Step 4: Generate a Key and CSR + +Use **Elliptic Curve Digital Signature Algorithm (ECDSA)** to generate both the **private key** (`tls.key`) and **Certificate Signing Request (CSR)** (`tls.csr`). + +```bash +openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -keyout tls.key -out tls.csr -config cert.cnf +``` + +- `-newkey ec`: Creates a new EC key. +- `-pkeyopt ec_paramgen_curve:prime256v1`: Uses P-256 curve. +- `-nodes` - No password on the private key. +- `-keyout tls.key`: Saves the private key. +- `-out tls.csr`: Saves the certificate signing request (CSR). +- `-config cert.cnf`: Uses the config file for CSR details. + +### Step 5: Sign the CSR with the CA + +This generates your server certificate from the CSR. + +```bash +openssl x509 -req -in tls.csr -CA homelabCA.crt -CAkey homelabCA.key -CAcreateserial -out tls.crt -days 365 -sha256 -extfile cert.cnf -extensions v3_ext +``` + +- `-req -in tls.csr`: Uses the Certificate Signing Request (CSR) for signing. +- `-CA homelabCA.crt -CAkey homelabCA.key`: Uses our CA to sign the certificate. +- `-CAcreateserial`:Generates a unique serial number. +- `-out tls.crt`: Saves the signed certificate. +- `-days 365`: Valid for 365 days (1 year). +- `-extfile cert.cnf` -extensions v3_ext → Includes Subject Alternative Names (SAN)s. + +### Step 6: Create a Combined `tls.pem` File + +```bash +cat tls.key tls.crt | tee tls.pem +``` + +### Step 7: [On Pi-hole Server] Remove existing Pi-hole self-signed cert files: + +```bash +sudo rm /etc/pihole/tls* +``` + +### Step 8: [On Pi-hole Server] Copy `tls.pem` (cert+private key) to Pi-hole directory + +```bash +sudo cp tls.pem /etc/pihole +``` + +### Step 9. [On Pi-hole Server] Restart Pi-hole + +```bash +sudo service pihole-FTL restart +``` + +### Step 10: Install `homelabCA.crt` (CA) in Chrome (this is on your client machine running a browser, for example your Windows PC running Chrome) + +Import `homelabCA.crt` into your browser's **Trusted Root Certificate Store** + +- Copy `homelabCA.crt` to your local PC +- Open `chrome://certificate-manager` in Chrome +- Click **Manage Imported Certificates** +- Click **Trusted Root Certification Authorities** +- Click **Import, Next, Finish** + +### Issuing additional server certificates with your CA (Optional) + +You can issue additional certificates for your other servers using the CA you created in **step 2**, and you do not have to re-install the CA certificate in your browser. +Just run the commands listed in **steps 4 and 5** again: + +```bash +openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -keyout tls2.key -out tls2.csr -config cert2.cnf +``` + +```bash +openssl x509 -req -in tls.csr -CA homelabCA.crt -CAkey homelabCA.key -CAcreateserial -out tls2.crt -days 365 -sha256 -extfile cert2.cnf -extensions v3_ext +``` + +--- + +## Method 2: Use a Self-Signed Certificate and Manually Trust It + +- Pros: Simple, no need to set up a CA. +- Cons: Must manually add each self-signed cert to your browser. + +**Summary:** Generate a self-signed certificate and install it in your browser. You must manually trust each certificate, so this is adequate for a single server setup. + +### Step 1: Create a directory to hold your cert, config, and key files: + +```bash +mkdir -p ~/crt && cd ~/crt +``` + +### Step 2: Create a Certificate Configuration File (`cert.cnf`) + +```bash +touch cert.cnf && nano cert.cnf +``` + +Add the following content to `~/crt/cert.cnf`: + +```ini +# Country Name (C) +#Organization Name (O) +#Common Name (CN) - Set this to your server’s hostname or IP address. + +# SAN (Subject Alternative Name), [alt-names] is required +# You can add as many hostname and IP entries as you wish + +[req] +default_md = sha256 +distinguished_name = req_distinguished_name +req_extensions = v3_ext +x509_extensions = v3_ext +prompt = no + +[req_distinguished_name] +C = US +O = My Homelab +CN = pi.hole + +[v3_ext] +subjectAltName = @alt_names + +[alt_names] +DNS.1 = pi.hole # Default pihole hostname +DNS.2 = pihole-test # Replace with your server's hostname +DNS.3 = pihole-test.home.arpa # Replace with your server's FQDN +IP.1 = 10.10.10.115 # Replace with your Pi-hole IP +IP.2 = 10.10.10.116 # Another local IP if needed +``` + +### Step 3: Generate a key and Self-Signed Certificate + +Use **Elliptic Curve Digital Signature Algorithm (ECDSA)** to generate both the **private key** (`tls.key`) and the **Self-Signed Certificate** (`tls.crt`). + +```bash +openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -days 365 -keyout tls.key -out tls.crt -config cert.cnf +``` + +- `x509`: Creates a self-signed certificate. +- `-newkey ec`: Creates a new Elliptic Curve (EC) key. +- `-pkeyopt ec_paramgen_curve:prime256v1`: Uses P-256 (NIST prime256v1) curve. +- `-nodes`: Skips password protection. +- `-days 365`: Valid for 365 days (1 year). +- `-keyout tls.key`: Saves the private key. +- `-out tls.crt`: Saves the self-signed certificate. +- `-config cert.cnf` Uses cert configuration file `cert.cnf` defined above. + +### Step 4: Create a Combined `tls.pem` File + +```bash +cat tls.key tls.crt | tee tls.pem +``` + +### Step 5: [On Pi-hole Server] Remove existing Pi-hole self-signed cert files: + +```bash +sudo rm /etc/pihole/tls* +``` + +### Step 6: [On Pi-hole Server] Copy `tls.pem` (cert+private key) to Pi-hole directory + +```bash +sudo cp tls.pem /etc/pihole +``` + +### Step 7. [On Pi-hole Server] Restart Pi-hole + +```bash +sudo service pihole-FTL restart +``` + +### Step 8: Install `tls.crt` (cert) in Chrome (this is on your client machine running a browser, for example your Windows PC running Chrome) + +Import `tls.crt` into your browser's **Trusted Root Certificate Store** + +- Copy `tls.crt` to your local PC +- Open `chrome://certificate-manager` in Chrome +- Click **Manage Imported Certificates** +- Click **Trusted Root Certification Authorities** +- Click **Import, Next, Finish** + +## Installation of Self-Signed Certs for Mobile Devices + +- See: Pi-hole API > [TLS/SSL](../../api/tls.md) diff --git a/mkdocs.yml b/mkdocs.yml index a289100fc..f81e78007 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -203,6 +203,9 @@ nav: - 'Optional: Full and DNS-only': guides/vpn/openvpn/dual-VPN.md - 'Optional: Dynamic DNS': guides/vpn/openvpn/dynDNS.md - 'Troubleshooting': guides/vpn/openvpn/troubleshooting.md + - 'TLS/SSL': + - 'Creating Your Own Self-Signed SSL Certificates': guides/ssl/self-signed.md + - 'Automating Certificate Renewal': guides/ssl/automatic-renewal.md - 'Misc': - 'Home Assistant': guides/misc/homeassistant.md - 'Benchmarking': guides/misc/benchmark.md