Membuat Layanan Systemd Kustom untuk Aplikasi Linux

Systemd adalah manajer layanan (init system) di Linux modern. Layanan systemd memungkinkan aplikasi berjalan otomatis saat boot, restart jika crash, dan dikelola dengan mudah. Artikel ini membahas cara membuat service unit systemd kustom untuk mengelola aplikasi Linux.

Pengertian Systemd

Systemd adalah sistem inisialisasi dan manajemen layanan yang menggantikan SysVinit tradisional. Systemd mengelola semua proses di Linux, mulai dari booting sistem hingga menjalankan aplikasi sebagai layanan (daemon).

Keunggulan Systemd

  • Auto-start: Aplikasi berjalan otomatis saat server dinyalakan
  • Auto-restart: Layanan otomatis restart jika crash
  • Dependency Management: Layanan dijalankan sesuai urutan dependensinya
  • Logging Terpusat: Semua log dikelola oleh journald
  • Resource Control: Batasi CPU, memory, dan I/O per layanan
  • Status Monitoring: Cek status layanan kapan saja

Struktur Unit File Systemd

File unit systemd berada di /etc/systemd/system/ atau /lib/systemd/system/. Format file adalah [Section].

ini
[Unit]       # Deskripsi dan dependensi
[Service]    # Konfigurasi layanan
[Install]    # Kapan layanan diaktifkan

Penjelasan Section

  • [Unit]: Informasi umum, deskripsi, dependensi
  • [Service]: Bagaimana layanan dijalankan
  • [Install]: Kapan layanan aktif (runlevel)

Membuat Layanan Kustom

1. Buat Unit File

bash
nano /etc/systemd/system/myapp.service

2. Template Dasar

ini
[Unit]
Description=My Web Application
After=network.target nginx.service
Requires=nginx.service

