Repository: authelia/authelia (go)

Issue:
More flexible server.address configuration (file descriptor, PROXY...)
### Description


First of all, thank you for this nice project!

I would like to deploy authelia using systemd sockets (systemd opens the privileged port and handles it to authelia).
Looking at the code, it seems that `server.address` currently supports `tcp(4|6)` and `unix` (with `?umask`).

It would be nice if listening to file descriptor was possible.

### Use Case


Better integration with systemd (so that the authelia service does not need to bind on any socket).

### Details


Instead of reinventing the wheel, maybe something like https://github.com/AGWA/go-listener/ could be used. It allows to create a `net.Listener` by parsing a string. For instance:
```
tcp:80  // all interfaces, port 80
tcp:0.0.0.0:80 // all ipv4, port 80
tcp:[::1]:80 // all ipv6, port 80

unix:/path/to/socket // unix socket (umask is not supported yet, maybe upstream would accept a PR)

fd:4 // listen on file descriptor 4 - which can be passed by systemd
```

Those listeners can also be wrapped, by prepending them. For instance the `tls` subpackage allows:
```
tls:/folder/with/certificates/:tcp:443 // will get the key and certificate from the folder
tls:/path/to/certificate_file:tcp:443 // will get the key and certificate from the file
tls:example.com:tcp:443 // will use lets encrypt to get the certificate
```

Another (currently) missing feature of `go-listener` is client certificates. I could also look into implementing them upstream or in a dedicated package.

## Example of the proposed change on the config

Current
```yml
server:
  address: tcp://:9091
  tls:
    key: "/folder/with/certificates/key"
    certificate: "folder/with/certificates/certificate"
    client_certificates: ["/folder/with/client/cert"]
```
Proposed:

```yml
server:
  listener: tls:/folder/with/certificates/:tcp:9091
  client_certificates: ["/folder/with/client/cert"]
```

Other examples:
```yml
server:
  listener: tls:example.org:fd:4
```

## Contributing

I would be willing to craft a PR, if you think that this approach sound sensible.

### Documentation


_No response_

### Pre-Submission Checklist


