Skip to content
LinkedIn GitHub X

Deploying a Simple Go API with Supervisor and Nginx

Go, Supervisor & Nginx Cover

Intro

Hi! In this post, I’ll show you how to deploy a Go API using Supervisor to manage the process and Nginx as a web server to serve it.

Before we dive into the deployment steps, let’s briefly discuss why we’re using Supervisor and Nginx.

- Supervisor is a process control system that helps manage and monitor applications running in the background. It ensures that your Go API stays up and automatically restarts it if it crashes. See the full documentation

- Nginx is a high-performance web server that can also function as a reverse proxy, making it ideal for serving our Go API to the internet. See the full documentation

🤔 Why Choose Supervisor Over Other Options?

You might wonder why we use Supervisor instead of alternatives like Systemd, PM2, or containerized solutions like Docker. Here’s a quick comparison:

ToolsProsCons
SupervisorSimple setup, great for managing multiple processes, easy log managementRequires manual config
SystemdNative to Linux, faster startupMore complex setup, harder to debug
PM2Built for Node.js, supports process monitoringNot ideal for Go applications
DockerIsolated environment, easy deployment, scalableMore setup overhead, requires container knowledge

When Should You Use Supervisor?

Use Supervisor when you want a non-containerized way to manage a Go service, with features like auto-restart and log management, without dealing with systemd’s complexity or Docker’s extra overhead.

Setup and Run a Simple Go API

Requirements

Before starting, make sure you have the following installed on your system:

- Go

Terminal window
$ go version
go version go1.24.0 linux/amd64

If not installed, download it from the official site.

- Supervisor

  • Ubuntu/Debian

    Terminal window
    $ sudo apt update
    $ sudo apt install supervisor -y
  • CentOS/RHEL

    Terminal window
    $ sudo yum install supervisor -y
  • Homebrew (macOS)

    Terminal window
    $ brew install supervisor

    After installation, check if Supervisor is running:

    Terminal window
    $ sudo systemctl status supervisor

    If it’s not running, start and enable it:

    Terminal window
    $ sudo systemctl start supervisor
    $ sudo systemctl enable supervisor

- Nginx

  • Ubuntu/Debian

    Terminal window
    $ sudo apt install nginx -y
  • CentOS/RHEL

    Terminal window
    $ sudo yum install nginx -y
  • Homebrew (macOS)

    Terminal window
    $ brew install nginx

    After installation, check if Nginx is running:

    Terminal window
    $ sudo systemctl status nginx

    If it’s not running, start and enable it:

    Terminal window
    $ sudo systemctl start nginx
    $ sudo systemctl enable nginx

Initialize a New Go Project

First, create a new directory for the project and initialize a Go module:

Terminal window
$ cd /var/www/
$ mkdir go-api && cd go-api
Terminal window
$ go mod init example.com/go-api

This command creates a Go module named example.com/go-api, which helps manage dependencies.

Create a Simple API

Now, create a new file main.go and add the following code:

Terminal window
$ vim main.go
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
fmt.Fprintln(w, "Simple Go API")
}
func main() {
http.HandleFunc("/", handler)
fmt.Println("Server started at :8080")
http.ListenAndServe(":8080", nil)
}

Compile and run the Go server:

Terminal window
$ go run main.go

If successful, you should see this message in the terminal:

Terminal window
Server started at :8080

Now test the API using curl:

Terminal window
$ curl localhost:8080
Simple Go API

Create a Simple API with ASCII Text Response (Optional)

First, install the go-figure package:

Terminal window
$ go get github.com/common-nighthawk/go-figure

Now, modify main.go to generate an ASCII text response dynamically:

package main
import (
"fmt"
"net/http"
"github.com/common-nighthawk/go-figure"
)
func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
asciiArt := figure.NewFigure("Simple Go API", "", true).String()
fmt.Fprintln(w, asciiArt)
}
func main() {
http.HandleFunc("/", handler)
fmt.Println("Server started at :8080")
http.ListenAndServe(":8080", nil)
}
Terminal window
$ curl localhost:8080
____ _ _ ____ _ ____ ___
/ ___| (_) _ __ ___ _ __ | | ___ / ___| ___ / \ | _ \ |_ _|
\___ \ | | | '_ ` _ \ | '_ \ | | / _ \ | | _ / _ \ / _ \ | |_) | | |
___) | | | | | | | | | | |_) | | | | __/ | |_| | | (_) | / ___ \ | __/ | |
|____/ |_| |_| |_| |_| | .__/ |_| \___| \____| \___/ /_/ \_\ |_| |___|
|_|

