~/saidqb cat wiki/stack/server/deploy-go.md
commit by saidqb
Deploy Go (systemd + Nginx)
Beda dari Laravel/FastAPI: Go compile jadi satu binary statis, tidak butuh interpreter/runtime terinstall di server sama sekali (tidak ada composer install/pip install di server). Build dilakukan di local/CI, hasilnya tinggal dikirim & dijalankan.
Tiap project dapat Linux user sendiri (/home/<appuser>/app), bukan numpuk di satu folder /var/www bersama — kalau server ini dipakai buat banyak project, satu project ke-compromise tidak otomatis bisa baca file project lain.
0. Prasyarat sebelum deploy
- Akses SSH ke server (user dengan hak
sudo) — disiapkan penyedia server, bukan sesuatu yang di-install - Domain sudah diarahkan (DNS A record) ke IP server — diatur di panel DNS registrar, bukan di server
- Go terinstall di mesin yang dipakai untuk build (local/CI — bukan server produksi, server cuma jalanin binary hasil compile): cek go.dev/dl, lalu
go version - Nginx sudah terinstall di server:
sudo apt install nginx -y
1. Buat user khusus untuk app
sudo adduser --disabled-password --gecos "" goapp
--disabled-password — user ini tidak bisa login pakai password (cuma diakses lewat sudo -iu goapp dari user SSH yang sudah masuk). --gecos "" skip pertanyaan nama/nomor telepon dsb yang tidak relevan buat service account. Home directory-nya otomatis jadi /home/goapp.
ssh user@server 'sudo mkdir -p /home/goapp/app && sudo chown goapp:goapp /home/goapp/app'
2. Build binary (local/CI) & kirim ke server
Go bisa cross-compile buat target Linux dari mesin apa pun (Windows/macOS/Linux) — GOOS/GOARCH ganti target-nya:
GOOS=linux GOARCH=amd64 go build -o app main.go
scp app user@server:/home/goapp/app/app
ssh user@server 'sudo chown goapp:goapp /home/goapp/app/app && sudo chmod +x /home/goapp/app/app'
3. Buat systemd service
/etc/systemd/system/app.service
[Unit]
Description=Go app
After=network.target
[Service]
User=goapp
Group=goapp
WorkingDirectory=/home/goapp/app
ExecStart=/home/goapp/app/app
Restart=always
Environment=PORT=8080
[Install]
WantedBy=multi-user.target
Sesuaikan Environment= dengan config yang dibaca app-nya (DB_DSN, dll) — atau pakai file .env/EnvironmentFile=/home/goapp/app/.env kalau app-nya baca lewat file, bukan env var langsung.
sudo systemctl daemon-reload
sudo systemctl enable --now app
4. Reverse proxy Nginx
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
sudo ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo ufw allow 'Nginx Full' # buka port 80/443 di firewall — tanpa ini situs tidak bisa diakses dari luar meski Nginx sudah jalan benar, kalau ufw aktif (default di banyak VPS). Port 8080 tidak perlu dibuka karena cuma diakses lewat proxy_pass internal.
5. Urutan tiap kali deploy update
GOOS=linux GOARCH=amd64 go build -o app main.go
scp app user@server:/home/goapp/app/app.new
ssh user@server 'sudo systemctl stop app && sudo mv /home/goapp/app/app.new /home/goapp/app/app && sudo chown goapp:goapp /home/goapp/app/app && sudo chmod +x /home/goapp/app/app && sudo systemctl start app'
Kirim ke nama file sementara (app.new) dulu baru mv — kalau scp langsung menimpa app yang sedang dieksekusi systemd, ada risiko file rusak/setengah-tertulis kebaca proses lama sebelum sempat restart. mv di filesystem yang sama itu atomic, jadi aman.
Opsional: HTTPS
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d app.example.com
Konfigurasi SSL-nya tidak perlu ditulis manual — plugin --nginx otomatis suntik langsung ke server block yang sudah dibuat di Langkah 4, dan pasang auto-renewal sendiri. Lihat deploy-laravel.md bagian HTTPS buat contoh lengkap hasil suntikannya.
Kalau domain dipasang di belakang Cloudflare (proxy oranye), lihat catatan cloudflare.md — ada penyesuaian mode SSL/TLS & opsi sertifikat yang perlu diperhatikan.