Skip to content
Back to blog
Rehber Node.js Deploy PM2 Nginx Systemd Linux

Node.js Uygulamasını Canlı Ortamda Yayınlama: PM2, Nginx ve Systemd ile Sürdürülebilir Mimari

Yerel makamda kusursuz çalışan bir Node.js uygulamasını üretim ortamına taşırken dikkat edilmesi gerekenler, süreç yönetimi ve ters proxy yapılandırması üzerine adım adım rehber.

Caner Serbest

Sistem ve Altyapı

4 min read

Node.js Uygulamasını Canlı Ortamda Yayınlama: PM2, Nginx e Systemd ile Sürdürülebilir Mimari

Geliştirme ortamında node app.js veya npm run dev komutlarıyla ayağa kaldırdığımız bir uygulamayı canlı (production) ortama taşımak, yazılım yaşam döngüsünün en kritik eşiklerinden biridir. Yerel makinelerde karşılaşılan hatalar genellikle anlık olarak çözülürken, canlı sistemlerde kesintisiz çalışabilirlik (high availability), güvenlik ve kaynak yönetimi ön plana çıkar.

Bu rehberde, bir Node.js uygulamasını sıfırdan kurulan bir Linux sunucuda, endüstri standardı araçlar olan PM2, Nginx ve Systemd kullanarak nasıl güvenli ve sürdürülebilir bir şekilde yayınlayacağımızı adım adım inceleyeceğiz.


1. Hazırlık ve Sunucu Ortamı

Uygulamamızı yayına almadan önce sunucumuzun güncel olduğundan ve gerekli Node.js sürümünün kurulu olduğundan emin olmalıyız. Bu rehber için Ubuntu Server kullanacağız.

Öncelikle paket listemizi güncelleyelim:

sudo apt update && sudo apt upgrade -y

Node.js kurulumu için NodeSource deposunu kullanmak en sağlıklı yöntemdir. LTS (Long Term Support) sürümünü kurmak kararlılık açısından her zaman ilk tercihimiz olmalıdır:

curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt install -y nodejs

Kurulumun ardından sürüm kontrolü yaparak her şeyin yolunda gittiğini doğrulayalım:

node -v
npm -v

2. Uygulamanın Sunucuya Taşınması ve Bağımlılıklar

Uygulama kodlarımızı sunucuya genellikle Git aracılığıyla çekeriz. /var/www dizini altında projemiz için bir klasör oluşturalım ve yetkilendirmeyi yapalım:

sudo mkdir -p /var/www/my-app
sudo chown -R $USER:$USER /var/www/my-app

Proje dizinine giderek kodlarımızı klonlayalım ve bağımlılıkları yükleyelim. Canlı ortamda sadece üretim bağımlılıklarını (dependencies) kurmak, gereksiz şişmeyi önler:

cd /var/www/my-app
git clone https://github.com/kullaniciadi/proje-adi.git .
npm ci --production

Not: npm ci, package-lock.json dosyasına sadık kalarak kararlı bir kurulum sağlar ve canlı ortamlar için önerilir.


3. PM2 ile Süreç Yönetimi (Process Management)

node app.js komutuyla uygulamayı başlattığımızda, terminal kapandığında uygulama da kapanacaktır. Ayrıca uygulama hata alıp çöktüğünde (crash) otomatik olarak yeniden başlamaz. İşte bu noktada PM2 devreye girer.

PM2’yi küresel (global) olarak kuralım:

sudo npm install -g pm2

Uygulamamızı doğrudan başlatmak yerine, proje kök dizininde bir yapılandırma dosyası (ecosystem.config.js) oluşturmak uzun vadede işimizi kolaylaştırır. Bu dosya, uygulamanın kaç örnekle (instance) çalışacağını, hata loglarının nereye yazılacağını ve ortam değişkenlerini yönetmemizi sağlar.

ecosystem.config.js dosyasını oluşturalım:

module.exports = {
  apps: [
    {
      name: 'my-app',
      script: './index.js',
      instances: 'max',
      exec_mode: 'cluster',
      env: {
        NODE_ENV: 'production',
        PORT: 3000
      },
      error_file: './logs/err.log',
      out_file: './logs/out.log',
      log_date_format: 'YYYY-MM-DD HH:mm:ss',
      max_memory_restart: '500M'
    }
  ]
};

Bu yapılandırmada dikkat çeken detaylar:

  • instances: ‘max’: Sunucunun sahip olduğu CPU çekirdek sayısı kadar uygulama örneği çalıştırarak yük dengelemesi (load balancing) yapar.
  • max_memory_restart: ‘500M’: Uygulama herhangi bir nedenle bellek sızıntısı (memory leak) yaşar ve 500 MB RAM sınırını aşarsa, PM2 uygulamayı güvenli bir şekilde yeniden başlatır.