Running the API as a Background Service with Supervisor

Create a Supervisor Configuration for the Go API

Create a new Supervisor config file:

Terminal window
$ sudo vim /etc/supervisor/conf.d/go-api.conf

Add the following configuration:

Terminal window
[program:go-api]
process_name=%(program_name)s_%(process_num)02d
directory=/var/www/go-api
command=bash -c 'cd /var/www/go-api && ./main'
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stderr_logfile=/var/log/go-api.err.log
stdout_logfile=/var/log/go-api.out.log

Explanation:

directory=/var/www/go-api → The working directory of the Go API.

command=bash -c 'cd /var/www/go-api && ./main' → Runs the API.

autostart=true → Starts automatically on system boot.

autorestart=true → Restarts if the process crashes.

user=www-data → Runs as the www-data user (adjust as needed).

redirect_stderr=true → Redirects error logs to stdout.

stdout_logfile=/var/log/api/go-api.out.log → Standard output log file.

stderr_logfile=/var/log/api/go-api.err.log → Error log file.

Now, we need build the Go API:

Terminal window
$ go build -o main .

Ensure the directory and binary have the correct permissions:

Terminal window
$ sudo chown -R www-data:www-data /var/www/go-api
$ sudo chmod 775 /var/www/go-api/main

Apply the Supervisor Configuration

Reload Supervisor and start the service:

Terminal window
$ sudo supervisorctl reread
$ sudo supervisorctl update
$ sudo supervisorctl start go-api:*

Check the service status:

Terminal window
$ sudo supervisorctl avail
go-api:go-api_00 in use auto 999:999
Terminal window
$ sudo supervisorctl status go-api:*
go-api:go-api_00 RUNNING pid 198867, uptime 0:01:52

Check Logs and Debugging

If the API is not running, check the logs:

Terminal window
$ cat /var/log/go-api.out.log
$ cat /var/log/go-api.err.log

Or use Supervisor’s built-in log viewer:

Terminal window
$ sudo supervisorctl tail -f go-api:go-api_00
==> Press Ctrl-C to exit <==
Server started at :8080

Setting Up Nginx as a Reverse Proxy for the API

Create a new configuration file:

Terminal window
$ sudo vim /etc/nginx/sites-available/go-api
Terminal window
server {
server_name _;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
}
error_log /var/log/nginx/go-api_error.log;
access_log /var/log/nginx/go-api_access.log;
}

Create a symbolic link to enable the site:

Terminal window
$ sudo ln -s /etc/nginx/sites-available/go-api /etc/nginx/sites-enabled/

Test the configuration:

Terminal window
$ nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

If the test is successful, restart Nginx:

Terminal window
$ sudo systemctl restart nginx

Now, you can access your Go API using:

  • Localhost (if running locally)
Terminal window
curl http://localhost
____ _ _ ____ _ ____ ___
/ ___| (_) _ __ ___ _ __ | | ___ / ___| ___ / \ | _ \ |_ _|
\___ \ | | | '_ ` _ \ | '_ \ | | / _ \ | | _ / _ \ / _ \ | |_) | | |
___) | | | | | | | | | | |_) | | | | __/ | |_| | | (_) | / ___ \ | __/ | |
|____/ |_| |_| |_| |_| | .__/ |_| \___| \____| \___/ /_/ \_\ |_| |___|
|_|
  • Server’s Public IP (if running on a VPS or remote server)
Terminal window
curl http://YOUR_SERVER_IP

Note: If you want to access your Go API using a custom domain instead of an IP address, you need to purchase a domain, configure its DNS to point to your server’s IP, and update your Nginx configuration accordingly. For better security, it’s recommended to set up HTTPS using Let’s Encrypt.

Conclusion

In this guide, we deployed a Go API using Supervisor to manage the process ensuring automatic restarts and efficient request handling also Nginx as a reverse proxy. Thank you for reading, and good luck with your deployment! 🚀

Tags: