مقدمه
اجرای یک برنامه Node.js روی سیستم شخصی تنها اولین قدم در مسیر توسعه است. زمانی که قصد دارید برنامه را در یک سرور واقعی در اختیار کاربران قرار دهید، باید آن را برای شرایط محیط Production آماده کنید.
در یک محیط عملیاتی، برنامه باید بتواند در صورت Crash شدن دوباره اجرا شود، ارتباط کاربران بهصورت رمزنگاریشده برقرار باشد، درخواستهای زیاد را بدون اختلال مدیریت کند و در برابر حملات رایج نیز تا حد امکان ایمن باشد.
در این آموزش یاد میگیرید چگونه یک محیط Production استاندارد برای اجرای برنامههای Node.js روی Ubuntu 24.04 LTS ایجاد کنید.
در این راهنما از ابزارهای زیر استفاده خواهیم کرد:
- Node.js برای اجرای برنامه
- PM2 برای مدیریت پردازشها و راهاندازی مجدد خودکار برنامه
- Nginx بهعنوان Reverse Proxy
- Let’s Encrypt برای دریافت گواهی SSL رایگان
- UFW برای ایمنسازی دسترسیهای شبکه
ترکیب این ابزارها، یکی از رایجترین معماریهای استقرار برنامههای Node.js در سرورهای لینوکسی است و توسط بسیاری از تیمهای توسعه و DevOps مورد استفاده قرار میگیرد.
در پایان این آموزش چه چیزهایی یاد میگیرید؟
پس از مطالعه این مقاله قادر خواهید بود:
- Node.js را با آخرین نسخه LTS روی Ubuntu نصب کنید.
- برنامه Node.js را با PM2 اجرا و مدیریت کنید.
- اجرای خودکار برنامه بعد از ریبوت سرور را فعال کنید.
- Nginx را به عنوان Reverse Proxy پیکربندی کنید.
- ارتباط HTTPS را با استفاده از Let’s Encrypt فعال کنید.
- دسترسیهای شبکه را با UFW محدود کنید.
- متغیرهای محیطی (Environment Variables) را به شکل امن مدیریت کنید.
- تنظیمات لازم برای افزایش Performance در محیط Production را انجام دهید.
- لاگها و منابع مصرفی برنامه را مانیتور کنید.
- با رایجترین مشکلات استقرار برنامههای Node.js آشنا شوید.
پیشنیازها
قبل از شروع این آموزش، موارد زیر باید آماده باشند:
- یک سرور Ubuntu 24.04 LTS
- یک کاربر غیر Root با دسترسی sudo
- فعال بودن فایروال UFW
- یک دامنه که به IP سرور اشاره کند
- نصب و پیکربندی Nginx
- فعال بودن SSL با استفاده از Let’s Encrypt
اگر هنوز سرور خود را آماده نکردهاید، میتوانید تمامی این مراحل را روی پارمین کلود (Parmin Cloud) انجام دهید و سپس ادامه این آموزش را دنبال کنید.
در ادامه فرض میکنیم دامنه شما به شکل زیر است:
example.com
معماری نهایی این آموزش
در پایان، ساختار ارتباط سرویسها به شکل زیر خواهد بود:
Internet
│
HTTPS (443)
│
Nginx
│
Reverse Proxy
│
localhost:3000
│
PM2
│
Node.js App
در این معماری:
- کاربران تنها به Nginx دسترسی دارند.
- برنامه Node.js مستقیماً از اینترنت قابل دسترسی نیست.
- تمامی ارتباطات با HTTPS رمزنگاری میشوند.
- PM2 مسئول نگهداری و Restart خودکار برنامه خواهد بود.
- در صورت ریبوت شدن سرور، برنامه بهصورت خودکار اجرا خواهد شد.
مرحله اول: نصب آخرین نسخه Node.js روی Ubuntu 24.04
در این بخش، آخرین نسخه LTS از Node.js را نصب میکنیم. برای این کار از مخزن رسمی NodeSource استفاده میشود که همیشه جدیدترین نسخههای پایدار Node.js را ارائه میکند.
نکته
نسخه موجود در مخازن پیشفرض Ubuntu معمولاً قدیمیتر از نسخههای رسمی Node.js است؛ بنابراین برای استفاده در محیط Production توصیه میشود از مخزن NodeSource استفاده کنید.
مرحله ۱: بروزرسانی پکیجهای سیستم
ابتدا لیست مخازن سیستم را بروزرسانی کنید:
sudo apt update && sudo apt upgrade -y
مرحله ۲: دانلود اسکریپت نصب NodeSource
وارد دایرکتوری Home شوید:
cd ~
سپس اسکریپت نصب آخرین نسخه LTS را دانلود کنید:
curl -fsSL https://deb.nodesource.com/setup_24.x -o nodesource_setup.sh
در صورت تمایل میتوانید قبل از اجرا، محتوای اسکریپت را بررسی کنید:
nano nodesource_setup.sh
مرحله ۳: اجرای اسکریپت
پس از بررسی، اسکریپت را اجرا کنید:
sudo bash nodesource_setup.sh
با اجرای این دستور:
- مخزن NodeSource به سیستم اضافه میشود.
- کلید GPG مربوطه ثبت میشود.
- لیست مخازن بهصورت خودکار بروزرسانی خواهد شد.
مرحله ۴: نصب Node.js
اکنون Node.js را نصب کنید:
sudo apt install nodejs -y
مرحله ۵: بررسی نسخه نصبشده
پس از پایان نصب، نسخه Node.js را بررسی کنید:
node -v
خروجی باید مشابه نمونه زیر باشد:
v24.x.x
سپس نسخه npm را نیز بررسی کنید:
npm -v
خروجی مشابه زیر خواهد بود:
11.x.x
نکته
با نصب بسته
nodejs، ابزار npm نیز بهصورت خودکار نصب میشود و نیازی به نصب جداگانه آن نیست.
نصب ابزارهای موردنیاز برای کامپایل پکیجها
برخی از پکیجهای Node.js هنگام نصب نیاز به کامپایل شدن دارند. برای جلوگیری از بروز خطا، بسته build-essential را نیز نصب کنید:
sudo apt install build-essential -y
این بسته شامل ابزارهای ضروری مانند:
- gcc
- g++
- make
و سایر ابزارهای موردنیاز برای Build کردن ماژولهای Native است.
بررسی عملکرد Node.js
برای اطمینان از نصب صحیح، دستور زیر را اجرا کنید:
node
در صورتی که نصب با موفقیت انجام شده باشد، وارد محیط تعاملی Node.js خواهید شد:
Welcome to Node.js v24.x.x.
Type ".help" for more information.
>
برای خروج نیز دستور زیر را وارد کنید:
.exit
چرا از نسخه LTS استفاده میکنیم؟
Node.js دو شاخه انتشار دارد:
- Current
- LTS (Long Term Support)
برای محیطهای عملیاتی (Production)، همیشه استفاده از نسخه LTS توصیه میشود، زیرا:
- پایداری بیشتری دارد.
- مدت طولانیتری پشتیبانی میشود.
- اکثر کتابخانهها ابتدا با نسخه LTS تست میشوند.
- احتمال بروز ناسازگاری بسیار کمتر است.
به همین دلیل در این آموزش از آخرین نسخه LTS استفاده شده است.
مرحله دوم: ساخت یک برنامه نمونه Node.js
اکنون که Node.js با موفقیت روی سرور نصب شده است، بهتر است قبل از ادامه مراحل، یک برنامه ساده ایجاد کنیم تا از صحت عملکرد محیط اجرا اطمینان حاصل کنیم.
در این مثال، یک وبسرور بسیار ساده ایجاد میکنیم که در پاسخ به هر درخواست HTTP، عبارت Hello World! را نمایش میدهد.
نکته
در محیط Production بهتر است برنامههای Node.js مستقیماً روی اینترنت در دسترس نباشند. به همین دلیل در این آموزش، برنامه تنها روی آدرس localhost اجرا میشود و Nginx مسئول دریافت درخواستهای کاربران خواهد بود.
ایجاد فایل برنامه
ابتدا وارد دایرکتوری Home شوید:
cd ~
سپس فایل جدیدی ایجاد کنید:
nano hello.js
کد زیر را داخل فایل قرار دهید:
const http = require('http');
const hostname = 'localhost';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World!\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
فایل را ذخیره کرده و از ویرایشگر خارج شوید.
این برنامه چه کاری انجام میدهد؟
کد بالا یک وبسرور ساده ایجاد میکند که:
- روی پورت 3000 اجرا میشود.
- فقط روی localhost گوش میدهد.
- برای تمام درخواستها پاسخ Hello World! ارسال میکند.
از آنجایی که آدرس localhost استفاده شده است، این برنامه از خارج سرور قابل دسترس نیست و فقط خود سیستمعامل میتواند به آن متصل شود.
این دقیقاً همان چیزی است که در محیطهای عملیاتی به آن نیاز داریم.
اجرای برنامه
اکنون برنامه را اجرا کنید:
node hello.js
در صورت موفقیت، خروجی مشابه زیر مشاهده خواهید کرد:
Server running at http://localhost:3000/
تست عملکرد برنامه
یک ترمینال جدید باز کنید و دستور زیر را اجرا کنید:
curl http://localhost:3000
در صورتی که همه چیز درست باشد، خروجی زیر نمایش داده میشود:
Hello World!
اگر خروجی دیگری مشاهده کردید، موارد زیر را بررسی کنید:
- برنامه هنوز در حال اجرا باشد.
- شماره پورت صحیح باشد.
- مقدار
hostnameبرابرlocalhostباشد.
توقف برنامه
پس از اطمینان از عملکرد صحیح، به ترمینالی که برنامه در آن اجرا شده برگردید و کلیدهای زیر را فشار دهید:
CTRL + C
با این کار برنامه متوقف میشود.
چرا در محیط Production از localhost استفاده میکنیم؟
یکی از اشتباهات رایج این است که برنامه Node.js روی آدرس 0.0.0.0 اجرا شود تا مستقیماً از اینترنت قابل دسترس باشد.
اگرچه این روش کار میکند، اما از نظر امنیتی توصیه نمیشود.
در یک معماری استاندارد، وضعیت به این شکل است:
کاربر
│
HTTPS
│
Nginx
│
Reverse Proxy
│
localhost:3000
│
Node.js
این ساختار چند مزیت مهم دارد:
جلوگیری از دسترسی مستقیم
کاربران هرگز مستقیماً به Node.js متصل نمیشوند و تمام درخواستها ابتدا از Nginx عبور میکنند.
مدیریت SSL توسط Nginx
رمزنگاری HTTPS و مدیریت گواهی SSL توسط Nginx انجام میشود و برنامه Node.js نیازی به مدیریت گواهیها ندارد.
افزایش امنیت
با فعال بودن UFW تنها پورتهای 80 و 443 از بیرون قابل دسترس خواهند بود و پورت 3000 کاملاً بسته باقی میماند.
افزایش کارایی
Nginx در سرویسدهی فایلهای Static، مدیریت Cache، فشردهسازی و Load Balancing عملکرد بسیار بهتری نسبت به Node.js دارد.
به همین دلیل تقریباً تمام سرویسهای Node.js در محیط Production پشت یک Reverse Proxy مانند Nginx اجرا میشوند.
مرحله سوم: نصب و پیکربندی PM2
اگر برنامه Node.js را با دستور node app.js اجرا کنید، با بسته شدن ترمینال یا ریبوت شدن سرور، برنامه نیز متوقف خواهد شد.
در محیط Production این موضوع قابل قبول نیست؛ زیرا برنامه باید همیشه در حال اجرا باشد و در صورت بروز خطا یا Crash نیز بهصورت خودکار مجدداً اجرا شود.
برای حل این مشکل از PM2 استفاده میکنیم.
PM2 یکی از محبوبترین Process Managerهای Node.js است که امکانات زیر را در اختیار شما قرار میدهد:
- اجرای دائمی برنامه
- Restart خودکار پس از Crash
- اجرای خودکار بعد از ریبوت سرور
- مدیریت چندین برنامه بهصورت همزمان
- مشاهده مصرف CPU و RAM
- مدیریت لاگها
- اجرای برنامه در حالت Cluster
نصب PM2
PM2 از طریق npm نصب میشود.
دستور زیر را اجرا کنید:
sudo npm install -g pm2
پارامتر -g باعث میشود PM2 بهصورت سراسری (Global) روی سیستم نصب شود و برای همه کاربران قابل استفاده باشد.
اجرای برنامه توسط PM2
اکنون برنامهای که در مرحله قبل ساختیم را اجرا کنید:
pm2 start hello.js
در صورت موفقیت، خروجی مشابه زیر مشاهده خواهید کرد:
┌────┬────────┬─────────┬────────┬──────────┬────────┐
│ id │ name │ mode │ status │ cpu │ memory │
├────┼────────┼─────────┼────────┼──────────┼────────┤
│ 0 │ hello │ fork │ online │ 0% │ 35 MB │
└────┴────────┴─────────┴────────┴──────────┴────────┘
این جدول اطلاعات مفیدی مانند موارد زیر را نمایش میدهد:
- شناسه برنامه
- نام برنامه
- وضعیت اجرا
- میزان مصرف CPU
- میزان مصرف حافظه
بررسی وضعیت برنامه
برای مشاهده لیست برنامههایی که توسط PM2 مدیریت میشوند، دستور زیر را اجرا کنید:
pm2 list
یا:
pm2 status
خروجی نمونه:
┌────┬────────┬────────┬────────┐
│ id │ name │ status │ uptime │
├────┼────────┼────────┼────────┤
│ 0 │ hello │ online │ 5m │
└────┴────────┴────────┴────────┘
اگر وضعیت online باشد یعنی برنامه بدون مشکل در حال اجراست.
تست عملکرد برنامه
اکنون دوباره برنامه را بررسی کنید:
curl http://localhost:3000
باید خروجی زیر را مشاهده کنید:
Hello World!
این بار تفاوت مهم این است که برنامه دیگر مستقیماً توسط Node.js اجرا نشده، بلکه PM2 آن را مدیریت میکند.
مشاهده اطلاعات کامل برنامه
برای مشاهده جزئیات بیشتر از دستور زیر استفاده کنید:
pm2 info hello
یا:
pm2 describe hello
اطلاعاتی مانند موارد زیر نمایش داده میشود:
- مسیر فایل برنامه
- زمان اجرا
- تعداد Restartها
- PID
- مصرف حافظه
- مصرف CPU
- نسخه Node.js
مشاهده لاگهای برنامه
یکی از امکانات بسیار کاربردی PM2، مدیریت لاگها است.
برای مشاهده خروجی برنامه:
pm2 logs
یا فقط لاگهای برنامه hello:
pm2 logs hello
برای خروج از حالت مشاهده لاگ:
CTRL + C
مانیتورینگ لحظهای
برای مشاهده وضعیت لحظهای پردازشها:
pm2 monit
در این صفحه میتوانید موارد زیر را بهصورت زنده مشاهده کنید:
- مصرف CPU
- مصرف RAM
- تعداد درخواستها
- وضعیت پردازشها
- لاگهای لحظهای
این ابزار برای پیدا کردن Memory Leak یا افزایش مصرف منابع بسیار کاربردی است.
راهاندازی خودکار PM2 بعد از ریبوت
PM2 میتواند پس از هر بار روشن شدن سرور، برنامههای شما را بهصورت خودکار اجرا کند.
ابتدا دستور زیر را اجرا کنید:
pm2 startup systemd
خروجی چیزی شبیه زیر خواهد بود:
sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u username --hp /home/username
نکته
این دستور برای هر کاربر و هر نسخه Node.js متفاوت است. کافی است دقیقاً همان دستوری که PM2 نمایش میدهد را کپی و اجرا کنید.
ذخیره برنامههای در حال اجرا
پس از اجرای دستور بالا، وضعیت فعلی PM2 را ذخیره کنید تا بعد از ریبوت نیز همین برنامهها اجرا شوند:
pm2 save
خروجی:
Successfully saved in ~/.pm2/dump.pm2
از این پس، پس از هر بار راهاندازی مجدد سرور، PM2 بهصورت خودکار اجرا شده و برنامههای ذخیرهشده را مجدداً بالا میآورد.
بررسی سرویس PM2
برای اطمینان از فعال بودن سرویس:
systemctl status pm2-$USER
نمونه خروجی:
Active: active (running)
اگر وضعیت active (running) نمایش داده شود، همه چیز بهدرستی پیکربندی شده است.
دستورات پرکاربرد PM2
در ادامه، مهمترین دستورات PM2 را مشاهده میکنید:
| دستور | توضیح |
|---|---|
pm2 list |
نمایش برنامههای در حال اجرا |
pm2 status |
مشاهده وضعیت برنامهها |
pm2 logs |
مشاهده لاگها |
pm2 monit |
مانیتورینگ لحظهای |
pm2 restart hello |
راهاندازی مجدد برنامه |
pm2 stop hello |
توقف برنامه |
pm2 delete hello |
حذف برنامه از PM2 |
pm2 save |
ذخیره وضعیت فعلی |
pm2 resurrect |
بازیابی برنامههای ذخیرهشده |
اکنون برنامه Node.js بهصورت دائمی توسط PM2 مدیریت میشود و حتی در صورت Crash یا ریبوت سرور نیز مجدداً اجرا خواهد شد.
استفاده از فایل Ecosystem در PM2
زمانی که تنها یک برنامه Node.js روی سرور اجرا میکنید، اجرای مستقیم فایل با دستور pm2 start app.js کاملاً مناسب است.
اما در پروژههای واقعی معمولاً با شرایط زیر روبهرو میشویم:
- چندین برنامه روی یک سرور اجرا میشوند.
- هر محیط (Development، Staging و Production) تنظیمات متفاوتی دارد.
- متغیرهای محیطی (Environment Variables) باید بهصورت متمرکز مدیریت شوند.
- لازم است تنظیمات Restart، تعداد پردازشها و سایر پارامترها در یک فایل نگهداری شوند.
برای چنین شرایطی، PM2 قابلیتی به نام Ecosystem File ارائه میدهد.
ایجاد فایل Ecosystem
برای ساخت فایل تنظیمات، دستور زیر را اجرا کنید:
pm2 ecosystem
با اجرای این دستور، فایل زیر ایجاد میشود:
ecosystem.config.js
ساختار فایل
فایل را باز کنید:
nano ecosystem.config.js
سپس محتوای آن را به شکل زیر تغییر دهید:
module.exports = {
apps: [
{
name: "hello",
script: "hello.js",
env: {
NODE_ENV: "development",
PORT: 3001
},
env_production: {
NODE_ENV: "production",
PORT: 3000
}
}
]
};
آشنایی با بخشهای فایل
در این فایل، هر برنامه بهصورت یک شیء (Object) تعریف میشود.
پارامترهای مهم عبارتاند از:
| گزینه | توضیح |
|---|---|
name |
نام برنامه در PM2 |
script |
فایل اجرایی برنامه |
env |
تنظیمات محیط Development |
env_production |
تنظیمات محیط Production |
اجرای برنامه در حالت Production
پس از ذخیره فایل، برنامه را با دستور زیر اجرا کنید:
pm2 start ecosystem.config.js --env production
PM2 متغیرهای تعریفشده در بخش env_production را بارگذاری خواهد کرد.
بررسی وضعیت
برای مشاهده وضعیت برنامه:
pm2 list
یا
pm2 status
مزایای استفاده از Ecosystem File
استفاده از این فایل مزایای زیادی دارد:
- مدیریت چندین برنامه در یک فایل
- تعریف متغیرهای محیطی
- اجرای برنامه در محیطهای مختلف
- نگهداری تنظیمات Restart
- تعیین تعداد Instanceها
- راهاندازی Cluster
- سادهتر شدن فرآیند Deploy
به همین دلیل تقریباً تمام پروژههای Production از فایل Ecosystem استفاده میکنند.
اجرای چندین برنامه
فرض کنید دو برنامه مختلف روی سرور دارید.
کافی است هر دو را داخل فایل تعریف کنید:
module.exports = {
apps: [
{
name: "frontend",
script: "./frontend/app.js"
},
{
name: "api",
script: "./backend/server.js"
}
]
};
سپس هر دو را همزمان اجرا کنید:
pm2 start ecosystem.config.js
PM2 هر دو برنامه را مدیریت خواهد کرد.
اجرای چند پردازش (Cluster Mode)
یکی از مهمترین قابلیتهای PM2، اجرای برنامه روی تمام هستههای CPU است.
برای فعال کردن Cluster Mode کافی است تنظیمات زیر را اضافه کنید:
module.exports = {
apps: [
{
name: "hello",
script: "hello.js",
instances: "max",
exec_mode: "cluster"
}
]
};
در این حالت:
- PM2 به اندازه تعداد هستههای CPU پردازش ایجاد میکند.
- درخواستها بین پردازشها توزیع میشوند.
- در صورت Crash شدن یکی از پردازشها، فقط همان پردازش مجدداً اجرا خواهد شد.
برای سرورهای Production این روش نسبت به حالت Fork عملکرد بسیار بهتری دارد.
ذخیره تنظیمات
پس از اجرای برنامه، وضعیت را ذخیره کنید:
pm2 save
تا پس از ریبوت سرور نیز همین تنظیمات بازیابی شوند.
پیشنهاد برای محیط Production
برای پروژههای واقعی، فایل Ecosystem میتواند کاملتر باشد:
module.exports = {
apps: [
{
name: "myapp",
script: "app.js",
instances: "max",
exec_mode: "cluster",
autorestart: true,
watch: false,
max_memory_restart: "500M",
env_production: {
NODE_ENV: "production",
PORT: 3000
}
}
]
};
در این پیکربندی:
- از تمام هستههای CPU استفاده میشود.
- در صورت مصرف بیش از ۵۰۰ مگابایت حافظه، برنامه بهطور خودکار Restart میشود.
- قابلیت Watch غیرفعال است تا مصرف منابع کاهش یابد.
- Restart خودکار نیز فعال است.
اکنون برنامه شما بهصورت حرفهای توسط PM2 مدیریت میشود و آماده است تا در پشت Nginx Reverse Proxy قرار بگیرد.
مرحله چهارم: پیکربندی Nginx بهعنوان Reverse Proxy
اکنون که برنامه Node.js توسط PM2 اجرا میشود، باید آن را در دسترس کاربران قرار دهیم.
بهترین روش در محیط Production این است که Node.js مستقیماً درخواستهای کاربران را دریافت نکند و تمام ترافیک ابتدا وارد Nginx شود.
در این معماری، Nginx وظایف زیر را برعهده دارد:
- دریافت درخواستهای HTTP و HTTPS
- مدیریت گواهی SSL
- ارسال درخواستها به Node.js
- سرویسدهی فایلهای Static
- اعمال Cache و Compression
- افزایش امنیت برنامه
در نتیجه، برنامه Node.js تنها روی localhost اجرا میشود و از اینترنت قابل دسترس نخواهد بود.
ساختار کلی ارتباط
پس از پایان این مرحله، مسیر درخواستها به شکل زیر خواهد بود:
کاربر
│
HTTPS
│
Nginx
│
Reverse Proxy
│
localhost:3000
│
Node.js
ویرایش فایل تنظیمات Nginx
اگر پیشنیازهای این آموزش را انجام داده باشید، فایل تنظیمات سایت شما در مسیر زیر قرار دارد:
sudo nano /etc/nginx/sites-available/example.com
بهجای
example.comنام دامنه خود را قرار دهید.
پیکربندی Reverse Proxy
داخل بلاک server، بخش location / را به شکل زیر تغییر دهید:
server {
listen 80;
server_name example.com www.example.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;
}
}
اگر برنامه شما روی پورتی غیر از 3000 اجرا میشود، مقدار proxy_pass را متناسب با آن تغییر دهید.
هر بخش چه کاری انجام میدهد؟
proxy_pass
proxy_pass http://localhost:3000;
تمام درخواستهای کاربران را به برنامه Node.js ارسال میکند.
proxy_http_version
proxy_http_version 1.1;
استفاده از HTTP/1.1 باعث میشود قابلیتهایی مانند WebSocket بدون مشکل کار کنند.
Upgrade Header
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
برای برنامههایی که از WebSocket استفاده میکنند (مانند Socket.IO) ضروری است.
Host Header
proxy_set_header Host $host;
نام دامنه اصلی را به برنامه Node.js ارسال میکند.
این مورد برای بسیاری از فریمورکها مانند Express ضروری است.
Cache Bypass
proxy_cache_bypass $http_upgrade;
در صورت استفاده از Upgrade یا WebSocket، از Cache عبور میکند.
تست تنظیمات
قبل از Reload کردن Nginx، تنظیمات را بررسی کنید:
sudo nginx -t
در صورت صحیح بودن تنظیمات، خروجی مشابه زیر خواهید دید:
nginx: the configuration file syntax is ok
nginx: configuration file test is successful
اعمال تنظیمات
اکنون تنظیمات را بدون قطع سرویس Reload کنید:
sudo systemctl reload nginx
تست عملکرد
اکنون مرورگر را باز کرده و دامنه خود را وارد کنید:
http://example.com
در صورتی که همه چیز به درستی تنظیم شده باشد، خروجی برنامه Node.js نمایش داده خواهد شد.
اجرای چند برنامه روی یک سرور
اگر چند برنامه Node.js روی سرور دارید، میتوانید برای هرکدام یک مسیر جداگانه تعریف کنید.
فرض کنید برنامه دوم روی پورت 3001 اجرا شده است.
location /app2 {
proxy_pass http://localhost:3001;
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;
}
در این حالت:
https://example.com/
برنامه اول را نمایش میدهد.
و
https://example.com/app2
برنامه دوم را اجرا خواهد کرد.
استفاده از Subdomain
در پروژههای واقعی معمولاً برای هر سرویس یک Subdomain تعریف میشود.
برای مثال:
| آدرس | برنامه |
|---|---|
| app.example.com | برنامه اصلی |
| api.example.com | API |
| admin.example.com | پنل مدیریت |
در این حالت برای هر Subdomain یک فایل تنظیمات جداگانه در Nginx ایجاد میشود که نگهداری آن بسیار سادهتر خواهد بود.
چرا Reverse Proxy اهمیت دارد؟
استفاده از Reverse Proxy مزایای بسیار مهمی دارد:
- برنامه Node.js مستقیماً در اینترنت در دسترس نیست.
- مدیریت HTTPS توسط Nginx انجام میشود.
- امکان فعالسازی Cache و Compression وجود دارد.
- فایلهای Static با سرعت بسیار بیشتری سرویسدهی میشوند.
- امکان Load Balancing بین چندین Instance فراهم میشود.
- امنیت برنامه به شکل محسوسی افزایش پیدا میکند.
به همین دلیل تقریباً تمام پروژههای Production از معماری Nginx + Node.js + PM2 استفاده میکنند.
مرحله پنجم: فعالسازی HTTPS با Let’s Encrypt
اکنون که برنامه Node.js از طریق Nginx در دسترس قرار گرفته است، زمان آن رسیده تا ارتباط کاربران با سرور را رمزنگاری کنیم.
استفاده از HTTPS دیگر یک قابلیت اختیاری نیست؛ بلکه یکی از مهمترین الزامات هر سرویس آنلاین محسوب میشود.
با فعالسازی SSL:
- تمام اطلاعات بین کاربر و سرور رمزنگاری میشود.
- از سرقت اطلاعات جلوگیری میشود.
- مرورگرها سایت را بهعنوان Secure نمایش میدهند.
- اعتماد کاربران افزایش پیدا میکند.
- موتورهای جستجو مانند Google امتیاز بهتری برای سایت در نظر میگیرند.
در این آموزش از Let’s Encrypt برای دریافت رایگان گواهی SSL استفاده میکنیم.
نصب Certbot
ابتدا فهرست بستههای سیستم را بهروزرسانی کنید:
sudo apt update
سپس Certbot و افزونه مخصوص Nginx را نصب کنید:
sudo apt install certbot python3-certbot-nginx -y
دریافت گواهی SSL
اکنون دستور زیر را اجرا کنید:
sudo certbot --nginx -d example.com -d www.example.com
بهجای example.com دامنه واقعی خود را قرار دهید.
برای مثال:
sudo certbot --nginx -d parmincloud.ir -d www.parmincloud.ir
در زمان نصب چه اتفاقی میافتد؟
Certbot بهصورت خودکار مراحل زیر را انجام میدهد:
- بررسی مالکیت دامنه
- دریافت گواهی SSL از Let’s Encrypt
- ویرایش فایل تنظیمات Nginx
- فعال کردن HTTPS
- ایجاد ریدایرکت HTTP به HTTPS
- Reload کردن Nginx
بنابراین نیازی نیست فایل تنظیمات را بهصورت دستی تغییر دهید.
اطلاعاتی که Certbot از شما میپرسد
در طول نصب چند سؤال نمایش داده میشود.
ایمیل
Enter email address
ایمیل خود را وارد کنید.
این ایمیل برای اطلاعرسانی تمدید گواهی استفاده میشود.
قوانین استفاده
Do you agree?
گزینه:
Y
را وارد کنید.
ریدایرکت خودکار
در ادامه سؤال زیر نمایش داده میشود:
Redirect HTTP to HTTPS?
گزینه شماره 2 را انتخاب کنید.
2
با این کار تمام درخواستهای HTTP به HTTPS منتقل میشوند.
بررسی گواهی نصبشده
برای مشاهده گواهیهای نصبشده:
sudo certbot certificates
خروجی نمونه:
Certificate Name: example.com
Domains: example.com www.example.com
Expiry Date: 2026-10-20
تست سایت
اکنون آدرس زیر را در مرورگر باز کنید:
https://example.com
باید:
- علامت قفل (🔒)
- اتصال امن (Secure)
- گواهی معتبر
را مشاهده کنید.
تمدید خودکار گواهی
گواهیهای Let’s Encrypt فقط ۹۰ روز اعتبار دارند.
اما جای نگرانی نیست.
Certbot هنگام نصب، سرویس تمدید خودکار را نیز فعال میکند.
برای اطمینان از عملکرد صحیح آن میتوانید دستور زیر را اجرا کنید:
sudo certbot renew --dry-run
اگر همه چیز درست باشد، خروجی مشابه زیر مشاهده خواهید کرد:
Congratulations, all simulated renewals succeeded.
این یعنی گواهیها در آینده نیز بدون دخالت شما تمدید خواهند شد.
محل ذخیره گواهیها
فایلهای گواهی در مسیر زیر قرار میگیرند:
/etc/letsencrypt/live/example.com/
مهمترین فایلها عبارتاند از:
fullchain.pem
و
privkey.pem
که Nginx از آنها استفاده میکند.
نمونه تنظیمات HTTPS در Nginx
اگر به هر دلیلی قصد داشتید تنظیمات را بهصورت دستی انجام دهید، ساختار کلی به شکل زیر خواهد بود:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
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;
}
}
در عمل، زمانی که از دستور certbot --nginx استفاده میکنید، این تنظیمات بهصورت خودکار ایجاد میشوند.
چرا HTTPS اهمیت دارد؟
فعالسازی HTTPS مزایای متعددی دارد:
- رمزنگاری اطلاعات کاربران
- جلوگیری از حملات Man-in-the-Middle
- افزایش اعتماد کاربران
- بهبود رتبه سایت در موتورهای جستجو
- امکان استفاده از HTTP/2 و HTTP/3
- سازگاری با استانداردهای امنیتی جدید
- جلوگیری از نمایش پیام Not Secure در مرورگر
به همین دلیل تقریباً تمام سرویسهای مدرن اینترنتی از HTTPS استفاده میکنند.
اکنون برنامه Node.js شما از طریق Nginx و با استفاده از HTTPS بهصورت کاملاً امن در اختیار کاربران قرار گرفته است.
مرحله ششم: پیکربندی فایروال UFW برای محیط Production
اکنون که برنامه Node.js از طریق Nginx و HTTPS در دسترس کاربران قرار گرفته است، زمان آن رسیده تا دسترسیهای غیرضروری به سرور را مسدود کنیم.
Ubuntu بهصورت پیشفرض فایروالی به نام UFW (Uncomplicated Firewall) ارائه میدهد که مدیریت قوانین فایروال را بسیار ساده میکند.
فعال بودن UFW باعث میشود فقط سرویسهایی که شما مجاز کردهاید از بیرون قابل دسترس باشند و سایر پورتها مسدود شوند.
بررسی وضعیت فایروال
ابتدا وضعیت فعلی UFW را بررسی کنید:
sudo ufw status
اگر خروجی زیر را مشاهده کردید:
Status: inactive
یعنی فایروال هنوز فعال نشده است.
اجازه دسترسی به SSH
قبل از فعال کردن فایروال، باید دسترسی SSH را مجاز کنید؛ در غیر این صورت ممکن است ارتباط شما با سرور قطع شود.
sudo ufw allow OpenSSH
اجازه دسترسی به Nginx
برای اینکه کاربران بتوانند از طریق HTTP و HTTPS به سایت متصل شوند، پروفایل کامل Nginx را فعال کنید:
sudo ufw allow 'Nginx Full'
این دستور پورتهای زیر را باز میکند:
- 80 (HTTP)
- 443 (HTTPS)
فعال کردن فایروال
اکنون UFW را فعال کنید:
sudo ufw enable
در صورت مشاهده پیام زیر:
Command may disrupt existing ssh connections.
Proceed with operation (y|n)?
حرف
y
را وارد کرده و Enter بزنید.
بررسی قوانین
اکنون دوباره وضعیت فایروال را بررسی کنید:
sudo ufw status
خروجی باید مشابه زیر باشد:
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Nginx Full ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Nginx Full (v6) ALLOW Anywhere (v6)
مشاهده پروفایلهای موجود
برای مشاهده پروفایلهای آماده UFW:
sudo ufw app list
نمونه خروجی:
Available applications:
Nginx Full
Nginx HTTP
Nginx HTTPS
OpenSSH
تفاوت پروفایلهای Nginx
| پروفایل | پورت |
|---|---|
| Nginx HTTP | 80 |
| Nginx HTTPS | 443 |
| Nginx Full | 80 و 443 |
در اکثر محیطهای Production از Nginx Full استفاده میشود.
حذف یک قانون
در صورت نیاز میتوانید یک قانون را حذف کنید.
برای مثال:
sudo ufw delete allow 'Nginx HTTP'
یا
sudo ufw delete allow 8080
نمایش قوانین شمارهگذاریشده
گاهی حذف قوانین با شماره راحتتر است:
sudo ufw status numbered
نمونه خروجی:
[1] OpenSSH
[2] Nginx Full
حذف قانون شماره 2:
sudo ufw delete 2
چرا نباید پورت Node.js باز باشد؟
اگر برنامه Node.js روی پورت 3000 اجرا میشود، نباید این پورت را در UFW باز کنید.
برای مثال، این دستور اشتباه است:
sudo ufw allow 3000
زیرا در این صورت کاربران میتوانند مستقیماً به برنامه Node.js متصل شوند و تمام مزایای Reverse Proxy از بین میرود.
در معماری صحیح:
Internet
│
▼
Port 443
│
Nginx
│
localhost:3000
│
Node.js
در این حالت، فقط Nginx به برنامه Node.js دسترسی دارد.
چرا فایروال اهمیت دارد؟
حتی اگر برنامه شما کاملاً ایمن باشد، باز بودن پورتهای غیرضروری میتواند ریسک امنیتی ایجاد کند.
فعال بودن فایروال مزایای زیر را دارد:
- جلوگیری از دسترسی مستقیم به سرویسهای داخلی
- کاهش سطح حمله (Attack Surface)
- جلوگیری از اسکن پورتها
- افزایش امنیت در برابر حملات خودکار
- رعایت استانداردهای امنیتی سرورها
بهترین تنظیمات UFW برای یک سرور Node.js
برای اغلب سرورهای Production، تنها قوانین زیر کافی هستند:
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable
به این ترتیب:
- SSH برای مدیریت سرور باز میماند.
- کاربران فقط از طریق HTTP و HTTPS به سایت دسترسی دارند.
- تمام پورتهای دیگر، از جمله پورت Node.js، از اینترنت قابل دسترس نخواهند بود.
با این مرحله، امنیت شبکه سرور نیز تکمیل شد و اکنون برنامه Node.js شما با استفاده از PM2، Nginx، HTTPS و UFW بهصورت استاندارد و آماده استفاده در محیط Production اجرا میشود.
مرحله هفتم: مدیریت امن متغیرهای محیطی (Environment Variables)
تقریباً تمام برنامههای Node.js برای اجرا به اطلاعاتی مانند موارد زیر نیاز دارند:
- اطلاعات اتصال به پایگاه داده
- کلیدهای API
- توکنهای JWT
- رمزهای عبور
- تنظیمات مربوط به سرویسهای جانبی
- شماره پورت
- نوع محیط اجرا (Development یا Production)
قرار دادن این اطلاعات داخل کد برنامه یکی از رایجترین اشتباهات امنیتی است؛ زیرا ممکن است این اطلاعات در مخزن Git، لاگها یا حتی در خروجی برنامه افشا شوند.
بهترین روش، استفاده از Environment Variables است.
استفاده از فایل .env
یکی از سادهترین روشها برای مدیریت تنظیمات، استفاده از فایل .env به کمک پکیج dotenv است.
ابتدا پکیج را نصب کنید:
npm install dotenv
سپس فایل .env را در ریشه پروژه ایجاد کنید:
nano .env
تعریف متغیرها
داخل فایل، تنظیمات موردنیاز را وارد کنید:
PORT=3000
NODE_ENV=production
DB_HOST=localhost
DB_PORT=5432
DB_NAME=mydatabase
DB_USER=myuser
DB_PASS=StrongPassword
JWT_SECRET=VeryStrongSecretKey
API_KEY=xxxxxxxxxxxxxxxx
هر متغیر در قالب:
KEY=VALUE
تعریف میشود.
بارگذاری فایل .env
در ابتدای فایل اصلی برنامه (برای مثال app.js یا server.js) دستور زیر را اضافه کنید:
require('dotenv').config();
اکنون میتوانید تمام متغیرها را از طریق process.env بخوانید.
برای مثال:
const express = require('express');
require('dotenv').config();
const app = express();
app.listen(process.env.PORT, () => {
console.log(
`Server started on port ${process.env.PORT}`
);
});
استفاده از متغیرها
برای نمونه:
const dbHost = process.env.DB_HOST;
const dbUser = process.env.DB_USER;
const dbPassword = process.env.DB_PASS;
به این ترتیب هیچ اطلاعات حساسی داخل کد قرار نمیگیرد.
استفاده از Environment Variables در PM2
اگر برنامه را با PM2 اجرا میکنید، میتوانید متغیرها را مستقیماً داخل فایل Ecosystem نیز تعریف کنید.
نمونه:
module.exports = {
apps: [
{
name: "myapp",
script: "app.js",
env: {
NODE_ENV: "development",
PORT: 3001
},
env_production: {
NODE_ENV: "production",
PORT: 3000,
DB_HOST: "localhost",
DB_USER: "myuser",
DB_PASS: "StrongPassword"
}
}
]
};
اجرای برنامه
pm2 start ecosystem.config.js --env production
PM2 بهصورت خودکار متغیرهای موجود در env_production را بارگذاری میکند.
جلوگیری از انتشار فایل .env
یکی از مهمترین نکات امنیتی این است که فایل .env نباید وارد مخزن Git شود.
فایل .gitignore را باز کنید:
nano .gitignore
و خط زیر را به آن اضافه کنید:
.env
در این صورت فایل هنگام Push کردن پروژه به GitHub یا GitLab ارسال نخواهد شد.
محدود کردن دسترسی به فایل
از آنجایی که فایل .env شامل اطلاعات حساس است، بهتر است فقط مالک فایل امکان خواندن آن را داشته باشد.
chmod 600 .env
این دستور باعث میشود فقط مالک فایل بتواند آن را بخواند یا ویرایش کند.
اعتبارسنجی متغیرها
در برنامههای Production بهتر است هنگام شروع برنامه بررسی شود که تمام متغیرهای ضروری مقداردهی شده باشند.
برای مثال:
if (!process.env.DB_PASS) {
throw new Error("DB_PASS is not defined.");
}
یا میتوانید از کتابخانههایی مانند:
- joi
- env-schema
- envalid
برای اعتبارسنجی کامل Environment Variables استفاده کنید.
نکات امنیتی مهم
برای محافظت از اطلاعات حساس، رعایت نکات زیر توصیه میشود:
- اطلاعات محرمانه را داخل کد قرار ندهید.
- فایل
.envرا وارد Git نکنید. - برای هر محیط (Development، Testing و Production) فایل جداگانه داشته باشید.
- دسترسی فایل
.envرا محدود کنید. - کلیدهای API و رمزهای عبور را بهصورت دورهای تغییر دهید.
- از چاپ اطلاعات حساس در لاگها خودداری کنید.
- در پروژههای بزرگ از سرویسهایی مانند HashiCorp Vault یا AWS Secrets Manager برای مدیریت Secrets استفاده کنید.
ساختار پیشنهادی
نمونهای از ساختار مناسب پروژه:
myapp/
├── app.js
├── package.json
├── ecosystem.config.js
├── .env
├── .gitignore
├── routes/
├── controllers/
├── models/
└── public/
در این ساختار، تمام اطلاعات محرمانه در فایل .env نگهداری میشوند و فایل ecosystem.config.js مسئول مدیریت نحوه اجرای برنامه توسط PM2 است.
با رعایت این اصول، اطلاعات حساس از کد برنامه جدا میشوند، مدیریت تنظیمات سادهتر خواهد شد و امنیت پروژه در محیط Production به شکل قابل توجهی افزایش پیدا میکند.
مرحله هشتم: بهینهسازی عملکرد (Performance Optimization)
اکنون برنامه شما بهصورت پایدار در محیط Production اجرا میشود، اما برای ارائه بهترین عملکرد لازم است چند بهینهسازی مهم را نیز انجام دهید.
بهینهسازی باعث میشود:
- صفحات سریعتر بارگذاری شوند.
- مصرف پهنای باند کاهش پیدا کند.
- فشار روی Node.js کمتر شود.
- تعداد کاربران بیشتری را بتوانید همزمان پاسخ دهید.
- هزینه منابع سرور کاهش پیدا کند.
در این بخش مهمترین روشهای بهینهسازی را بررسی میکنیم.
فعال کردن فشردهسازی Gzip
یکی از سادهترین راههای افزایش سرعت سایت، فشردهسازی فایلهای ارسالی به مرورگر است.
Nginx از Gzip بهصورت داخلی پشتیبانی میکند.
فایل تنظیمات اصلی را باز کنید:
sudo nano /etc/nginx/nginx.conf
داخل بخش http تنظیمات زیر را اضافه کنید یا از حالت کامنت خارج کنید:
gzip on;
gzip_types
text/plain
text/css
application/javascript
application/json
application/xml
text/xml
image/svg+xml;
gzip_min_length 256;
gzip_comp_level 5;
gzip_vary on;
توضیح هر گزینه:
| گزینه | توضیح |
|---|---|
| gzip on | فعال کردن Gzip |
| gzip_types | نوع فایلهایی که فشرده میشوند |
| gzip_min_length | حداقل اندازه فایل |
| gzip_comp_level | میزان فشردهسازی (۱ تا ۹) |
| gzip_vary | سازگاری بهتر با Cache مرورگر |
پس از اعمال تغییرات:
sudo nginx -t
اگر مشکلی وجود نداشت:
sudo systemctl reload nginx
استفاده از Brotli
Brotli نسبت به Gzip نرخ فشردهسازی بهتری دارد و اکثر مرورگرهای مدرن از آن پشتیبانی میکنند.
اگر ماژول Brotli روی Nginx نصب شده باشد، میتوانید آن را فعال کنید.
brotli on;
brotli_comp_level 5;
brotli_types
text/plain
text/css
application/javascript
application/json
application/xml;
در بسیاری از فایلهای CSS و JavaScript، Brotli بین ۱۵ تا ۳۰ درصد بهتر از Gzip عمل میکند.
کش کردن فایلهای استاتیک
فایلهایی مانند:
- CSS
- JavaScript
- تصاویر
- فونتها
به ندرت تغییر میکنند.
میتوانید از مرورگر بخواهید آنها را چند روز یا چند هفته Cache کند.
داخل فایل تنظیمات Nginx:
location ~* \.(jpg|jpeg|png|gif|svg|ico|css|js|woff|woff2|ttf)$ {
expires 7d;
add_header Cache-Control "public, no-transform";
}
در این حالت مرورگر تا ۷ روز فایلها را دوباره دانلود نخواهد کرد.
کش برای فایلهای تغییرناپذیر
اگر فایلها دارای Hash هستند (برای مثال app.8af213.js) میتوانید Cache طولانیتری تعیین کنید.
expires 30d;
یا حتی:
expires 365d;
اجرای برنامه بهصورت Cluster
بهصورت پیشفرض Node.js تنها از یک هسته CPU استفاده میکند.
اگر سرور شما چند هستهای باشد، بخش زیادی از قدرت پردازشی بدون استفاده باقی میماند.
PM2 این مشکل را با Cluster Mode حل میکند.
برای استفاده از تمام هستههای CPU:
pm2 start app.js -i max
پارامتر max باعث میشود PM2 به تعداد هستههای پردازنده، Process ایجاد کند.
برای مثال:
سرور ۴ هستهای:
CPU Core 1 → App
CPU Core 2 → App
CPU Core 3 → App
CPU Core 4 → App
در نتیجه ظرفیت پاسخگویی برنامه چند برابر خواهد شد.
مانیتورینگ مصرف منابع
برای مشاهده مصرف CPU و RAM:
pm2 monit
نمونه اطلاعات نمایش دادهشده:
- CPU Usage
- Memory Usage
- Restart Count
- Uptime
اگر مصرف حافظه بهصورت مداوم افزایش پیدا کند، احتمال وجود Memory Leak در برنامه وجود دارد.
سرویسدهی فایلهای استاتیک توسط Nginx
یکی از رایجترین اشتباهات این است که تصاویر و فایلهای CSS و JavaScript توسط Node.js ارسال شوند.
بهتر است Nginx این فایلها را مستقیماً ارائه دهد.
نمونه:
location /static {
alias /var/www/myapp/public;
}
در این حالت درخواستها مستقیماً توسط Nginx پاسخ داده میشوند و هیچ فشاری به Node.js وارد نمیشود.
مدیریت لاگهای PM2
برای مشاهده لاگها:
pm2 logs
اما با گذشت زمان حجم لاگها افزایش پیدا میکند.
برای جلوگیری از پر شدن فضای دیسک، افزونه Log Rotate را نصب کنید:
pm2 install pm2-logrotate
سپس حداکثر اندازه فایل لاگ را تعیین کنید:
pm2 set pm2-logrotate:max_size 10M
تعداد فایلهایی که نگهداری شوند:
pm2 set pm2-logrotate:retain 7
در این مثال:
- هر فایل حداکثر ۱۰ مگابایت خواهد بود.
- فقط لاگهای ۷ روز اخیر نگهداری میشوند.
بررسی لاگهای Nginx
لاگ درخواستها:
/var/log/nginx/access.log
لاگ خطاها:
/var/log/nginx/error.log
برای مشاهده زنده لاگها:
sudo tail -f /var/log/nginx/access.log
یا
sudo tail -f /var/log/nginx/error.log
تحلیل لاگها با GoAccess
یکی از بهترین ابزارها برای تحلیل لاگهای Nginx، نرمافزار GoAccess است.
نصب:
sudo apt install goaccess
ساخت گزارش HTML:
sudo goaccess \
/var/log/nginx/access.log \
-o /var/www/html/report.html \
--log-format=COMBINED
این گزارش شامل اطلاعاتی مانند:
- تعداد بازدیدکنندگان
- صفحات پربازدید
- آدرس IP کاربران
- وضعیت پاسخها
- سرعت پاسخدهی
خواهد بود.
تنظیمات محیط اجرا
بهتر است برخی تنظیمات عملکردی نیز از طریق Environment Variables مدیریت شوند.
برای مثال:
CACHE_TIME=3600
LOG_LEVEL=info
API_RATE_LIMIT=100
در این صورت بدون تغییر کد برنامه میتوانید تنظیمات را تغییر دهید.
مرحله نهم: مانیتورینگ و جمعآوری متریکها (Monitoring & Metrics)
پس از راهاندازی برنامه در محیط Production، تنها اجرا شدن برنامه کافی نیست؛ باید بهصورت مداوم وضعیت آن را نیز پایش کنید.
مانیتورینگ به شما کمک میکند تا:
- از قطعی سرویس سریعاً مطلع شوید.
- مصرف CPU و RAM را بررسی کنید.
- مشکلات عملکردی را قبل از تأثیر بر کاربران شناسایی کنید.
- افزایش بار سرور را مشاهده کنید.
- روند رشد برنامه را در طول زمان تحلیل کنید.
یک سیستم مانیتورینگ مناسب معمولاً شامل دو بخش است:
- پایش لحظهای (Real-time Monitoring) برای مشاهده وضعیت فعلی
- ذخیره متریکها (Metrics Collection) برای تحلیل عملکرد در طول زمان
مانیتورینگ برنامه با PM2
PM2 علاوه بر مدیریت Processها، ابزارهای مانیتورینگ مناسبی نیز ارائه میدهد.
مشاهده وضعیت برنامهها
برای مشاهده تمام برنامههای در حال اجرا:
pm2 list
نمونه خروجی:
┌────┬──────────┬─────────┬────────┬────────┬──────────┐
│ id │ name │ status │ cpu │ memory │ uptime │
└────┴──────────┴─────────┴────────┴────────┴──────────┘
در این جدول میتوانید اطلاعات زیر را مشاهده کنید:
- وضعیت برنامه
- میزان مصرف CPU
- میزان مصرف حافظه
- مدت زمان اجرا
- تعداد Restartها
داشبورد لحظهای PM2
برای مشاهده وضعیت سیستم بهصورت زنده:
pm2 monit
این داشبورد اطلاعات زیر را نمایش میدهد:
- مصرف CPU
- مصرف RAM
- تعداد درخواستها
- وضعیت هر Process
- Restart Count
- لاگهای لحظهای
اگر مشاهده کردید که مصرف حافظه بهصورت مداوم افزایش پیدا میکند، احتمال وجود Memory Leak در برنامه وجود دارد.
مشاهده لاگها
برای مشاهده لاگ تمام برنامهها:
pm2 logs
برای مشاهده لاگ یک برنامه خاص:
pm2 logs myapp
بررسی تعداد Restartها
اگر برنامه مرتباً Restart میشود:
pm2 status
یا
pm2 info myapp
در بخش Restart Count میتوانید تعداد Restartها را مشاهده کنید.
افزایش غیرعادی این عدد معمولاً نشانه وجود خطا در برنامه است.
مانیتورینگ Nginx
Nginx اطلاعات ارزشمندی درباره درخواستهای کاربران در اختیار شما قرار میدهد.
Access Log
تمام درخواستها در فایل زیر ثبت میشوند:
/var/log/nginx/access.log
برای مشاهده لحظهای:
sudo tail -f /var/log/nginx/access.log
Error Log
خطاهای Nginx در فایل زیر ذخیره میشوند:
/var/log/nginx/error.log
برای مشاهده:
sudo tail -f /var/log/nginx/error.log
فعال کردن صفحه وضعیت Nginx
Nginx قابلیتی به نام stub_status دارد که اطلاعات زندهای از وضعیت وبسرور نمایش میدهد.
داخل تنظیمات سایت:
location /nginx_status {
stub_status;
allow 127.0.0.1;
deny all;
}
سپس:
sudo systemctl reload nginx
اکنون از داخل سرور:
curl http://localhost/nginx_status
نمونه خروجی:
Active connections: 5
server accepts handled requests
10240 10240 20350
Reading: 0
Writing: 2
Waiting: 3
جمعآوری متریکهای برنامه Node.js
گاهی لازم است اطلاعاتی مانند موارد زیر را نیز ثبت کنید:
- تعداد درخواستها
- مدت پاسخدهی API
- مصرف حافظه
- تعداد Queryهای دیتابیس
یکی از بهترین ابزارها برای این کار Prometheus است.
ابتدا کتابخانه مربوطه را نصب کنید:
npm install prom-client
نمونه:
const express = require('express');
const client = require('prom-client');
const app = express();
client.collectDefaultMetrics();
app.get('/metrics', async (req, res) => {
res.set(
'Content-Type',
client.register.contentType
);
res.end(
await client.register.metrics()
);
});
app.listen(3000);
اکنون آدرس:
/metrics
تمام متریکهای برنامه را در اختیار Prometheus قرار میدهد.
مانیتورینگ سیستم
علاوه بر خود برنامه، باید وضعیت سرور نیز بررسی شود.
htop
یکی از بهترین ابزارها:
sudo apt install htop
اجرای برنامه:
htop
نمایش:
- CPU
- RAM
- Swap
- Processها
بررسی فضای دیسک
df -h
بررسی حافظه
free -h
بررسی شبکه
ss -tulnp
یا
netstat -tulnp
بررسی مصرف دیسک
iostat
ابزارهای حرفهای مانیتورینگ
برای پروژههای Production پیشنهاد میشود از ابزارهای زیر استفاده کنید:
| ابزار | کاربرد |
|---|---|
| Grafana | داشبوردهای گرافیکی |
| Prometheus | ذخیره متریکها |
| Netdata | مانیتورینگ لحظهای |
| Glances | مشاهده وضعیت سیستم |
| Grafana Agent | جمعآوری متریکها |
| Loki | مدیریت لاگها |
این ابزارها امکان مشاهده وضعیت سرور و برنامه در طول زمان را فراهم میکنند.
PM2 Plus
PM2 نسخه حرفهای نیز ارائه میدهد که امکانات زیر را دارد:
- داشبورد تحت وب
- نمودار مصرف منابع
- هشدار هنگام افزایش مصرف CPU
- هشدار هنگام افزایش مصرف RAM
- نمایش Restartها
- مشاهده وضعیت چندین سرور بهصورت همزمان
چرا مانیتورینگ اهمیت دارد؟
اگر مانیتورینگ نداشته باشید:
- ممکن است برنامه ساعتها از دسترس خارج باشد و متوجه نشوید.
- افزایش مصرف RAM را نبینید.
- حملات یا درخواستهای غیرعادی را شناسایی نکنید.
- علت کند شدن برنامه را پیدا نکنید.
اما با مانیتورینگ مناسب میتوانید:
- مشکلات را پیش از کاربران شناسایی کنید.
- روند رشد مصرف منابع را بررسی کنید.
- برای ارتقای سختافزار یا مقیاسپذیری تصمیمهای دقیقتری بگیرید.
- از پایداری سرویس در بلندمدت اطمینان حاصل کنید.
مرحله ۱۰ — خطاهای رایج، عیبیابی و بهترین روشها (Common Errors, Troubleshooting, and Best Practices)
حتی اگر زیرساخت Node.js شما بهدرستی پیکربندی شده باشد، باز هم ممکن است در طول زمان با خطاها یا مشکلاتی روبهرو شوید. آشنایی با روش عیبیابی و رعایت بهترین شیوهها، باعث میشود سرویس شما پایدارتر، امنتر و نگهداری آن سادهتر باشد.
در این بخش، رایجترین خطاهای محیط Production، روش برطرف کردن آنها و مجموعهای از Best Practiceهای مهم را بررسی میکنیم.
خطاهای رایج و روش رفع آنها
۱. برنامه توسط PM2 اجرا نمیشود
اگر پس از اجرای دستور pm2 start برنامه شما اجرا نشد، معمولاً یکی از موارد زیر علت آن است:
- مسیر فایل اشتباه است.
- برخی وابستگیها (Dependencies) نصب نشدهاند.
- متغیرهای محیطی (Environment Variables) مقداردهی نشدهاند.
برای مشاهده علت خطا ابتدا لاگهای برنامه را بررسی کنید:
pm2 logs
سپس از صحیح بودن مسیر فایل اصلی برنامه و نصب بودن تمامی پکیجها مطمئن شوید:
npm install --production
همچنین بررسی کنید فایل .env یا تنظیمات موجود در فایل ecosystem.config.js بهدرستی بارگذاری شده باشند.
۲. خطای Port Already in Use
اگر هنگام اجرای برنامه با خطایی مشابه زیر مواجه شدید:
Error: listen EADDRINUSE
یعنی پورتی که برنامه قصد استفاده از آن را دارد، توسط پردازش دیگری اشغال شده است.
ابتدا پردازش استفادهکننده از پورت را پیدا کنید:
sudo lsof -i :3000
سپس در صورت نیاز آن را متوقف کنید:
sudo kill -9 PID
یا شماره پورت برنامه را در فایل .env یا فایل تنظیمات PM2 تغییر دهید.
۳. خطای Nginx 502 Bad Gateway
یکی از رایجترین خطاها هنگام استفاده از Reverse Proxy، نمایش صفحه 502 Bad Gateway است.
این خطا معمولاً به یکی از دلایل زیر رخ میدهد:
- برنامه Node.js متوقف شده است.
- PM2 برنامه را اجرا نکرده است.
- مقدار
proxy_passدر Nginx اشتباه است. - برنامه روی پورت دیگری اجرا شده است.
ابتدا برنامه را مجدداً اجرا کنید:
pm2 restart all
سپس تنظیمات Nginx را بارگذاری مجدد کنید:
sudo systemctl reload nginx
در نهایت بررسی کنید مقدار proxy_pass دقیقاً به پورتی اشاره کند که برنامه Node.js روی آن اجرا شده است؛ برای مثال:
proxy_pass http://localhost:3000;
۴. خطاهای Permission Denied
اگر برنامه اجازه خواندن یا نوشتن فایلها را نداشته باشد، با خطاهای Permission مواجه خواهید شد.
مالکیت فایلها را اصلاح کنید:
sudo chown -R $USER:$USER /var/www/myapp
سپس سطح دسترسی مناسب را اعمال کنید:
sudo chmod -R 755 /var/www/myapp
نکته: هرگز برنامههای Node.js یا PM2 را با کاربر root اجرا نکنید.
۵. تمدید نشدن گواهی SSL
اگر گواهیهای Let’s Encrypt تمدید نشوند، ابتدا فرآیند تمدید را آزمایش کنید:
sudo certbot renew --dry-run
در صورت مشاهده خطا موارد زیر را بررسی کنید:
- رکورد DNS دامنه به سرور اشاره کند.
- تنظیمات Nginx صحیح باشد.
- دامنه در دسترس باشد.
همچنین میتوانید فایل لاگ Certbot را بررسی کنید:
/var/log/letsencrypt/
۶. مسدود شدن دسترسی توسط فایروال
اگر سایت از بیرون در دسترس نیست اما سرویسها اجرا هستند، احتمالاً UFW دسترسی را مسدود کرده است.
اجازه دسترسی Nginx را صادر کنید:
sudo ufw allow 'Nginx Full'
فعال بودن فایروال را بررسی کنید:
sudo ufw status
فرآیند استاندارد عیبیابی (Troubleshooting Workflow)
هر زمان با مشکلی مواجه شدید، این مراحل را بهترتیب انجام دهید.
۱. بررسی لاگها
تقریباً تمامی خطاها ابتدا در لاگها ثبت میشوند.
برای مشاهده لاگهای PM2:
pm2 logs
برای مشاهده لاگهای Nginx:
sudo tail -f /var/log/nginx/error.log
۲. بررسی وضعیت سرویسها
از فعال بودن سرویسها مطمئن شوید:
pm2 status
و
systemctl status nginx
۳. بررسی فایلهای پیکربندی
قبل از ریستارت کردن Nginx همیشه تنظیمات را تست کنید:
sudo nginx -t
اگر از فایل Ecosystem استفاده میکنید، از صحیح بودن ساختار فایل نیز مطمئن شوید.
۴. بررسی پورتهای فعال
اطمینان حاصل کنید برنامه روی پورتی که انتظار دارید اجرا شده باشد:
sudo netstat -tulnp | grep node
یا:
ss -tulnp
۵. بررسی منابع سرور
گاهی مشکل از کمبود حافظه یا مصرف بیش از حد CPU است.
برای مشاهده وضعیت سیستم:
htop
یا:
pm2 monit
۶. تست مستقیم برنامه
برای اینکه مطمئن شوید خود برنامه سالم است، آن را بدون Nginx تست کنید:
curl http://localhost:3000
اگر پاسخ مناسب دریافت کردید، مشکل احتمالاً در تنظیمات Nginx قرار دارد.
بهترین روشها (Best Practices)
برای داشتن یک محیط Production پایدار، امن و قابل نگهداری، رعایت نکات زیر توصیه میشود.
نکات امنیتی
- سیستمعامل و بستهها را مرتب بهروزرسانی کنید:
sudo apt update && sudo apt upgrade -y
- تمام ترافیک را به HTTPS هدایت کنید.
- ورود SSH را فقط با کلید SSH فعال کنید.
- ورود مستقیم کاربر root را غیرفعال کنید.
- برنامهها را با یک کاربر غیر Root اجرا کنید.
- اطلاعات حساس مانند Stack Trace را برای کاربران نمایش ندهید.
- وابستگیهای پروژه را مرتب بررسی کنید:
npm audit
بهینهسازی عملکرد
برای استفاده از تمام هستههای پردازنده:
pm2 start app.js -i max
همچنین پیشنهاد میشود:
- از Redis یا سایر Cacheها استفاده کنید.
- فشردهسازی Gzip یا Brotli را در Nginx فعال کنید.
- فایلهای Static را مستقیماً توسط Nginx سرویسدهی کنید.
- لاگها را بهصورت دورهای Rotate کنید.
- عملکرد سرور را بهطور مداوم مانیتور کنید.
نگهداری و مدیریت
برای کاهش ریسک از دست رفتن اطلاعات:
- بهصورت منظم نسخه پشتیبان (Backup) تهیه کنید.
- تنظیمات پروژه را در Git نگهداری کنید.
- تمامی مراحل استقرار (Deployment) را مستندسازی کنید.
- قبل از اعمال تغییرات روی سرور اصلی، آنها را در محیط Staging آزمایش کنید.
- از سرویسهای مانیتورینگ Uptime مانند UptimeRobot یا StatusCake استفاده کنید.
- در صورت افزایش ترافیک، از Load Balancer، Docker یا Kubernetes برای مقیاسپذیری استفاده کنید.
- بهصورت دورهای تنظیمات امنیتی و عملکرد سرور را بازبینی کنید.
با رعایت این موارد، زیرساخت Node.js شما در محیط Production پایدارتر، امنتر و آماده پاسخگویی به بار کاری بیشتر خواهد بود.
مرحله ۱۱ — پرسشهای متداول (FAQ)
در این بخش به رایجترین سؤالاتی که هنگام راهاندازی و استقرار برنامههای Node.js در محیط Production روی Ubuntu مطرح میشود، پاسخ میدهیم.
۱. چگونه یک برنامه Node.js را روی Ubuntu بهصورت Production اجرا کنیم؟
برای استقرار اصولی یک برنامه Node.js در محیط Production، بهتر است مراحل زیر را بهترتیب انجام دهید. اجرای برنامه با دستور node app.js بهتنهایی مناسب نیست، زیرا با بسته شدن ترمینال، برنامه نیز متوقف خواهد شد.
روند پیشنهادی به این صورت است:
سیستم را بهروز کنید
sudo apt update && sudo apt upgrade -y
یک کاربر غیر Root ایجاد کنید
برای افزایش امنیت، برنامه را با کاربر Root اجرا نکنید و از یک کاربر معمولی با دسترسی sudo استفاده کنید.
آخرین نسخه LTS از Node.js را نصب کنید
بهترین روش، استفاده از مخزن رسمی NodeSource است:
curl -fsSL https://deb.nodesource.com/setup_24.x -o nodesource_setup.sh
sudo bash nodesource_setup.sh
sudo apt install nodejs -y
پروژه را دریافت و وابستگیها را نصب کنید
اگر پروژه در Git قرار دارد، ابتدا آن را Clone کرده و سپس وابستگیها را نصب کنید:
git clone https://your-repository.git
cd your-project
npm ci
استفاده از
npm ciدر محیط Production نسبت بهnpm installتوصیه میشود، زیرا دقیقاً نسخههای ثبتشده درpackage-lock.jsonرا نصب میکند.
متغیرهای محیطی را تعریف کنید
اطلاعات حساسی مانند:
- اطلاعات دیتابیس
- API Key
- JWT Secret
- Tokenها
را داخل فایل .env نگهداری کنید.
برنامه را توسط PM2 اجرا کنید
sudo npm install -g pm2
pm2 start app.js --name my-production-app
اجرای خودکار بعد از ریبوت
ابتدا دستور Startup را تولید کنید:
pm2 startup
سپس دستوری که PM2 نمایش میدهد را اجرا کنید.
در پایان نیز وضعیت فعلی برنامهها را ذخیره کنید:
pm2 save
۲. بهترین ابزار برای مدیریت برنامههای Node.js روی VPS چیست؟
در اغلب پروژههای حرفهای، PM2 بهترین انتخاب برای مدیریت برنامههای Node.js است.
مزایای PM2 عبارتاند از:
- راهاندازی خودکار بعد از ریبوت
- Restart خودکار هنگام Crash
- اجرای Cluster روی چند هسته CPU
- مانیتورینگ مصرف CPU و RAM
- مدیریت لاگها
- امکان اجرای همزمان چند برنامه
به همین دلیل PM2 به استاندارد رایج اجرای برنامههای Node.js در محیط Production تبدیل شده است.
۳. برای محیط Production از PM2 استفاده کنیم یا Systemd؟
در واقع بهترین راهکار استفاده از هر دو است.
در این ساختار:
- PM2 مسئول مدیریت برنامه Node.js است.
- Systemd مسئول اجرای خودکار PM2 پس از راهاندازی مجدد سرور خواهد بود.
مراحل کار:
برنامه را اجرا کنید:
pm2 start app.js
سپس Startup Script را ایجاد کنید:
pm2 startup
دستور تولیدشده را اجرا نمایید.
در پایان:
pm2 save
با این روش، پس از هر بار ریبوت سرور، تمامی برنامهها بهصورت خودکار اجرا خواهند شد.
۴. چگونه Nginx را بهعنوان Reverse Proxy برای Node.js تنظیم کنیم؟
در محیط Production بهتر است کاربران مستقیماً به Node.js متصل نشوند.
بهجای آن:
Client
│
▼
Nginx (80 / 443)
│
▼
Node.js (localhost:3000)
نمونه تنظیمات:
server {
listen 80;
server_name example.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;
}
}
پس از ذخیره فایل:
sudo nginx -t
sudo systemctl reload nginx
۵. چگونه HTTPS را برای برنامه Node.js فعال کنیم؟
بهترین روش استفاده از Let’s Encrypt به همراه Certbot است.
ابتدا Certbot را نصب کنید:
sudo apt install certbot python3-certbot-nginx
سپس گواهی SSL را دریافت کنید:
sudo certbot --nginx -d example.com -d www.example.com
Certbot بهصورت خودکار:
- گواهی SSL را دریافت میکند.
- تنظیمات Nginx را بروزرسانی میکند.
- ریدایرکت HTTP به HTTPS را فعال میکند.
- تمدید خودکار گواهی را نیز پیکربندی میکند.
برای آزمایش تمدید خودکار:
sudo certbot renew --dry-run
۶. چگونه امنیت برنامه Node.js را افزایش دهیم؟
برای افزایش امنیت سرور، رعایت نکات زیر توصیه میشود.
فایروال را فعال کنید
sudo ufw allow OpenSSH
sudo ufw allow "Nginx Full"
sudo ufw enable
از کلید SSH استفاده کنید
ورود با رمز عبور را غیرفعال کرده و فقط از SSH Key استفاده کنید.
برنامه را با کاربر Root اجرا نکنید
همیشه برنامه را با یک کاربر معمولی اجرا کنید.
از Helmet استفاده کنید
برای افزایش امنیت Headerهای HTTP:
npm install helmet
Node.js را فقط روی localhost اجرا کنید
const hostname = "127.0.0.1";
در این حالت فقط Nginx قادر خواهد بود به برنامه دسترسی داشته باشد و کاربران هرگز مستقیماً به سرویس Node.js متصل نمیشوند.
وابستگیهای پروژه را مرتب بررسی کنید
npm audit
در صورت وجود آسیبپذیری، آنها را بروزرسانی کنید.
با رعایت این موارد، زیرساخت Node.js شما از نظر امنیت، پایداری و عملکرد، آماده استفاده در محیطهای عملیاتی خواهد بود.
جمعبندی
در این مقاله، یک زیرساخت استاندارد و آماده Production برای اجرای برنامههای Node.js روی Ubuntu را راهاندازی کردیم. ابتدا آخرین نسخه LTS از Node.js را نصب کردیم، سپس با استفاده از PM2 فرآیند اجرای برنامه را مدیریت کردیم تا در صورت بروز خطا بهصورت خودکار Restart شود و پس از راهاندازی مجدد سرور نیز بدون نیاز به دخالت کاربر اجرا شود.
در ادامه، با پیکربندی Nginx بهعنوان Reverse Proxy، دسترسی مستقیم به برنامه Node.js را حذف کرده و تمامی درخواستها را از طریق Nginx مدیریت کردیم. همچنین با استفاده از گواهیهای SSL رایگان Let’s Encrypt، ارتباط کاربران با وبسایت را بهصورت رمزنگاریشده برقرار کردیم تا امنیت اطلاعات افزایش پیدا کند.
برای افزایش امنیت سرور نیز فایروال UFW را پیکربندی کردیم، نحوه مدیریت متغیرهای محیطی و اطلاعات حساس را بررسی کردیم و با فعالسازی فشردهسازی، کش و ابزارهای مانیتورینگ، عملکرد و پایداری سرویس را بهبود دادیم.
در پایان نیز رایجترین خطاهای محیط Production، روشهای عیبیابی و مجموعهای از بهترین شیوههای نگهداری، امنیت و بهینهسازی را مرور کردیم تا بتوانید یک سرویس Node.js پایدار، سریع و ایمن را در محیط عملیاتی مدیریت کنید.
با رعایت این نکات، زیرساخت شما آماده میزبانی از برنامههای Node.js در مقیاسهای مختلف خواهد بود و در صورت افزایش ترافیک نیز میتوانید با استفاده از ابزارهایی مانند Docker، Kubernetes یا Load Balancerها، سرویس خود را بهسادگی مقیاسپذیر کنید.
مطالعه بیشتر
اگر قصد دارید دانش خود را در زمینه استقرار و مدیریت برنامههای Node.js گسترش دهید، مطالعه مقالات زیر نیز پیشنهاد میشود:
- آموزش نصب Node.js روی Ubuntu
- آموزش استفاده از PostgreSQL در پروژههای Node.js
- آموزش نصب و پیکربندی Nginx روی Ubuntu
- آموزش دریافت گواهی SSL رایگان با Let’s Encrypt
- آموزش استقرار برنامههای Node.js با Docker
- آموزش راهاندازی CI/CD برای پروژههای Node.js با Jenkins یا GitHub Actions
از همراهی شما با پارمین کلود سپاسگزاریم.
نظرات کاربران