Developer Stacks

How to Deploy Go (Golang) Gin and Fiber Microservices on Linux VPS with Systemd

How to Deploy Go (Golang) Gin and Fiber Microservices on Linux VPS with Systemd - CpanelFree Guide
Written by Blog

Why Go (Golang) Excels at Cloud Microservices & APIs

Created by Google engineers, Go (Golang) was designed from first principles for cloud networking, multi-threaded concurrency, and server-side infrastructure. Unlike interpreted languages requiring complex runtime installations or heavyweight virtual machines, Go compiles directly into a **single, self-contained, statically linked binary** that contains all dependencies and runtime schedulers.

High-speed Go web frameworks like Fiber (built on FastHTTP) and Gin leverage Go’s lightweight **Goroutines** (which consume only 2KB of initial stack memory compared to 1MB+ for OS threads), allowing a single modest VPS to effortlessly manage tens of thousands of concurrent WebSocket and REST API connections.

In this technical tutorial, we will configure the latest Go compiler on Ubuntu 24.04/22.04 LTS, build a production Fiber API microservice, supervise the binary with systemd, and configure an Nginx reverse proxy with SSL encryption.

Step 1: Installing the Official Go Compiler on Ubuntu VPS

Install the latest official Go release tarball directly from Google’s distribution server:

# Remove old versions and download latest Go 1.22
sudo rm -rf /usr/local/go
cd /tmp
curl -LO https://go.dev/dl/go1.22.6.linux-amd64.tar.gz

# Extract binary to /usr/local
sudo tar -C /usr/local -xzf go1.22.6.linux-amd64.tar.gz

# Configure system-wide environment PATH
echo 'export PATH=$PATH:/usr/local/go/bin' | sudo tee -a /etc/profile
source /etc/profile

# Confirm Go compiler version
go version

Step 2: Initializing the Go Microservice Project

Create a dedicated workspace directory and initialize a Go module:

# Create project directory
sudo mkdir -p /var/www/go-microservice
sudo chown -R $USER:$USER /var/www/go-microservice
cd /var/www/go-microservice

# Initialize Go module
go mod init go-microservice

# Install Fiber v2 web framework
go get github.com/gofiber/fiber/v2

Create the production API entrypoint at /var/www/go-microservice/main.go:

package main

import (
    "log"
    "time"
    "github.com/gofiber/fiber/v2"
    "github.com/gofiber/fiber/v2/middleware/compress"
    "github.com/gofiber/fiber/v2/middleware/cors"
    "github.com/gofiber/fiber/v2/middleware/logger"
    "github.com/gofiber/fiber/v2/middleware/recover"
)

type ApiResponse struct {
    Status    string `json:"status"`
    Message   string `json:"message"`
    Timestamp int64  `json:"timestamp"`
}

func main() {
    app := fiber.New(fiber.Config{
        Prefork:       false,
        ServerHeader:  "CpanelFree-Go-Engine",
        StrictRouting: true,
        CaseSensitive: true,
    })

    // Production Middlewares
    app.Use(recover.New())
    app.Use(logger.New())
    app.Use(compress.New(compress.Config{Level: compress.LevelBestSpeed}))
    app.Use(cors.New())

    // Health Check Endpoint
    app.Get("/health", func(c *fiber.Ctx) error {
        return c.Status(fiber.StatusOK).JSON(ApiResponse{
            Status:    "healthy",
            Message:   "Go microservice executing with sub-millisecond response time",
            Timestamp: time.Now().Unix(),
        })
    })

    log.Println("Go Fiber Microservice listening on 127.0.0.1:8080...")
    log.Fatal(app.Listen("127.0.0.1:8080"))
}

Step 3: Compiling Statically Linked Production Binary

Compile a stripped, standalone production binary with debug symbols removed:

# Compile production binary with optimizations (-s -w strips debug symbols)
CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /usr/local/bin/go-api main.go

# Verify file size and executable permissions
ls -lh /usr/local/bin/go-api
sudo chmod +x /usr/local/bin/go-api

Step 4: Supervising the Binary with Systemd Daemon

Create /etc/systemd/system/go-api.service:

[Unit]
Description=Go Fiber Production Microservice
After=network.target

[Service]
User=www-data
Group=www-data
Type=simple
ExecStart=/usr/local/bin/go-api
Restart=always
RestartSec=3
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target

Start and enable the systemd daemon:

sudo systemctl daemon-reload
sudo systemctl enable --now go-api
sudo systemctl status go-api --no-pager

Step 5: Nginx Reverse Proxy with SSL

Configure Nginx at /etc/nginx/sites-available/go-api.example.com:

server {
    listen 80;
    server_name go-api.example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Enable the site and issue an SSL certificate:

sudo ln -s /etc/nginx/sites-available/go-api.example.com /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d go-api.example.com

Building Asynchronous Database Connection Pools with pgx

For maximum SQL performance and low-overhead binary protocol communication, connect Go microservices to PostgreSQL using the official pgx driver pool:

package main

import (
    "context"
    "log"
    "github.com/jackc/pgx/v5/pgxpool"
)

var dbPool *pgxpool.Pool

func initDB() {
    config, err := pgxpool.ParseConfig("postgres://app_user:[email protected]:5432/app_prod?sslmode=disable")
    if err != nil {
        log.Fatalf("Unable to parse database config: %v", err)
    }
    config.MaxConns = 25
    config.MinConns = 5

    dbPool, err = pgxpool.NewWithConfig(context.Background(), config)
    if err != nil {
        log.Fatalf("Unable to connect to database: %v", err)
    }
}

Go Production Tuning & Garbage Collection Optimizations

Fine-tune Go’s memory ballasts and garbage collector target percentages using environment variables:

# Set GOGC to 100 or 200 in systemd service to balance memory vs CPU cycles
Environment="GOGC=150"
Environment="GOMAXPROCS=4"

Go Microservice Operational Checklist

  • Compile with CGO_ENABLED=0: Guarantees a 100% portable static binary with no external C library dependencies.
  • Enforce Timeout Contexts: Always pass context.WithTimeout to database and external HTTP requests.
  • Implement Graceful Shutdowns: Intercept os.Interrupt signals and execute app.Shutdown() before exiting.

Benchmarking Go Microservices with wrk & Systemd Hardening

Measure raw throughput on your Linux VPS by executing high-concurrency benchmarks using wrk:

# Benchmark 4 threads with 200 concurrent connections for 30 seconds
wrk -t4 -c200 -d30s http://127.0.0.1:8080/health

# Typical Output:
# Running 30s test @ http://127.0.0.1:8080/health
#   4 threads and 200 connections
#   Requests/sec: 142,520.12
#   Latency: 1.22ms

Go Microservice Production Security Directives

Add security isolation in your systemd service configuration file:

ProtectSystem=strict
ProtectHome=true
NoNewPrivileges=true
PrivateTmp=true

Deploy High-Speed Go Microservices on CpanelFree

Scale your asynchronous APIs and Golang workloads with dedicated enterprise virtual CPU cores, ultra-low latency NVMe storage, and 100% free hosting options.

Get Free Cloud Hosting Today →

Deploy Fast, Reliable Web Hosting on CpanelFree

Get genuine cPanel control, unmetered NVMe SSD storage, and free AutoSSL at $0 cost forever.

Claim Free Hosting Account

About the author

Blog

DevOps architect and Linux sysadmin specializing in server hardening, OpenLiteSpeed performance optimization, and free cloud hosting infrastructure.

Leave a Comment