service file for golang app

Solution 1:

This worked.

[Unit]
Description=golang wiki initialization

[Service]
PIDFile=/tmp/gowiki.pid-4040
User=root
Group=root
WorkingDirectory=/var/www
ExecStart=/bin/bash -c '/var/www/wiki'

[Install]
WantedBy=multi-user.target

Because the Type=forking services expect the parent service to exit before the service has actually started. If the parent never exits, then systemctl start will not give you back a prompt because it doesn't think that it's done executing.

Solution 2:

If you don't mind adjusting your code a little for systemd the cleanest solution I've found thus far is using the SDNotify-signal.

import "github.com/coreos/go-systemd/daemon"

func main() {
    // Important init stuff here
    ....

    // Notify systemd that we're ready
    sent, e := daemon.SdNotify(false, "READY=1")
    if e != nil {
        log.Fatal(e)
    }
    if !sent {
        log.Printf("SystemD notify NOT sent\n")
    }

    // And do something blocking like listening for HTTP(s)
  • It has no CGO-deps
  • The code also works on non-systemd systems (in this case it emits a warning notify not sent)
  • If you want a working example: https://github.com/mpdroog/dnsleak

Your corresponding systemd unit-file:

[Unit]
Description=golang wiki initialization
After=network.target
Requires=network.target

[Service]
Type=notify

Restart=always
RestartSec=30
TimeoutStartSec=0

WorkingDirectory=/var/www
ExecStart=/var/www/wiki
User=www-data
Group=www-data
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target