Running Caddy as non-root user + local certs (not caddy managed)

1. Caddy version (caddy version):

(devel) Compiled from github/2.4.5 version

2. How I run Caddy:

sudo -u apache caddy run

a. System environment:

Gentoo Linux 5.13.12, OpenRC,

b. Command:


c. Service/unit/compose file:

Paste full file contents here.
Make sure backticks stay on their own lines,
and the post looks nice in the preview pane.

d. My complete Caddyfile or JSON config:

	#	http_port 60001
	auto_https off
	log {
		output file /var/log/caddy/caddy_main.log {
			roll_size 100MiB
			roll_keep_for 100d
	servers [2001:470:28:704::100]:443 {
		protocol {
	servers [2001:470:28:704::100]:80 {
		protocol {

## Hosts section {
	bind 2001:470:28:704::100
	tls /etc/letsencrypt/live/ /etc/letsencrypt/live/ {
	log {
		output file /var/log/caddy/ {
			roll_size 100MiB
			roll_keep_for 100d
	root * /var/www/domains/
	php_fastcgi unix//var/run/php-fpm/fpm-www.socket
	encode zstd gzip

3. The problem I’m having:

I want to run Caddy as a non-root user, and I want to use local TLS certs that are access-only for root user.

Is there a way for Caddy to start as root user to set up listening sockets and load TLS certs, and then drop to a non-privileged user?

Perhaps there is a better way to import or load local TLS certs into Caddy? Though I do not want Caddy to deal with renewals, new registrations, etc.

4. Error messages and/or full log output:

5. What I already tried:

Only tried to run Caddy as non-root user. It failed on reading the TLS certs. This is natural as they are read only by root user.

6. Links to relevant resources:

You don’t need to run as root at all:

sudo setcap cap_net_bind_service=+ep $(which caddy)

That sounds like a systems permission misconfiguration.

I do not want my private keys to be readable by the user that runs Caddy. Apache, for example, handles this by loading the TLS certs as root and then running the the servers as the www user.

Caddy doesn’t have privilege de-escalation, because it runs as a single process.

That requirement also doesn’t make sense with how Caddy is designed, with config reloading at its core. Caddy needs to reload the certs/keys on config reload because it’s swapping out the entire config in-memory.

Why aren’t you letting Caddy issue your certs automatically, since you seem to be using a cert from Let’s Encrypt? That’s one of Caddy’s biggest strengths. Caddy has the most robust ACME client implementation out there.

At the moment I am not only using Caddy, but also other services and tools with Let’s Encrypt. So I prefer, for now, to manage all of them in another stand-alone tool.

I suppose the easiest way is to provide a copy of the certs that are readable by Caddy usergroup.

Is it possible to import existing LE certs and account?

That’s not necessary. Caddy will issue new ones immediately. It’s much more effort than it’s worth to try to move the certs/keys into the exact storage locations Caddy would expect.

There’s no actual reason to keep the certs/accounts the same between deployments. As long as the certificates are signed by a publicly trusted CA, and your private keys are kept secret, it’s secure.

This topic was automatically closed after 30 days. New replies are no longer allowed.