From 03e8a331643f6224a1991b35e9a9ec483a862b61 Mon Sep 17 00:00:00 2001 From: Christian Kaczmarek Date: Sun, 17 Aug 2025 20:25:39 -0600 Subject: [PATCH 1/2] Add TLS certificate guides for Pi-hole - Add automatic SSL certificate renewal guide using acme.sh + Let's Encrypt * Covers Cloudflare DNS validation setup * Includes certificate installation and Pi-hole configuration * Documents automatic renewal via cron jobs - Add self-signed SSL certificate creation guide * Method 1: Internal CA approach for multiple servers (recommended) * Method 2: Direct self-signed certificates for single server * Includes Subject Alternative Names (SAN) configuration * Covers browser certificate installation steps These guides are adapted from my existing GitHub Gists: - Automatic renewal: https://gist.github.com/kaczmar2/17f02a0ddb59a7d336b20376695797c6 - Self-signed certs: https://gist.github.com/kaczmar2/e1b5eb635c1a1e792faf36508c5698ee Both guides provide step-by-step instructions for different deployment scenarios. Fix Pi-hole branding in new guides. Signed-off-by: Christian Kaczmarek --- docs/guides/ssl/automatic-renewal.md | 118 +++++++++++++ docs/guides/ssl/self-signed.md | 254 +++++++++++++++++++++++++++ mkdocs.yml | 3 + 3 files changed, 375 insertions(+) create mode 100644 docs/guides/ssl/automatic-renewal.md create mode 100644 docs/guides/ssl/self-signed.md diff --git a/docs/guides/ssl/automatic-renewal.md b/docs/guides/ssl/automatic-renewal.md new file mode 100644 index 000000000..bd1a7409b --- /dev/null +++ b/docs/guides/ssl/automatic-renewal.md @@ -0,0 +1,118 @@ +# 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: +``` +sudo -i +``` + +Install it: +```bash +curl https://get.acme.sh | sh -s email=my@example.com +``` + +Reload .bashrc to register the acme.sh alias: +``` +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: +``` +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..b3974bb05 --- /dev/null +++ b/docs/guides/ssl/self-signed.md @@ -0,0 +1,254 @@ +# 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`: +``` +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 mahcine 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: +``` +mkdir -p ~/crt && cd ~/crt +``` + +### Step 2: Create a Certificate Authority (CA) Key and Certificate + +The CA will be used to sign server certificates. + +``` +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`) + +``` +touch cert.cnf && nano cert.cnf +``` + +Use the attached [cert.cnf](https://gist.github.com/kaczmar2/e1b5eb635c1a1e792faf36508c5698ee#file-cert-cnf) file as a template: +```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`). +``` +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. +``` +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 +``` +cat tls.key tls.crt | tee tls.pem +``` + +### Step 7: [On Pi-hole Server] Remove existing Pi-hole self-signed cert files: +``` +sudo rm /etc/pihole/tls* +``` + +### Step 8: [On Pi-hole Server] Copy `tls.pem` (cert+private key) to Pi-hole directory +``` +sudo cp tls.pem /etc/pihole +``` + +### Step 9. [On Pi-hole Server] Restart Pi-hole +``` +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: + +``` +openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -keyout tls2.key -out tls2.csr -config cert2.cnf +``` +``` +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: +``` +mkdir -p ~/crt && cd ~/crt +``` + +### Step 2: Create a Certificate Configuration File (`cert.cnf`) + +``` +touch cert.cnf && nano cert.cnf +``` + +Use the attached [cert.cnf](https://gist.github.com/kaczmar2/e1b5eb635c1a1e792faf36508c5698ee#file-cert-cnf) file as a template: +```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`). +``` +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 +``` +cat tls.key tls.crt | tee tls.pem +``` + +### Step 5: [On Pi-hole Server] Remove existing Pi-hole self-signed cert files: +``` +sudo rm /etc/pihole/tls* +``` + +### Step 6: [On Pi-hole Server] Copy `tls.pem` (cert+private key) to Pi-hole directory +``` +sudo cp tls.pem /etc/pihole +``` + +### Step 7. [On Pi-hole Server] Restart Pi-hole +``` +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 From 4fd65ff3510d96bee8df249fd79caf5632d36983 Mon Sep 17 00:00:00 2001 From: Christian Kaczmarek Date: Sun, 17 Aug 2025 21:48:35 -0600 Subject: [PATCH 2/2] Fix markdown linting errors Signed-off-by: Christian Kaczmarek --- docs/guides/ssl/automatic-renewal.md | 39 ++++++++++---- docs/guides/ssl/self-signed.md | 81 +++++++++++++++++++--------- 2 files changed, 84 insertions(+), 36 deletions(-) diff --git a/docs/guides/ssl/automatic-renewal.md b/docs/guides/ssl/automatic-renewal.md index bd1a7409b..b8abc55cc 100644 --- a/docs/guides/ssl/automatic-renewal.md +++ b/docs/guides/ssl/automatic-renewal.md @@ -12,33 +12,38 @@ This guide uses: ## 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`). +- **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. + +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 ``` @@ -46,40 +51,48 @@ 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 cat fullchain.cer ns1.mydomain.com.key | sudo tee /etc/pihole/tls.pem && \\ sudo service pihole-FTL restart" ``` @@ -92,6 +105,7 @@ This: --- ## **5. Configure Pi-hole** + To avoid domain mismatch warnings (`CERTIFICATE_DOMAIN_MISMATCH`), set the **correct hostname**: ```bash @@ -99,20 +113,25 @@ sudo pihole-FTL --config webserver.domain 'ns1.mydomain.com' sudo service pihole-FTL restart ``` -Fixes: -``` +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 index b3974bb05..5d4185f18 100644 --- a/docs/guides/ssl/self-signed.md +++ b/docs/guides/ssl/self-signed.md @@ -7,7 +7,8 @@ By default, Pi-hole v6 provides a self-signed SSL certificate, but you can creat ## 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 @@ -15,19 +16,22 @@ 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` 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 mahcine 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 ``` @@ -35,9 +39,10 @@ mkdir -p ~/crt && cd ~/crt 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. @@ -54,11 +59,12 @@ The **CA key** (homelabCA.key) and **CA certificate** (homelabCA.crt) is now rea ### Step 3: Create a Certificate Configuration File (`cert.cnf`) -``` +```bash touch cert.cnf && nano cert.cnf ``` Use the attached [cert.cnf](https://gist.github.com/kaczmar2/e1b5eb635c1a1e792faf36508c5698ee#file-cert-cnf) file as a template: + ```ini # Country Name (C) #Organization Name (O) @@ -93,9 +99,11 @@ 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. @@ -106,9 +114,11 @@ openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -keyout ### 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. @@ -117,64 +127,75 @@ openssl x509 -req -in tls.csr -CA homelabCA.crt -CAkey homelabCA.key -CAcreatese - `-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** + +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** +- 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. + +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 ``` Use the attached [cert.cnf](https://gist.github.com/kaczmar2/e1b5eb635c1a1e792faf36508c5698ee#file-cert-cnf) file as a template: + ```ini # Country Name (C) #Organization Name (O) @@ -207,10 +228,11 @@ 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`). -``` -openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -days 365 -keyout tls.key -out tls.crt -config cert.cnf +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. @@ -223,27 +245,33 @@ openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -nodes -days - `-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** + +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** @@ -251,4 +279,5 @@ Import `tls.crt` into your browser’s **Trusted Root Certificate Store** - Click **Import, Next, Finish** ## Installation of Self-Signed Certs for Mobile Devices + - See: Pi-hole API > [TLS/SSL](../../api/tls.md)