Proxmox Let's Encrypt ACME Certificate Setup Guide

Set up free Let's Encrypt SSL certificates on Proxmox VE using the built-in ACME client. Works for homelab hosts using DNS challenge — no public IP needed.

Proxmox Pulse Proxmox Pulse
9 min read
lets-encrypt acme ssl certificates dns-challenge
A crystalline geometric padlock with glowing certificate chains symbolizing SSL encryption.

The browser "Your connection is not private" warning on your Proxmox web UI is more than visual friction — every modern browser suppresses password autofill on untrusted origins, and if you're accessing your node through Tailscale or a reverse proxy, broken certificate validation creates real operational headaches. Proxmox VE 9.x ships a full ACME client built into both the web UI and CLI. In under 15 minutes, you can have a free, auto-renewing Let's Encrypt certificate on any Proxmox node — including homelab hosts with no public IP — using the DNS-01 challenge. This guide walks through the setup with Cloudflare as the DNS provider, but the same steps apply to AWS Route 53, Hetzner, DigitalOcean, and the 30+ other providers Proxmox ships plugins for.

Key Takeaways

  • Built-in ACME client: No certbot or acme.sh needed — Proxmox VE has included its own ACME client since version 6.2.
  • DNS-01 for homelabs: If your Proxmox host isn't publicly reachable on port 80, DNS-01 proves domain ownership through your DNS provider's API instead.
  • Scoped API token: Create a Cloudflare token with Zone:DNS:Edit permission only — do not use the global API key.
  • Auto-renewal: The pve-daily-update.timer systemd unit renews certificates automatically when fewer than 30 days remain.
  • Per-node in clusters: Each cluster node needs its own ACME configuration — there is no cluster-wide certificate push.

Why the Default Self-Signed Certificate Is a Real Problem

Proxmox generates a self-signed certificate at install time using a local CA. Every browser flags it as untrusted, which means:

  • Chrome and Firefox suppress password autofill on https:// pages with cert errors
  • Browser extensions and API clients refuse connections that fail certificate validation
  • You train yourself to click through security warnings — exactly the reflex that Proxmox firewall and SSH hardening is designed to eliminate

A valid certificate fixes all of this and costs nothing beyond owning a domain.

Prerequisites

Before starting, confirm three things:

  1. You own a domain managed through a supported DNS provider (list available at Datacenter > ACME > Challenge Plugins)
  2. Your Proxmox node has outbound internet access to acme-v02.api.letsencrypt.org on port 443
  3. Your node's hostname is a fully qualified domain name

Check the current hostname:

hostname --fqdn

If the result is just pve with no domain suffix, fix it before proceeding. The Proxmox installation guide covers hostname configuration as part of its initial setup checklist, but the quick fix is:

hostnamectl set-hostname pve.yourdomain.com

Then update /etc/hosts so the node's IP maps to the FQDN:

192.168.1.10  pve.yourdomain.com pve

How to Register an ACME Account

Proxmox's ACME client needs a Let's Encrypt account to issue certificates. Register once per node.

Via the Web UI:

  1. Navigate to Datacenter > ACME
  2. Under "Accounts", click Add
  3. Enter your email address and accept the Terms of Service
  4. Select the Staging directory first — it has no rate limits and lets you validate the full flow without burning production quota

Via the CLI:

# Staging — use this first
pvenode acme account register staging your@email.com \
  --directory https://acme-staging-v02.api.letsencrypt.org/directory

# Production — switch to this after staging succeeds
pvenode acme account register default your@email.com \
  --directory https://acme-v02.api.letsencrypt.org/directory

List registered accounts at any point:

pvenode acme account list

HTTP-01 vs DNS-01: Which Challenge Type to Use

Challenge Requirement Best for
HTTP-01 Port 80 publicly reachable on your domain's IP Public-facing hosts
DNS-01 API access to your DNS provider Homelabs, private IPs, wildcards
TLS-ALPN-01 Port 443 publicly reachable Rarely needed with Proxmox

For a typical homelab Proxmox node, DNS-01 is the right call. Your host stays completely internal — only the Proxmox node needs outbound HTTPS access to Let's Encrypt's servers and your DNS provider's API. No inbound port forwarding required.

Setting Up the Cloudflare DNS Plugin

First, create a scoped API token in Cloudflare:

  1. Log into Cloudflare > My Profile > API Tokens > Create Token
  2. Select the Edit zone DNS template
  3. Scope it to your specific zone (domain) — not "All zones"
  4. Copy the token immediately — it won't be shown again

Add the plugin in Proxmox:

Web UI: Datacenter > ACME > Challenge Plugins > Add

  • Plugin ID: cloudflare
  • Plugin type: Cloudflare Managed DNS
  • API Token: paste your token

CLI:

pvenode acme plugin add dns cloudflare \
  --api cf \
  --data "CF_Token=your_cloudflare_api_token_here"

Verify the plugin was saved:

pvenode acme plugin list

Configuring the Domain on Your Node

Attach a domain and the DNS plugin to your node's certificate configuration.

Web UI: Node > Certificates > ACME > Add

  • Domain: pve.yourdomain.com
  • Challenge type: DNS
  • Plugin: cloudflare

CLI:

