Deploy a Go Web Server with systemd on Linux
When developing a small Go web server, it is common to run it manually with go run main.go. The problem is that the process stops when the terminal closes, and it will not automatically return after a server reboot.
A better production setup is to run the application as a systemd service. That gives you automatic startup, monitoring, service management, and optional restart behavior after failures.
1. Create a Simple Go Web Server
Start with a minimal HTTP server:
package main
import (
"encoding/json"
"log"
"net/http"
)
type Response struct {
Message string `json:"message"`
}
func handleRequest(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(Response{Message: "Success"}); err != nil {
log.Printf("encode response: %v", err)
}
}
func main() {
http.HandleFunc("/", handleRequest)
log.Fatal(http.ListenAndServe(":8080", nil))
}The server listens on port 8080 and returns:
{"message":"Success"}2. Build the Binary
Compile the application:
go build -o myapp main.goThis creates an executable named myapp.
3. Install the Binary
Move it to a standard location:
sudo mv myapp /usr/local/bin/myappFor real deployments, you may prefer a dedicated application directory such as /opt/myapp if the service needs configuration files or other assets.
4. Create a systemd Unit
Create a service file:
sudo nano /etc/systemd/system/myapp.serviceAdd:
[Unit]
Description=My Go App
After=network-online.target
Wants=network-online.target
[Service]
ExecStart=/usr/local/bin/myapp
Restart=on-failure
RestartSec=5
User=nobody
Group=nogroup
[Install]
WantedBy=multi-user.targetImportant settings:
ExecStartpoints to the compiled Go binary.Restart=on-failurerestarts the process after unexpected failures.UserandGrouprun the service without root privileges.
On some Linux distributions, nogroup may not exist. Use an appropriate dedicated service account for your system when deploying a real application.
5. Reload, Start, and Enable the Service
Reload systemd after creating or editing the unit:
sudo systemctl daemon-reloadStart the application:
sudo systemctl start myappEnable it at boot:
sudo systemctl enable myappYou can combine the last two operations with:
sudo systemctl enable --now myapp6. Check Service Status and Logs
Check whether the service is running:
sudo systemctl status myappView logs with journalctl:
sudo journalctl -u myapp -f7. Test the Server
Run:
curl http://localhost:8080Expected output:
{"message":"Success"}Conclusion
Running a Go server under systemd gives you a reliable baseline deployment: the application can start automatically after boot, restart after failures, and be managed consistently through systemctl and journalctl.
For an internet-facing deployment, place a reverse proxy such as Nginx or Caddy in front of the Go service and keep the application itself bound to a private interface whenever appropriate.