Aplikasi Python: gunicorn dan systemd
Menjalankan Django, Flask, atau FastAPI di VDS: virtual environment, gunicorn dengan socket, layanan systemd, dan memilih jumlah worker untuk tier Anda.
Diperbarui 23 Agustus 2026
Server pengembangan bawaan (manage.py runserver, flask run) tidak dirancang untuk beban produksi. Di VPS, Anda memasang gunicorn atau uvicorn, lalu sebuah web server melayaninya secara eksternal.
Lingkungan
Jangan pernah memasang paket proyek ke Python sistem — pembaruan sistem akan merusak aplikasi.
apt install -y python3 python3-venv python3-pip
useradd -r -m -d /srv/app -s /usr/sbin/nologin appuser
sudo -u appuser python3 -m venv /srv/app/venv
sudo -u appuser /srv/app/venv/bin/pip install -r /srv/app/requirements.txt
sudo -u appuser /srv/app/venv/bin/pip install gunicorn
Untuk FastAPI, pasang juga uvicorn[standard] — gunicorn menjalankannya sebagai worker class.
Service
/etc/systemd/system/myapp.service:
[Unit]
Description=Python app
After=network-online.target postgresql.service
[Service]
User=appuser
WorkingDirectory=/srv/app
EnvironmentFile=/srv/app/.env
ExecStart=/srv/app/venv/bin/gunicorn \
--workers 3 \
--bind unix:/run/myapp/gunicorn.sock \
--access-logfile - \
myproject.wsgi:application
RuntimeDirectory=myapp
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Untuk FastAPI, ganti baris peluncuran dengan --worker-class uvicorn.workers.UvicornWorker app.main:app.
systemctl daemon-reload
systemctl enable --now myapp
journalctl -u myapp -f
RuntimeDirectory=myapp membuat /run/myapp dengan izin yang diperlukan pada setiap start — jika tidak, tidak ada tempat untuk menaruh socket.
Berapa banyak worker
Rumus yang biasa dipakai adalah 2 × cores + 1, tetapi ini terbentur batas memori: setiap worker Django memakai 80–200 MB.
| Tier | Core | Worker |
|---|---|---|
| VDS-1 | 1 | 2 |
| VDS-2 | 2 | 3 |
| VDS-3 | 4 | 5 |
| VDS-4 | 6 | 9 |
Jika aplikasi banyak menghabiskan waktu menunggu jaringan dan database, tambahkan --threads 2 alih-alih menambah jumlah proses.
Web server
location / {
proxy_pass http://unix:/run/myapp/gunicorn.sock;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /static/ { alias /srv/app/static/; }
Layani file statis Django langsung dengan Nginx setelah mengumpulkannya: collectstatic. Melewatkannya melalui Python hanya menambah beban yang tidak perlu.
Kesalahan umum
| Gejala | Penyebab |
|---|---|
502 dan connect() to unix:... failed (13) | Nginx tidak punya izin untuk socket — atur --umask 007 dan grup bersama |
ModuleNotFoundError | Dijalankan dengan Python sistem, bukan dari venv |
DisallowedHost di Django | Domain belum ditambahkan ke ALLOWED_HOSTS |
| Worker dimatikan karena timeout | Request berjalan lama — naikkan --timeout, pindahkan pekerjaan berat ke queue |
| Semuanya berhenti setelah rilis | Anda lupa systemctl restart myapp — kode di memori tidak memperbarui dirinya sendiri |
Simpan rahasia di
EnvironmentFiledengan izin600, bukan disettings.py. File settings cepat atau lambat akan berakhir di repositori.