# Set the ACME account for this node
pvenode config set --acme "account=default"

# Set the domain with the DNS plugin
pvenode config set --acmedomain0 "pve.yourdomain.com,plugin=cloudflare"

Verify the config was written correctly:

grep -E "^acme" /etc/pve/nodes/$(hostname)/config

Expected output:

acme: account=default
acmedomain0: pve.yourdomain.com,plugin=cloudflare

Ordering the Certificate

With the account and domain configured, request the certificate:

Web UI: Node > Certificates > ACME > Order Certificates Now

A task log shows the challenge flow in real time. DNS-01 validation against Cloudflare typically takes 30-60 seconds — Cloudflare's API propagation is fast enough that the challenge succeeds on the first validation attempt.

CLI:

pvenode acme cert order

If you're using the staging account, the certificate issuer will be "Fake LE Intermediate X1" — that's correct. Once staging succeeds, switch to the production account and re-order:

pvenode config set --acme "account=default"
pvenode acme cert order --force

After a successful order, the Proxmox web UI immediately starts serving the new certificate. Reload your browser — the padlock should now show a valid issuer.

How Auto-Renewal Works

Proxmox does not use a separate cron job for certificate renewal. The pve-daily-update.service systemd unit runs once per day and checks whether any node certificates expire within 30 days. If they do, it renews automatically via the same ACME config.

Check the timer status:

systemctl status pve-daily-update.timer

Trigger a manual renewal check:

pvenode acme cert renew

If a renewal fails silently, check the update log:

grep -i acme /var/log/pveupdate.log | tail -20

Expect to see lines confirming the renewal check ran and either skipped (cert still valid) or completed successfully.

Gotchas and Pitfalls From Real Use

Rate limits hit fast during testing: Let's Encrypt's production CA allows 5 failed certificate orders per domain per hour. If your plugin config is wrong and you retry quickly, you'll burn the limit. Always test with the staging CA first — it has no rate limits.

DNS propagation timing: The Cloudflare plugin inserts the TXT record and then waits before signaling ACME to validate. Cloudflare is typically 5-15 seconds. Slower DNS providers can take 2-5 minutes, and the Proxmox ACME client's built-in propagation wait may time out before slower providers finish. If validation fails consistently with a non-Cloudflare provider, look for a sleep or propagation_seconds setting in its plugin script under /usr/share/proxmox-acme/dnsapi/.

Wildcard certificates require DNS-01: Let's Encrypt issues wildcard certs only via DNS-01. To get *.yourdomain.com, set:

pvenode config set --acmedomain0 "*.yourdomain.com,plugin=cloudflare"

Note that *.yourdomain.com covers pve.yourdomain.com but not the apex yourdomain.com. Add a second domain entry (--acmedomain1) for the apex if you need it.

Cluster nodes each need separate certs: In a three-node cluster, configure ACME independently on pve1, pve2, and pve3. Each node's config lives at /etc/pve/nodes/<nodename>/config. There is no mechanism to push a certificate from the cluster view. Once you've invested the time setting up a full Proxmox private cloud, budget an extra 10 minutes per additional node for certificate setup.

Port 8006 vs port 80: HTTP-01 challenge needs port 80 forwarded to the Proxmox host — not port 8006. Forwarding 80 → 8006 via NAT will fail the challenge because the ACME token is served on port 80, not the web UI port.

Verifying the Certificate

After ordering, confirm the cert details:

Web UI: Node > Certificates — you'll see the Let's Encrypt cert listed alongside the original self-signed CA cert.

CLI:

openssl x509 \
  -in /etc/pve/local/pveproxy-ssl.pem \
  -text -noout \
  | grep -E "(Subject:|Issuer:|Not After)"

Expected output:

Subject: CN=pve.yourdomain.com
Issuer: C=US, O=Let's Encrypt, CN=R10
Not After : Jul 23 12:00:00 2026 GMT

The certificate is valid for 90 days. Proxmox renews it when fewer than 30 days remain, so in steady state you should never see expiry-related downtime.

Using a Different DNS Provider

Proxmox ships ACME DNS plugins for 30+ providers. List all available APIs:

ls /usr/share/proxmox-acme/dnsapi/

The naming convention: dns_cf.sh → pass --api cf to pvenode acme plugin add dns. For AWS Route 53:

pvenode acme plugin add dns myroute53 \
  --api route53 \
  --data "AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE&AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

If your DNS provider isn't in the list, the acme-dns delegation approach works universally — you create a CNAME from _acme-challenge.yourdomain.com to a subdomain on a separate acme-dns server you control. More setup, but compatible with any registrar.

Conclusion

Setting up Let's Encrypt on Proxmox takes about 15 minutes and permanently eliminates the certificate warning on your management interface. Register a staging account, add your DNS plugin, configure the domain, confirm the staging cert orders cleanly, then switch to production — the systemd timer handles every renewal from that point forward. This pairs directly with the steps in the Proxmox firewall, fail2ban, and SSH hardening guide to give your management interface a properly secured baseline from day one.

Share
Proxmox Pulse

Written by

Proxmox Pulse

Sysadmin-driven guides for getting the most out of Proxmox VE in production and homelab environments.

Related Articles

View all →