Gerçekten Çalışan VPS Kurulumu: Node.js, PM2, Nginx ve Sıfır Kesintili Dağıtım
Üretimde kullandığım birebir VPS dağıtım kurulumu — Ubuntu güçlendirme, PM2 küme modu, Nginx ters proxy, SSL ve beni hiç yarı yolda bırakmamış bir deploy betiği. Teori yok, sadece işe yarayan şeyler.
Bu blog ayda 10 dolarlık bir VPS üzerinde çalışıyor. Vercel değil, AWS değil, altı kişilik bir ekip tarafından yönetilen Kubernetes kümesi değil. Nginx, PM2 ve 30 saniyenin altında dağıtım yapan bir bash betiği olan tek bir Ubuntu kutusu.
Diğer yolları denedim. Vercel kullandım (cron işleri, kalıcı WebSocket'ler veya sadece kontrol ihtiyacınız olana kadar harika). AWS kullandım (gününüzün yarısını IAM politikalarında geçirmekten zevk alıyorsanız harika). Her seferinde VPS'e geri dönüyorum.
Ama şöyle bir sorun var: internetteki her "VPS'e dağıt" öğreticisi mutlu senaryoda duruyor. Size Node.js'i nasıl kuracağınızı ve node server.js çalıştırmayı gösteriyorlar ve buna üretim diyorlar. Sonra sunucunuz SSH kaba kuvvet saldırısına uğruyor, süreciniz gece 3'te ölüyor çünkü kimse süreç yöneticisi kurmamış ve SSL sertifikanız üç ay önce sona ermiş.
Bu, keşke elimde olsaydı dediğim rehber. Buradaki her şey savaş testinden geçmiş — tam olarak bu kurulum şu anda okuduğunuz sayfayı sunuyor.
Kodla Değil, Güvenlikle Başlayın#
Node.js'i düşünmeden önce kutuyu kilitleyin. Yeni VPS örnekleri hedeftir. Otomatik botlar, tedarik edildikten dakikalar sonra SSH portunuza vurmaya başlar.
Root Olmayan Kullanıcı Oluşturun#
adduser deploy
usermod -aG sudo deploySSH Anahtar Kimlik Doğrulaması Kurun#
Yerel makinenizde:
ssh-copy-id deploy@your-server-ipArdından parola kimlik doğrulamasını tamamen devre dışı bırakın:
sudo nano /etc/ssh/sshd_configPasswordAuthentication no
PermitRootLogin nosudo systemctl restart sshdBunu atlarsanız, birkaç gün içinde kimlik doğrulama loglarınızda binlerce başarısız giriş denemesi göreceksiniz. Bu paranoya değil — açık internette sıradan bir gün.
UFW ile Güvenlik Duvarı#
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enableBu kadar. Dört kural. Yalnızca SSH ve web trafiği geçer.
Fail2Ban#
sudo apt install fail2ban -y
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local/etc/fail2ban/jail.local dosyasını düzenleyin:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600sudo systemctl enable fail2ban
sudo systemctl start fail2banÜç başarısız SSH denemesi ve bir saatliğine yasaklanırsınız. Fail2Ban'in tek bir günde yüzlerce IP'yi engellediğini izledim. İşe yarıyor.
Otomatik Güvenlik Güncellemeleri#
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgradesSunucunuz artık güvenlik yamalarını otomatik olarak yükleyecek. Unutulması gereken bir şey daha az.
Node.js: apt Değil, NVM Kullanın#
Bunu her öğreticide görüyorum: sudo apt install nodejs. Yapmayın.
Ubuntu'nun paket depoları eski Node.js sürümleri gönderir. NodeSource PPA bile geride kalır. Ve farklı projeler için Node 20 ile Node 22 arasında geçiş yapmanız gerektiğinde takılırsınız.
NVM bunu çözer:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
source ~/.bashrc
nvm install --lts
nvm alias default lts/*Şimdi doğrulayın:
node -v # v22.x.x veya güncel LTS hangisiyse
npm -vGöze çarpmayan ipucu: NVM ile global paketler kurduğunuzda (PM2 gibi), bunlar o Node sürümüne bağlıdır. nvm use ile sürüm değiştirirseniz, globalleriniz kaybolur. Sunucuda varsayılanınızı ayarlayın ve ona bağlı kalın:
nvm alias default 22Bu beni tam olarak bir kez yakaladı. Bir kez yeterliydi.
PM2: Hak Ettiğini Kanıtlayan Süreç Yöneticisi#
PM2, "dağıtıldı" ile "üretime hazır" arasındaki farktır. Süreç yönetimi, kümeleme, log rotasyonu, çökmelerde otomatik yeniden başlatma ve başlangıç betiklerini yönetir. Ücretsiz.
Kurulum#
npm install -g pm2Ekosistem Yapılandırması#
Uygulamaları CLI bayraklarıyla başlatmayın. Bir ecosystem.config.js dosyası kullanın. Sürüm kontrollü, tekrarlanabilir ve kendi kendini belgeleyen bir dosyadır.
// ecosystem.config.js
module.exports = {
apps: [
{
name: "akousa",
script: "node_modules/.bin/next",
args: "start -p 3002",
cwd: "/var/www/akousa.net",
instances: 2,
exec_mode: "cluster",
max_memory_restart: "500M",
env: {
NODE_ENV: "production",
PORT: 3002,
},
// Zarif kapanış
kill_timeout: 5000,
listen_timeout: 10000,
wait_ready: false,
// Loglama
log_date_format: "YYYY-MM-DD HH:mm:ss Z",
error_file: "/var/log/pm2/akousa-error.log",
out_file: "/var/log/pm2/akousa-out.log",
merge_logs: true,
// Başarısızlıkta otomatik yeniden başlat
autorestart: true,
max_restarts: 10,
min_uptime: "10s",
// Üretimde izleme yapma
watch: false,
},
],
};Önemli olan seçimleri açıklayayım:
instances: 2, "max" yerine: 1-2 çekirdekli küçük bir VPS'te "max" kulağa akıllıca gelir ama build sırasında kaynak için yarışan süreçler doğurur. İki örnek, sıfır kesintili yeniden yüklemeler sağlarken alan bırakır. 4+ çekirdekli bir makinede, tabii ki "max" kullanın.
exec_mode: "cluster": Sıfır kesintili yeniden yüklemeleri mümkün kılan budur. Küme modu olmadan, pm2 reload süslü bir yeniden başlatmadır. Küme moduyla PM2, örnekleri birer birer yeniden başlatır — uygulamanız hiçbir zaman tamamen çevrimdışı olmaz.
max_memory_restart: "500M": Next.js uygulamanızın bellek sızıntısı mı var? PM2, sunucunuzu OOM-kill etmeden önce yeniden başlatır. Bu beni gece 2 uyarılarından birden fazla kez kurtardı.
kill_timeout: 5000: PM2 zorla sonlandırmadan önce uygulamanıza devam eden istekleri tamamlaması için 5 saniye verir. Varsayılan (1600ms) veritabanı bağlantıları olan uygulamalar için çok agresiftir.
watch: false: İnsanların üretimde watch: true bıraktığını gördüm. PM2 bunun üzerine her log dosyası değiştiğinde uygulamayı yeniden başlatır. Uygulamanız yeniden başlatma döngüsüne girer. Yapmayın.
Başlangıç Betiği#
PM2'nin yeniden başlatmalardan sağ çıkmasını sağlayın:
pm2 startup systemd
# Çıktıladığı komutu kopyalayın ve çalıştırın
pm2 saveBu bir systemd servisi oluşturur. Sunucu yeniden başlatıldıktan sonra uygulamanız otomatik olarak geri gelir. Test edin — sunucunuzu yeniden başlatın ve doğrulayın. Varsaymayın.
Log Rotasyonu#
Loglar sonunda diskinizi yiyecek. Rotasyon modülünü kurun:
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 50M
pm2 set pm2-logrotate:retain 7
pm2 set pm2-logrotate:compress trueDosya başına maksimum 50MB, 7 döndürülmüş dosya tut, eskileri sıkıştır. Bu olmadan, orta trafikli bir uygulamada /var/log'un 25GB'lık bir diski üç haftada doldurduğunu gördüm.
Nginx: Düşündüğünüzden Fazlasını Yapan Ters Proxy#
"Neden Node.js'i doğrudan 80 portunda açmıyoruz?"
Çünkü Nginx, Node.js'in döngü harcamaması gereken şeyleri yönetir: SSL sonlandırma, statik dosya sunma, gzip sıkıştırma, istek tamponlama, bağlantı limitleri ve yavaş istemcilerin zarif yönetimi. C'de yazılmıştır ve bunun için özel olarak tasarlanmıştır.
Kurulum#
sudo apt install nginx -yYapılandırma#
# /etc/nginx/sites-available/akousa.net
upstream node_app {
server 127.0.0.1:3002;
keepalive 64;
}
server {
listen 80;
listen [::]:80;
server_name akousa.net www.akousa.net;
# Tüm HTTP'yi HTTPS'ye yönlendir
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name akousa.net www.akousa.net;
# SSL (Certbot tarafından yönetilir — bu satırlar otomatik eklenir)
ssl_certificate /etc/letsencrypt/live/akousa.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/akousa.net/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# Güvenlik başlıkları
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# Gzip sıkıştırma
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 256;
gzip_types
text/plain
text/css
text/javascript
application/javascript
application/json
application/xml
image/svg+xml
application/wasm;
# Proxy ayarları
location / {
proxy_pass http://node_app;
proxy_http_version 1.1;
# Başlıklar
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;
# WebSocket desteği (ihtiyacınız olursa)
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Zaman aşımları — cömert ama sonsuz değil
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Tamponlama — yavaş istemcileri Nginx'e bırak
proxy_buffering on;
proxy_buffer_size 16k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
}
# Next.js statik varlıkları — Nginx'in doğrudan sunmasını sağla
location /_next/static/ {
alias /var/www/akousa.net/.next/static/;
expires 365d;
access_log off;
add_header Cache-Control "public, immutable";
}
# Genel statik dosyalar
location /static/ {
alias /var/www/akousa.net/public/static/;
expires 30d;
access_log off;
}
# Nokta dosyalarına erişimi engelle
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
}Etkinleştirin:
sudo ln -s /etc/nginx/sites-available/akousa.net /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginxYeniden yüklemeden önce her zaman nginx -t çalıştırın. Bir keresinde bozuk bir yapılandırma gönderdim ve söz dizimi kontrolünü atladığım için siteyi çökerttim. nginx -t'nin beş karakteri bana otuz dakikalık panikli hata ayıklama tasarruf ettirirdi.
Bu yapılandırmada çoğu öğreticinin atladığı şeyler:
keepalive 64 ile upstream bloğu: Nginx, her istek için yeni bir TCP bağlantısı açmak yerine Node.js arka ucunuza bağlantıları yeniden kullanır. Bu yük altında önem kazanır.
proxy_buffering on: Nginx, Node.js'ten tüm yanıtı belleğe okur, sonra istemcinin kaldırabileceği hızda istemciye gönderir. Bu olmadan, 3G bağlantısındaki yavaş bir istemci Node.js worker'ınızı meşgul eder.
_next/static/ doğrudan sunma: Bunlar hash'lenmiş, değiştirilemez varlıklardır. Nginx'in bunları 365 günlük önbellek başlığıyla diskten sunmasına izin verin. Node.js süreçleriniz buna zaman harcamamalı.
Beş Dakikada SSL#
Let's Encrypt SSL sorununu çözdü. 2026'da hâlâ sertifika için ödeme yapıyorsanız, bırakın.
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d akousa.net -d www.akousa.netCertbot e-postanızı soracak, Hizmet Şartlarını kabul edecek ve Nginx yapılandırmanızı SSL direktiflerini içerecek şekilde otomatik olarak değiştirecek. Bu kadar.
Otomatik Yenilemeyi Doğrulayın#
Certbot, günde iki kez kontrol eden ve sertifikaları son kullanma tarihinden 30 gün önce yenileyen bir systemd zamanlayıcı kurar:
sudo systemctl list-timers | grep certbotYenilemenin çalıştığını test edin:
sudo certbot renew --dry-runDeneme çalışması geçerse, SSL hakkında bir daha asla düşünmezsiniz. Başarısız olursa, genellikle 80 portu engellenmiştir (UFW kurallarınızı kontrol edin) veya Nginx çalışmıyordur.
Beni yakalayan bir şey: Certbot'u çalıştırmadan önce Nginx kurarsanız, sunucu bloğunuzun HTTPS yönlendirmesi olmadan önce 80 portunu dinlediğinden emin olun. Certbot, HTTP-01 doğrulaması için 80 portuna ulaşmak zorundadır. Certbot başarıyla çalıştıktan sonra yönlendirmeyi ekleyin.
Deploy Betiği#
Bu, her üretime gönderdiğimde çalışan betik. CI/CD platformu yok, GitHub Actions yok. Sadece SSH ve bash.
#!/bin/bash
# deploy.sh — sıfıra yakın kesintili dağıtım
set -euo pipefail
APP_DIR="/var/www/akousa.net"
APP_NAME="akousa"
LOG_FILE="/var/log/deploy.log"
HEALTH_URL="http://localhost:3002"
MAX_RETRIES=10
RETRY_INTERVAL=3
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "=== Deploy başladı ==="
cd "$APP_DIR"
# En son kodu çek
log "En son değişiklikler çekiliyor..."
git pull origin main 2>&1 | tee -a "$LOG_FILE"
# Bağımlılıkları kur
log "Bağımlılıklar kuruluyor..."
npm install --legacy-peer-deps 2>&1 | tee -a "$LOG_FILE"
# Derle
log "Uygulama derleniyor..."
rm -rf .next
npm run build 2>&1 | tee -a "$LOG_FILE"
if [ $? -ne 0 ]; then
log "HATA: Derleme başarısız. Deploy iptal ediliyor."
exit 1
fi
# PM2'yi yeniden yükle (küme modunda sıfır kesinti)
log "PM2 yeniden yükleniyor..."
pm2 reload "$APP_NAME" 2>&1 | tee -a "$LOG_FILE"
pm2 save 2>&1 | tee -a "$LOG_FILE"
# Yeniden denemeli sağlık kontrolü
log "Sağlık kontrolü çalıştırılıyor..."
for i in $(seq 1 $MAX_RETRIES); do
HTTP_CODE=$(curl -s -o /dev/null -w '%{http_code}' "$HEALTH_URL" 2>/dev/null || echo "000")
if [ "$HTTP_CODE" = "200" ]; then
log "Sağlık kontrolü geçti (HTTP $HTTP_CODE)"
log "=== Deploy başarıyla tamamlandı ==="
exit 0
fi
log "Sağlık kontrolü denemesi $i/$MAX_RETRIES (HTTP $HTTP_CODE). ${RETRY_INTERVAL}s sonra tekrar deneniyor..."
sleep $RETRY_INTERVAL
done
log "HATA: $MAX_RETRIES denemeden sonra sağlık kontrolü başarısız"
log "Önceki PM2 durumuna geri dönülüyor..."
pm2 restart "$APP_NAME" 2>&1 | tee -a "$LOG_FILE"
exit 1Çalıştırılabilir yapın:
chmod +x deploy.shYerel makinenizden dağıtım yapın:
ssh root@your-server-ip "bash /var/www/akousa.net/deploy.sh"Bu betikteki temel kararlar:
set -euo pipefail: Betik herhangi bir hatada hemen çıkar. Bu olmadan, başarısız bir npm install sessizce derleme adımına devam eder ve hata ayıklamak için 20 dakika harcayacağınız şifreli bir hata alırsınız.
Derlemeden önce rm -rf .next: Next.js'in ara sıra eski çıktı üreten bir derleme önbelleği vardır. Bir keresinde bundan etkilendim — kaynak kodu güncellenmiş olmasına rağmen bir sayfa eski içeriği gösterdi. Derleme dizinini silmek belki 15 saniye ekler ama taze çıktıyı garanti eder.
pm2 restart yerine pm2 reload: Sıfır kesinti kısmı budur. Küme modunda reload, yuvarlanan bir yeniden başlatma gerçekleştirir — güncellenmiş kodla yeni örnekler başlatır, hazır olmalarını bekler, sonra eskileri zarif bir şekilde kapatır. Hiçbir noktada sıfır örnek çalışmıyor olmaz.
Yeniden denemeli sağlık kontrolü: Next.js yeniden başlatmadan sonra ısınması için birkaç saniye alır. Betik, uygulamanın HTTP 200 ile yanıt verip vermediğini kontrol ederek 30 saniyeye kadar (10 deneme x 3 saniye) bekler. Vermiyorsa, bir şeyler yanlıştır ve bunu kullanıcıdan değil hemen bilmeniz gerekir.
Başarısızlıkta geri alma: Sağlık kontrolü tüm denemelerden sonra başarısız olursa, betik PM2'yi yeniden başlatır (son kaydedilen durumu yükler). Mükemmel bir geri alma değildir, ama sunucuyu bozuk durumda bırakmaktan iyidir.
Gece 2'de İşler Bozulduğunda#
İşte tam da bu kurulumda gerçekten hata ayıkladığım şeyler:
"Site çökmüş"#
Çalıştırılacak ilk komutlar:
pm2 status
pm2 logs akousa --lines 50
sudo systemctl status nginx
sudo tail -50 /var/log/nginx/error.logOn seferden dokuzunda pm2 logs ne olduğunu hemen söyler. Eksik bir ortam değişkeni, başarısız bir veritabanı bağlantısı veya yakalanmamış bir promise reddi.
"Bellek sürekli artıyor"#
pm2 monitBu size süreç başına CPU ve belleğin canlı bir kontrol panelini verir. Bellek düzleşmeden sürekli tırmanıyorsa, sızıntınız vardır. Ekosistem yapılandırmanızdaki max_memory_restart ayarı güvenlik ağınızdır — PM2, sunucunuzu çökertmeden önce süreci yeniden başlatır.
Daha derin araştırma için:
pm2 describe akousaBu çalışma süresini, yeniden başlatma sayısını ve bellek anlık görüntülerini gösterir. Son 24 saatte 47 yeniden başlatma görüyorsanız, ipucunuz budur.
"SSL sertifikası süresi dolmuş"#
sudo certbot certificatesTüm sertifikaları son kullanma tarihleriyle listeler. Otomatik yenileme başarısız olduysa:
sudo certbot renew --force-renewal
sudo systemctl reload nginx"Disk alanı dolmuş"#
df -h
du -sh /var/log/*
pm2 flushpm2 flush tüm PM2 log dosyalarını hemen temizler. Log rotasyonu kurmadıysanız (söylemiştim), acıyı burada hissedersiniz.
Her Sabah Çalıştırdığım Komut#
ssh deploy@akousa.net "pm2 status && df -h / && uptime"Tek satırda üç şey: süreçlerim çalışıyor mu, diskim iyi mi, sunucu aşırı yüklü mü. İki saniye sürer. Sorunları kullanıcılardan önce yakalar.
Çoğu Rehberin Size Söylemeyeceği Şeyler#
Derleme adımınız en büyük güvenlik açığınızdır. 1GB RAM'li bir VPS'te, bir Next.js uygulaması için npm run build 800MB+ bellek tüketebilir. Build sırasında PM2 uygulamanızı iki örnekte çalıştırıyorsa, OOM olursunuz. Çözümler: bir takas dosyası kullanın (en az 2GB) veya derlemeler sırasında uygulamayı durdurun ve birkaç saniyelik kesinti kabul edin. Ben takas kullanıyorum.
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstabKurulum komutunuzdaki --legacy-peer-deps bir çözüm değil, kod kokusudur. Bağımlılık ağacımdaki bazı paketler eş bağımlılık aralıklarını güncellemediği için kullanıyorum. Birkaç ayda bir kaldırmayı deniyorum. Bir gün işe yarayacak. O zamana kadar gönderiyorum.
Deploy betiğinizi sıfırdan test edin. Deponuzu yeni bir sunucuya klonlayın ve her adımı manuel çalıştırın. Deploy betiklerinde gizlenen "benim makinemde çalışıyor" sorunlarının sayısı utanç vericidir. Bunu yaptığımda benimkinde üç sorun buldum — eksik global paketler, yanlış dosya izinleri ve yalnızca önceki bir manuel kurulum yüzünden var olan bir yol.
Sunucunuzun IP'sini SSH yapılandırmanıza koyun. IP adresi yazmayı bırakın:
# ~/.ssh/config
Host akousa
HostName 69.62.66.94
User deploy
IdentityFile ~/.ssh/id_ed25519Artık tek ihtiyacınız olan ssh akousa. Küçük şeyler birikerek büyük fark yaratır.
Tam Kontrol Listesi#
Bitirdim demeden önce:
- Sudo erişimli root olmayan kullanıcı
- Yalnızca SSH anahtar kimlik doğrulaması, parola kimlik doğrulaması devre dışı
- UFW etkin, yalnızca gerekli portlar açık
- SSH'yi koruyan Fail2Ban
- Otomatik güvenlik yükseltmeleri etkin
- NVM ile kurulmuş Node.js
- PM2 uygulamanızı küme modunda çalıştırıyor
- PM2 başlangıç betiği yapılandırılmış (yeniden başlatmadan sağ çıkar)
- PM2 log rotasyonu kurulu
- Uygun başlıklarla Nginx ters proxy
- Otomatik yenileme ile Let's Encrypt üzerinden SSL
- Sağlık kontrollü deploy betiği
- Takas dosyası yapılandırılmış (derleme için alan)
- Test edildi: sunucuyu yeniden başlatın ve her şeyin geri geldiğini doğrulayın
Son madde insanların atladığı maddedir. O kişi olmayın. Sunucuyu yeniden başlatın, 60 saniye bekleyin ve uygulamanızın canlı olup olmadığını kontrol edin. Değilse, başlangıç betikleriniz yanlış yapılandırılmıştır ve bunu mümkün olan en kötü zamanda öğrenirsiniz.
Bu "Kurumsal Düzeyde" mi?#
Hayır. Ve mesele de bu.
Bu kurulum, bu blogu ayda 10 doların altında güvenilir bir şekilde sunuyor. Tek bir komutla 30 saniyede dağıtılıyor. Her parçasını anlıyorum. Bir şey bozulduğunda tam olarak nereye bakacağımı biliyorum.
Docker kullanabilir miydim? Elbette. Kubernetes kullanabilir miydim? Teknik olarak. Hazırlık ortamları ve kanarya dağıtımlarıyla tam bir CI/CD hattı kurabilir miydim? Kesinlikle.
Ama en iyi altyapının gerçekten anladığınız, gece 2'de hata ayıklayabildiğiniz ve projenin kazandığından fazlasına mal olmayan altyapı olduğunu öğrendim. Kişisel bir site, bir SaaS MVP'si veya küçük bir girişim için — bu o kurulumdur.
Önce gönderin. İhtiyaç olduğunda ölçekleyin. Ve her zaman, her zaman, deploy betiğinizi temiz bir sunucuda test edin.