Deploying Go Apps with Systemd in 10 Minutes (without Docker)

When you want to deploy a dead-simple Go API and you don't really have the urge to learn Docker and large scale deployment (although certainly a useful skill), you have come to the right tutorial.

We're going to have a quick look at setting up running a golang web app on a Linux VPS without spending more than 10 minutes on it.

Creating a Service for Systemd

On my Ubuntu VPS the following was sufficient to create a service after the go app was placed in my home folder: /home/jonathan/wombatapp.

touch /lib/systemd/system/wombatapp.service

Next, I inserted the following into the file through vim

[Unit]
Description=wombatapp

[Service]
Type=simple
Restart=always
RestartSec=5s
ExecStart=/home/jonathan/wombatapp

[Install]
WantedBy=multi-user.target

This allows you to start your binary/service/webapp with:

service wombatapp start

To enable it on boot, type:

service wombatapp enable

Don't forget to check if everything's cool through:

service wombatapp status

Example output:

● wombatapp.service - wombatapp
   Loaded: loaded (/lib/systemd/system/wombatapp.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2017-12-06 21:00:01 UTC; 12min ago
 Main PID: 24735 (acj)
    Tasks: 3 (limit: 4915)
   Memory: 1.8M
      CPU: 20ms
   CGroup: /system.slice/wombatapp.service
           └─24735 /home/jonathan/wombatapp

Dec 06 21:00:01 serenity systemd[1]: Started wombatapp.

Adding Environment Variables for Systemd

To add environment variables, for example a database password or the port your web app is going to run on, you can just add as many Environment lines to your system file as you wish.

Full example below:

[Unit]
Description=wombatapp

[Service]
Type=simple
Restart=always
RestartSec=5s
Environment=PORT=80
Environment=GIN_MODE=release
ExecStart=/home/jonathan/wombatapp

[Install]
WantedBy=multi-user.target

In my case, I needed gin to receive the correct port it's supposed to run on and the GIN_MODE=release to make sure gin runs in production and not development mode.

Since I also used these flags when developing, in development the app was behaving differently and was easier to test and work with, in production it was more restricted based on the environment.

Short snippet from my app:

if os.Getenv("GIN_MODE") != "release" {
  return true
}

After updating your systemd entry, restart your service with:

service wombatapp restart
Tagged with: #go #golang #systemd

Thank you for reading! If you have any comments, additions or questions, please tweet or toot them at me!