Lewati ke isi

Server & Infrastruktur

Cara Membuat Service systemd untuk Aplikasi Kamu

Jalankan aplikasi Node.js, Python, atau Go sebagai service systemd: file unit, restart otomatis, environment, user non-root, dan journalctl.

Terbit 5 menit baca

Jawaban singkat

Buat file unit di /etc/systemd/system/nama.service berisi perintah start, user non-root, folder kerja, file environment, dan Restart=on-failure. Jalankan systemctl daemon-reload, lalu systemctl enable --now nama. Log dibaca dengan journalctl -u nama.

Daftar isi
  1. Apa yang sebenarnya dilakukan systemd?
  2. Langkah membuat service systemd
  3. Langkah 1. Siapkan user khusus aplikasi
  4. Langkah 2. Pisahkan konfigurasi ke file environment
  5. Langkah 3. Tulis file unit
  6. Langkah 4. Muat, nyalakan, dan aktifkan saat boot
  7. Langkah 5. Baca log dengan journalctl
  8. Langkah 6. Uji restart otomatis
  9. Bagaimana untuk Python dan Go?
  10. Opsi tambahan yang berguna
  11. Pertanyaan yang sering diajukan

Aplikasimu mati begitu jendela SSH ditutup, atau tidak hidup lagi setelah server reboot? Itu tanda aplikasi masih dijalankan secara manual dari terminal. Di server Linux modern, cara yang rapi adalah menjadikannya service systemd: aplikasi berjalan di latar belakang, otomatis hidup saat boot, otomatis dinyalakan ulang bila crash, dan lognya tersimpan di satu tempat.

Kamu cukup menulis satu file teks pendek. Langkah di bawah memakai contoh aplikasi Node.js, lalu menunjukkan apa yang berubah untuk Python dan Go.

Apa yang sebenarnya dilakukan systemd?

systemd adalah sistem init di sebagian besar distro Linux saat ini, termasuk Ubuntu, Debian, dan keluarga Red Hat. Ia menyalakan dan mengawasi semua layanan, dari SSH sampai web server. Setiap layanan dijelaskan dalam file unit. Untuk aplikasi yang berjalan terus, jenis unitnya adalah .service.

Dibanding nohup, screen, atau menjalankan dengan &, service systemd memberi pengawasan: systemd tahu kapan proses mati, bisa menyalakannya lagi, dan mencatat semua output ke journal.

Langkah membuat service systemd

Langkah 1. Siapkan user khusus aplikasi

Jangan jalankan aplikasi web sebagai root. Bila aplikasi dibobol, penyerang hanya mendapat hak user tersebut.

sudo useradd --system --create-home --shell /usr/sbin/nologin appku
sudo mkdir -p /opt/appku
sudo chown -R appku:appku /opt/appku

Pindahkan kode aplikasi ke /opt/appku. Prinsip memisahkan hak akses ini bagian dari langkah awal mengamankan VPS.

Langkah 2. Pisahkan konfigurasi ke file environment

Simpan variabel seperti port, alamat database, dan API key di file terpisah, bukan di file unit:

sudo nano /etc/appku.env
NODE_ENV=production
PORT=3000
DATABASE_URL=postgres://appku:rahasia@localhost/appku
sudo chown root:appku /etc/appku.env
sudo chmod 640 /etc/appku.env

File ini hanya bisa dibaca root dan grup aplikasi.

Langkah 3. Tulis file unit

Buat /etc/systemd/system/appku.service:

[Unit]
Description=Aplikasi appku
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=appku
Group=appku
WorkingDirectory=/opt/appku
EnvironmentFile=/etc/appku.env
ExecStart=/usr/bin/node /opt/appku/server.js
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Penjelasan singkat bagian yang penting:

  • After dan Wants membuat service menunggu jaringan siap. Bila aplikasi bergantung pada database di server yang sama, tambahkan juga unit database di After, misalnya postgresql.service.
  • ExecStart wajib memakai path lengkap ke program. Cek dengan command -v node. Kalau Node dipasang lewat nvm, path-nya ada di folder home user, jadi lebih aman memasang Node dari paket sistem atau menulis path lengkap hasil nvm.
  • Restart=on-failure menyalakan ulang proses bila keluar dengan error atau terbunuh sinyal. Pilih always bila aplikasi harus hidup apa pun alasan berhentinya.
  • WantedBy=multi-user.target membuat service ikut menyala saat boot normal.

Langkah 4. Muat, nyalakan, dan aktifkan saat boot

sudo systemctl daemon-reload
sudo systemctl enable --now appku
sudo systemctl status appku

