From 462aa5f8009c9ea0964b0cab2e2bcaf2704ad516 Mon Sep 17 00:00:00 2001 From: Nicholas Schwab Date: Mon, 5 Aug 2024 19:50:42 +0200 Subject: [PATCH 1/2] Enable server to be activated via systemd sockets. Systemd sockets start the corresponding service when there is a request on the specified port. Systemd will then forward the port to the service by passing a file descriptor. The service must be prepared to accept this, since it cannot just bind to the same port the socket is already bound to. This change enables this. That this works can be tested via ``` systemd-socket-activation -l 11434 ./ollama server ``` This will bind to port 11434 but not start ollama. When trying to connect to this port, the server will actually start. --- cmd/cmd.go | 18 +++++++++++++++++- go.mod | 1 + go.sum | 3 +++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index d47db65b..5818f2ab 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -26,6 +26,7 @@ import ( "time" "github.com/containerd/console" + "github.com/coreos/go-systemd/v22/activation" "github.com/mattn/go-runewidth" "github.com/olekukonko/tablewriter" "github.com/spf13/cobra" @@ -1091,7 +1092,8 @@ func RunServer(cmd *cobra.Command, _ []string) error { return err } - ln, err := net.Listen("tcp", envconfig.Host().Host) + ln, err := obtainListener() + if err != nil { return err } @@ -1150,6 +1152,20 @@ func initializeKeypair() error { return nil } +func obtainListener() (net.Listener, error) { + listeners, err := activation.Listeners() + + if err == nil && len(listeners) == 1 { + return listeners[0], nil + } + + if err == nil && len(listeners) > 1 { + fmt.Printf("Activation via systemd sockets returned %d listeners. Cannot handle more than one listener and fall back to standard behavior of binding to the port myself.", len(listeners)) + } + + return net.Listen("tcp", envconfig.Host().Host) +} + func checkServerHeartbeat(cmd *cobra.Command, _ []string) error { client, err := api.ClientFromEnvironment() if err != nil { diff --git a/go.mod b/go.mod index 2e0c6614..3def935e 100644 --- a/go.mod +++ b/go.mod @@ -70,6 +70,7 @@ require ( golang.org/x/crypto v0.23.0 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa golang.org/x/net v0.25.0 // indirect + github.com/coreos/go-systemd/v22 v22.5.0 golang.org/x/sys v0.20.0 golang.org/x/term v0.20.0 golang.org/x/text v0.15.0 diff --git a/go.sum b/go.sum index 926ed26d..40efdc9d 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,8 @@ github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnht github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/d4l3k/go-bfloat16 v0.0.0-20211005043715-690c3bdd05f1 h1:cBzrdJPAFBsgCrDPnZxlp1dF2+k4r1kVpD7+1S1PVjY= @@ -78,6 +80,7 @@ github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBEx github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= From ba9a6fe80e094cd4350ea096c74cf4e61fa2da70 Mon Sep 17 00:00:00 2001 From: Nicholas Schwab Date: Mon, 5 Aug 2024 20:03:39 +0200 Subject: [PATCH 2/2] Create systemd socket file in install script. --- scripts/install.sh | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/scripts/install.sh b/scripts/install.sh index aa8b3e5e..d5ebeeba 100644 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -116,6 +116,16 @@ Environment="PATH=$PATH" [Install] WantedBy=default.target EOF + + status "Creating ollama systemd socket..." + cat </dev/null +[Unit] +Description=Ollama Socket + +[Socket] +ListenStream=11434 +EOF + SYSTEMCTL_RUNNING="$(systemctl is-system-running || true)" case $SYSTEMCTL_RUNNING in running|degraded) @@ -205,7 +215,7 @@ CUDA_REPO_ERR_MSG="NVIDIA GPU detected, but your OS and Architecture are not sup # ref: https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#fedora install_cuda_driver_yum() { status 'Installing NVIDIA repository...' - + case $PACKAGE_MANAGER in yum) $SUDO $PACKAGE_MANAGER -y install yum-utils