1. The problem I’m having:
I want to run Caddy as a non-administrative user under Windows, as a service, as it is not best practice to run it as an administrator.
When the service runs under a local account that is a member of the Administrators group, caddy works without problems. I take that as confirmation/sanity check that my caddyfile, cloudflare token and overall network configuration are not to blame.
Only when the service runs under a normal user that is not an administrator, caddy is unable to retrieve certificates. It will fail (repeatedly) with the errors below. Therefore, the sites cannot be accessed and browsers will display a certificate error when trying to access them.
As soon as the service user is added to the Administrators group, the directory
C:\Users\proxyuser\AppData\Roaming\Caddy\
purged and the service restarted, caddy will once again work perfectly.
If admin rights are again withdrawn, certificate retrieval will fail again.
What I need to know and was unable to find out:
- Which permissions do I need to give to the ordinary user for caddy to be able to retrieve the certificates without timeout.
Is it possible that to create the certificate requests, caddy relies on a Windows function or library that is not accessible to normal users, only to administrators?
2. Error messages and/or full log output:
As stated, when running as an admin user, caddy works fine and retrieves the certificates quickly and without any issues.
When running as normal user as service (see section 4 below), caddy is unable to get the certificates (except once for one of the two domains during testing, which I consider spurious) and will usually create these errors:
{"level":"error","ts":1729797523.7216048,"logger":"tls.obtain","msg":"could not get certificate from issuer","identifier":"ab.mydomain.com","issuer":"acme-v02.api.letsencrypt.org-directory","error":"[ab.mydomain.com] solving challenges: waiting for solver certmagic.solverWrapper to be ready: timed out waiting for record to fully propagate; verify DNS provider configuration is correct - last error: <nil> (order=https://acme-v02.api.letsencrypt.org/acme/order/2018563123/316703407123) (ca=https://acme-v02.api.letsencrypt.org/directory)"}
{"level":"error","ts":1729797523.7221572,"logger":"tls.obtain","msg":"will retry","error":"[ab.mydomain.com] Obtain: [ab.mydomain.com] solving challenges: waiting for solver certmagic.solverWrapper to be ready: timed out waiting for record to fully propagate; verify DNS provider configuration is correct - last error: <nil> (order=https://acme-v02.api.letsencrypt.org/acme/order/2018563234/316703407234) (ca=https://acme-v02.api.letsencrypt.org/directory)","attempt":1,"retrying_in":60,"elapsed":125.5902871,"max_duration":2592000}
{"level":"error","ts":1729797523.7256222,"logger":"tls.obtain","msg":"could not get certificate from issuer","identifier":"cd.mydomain.com","issuer":"acme-v02.api.letsencrypt.org-directory","error":"[cd.mydomain.com] solving challenges: waiting for solver certmagic.solverWrapper to be ready: timed out waiting for record to fully propagate; verify DNS provider configuration is correct - last error: <nil> (order=https://acme-v02.api.letsencrypt.org/acme/order/2018563456/316703407345) (ca=https://acme-v02.api.letsencrypt.org/directory)"}
{"level":"error","ts":1729797523.7256222,"logger":"tls.obtain","msg":"will retry","error":"[cd.mydomain.com] Obtain: [cd.mydomain.com] solving challenges: waiting for solver certmagic.solverWrapper to be ready: timed out waiting for record to fully propagate; verify DNS provider configuration is correct - last error: <nil> (order=https://acme-v02.api.letsencrypt.org/acme/order/2018563157/316703407567) (ca=https://acme-v02.api.letsencrypt.org/directory)","attempt":1,"retrying_in":60,"elapsed":125.6029214,"max_duration":2592000}
3. Caddy version:
v2.8.4 h1:q3pe0wpBj1OcHFZ3n/1nl4V4bxBrYoSoab7rL9BMYNk=
4. How I installed and ran Caddy:
a. System environment:
Clean, fresh Windows Server 2022 install with latest updates as of today. Also tried on a Windows Server 2025 (Core, without desktop experience) machine with identical results.
Windows Firewall has been completely deactivated for troubleshooting purposes, so can be ruled out as culprit. There is no other software installed on the system.
Due to the fact that everything works as soon as local admin rights are given to the caddyservice user account, I believe any external factors (cloudflare config, router, port forwarding etc.) can also be ruled out.
b. Command:
-
Downloaded caddy with cloudflare and replace-response from here.
-
Saved exe and caddyfile to C:\caddy
-
Installed caddy as service with this cmd
sc.exe create "caddyservice" start=auto binPath="C:\caddy\caddy.exe run"
-
With
lusrmgr.msc
, created a standard new local Windows user account called “proxyuser” (non-admin, member of default group “Users” only) -
In
services.msc
, changed user for caddyservice to “proxyuser” and acknowledged the message to give this account local service permissions. -
Set service to start automatically.
-
Alternatively, for troubleshooting purposes, caddy was also run as local admin user (member of “Administrators” group) in cmd via
caddy.exe run --watch
while the service was stopped. -
For further troubleshooting, “proxyuser” was intermittently added to the group “Administrators” for testing purposes (while the service was stopped; AppData directory contents deleted before starting service again) which would then solve the errors.
d. My complete Caddy config:
{
#debug
order replace after encode
log default {
output file C:\\caddy\\log.txt {
roll_size 1MiB
roll_local_time
}
level WARN
}
}
https://ab.mydomain.com {
encode gzip
reverse_proxy https://10.0.0.10 {
header_up Accept-Encoding identity
transport http {
tls_insecure_skip_verify
}
}
tls {
dns cloudflare 123mytoken123
resolvers 1.1.1.1
}
replace {
"Hello" "Bye"
}
}
https://cd.mydomain.com {
encode gzip
root * C:\\caddy\\www\\cd.mydomain.com
file_server
tls {
dns cloudflare 123mytoken123
resolvers 1.1.1.1
}
}