Skip to main content
  1. Posts/

Deploy Aplikasi Web Menggunakan Phusion Passenger

·6 mins·
Table of Contents

Phusion Passenger adalah web application server open source yang berfungsi sebagai jembatan antara web server (Nginx atau Apache) dengan aplikasi berbasis Ruby, Python, maupun Node.js.

Keunggulan Passenger:

  • Mudah digunakan
  • Mempermudah proses deployment ke produksi
  • Skalabel
  • Mendukung multitenancy (bisa menjalankan beberapa aplikasi sekaligus)

Bahasa yang Didukung:

  • Ruby / Ruby on Rails
  • Python
  • Node.js

Integrasi yang Didukung:

  • Nginx
  • Apache
  • Standalone (tanpa web server terpisah)

Passenger secara otomatis mencoba mendeteksi file startup (entry point) sesuai bahasa yang digunakan pada aplikasi.

Passenger Startup File Convention
#

Language Startup File (Convention)
Ruby / Ruby on Rails config.ru
Python passenger_wsgi.py
Node.js app.js

Installation
#

1. Tambahkan Repository Passenger
#

sudo apt-get install -y dirmngr gnupg apt-transport-https ca-certificates curl

curl https://oss-binaries.phusionpassenger.com/auto-software-signing-gpg-key.txt \
  | gpg --dearmor \
  | sudo tee /etc/apt/trusted.gpg.d/phusion.gpg >/dev/null

echo "deb https://oss-binaries.phusionpassenger.com/apt/passenger jammy main" \
  | sudo tee /etc/apt/sources.list.d/passenger.list

sudo apt-get update

2. Install Passenger
#

sudo apt-get install -y passenger

Quickstart Ruby
#

1. Clone repository aplikasi Hello World Ruby
#

git clone https://github.com/devetop/learn-ruby.git
cd learn-ruby

2. Install dependency dengan Bundler
#

bundle config set --local path 'vendor/bundle'
bundle config set --local disable_shared_gems '1'
bundle config set --local deployment 'true'
bundle config set --local without 'development test'
bundle config set --local jobs $(nproc)
bundle install

3. Jalankan aplikasi menggunakan Passenger Standalone
#

passenger start \
  --environment production \
  --daemonize \
  --port 30002 \
  --app-type rack \
  --startup-file config.ru \
  --instance-registry-dir /home/user/tmp/ \
  --pid-file /home/user/run/passenger.30002.pid \
  --log-file /home/user/logs/passenger.30002.log \
  --max-pool-size 6 \
  --min-instances 2 \
  --max-requests 1000 \
  --friendly-error-pages \
  --envvar PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/usr/kerberos/sbin:/usr/kerberos/bin:/sbin:/bin:/root/bin \
  --envvar RAILS_ENV=production \
  --envvar RACK_ENV=production \
  --load-shell-envvars

Passenger akan berjalan di background (daemon mode) pada port 30002.

4. Menjalankan Passenger sebagai systemd Service
#

Agar aplikasi aktif otomatis saat boot dan restart jika crash, buat file:

/etc/systemd/system/myapp-ruby.service

[Unit]
Description=Passenger Standalone for MyApp (Ruby)
After=network.target

[Service]
Type=simple
User=user
Group=user
WorkingDirectory=/home/user/learn-ruby

Environment=PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/usr/kerberos/sbin:/usr/kerberos/bin:/sbin:/bin:/root/bin
Environment=RAILS_ENV=production
Environment=RACK_ENV=production
Environment=PORT=30002

ExecStart=/usr/bin/passenger start \
  --port ${PORT} \
  --app-type rack \
  --startup-file config.ru \
  --instance-registry-dir /home/user/tmp/ \
  --max-pool-size 6 \
  --min-instances 2 \
  --max-requests 1000 \
  --environment production \
  --pid-file /home/user/run/passenger.${PORT}.pid \
  --log-file /home/user/logs/passenger.${PORT}.log

ExecStop=/usr/bin/passenger stop \
  --pid-file /home/user/run/passenger.${PORT}.pid

Restart=always

[Install]
WantedBy=multi-user.target

Aktifkan service:

sudo systemctl daemon-reload
sudo systemctl enable myapp-ruby
sudo systemctl start myapp-ruby

5. Load .env di config.ru (Rack apps)
#

Untuk load .env di dalam config.ru.

