Obtaining Let's Encrypt certificate using Cloudflare
Introduction
HTTPS is the current standard for secure access to webpages, even in your homelab environment. However, most self-hosted applications by default use HTTP. To enable HTTPS you can use self-signed certificates, but then when accessing application, you will be prompted to trust self-signed certificate. On some devices like Android, this can be very troublesome because you need to trust self-signed certificate every time you open webpage. To solve this problem you need to add RootCA certificate to the system, which is also a troublesome process. Less troublesome solution is to use Let's Encrypt certificates. In this post, I will show you how to obtain such certificate for single host in your homelab.
UPDATE 2025-11-15: Added paragraph "Bonus - Copying certificates" at the end of article describing how to auto copy certificates to other directories.
OS used: Debian 12
Software used: certbot 2.1.0
Source
- Official Certbot documentation
- Official certbot-dns-cloudflare plugin documentation
Prerequisites
For Let's Encrypt to work with the instructions in this post, you will need:
- Have a domain - Buy one that you like or if you don't want to pay you can use free and popular DuckDNS. DuckDNS can be used to obtain Let's Encrypt certificates without the need of Cloudflare, but it is out of scope of this tutorial.
- Create free Cloudflare account - This instruction is written for use with Cloudflare free account.
- Router with DNS server or DNS server in local network for example Pi-hole.
Let's Encrypt information
Most popular application to get certificates from Let's Encrypt is called certbot. certbot can work in different modes to get certificates:
- HTTP challenge/response -
certbotstarts its own web server which is used for obtaining certificates. For this method to work, you need to have port80open and forwarded to your server. This limits to only onecertbotrunning in your network (because of port forwarding on your router) and it's on you how to distribute obtained certificates to one or more hosts. - DNS challenge/response - Validation for obtaining certificates is put in TXT field of a DNS record. So
certbotneeds to edit the DNS record, which is why you need a DNS provider with a supported API for this to work.
Note
You can read more about different challenge types here Let's Encrypt documentation - Challenge Types.
Installing certbot
Install cerbot on the server where you want to obtain certificates.
$ sudo apt install certbot python3-certbot-dns-cloudflare
Automatic renewal of certificates
Let's Encrypt certificates are issued for 3 months. After that you need to get new certificates. Debian certbot package automatically creates systemd timer that checks for new certificate twice a day. Timer location is /lib/systemd/system/certbot.timer.
You can list systemd timer with command:
$ systemctl list-timers
Cloudflare configuration with your domain
Log in to Cloudflare and perform following actions (this instruction will assume that your domain is example.com).
Cloudflare DNS
Add your domain to Cloudflare:
- Click
Home> clickAdd site>for example example.com> clickAdd site - Click
DNS> click button at the bottomContinue> find entryCloudflare's nameservers> enter those nameservers where you bought your domain - In Cloudflare dashboard enter your added site
- Click
DNS>Records> clickAdd record: - Create
ADNS record:Type: AName:- for example myservername.homelabIPv4 address:127.0.0.1- to annoy script kiddies pinging your host, DNS record on Cloudflare is only needed for obtaining certificate, IP address resoultion will be performed on your local DNS serverProxy: disable
Cloudflare API Token
You need Cloudflare API Token for certbot to be able to modify TXT field of your DNS record.
- Click Avatar in right top corner >
My Profile>API Tokens> clickCreate Token>Create Custom Token: Token name- enter name for your TokenPermissions- create 2 entries and set following values in fields:- Zone | Zone | Read
- Zone | DNS | Edit
Zone Resources- set following- Include | Specific zone | chose your zone created earlier
- Example: Include | Specific zone | example.com
Client IP Address Filtering- if you have dynamic Public IP you can leave it emptyTTL- leave empty for Token to be valid forever- Click
Continue to summary> clickCreate Token - Copy Token - Token will be shown only once, if you loose it, delete it and generate new Token
- Create credentials file with text editor on your server and enter there obtained Token:
$ sudo mkdir -m 700 -p /root/certbot && \
sudo vim /root/certbot/cloudflare.ini
-m 700 - rwx --- --- permissions for /root/certbot directory
dns_cloudflare_api_token = <put-your-token-here>
- Secure the file:
$ sudo chmod 600 /root/certbot/cloudflare.ini
DNS server configuration
Enter your domain name and IP address in your local DNS server, for example:
DNS A record: myservername.homelab.example.com | IPv4 address: 192.168.1.46.
Obtain certificate
Obtain a certificate:
$ sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /root/certbot/cloudflare.ini \
-d "myservername.homelab.example.com"
After running this command you will need to:
- Enter email address used for urgent notices from Let's Encrypt
- Accept Let's Encrypt Terms of Service
- Answer it you want to receive emails from Electronic Frontier Foundation (organization that develops
certbot)
Certificates
Obtained certificates will be put in folder: /etc/letsencrypt/live/<your_domain_name>/
Command to list certificates:
$ sudo certbot certificates
Now you can reference the certificate in application's configuration, create a symbolic link to it, or copy it, according to the documentation of web application you will be using with HTTPS. If you copy the certificate, remember to do this periodically with a script because the certificate is valid only for 90 days and after that time is automatically renewed by certbot in its original location.
Bonus - Copying certificates
Following instruction demonstrates how to auto copy obtained certificate to other directory. It is needed for Docker because containers can't read symlinks which certbot uses in certificate folder (/etc/letsencrypt/live/). To auto copy certificate we will use the fact that certificate renewal command is run 2 times per day by certbot.timer (which invokes certbot.service) and certbot has option to run command after successful certificate renewal. Both timer and service are located in /usr/lib/systemd/system/.
Create script file in /etc/letsencrypt/renewal-hooks/deploy/ folder that will be run after a successful certificate renewal:
$ sudo vim /etc/letsencrypt/renewal-hooks/deploy/copy-certificate
cp /etc/letsencrypt/live/<your_domain_name>/fullchain.pem /path/to/folder/certificate.crt
cp /etc/letsencrypt/live/<your_domain_name>/privkey.pem /path/to/folder/private.key
path/to/folder - enter path where to copy certificate and certificate private key
Make file executable:
$ sudo chmod 744 /etc/letsencrypt/renewal-hooks/deploy/copy-certificate
Force certificate renewal:
$ sudo certbot renew --force-renewal
Check if certificate and certificate private key was copied to specified folder:
$ ls -la /path/to/folder/<your_domain_name>/