PM2 + Nginx ters proxy: Node.js uygulamasını 80 numaralı porta bağlama
Ubuntu 24.04 sunucusuna Node.js PM2 Nginx ters proxy yapısını kurduk: uygulamayı PM2 çalıştırıyor, 80 numaralı porta gelen istekleri de Nginx uygulamaya aktarıyor. Uygulama süreci zorla sonlandırılsa veya sunucu yeniden başlatılsa bile PM2'nin uygulamayı tekrar çalıştırdığını da doğruladık.
Aşağıdaki sonuç kutuları, normal kullanıcı deploy ile çalıştırılan komutların çıktısıdır. Alan adı yerine örnek değer example.com kullanıldı ve istekler sunucu içinden Host başlığı eklenerek gönderildi.
1️⃣ Node.js kurulumu
Node.js, NodeSource deposu apt'ye eklenerek kurulur; sürüm olarak Kasım 2026 itibarıyla LTS olan Node.js 26'yı seçtik.
🔲 NodeSource setup_26.x
export DEBIAN_FRONTEND=noninteractiveBu değeri önce tanımlarsanız paket kurulumu sırasında ayar soran pencere açılmaz. Aşağıdaki sudo komutunun -E seçeneği bu değeri root yetkisiyle çalışan komuta da aynen aktarır.
curl -fsSL https://deb.nodesource.com/setup_26.x | sudo -E bash -2026-11-07 16:08:16 - Repository configured successfully.
2026-11-07 16:08:16 - To install Node.js, run: apt install nodejs -yBetik depoyu eklemeyi bitirdiğinde Node.js'i diğer Ubuntu paketleri gibi apt ile kurabilirsiniz.
🔲 apt-get install nodejs
sudo -E apt-get install -y nodejsSetting up libatomic1:amd64 (14.2.0-4ubuntu2~24.04.1) ...
Setting up nodejs (26.13.0-1nodesource1) ...
Processing triggers for libc-bin (2.39-0ubuntu8.9) ...
Processing triggers for man-db (2.12.0-4build2) ...🔲 node -v, npm -v
node -vv26.13.0npm -v11.20.0npm, nodejs paketinin içinde geldiği için ayrıca kurmanız gerekmez.
2️⃣ Node.js test uygulaması
PM2 ile Nginx'in doğru bağlandığını görmek için, istek aldığında tek satır metin döndüren bir test uygulaması oluşturun.
🔲 app.js
mkdir -p ~/helloEv klasörünüzün altında hello klasörünü oluşturun ve içine app.js dosyasını yazın.
cat > ~/hello/app.js <<'APP'
const http = require('http');
http.createServer((req, res) => {
console.log(req.method, req.url);
res.end('hello from node\n');
}).listen(3000, '127.0.0.1');
APPUygulama yalnızca 127.0.0.1'in 3000 numaralı portunda istek kabul ettiği için sunucunun dışından doğrudan açılmaz. Dışarıdan gelen istekleri Nginx'in alıp bu porta aktarmasını ayarlayacağız.
3️⃣ PM2 ile uygulama çalıştırma ve otomatik başlatma
PM2, Node.js uygulamalarını arka planda çalıştıran ve uygulama süreci durduğunda onu yeniden çalıştıran bir süreç yönetim aracıdır. Sunucu açıldığında uygulamayı tekrar ayağa kaldıran otomatik başlatmayı da bu bölümde ayarlıyoruz.
🔲 npm install -g pm2
sudo npm install -g pm2added 45 packages in 5spm2 -v[PM2] Spawning PM2 daemon with pm2_home=/home/deploy/.pm2
[PM2] PM2 Successfully daemonized
7.1.2pm2 komutu ilk kez çalıştırıldığında PM2 arka plan hizmeti de başlar; kurulan PM2 sürümü 7.1.2'dir.
🔲 pm2 start
cd ~/helloapp.js dosyasının bulunduğu klasöre geçin, ardından uygulamayı PM2 ile çalıştırın.
pm2 start app.js --name hello[PM2] Starting /home/deploy/hello/app.js in fork_mode (1 instance)
[PM2] Done.
┌────┬──────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├────┼──────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0 │ hello │ default │ N/A │ fork │ 17257 │ 0s │ 0 │ online │ 0% │ 26.3mb │ deploy │ disabled │
└────┴──────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘--name, PM2 listesinde görünecek uygulama adıdır ve sonraki komutlar uygulamayı bu adla belirtir.
pm2 list┌────┬──────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├────┼──────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0 │ hello │ default │ N/A │ fork │ 17257 │ 2s │ 0 │ online │ 0% │ 58.5mb │ deploy │ disabled │
└────┴──────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
host metrics | cpu: 0% | ram usage: 38.8% | disk: ⇓ 0mb/s ⇑ 0mb/sstatus sütunundaki online uygulamanın çalıştığı anlamına gelir; ↺ sütunu ise PM2'nin uygulamayı kaç kez yeniden başlattığını gösterir.
🔲 curl 127.0.0.1:3000
Sunucu içinden istek gönderdiğinizde uygulamanın döndürdüğü tek satır metin olduğu gibi görünür.
curl -sS http://127.0.0.1:3000/hello from node🔲 pm2 restart
Uygulama kodunu değiştirdikten sonra değişikliği uygulamak için uygulamayı yeniden başlatın.
pm2 restart helloUse --update-env to update environment variables
[PM2] Applying action restartProcessId on app [hello](ids: [ 0 ])
[PM2] [hello](0) ✓
┌────┬──────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├────┼──────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0 │ hello │ default │ N/A │ fork │ 17306 │ 0s │ 1 │ online │ 0% │ 19.3mb │ deploy │ disabled │
└────┴──────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
host metrics | cpu: 0% | ram usage: 38.8% | disk: ⇓ 0mb/s ⇑ 0mb/spm2 list┌────┬──────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├────┼──────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0 │ hello │ default │ N/A │ fork │ 17306 │ 2s │ 1 │ online │ 0% │ 58.3mb │ deploy │ disabled │
└────┴──────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
host metrics | cpu: 0% | ram usage: 38.8% | disk: ⇓ 0mb/s ⇑ 0mb/sYeniden başlatmadan sonra pid 17257'den 17306'ya değişti ve ↺ sütunu 1'e çıktı.
🔲 kill -9
Uygulama sürecinin aniden durması durumunu kill -9 ile oluşturabilirsiniz; pm2 pid uygulamanın süreç numarasını yazdırır.
kill -9 "$(pm2 pid hello)"3 saniye sonra PM2 listesini tekrar kontrol edin.
pm2 list┌────┬──────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├────┼──────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0 │ hello │ default │ N/A │ fork │ 17797 │ 3s │ 2 │ online │ 0% │ 58.6mb │ deploy │ disabled │
└────┴──────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
host metrics | cpu: 51.2% | ram usage: 35.8% | eth0: ⇓ 1kb/s ⇑ 1kb/s | eth1: ⇓ 19kb/s ⇑ 0mb/s | disk: ⇓ 728kb/s ⇑ 3.1mb/sPM2 uygulamayı yeni pid 17797 ile tekrar çalıştırmıştı, uygulama online durumdaydı ve ↺ sütunu 2'ye çıkmıştı.
🔲 pm2 save
pm2 save[PM2] Saving current process list...
[PM2] Successfully saved in /home/deploy/.pm2/dump.pm2pm2 save şu anda çalışan uygulamaların listesini dump.pm2 dosyasına kaydeder; açılışta PM2 uygulamaları bu listeye göre tekrar çalıştırır.
🔲 pm2 startup
PM2'nin açılışta çalışması için PM2'yi systemd hizmeti olarak kaydedin. Aşağıdaki komut, şu anki hesap adını ve ev klasörünü kullanarak hizmeti oluşturur.
sudo env PATH="$PATH" pm2 startup systemd -u "$(id -un)" --hp "$HOME"ExecStart=/usr/lib/node_modules/pm2/bin/pm2 resurrect
ExecReload=/usr/lib/node_modules/pm2/bin/pm2 reload all
ExecStop=/usr/lib/node_modules/pm2/bin/pm2 kill
[Install]
WantedBy=multi-user.target
Target path
/etc/systemd/system/pm2-deploy.service
Command list
[ 'systemctl enable pm2-deploy' ]
[PM2] Writing init configuration in /etc/systemd/system/pm2-deploy.service
[PM2] Making script booting at startup...
[PM2] [-] Executing: systemctl enable pm2-deploy...
Created symlink /etc/systemd/system/multi-user.target.wants/pm2-deploy.service → /etc/systemd/system/pm2-deploy.service.
[PM2] [v] Command successfully executed.env PATH, root yetkisiyle çalışan pm2'nin şu anki hesabın node yolunu bulmasını sağlayan kısımdır; -u ve --hp ise hizmetin çalışacağı hesap ve ev klasörüdür. Hizmet dosyasındaki ExecStart satırı pm2 resurrect'tir ve açılışta kaydedilmiş uygulama listesini geri yükler.
systemctl status pm2-deploy --no-pager | head -n 5○ pm2-deploy.service - PM2 process manager
Loaded: loaded (/etc/systemd/system/pm2-deploy.service; enabled; preset: enabled)
Active: inactive (dead)
Docs: https://pm2.keymetrics.io/enabled, hizmetin açılışta çalışacağı anlamına gelir. pm2 startup hizmeti yalnızca kaydeder, şimdi çalıştırmaz; bu yüzden inactive (dead) görünür ve hizmet bir sonraki açılıştan itibaren çalışır.
🔲 Yeniden başlatma sonrası pm2 list
sudo systemctl rebootYaklaşık 2 dakika sonra deploy ile tekrar bağlanın ve uygulamanın durumunu kontrol edin.
uptime -pup 2 minutespm2 list┌────┬──────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
├────┼──────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0 │ hello │ default │ N/A │ fork │ 976 │ 108s │ 0 │ online │ 0% │ 63.0mb │ deploy │ disabled │
└────┴──────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
host metrics | cpu: 0.3% | ram usage: 35.1% | disk: ⇓ 4kb/s ⇑ 4kb/sSunucu açıldıktan 2 dakika sonra uygulama zaten 108 saniyedir online durumdaydı; PM2 uygulamayı açılışla birlikte tekrar çalıştırmıştı.
4️⃣ Nginx ters proxy ayarı
Uygulama yalnızca 127.0.0.1:3000 üzerinde istek kabul ettiği için 80 numaralı porta gelen istekleri Nginx alır ve uygulamaya aktarır. İstekleri önde karşılayıp arkadaki sunucuya ileten bu yapıya ters proxy denir.
🔲 apt-get install nginx
sudo -E apt-get install -y nginxSetting up nginx-common (1.24.0-2ubuntu7.19) ...
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
Setting up nginx (1.24.0-2ubuntu7.19) ...nginx -vnginx version: nginx/1.24.0 (Ubuntu)Ubuntu 24.04 deposundaki Nginx 1.24.0 sürümüdür ve kurulumla birlikte açılışta çalışacak şekilde kaydedilir.
🔲 /etc/nginx/sites-available/hello
/etc/nginx/sites-available/hello dosyasını oluşturun ve içine aşağıdaki içeriği yazın.
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}proxy_pass, isteklerin aktarılacağı uygulama adresidir. Host, X-Real-IP, X-Forwarded-For ve X-Forwarded-Proto başlıkları, uygulamanın asıl isteğin alan adını, ziyaretçinin IP'sini ve isteğin http mi https mi olduğunu bilebilmesi için aktarılan değerlerdir.
proxy_http_version 1.1 ile Upgrade ve Connection başlıkları, WebSocket bağlantılarını uygulamaya kadar iletmek için gerekir. Upgrade ve Connection başlıkları bir proxy'den geçtikten sonra uygulamaya iletilmediği için ayarlarda doğrudan eklenir.
sudo ln -sf /etc/nginx/sites-available/hello /etc/nginx/sites-enabled/helloNginx yalnızca sites-enabled klasöründe bağlantısı oluşturulan ayarları okur.
🔲 nginx -t
sudo nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successfulsudo systemctl reload nginxÖnce nginx -t ile ayar söz dizimini kontrol edin; geçerse reload ile Nginx'i durdurmadan yeni ayarı uygulayın.
🔲 Host başlıklı curl isteği
curl -sS -i -H 'Host: example.com' http://127.0.0.1/ | head -n 4HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)
Date: Sat, 07 Nov 2026 08:09:38 GMT
Content-Length: 16Ayar yeniden okunduktan sonra Host başlığıyla gönderilen isteğe uygulamanın yanıtı döndü. Yanıt başlıklarındaki Server satırı nginx'tir; Content-Length 16 ise uygulamanın döndürdüğü hello from node satırıyla (satır sonu dahil 16 bayt) aynı boyuttadır. Sunucunun dışından bağlanmak için güvenlik duvarında 80 numaralı portun açık olması gerekir.
5️⃣ Certbot ile HTTPS uygulama
Certbot'un Nginx eklentisiyle sertifika almayı ve Nginx ayarını değiştirmeyi tek seferde yapabilirsiniz. Alan adı sunucunun IP'sini gösterirken aşağıdaki komutu çalıştırın.
sudo certbot --nginxCertbot kurulumu ve otomatik yenileme testi aşağıdaki yazıda anlatılıyor; o yazıdaki sertifika alma komutu Apache içindir, bu yüzden yalnızca sertifika alma adımını yukarıdaki komutla değiştirerek çalıştırın.
🔢 SSS & önerilen içerikler
Hizmet günlükleri
journalctl komutu: kullanımı, servis bazında loglar ve journal boyutunu temizleme
nginx veya pm2-deploy gibi systemd hizmetlerinin günlüklerini hizmet bazında okumayı anlatan yazı.
ℹ️ Satış ortaklığı bildirimi
Bu sitenin içeriklerinde satış ortaklığı bağlantıları bulunur. Bir ziyaretçi bu bağlantılar üzerinden ürün veya hizmet satın alırsa bu site satıcıdan komisyon alır. Bu süreçte alıcının ödediği tutar (kampanya indirimlerinde tutar düşer↓) artmaz. Yayımlanan fiyat, indirim ve stok bilgileri yazının yazıldığı zamana aittir ve gerçek durumdan farklı olabilir; bu yüzden satın almadan önce son bilgiyi satıcıdan kontrol etmenizi rica ederiz. Ürünler kendi ölçütlerimize göre seçilir ve değerlendirilir; komisyon alınıp alınmaması tanıtım sırasını veya değerlendirme içeriğini etkilemez.