Files
docs/content/vps/go-systemd.md
2026-07-28 07:20:32 -05:00

216 lines
4.1 KiB
Markdown

---
title: "Deploy a Go Binary as a Systemd Service"
description: "Run a Go application as a background service on your Arcline VPS with systemd."
section: vps
order: 5
---
# Deploy a Go Binary as a Systemd Service
Go compiles to a single static binary — no runtime, no dependencies, no package manager. This makes it ideal for running as a systemd service on your Arcline VPS.
---
## Prerequisites
- A VPS with SSH access
- A Go binary compiled for Linux amd64 (or arm64 if using an ARM VPS)
---
## Step 1 — Build your Go binary
On your local machine, cross-compile for your target VPS:
```bash
# For Linux amd64 (most common)
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o myapp
# For Linux arm64 (e.g., Raspberry Pi)
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o myapp
```
The `CGO_ENABLED=0` flag ensures a fully static binary with no external library dependencies.
---
## Step 2 — Upload the binary
```bash
scp myapp yourname@your.vps.ip.address:/tmp/
```
On the VPS, move it to its final location:
```bash
sudo mkdir -p /opt/myapp
sudo mv /tmp/myapp /opt/myapp/
sudo chmod +x /opt/myapp/myapp
```
---
## Step 3 — Create a systemd service file
```bash
sudo nano /etc/systemd/system/myapp.service
```
```ini
[Unit]
Description=My Go Application
After=network.target
Wants=network-online.target
[Service]
Type=simple
User=yourname
Group=yourname
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/myapp
Restart=always
RestartSec=5
EnvironmentFile=-/opt/myapp/.env
# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/myapp
[Install]
WantedBy=multi-user.target
```
---
## Step 4 — Create an environment file
If your app reads configuration from environment variables:
```bash
sudo nano /opt/myapp/.env
```
```
PORT=8080
DATABASE_PATH=/opt/myapp/data.db
LOG_LEVEL=info
```
Secure the file:
```bash
sudo chmod 600 /opt/myapp/.env
sudo chown yourname:yourname /opt/myapp/.env
```
---
## Step 5 — Start and enable the service
```bash
sudo systemctl daemon-reload
sudo systemctl start myapp
sudo systemctl enable myapp # starts on boot
```
Check the status:
```bash
sudo systemctl status myapp
```
---
## Step 6 — Set up Nginx reverse proxy (if it's a web app)
If your Go app serves HTTP on a port like `8080`, put Nginx in front:
```nginx
server {
listen 80;
server_name 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 SSL with Certbot:
```bash
sudo certbot --nginx -d api.example.com
```
---
## Managing the service
| Command | Description |
|---------|-------------|
| `sudo systemctl start myapp` | Start the service |
| `sudo systemctl stop myapp` | Stop the service |
| `sudo systemctl restart myapp` | Restart the service |
| `sudo systemctl status myapp` | Show status and recent logs |
| `sudo systemctl enable myapp` | Enable auto-start on boot |
| `sudo systemctl disable myapp` | Disable auto-start |
| `journalctl -u myapp -f` | Follow live logs |
---
## Updating the binary
```bash
# Build new version locally
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o myapp
# Upload
scp myapp yourname@your.vps.ip.address:/tmp/
# On the VPS
sudo systemctl stop myapp
sudo cp /tmp/myapp /opt/myapp/
sudo systemctl start myapp
sudo systemctl status myapp
```
---
## Logging
Your Go app's stdout and stderr are automatically captured by systemd's journal. View them with:
```bash
journalctl -u myapp -f
```
For persistent log files, your app can write to a file, or you can configure systemd to forward logs to syslog:
```bash
sudo mkdir -p /var/log/myapp
sudo chown yourname:yourname /var/log/myapp
```
Then in your service file, add:
```
StandardOutput=append:/var/log/myapp/stdout.log
StandardError=append:/var/log/myapp/stderr.log
```
---
## What's next
- [Set up automated backups](/vps/automated-backups/) with restic
- [Install fail2ban](/vps/fail2ban/) for SSH brute-force protection