Systemd Service untuk Development Tools Lokal

by Marcus Chen
Systemd Service untuk Development Tools Lokal

Masalah: Tools Dev Mati Tiap Reboot

Kamu lagi kerja di project, buka terminal, langsung rails server atau npm run dev — eh, error. Ternyata Redis-nya mati. Jalanin Redis, lanjut kerja, besok pagi reboot laptop, ulang lagi dari awal.

Kalau kamu cuma pakai satu tools mungkin masih oke. Tapi kalau stack kamu butuh Redis, Mailhog, PostgreSQL versi custom, dan beberapa background worker — setiap sesi kerja dimulai dengan ritual manual yang sama. Itu buang waktu dan mental energy.

Solusinya: bikin systemd service untuk development tools kamu. Sekali setup, tools-nya jalan otomatis waktu login atau reboot, log-nya terpusat, dan kamu bisa manage semuanya pakai satu interface.


Kenapa Systemd, Bukan Cron atau Shell Script?

Banyak dev yang pertama kali dengar ini langsung bilang, "Eh, gue tinggal taruh di .bashrc aja kan bisa?"

Bisa. Tapi ada beberapa masalah:

  • .bashrc cuma jalan waktu kamu buka terminal baru. Kalau kamu pakai GUI app yang nggak spawn terminal, tools-nya nggak jalan.
  • Nggak ada restart otomatis kalau process crash.
  • Log-nya berserakan atau nggak ada sama sekali.
  • Susah di-stop dengan bersih — kamu harus pkill manual.

Systemd sudah ada di hampir semua distro Linux modern (Ubuntu, Fedora, Arch, Debian). Dia dirancang buat manage lifecycle process: start, stop, restart, log, dependency antar service. Kita tinggal manfaatin untuk kebutuhan dev.

Dan yang penting: kamu nggak perlu akses root kalau pakai systemd user service. Ini yang akan kita pakai.


Setup Systemd User Service: Contoh dengan Redis

Kita mulai dengan Redis karena hampir semua dev butuh ini. Asumsi Redis sudah terinstall di sistem kamu (redis-server tersedia di PATH).

1. Buat direktori unit file

mkdir -p ~/.config/systemd/user

2. Buat file unit untuk Redis

nano ~/.config/systemd/user/redis-dev.service

Isi file-nya:

[Unit]
Description=Redis Dev Server
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/redis-server --port 6380 --daemonize no
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=default.target

Beberapa hal yang perlu diperhatiin:

  • Gue pakai port 6380 bukan 6379 supaya nggak bentrok sama Redis sistem yang mungkin sudah jalan.
  • --daemonize no penting banget. Systemd butuh process jalan di foreground, bukan fork ke background sendiri.
  • Restart=on-failure artinya kalau Redis crash, systemd otomatis restart.
  • WantedBy=default.target artinya service ini jalan waktu user login.

3. Reload dan enable service

systemctl --user daemon-reload
systemctl --user enable redis-dev.service
systemctl --user start redis-dev.service

4. Cek statusnya

systemctl --user status redis-dev.service

Output yang kamu harap:

● redis-dev.service - Redis Dev Server
     Loaded: loaded (~/.config/systemd/user/redis-dev.service; enabled)
     Active: active (running) since ...

5. Lihat log

journalctl --user -u redis-dev.service -f

Flag -f buat follow log secara real-time, mirip tail -f.


Contoh Kedua: Mailhog untuk Testing Email

Mailhog adalah SMTP server lokal yang nangkap semua email yang dikirim app kamu — email nggak kemana-mana, cuma ke Mailhog. Sangat berguna waktu development.

Download binary-nya dulu:

wget https://github.com/mailhog/MailHog/releases/latest/download/MailHog_linux_amd64 -O ~/bin/mailhog
chmod +x ~/bin/mailhog

Buat file unit-nya:

nano ~/.config/systemd/user/mailhog.service
[Unit]
Description=Mailhog Dev SMTP
After=network.target

[Service]
Type=simple
ExecStart=%h/bin/mailhog -smtp-bind-addr 0.0.0.0:1025 -ui-bind-addr 0.0.0.0:8025
Restart=on-failure
RestartSec=3
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=default.target

Perhatiin %h — itu adalah specifier systemd untuk home directory kamu. Lebih portable daripada hardcode /home/username.

Enable dan start:

systemctl --user daemon-reload
systemctl --user enable mailhog.service
systemctl --user start mailhog.service

Sekarang akses http://localhost:8025 untuk UI Mailhog, dan arahkan SMTP app kamu ke localhost:1025.


Contoh Ketiga: Custom PostgreSQL Instance

Kadang kamu butuh PostgreSQL versi berbeda dari yang ada di sistem — misalnya project lama butuh PG 14 sementara sistem kamu sudah PG 16. Atau kamu mau isolasi data dev dari sistem.

Anggap kamu sudah install PostgreSQL 14 via pg_lsclusters atau manual, dengan data directory di ~/pgdata-dev:

