Client Area

Running Go Applications on DomainIndia VPS (systemd, nginx Reverse Proxy, SSL)

ByDomain India Team·DomainIndia Engineering
5 min readPublished 23 Apr 2026Updated 23 Jun 2026173 views

In this article

  • 1Why Go on a VPS (and not shared)
  • 2Step 1 — Prepare the VPS
  • 3Step 2 — Build your binary
  • 4Step 3 — Run under systemd
  • 5Step 4 — nginx reverse proxy

Running Go Applications on DomainIndia VPS (systemd, nginx Reverse Proxy, SSL)

TL;DR
Go (Golang) produces a single compiled binary — ideal for lean production deployments on a DomainIndia VPS. This guide covers the full stack: building your binary, running it under systemd, fronting it with nginx or Caddy, and adding Let's Encrypt SSL.

Why Go on a VPS (and not shared)

Go apps are long-running compiled processes listening on a port. Shared hosting (cPanel, DirectAdmin) runs PHP per-request via FastCGI — there's no equivalent for Go. A VPS gives you the systemd services, port control, and iptables needed.

Any Go app — REST API, WebSocket server, gRPC service, static-site generator on a schedule — runs the same way on our VPS:

  1. Compile to a binary on your laptop (or on the VPS)
  2. Upload the binary
  3. Run it as a systemd service
  4. Proxy HTTP via nginx/Caddy
  5. Get SSL via Let's Encrypt

Step 1 — Prepare the VPS

Order a DomainIndia VPS (AlmaLinux 9 or Ubuntu 22.04 recommended). SSH in as root:

  1. Create a non-root user for the app:

```bash

useradd -m -s /bin/bash goapp

mkdir -p /home/goapp/app

chown goapp:goapp /home/goapp/app

```

  1. Install essentials:

