Skip to content

Conversation

@Siomachkin
Copy link
Contributor

This PR implements support for named socket activation in systemd, allowing users to reference sockets by name using fdname/name and fdgramname/name syntax instead of only numeric fd/N and fdgram/N references.

Solution Logic

The implementation uses an early normalization approach:

  1. New function getFdByName() - reads systemd environment variable LISTEN_FDNAMES and maps socket names to file descriptor numbers

  2. Extended ParseNetworkAddressWithDefaults() - detects fdname/ and fdgramname/ prefixes and converts them to standard fd/N and fdgram/N syntax internally

  3. Backward compatibility - existing fd/N syntax continues to work unchanged

The conversion happens at parse time, so all downstream code continues to work with the standard fd syntax without modifications.

Testing Results

Unit Tests

  • TestGetFdByName: 7 test cases covering environment variable parsing, multiple sockets, error handling
  • TestParseNetworkAddressFdName: 9 test cases covering address parsing with both old and new syntax

Manual Testing

  • Verified backward compatibility with fd/3 and fdgram/4 syntax
  • Tested new fdname/http and fdgramname/dns syntax with environment variables
  • Confirmed proper error handling for missing environment variables and invalid socket names

Usage Examples

Before (numeric references)

fd/3
fdgram/4

After (named references)

fdname/http
fdgramname/dns

Assistance Disclosure
I consulted Claude to understand the project architecture, but I authored/coded the fix myself

Resolves #6792

@francislavoie
Copy link
Member

Hmm. I don't know much about socket activation (not something I've ever used/needed) but generally we try to avoid having configuration via env vars. Are you sure that's necessary? Why can't it be in the config itself?

@Siomachkin
Copy link
Contributor Author

From the issue description:

"Systemd supports using multiple socket files for a single service, but does not define an ordering of the sockets between those socket files. Instead, systemd provides the names of the socket files within environment variables (LISTEN_FDS and LISTEN_FDNAMES combine to name the fds)."

Without LISTEN_FDNAMES, there's no way to know which FD number corresponds to which socket - the ordering is unpredictable. This follows the same pattern as systemd's standard sd_listen_fds_with_names() C function.

@codyps
Copy link

codyps commented Sep 6, 2025

Referring to #6792 (comment), it's possible (even likely) to have multiple sockets with the same name by defining those sockets within the same systemd.socket file. The manual for sd_listen_fds_with_names() says: "Note that the names used are not unique in any way."

Additionally, the current sock activation pattern (using fd/N) exposes and requires uses the existence of multiple sockets in a systemd.socket file (but simply can't handle multiple socket files).

To fully support named socket activation, we need to be able to express to caddy the "index" of a socket with a given name.

The current impl in this PR always returns the first socket with a given name. To allow full utilization of named socket activation, it could be adjusted to provide a way to return the Nth socket with a given name.

@Siomachkin
Copy link
Contributor Author

I've added full support for indexed named sockets. Now supports:

bind fdname/web        # first socket named "web" (default :0)
bind fdname/web:0      # same as above (explicit)
bind fdname/web:1      # second socket named "web"
bind fdgramname/dns:2  # third UDP socket named "dns"

@francislavoie
Copy link
Member

Ah, so LISTEN_FDNAMES is a standard env var outside of Caddy? That's okay, then. I had the impression you were adding this as a way to configure Caddy specifically.

@eriksjolund
Copy link

This is just a matter of personal taste but I think the default syntax could be dropped

bind fdname/web        # first socket named "web" (default :0)

Intiutively, no number could also be understood as all sockets named "web".

I would instead always require a number when an fdname is provided.

@Siomachkin
Copy link
Contributor Author

I prefer keeping the default for single sockets (fdname/web). In practice, I think socket files define one socket with a given name in most cases. Requiring :0 always would make the simple case unnecessarily verbose.

@francislavoie francislavoie added this to the v2.11.0 milestone Sep 14, 2025
@francislavoie francislavoie changed the title Add support for named socket activation listeners: Add support for named socket activation Oct 21, 2025
Copy link
Member

@francislavoie francislavoie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Simple and narrow change, with tests. Thanks!

@francislavoie francislavoie force-pushed the add-named-socket-activation branch from a819b73 to 00e68aa Compare October 21, 2025 04:49
@francislavoie francislavoie enabled auto-merge (squash) October 21, 2025 04:50
@francislavoie francislavoie added the feature ⚙️ New feature or request label Oct 21, 2025
@francislavoie francislavoie merged commit 156ce99 into caddyserver:master Oct 21, 2025
23 checks passed
@MayCXC
Copy link
Contributor

MayCXC commented Oct 24, 2025

did you see http://github.com/MayCXC/caddy-systemd-socket-activation ? it supports the indices from systemd.socket. for this to go into main, I would like to take your test cases and use the implementation from the extension and add them to the _linux target. are you able to test that the extension works for you?

@mohammed90 mohammed90 mentioned this pull request Oct 25, 2025
45 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature ⚙️ New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

caddy socket activation (bind fd/N, bind fdgram/N) only works with a single systemd.socket file, limiting configurability

5 participants