# Inisialisasi cluster baru (sekali aja)
initdb -D ~/pgdata-dev

Buat file unit:

nano ~/.config/systemd/user/postgres-dev.service
[Unit]
Description=PostgreSQL Dev Instance
After=network.target

[Service]
Type=simple
ExecStart=/usr/lib/postgresql/14/bin/postgres -D %h/pgdata-dev -p 5433
ExecStop=/usr/lib/postgresql/14/bin/pg_ctl stop -D %h/pgdata-dev -m fast
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=default.target

Port 5433 supaya nggak bentrok sama PostgreSQL sistem di 5432.


Gotcha yang Gue Kena

1. Linger — service nggak jalan setelah logout

Ini gotcha paling umum. Kalau kamu kerja di server remote dan logout dari SSH, semua user service langsung mati. Solusinya:

loginctl enable-linger $USER

Perintah ini bikin systemd tetap jalan user session kamu meskipun kamu logout. Penting banget kalau kamu setup dev tools di VPS atau server dev bersama.

2. Environment variable nggak ter-load

User service nggak otomatis baca .bashrc atau .zshrc kamu. Kalau service butuh environment variable tertentu, ada dua cara:

Cara 1: Tambahkan langsung di file unit:

[Service]
Environment=REDIS_URL=redis://localhost:6380
Environment=NODE_ENV=development

Cara 2: Pakai file environment terpisah:

nano ~/.config/systemd/user/dev-env.conf
REDIS_URL=redis://localhost:6380
DATABASE_URL=postgresql://localhost:5433/myapp_dev

Lalu di file unit:

[Service]
EnvironmentFile=%h/.config/systemd/user/dev-env.conf

3. Binary nggak ketemu di PATH

Systemd user service punya PATH yang lebih terbatas dari shell kamu. Kalau service gagal dengan error "command not found", coba pakai absolute path:

# Cek path binary
which redis-server
# Output: /usr/bin/redis-server

Lalu pakai /usr/bin/redis-server di ExecStart, bukan cuma redis-server.

4. Type=forking vs Type=simple

Kalau kamu pakai tools yang secara default fork ke background (daemonize), kamu perlu paksa dia jalan di foreground ATAU ganti Type=forking dan kasih tau systemd PID file-nya. Cara termudah: selalu cari flag --foreground atau --no-daemon di tools yang kamu pakai.


Manage Semua Services Sekaligus

Kalau kamu punya banyak dev service, repot juga kalau harus start satu-satu. Bikin target group:

nano ~/.config/systemd/user/dev-tools.target
[Unit]
Description=All Dev Tools
Wants=redis-dev.service mailhog.service postgres-dev.service
After=redis-dev.service mailhog.service postgres-dev.service

[Install]
WantedBy=default.target

Enable target-nya:

systemctl --user enable dev-tools.target

Sekarang kamu bisa:

# Start semua sekaligus
systemctl --user start dev-tools.target

# Stop semua sekaligus
systemctl --user stop dev-tools.target

# Cek status semua
systemctl --user list-units --type=service --state=running

Cheat Sheet Command Systemd User Service

# Reload setelah ubah file unit
systemctl --user daemon-reload

# Enable (jalan otomatis saat login)
systemctl --user enable nama-service.service

# Disable (nggak jalan otomatis)
systemctl --user disable nama-service.service

# Start manual
systemctl --user start nama-service.service

# Stop
systemctl --user stop nama-service.service

# Restart
systemctl --user restart nama-service.service

# Cek status
systemctl --user status nama-service.service

# Lihat log (100 baris terakhir)
journalctl --user -u nama-service.service -n 100

# Follow log real-time
journalctl --user -u nama-service.service -f

# List semua user service
systemctl --user list-units --type=service

Yang Gue Lakuin Sekarang

Setup ini gue pakai di laptop dev dan VPS kecil yang gue sewa buat testing. Semua development tools — Redis, Mailhog, PostgreSQL dev instance, dan beberapa background job worker — jalan otomatis.

Workflow gue sekarang: buka laptop, langsung buka IDE, langsung coding. Nggak ada ritual "eh Redis belum jalan" atau "lupa start worker"-nya.

Kalau kamu mau lanjut dari sini:

  1. Coba dulu dengan satu service — Redis atau Mailhog, yang paling sering kamu pakai manual.
  2. Tambahkan Environment atau EnvironmentFile kalau service butuh config spesifik.
  3. Aktifkan linger kalau kamu kerja di server remote.
  4. Buat dev-tools.target setelah kamu punya 3+ services supaya management-nya lebih gampang.

Satu kali setup, kamu nggak perlu mikirin lagi. Itu yang bikin WordPress object cache dan caching strategy secara umum penting untuk performa — sama halnya dengan systemd service untuk development tools, ini tentang automation yang nggak perlu dipikirkan lagi. Bukan karena keren, tapi karena nggak ada yang lebih nyebelin dari debugging sambil lupa Redis-nya belum jalan.