Installing modules - layer4 module

1. The problem I’m having:

I’m trying to use the layer4 module but i keep getting errors that state the service does not recognize the module. What am i doing wrong installing this custom module?

2. Error messages and/or full log output:

user1@sync ✔ 22:28:32 /etc/caddy  > caddy run --config /etc/caddy/Caddyfile
2025/04/13 22:28:38.932 INFO    using config from file  {"file": "/etc/caddy/Caddyfile"}
Error: adapting config using caddyfile: /etc/caddy/Caddyfile:2: unrecognized global option: layer4
user1@sync ✘ 22:28:38 /etc/caddy  > 
user1@sync ✘ 22:29:13 /etc/caddy  > sudo systemctl status caddy
× caddy.service - Caddy
     Loaded: loaded (/etc/systemd/system/caddy.service; enabled; preset: enabled)
     Active: failed (Result: exit-code) since Sun 2025-04-13 22:15:15 UTC; 14min ago
       Docs: https://caddyserver.com/docs/
    Process: 1738 ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile (code=exited, status=1/FAILURE)
   Main PID: 1738 (code=exited, status=1/FAILURE)
        CPU: 45ms

Apr 13 22:15:15 sync.maxworks.pro caddy[1738]: LOGNAME=caddy
Apr 13 22:15:15 sync.maxworks.pro caddy[1738]: USER=caddy
Apr 13 22:15:15 sync.maxworks.pro caddy[1738]: INVOCATION_ID=63e16bc4d2214c1fa024eca71e29fa44
Apr 13 22:15:15 sync.maxworks.pro caddy[1738]: JOURNAL_STREAM=8:21655
Apr 13 22:15:15 sync.maxworks.pro caddy[1738]: SYSTEMD_EXEC_PID=1738
Apr 13 22:15:15 sync.maxworks.pro caddy[1738]: {"level":"info","ts":1744582515.396744,"msg":"using config from file","file":"/etc/caddy/Caddyfile"}
Apr 13 22:15:15 sync.maxworks.pro caddy[1738]: Error: adapting config using caddyfile: /etc/caddy/Caddyfile:2: unrecognized global option: l4
Apr 13 22:15:15 sync.maxworks.pro systemd[1]: caddy.service: Main process exited, code=exited, status=1/FAILURE
Apr 13 22:15:15 sync.maxworks.pro systemd[1]: caddy.service: Failed with result 'exit-code'.
Apr 13 22:15:15 sync.maxworks.pro systemd[1]: Failed to start caddy.service - Caddy.
maxb@sync ✘ 22:29:18 /etc/caddy  > 

After its been installed i get a ././caddy is this the correct executable?

go: added github.com/things-go/go-socks5 v0.0.5
2025/04/13 22:40:44 [INFO] exec (timeout=0s): /usr/local/go/bin/go get -v  
2025/04/13 22:40:48 [INFO] Build environment ready
2025/04/13 22:40:48 [INFO] Building Caddy
2025/04/13 22:40:48 [INFO] exec (timeout=0s): /usr/local/go/bin/go mod tidy -e 
2025/04/13 22:40:48 [INFO] exec (timeout=0s): /usr/local/go/bin/go build -o /etc/caddy/caddy -ldflags -w -s -trimpath -tags nobadger,nomysql,nopgx 
2025/04/13 22:40:54 [INFO] Build complete: ./caddy
2025/04/13 22:40:54 [INFO] Cleaning up temporary folder: /tmp/buildenv_2025-04-13-2240.3637856850

././caddy version
v2.9.1 h1:OEYiZ7DbCzAWVb6TNEkjRcSCRGHVoZsJinoDR/n9oaY=

3. Caddy version:

maxb@sync ✘ 22:29:46 /etc/caddy  > caddy version
v2.9.1 h1:OEYiZ7DbCzAWVb6TNEkjRcSCRGHVoZsJinoDR/n9oaY=
maxb@sync ✔ 22:29:50 /etc/caddy  > 

4. How I installed and ran Caddy:

a. System environment:

Debian 12 in a VPS. I originally installed caddy using the below method

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

b. Command:

I installed this layer4 package with xcaddy GitHub - caddyserver/xcaddy: Build Caddy with plugins. Here is the git GitHub - mholt/caddy-l4: Layer 4 (TCP/UDP) app for Caddy.

I installed it with the below command. I also needed to install go which I set a path variable in my zsh shell.

$ xcaddy build --with github.com/mholt/caddy-l4

c. Service/unit/compose file:

i set the service file up as the efault

[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target

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

[Install]
WantedBy=multi-user.target
maxb@sync ✔ 22:33:47 systemd/system  > 

d. My complete Caddy config:

{
    layer4 {
        server {
            listen :15000

            route {
                match tls
                proxy {
                    to localhost:22067
                }
            }
        }
    }
}

Follow the instructions here:

1 Like

Can you please run this command and share the output?

/usr/bin/caddy list-modules
1 Like

I was able to run this module using that ././caddy that is shown at the end of the xcaddy build --with github.com/mholt/caddy-l4 command.

2025/04/13 22:40:54 [INFO] Cleaning up temporary folder: /tmp/buildenv_2025-04-13-2240.3637856850

././caddy version
v2.9.1 h1:OEYiZ7DbCzAWVb6TNEkjRcSCRGHVoZsJinoDR/n9oaY=

The modules are listed there but not under ./caddy rather under ././caddy. Why is that?

 ././caddy run --config /etc/caddy/Caddyfile

...
caddy.listeners.layer4
layer4
layer4.handlers.echo
layer4.handlers.proxy
layer4.handlers.proxy_protocol
layer4.handlers.socks5
layer4.handlers.subroute
layer4.handlers.tee
layer4.handlers.throttle
layer4.handlers.tls
layer4.matchers.clock
layer4.matchers.dns
layer4.matchers.http
layer4.matchers.local_ip
layer4.matchers.not
layer4.matchers.openvpn
layer4.matchers.postgres
layer4.matchers.proxy_protocol
layer4.matchers.quic
layer4.matchers.rdp
layer4.matchers.regexp
layer4.matchers.remote_ip
layer4.matchers.socks4
layer4.matchers.socks5
layer4.matchers.ssh
layer4.matchers.tls
layer4.matchers.winbox
layer4.matchers.wireguard
layer4.matchers.xmpp
layer4.proxy.selection_policies.first
layer4.proxy.selection_policies.ip_hash
layer4.proxy.selection_policies.least_conn
layer4.proxy.selection_policies.random
layer4.proxy.selection_policies.random_choose
layer4.proxy.selection_policies.round_robin
tls.handshake_match.alpn

  Non-standard modules: 36

Is that the result of

/usr/bin/caddy list-modules

Sorry, I didn’t realize it produces a new executable in the current directory.