How to Renew GitLab SSL Certificates in a Proxmox LXC with Certbot and Cloudflare DNS

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:

  1. Go to My Profile → API Tokens → Create Token
  2. Use the “Edit zone DNS” template
  3. Restrict it to your domain (e.g., example.com)
  4. 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.com

Then 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 nginx

Make 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

TaskCommand / Path
Certbot installapt 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.