-
-
Notifications
You must be signed in to change notification settings - Fork 832
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for systemd socket activation #704
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# Using systemd socket activation | ||
|
||
_New in v2.9.0_ | ||
|
||
On platforms that use [systemd](https://systemd.io), [webhook][w] | ||
supports the _socket activation_ mechanism. In this mode, systemd itself is responsible for managing the listening socket, and it launches [webhook][w] the first time it receives a request on the socket. This has a number of advantages over the standard mode: | ||
|
||
- [webhook][w] can run as a normal user while still being able to use a port number like 80 or 443 that would normally require root privilege | ||
- if the [webhook][w] process dies and is restarted, pending connections are not dropped - they just keep waiting until the restarted [webhook][w] is ready | ||
|
||
No special configuration is necessary to tell [webhook][w] that socket activation is being used - socket activation sets specific environment variables when launching the activated service, if [webhook][w] detects these variables it will ignore the `-port` and `-socket` options and simply use the systemd-provided socket instead of opening its own. | ||
|
||
## Configuration | ||
To run [webhook][w] with socket activation you need to create _two_ separate unit files in your systemd configuration directory (typically `/etc/systemd/system`), one for the socket and one for the service. They must have matching names; in this example we use `webhook.socket` and `webhook.service`. At their simplest, these files should look like: | ||
|
||
**webhook.socket** | ||
``` | ||
[Unit] | ||
Description=Webhook server socket | ||
|
||
[Socket] | ||
# Listen on all network interfaces, port 9000 | ||
ListenStream=9000 | ||
|
||
# Alternatives: | ||
|
||
## Listen on one specific interface only | ||
# ListenStream=10.0.0.1:9000 | ||
# FreeBind=true | ||
|
||
## Listen on a Unix domain socket | ||
# ListenStream=/tmp/webhook.sock | ||
|
||
[Install] | ||
WantedBy=multi-user.target | ||
``` | ||
|
||
**webhook.service** | ||
``` | ||
[Unit] | ||
Description=Webhook server | ||
|
||
[Service] | ||
Type=exec | ||
ExecStart=webhook -nopanic -hooks /etc/webhook/hooks.yml | ||
|
||
# Which user should the webhooks run as? | ||
User=nobody | ||
Group=nogroup | ||
``` | ||
|
||
You should enable and start the _socket_, but it is not necessary to enable the _service_ - this will be started automatically when the socket receives its first request. | ||
|
||
```sh | ||
sudo systemctl enable webhook.socket | ||
sudo systemctl start webhook.socket | ||
``` | ||
|
||
Systemd unit files support many other options, see the [systemd.socket](https://www.freedesktop.org/software/systemd/man/latest/systemd.socket.html) and [systemd.service](https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html) manual pages for full details. | ||
|
||
[w]: https://github.com/adnanh/webhook |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,15 +6,40 @@ package main | |
import ( | ||
"flag" | ||
"fmt" | ||
"github.com/coreos/go-systemd/v22/activation" | ||
"net" | ||
) | ||
|
||
func platformFlags() { | ||
flag.StringVar(&socket, "socket", "", "path to a Unix socket (e.g. /tmp/webhook.sock) to use instead of listening on an ip and port; if specified, the ip and port options are ignored") | ||
flag.IntVar(&setGID, "setgid", 0, "set group ID after opening listening port; must be used with setuid, not permitted with -socket") | ||
flag.IntVar(&setUID, "setuid", 0, "set user ID after opening listening port; must be used with setgid, not permitted with -socket") | ||
Comment on lines
+15
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since setuid and setgid don't work on Windows anyway, I've moved then in here so that they are only available as flags for non-Windows builds. |
||
} | ||
|
||
func trySocketListener() (net.Listener, error) { | ||
// first check whether we have any sockets from systemd | ||
listeners, err := activation.Listeners() | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to retrieve sockets from systemd: %w", err) | ||
} | ||
numListeners := len(listeners) | ||
if numListeners > 1 { | ||
return nil, fmt.Errorf("received %d sockets from systemd, but only 1 is supported", numListeners) | ||
} | ||
if numListeners == 1 { | ||
sockAddr := listeners[0].Addr() | ||
if sockAddr.Network() == "tcp" { | ||
addr = sockAddr.String() | ||
} else { | ||
addr = fmt.Sprintf("{%s:%s}", sockAddr.Network(), sockAddr.String()) | ||
} | ||
return listeners[0], nil | ||
} | ||
// if we get to here, we got no sockets from systemd, so check -socket flag | ||
if socket != "" { | ||
if setGID != 0 || setUID != 0 { | ||
return nil, fmt.Errorf("-setuid and -setgid options are not compatible with -socket. If you need to bind a socket as root but run webhook as a different user, consider using systemd activation") | ||
} | ||
addr = fmt.Sprintf("{unix:%s}", socket) | ||
return net.Listen("unix", socket) | ||
} | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change this to whatever the next release version number will be...