Uygulamayı bu dosyayla başlatalım:

pm2 start ecosystem.config.js

Sunucu yeniden başladığında PM2’nin uygulamamızı otomatik olarak ayağa kaldırması için şu komutu çalıştıralım ve çıktısındaki komutu kopyalayıp terminale yapıştıralım:

pm2 startup

Son olarak mevcut durumu kaydetmek için:

pm2 save

4. Nginx ile Ters Proxy (Reverse Proxy) Yapılandırması

Node.js uygulamamız şu anda localhost:3000 adresinde çalışıyor. Ancak kullanıcıların bu uygulamaya doğrudan http://alanadiniz.com:3000 şeklinde erişmesi hem güvenlik hem de kullanıcı deneyimi açısından uygun değildir. Ayrıca 80 (HTTP) ve 443 (HTTPS) portlarını doğrudan Node.js’e açmak root yetkileri gerektirdiği için güvenlik açığı yaratabilir.

Bu sorunu çözmek için Nginx’i bir ters proxy olarak yapılandıracağız. Nginx dışarıdan gelen HTTP/HTTPS isteklerini karşılayacak ve bunları güvenli bir şekilde arka plandaki Node.js uygulamasına (localhost:3000) iletecektir.

Nginx’i kuralım:

sudo apt install -y nginx

Uygulamamız için yeni bir Nginx yapılandırma dosyası oluşturalım:

sudo nano /etc/nginx/sites-available/my-app

Dosyanın içine aşağıdaki yapılandırmayı ekleyelim (alan adınızı kendi alan adınızla değiştirmeyi unutmayın):

server {
    listen 80;
    server_name alanadiniz.com www.alanadiniz.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Bu yapılandırmayı aktif hale getirmek için sites-enabled dizinine bir sembolik bağ (symlink) oluşturalım:

sudo ln -s /etc/nginx/sites-available/my-app /etc/nginx/sites-enabled/

Nginx yapılandırmasında syntax hatası olup olmadığını test edelim:

sudo nginx -t

Herhangi bir hata yoksa Nginx servisçisini yeniden başlatalım:

sudo systemctl restart nginx

Artık alan adınıza girdiğinizde, Nginx isteği alacak ve arkadaki Node.js uygulamanıza yönlendirecektir.


5. Güvenlik ve SSL Sertifikası (Certbot)

Canlı bir sistemin olmazsa olmazı HTTPS protokolüdür. Let’s Encrypt ve Certbot kullanarak ücretsiz ve otomatik bir SSL sertifikası kuralım.

Certbot ve Nginx eklentisini kuralım:

sudo apt install -y certbot python3-certbot-nginx

Sertifika oluşturma ve Nginx yapılandırmasını otomatik güncelleme komutunu çalıştıralım:

sudo certbot --nginx -d alanadiniz.com -d www.alanadiniz.com

Certbot, e-posta adresinizi isteyecek ve kullanım şartlarını onaylamanızı bekleyecektir. İşlem tamamlandığında Nginx yapılandırmanız otomatik olarak HTTPS yönlendirmesini içerecek şekilde güncellenecektir.

Let’s Encrypt sertifikaları 90 günde bir yenilenmelidir. Certbot bu süreci otomatik yönetmek için bir systemd timer kurar. Durumu test etmek için şu komutu çalıştırabilirsiniz:

sudo certbot renew --dry-run

6. Güvenlik Duvarı (UFW) Yapılandırması

Sunucumuzun dış dünyaya sadece gerekli portları açması gerekir. UFW (Uncomplicated Firewall) kullanarak sadece SSH, HTTP ve HTTPS trafiğine izin verelim:

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

Durumu kontrol etmek için:

sudo ufw status

Node.js uygulamamızın çalıştığı 3000 numaralı portu dış dünyaya kapatmış olduk; çünkü artık dış dünya doğrudan Node.js ile değil, sadece Nginx ile konuşuyor. Node.js ise yerel ağda (localhost) güvenli bir şekilde çalışmaya devam ediyor.


Sonuç

Bu rehberde, bir Node.js uygulamasını geliştirme ortamından çıkarıp, canlı ve kurumsal standartlara uygun bir üretim ortamına nasıl taşıyacağımızı ele aldık. PM2 ile süreç sürekliliğini sağlarken, Nginx ile ters proxy mimarisini kurduk ve Certbot ile şifrelenmiş güvenli bir iletişim katmanı oluşturduk.

Bu katmanları doğru yapılandırmak, uygulamanızın ölçeklenebilirliğini artırır, olası çökme senaryolarında sistemin kendi kendini onarmasına olanak tanır ve en önemlisi son kullanıcılarınıza güvenli bir deneyim sunar.


Bu yazı Gemini ile otomatik oluşturulmuştur.