Deploying a Simple Go API with Supervisor and Nginx

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?
Section titled “🤔 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:
| Tools | Pros | Cons |
|---|---|---|
| Supervisor | Simple setup, great for managing multiple processes, easy log management | Requires manual config |
| Systemd | Native to Linux, faster startup | More complex setup, harder to debug |
| PM2 | Built for Node.js, supports process monitoring | Not ideal for Go applications |
| Docker | Isolated environment, easy deployment, scalable | More setup overhead, requires container knowledge |
When Should You Use Supervisor?
Section titled “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
Section titled “Setup and Run a Simple Go API”Requirements
Section titled “Requirements”Before starting, make sure you have the following installed on your system:
Go
Terminal window $ go versiongo version go1.24.0 linux/amd64If not installed, download it from the official site.
Supervisor
Ubuntu/Debian
Terminal window $ sudo apt update$ sudo apt install supervisor -yCentOS/RHEL
Terminal window $ sudo yum install supervisor -yHomebrew (macOS)
Terminal window $ brew install supervisorAfter installation, check if Supervisor is running:
Terminal window $ sudo systemctl status supervisorIf it’s not running, start and enable it:
Terminal window $ sudo systemctl start supervisor$ sudo systemctl enable supervisorNginx
Ubuntu/Debian
Terminal window $ sudo apt install nginx -yCentOS/RHEL
Terminal window $ sudo yum install nginx -yHomebrew (macOS)
Terminal window $ brew install nginxAfter installation, check if Nginx is running:
Terminal window $ sudo systemctl status nginxIf it’s not running, start and enable it:
Terminal window $ sudo systemctl start nginx$ sudo systemctl enable nginx
Initialize a New Go Project
Section titled “Initialize a New Go Project”First, create a new directory for the project and initialize a Go module:
$ cd /var/www/$ mkdir go-api && cd go-api$ go mod init example.com/go-apiThis command creates a Go module named example.com/go-api, which helps manage dependencies.
Create a Simple API
Section titled “Create a Simple API”Now, create a new file main.go and add the following code:
$ vim main.gopackage 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:
$ go run main.goIf successful, you should see this message in the terminal:
Server started at :8080Now test the API using curl:
$ curl localhost:8080
Simple Go APICreate a Simple API with ASCII Text Response (Optional)
Section titled “Create a Simple API with ASCII Text Response (Optional)”First, install the go-figure package:
$ go get github.com/common-nighthawk/go-figureNow, 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)}$ curl localhost:8080
____ _ _ ____ _ ____ ___ / ___| (_) _ __ ___ _ __ | | ___ / ___| ___ / \ | _ \ |_ _| \___ \ | | | '_ ` _ \ | '_ \ | | / _ \ | | _ / _ \ / _ \ | |_) | | | ___) | | | | | | | | | | |_) | | | | __/ | |_| | | (_) | / ___ \ | __/ | | |____/ |_| |_| |_| |_| | .__/ |_| \___| \____| \___/ /_/ \_\ |_| |___| |_|Running the API as a Background Service with Supervisor
Section titled “Running the API as a Background Service with Supervisor”Create a Supervisor Configuration for the Go API
Section titled “Create a Supervisor Configuration for the Go API”Create a new Supervisor config file:
$ sudo vim /etc/supervisor/conf.d/go-api.confAdd the following configuration:
[program:go-api]process_name=%(program_name)s_%(process_num)02ddirectory=/var/www/go-apicommand=bash -c 'cd /var/www/go-api && ./main'autostart=trueautorestart=trueuser=www-dataredirect_stderr=truestderr_logfile=/var/log/go-api.err.logstdout_logfile=/var/log/go-api.out.logExplanation:
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:
$ go build -o main .Ensure the directory and binary have the correct permissions:
$ sudo chown -R www-data:www-data /var/www/go-api$ sudo chmod 775 /var/www/go-api/mainApply the Supervisor Configuration
Section titled “Apply the Supervisor Configuration”Reload Supervisor and start the service:
$ sudo supervisorctl reread$ sudo supervisorctl update$ sudo supervisorctl start go-api:*Check the service status:
$ sudo supervisorctl availgo-api:go-api_00 in use auto 999:999$ sudo supervisorctl status go-api:*
go-api:go-api_00 RUNNING pid 198867, uptime 0:01:52Check Logs and Debugging
Section titled “Check Logs and Debugging”If the API is not running, check the logs:
$ cat /var/log/go-api.out.log$ cat /var/log/go-api.err.logOr use Supervisor’s built-in log viewer:
$ sudo supervisorctl tail -f go-api:go-api_00
==> Press Ctrl-C to exit <==Server started at :8080Setting Up Nginx as a Reverse Proxy for the API
Section titled “Setting Up Nginx as a Reverse Proxy for the API”Create a new configuration file:
Section titled “Create a new configuration file:”$ sudo vim /etc/nginx/sites-available/go-apiserver { 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:
$ sudo ln -s /etc/nginx/sites-available/go-api /etc/nginx/sites-enabled/Test the configuration:
$ nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successfulIf the test is successful, restart Nginx:
$ sudo systemctl restart nginxNow, you can access your Go API using:
- Localhost (if running locally)
curl http://localhost
____ _ _ ____ _ ____ ___ / ___| (_) _ __ ___ _ __ | | ___ / ___| ___ / \ | _ \ |_ _| \___ \ | | | '_ ` _ \ | '_ \ | | / _ \ | | _ / _ \ / _ \ | |_) | | | ___) | | | | | | | | | | |_) | | | | __/ | |_| | | (_) | / ___ \ | __/ | | |____/ |_| |_| |_| |_| | .__/ |_| \___| \____| \___/ /_/ \_\ |_| |___| |_|- Server’s Public IP (if running on a VPS or remote server)
curl http://YOUR_SERVER_IPNote: 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
Section titled “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! 🚀