require 'dotenv'
Dotenv.load

require './app'
run MyApp

Quickstart Python
#

1. Clone repository aplikasi Hello World Python
#

git clone https://github.com/phusion/passenger-python-flask-demo.git
cd passenger-python-flask-demo

2. Tambahkan file passenger_wsgi.py
#

Passenger membutuhkan entry point WSGI. Tambahkan file berikut di root proyek:

passenger_wsgi.py

import sys
import os

# Tambahkan path aplikasi ke sys.path
sys.path.insert(0, os.path.dirname(__file__))

# Import aplikasi Flask Anda (ubah sesuai nama module)
from app import MyApp as application  # Untuk Flask

# Jika Django, gunakan:
# from your_project.wsgi import application
Pastikan nama aplikasi Flask (MyApp) sesuai dengan yang ada di proyek Anda.

3. Jalankan aplikasi menggunakan Passenger Standalone
#

passenger start \
  --environment production \
  --daemonize \
  --port 30001 \
  --app-type wsgi \
  --startup-file passenger_wsgi.py \
  --instance-registry-dir /home/user/tmp/ \
  --pid-file /home/user/run/passenger.30001.pid \
  --log-file /home/user/logs/passenger.30001.log \
  --max-pool-size 6 \
  --min-instances 2 \
  --max-requests 1000 \
  --friendly-error-pages \
  --envvar PATH=/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/home/user/passenger-python-flask-demo/venv/bin \
  --envvar PYTHON=/home/user/passenger-python-flask-demo/venv/bin/python \
  --envvar WSGI_ENV=production \
  --load-shell-envvars

Passenger akan berjalan di background (daemon mode) pada port 30001.

4. Menjalankan Passenger Python sebagai systemd Service
#

Buat service agar aplikasi berjalan otomatis saat boot dan restart jika crash.

Buat file:

/etc/systemd/system/myapp-python.service

[Unit]
Description=Passenger Standalone for MyApp (Python)
After=network.target

[Service]
Type=simple
User=user
Group=user
WorkingDirectory=/home/user/passenger-python-flask-demo

Environment=PATH=/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/home/user/passenger-python-flask-demo/venv/bin
Environment=WSGI_ENV=production
Environment=PYTHON=/home/user/passenger-python-flask-demo/venv/bin/python
Environment=PORT=30001

ExecStart=/usr/bin/passenger start \
  --port ${PORT} \
  --app-type wsgi \
  --startup-file passenger_wsgi.py \
  --instance-registry-dir /home/user/tmp/ \
  --max-pool-size 6 \
  --min-instances 2 \
  --max-requests 1000 \
  --environment production \
  --pid-file /home/user/run/passenger.${PORT}.pid \
  --log-file /home/user/logs/passenger.${PORT}.log

ExecStop=/usr/bin/passenger stop \
  --pid-file /home/user/run/passenger.${PORT}.pid

Restart=always

[Install]
WantedBy=multi-user.target

Aktifkan service:

sudo systemctl daemon-reload
sudo systemctl enable myapp-python
sudo systemctl start myapp-python

5. Load .env di passenger_wsgi.py
#

Untuk load .env di dalam passenger_wsgi.py.

import sys
import os
from dotenv import load_dotenv

# Path ke .env
env_path = os.path.join(os.path.dirname(__file__), '.env')

# Muat environment variable
load_dotenv(env_path)

# Tambahkan path aplikasi
sys.path.insert(0, os.path.dirname(__file__))

# Import aplikasi Flask/Django
from app import MyApp as application

Quickstart Node
#

1. Clone repository aplikasi Hello World Node.js
#

git clone https://github.com/phusion/passenger-nodejs-connect-demo.git
cd passenger-nodejs-connect-demo

2️. Install dependensi Node.js
#

npm install

3️. Jalankan aplikasi menggunakan Passenger Standalone
#

passenger start \
  --environment production \
  --daemonize \
  --port 30000 \
  --app-type node \
  --startup-file app.js \
  --instance-registry-dir /home/user/tmp/ \
  --pid-file /home/user/run/passenger.30000.pid \
  --log-file /home/user/logs/passenger.30000.log \
  --max-pool-size 6 \
  --min-instances 2 \
  --max-requests 1000 \
  --friendly-error-pages \
  --envvar PATH=/usr/local/apps/nodejs22/bin:/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin \
  --envvar NODE_ENV=production \
  --load-shell-envvars

