How to Renew GitLab SSL Certificates in a Proxmox LXC with Certbot and Cloudflare DNS
Running GitLab inside a Proxmox LXC container based on a TurnKey Linux template is an efficient, resource-friendly way to self-host your DevOps platform. But managing SSL certificates securely is critical — especially if your GitLab runs behind Cloudflare’s reverse proxy.
In this guide, we’ll configure Certbot with Cloudflare DNS validation so that GitLab can automatically renew SSL certificates even if port 80 or 443 isn’t directly accessible.
💡 You’ll Learn How To:Configure Certbot for Cloudflare DNS validationUse deploy hooks to reload GitLab automaticallyManage SSL certificates in an LXC container on Proxmox
✅ Step 1: Access Your Proxmox LXC
On your Proxmox host, find your GitLab container ID and enter it:
pct enter <container-id>
Confirm GitLab is running:
sudo gitlab-ctl status
If you’re using the TurnKey Linux GitLab template, GitLab CE and its built-in NGINX are preinstalled.
✅ Step 2: Install Certbot and Cloudflare Plugin
Inside the container:
sudo apt update
sudo apt install certbot python3-certbot-dns-cloudflare -y
This installs Certbot and the Cloudflare DNS plugin, allowing you to use DNS-01 validation for Let’s Encrypt.
✅ Step 3: Create Cloudflare API Credentials
On your Cloudflare dashboard:
- Go to My Profile → API Tokens → Create Token
- Use the “Edit zone DNS” template
- Restrict it to your domain (e.g.,
example.com) - Copy the token
Then, on your container, create a credentials file:
sudo mkdir -p /etc/letsencrypt
sudo nano /etc/letsencrypt/cloudflare.ini
Add:
dns_cloudflare_api_token = <YOUR_CLOUDFLARE_API_TOKEN>
Secure it:
sudo chmod 600 /etc/letsencrypt/cloudflare.ini
✅ Step 4: Obtain the Initial Certificate
Stop GitLab’s internal NGINX to free port 443 if it’s running:
sudo gitlab-ctl stop nginx
Request your certificate via Cloudflare DNS validation:
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini \
-d your-domain.com -d www.your-domain.comThen restart GitLab:
sudo gitlab-ctl start nginx
Certbot will automatically create and clean up the necessary _acme-challenge DNS records in Cloudflare.
✅ Step 5: Point GitLab to the Let’s Encrypt Certificates
Edit GitLab’s configuration file:
sudo nano /etc/gitlab/gitlab.rb
Add or update these lines:
external_url "https://your-domain.com"
nginx['ssl_certificate'] = "/etc/letsencrypt/live/your-domain.com/fullchain.pem"
nginx['ssl_certificate_key'] = "/etc/letsencrypt/live/your-domain.com/privkey.pem"
Reconfigure GitLab to apply changes:
sudo gitlab-ctl reconfigure
✅ Step 6: Create a Deploy Hook for Automatic Reload
When Certbot renews the certificate, GitLab’s NGINX must reload to apply the new one.
Create a deploy hook script:
sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-gitlab.sh
Add:
#!/bin/bash
echo "Reloading GitLab after SSL certificate renewal..."
/opt/gitlab/bin/gitlab-ctl hup nginxMake it executable:
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-gitlab.sh
✅ Step 7: Test and Automate Renewal
Perform a test renewal:
sudo certbot renew --dry-run
If it completes without errors, Certbot and the deploy hook are correctly configured.
Certbot installs a systemd timer automatically, but you can verify with:
systemctl list-timers | grep certbot
If missing, add a cron job:
sudo crontab -e
Then add:
0 3 * * * certbot renew --quiet
✅ Step 8: Verify SSL Certificate Status
After renewal, reload NGINX manually once:
sudo gitlab-ctl hup nginx
Check expiration date:
sudo openssl x509 -in /etc/letsencrypt/live/your-domain.com/fullchain.pem -noout -dates
🧩 Summary Table
| Task | Command / Path |
|---|---|
| Certbot install | apt install certbot python3-certbot-dns-cloudflare |
| Credentials file | /etc/letsencrypt/cloudflare.ini |
| SSL cert path | /etc/letsencrypt/live/<domain>/ |
| Deploy hook | /etc/letsencrypt/renewal-hooks/deploy/reload-gitlab.sh |
| Reload GitLab | /opt/gitlab/bin/gitlab-ctl hup nginx |
| GitLab config | /etc/gitlab/gitlab.rb |
🧠 Final Thoughts
By using Cloudflare DNS validation, your GitLab SSL renewal process becomes completely hands-free — even behind Cloudflare’s proxy or firewalls. Combined with Proxmox LXC containers and TurnKey Linux templates, this is a robust, production-ready setup that minimizes maintenance overhead.
🧰 Recommended Tools & Resources:TurnKey Linux GitLab TemplateCloudflare DNS ManagementProxmox VE Hardware (Mini PC & NUCs)Certbot Official Docs
About the author
Tim Wilkes is a UK-based security architect with over 15 years of experience in electronics, Linux, and Unix systems administration. Since 2021, he's been designing secure systems for a telecom company while indulging his passions for programming, automation, and 3D printing. Tim shares his projects, tinkering adventures, and tech insights here - partly as a personal log, and partly in the hopes that others will find them useful.
Want to connect or follow along?
LinkedIn: [phpsytems]
Twitter / X: [@timmehwimmy]
Mastodon: [@timmehwimmy@infosec.exchange]
If you've found a post helpful, consider supporting the blog - it's a part-time passion that your support helps keep alive.
⚠️ Disclaimer
This post may contain affiliate links. If you choose to purchase through them, I may earn a small commission at no extra cost to you. I only recommend items and services I’ve personally read or used and found valuable.
As an Amazon Associate I earn from qualifying purchases.