- [X] I agree to follow the [Code of Conduct](http://www.authelia.com/code-of-conduct)

- [X] I have checked for related issues and checked the documentation


Pull request:
feat: listen on file descriptor
Closes #5971

Patch:
diff --git a/config.template.yml b/config.template.yml
index 3b21adca3..0ca3b4535 100644
--- a/config.template.yml
+++ b/config.template.yml
@@ -36,7 +36,7 @@
   ## Formats:
   ##  - [<scheme>://]<hostname>[:<port>][/<path>]
   ##  - [<scheme>://][hostname]:<port>[/<path>]
-  ## Square brackets indicate optional portions of the format. Scheme must be 'tcp', 'tcp4', 'tcp6', or 'unix'.
+  ## Square brackets indicate optional portions of the format. Scheme must be 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd'.
   ## The default scheme is 'unix' if the address is an absolute path otherwise it's 'tcp'. The default port is '9091'.
   ## If the path is specified this configures the router to handle both the `/` path and the configured path.
   # address: 'tcp://:9091/'
@@ -148,7 +148,7 @@
     ## Formats:
     ##  - [<scheme>://]<hostname>[:<port>][/<path>]
     ##  - [<scheme>://][hostname]:<port>[/<path>]
-    ## Square brackets indicate optional portions of the format. Scheme must be 'tcp', 'tcp4', 'tcp6', or 'unix'.
+    ## Square brackets indicate optional portions of the format. Scheme must be 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd'.
     ## The default scheme is 'unix' if the address is an absolute path otherwise it's 'tcp'. The default port is '9959'.
     ## If the path is not specified it defaults to `/metrics`.
     # address: 'tcp://:9959/metrics'
diff --git a/docs/content/configuration/miscellaneous/server.md b/docs/content/configuration/miscellaneous/server.md
index ead3030a3..473efe00f 100644
--- a/docs/content/configuration/miscellaneous/server.md
+++ b/docs/content/configuration/miscellaneous/server.md
@@ -56,10 +56,11 @@ The [Proxy Integration](../../integration/proxies/introduction.md#important-note
 this option for when integrating it with a proxy.
 {{< /callout >}}
 
-Configures the listener address for the Main HTTP Server. The address itself is a listener and the scheme must either be
-the `unix` scheme or one of the `tcp` schemes. It can configure the host, port, and path the listener responds to.
+Configures the listener address for the Main HTTP Server. The address itself is a listener and the scheme must be the
+`unix` scheme, the `fd` scheme, or one of the `tcp` schemes. It can configure the host, port, and path the listener
+responds to.
 
-To configure the path for a unix socket see the address syntax documentation linked above.
+To configure the path for a `unix` or `fd` scheme see the address syntax documentation linked above.
 
 If the path is configured to anything other than `/` requests will be handled for both `/` and the configured path.
 For example if configured to `tcp://:{{< sitevar name="port" nojs="9091" >}}/authelia` then requests will be handled for both the `/` and `/authelia/`
@@ -82,6 +83,12 @@ server:
   address: 'unix:///var/run/authelia.sock'
 ```
 
+```yaml
+# When running "systemd-socket-activate -l 9091 go run ./cmd/authelia", the connections to port 9091 will be forwaded to file descriptor 3.
+server:
+  address: fd://:3
+```
+
 ### asset_path
 
 {{< confkey type="string" required="no" >}}
diff --git a/docs/content/configuration/prologue/common.md b/docs/content/configuration/prologue/common.md
index 9f44328c8..f5dff56bf 100644
--- a/docs/content/configuration/prologue/common.md
+++ b/docs/content/configuration/prologue/common.md
@@ -89,6 +89,15 @@ The base type for this syntax is a string.
 The address type is a string that indicates how to configure a listener (i.e. listening for connections) or connector
 (i.e. opening remote connections), which are the two primary categories of addresses.
 
+#### Query Parameters
+
+Some schemes support parameters, this table describes them.
+
+| Parameter | Listeners | Connectors |                                                                                                           Purpose                                                                                                            |
+|:---------:|:---------:|:----------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
+|  `umask`  |    Yes    |     No     |                                             Sets the umask prior to creating the socket and restores it after creating it. The value must be an octal number with 3 or 4 digits.                                             |
+|  `path`   |    Yes    |     No     | Sets the path variable to configure the subpath, specifically for a unix socket but technically works for TCP as well. Note that this should just be the alphanumeric portion it should not be prefixed with a forward slash |
+
 
 #### Format
 
@@ -123,20 +132,38 @@ available addresses when not provided.
 [<scheme>://][hostname]:<port>[/<path>]
 ```
 
+##### File Descriptors
+
+The following format represents the file descriptor format. It's valid only for a listener. Refer to the individual
+documentation for an option for clarity. In this format as per the notation there are no optional portions.
+
+The File Descriptor format also accepts a query string. The [Query Parameters](#query-parameters) described above
+control certain behavior of this address type.
+
+```text
+fd://<file descriptor number>
+```
+
+```text
+fd://<file descriptor number>?umask=0022
+```
+
+```text
+fd://<file descriptor number>?path=auth
+```
+
+```text
+fd://<file descriptor number>?umask=0022&path=auth
+```
+
 ##### Unix Domain Socket
 
 The following format represents the unix domain socket format. It's valid for both a listener and connector in most
 instances. Refer to the individual documentation for an option for clarity. In this format as per the notation there
 are no optional portions.
 
-The Unix Domain Socket format also accepts a query string. The following query parameters control certain behavior of
-this address type.
-
-| Parameter | Listeners | Connectors |                                                                                                           Purpose                                                                                                            |
-|:---------:|:---------:|:----------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
-|  `umask`  |    Yes    |     No     |                                             Sets the umask prior to creating the socket and restores it after creating it. The value must be an octal number with 3 or 4 digits.                                             |
-|  `path`   |    Yes    |     No     | Sets the path variable to configure the subpath, specifically for a unix socket but technically works for TCP as well. Note that this should just be the alphanumeric portion it should not be prefixed with a forward slash |
-
+The Unix Domain Socket format also accepts a query string. The [Query Parameters](#query-parameters) described above
+control certain behavior of this address type.
 
 ```text
 unix://<path>
diff --git a/internal/configuration/config.template.yml b/internal/configuration/config.template.yml
index 3b21adca3..0ca3b4535 100644
--- a/internal/configuration/config.template.yml
+++ b/internal/configuration/config.template.yml
@@ -36,7 +36,7 @@
   ## Formats:
   ##  - [<scheme>://]<hostname>[:<port>][/<path>]
   ##  - [<scheme>://][hostname]:<port>[/<path>]
-  ## Square brackets indicate optional portions of the format. Scheme must be 'tcp', 'tcp4', 'tcp6', or 'unix'.
+  ## Square brackets indicate optional portions of the format. Scheme must be 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd'.
   ## The default scheme is 'unix' if the address is an absolute path otherwise it's 'tcp'. The default port is '9091'.
   ## If the path is specified this configures the router to handle both the `/` path and the configured path.
   # address: 'tcp://:9091/'
@@ -148,7 +148,7 @@
     ## Formats:
     ##  - [<scheme>://]<hostname>[:<port>][/<path>]
     ##  - [<scheme>://][hostname]:<port>[/<path>]
-    ## Square brackets indicate optional portions of the format. Scheme must be 'tcp', 'tcp4', 'tcp6', or 'unix'.
+    ## Square brackets indicate optional portions of the format. Scheme must be 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd'.
     ## The default scheme is 'unix' if the address is an absolute path otherwise it's 'tcp'. The default port is '9959'.
     ## If the path is not specified it defaults to `/metrics`.
     # address: 'tcp://:9959/metrics'
diff --git a/internal/configuration/schema/const.go b/internal/configuration/schema/const.go
index 659c44ea4..004b4ba26 100644
--- a/internal/configuration/schema/const.go
+++ b/internal/configuration/schema/const.go
@@ -122,6 +122,7 @@ const (
 
 const (
 	addressQueryParamUmask = "umask"
+	addressQueryParamPath  = "path"
 )
 
 const (
@@ -173,17 +174,18 @@ const (
 
 // Address Schemes.
 const (
-	AddressSchemeTCP         = "tcp"
-	AddressSchemeTCP4        = "tcp4"
-	AddressSchemeTCP6        = "tcp6"
-	AddressSchemeUDP         = "udp"
-	AddressSchemeUDP4        = "udp4"
-	AddressSchemeUDP6        = "udp6"
-	AddressSchemeUnix        = "unix"
-	AddressSchemeLDAP        = "ldap"
-	AddressSchemeLDAPS       = "ldaps"
-	AddressSchemeLDAPI       = "ldapi"
-	AddressSchemeSMTP        = "smtp"
-	AddressSchemeSUBMISSION  = "submission"
-	AddressSchemeSUBMISSIONS = "submissions"
+	AddressSchemeTCP            = "tcp"
+	AddressSchemeTCP4           = "tcp4"
+	AddressSchemeTCP6           = "tcp6"
+	AddressSchemeUDP            = "udp"
+	AddressSchemeUDP4           = "udp4"
+	AddressSchemeUDP6           = "udp6"
+	AddressSchemeUnix           = "unix"
+	AddressSchemeLDAP           = "ldap"
+	AddressSchemeLDAPS          = "ldaps"
+	AddressSchemeLDAPI          = "ldapi"
+	AddressSchemeSMTP           = "smtp"
+	AddressSchemeSUBMISSION     = "submission"
+	AddressSchemeSUBMISSIONS    = "submissions"
+	AddressSchemeFileDescriptor = "fd"
 )
diff --git a/internal/configuration/schema/notifier.go b/internal/configuration/schema/notifier.go
index 08567e9a1..be17e4ae1 100644
--- a/internal/configuration/schema/notifier.go
+++ b/internal/configuration/schema/notifier.go
@@ -44,7 +44,7 @@ type NotifierSMTP struct {
 
 // DefaultSMTPNotifierConfiguration represents default configuration parameters for the SMTP notifier.
 var DefaultSMTPNotifierConfiguration = NotifierSMTP{
-	Address:             &AddressSMTP{Address{true, false, -1, 25, &url.URL{Scheme: AddressSchemeSMTP, Host: "localhost:25"}}},
+	Address:             &AddressSMTP{Address{true, false, -1, 25, nil, &url.URL{Scheme: AddressSchemeSMTP, Host: "localhost:25"}}},
 	Timeout:             time.Second * 5,
 	Subject:             "[Authelia] {title}",
 	Identifier:          "localhost",
diff --git a/internal/configuration/schema/server.go b/internal/configuration/schema/server.go
index 1a4b1c2fe..297219318 100644
--- a/internal/configuration/schema/server.go
+++ b/internal/configuration/schema/server.go
@@ -76,7 +76,7 @@ type ServerEndpointRateLimitBucket struct {
 
 // DefaultServerConfiguration represents the default values of the Server.
 var DefaultServerConfiguration = Server{
-	Address: &AddressTCP{Address{true, false, -1, 9091, &url.URL{Scheme: AddressSchemeTCP, Host: ":9091", Path: "/"}}},
+	Address: &AddressTCP{Address{true, false, -1, 9091, nil, &url.URL{Scheme: AddressSchemeTCP, Host: ":9091", Path: "/"}}},
 	Buffers: ServerBuffers{
 		Read:  4096,
 		Write: 4096,
diff --git a/internal/configuration/schema/storage.go b/internal/configuration/schema/storage.go
index 4bdf397f5..dcd93f876 100644
--- a/internal/configuration/schema/storage.go
+++ b/internal/configuration/schema/storage.go
@@ -68,7 +68,7 @@ var DefaultSQLStorageConfiguration = StorageSQL{
 // DefaultMySQLStorageConfiguration represents the default MySQL configuration.
 var DefaultMySQLStorageConfiguration = StorageMySQL{
 	StorageSQL: StorageSQL{
-		Address: &AddressTCP{Address{true, false, -1, 3306, &url.URL{Scheme: AddressSchemeTCP, Host: "localhost:3306"}}},
+		Address: &AddressTCP{Address{true, false, -1, 3306, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "localhost:3306"}}},
 		TLS: &TLS{
 			MinimumVersion: TLSVersion{tls.VersionTLS12},
 		},
@@ -78,14 +78,14 @@ var DefaultMySQLStorageConfiguration = StorageMySQL{
 // DefaultPostgreSQLStorageConfiguration represents the default PostgreSQL configuration.
 var DefaultPostgreSQLStorageConfiguration = StoragePostgreSQL{
 	StorageSQL: StorageSQL{
-		Address: &AddressTCP{Address{true, false, -1, 5432, &url.URL{Scheme: AddressSchemeTCP, Host: "localhost:5432"}}},
+		Address: &AddressTCP{Address{true, false, -1, 5432, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "localhost:5432"}}},
 		TLS: &TLS{
 			MinimumVersion: TLSVersion{tls.VersionTLS12},
 		},
 	},
 	Servers: []StoragePostgreSQLServer{
 		{
-			Address: &AddressTCP{Address{true, false, -1, 5432, &url.URL{Scheme: AddressSchemeTCP, Host: "localhost:5432"}}},
+			Address: &AddressTCP{Address{true, false, -1, 5432, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "localhost:5432"}}},
 			TLS: &TLS{
 				MinimumVersion: TLSVersion{tls.VersionTLS12},
 			},
diff --git a/internal/configuration/schema/telemetry.go b/internal/configuration/schema/telemetry.go
index f5b53ad42..ca5c8cca7 100644
--- a/internal/configuration/schema/telemetry.go
+++ b/internal/configuration/schema/telemetry.go
@@ -22,7 +22,7 @@ type TelemetryMetrics struct {
 // DefaultTelemetryConfig is the default telemetry configuration.
 var DefaultTelemetryConfig = Telemetry{
 	Metrics: TelemetryMetrics{
-		Address: &AddressTCP{Address{true, false, -1, 9959, &url.URL{Scheme: AddressSchemeTCP, Host: ":9959", Path: "/metrics"}}},
+		Address: &AddressTCP{Address{true, false, -1, 9959, nil, &url.URL{Scheme: AddressSchemeTCP, Host: ":9959", Path: "/metrics"}}},
 		Buffers: ServerBuffers{
 			Read:  4096,
 			Write: 4096,
diff --git a/internal/configuration/schema/types_address.go b/internal/configuration/schema/types_address.go
index 7cdcf2476..60bb90791 100644
--- a/internal/configuration/schema/types_address.go
+++ b/internal/configuration/schema/types_address.go
@@ -22,7 +22,7 @@ func NewAddress(value string) (address *Address, err error) {
 // else without a scheme is the schemeDefault scheme.
 func NewAddressDefault(value, schemeDefault, schemeDefaultPath string) (address *Address, err error) {
 	if len(value) == 0 {
-		return &Address{true, false, -1, 0, &url.URL{Scheme: AddressSchemeTCP, Host: ":0"}}, nil
+		return &Address{true, false, -1, 0, nil, &url.URL{Scheme: AddressSchemeTCP, Host: ":0"}}, nil
 	}
 
 	var u *url.URL
@@ -72,7 +72,7 @@ func NewAddressFromNetworkValuesDefault(value string, port uint16, schemeDefault
 
 // NewAddressUnix returns an *Address from a path value.
 func NewAddressUnix(path string) Address {
-	return Address{true, true, -1, 0, &url.URL{Scheme: AddressSchemeUnix, Path: path}}
+	return Address{true, true, -1, 0, nil, &url.URL{Scheme: AddressSchemeUnix, Path: path}}
 }
 
 // NewAddressFromNetworkValues returns an *Address from network values.
@@ -82,7 +82,7 @@ func NewAddressFromNetworkValues(network, host string, port uint16) Address {
 
 // NewAddressFromNetworkPathValues returns an *Address from network values and a path.
 func NewAddressFromNetworkPathValues(network, host string, port uint16, path string) Address {
-	return Address{true, false, -1, port, &url.URL{Scheme: network, Host: fmt.Sprintf("%s:%d", host, port), Path: path}}
+	return Address{true, false, -1, port, nil, &url.URL{Scheme: network, Host: fmt.Sprintf("%s:%d", host, port), Path: path}}
 }
 
 // NewSMTPAddress returns an *AddressSMTP from SMTP values.
@@ -109,7 +109,7 @@ func NewSMTPAddress(scheme, host string, port uint16) *AddressSMTP {
 		}
 	}
 
-	return &AddressSMTP{Address: Address{true, false, -1, port, &url.URL{Scheme: scheme, Host: fmt.Sprintf("%s:%d", host, port)}}}
+	return &AddressSMTP{Address: Address{true, false, -1, port, nil, &url.URL{Scheme: scheme, Host: fmt.Sprintf("%s:%d", host, port)}}}
 }
 
 // NewAddressFromURL returns an *Address and error depending on the ability to parse the *url.URL as an Address.
@@ -188,6 +188,7 @@ type Address struct {
 	socket bool
 	umask  int
 	port   uint16
+	fd     *uint64
 
 	url *url.URL
 }
@@ -220,6 +221,11 @@ func (a *Address) IsUnixDomainSocket() bool {
 	return a.socket
 }
 
+// IsFileDescriptor returns true if the address has been determined to be a File Descriptor.
+func (a *Address) IsFileDescriptor() bool {
+	return a.fd != nil
+}
+
 // IsTCP returns true if the address is one of the TCP schemes (not including application schemes that use TCP).
 func (a *Address) IsTCP() bool {
 	switch a.Scheme() {
@@ -253,10 +259,10 @@ func (a *Address) IsExplicitlySecure() bool {
 // ValidateListener returns true if the Address is valid for a connection listener.
 func (a *Address) ValidateListener() error {
 	switch a.Scheme() {
-	case AddressSchemeTCP, AddressSchemeTCP4, AddressSchemeTCP6, AddressSchemeUDP, AddressSchemeUDP4, AddressSchemeUDP6, AddressSchemeUnix:
+	case AddressSchemeTCP, AddressSchemeTCP4, AddressSchemeTCP6, AddressSchemeUDP, AddressSchemeUDP4, AddressSchemeUDP6, AddressSchemeUnix, AddressSchemeFileDescriptor:
 		break
 	default:
-		return fmt.Errorf("scheme must be one of 'tcp', 'tcp4', 'tcp6', 'udp', 'udp4', 'udp6', or 'unix' but is configured as '%s'", a.Scheme())
+		return fmt.Errorf("scheme must be one of 'tcp', 'tcp4', 'tcp6', 'udp', 'udp4', 'udp6', 'unix', or 'fd' but is configured as '%s'", a.Scheme())
 	}
 
 	return nil
@@ -269,10 +275,10 @@ func (a *Address) ValidateHTTP() error {
 	}
 
 	switch a.Scheme() {
-	case AddressSchemeUnix:
+	case AddressSchemeUnix, AddressSchemeFileDescriptor:
 		return nil
 	default:
-		return fmt.Errorf("scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as '%s'", a.Scheme())
+		return fmt.Errorf("scheme must be one of 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd' but is configured as '%s'", a.Scheme())
 	}
 }
 
@@ -296,7 +302,7 @@ func (a *Address) ValidateSQL() error {
 	case AddressSchemeUnix:
 		return nil
 	default:
-		return fmt.Errorf("scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as '%s'", a.Scheme())
+		return fmt.Errorf("scheme must be one of 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd' but is configured as '%s'", a.Scheme())
 	}
 }
 
@@ -389,9 +395,9 @@ func (a *Address) RouterPath() string {
 		return ""
 	}
 
-	if a.socket {
-		if a.url.Query().Has("path") {
-			return fmt.Sprintf("/%s", a.url.Query().Get("path"))
+	if a.socket || a.fd != nil {
+		if a.url.Query().Has(addressQueryParamPath) {
+			return fmt.Sprintf("/%s", a.url.Query().Get(addressQueryParamPath))
 		}
 
 		return "/"
@@ -470,7 +476,7 @@ func (a *Address) validate() (err error) {
 	}
 
 	switch {
-	case a.url.RawQuery != "" && a.url.Scheme != AddressSchemeUnix:
+	case a.url.RawQuery != "" && a.url.Scheme != AddressSchemeUnix && a.url.Scheme != AddressSchemeFileDescriptor:
 		return fmt.Errorf("error validating the address: the url '%s' appears to have a query but this is not valid for addresses with the '%s' scheme", a.url.String(), a.url.Scheme)
 	case a.url.RawFragment != "", a.url.Fragment != "":
 		return fmt.Errorf("error validating the address: the url '%s' appears to have a fragment but this is not valid for addresses", a.url.String())
@@ -501,6 +507,10 @@ func (a *Address) validate() (err error) {
 		if err = a.validateProtocol(); err != nil {
 			return err
 		}
+	case AddressSchemeFileDescriptor:
+		if err = a.validateFD(); err != nil {
+			return err
+		}
 	}
 
 	a.valid = true
@@ -588,3 +598,32 @@ func (a *Address) validateUnixSocket() (err error) {
 
 	return nil
 }
+
+func (a *Address) validateFD() (err error) {
+	var actualFD uint64
+
+	if actualFD, err = strconv.ParseUint(a.url.Host, 10, 64); err != nil {
+		return fmt.Errorf("failed to parse file descriptor: %w", err)
+	}
+
+	umask := -1
+
+	if a.url.Query().Has(addressQueryParamUmask) {
+		v := a.url.Query().Get(addressQueryParamUmask)
+
+		if !regexpIsUmask.MatchString(v) {
+			return fmt.Errorf("error validating the file descriptor address: could not parse address '%s': the address has a umask value of '%s' which does not appear to be a valid octal string", a.url.String(), v)
+		}
+
+		var p int64
+
+		p, _ = strconv.ParseInt(v, 8, 0)
+
+		umask = int(p)
+	}
+
+	a.fd = &actualFD
+	a.umask = umask
+
+	return nil
+}
diff --git a/internal/configuration/schema/types_addresses_nix.go b/internal/configuration/schema/types_addresses_nix.go
index aeee2fbd1..377067f95 100644
--- a/internal/configuration/schema/types_addresses_nix.go
+++ b/internal/configuration/schema/types_addresses_nix.go
@@ -5,6 +5,8 @@ package schema
 import (
 	"fmt"
 	"net"
+	"os"
+	"strconv"
 	"syscall"
 )
 
@@ -14,15 +16,37 @@ func (a *Address) Listener() (ln net.Listener, err error) {
 		return nil, fmt.Errorf("address url is nil")
 	}
 
-	if a.socket && a.umask != -1 {
-		umask := syscall.Umask(a.umask)
+	var create func() (ln net.Listener, err error)
 
-		ln, err = net.Listen(a.Network(), a.NetworkAddress())
+	if a.fd != nil {
+		create = func() (ln net.Listener, err error) {
+			fd := os.NewFile(uintptr(*a.fd), strconv.FormatUint(*a.fd, 10))
 
-		_ = syscall.Umask(umask)
+			defer func() {
+				_ = fd.Close()
+			}()
+
+			return net.FileListener(fd)
+		}
+	} else {
+		create = func() (ln net.Listener, err error) {
+			return net.Listen(a.Network(), a.NetworkAddress())
+		}
+	}
+
+	return a.listenerWithUmask(create)
+}
 
-		return ln, err
+func (a *Address) listenerWithUmask(create func() (net.Listener, error)) (ln net.Listener, err error) {
+	if a.umask == -1 {
+		return create()
 	}
 
-	return net.Listen(a.Network(), a.NetworkAddress())
+	umask := syscall.Umask(a.umask)
+
+	defer func() {
+		_ = syscall.Umask(umask)
+	}()
+
+	return create()
 }


Test patch:
diff --git a/internal/configuration/schema/types_address_test.go b/internal/configuration/schema/types_address_test.go
index bc2adf25c..7a13e3945 100644
--- a/internal/configuration/schema/types_address_test.go
+++ b/internal/configuration/schema/types_address_test.go
@@ -12,6 +12,8 @@ import (
 )
 
 func TestNewAddressFromString(t *testing.T) {
+	four := uint64(4)
+
 	testCases := []struct {
 		name                                         string
 		have                                         string
@@ -21,7 +23,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldParseBasicAddress",
 			"tcp://0.0.0.0:9091",
-			&Address{true, false, -1, 9091, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:9091"}},
+			&Address{true, false, -1, 9091, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:9091"}},
 			"0.0.0.0:9091",
 			"tcp://0.0.0.0:9091",
 			"",
@@ -29,7 +31,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldParseEmptyAddress",
 			"",
-			&Address{true, false, -1, 0, &url.URL{Scheme: AddressSchemeTCP, Host: ":0"}},
+			&Address{true, false, -1, 0, nil, &url.URL{Scheme: AddressSchemeTCP, Host: ":0"}},
 			":0",
 			"tcp://:0",
 			"",
@@ -37,7 +39,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldParseAddressMissingScheme",
 			"0.0.0.0:9091",
-			&Address{true, false, -1, 9091, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:9091"}},
+			&Address{true, false, -1, 9091, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:9091"}},
 			"0.0.0.0:9091",
 			"tcp://0.0.0.0:9091",
 			"",
@@ -45,7 +47,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldParseUnixAddressMissingScheme",
 			"/var/run/example.sock",
-			&Address{true, true, -1, 0, &url.URL{Scheme: AddressSchemeUnix, Path: "/var/run/example.sock"}},
+			&Address{true, true, -1, 0, nil, &url.URL{Scheme: AddressSchemeUnix, Path: "/var/run/example.sock"}},
 			"/var/run/example.sock",
 			"unix:///var/run/example.sock",
 			"",
@@ -53,7 +55,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldParseAddressMissingPort",
 			"tcp://0.0.0.0",
-			&Address{true, false, -1, 0, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:0"}},
+			&Address{true, false, -1, 0, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:0"}},
 			"0.0.0.0:0",
 			"tcp://0.0.0.0:0",
 			"",
@@ -85,7 +87,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldParseUnixSocket",
 			"unix:///path/to/a/socket.sock",
-			&Address{true, true, -1, 0, &url.URL{Scheme: AddressSchemeUnix, Path: "/path/to/a/socket.sock"}},
+			&Address{true, true, -1, 0, nil, &url.URL{Scheme: AddressSchemeUnix, Path: "/path/to/a/socket.sock"}},
 			"/path/to/a/socket.sock",
 			"unix:///path/to/a/socket.sock",
 			"",
@@ -101,7 +103,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldParseUnixSocketWithPort",
 			"unix://:5432/path/to/a/socket.sock",
-			&Address{true, true, -1, 5432, &url.URL{Scheme: AddressSchemeUnix, Host: ":5432", Path: "/path/to/a/socket.sock"}},
+			&Address{true, true, -1, 5432, nil, &url.URL{Scheme: AddressSchemeUnix, Host: ":5432", Path: "/path/to/a/socket.sock"}},
 			"/path/to/a/socket.sock",
 			"unix://:5432/path/to/a/socket.sock",
 			"",
@@ -125,7 +127,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldParseUnixSocketWithQuery",
 			"unix:///path/to/a/socket.sock?umask=0022",
-			&Address{true, true, 18, 0, &url.URL{Scheme: AddressSchemeUnix, Path: "/path/to/a/socket.sock", RawQuery: "umask=0022"}},
+			&Address{true, true, 18, 0, nil, &url.URL{Scheme: AddressSchemeUnix, Path: "/path/to/a/socket.sock", RawQuery: "umask=0022"}},
 			"/path/to/a/socket.sock",
 			"unix:///path/to/a/socket.sock?umask=0022",
 			"",
@@ -133,7 +135,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldParseAbstractUnixSocket",
 			"unix://@abstract",
-			&Address{true, true, -1, 0, &url.URL{Scheme: AddressSchemeUnix, User: url.User(""), Host: "abstract", Path: ""}},
+			&Address{true, true, -1, 0, nil, &url.URL{Scheme: AddressSchemeUnix, User: url.User(""), Host: "abstract", Path: ""}},
 			"@abstract",
 			"unix://@abstract",
 			"",
@@ -141,7 +143,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldParseAbstractUnixSocketWithSlash",
 			"unix://@abstract/path",
-			&Address{true, true, -1, 0, &url.URL{Scheme: AddressSchemeUnix, User: url.User(""), Host: "abstract", Path: "/path"}},
+			&Address{true, true, -1, 0, nil, &url.URL{Scheme: AddressSchemeUnix, User: url.User(""), Host: "abstract", Path: "/path"}},
 			"@abstract/path",
 			"unix://@abstract/path",
 			"",
@@ -165,11 +167,35 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldParseUnknownScheme",
 			"a://0.0.0.0",
-			&Address{true, false, -1, 0, &url.URL{Scheme: "a", Host: "0.0.0.0"}},
+			&Address{true, false, -1, 0, nil, &url.URL{Scheme: "a", Host: "0.0.0.0"}},
 			"0.0.0.0",
 			"a://0.0.0.0",
 			"",
 		},
+		{
+			"ShouldParseFileDescriptor",
+			"fd://4",
+			&Address{true, false, -1, 0, &four, &url.URL{Scheme: "fd", Host: "4"}},
+			"4",
+			"fd://4",
+			"",
+		},
+		{
+			"ShouldParseFileDescriptorWithUmask",
+			"fd://4?umask=0022",
+			&Address{true, false, 18, 0, &four, &url.URL{Scheme: "fd", Host: "4", RawQuery: "umask=0022"}},
+			"4",
+			"fd://4?umask=0022",
+			"",
+		},
+		{
+			"ShouldParseFileDescriptorWithUmaskAndPath",
+			"fd://4?umask=0022&path=example",
+			&Address{true, false, 18, 0, &four, &url.URL{Scheme: "fd", Host: "4", RawQuery: "umask=0022&path=example"}},
+			"4",
+			"fd://4?umask=0022&path=example",
+			"",
+		},
 		{
 			"ShouldNotParseInvalidPort",
 			"tcp://0.0.0.0:abc",
@@ -197,7 +223,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldSetDefaultPortLDAP",
 			"ldap://127.0.0.1",
-			&Address{true, false, -1, 389, &url.URL{Scheme: AddressSchemeLDAP, Host: "127.0.0.1:389"}},
+			&Address{true, false, -1, 389, nil, &url.URL{Scheme: AddressSchemeLDAP, Host: "127.0.0.1:389"}},
 			"127.0.0.1:389",
 			"ldap://127.0.0.1:389",
 			"",
@@ -205,7 +231,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldSetDefaultPortLDAPS",
 			"ldaps://127.0.0.1",
-			&Address{true, false, -1, 636, &url.URL{Scheme: AddressSchemeLDAPS, Host: "127.0.0.1:636"}},
+			&Address{true, false, -1, 636, nil, &url.URL{Scheme: AddressSchemeLDAPS, Host: "127.0.0.1:636"}},
 			"127.0.0.1:636",
 			"ldaps://127.0.0.1:636",
 			"",
@@ -213,7 +239,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldAllowLDAPI",
 			"ldapi:///abc",
-			&Address{true, true, -1, 0, &url.URL{Scheme: AddressSchemeLDAPI, Path: "/abc"}},
+			&Address{true, true, -1, 0, nil, &url.URL{Scheme: AddressSchemeLDAPI, Path: "/abc"}},
 			"/abc",
 			"ldapi:///abc",
 			"",
@@ -221,7 +247,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldAllowImplicitLDAPI",
 			"ldapi://",
-			&Address{true, true, -1, 0, &url.URL{Scheme: AddressSchemeLDAPI, Path: ""}},
+			&Address{true, true, -1, 0, nil, &url.URL{Scheme: AddressSchemeLDAPI, Path: ""}},
 			"",
 			"ldapi:",
 			"",
@@ -229,7 +255,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldAllowImplicitLDAPINoSlash",
 			"ldapi:",
-			&Address{true, true, -1, 0, &url.URL{Scheme: AddressSchemeLDAPI, Path: ""}},
+			&Address{true, true, -1, 0, nil, &url.URL{Scheme: AddressSchemeLDAPI, Path: ""}},
 			"",
 			"ldapi:",
 			"",
@@ -237,7 +263,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldSetDefaultPortSMTP",
 			"smtp://127.0.0.1",
-			&Address{true, false, -1, 25, &url.URL{Scheme: AddressSchemeSMTP, Host: "127.0.0.1:25"}},
+			&Address{true, false, -1, 25, nil, &url.URL{Scheme: AddressSchemeSMTP, Host: "127.0.0.1:25"}},
 			"127.0.0.1:25",
 			"smtp://127.0.0.1:25",
 			"",
@@ -245,7 +271,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldSetDefaultPortSUBMISSION",
 			"submission://127.0.0.1",
-			&Address{true, false, -1, 587, &url.URL{Scheme: AddressSchemeSUBMISSION, Host: "127.0.0.1:587"}},
+			&Address{true, false, -1, 587, nil, &url.URL{Scheme: AddressSchemeSUBMISSION, Host: "127.0.0.1:587"}},
 			"127.0.0.1:587",
 			"submission://127.0.0.1:587",
 			"",
@@ -253,7 +279,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldSetDefaultPortSUBMISSIONS",
 			"submissions://127.0.0.1",
-			&Address{true, false, -1, 465, &url.URL{Scheme: AddressSchemeSUBMISSIONS, Host: "127.0.0.1:465"}},
+			&Address{true, false, -1, 465, nil, &url.URL{Scheme: AddressSchemeSUBMISSIONS, Host: "127.0.0.1:465"}},
 			"127.0.0.1:465",
 			"submissions://127.0.0.1:465",
 			"",
@@ -261,7 +287,7 @@ func TestNewAddressFromString(t *testing.T) {
 		{
 			"ShouldNotOverridePort",
 			"ldap://127.0.0.1:123",
-			&Address{true, false, -1, 123, &url.URL{Scheme: AddressSchemeLDAP, Host: "127.0.0.1:123"}},
+			&Address{true, false, -1, 123, nil, &url.URL{Scheme: AddressSchemeLDAP, Host: "127.0.0.1:123"}},
 			"127.0.0.1:123",
 			"ldap://127.0.0.1:123",
 			"",
@@ -296,25 +322,25 @@ func TestAddress_ValidateErrors(t *testing.T) {
 	}{
 		{
 			"ShouldValidateLDAPAddress",
-			&Address{true, false, -1, 0, &url.URL{Scheme: AddressSchemeLDAP, Host: "127.0.0.1"}},
+			&Address{true, false, -1, 0, nil, &url.URL{Scheme: AddressSchemeLDAP, Host: "127.0.0.1"}},
 			"",
 			"scheme must be one of 'smtp', 'submission', or 'submissions' but is configured as 'ldap'",
-			"scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'ldap'",
-			"scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'ldap'",
-			"scheme must be one of 'tcp', 'tcp4', 'tcp6', 'udp', 'udp4', 'udp6', or 'unix' but is configured as 'ldap'",
+			"scheme must be one of 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd' but is configured as 'ldap'",
+			"scheme must be one of 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd' but is configured as 'ldap'",
+			"scheme must be one of 'tcp', 'tcp4', 'tcp6', 'udp', 'udp4', 'udp6', 'unix', or 'fd' but is configured as 'ldap'",
 		},
 		{
 			"ShouldValidateSMTPAddress",
-			&Address{true, false, -1, 0, &url.URL{Scheme: AddressSchemeSMTP, Host: "127.0.0.1"}},
+			&Address{true, false, -1, 0, nil, &url.URL{Scheme: AddressSchemeSMTP, Host: "127.0.0.1"}},
 			"scheme must be one of 'ldap', 'ldaps', or 'ldapi' but is configured as 'smtp'",
 			"",
-			"scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'smtp'",
-			"scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'smtp'",
-			"scheme must be one of 'tcp', 'tcp4', 'tcp6', 'udp', 'udp4', 'udp6', or 'unix' but is configured as 'smtp'",
+			"scheme must be one of 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd' but is configured as 'smtp'",
+			"scheme must be one of 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd' but is configured as 'smtp'",
+			"scheme must be one of 'tcp', 'tcp4', 'tcp6', 'udp', 'udp4', 'udp6', 'unix', or 'fd' but is configured as 'smtp'",
 		},
 		{
 			"ShouldValidateTCPAddress",
-			&Address{true, false, -1, 0, &url.URL{Scheme: AddressSchemeTCP, Host: "127.0.0.1"}},
+			&Address{true, false, -1, 0, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "127.0.0.1"}},
 			"scheme must be one of 'ldap', 'ldaps', or 'ldapi' but is configured as 'tcp'",
 			"scheme must be one of 'smtp', 'submission', or 'submissions' but is configured as 'tcp'",
 			"",
@@ -323,7 +349,7 @@ func TestAddress_ValidateErrors(t *testing.T) {
 		},
 		{
 			"ShouldValidateUnixSocket",
-			&Address{true, true, -1, 0, &url.URL{Scheme: AddressSchemeUnix, Path: "/path/to/socket"}},
+			&Address{true, true, -1, 0, nil, &url.URL{Scheme: AddressSchemeUnix, Path: "/path/to/socket"}},
 			"scheme must be one of 'ldap', 'ldaps', or 'ldapi' but is configured as 'unix'",
 			"scheme must be one of 'smtp', 'submission', or 'submissions' but is configured as 'unix'",
 			"",
@@ -368,7 +394,7 @@ func TestAddress_ValidateErrors(t *testing.T) {
 }
 
 func TestAddress_SetHostname(t *testing.T) {
-	address := &Address{true, false, -1, 0, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0"}}
+	address := &Address{true, false, -1, 0, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0"}}
 
 	assert.Equal(t, "tcp://0.0.0.0", address.String())
 
@@ -387,7 +413,7 @@ func TestAddressOutputValues(t *testing.T) {
 	address = &Address{}
 	assert.EqualError(t, address.validate(), "error validating the address: address url was nil")
 
-	address = &Address{false, false, -1, 0, nil}
+	address = &Address{false, false, -1, 0, nil, nil}
 
 	assert.Equal(t, "", address.String())
 	assert.Equal(t, "", address.Scheme())
@@ -401,7 +427,7 @@ func TestAddressOutputValues(t *testing.T) {
 	assert.Nil(t, listener)
 	assert.EqualError(t, err, "address url is nil")
 
-	address = &Address{true, false, -1, 8080, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:8080"}}
+	address = &Address{true, false, -1, 8080, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:8080"}}
 
 	assert.Equal(t, "tcp://0.0.0.0:8080", address.String())
 	assert.Equal(t, "tcp", address.Scheme())
@@ -415,7 +441,7 @@ func TestAddressOutputValues(t *testing.T) {
 	assert.NotNil(t, listener)
 	assert.NoError(t, err)
 
-	address = &Address{true, false, -1, 0, nil}
+	address = &Address{true, false, -1, 0, nil, nil}
 
 	assert.Equal(t, "", address.String())
 	assert.Equal(t, "", address.Scheme())
@@ -457,7 +483,7 @@ func TestAddressOutputValues(t *testing.T) {
 
 	assert.Equal(t, "/abc", address.Path())
 
-	address = &Address{true, false, -1, 9091, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:9091"}}
+	address = &Address{true, false, -1, 9091, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:9091"}}
 
 	assert.Equal(t, "tcp://0.0.0.0:9091", address.String())
 	assert.Equal(t, "tcp", address.Scheme())
@@ -497,6 +523,22 @@ func TestAddressOutputValues(t *testing.T) {
 	assert.Equal(t, "example.com", address.Hostname())
 	assert.Equal(t, "example.com:9092", address.NetworkAddress())
 	assert.Equal(t, uint16(9092), address.Port())
+
+	address = &Address{true, false, -1, 9091, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "0.0.0.0:9091"}}
+
+	assert.Equal(t, "tcp://0.0.0.0:9091", address.String())
+	assert.Equal(t, "tcp", address.Scheme())
+	assert.Equal(t, "0.0.0.0:9091", address.Host())
+	assert.Equal(t, "0.0.0.0", address.Hostname())
+	assert.Equal(t, "0.0.0.0:9091", address.NetworkAddress())
+	assert.Equal(t, uint16(9091), address.Port())
+
+	listener, err = address.Listener()
+
+	assert.NotNil(t, listener)
+	assert.NoError(t, err)
+
+	assert.NoError(t, listener.Close())
 }
 
 func TestNewAddressUnix(t *testing.T) {
@@ -623,19 +665,19 @@ func TestAddress_Dial(t *testing.T) {
 	}{
 		{
 			"ShouldNotDialNil",
-			Address{true, false, -1, 0, nil},
+			Address{true, false, -1, 0, nil, nil},
 			false,
 			"address url is nil",
 		},
 		{
 			"ShouldNotDialInvalid",
-			Address{false, false, -1, 0, &url.URL{}},
+			Address{false, false, -1, 0, nil, &url.URL{}},
 			false,
 			"address url is nil",
 		},
 		{
 			"ShouldNotDialInvalidAddress",
-			Address{true, false, -1, 0, &url.URL{Scheme: "abc", Host: "127.0.0.1:0"}},
+			Address{true, false, -1, 0, nil, &url.URL{Scheme: "abc", Host: "127.0.0.1:0"}},
 			false,
 			"dial tcp 127.0.0.1:0: connect: connection refused",
 		},
@@ -671,65 +713,91 @@ func TestAddress_Dial(t *testing.T) {
 func TestAddress_UnixDomainSocket(t *testing.T) {
 	dir := t.TempDir()
 
+	four := uint64(4)
+
 	testCases := []struct {
 		name     string
 		have     string
 		socket   bool
+		fd       *uint64
 		path     string
 		rpath    string
 		strUmask string
 		umask    int
 		err      string
+		lnerr    string
 	}{
 		{
 			"ShouldNotBeSocket",
 			"tcp://:9091",
 			false,
+			nil,
 			"",
 			"",
 			"",
 			-1,
 			"",
+			"",
 		},
 		{
 			"ShouldParseSocket",
 			fmt.Sprintf("unix://%s", filepath.Join(dir, "example.sock")),
 			true,
+			nil,
 			filepath.Join(dir, "example.sock"),
 			"/",
 			"",
 			-1,
 			"",
+			"",
 		},
 		{
 			"ShouldParseSocketWithUmask",
 			fmt.Sprintf("unix://%s?umask=0022", filepath.Join(dir, "example.sock")),
 			true,
+			nil,
 			filepath.Join(dir, "example.sock"),
 			"/",
 			"0022",
 			18,
 			"",
+			"",
 		},
 		{
 			"ShouldParseSocketWithUmaskAndPath",
 			fmt.Sprintf("unix://%s?umask=0022&path=abc", filepath.Join(dir, "example.sock")),
 			true,
+			nil,
 			filepath.Join(dir, "example.sock"),
 			"/abc",
 			"0022",
 			18,
 			"",
+			"",
+		},
+		{
+			"ShouldParseFileDescriptorWithUmaskAndPath",
+			"fd://4?umask=0022&path=abc",
+			false,
+			&four,
+			"",
+			"/abc",
+			"0022",
+			18,
+			"",
+			"file file+net 4: getsockopt: socket operation on non-socket",
 		},
 		{
 			"ShouldParseSocketWithBadUmask",
 			fmt.Sprintf("unix://%s?umask=abc", filepath.Join(dir, "example.sock")),
 			true,
+			nil,
 			"",
 			"",
 			"",
 			-1,
 			fmt.Sprintf("error validating the unix socket address: could not parse address 'unix://%s?umask=abc': the address has a umask value of 'abc' which does not appear to be a valid octal string", filepath.Join(dir, "example.sock")),
+			"",
 		},
 	}
 
@@ -740,6 +808,13 @@ func TestAddress_UnixDomainSocket(t *testing.T) {
 			if tc.err == "" {
 				require.NoError(t, err)
 				assert.Equal(t, tc.socket, actual.IsUnixDomainSocket())
+
+				if tc.fd != nil {
+					require.NotNil(t, actual.fd)
+					assert.True(t, actual.IsFileDescriptor())
+					assert.Equal(t, *tc.fd, *actual.fd)
+				}
+
 				assert.Equal(t, tc.path, actual.Path())
 				assert.Equal(t, tc.rpath, actual.RouterPath())
 				assert.Equal(t, tc.strUmask, actual.Umask())
@@ -747,10 +822,15 @@ func TestAddress_UnixDomainSocket(t *testing.T) {
 
 				ln, err := actual.Listener()
 
-				assert.NoError(t, err)
-				assert.NotNil(t, ln)
+				if tc.lnerr != "" {
+					assert.EqualError(t, err, tc.lnerr)
+					assert.Nil(t, ln)
+				} else {
+					assert.NoError(t, err)
+					assert.NotNil(t, ln)
 
-				assert.NoError(t, ln.Close())
+					assert.NoError(t, ln.Close())
+				}
 			} else {
 				assert.EqualError(t, err, tc.err)
 			}
@@ -766,22 +846,22 @@ func TestAddress_SocketHostname(t *testing.T) {
 	}{
 		{
 			"ShouldReturnHostname",
-			Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeTCP, Host: "examplea:80"}},
+			Address{true, false, -1, 80, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "examplea:80"}},
 			"examplea",
 		},
 		{
 			"ShouldReturnPath",
-			Address{true, true, -1, 80, &url.URL{Scheme: AddressSchemeUnix, Path: "/abc/123"}},
+			Address{true, true, -1, 80, nil, &url.URL{Scheme: AddressSchemeUnix, Path: "/abc/123"}},
 			"/abc/123",
 		},
 		{
 			"ShouldReturnNothing",
-			Address{false, true, -1, 80, &url.URL{Scheme: AddressSchemeUnix, Path: "/abc/123"}},
+			Address{false, true, -1, 80, nil, &url.URL{Scheme: AddressSchemeUnix, Path: "/abc/123"}},
 			"",
 		},
 		{
 			"ShouldReturnNothingNil",
-			Address{true, true, -1, 80, nil},
+			Address{true, true, -1, 80, nil, nil},
 			"",
 		},
 	}
@@ -801,22 +881,22 @@ func TestAddress_Path(t *testing.T) {
 	}{
 		{
 			"ShouldReturnEmptyPath",
-			Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta"}},
+			Address{true, false, -1, 80, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta"}},
 			"",
 		},
 		{
 			"ShouldReturnPath",
-			Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta", Path: "/apath"}},
+			Address{true, false, -1, 80, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta", Path: "/apath"}},
 			"/apath",
 		},
 		{
 			"ShouldNotReturnPathInvalid",
-			Address{false, false, -1, 80, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta", Path: "/apath"}},
+			Address{false, false, -1, 80, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta", Path: "/apath"}},
 			"",
 		},
 		{
 			"ShouldNotReturnPathNil",
-			Address{true, false, -1, 80, nil},
+			Address{true, false, -1, 80, nil, nil},
 			"",
 		},
 	}
@@ -836,22 +916,22 @@ func TestAddress_RouterPath(t *testing.T) {
 	}{
 		{
 			"ShouldReturnEmptyPath",
-			Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta"}},
+			Address{true, false, -1, 80, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta"}},
 			"",
 		},
 		{
 			"ShouldReturnPath",
-			Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta", Path: "/apath"}},
+			Address{true, false, -1, 80, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta", Path: "/apath"}},
 			"/apath",
 		},
 		{
 			"ShouldNotReturnPathInvalid",
-			Address{false, false, -1, 80, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta", Path: "/apath"}},
+			Address{false, false, -1, 80, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta", Path: "/apath"}},
 			"",
 		},
 		{
 			"ShouldNotReturnPathNil",
-			Address{true, false, -1, 80, nil},
+			Address{true, false, -1, 80, nil, nil},
 			"",
 		},
 	}
@@ -872,49 +952,49 @@ func TestAddress_IsTCP_IsUDP(t *testing.T) {
 	}{
 		{
 			"ShouldReturnTrueTCP",
-			Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta"}},
+			Address{true, false, -1, 80, nil, &url.URL{Scheme: AddressSchemeTCP, Host: "tcphosta"}},
 			true,
 			false,
 		},
 		{
 			"ShouldReturnTrueTCP4",
-			Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeTCP4, Host: "tcphostb"}},
+			Address{true, false, -1, 80, nil, &url.URL{Scheme: AddressSchemeTCP4, Host: "tcphostb"}},
 			true,
 			false,
 		},
 		{
 			"ShouldReturnTrueTCP6",
-			Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeTCP6, Host: "tcphostc"}},
+			Address{true, false, -1, 80, nil, &url.URL{Scheme: AddressSchemeTCP6, Host: "tcphostc"}},
 			true,
 			false,
 		},
 		{
 			"ShouldReturnFalseUDP",
-			Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeUDP, Host: "tcphostd"}},
+			Address{true, false, -1, 80, nil, &url.URL{Scheme: AddressSchemeUDP, Host: "tcphostd"}},
 			false,
 			true,
 		},
 		{
 			"ShouldReturnFalseUDP4",
-			Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeUDP4, Host: "tcphoste"}},
+			Address{true, false, -1, 80, nil, &url.URL{Scheme: AddressSchemeUDP4, Host: "tcphoste"}},
 			false,
 			true,
 		},
 		{
 			"ShouldReturnFalseUDP6",
-			Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeUDP6, Host: "tcphostf"}},
+			Address{true, false, -1, 80, nil, &url.URL{Scheme: AddressSchemeUDP6, Host: "tcphostf"}},
 			false,
 			true,
 		},
 		{
 			"ShouldReturnFalseSMTP",
-			Address{true, false, -1, 80, &url.URL{Scheme: AddressSchemeSMTP, Host: "tcphostg"}},
+			Address{true, false, -1, 80, nil, &url.URL{Scheme: AddressSchemeSMTP, Host: "tcphostg"}},
 			false,
 			false,
 		},
 		{
 			"ShouldReturnFalseUnix",
-			Address{true, true, -1, 80, &url.URL{Scheme: AddressSchemeUnix, Host: "tcphosth"}},
+			Address{true, true, -1, 80, nil, &url.URL{Scheme: AddressSchemeUnix, Host: "tcphosth"}},
 			false,
 			false,
 		},
diff --git a/internal/configuration/validator/server_test.go b/internal/configuration/validator/server_test.go
index 13cdb0bb9..9950769fe 100644
--- a/internal/configuration/validator/server_test.go
+++ b/internal/configuration/validator/server_test.go
@@ -196,11 +196,11 @@ func TestValidateServerShouldCorrectlyIdentifyValidAddressSchemes(t *testing.T)
 		{schema.AddressSchemeTCP, ""},
 		{schema.AddressSchemeTCP4, ""},
 		{schema.AddressSchemeTCP6, ""},
-		{schema.AddressSchemeUDP, "server: option 'address' with value 'udp://:9091' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'udp'"},
-		{schema.AddressSchemeUDP4, "server: option 'address' with value 'udp4://:9091' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'udp4'"},
-		{schema.AddressSchemeUDP6, "server: option 'address' with value 'udp6://:9091' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'udp6'"},
+		{schema.AddressSchemeUDP, "server: option 'address' with value 'udp://:9091' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd' but is configured as 'udp'"},
+		{schema.AddressSchemeUDP4, "server: option 'address' with value 'udp4://:9091' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd' but is configured as 'udp4'"},
+		{schema.AddressSchemeUDP6, "server: option 'address' with value 'udp6://:9091' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd' but is configured as 'udp6'"},
 		{schema.AddressSchemeUnix, ""},
-		{"http", "server: option 'address' with value 'http://:9091' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'http'"},
+		{"http", "server: option 'address' with value 'http://:9091' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd' but is configured as 'http'"},
 	}
 
 	validator := schema.NewStructValidator()
diff --git a/internal/configuration/validator/storage_test.go b/internal/configuration/validator/storage_test.go
index 1fe977350..34613dcd1 100644
--- a/internal/configuration/validator/storage_test.go
+++ b/internal/configuration/validator/storage_test.go
@@ -131,7 +131,7 @@ func (suite *StorageSuite) TestShouldRaiseErrorOnInvalidMySQLAddressScheme() {
 	suite.Len(suite.val.Warnings(), 0)
 	suite.Require().Len(suite.val.Errors(), 1)
 
-	suite.EqualError(suite.val.Errors()[0], "storage: mysql: option 'address' with value 'udp://mysql:1234' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'udp'")
+	suite.EqualError(suite.val.Errors()[0], "storage: mysql: option 'address' with value 'udp://mysql:1234' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd' but is configured as 'udp'")
 }
 
 func (suite *StorageSuite) TestShouldRaiseErrorOnInvalidMySQLTLSVersion() {
@@ -328,7 +328,7 @@ func (suite *StorageSuite) TestShouldValidatePostgresServers() {
 	errors := suite.val.Errors()
 
 	suite.Require().Len(errors, 3)
-	suite.EqualError(errors[0], "storage: postgres: servers: #1: option 'address' with value 'udp://server1:4321' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'udp'")
+	suite.EqualError(errors[0], "storage: postgres: servers: #1: option 'address' with value 'udp://server1:4321' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd' but is configured as 'udp'")
 	suite.EqualError(errors[1], "storage: postgres: servers: #2: option 'address' is required")
 	suite.EqualError(errors[2], "storage: postgres: servers: #5: tls: option combination of 'minimum_version' and 'maximum_version' is invalid: minimum version TLS1.3 is greater than the maximum version TLS1.0")
 }
@@ -389,7 +389,7 @@ func (suite *StorageSuite) TestShouldValidatePostgresUDP() {
 	suite.Len(suite.val.Warnings(), 0)
 	suite.Require().Len(suite.val.Errors(), 1)
 
-	suite.EqualError(suite.val.Errors()[0], "storage: postgres: option 'address' with value 'udp://postgre:4321' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'udp'")
+	suite.EqualError(suite.val.Errors()[0], "storage: postgres: option 'address' with value 'udp://postgre:4321' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd' but is configured as 'udp'")
 }
 
 func (suite *StorageSuite) TestShouldValidatePostgresSetPort() {
diff --git a/internal/configuration/validator/telemetry_test.go b/internal/configuration/validator/telemetry_test.go
index c47d7070d..7a08c9381 100644
--- a/internal/configuration/validator/telemetry_test.go
+++ b/internal/configuration/validator/telemetry_test.go
@@ -72,7 +72,7 @@ func TestValidateTelemetry(t *testing.T) {
 			&schema.Configuration{Telemetry: schema.Telemetry{Metrics: schema.TelemetryMetrics{Address: mustParseAddress("udp://0.0.0.0")}}},
 			&schema.Configuration{Telemetry: schema.Telemetry{Metrics: schema.TelemetryMetrics{Address: mustParseAddress("udp://0.0.0.0:9959/metrics")}}},
 			nil,
-			[]string{"telemetry: metrics: option 'address' with value 'udp://0.0.0.0:0' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'udp'"},
+			[]string{"telemetry: metrics: option 'address' with value 'udp://0.0.0.0:0' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd' but is configured as 'udp'"},
 		},
 	}
 
@@ -122,11 +122,11 @@ func TestValidateTelemetryShouldCorrectlyIdentifyValidAddressSchemes(t *testing.
 		{schema.AddressSchemeTCP, ""},
 		{schema.AddressSchemeTCP4, ""},
 		{schema.AddressSchemeTCP6, ""},
-		{schema.AddressSchemeUDP, "telemetry: metrics: option 'address' with value 'udp://:9091' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'udp'"},
-		{schema.AddressSchemeUDP4, "telemetry: metrics: option 'address' with value 'udp4://:9091' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'udp4'"},
-		{schema.AddressSchemeUDP6, "telemetry: metrics: option 'address' with value 'udp6://:9091' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'udp6'"},
+		{schema.AddressSchemeUDP, "telemetry: metrics: option 'address' with value 'udp://:9091' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd' but is configured as 'udp'"},
+		{schema.AddressSchemeUDP4, "telemetry: metrics: option 'address' with value 'udp4://:9091' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd' but is configured as 'udp4'"},
+		{schema.AddressSchemeUDP6, "telemetry: metrics: option 'address' with value 'udp6://:9091' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd' but is configured as 'udp6'"},
 		{schema.AddressSchemeUnix, ""},
-		{"http", "telemetry: metrics: option 'address' with value 'http://:9091' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'http'"},
+		{"http", "telemetry: metrics: option 'address' with value 'http://:9091' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', 'unix', or 'fd' but is configured as 'http'"},
 	}
 
 	have := &schema.Configuration{}