daemon-reload wajib setiap kali file unit diubah. enable --now sekaligus mengaktifkan saat boot dan menyalakan sekarang. Status yang benar menunjukkan active (running).

Langkah 5. Baca log dengan journalctl

Semua yang ditulis aplikasi ke stdout dan stderr masuk ke journal:

journalctl -u appku -f          # ikuti log secara langsung
journalctl -u appku -b          # log sejak boot terakhir
journalctl -u appku --since "1 hour ago"

Tidak perlu lagi mengurus file log sendiri, asalkan ukuran journal dibatasi. Atur SystemMaxUse= di /etc/systemd/journald.conf agar journal tidak memakan disk tanpa batas.

Langkah 6. Uji restart otomatis

Pastikan pengawasan benar-benar bekerja:

sudo systemctl kill -s SIGKILL appku
sleep 6
systemctl status appku

Dalam beberapa detik, status harus kembali active (running) dengan PID baru. Uji juga dengan reboot server sekali, karena itu skenario yang pasti terjadi suatu saat.

Bagaimana untuk Python dan Go?

Struktur file unit sama, yang berubah hanya ExecStart.

Untuk aplikasi Python di virtualenv, arahkan langsung ke program di folder bin venv sehingga tidak perlu "activate":

ExecStart=/opt/appku/venv/bin/gunicorn --bind 127.0.0.1:8000 app:app

Tambahkan Environment=PYTHONUNBUFFERED=1 agar output Python langsung muncul di journal, tidak tertahan di buffer.

Untuk Go, hasil build berupa satu file biner, jadi ExecStart cukup menunjuk ke biner itu:

ExecStart=/opt/appku/appku-server

Di depan aplikasi biasanya dipasang web server sebagai reverse proxy yang menangani domain dan HTTPS. Pilihannya dibahas di Nginx vs Apache vs LiteSpeed.

Opsi tambahan yang berguna

OpsiFungsiContoh
Restart=Kapan proses dinyalakan ulangon-failure, always
RestartSec=Jeda sebelum restart5
Environment=Satu variabel langsung di unitEnvironment=PORT=3000
EnvironmentFile=Variabel dari file terpisah/etc/appku.env
NoNewPrivileges=Cegah proses menaikkan haktrue
ProtectSystem=Jadikan sebagian besar sistem file hanya-bacafull atau strict
PrivateTmp=Folder /tmp terpisah untuk servicetrue
MemoryMax=Batas memori service512M
ExecReload=Perintah untuk reload tanpa restart/bin/kill -HUP $MAINPID

Opsi pengerasan seperti ProtectSystem=strict bisa membuat aplikasi gagal menulis file. Tambahkan satu per satu, uji, dan izinkan folder tertentu dengan ReadWritePaths=. Perintah systemd-analyze security appku memberi gambaran opsi mana yang belum dipakai.

Pertanyaan yang sering diajukan

Apa beda systemctl restart dan reload?

Restart menghentikan lalu menyalakan proses baru. Reload menjalankan perintah ExecReload, biasanya memberi tahu aplikasi untuk membaca ulang konfigurasi tanpa berhenti. Reload hanya bisa bila aplikasinya mendukung.

Kenapa service berhenti mencoba restart setelah beberapa kali gagal?

systemd punya batas percobaan start dalam rentang waktu tertentu (StartLimitBurst dan StartLimitIntervalSec). Bila terlampaui, service masuk status gagal. Perbaiki penyebabnya, lalu jalankan systemctl reset-failed appku.

Apakah perlu PM2 kalau sudah pakai systemd?

Tidak wajib. systemd sudah menangani start saat boot, restart otomatis, dan log. PM2 bisa tetap dipakai bila kamu butuh fiturnya seperti mode cluster, tapi jangan sampai dua pengawas saling berebut proses.

Bisakah service systemd dibuat tanpa root?

Bisa, dengan user service di ~/.config/systemd/user dan perintah systemctl --user. Agar tetap berjalan setelah logout, aktifkan lingering dengan loginctl enable-linger nama-user.

Bagaimana menjalankan tugas terjadwal dengan systemd?

Buat service bertipe oneshot lalu pasangkan dengan file .timer. Bandingannya dengan cron dibahas di cara membuat cron job di Linux.

Daftar periksa singkat:

  • Aplikasi berjalan sebagai user non-root
  • Rahasia ada di file environment dengan izin 640
  • ExecStart memakai path lengkap
  • Restart=on-failure atau always sudah dipasang
  • systemctl enable dijalankan, dan uji reboot berhasil
  • Ukuran journal dibatasi

Baca juga