Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/klzgrad/naiveproxy/llms.txt

Use this file to discover all available pages before exploring further.

Running Caddy as an interactive foreground process is fine for testing, but in production you want it managed by systemd so it starts automatically on boot, restarts if it crashes, and integrates with the system logging infrastructure. This guide walks through manually registering the NaïveProxy Caddy binary as a systemd service — no package manager installation required.

Requirements

  • A caddy binary built with the NaïveProxy fork of the forwardproxy plugin (see Caddy Setup)
  • systemctl --version >= 232
  • sudo privileges on the target machine
1
Move the Binary and Caddyfile into Place
2
Make the binary executable and move it to a system-wide location on $PATH. Then create the Caddy configuration directory and move your Caddyfile into it:
3
chmod +x caddy
mv caddy /usr/bin/
mkdir /etc/caddy
mv Caddyfile /etc/caddy/
4
Test the Configuration
5
Before installing the service, verify that Caddy starts successfully with the configuration file. This will catch any Caddyfile syntax errors and confirm that certificate issuance works:
6
/usr/bin/caddy run --config /etc/caddy/Caddyfile
7
Press Ctrl+C to stop once you have confirmed it starts cleanly.
8
Create a Dedicated System User and Group
9
Running Caddy as root is unnecessary and inadvisable. Create a dedicated system account instead:
10
groupadd --system caddy

useradd --system \
    --gid caddy \
    --create-home \
    --home-dir /var/lib/caddy \
    --shell /usr/sbin/nologin \
    --comment "Caddy web server" \
    caddy
11
The --system flag creates a low-UID service account. The --shell /usr/sbin/nologin flag prevents interactive logins. Caddy stores its automatic TLS certificates in its home directory (/var/lib/caddy), which is why --create-home is needed.
12
Create the systemd Unit File
13
Create /etc/systemd/system/caddy.service with the following content:
14
[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target

[Service]
User=caddy
Group=caddy
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target
15
Double-check that the paths in ExecStart and ExecReload exactly match where you placed the caddy binary and Caddyfile. If either path is wrong, the service will fail to start or fail to reload. Use which caddy to confirm the binary location.
16
Key unit settings:
17
  • After=network-online.target / Requires=network-online.target — Ensures the service only starts once the network is fully up, which is necessary for Let’s Encrypt certificate issuance on first boot.
  • AmbientCapabilities=CAP_NET_BIND_SERVICE — Grants the caddy user permission to bind to privileged ports (443) without running as root.
  • LimitNOFILE=1048576 — Raises the open file descriptor limit to handle many concurrent connections.
  • PrivateTmp=true / ProtectSystem=full — Sandbox the process to reduce the impact of any security vulnerabilities.
  • ExecReload — Allows systemctl reload caddy to apply configuration changes without a full restart and without dropping existing connections.
  • 18
    Enable and Start the Service
    19
    Reload systemd to pick up the new unit file, then enable and start the service:
    20
    systemctl daemon-reload
    systemctl enable caddy
    systemctl start caddy
    
    21
    Check that it is running:
    22
    systemctl status caddy
    
    23
    You should see Active: active (running) in the output.

    Ongoing Management

    Reload after a config change (graceful, no connection drops):
    systemctl reload caddy
    
    Restart the service (full stop and start):
    systemctl restart caddy
    
    View logs:
    journalctl -u caddy --follow
    

    Next Steps

    • If you have not yet written your Caddyfile, see Caddy Setup.
    • For the HAProxy-based frontend alternative, see HAProxy Setup.

    Build docs developers (and LLMs) love