4️. Membuat Service Systemd (Auto-start + Auto-restart)
#

Untuk membuat aplikasi berjalan otomatis saat boot dan auto-restart jika crash, buat file:

/etc/systemd/system/myapp-node.service

[Unit]
Description=Passenger Standalone for MyApp (Node.js)
After=network.target

[Service]
Type=simple
User=user
Group=user
WorkingDirectory=/home/user/app1

# Environment variables
Environment=PATH=/usr/local/apps/nodejs22/bin:/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
Environment=NODE_ENV=production
Environment=PORT=30000

# Start Passenger
ExecStart=/usr/bin/passenger start \
  --port ${PORT} \
  --environment production \
  --app-type node \
  --startup-file app.js \
  --instance-registry-dir /home/user/tmp/ \
  --pid-file /home/user/run/passenger.${PORT}.pid \
  --log-file /home/user/logs/passenger.${PORT}.log \
  --max-pool-size 6 \
  --min-instances 2 \
  --max-requests 1000

# Stop Passenger
ExecStop=/usr/bin/passenger stop --pid-file /home/user/run/passenger.${PORT}.pid

# Restart automatically if crashed
Restart=always

[Install]
WantedBy=multi-user.target

Aktifkan service:

sudo systemctl daemon-reload
sudo systemctl enable myapp-node
sudo systemctl start myapp-node

5. Load .env di app.js
#

Untuk load .env di dalam app.js.

require('dotenv').config();

const express = require('express');
const app = express();

app.get('/', (req, res) => res.send('Hello World'));
module.exports = app;

Auto-restart Saat File Berubah (Hot Reload Development Mode)
#

Mode ini berguna untuk developer yang ingin melihat perubahan tanpa restart manual.

mkdir -p tmp
touch tmp/always_restart.txt

Log Rotation untuk Passenger
#

Agar ukuran log tidak membesar tanpa batas, Anda dapat menggunakan logrotate untuk melakukan rotasi log otomatis.

Contoh log Passenger biasanya berada di:

/home/user/logs/passenger.<port>.log

Buat file konfigurasi logrotate:

/etc/logrotate.d/passenger

sudo nano /etc/logrotate.d/passenger

Isi dengan konfigurasi berikut:

/home/user/logs/passenger*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    copytruncate
    dateext
    dateformat -%Y%m%d
}

Penjelasan Opsi:

  • daily — rotasi dilakukan setiap hari.
  • rotate 14 — menyimpan 14 arsip log (sekitar dua minggu).
  • compress — mengompres log lama (.gz).
  • delaycompress — kompresi dimulai satu hari setelah rotasi, aman untuk software yang masih memakai file log.
  • notifempty — tidak merotasi jika log kosong.
  • copytruncate — menyalin log lalu mengosongkan file lama tanpa mematikan service (aman untuk Passenger).
  • dateext dan dateformat — menambahkan tanggal pada nama file log rotasi.

Jalankan test untuk memastikan tidak ada error:

sudo logrotate -f /etc/logrotate.d/passenger

Jika berjalan tanpa pesan error, konfigurasi logrotate sudah benar.

Best Practice Struktur Folder untuk Passenger Standalone
#

Struktur folder yang rapi akan mempermudah:

  • deployment
  • log management
  • isolasi environment
  • debugging
  • integrasi dengan systemd
  • backup & restore

Berikut struktur direkomendasikan untuk aplikasi Passenger Standalone (apa pun bahasanya):

/home/user/myapp/
├── app/                     # kode aplikasi utama
├── config/                  # konfigurasi internal app
├── public/                  # file statis (jika ada)
├── vendor/                  # bundler install dir (Ruby)
├── venv/                    # virtualenv (Python)
├── node_modules/            # dependencies (Node.js)
├── logs/                    # log Passenger & app
│   ├── passenger.30001.log
│   ├── app.log
├── run/                     # pid-file
│   └── passenger.30001.pid
├── tmp/                     # cache / always_restart.txt
│   └── always_restart.txt
├── .env                     # environment variable
├── passenger_wsgi.py        # (Python) entry point
├── config.ru                # (Ruby) entry point
├── app.js                   # (Node.js) entry point
└── start.sh                 # optional: wrapper script

Referensi:

Related