Create a systemd entry for your Golang application

You build your first Golang web application and running in a remote server via SSH. The problem with that is once the SSH session is terminated it also kill any running programs associated with that SSH session. Using nohup solves this problem but I think this is okay during development and testing phase. A better way to deploy your Golang application into a Linux production environment is create a systemd entry making it a daemon program. I used an awesome daemon library from github.com/takama/daemon.

Below is the code snippet of my simple Golang application using takama’s daemon library.

// Service ...
type Service struct {
        daemon.Daemon
}

// Manage ...
func (service *Service) Manage() (string, error) {
	usage := "Usage: cf-client install | remove | start | stop | status"

	if len(os.Args) > 1 {
		command := os.Args[1]
		switch command {
		case "install":
			return service.Install()
		case "remove":
			return service.Remove()
		case "start":
			return service.Start()
		case "stop":
			return service.Stop()
		case "status":
			return service.Status()
		default:
			return usage, nil
		}
	}

	interrupt := make(chan os.Signal, 1)
	signal.Notify(interrupt, os.Interrupt, os.Kill, syscall.SIGTERM)

	c := cron.New()
	c.AddFunc("*/5 * * * *", updateIP)
	c.Start()

	killSignal := <-interrupt
	log.Println(killSignal, " Signal")
	return "Service exited", nil
}

func main() {
	loadConfiguration("config.yml", &configuration)
	srv, err := daemon.New(name, description)
	if err != nil {
		log.Println("Error: ", err)
		os.Exit(1)
	}

	service := &Service{srv}
	status, err := service.Manage()
	if err != nil {
		log.Println(status, "\nError: ", err)
		os.Exit(1)
	}
	log.Println(status)
}

Filename: /etc/systemd/system/cf-client.service

[Unit]
Description=A Dynamic IP changer
Requires=multi-user.target
After=multi-user.target

[Service]
WorkingDirectory=/opt/go-app
PIDFile=/var/run/cf-client.pid
ExecStartPre=/bin/rm -f /var/run/cf-client.pid
ExecStart=/opt/go-app/cf-client 
Restart=on-failure

[Install]
WantedBy=multi-user.target