How to Deploy golang (rest api) to production using Supervisor

keith wachira
keith wachira
i.
Feb 20, 2021 5 min read

In one of our previous article we saw how we can deploy a golang application using systemd. While systemd is good enough, Lately I have started using Supervisord to monitor and control my apps due to some few reason:

  1. Any user can manage processes. No need to be superuser.
  2. More flexibility in managing process(groups, priority order).

Installing Supervisor

This article assumes you are hosting your application on a linux based systems specifically ubuntu. To install supervisor on ubuntu run this commands.

1
2
3
sudo apt-get update
sudo apt-get install -y supervisor 
sudo service supervisor start

Making A simple Go rest api

With Supervisor installed proceed to create the golang application that we will be deploying to production. For the sake of this article we will create a very simple hello world rest api.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package main

import (
	"fmt"
	"net/http"
)
func main() {
	handler := http.NewServeMux()
	handler.HandleFunc("/api/hello", SayHello)
	http.ListenAndServe("0.0.0.0:8080", handler)
	//we tell our api to listen to all request to port 8080.
}
func SayHello(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, `Hello world`)
}

Building and deploying our golang application using ssh

First let build a binary that we will upload. Cd to you project(where your main.go is located )and run this command to build for linux.

1
GOOS=linux GOARCH=amd64 go build

Note the binary produced will have the name of your parent folder name: e.g if your project is name myapp the binary will have the name myapp.

To change the output binary name when building add the -o flag like below Replace newname with the name you want to call you binary file.

1
GOOS=linux GOARCH=amd64 go build -o newname

After building you binary file upload it to the server. There are many ways to deploy an app to the cloud. You can use github actions ,gitlab ci/cd but ssh is the simplest way to upload an app to the server. cd to where the binary is and run the following command to upload it to the server.

1
scp binaryname  user@example.com:/home/apis/go
  1. Replace binaryname with the name of your binary file,user with your server user name and example.com with you server Ip address or domain.
  2. /var/www/go - is the path on your server you want to store the golang binary file.You can store it on any path.Change it to the path you want to use.

Writing a supervisorctl file to manage our app.

All supervisor app configuration file are stored in /etc/supervisor/conf.d/

To add a new configuration file for our app run the following command.

1
sudo nano /etc/supervisor/conf.d/hello.conf

Replace hello with whatever name you would like you configuration file to have. The file must have the extension .conf

Add the following content to the configurartion file. Change the directory and command path to where you golang binary is in my case my binary is stored in the path /home/apis/go with the name hello .

1
2
3
4
5
6
7
[program:hello]
directory=/home/apis/go
command=/home/apis/go/hello
autostart=true
autorestart=true
stderr_logfile=/home/apis/go/hello.err
stdout_logfile=/home/apis/go/hello.log

Note if you are hosting multiple apps each app should have a configuration file like above. Replace [program:hello] with whichever name you want to give your program e.g [program:myapp] .

Not this name must be unique for each application configuration file.

After the setup tell supervisor to reload the configuration files with the command below

1
sudo supervisorctl reload

You can always check the supervisor status by running:

1
sudo supervisorctl status 
You should always restart your application whenever you update it. To start,restart and stop a single supervisor process you should run:

1
2
3
4
5
6
7
/// replace  hello with the name of you program (the one defined in your config file[program:nameToUsetoStopAndStart])
///To start a  process run
sudo supervisorctl start hello
///to stop  processs run
sudo supervisorctl stop hello
///to restart a process run
sudo supervisorctl restart hello

Configuring Nginx to Proxy Requests your go rest api

When running a golang restapi like the one we made.Its good to use a proxy server behind our golang application. This makes it easier to: 1. Add ssl certificate to our application for example using Let’s Encrypt

  1. It helps with load balancing.

  2. Use a single domain to run multiple.

While we have many proxy server like apache and caddy, I use nginx since it is very easy to setup and add free ssl with Let’s Encrypt follow this article to add free ssl to nginx.

Start by installing nginx

1
2
sudo apt update
sudo apt install nginx

Nginx store configuration files in /etc/nginx/sites-available

Create a new configuration file in /etc/nginx/sites-available and copy the content below:

To create the configuration file run:

1
2
/// Replace hello with the name you want to give you configuration file.
sudo nano /etc/nginx/sites-available/hello

Copy the content below to the new configuration file

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name example.com www.example.com ;  
location / {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

Replace the port number with the portĀ  you used.As you recall, in my case that is port 8080.(http.ListenAndServe("0.0.0.0:8080", handler)) The server_name should also be replaced with you domain name.

To enable the Nginx server block configuration we have just created,we need to create a symbolic link of our conf file to theĀ sites-enabled directory :

1
sudo ln -s /etc/nginx/sites-available/hello /etc/nginx/sites-enabled

We can test for syntax errors by typing:

sudo nginx -t

If this returns without indicating any errors, we can restart the Nginx process to read our new config:

1
sudo systemctl restart nginx

With that we are done.If I now visit my domain (https://example.com/hello) and type hello,I should see my api return hello world

Conclusion

For those who would like to manage their app using systemd you can read the one of our previous tutorial In our next tutorial we will cover how we can can build and deploy a golang application using github action.

comments powered by Disqus