NGINX برای توسعهدهندگان ASP.NET Core - قسمت ششم - پروژه عملی و جمعبندی
نویسنده: وحید نصیری
تاریخ: ۱۴۰۴/۰۴/۰۱ ۰۸:۱۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
dotnet new mvc --auth Individual.Release پابلیش کنید./var/www/final-project در سرور خود منتقل کنید.systemd مجزا بسازید (kestrel-fp-5000.service و kestrel-fp-5001.service).5000 و 5001 اجرا کند.final-project.conf در sites-available ایجاد کنید.upstream به نام project_backend تعریف کنید که شامل هر دو نمونه اپلیکیشن (پورتهای 5000 و 5001) باشد. از الگوریتم توزیع بار least_conn استفاده کنید.server اصلی را طوری تنظیم کنید که به درخواستهای دامنهی شما (مثلاً final-project.your-domain.com) گوش دهد.certbot، یک گواهینامه SSL رایگان از Let's Encrypt برای دامنه خود دریافت و نصب کنید.wwwroot پروژه سرو کند (با استفاده از متد try_files)./Identity/Account/Login) اعمال کنید تا از حملات Brute-force جلوگیری شود.nginx -t بررسی کنید.reload کنید.https://final-project.your-domain.com بروید و از صحت عملکرد سایت مطمئن شوید.Content-Encoding: gzip و وضعیت کش را بررسی کنید.systemd، تست کنید که سایت همچنان در دسترس باقی میماند (تست Load Balancing).sites-available و sites-enabled استفاده کنید. همیشه قبل از reload، کانفیگ خود را با nginx -t تست کنید. برای اعمال تغییرات بدون قطعی، از reload استفاده کنید نه restart.certbot برای سهولت کار استفاده کنید. هدرهای امنیتی را برای مقابله با حملات سمت کلاینت فراموش نکنید. روی نقاط حساس مانند صفحه لاگین، محدودیت نرخ اعمال کنید. سرویس اپلیکیشن خود را با یک کاربر غیر-root (مانند www-data) اجرا کنید.Release پابلیش کنید. فرآیند اجرای آن را با systemd مدیریت کنید تا به صورت خودکار اجرا شود. برای استقرارهای مدرن، استفاده از Docker و Docker Compose را در نظر بگیرید.502 Bad Gateway تقریباً همیشه به این معنی است که اپلیکیشن ASP.NET Core شما اجرا نشده یا NGINX نمیتواند به آن دسترسی پیدا کند. لاگهای NGINX (/var/log/nginx/error.log) و لاگهای اپلیکیشن (journalctl -fu your-service-name) بهترین دوستان شما برای یافتن مشکل هستند.Content-Security-Policy.worker_processes و worker_connections.systemd به عنوان سرویس اجرا کرده و NGINX را مستقیماً روی سرور نصب و پیکربندی میکنیم.systemd (برای نمونه اول)/etc/systemd/system/kestrel-final-project-5000.service ایجاد کنید.# /etc/systemd/system/kestrel-final-project-5000.service [Unit] Description=Final Project ASP.NET Core App running on Kestrel (Port 5000) [Service] # مسیر پوشهای که فایلهای پابلیش شده اپلیکیشن در آن قرار دارد WorkingDirectory=/var/www/final-project # دستور اصلی برای اجرای اپلیکیشن. # حتما نام فایل dll خود را جایگزین FinalProject.dll کنید. # با --urls به صورت صریح پورت اجرایی این نمونه را مشخص میکنیم. ExecStart=/usr/bin/dotnet /var/www/final-project/FinalProject.dll --urls "http://localhost:5000" # راهاندازی مجدد خودکار در صورت بروز خطا Restart=always # تاخیر ۱۰ ثانیهای قبل از راهاندازی مجدد RestartSec=10 KillSignal=SIGINT # اجرای سرویس با کاربر کماختیار www-data برای افزایش امنیت User=www-data # تنظیم متغیرهای محیطی برای اپلیکیشن Environment=ASPNETCORE_ENVIRONMENT=Production Environment=DOTNET_PRINT_CONSOLE_OUTPUT=true [Install] WantedBy=multi-user.target
5001 اجرا میشود)، کافی است این فایل را با نام kestrel-final-project-5001.service کپی کرده و در خط ExecStart، پورت را به 5001 تغییر دهید.final-project.conf)/etc/nginx/sites-available/final-project.conf ایجاد کنید.# /etc/nginx/sites-available/final-project.conf
# ۱. تعریف گروه سرورهای پشتیبان برای توزیع بار (Load Balancing)
upstream project_backend {
# استفاده از الگوریتم "کمترین ارتباط فعال" برای توزیع هوشمندانهتر
least_conn;
# لیست نمونههای در حال اجرای اپلیکیشن
server localhost:5000;
server localhost:5001;
}
# نکته: این بخش باید در فایل اصلی nginx.conf و داخل بلوک http قرار گیرد.
# limit_req_zone $binary_remote_addr zone=login_limit:10m rate=10r/m;
# ۲. بلوک اصلی سرور که به درخواستهای وبسایت پاسخ میدهد
server {
# گوش دادن روی پورت 80 و 443 (برای SSL)
# http2 عملکرد بهتری ارائه میدهد
listen 80;
listen 443 ssl http2;
server_name final-project.your-domain.com; # <-- دامنه خود را اینجا وارد کنید
# ۳. تنظیمات SSL/TLS
# این خطوط توسط certbot به صورت خودکار پر میشوند
ssl_certificate /etc/letsencrypt/live/final-project.your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/final-project.your-domain.com/privkey.pem;
# تنظیمات امنیتی پیشنهادی برای SSL
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
# ۴. افزودن هدرهای امنیتی
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; img-src 'self' data:; style-src 'self' 'unsafe-inline';" always;
# ۵. سرو کردن فایلهای استاتیک
# مسیر ریشه برای فایلهای استاتیک (wwwroot)
root /var/www/final-project/wwwroot;
# قانون اصلی برای مدیریت درخواستها
location / {
# ابتدا تلاش کن فایل استاتیک را پیدا کنی، اگر نبود به پراکسی بفرست
try_files $uri @proxy;
}
# ۶. مکانیابی (Location) برای مسیرهای حساس
# اعمال محدودیت نرخ روی صفحه لاگین
location /Identity/Account/Login {
limit_req zone=login_limit burst=10 nodelay;
# پس از بررسی محدودیت، درخواست را به پراکسی ارسال کن
proxy_pass http://project_backend;
# افزودن هدرهای ضروری برای پراکسی
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;
}
# ۷. مکانیابی اصلی برای Reverse Proxy
location @proxy {
# ارسال ترافیک به گروه سرورهای پشتیبان
proxy_pass http://project_backend;
# تنظیمات ضروری برای هدرها و پشتیبانی از WebSocket (برای SignalR)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_cache off; # کش برای ارتباطات WebSocket توصیه نمیشود
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;
}
}
# بلوک سرور برای ریدایرکت دائمی HTTP به HTTPS
# این بلوک هم توسط certbot به صورت خودکار ایجاد میشود
server {
listen 80;
server_name final-project.your-domain.com;
return 301 https://$host$request_uri;
}Dockerfile برای اپلیکیشن ASP.NET Core# Dockerfile # مرحله ۱: ساخت (Build) اپلیکیشن FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build WORKDIR /src # کپی کردن فایلهای پروژه و بازیابی پکیجها COPY ["FinalProject.csproj", "."] RUN dotnet restore "./FinalProject.csproj" # کپی کردن بقیه سورس کد و پابلیش کردن پروژه COPY . . WORKDIR "/src/." RUN dotnet publish "FinalProject.csproj" -c Release -o /app/publish # مرحله ۲: ساخت ایمیج نهایی و بهینه FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final WORKDIR /app COPY --from=build /app/publish . # پورت داخلی که Kestrel روی آن گوش میدهد EXPOSE 8080 # دستور اجرای اپلیکیشن هنگام استارت شدن کانتینر ENTRYPOINT ["dotnet", "FinalProject.dll"]
default.conf)nginx در کنار docker-compose.yml قرار دهید (./nginx/default.conf).# ./nginx/default.conf
server {
listen 80;
location / {
# نام "aspnet-app" نام سرویسی است که در docker-compose تعریف شده.
# داکر به صورت خودکار این نام را به IP داخلی کانتینر اپلیکیشن ترجمه میکند.
# پورت 8080 همان پورتی است که در Dockerfile اکسپوز کردیم.
proxy_pass http://aspnet-app:8080;
# تنظیمات استاندارد پراکسی
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
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
}docker-compose.yml# docker-compose.yml
version: '3.8'
services:
# سرویس اپلیکیشن ASP.NET Core
aspnet-app:
container_name: final-project-app
# ساخت ایمیج از روی Dockerfile موجود در همین مسیر
build:
context: .
dockerfile: Dockerfile
restart: always
environment:
# تنظیم Kestrel برای گوش دادن روی پورت 8080 در تمام اینترفیسهای شبکه داخل کانتینر
- ASPNETCORE_URLS=http://+:8080
# سرویس NGINX به عنوان Reverse Proxy
nginx-proxy:
container_name: final-project-nginx
image: nginx:latest
restart: always
ports:
# پورت 80 ماشین میزبان را به پورت 80 کانتینر NGINX متصل کن
- "80:80"
# در صورت نیاز به SSL، پورت 443 را هم متصل کنید
- "443:443"
volumes:
# فایل کانفیگ محلی ما را در مسیر کانفیگ پیشفرض NGINX در کانتینر قرار بده
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
# قبل از اجرای NGINX، منتظر باش تا سرویس اپلیکیشن آماده شود
depends_on:
- aspnet-app