[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/node app.js
Restart=always
RestartSec=10
Environment=NODE_ENV=production
Environment=PORT=3000
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp

# Resource limits
LimitNOFILE=65536
LimitNPROC=4096
MemoryLimit=512M
CPUQuota=80%

# Security
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ReadWritePaths=/opt/myapp/uploads

[Install]
WantedBy=multi-user.target

3. Aktifkan dan Jalankan

bash
# Reload systemd untuk mendeteksi unit baru
systemctl daemon-reload

# Aktifkan layanan (auto-start saat boot)
systemctl enable myapp

# Jalankan layanan
systemctl start myapp

# Cek status
systemctl status myapp

Jenis-Jenis Layanan Systemd

1. Simple Service

Untuk aplikasi yang berjalan di foreground:

ini
[Service]
Type=simple
ExecStart=/usr/bin/node app.js

2. Forking Service

Untuk aplikasi yang fork (daemonize):

ini
[Service]
Type=forking
ExecStart=/usr/bin/myapp --daemon
PIDFile=/run/myapp.pid

3. Oneshot Service

Untuk tugas yang berjalan sekali dan selesai:

ini
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
RemainAfterExit=yes

4. Timer Service

Untuk penjadwalan (pengganti cron):

ini
# backup.timer
[Unit]
Description=Run Database Backup Daily

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target
ini
# backup.service
[Unit]
Description=Database Backup

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup-db.sh

Aktifkan timer:

bash
systemctl enable backup.timer
systemctl start backup.timer

Mengelola Layanan

Perintah Dasar

bash
# Mulai layanan
systemctl start myapp

# Hentikan layanan
systemctl stop myapp

# Restart layanan
systemctl restart myapp

# Reload konfigurasi (tanpa restart)
systemctl reload myapp

# Cek status
systemctl status myapp

# Cek log
journalctl -u myapp
journalctl -u myapp -f       # Real-time
journalctl -u myapp --since "1 hour ago"

# Aktifkan auto-start
systemctl enable myapp

# Nonaktifkan auto-start
systemctl disable myapp

# Lihat semua layanan aktif
systemctl list-units --type=service --state=running

Contoh: Node.js Application Service

bash
nano /etc/systemd/system/webapp.service
ini
[Unit]
Description=Web Application Server
After=network.target postgresql.service redis.service
Requires=postgresql.service redis.service

[Service]
Type=simple
User=deploy
Group=deploy
WorkingDirectory=/opt/webapp
EnvironmentFile=/opt/webapp/.env
ExecStart=/usr/bin/node /opt/webapp/server.js
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=webapp

# Node.js specific
Environment=NODE_ENV=production
Environment=PORT=3000

# Resource limits
LimitNOFILE=65536
MemoryLimit=1G
CPUQuota=70%

# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/webapp/uploads
ReadWritePaths=/opt/webapp/logs

[Install]
WantedBy=multi-user.target

Contoh: Python Application Service

ini
[Unit]
Description=Python Bot Service
After=network.target

[Service]
Type=simple
User=bot
Group=bot
WorkingDirectory=/opt/bot
ExecStart=/usr/bin/python3 /opt/bot/bot.py
Restart=always
RestartSec=5
EnvironmentFile=/opt/bot/.env
StandardOutput=journal
StandardError=journal
SyslogIdentifier=bot

# Virtual environment
Environment=PATH=/opt/bot/venv/bin:/usr/bin:/usr/local/bin
ExecStart=/opt/bot/venv/bin/python /opt/bot/bot.py

[Install]
WantedBy=multi-user.target

Contoh: Bash Script as Service

ini
[Unit]
Description=Backup Service
After=network.target

[Service]
Type=oneshot
User=root
ExecStart=/usr/local/bin/backup.sh
StandardOutput=journal
StandardError=journal
SyslogIdentifier=backup

[Install]
WantedBy=multi-user.target

Dependency Management

Layanan Berketergantungan

ini
[Unit]
Description=My App
After=nginx.service postgresql.service redis.service
Requires=postgresql.service redis.service
Wants=nginx.service

[Service]
# ...

Penjelasan:

  • After: Jalankan setelah layanan ini
  • Requires: Wajib aktif, layanan gagal jika dependency gagal
  • Wants: Opsional, layanan tetap berjalan walau dependency gagal
  • BindsTo: Sangat ketat, layanan berhenti jika dependency berhenti

Contoh: Layanan dengan Chain Dependencies

ini
[Unit]
Description=Full Stack Application
After=postgresql.service redis.service nginx.service
Requires=postgresql.service redis.service
Before=nginx.service

Template Layanan (Multi-instance)

Membuat satu template untuk banyak instance layanan:

bash
# Template unit
nano /etc/systemd/system/@app-instance.service
ini
[Unit]
Description=Application Instance %i
After=network.target

[Service]
Type=simple
User=app
WorkingDirectory=/opt/app-%i
ExecStart=/usr/bin/node /opt/app-%i/server.js
Restart=always
Environment=INSTANCE_ID=%i
Environment=PORT=300%i

[Install]
WantedBy=multi-user.target

Jalankan beberapa instance:

bash
systemctl enable app-instance@1
systemctl enable app-instance@2
systemctl enable app-instance@3
systemctl start app-instance@1 app-instance@2 app-instance@3

Health Check dengan Systemd

1. StartLimit (Batasi Restart)

ini
[Service]
StartLimitInterval=60
StartLimitBurst=5

Ini menghentikan layanan setelah 5 restart dalam 60 detik.

2. Watchdog (Pemantauan Aktif)

ini
[Service]
Type=notify
WatchdogSec=30

Aplikasi harus mengirim heartbeat setiap 30 detik:

python
import systemd.daemon
systemd.daemon.notify("WATCHDOG=1")

3. Status Check Custom

ini
[Service]
ExecStartPre=/usr/local/bin/check-dependencies.sh
ExecStartPost=/usr/local/bin/notify-start.sh
ExecStop=/usr/local/bin/cleanup.sh

Logging dengan Journald

1. Lihat Log Layanan

bash
# Semua log layanan
journalctl -u myapp

# Log terakhir 100 baris
journalctl -u myapp -n 100

# Log real-time
journalctl -u myapp -f

# Log dari waktu tertentu
journalctl -u myapp --since "2026-09-04 02:00:00" --until "2026-09-04 06:00:00"

# Log dengan prioritas tertentu
journalctl -u myapp -p err

2. Atur Ukuran Log

bash
# Edit konfigurasi journald
nano /etc/systemd/journald.conf
ini
[Journal]
SystemMaxUse=500M
RuntimeMaxUse=200M
MaxFileSec=1month
MaxRetentionSec=3months

3. Export Log

bash
# Export log ke file
journalctl -u myapp > myapp.log

# Export dalam format JSON
journalctl -u myapp -o json > myapp.json

Troubleshooting

1. Layanan Tidak Bisa Start

Solusi:

bash
# Cek error detail
systemctl status myapp
journalctl -u myapp -e
# Coba jalankan manual untuk debug
/usr/bin/node /opt/myapp/app.js

2. Layanan Crash Berulang

Penyebab: Aplikasi error terus-menerus. Solusi:

bash
# Cek berapa kali restart
systemctl show myapp | grep NRestarts
# Cek log
journalctl -u myapp --no-pager | tail -50
# Tambahkan start limit
StartLimitInterval=60
StartLimitBurst=5

3. Layanan Tidak Auto-start

Penyebab: Tidak di-enable atau service file salah. Solusi:

bash
# Enable layanan
systemctl enable myapp
# Cek apakah aktif
systemctl is-enabled myapp
# Reload daemon
systemctl daemon-reload

4. Permission Denied

Penyebab: User tidak punya akses ke file atau port. Solusi:

bash
# Pastikan user benar
User=app
Group=app
# Pastikan permission file benar
chown -R app:app /opt/myapp
# Jika port < 1024, gunakan auth-bind atau port tinggi

5. Service Tidak Muncul di Status

Penyebab: File unit tidak ada atau lokasi salah. Solusi:

bash
# Cek file unit ada
ls -la /etc/systemd/system/myapp.service
# Reload daemon
systemctl daemon-reload
# Cek semua service
systemctl list-unit-files | grep myapp

6. Environment Variables Tidak Terbaca

Penyebab: EnvironmentFile salah path atau format. Solusi:

bash
# Pastikan file ada dan readable
ls -la /opt/myapp/.env
# Cek format file (KEY=VALUE)
cat /opt/myapp/.env
# Debug
systemctl show myapp | grep Environment

Kesimpulan

Systemd service unit memberikan cara profesional untuk mengelola aplikasi Linux sebagai layanan. Dengan auto-start, auto-restart, dependency management, dan resource limits, aplikasi Anda akan berjalan dengan stabil dan dapat dipantau dengan mudah.

Kunci utama:

  • Selalu gunakan systemctl daemon-reload setelah membuat/mengubah service file
  • Gunakan Restart=on-failure atau Restart=always untuk ketahanan layanan
  • Atur resource limits untuk mencegah satu layanan membebani server
  • Gunakan EnvironmentFile untuk mengelola secret dan konfigurasi
  • Pantau log dengan journalctl untuk troubleshooting
  • Gunakan systemctl enable agar layanan auto-start saat boot
  • Backup service file sebelum melakukan perubahan
Catatan penting: Jangan pernah menjalankan aplikasi sebagai root kecuali benar-benar diperlukan. Selalu gunakan user dan group khusus untuk setiap layanan. Gunakan opsi keamanan NoNewPrivileges=true, ProtectSystem=strict, dan PrivateTmp=true untuk meminimalkan risiko keamanan. Jangan lupa backup service file sebelum mengubahnya agar bisa di-rollback jika terjadi error yang menyebabkan layanan tidak bisa berjalan.
Ingat: Layanan systemd yang dikonfigurasi dengan baik adalah tulang punggung operasional server Anda. Setiap layanan harus diawasi, di-restart otomatis jika gagal, dan berjalan dengan user yang benar. Investasikan waktu untuk memahami setiap opsi konfigurasi systemd — ini akan menghemat waktu troubleshooting di masa depan dan membuat server Anda lebih reliable.
Dipublikasikan untuk membantu para administrator server dalam mengelola aplikasi Linux sebagai layanan systemd secara profesional.

Artikel Terkait