~/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.
Contoh command di dokumen ini pakai Ubuntu/Debian (apt). Kalau server-nya distro RHEL-based (Rocky Linux/AlmaLinux/CentOS Stream, pakai dnf), lihat catatan padanan di tiap langkah yang berbeda — binary Go hasil compile statis, jadi tidak butuh package runtime apa pun di server (tidak ada Remi/PHP yang relevan di sini), cuma Nginx.
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(Rocky Linux/AlmaLinux:sudo dnf 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.goscp 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.targetSesuaikan 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 app4. 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.Rocky Linux/AlmaLinux: tidak ada sites-available/sites-enabled bawaan — taruh langsung file konfigurasinya di /etc/nginx/conf.d/app.conf (tanpa symlink). Firewall default-nya firewalld, bukan ufw:
sudo firewall-cmd --permanent --add-service=http --add-service=https
sudo firewall-cmd --reloadSELinux aktif default di RHEL-based — kalau Nginx gagal proxy_pass ke 127.0.0.1:8080 padahal config & service sudah benar, biasanya SELinux yang blok koneksi keluar dari proses Nginx: sudo setsebool -P httpd_can_network_connect 1.
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.comRocky Linux/AlmaLinux: paket certbot-nya dari EPEL (sudo dnf install epel-release -y dulu kalau belum ada):
sudo dnf install certbot python3-certbot-nginx -y
sudo certbot --nginx -d app.example.comKonfigurasi 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.