```bash

# AlmaLinux

sudo dnf install -y nginx firewalld certbot python3-certbot-nginx

# Ubuntu

sudo apt install -y nginx ufw certbot python3-certbot-nginx

```

  1. Install Go (optional — only if you'll compile on the server):

```bash

wget https://go.dev/dl/go1.22.0.linux-amd64.tar.gz

sudo tar -C /usr/local -xzf go1.22.0.linux-amd64.tar.gz

echo 'export PATH=$PATH:/usr/local/go/bin' | sudo tee /etc/profile.d/go.sh

source /etc/profile.d/go.sh

go version

```

Step 2 — Build your binary

On your laptop (recommended) — cross-compile for Linux:

bash
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o myapp ./cmd/server

Upload:

bash
scp myapp goapp@your-vps-ip:/home/goapp/app/

Or build on the VPS:

bash
cd /home/goapp/app
git clone https://github.com/yourcompany/myapp .
go build -o myapp ./cmd/server
Insight

Keep the binary tiny. CGO_ENABLED=0 go build -ldflags="-s -w" strips debug symbols and cuts binary size 30%. Paired with -trimpath, your binary is reproducible and lean.

Step 3 — Run under systemd

Create /etc/systemd/system/myapp.service:

ini
[Unit]
Description=My Go Application
After=network.target

[Service]
Type=simple
User=goapp
Group=goapp
WorkingDirectory=/home/goapp/app
ExecStart=/home/goapp/app/myapp
Restart=on-failure
RestartSec=5

# Environment
Environment="PORT=8080"
Environment="DATABASE_URL=postgres://user:pass@localhost/dbname?sslmode=disable"
EnvironmentFile=-/home/goapp/app/.env

# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/home/goapp/app/data

# Logging
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Start and enable:

bash
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
sudo systemctl status myapp

Check logs:

bash
sudo journalctl -u myapp -f

Step 4 — nginx reverse proxy

Go listens on port 8080 (internal). nginx takes port 80/443 public traffic and forwards it.

/etc/nginx/conf.d/myapp.conf:

nginx
upstream myapp_backend {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name api.yourcompany.com;

    # Redirect to HTTPS after SSL setup
    # return 301 https://$host$request_uri;

    location / {
        proxy_pass http://myapp_backend;
        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;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 300s;
    }
}

Test and reload:

bash
sudo nginx -t && sudo systemctl reload nginx

Step 5 — Let's Encrypt SSL

bash
sudo certbot --nginx -d api.yourcompany.com

Certbot modifies your nginx config to add:

  • SSL certificate paths
  • HTTP → HTTPS redirect
  • Auto-renewal cron

Verify renewal:

bash
sudo certbot renew --dry-run

Alternative: Caddy (much simpler)

Caddy auto-obtains Let's Encrypt SSL and auto-renews. /etc/caddy/Caddyfile:

api.yourcompany.com {
    reverse_proxy 127.0.0.1:8080
}

That's it. Run sudo systemctl reload caddy — SSL appears within 60 seconds.

See our Nginx vs Caddy comparison article for the trade-offs.

Zero-downtime deployments

For a production API, deploying via "stop → replace binary → start" causes a few seconds of downtime. Two better approaches:

Approach 1 — Graceful restart with `SIGHUP`:

Use a package like github.com/cloudflare/tableflip or github.com/facebookgo/grace — the old process keeps serving existing requests while the new one picks up new connections.

Approach 2 — Blue-green with systemd:

Run two services (myapp-blue.service + myapp-green.service) on different ports. nginx upstream points to the active one. To deploy:

bash
# Stop green, deploy new binary, start green
sudo systemctl stop myapp-green
cp new-binary /home/goapp/app/myapp-green
sudo systemctl start myapp-green

# Wait for green to become healthy
curl -f http://127.0.0.1:8081/health

# Switch nginx to green, reload
sudo sed -i 's/server 127.0.0.1:8080/server 127.0.0.1:8081/' /etc/nginx/conf.d/myapp.conf
sudo nginx -s reload

Database access

PostgreSQL (recommended for Go):

bash
sudo dnf install -y postgresql-server postgresql-contrib
sudo postgresql-setup --initdb
sudo systemctl enable --now postgresql
sudo -u postgres createdb myapp
sudo -u postgres createuser goapp --pwprompt

Connection string in .env:

DATABASE_URL=postgres://goapp:password@localhost/myapp?sslmode=disable

MySQL: install mysql-server, use github.com/go-sql-driver/mysql.

SQLite: fine for small apps, zero setup. Use github.com/mattn/go-sqlite3.

Monitoring

Expose a Prometheus /metrics endpoint in your Go app:

go
import "github.com/prometheus/client_golang/prometheus/promhttp"
http.Handle("/metrics", promhttp.Handler())

On the server, install Prometheus + Grafana (or use Grafana Cloud's free tier — 10k metrics, 50 GB logs free).

Common pitfalls

FAQ

Q Can I run Go on shared hosting?

No. Shared hosting doesn't allow long-running daemons or custom port binding. You need VPS (or our App Platform for simpler deploys).

Q How much RAM do I need?

Lightweight Go APIs run fine on 1 GB VPS. For ~1000 concurrent requests with DB, 2 GB is safer. Go is memory-efficient by default.

Q Should I use gin, echo, fiber, or chi?

For REST APIs, chi (standard-library-friendly) and echo (full-featured) are popular. fiber (fasthttp-based) is fastest but deviates from net/http. For serious production, stick with net/http or chi.

Q How do I update Go without breaking my running app?

Compile the binary with the new Go version, drop it in, systemctl restart myapp. The Go runtime is statically linked — the Go version on disk doesn't matter to an already-compiled binary.

Q What's the cheapest DomainIndia VPS for Go?

Start with VPS Starter — 1 vCPU, 2 GB RAM, 40 GB SSD. Enough for most API workloads up to 200 req/sec.

Ready to deploy Go? Order a VPS and get root access today. View VPS plans

Was this article helpful?

Your feedback helps us improve our documentation

Still need help? Submit a support ticket

Run Go (Golang) Apps on DomainIndia VPS — Complete Deployment Guide