رفتن به محتوا
LoopX

نصب و اجرا

توی این درس یاد می‌گیری Nginx را به دو روش راه بیندازی: روی خود سرور با sudo apt install nginx (که آن را به یک سرویس systemd تبدیل می‌کند)، و داخل داکر با docker run -d -p 8080:80 nginx:alpine. سرویس را با systemctl کنترل می‌کنی و فرق حیاتی reload و restart را با یک آزمایش واقعی می‌بینی؛ فایروال را برای Nginx باز می‌کنی؛ و وقتی نصب یا اجرا شکست خورد، با systemctl status، journalctl و nginx -t دلیلش را پیدا و درستش می‌کنی.

مسئله: «نصب کردم ولی صفحه باز نمی‌شود»

Section titled “مسئله: «نصب کردم ولی صفحه باز نمی‌شود»”

نصب Nginx یک خط است، ولی سؤال‌های بعدش زیادند: الان در حال اجراست؟ بعد از ریبوت سرور خودش بالا می‌آید؟ تنظیمات را عوض کردم، چطور اعمالش کنم که سایت قطع نشود؟ پورت ۸۰ از بیرون باز است؟ و اگر بالا نیامد، پیام خطا کجاست؟ این درس جواب همین‌هاست. (و ماشین آزمایشی ما هم یک خطای واقعی و آموزنده جلویمان گذاشت.)

نصب Nginx مثل نصب یک کولر است. خریدن و نصبش (apt install) یک کار است؛ ولی بعدش باید بدانی کلیدش کجاست (systemctl start و stop)، اینکه بعد از قطع برق خودش روشن شود (enable)، اینکه برای عوض کردن دما لازم نیست خاموش و روشنش کنی (reload به‌جای restart)، و اینکه پنجره باید باز باشد تا باد بیرون برود (فایروال). و اگر روشن نشد، اول چراغ خطایش را نگاه می‌کنی (status و journalctl)، نه اینکه کولر را پس بدهی.

روی سرور (apt) داخل داکر
نصب sudo apt install nginx docker run -d -p 8080:80 nginx:alpine
مدیریت systemctl (سرویس systemd) docker start/stop/restart/logs
تنظیمات /etc/nginx/ فایل‌هایی که داخل کانتینر mount می‌کنی
نسخه نسخه‌ی مخزن Ubuntu (اینجا ۱.۲۴) هر نسخه‌ای که tag بگویی (nginx:1.27-alpine)
کی بهتر است؟ سرور معمولی، چند سایت، HTTPS با certbot وقتی بقیه‌ی اپ‌ها هم کانتینرند (Compose)، یا نسخه‌ی خاص می‌خواهی

هر دو را در این دوره به کار می‌بریم؛ مفاهیم و فایل تنظیمات در هر دو یکی است.

چرخه‌ی زندگی سرویس nginx در systemd: apt بسته را نصب و سرویس را فعال (enable) می‌کند، systemd آن را با ExecStart اجرا می‌کند، reload فقط تنظیمات را دوباره می‌خواند (worker های تازه، بدون قطع) و restart کل سرویس را می‌بندد و دوباره بالا می‌آورد.

این درس روی ماشین آزمایشی server (Ubuntu 24.04 با systemd واقعی) اجرا شده؛ اول Nginx را کامل از رویش پاک کردیم تا نصب را از صفر ببینیم. دستورها با root اجرا شده‌اند؛ روی سرور خودت جلویشان sudo بگذار (همان‌طور که در متن آمده). بخش داکر روی یک موتور داکر جدا اجرا شده است.

مثال ۱: نصب با sudo apt install nginx

Section titled “مثال ۱: نصب با sudo apt install nginx”

اول ببینیم نصب نیست و مخزن کدام نسخه را دارد:

Terminal window
command -v nginx || echo "nginx is not installed"
apt-cache policy nginx | head -n 3
خروجی
nginx is not installed
nginx:
Installed: (none)
Candidate: 1.24.0-2ubuntu7.18

apt-cache policy می‌گوید نسخه‌ی Candidate (همان که نصب خواهد شد) 1.24.0 است. حالا نصب (-y یعنی سؤال «مطمئنی؟» را خودکار بله بگو):

Terminal window
apt-get install -y nginx 2>&1 | grep -v 'Reading database'
echo "کد خروج apt: ${PIPESTATUS[0]}"
خروجی (بخشی از آن)
Process: 17602 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=1/FAILURE)
Oct 04 12:42:45 server systemd[1]: Starting nginx.service - A high performance web server and a reverse proxy server...
Oct 04 12:42:45 server nginx[17602]: nginx: [emerg] socket() [::]:80 failed (97: Address family not supported by protocol)
Oct 04 12:42:45 server nginx[17602]: nginx: configuration file /etc/nginx/nginx.conf test failed
Oct 04 12:42:45 server systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Oct 04 12:42:45 server systemd[1]: nginx.service: Failed with result 'exit-code'.
Oct 04 12:42:45 server systemd[1]: Failed to start nginx.service - A high performance web server and a reverse proxy server.
dpkg: error processing package nginx (--configure):
installed nginx package post-installation script subprocess returned error exit status 1
Processing triggers for man-db (2.12.0-4build2) ...
Processing triggers for ufw (0.36.2-6) ...
Errors were encountered while processing:
nginx
E: Sub-process /usr/bin/dpkg returned an error code (1)
کد خروج apt: 100

بسته‌ها دانلود و باز شدند، سرویس فعال (enable) شد (Created symlink ...multi-user.target.wants/nginx.service) و apt سعی کرد آن را شروع کند، ولی شکست خورد و آخرش Errors were encountered while processing: nginx و کد خروج ۱۰۰. روی بیشتر سرورها این مرحله بی‌مشکل تمام می‌شود و Nginx همان لحظه بالاست؛ ولی همین خطا یک درس واقعی است: نصب شکست نخورده، شروع سرویس شکست خورده. بسته‌ها کامل نصب شده‌اند و فقط مرحله‌ی «پیکربندی (configure)» ناتمام مانده. پس سراغ دلیلش می‌رویم، نه حذف و نصب دوباره.

مثال ۲: عیب‌یابی با systemctl status و journalctl

Section titled “مثال ۲: عیب‌یابی با systemctl status و journalctl”

اولین دستور برای هر سرویسی که درست کار نمی‌کند:

Terminal window
systemctl status nginx --no-pager | head -n 12
خروجی
× nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: failed (Result: exit-code) since Sun 2026-10-04 12:42:45 UTC; 140ms ago
Docs: man:nginx(8)
Process: 17602 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=1/FAILURE)
Oct 04 12:42:45 server systemd[1]: Starting nginx.service - A high performance web server and a reverse proxy server...
Oct 04 12:42:45 server nginx[17602]: nginx: [emerg] socket() [::]:80 failed (97: Address family not supported by protocol)
Oct 04 12:42:45 server nginx[17602]: nginx: configuration file /etc/nginx/nginx.conf test failed
Oct 04 12:42:45 server systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Oct 04 12:42:45 server systemd[1]: nginx.service: Failed with result 'exit-code'.
Oct 04 12:42:45 server systemd[1]: Failed to start nginx.service - A high performance web server and a reverse proxy server.

خط Active: failed وضعیت است و Process: ... ExecStartPre=/usr/sbin/nginx -t ... status=1/FAILURE می‌گوید قبل از شروع، آزمایش تنظیمات (nginx -t) شکست خورده است. چند خط آخر لاگ هم همان‌جاست. برای لاگ کامل سرویس:

Terminal window
journalctl -u nginx --no-pager | grep -E 'emerg|failed' | tail -n 3 | sed -E 's/^[A-Z][a-z]{2} [0-9]+ [0-9:]+ //'
echo "--- همان را مستقیم از nginx -t:"
nginx -t
خروجی
server nginx[17587]: nginx: configuration file /etc/nginx/nginx.conf test failed
server nginx[17602]: nginx: [emerg] socket() [::]:80 failed (97: Address family not supported by protocol)
server nginx[17602]: nginx: configuration file /etc/nginx/nginx.conf test failed
--- همان را مستقیم از nginx -t:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: [emerg] socket() [::]:80 failed (97: Address family not supported by protocol)
nginx: configuration file /etc/nginx/nginx.conf test failed

پیام اصلی این است: socket() [::]:80 failed (97: Address family not supported by protocol). یعنی Nginx می‌خواهد روی IPv6 (آدرس [::]) هم گوش بدهد، ولی هسته‌ی این ماشین IPv6 ندارد. سایت پیش‌فرض Ubuntu دو خط listen دارد؛ یکی برای IPv4 و یکی برای IPv6:

Terminal window
grep -n 'listen' /etc/nginx/sites-available/default | head -n 2
خروجی
22: listen 80 default_server;
23: listen [::]:80 default_server;

روی سروری که IPv6 دارد این دو خط با هم کار می‌کنند. روی سروری که IPv6 خاموش است (بعضی شرکت‌ها و میزبان‌ها خاموشش می‌کنند)، خط دوم را غیرفعال می‌کنیم:

Terminal window
sed -i 's/^\(\s*listen \[::\]:80\)/#\1/' /etc/nginx/sites-available/default
grep -n 'listen' /etc/nginx/sites-available/default | head -n 2
nginx -t
خروجی
22: listen 80 default_server;
23:# listen [::]:80 default_server;
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

# اول خط آن را به کامنت تبدیل کرد و nginx -t حالا موفق است. حالا مرحله‌ی ناتمام نصب را کامل می‌کنیم. dpkg --configure -a همه‌ی بسته‌هایی را که پیکربندی‌شان نیمه‌کاره مانده، دوباره پیکربندی می‌کند:

Terminal window
dpkg --configure -a 2>&1 | grep -v '^$'
echo "--- وضعیت بسته و سرویس:"
dpkg -l nginx | tail -n 1 | awk '{print $1, $2, $3}'
systemctl is-active nginx
systemctl is-enabled nginx
خروجی
Setting up nginx (1.24.0-2ubuntu7.18) ...
--- وضعیت بسته و سرویس:
ii nginx 1.24.0-2ubuntu7.18
active
enabled

ii یعنی «نصب‌شده و پیکربندی‌شده» (اگر ناتمام بود iF یا iU می‌دیدی)، سرویس active و enabled است. درس مهم: وقتی apt خطا می‌دهد، اول ببین کدام مرحله شکست خورده؛ اغلب با یک اصلاح و dpkg --configure -a درست می‌شود.

مثال ۳: systemctl، کنترل سرویس

Section titled “مثال ۳: systemctl، کنترل سرویس”

حالا که Nginx بالاست، systemctl status تصویر کامل را می‌دهد:

Terminal window
systemctl status nginx --no-pager | head -n 9
خروجی
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Sun 2026-10-04 12:42:45 UTC; 31ms ago
Docs: man:nginx(8)
Process: 17642 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Process: 17644 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Main PID: 17645 (nginx)
CGroup: /system.slice/nginx.service
├─17645 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
  • Loaded: فایل سرویس (/usr/lib/systemd/system/nginx.service) و enabled یعنی موقع بوت خودش اجرا می‌شود.
  • Active: active (running) و از کی.
  • Main PID و CGroup: پروسه‌ی master و worker ها (همان‌هایی که در درس قبل با ps دیدیم).

دستورهای کنترل:

Terminal window
systemctl stop nginx
echo "after stop: $(systemctl is-active nginx); curl: $(curl -s -o /dev/null -w '%{http_code}' http://localhost/ || true)"
systemctl start nginx
echo "after start: $(systemctl is-active nginx); curl: $(curl -s -o /dev/null -w '%{http_code}' http://localhost/)"
systemctl disable nginx 2>&1
echo "is-enabled: $(systemctl is-enabled nginx)"
systemctl enable nginx 2>&1
echo "is-enabled: $(systemctl is-enabled nginx)"
خروجی
after stop: inactive; curl: 000
after start: active; curl: 200
Synchronizing state of nginx.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
Executing: /usr/lib/systemd/systemd-sysv-install disable nginx
Removed "/etc/systemd/system/multi-user.target.wants/nginx.service".
is-enabled: disabled
Synchronizing state of nginx.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
Executing: /usr/lib/systemd/systemd-sysv-install enable nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
is-enabled: enabled

بعد از stop، curl اصلاً وصل نشد (کد 000 یعنی جوابی نیامد). disable فقط اجرای خودکار هنگام بوت را برمی‌دارد و سرویس الان را خاموش نمی‌کند؛ enable برعکس. (systemctl enable --now nginx هر دو کار را با هم می‌کند: فعال و همین الان شروع.)

مثال ۴: reload در برابر restart، با یک تنظیم خراب

Section titled “مثال ۴: reload در برابر restart، با یک تنظیم خراب”

بعد از هر تغییر تنظیمات باید Nginx را خبر کنی. دو راه هست و فرقشان حیاتی است. این آزمایش را ببین: یک فایل تنظیمات خراب (یک ; جاافتاده) می‌سازیم و هر دو را امتحان می‌کنیم:

Terminal window
printf 'server {\n listen 8090\n}\n' > /etc/nginx/conf.d/lx-broken.conf
echo "=== reload با تنظیم خراب:"
systemctl reload nginx 2>&1 | head -n 2
echo "سرویس: $(systemctl is-active nginx) | سایت: $(curl -s -o /dev/null -w '%{http_code}' http://localhost/)"
echo "=== restart با تنظیم خراب:"
systemctl restart nginx 2>&1 | head -n 2
echo "سرویس: $(systemctl is-active nginx) | سایت: $(curl -s -o /dev/null -w '%{http_code}' http://localhost/ || true)"
echo "=== اصلاح و شروع دوباره:"
rm /etc/nginx/conf.d/lx-broken.conf
nginx -t 2>&1 | tail -n 1
systemctl start nginx 2>&1 | head -n 1
journalctl -u nginx --no-pager | grep -c 'Start request repeated too quickly'
systemctl reset-failed nginx
systemctl start nginx
echo "سرویس: $(systemctl is-active nginx) | سایت: $(curl -s -o /dev/null -w '%{http_code}' http://localhost/)"
خروجی
=== reload با تنظیم خراب:
Job for nginx.service failed.
See "systemctl status nginx.service" and "journalctl -xeu nginx.service" for details.
سرویس: active | سایت: 200
=== restart با تنظیم خراب:
Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xeu nginx.service" for details.
سرویس: failed | سایت: 000
=== اصلاح و شروع دوباره:
nginx: configuration file /etc/nginx/nginx.conf test is successful
Job for nginx.service failed because the control process exited with error code.
6
سرویس: active | سایت: 200
  • reload با تنظیم خراب شکست خورد ولی سایت بالا ماند (کد ۲۰۰)؛ Nginx تنظیمات تازه را رد کرد و با تنظیمات قبلی ادامه داد.
  • restart با همان تنظیم خراب، Nginx را خاموش کرد و دیگر بالا نیاورد: سایت از دسترس خارج شد (000).

و یک نکته‌ی واقعی دیگر در قسمت آخر: بعد از اصلاح، اولین start هم شکست خورد! لاگ می‌گوید Start request repeated too quickly. systemd اگر سرویسی در مدت کوتاهی (به‌صورت پیش‌فرض ۵ بار در ۱۰ ثانیه) پشت هم شروع شود یا شکست بخورد، جلوی شروع دوباره را موقتاً می‌گیرد تا یک سرویس خراب سیستم را درگیر نکند. ما در همین چند ثانیه چند بار Nginx را شروع کرده بودیم. systemctl reset-failed nginx شمارنده را صفر می‌کند (یا چند ثانیه صبر کن).

قاعده‌ی طلایی: همیشه nginx -t و بعد reload. restart را فقط وقتی لازم است بزن (مثلاً بعد از ارتقای نسخه‌ی Nginx). یک‌خطی رایج: sudo nginx -t && sudo systemctl reload nginx (با &&، اگر آزمایش شکست بخورد reload اجرا نمی‌شود).

مثال ۵: صفحه‌ی پیش‌فرض و فایروال

Section titled “مثال ۵: صفحه‌ی پیش‌فرض و فایروال”

صفحه‌ی خوشامد Nginx از کجا می‌آید؟

Terminal window
curl -s http://localhost/ | grep -o '<title>.*</title>'
ls -l /var/www/html/
grep -E '^\s*(root|index)' /etc/nginx/sites-available/default
خروجی
<title>Welcome to nginx!</title>
total 4
-rw-r--r-- 1 root root 615 Oct 4 12:42 index.nginx-debian.html
root /var/www/html;
index index.html index.htm index.nginx-debian.html;

سایت پیش‌فرض پوشه‌ی /var/www/html را سرو می‌کند و اولین فایل از فهرست index را که پیدا کند (اینجا index.nginx-debian.html) نشان می‌دهد. اگر index.html خودت را در همین پوشه بگذاری، آن را نشان می‌دهد.

روی سرور واقعی، اگر فایروال (ufw، درس فایروال در دوره‌ی لینوکس) روشن است، باید پورت‌های وب را باز کنی. Nginx هنگام نصب پروفایل‌های آماده به ufw اضافه می‌کند:

Terminal window
ufw app list
ufw app info 'Nginx Full'
خروجی
Available applications:
Nginx Full
Nginx HTTP
Nginx HTTPS
OpenSSH
Profile: Nginx Full
Title: Web Server (Nginx, HTTP + HTTPS)
Description: Small, but very powerful and efficient web server
Ports:
80,443/tcp

Nginx HTTP فقط پورت ۸۰، Nginx HTTPS فقط ۴۴۳، و Nginx Full هر دو. دستور باز کردن روی سرور واقعی: sudo ufw allow 'Nginx Full' (و قبلش مطمئن شو SSH هم مجاز است: sudo ufw allow OpenSSH، وگرنه با روشن کردن فایروال خودت را بیرون می‌اندازی).

شکل کلی دستور:

شکل کلی
docker run -d -p 8080:80 nginx:alpine

-d یعنی در پس‌زمینه، -p 8080:80 یعنی «پورت ۸۰۸۰ میزبان را به پورت ۸۰ کانتینر وصل کن» (درس پورت‌ها در دوره‌ی داکر) و nginx:alpine ایمیج رسمی Nginx روی Alpine (کوچک). ما پورت 8091 و اسم lx-nginx را به کار می‌بریم تا با برنامه‌های دیگرت برخورد نکند (پورت ۸۰۸۰ را خود سایت LoopX در حالت داکری استفاده می‌کند):

Terminal window
docker run -d --name lx-nginx -p 8091:80 nginx:alpine > /dev/null
sleep 1
docker ps --filter name=lx-nginx --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}' | sed 's/, \[::\][^ ]*//'
docker exec lx-nginx nginx -v
curl -s -I http://localhost:8091/ | grep -iE '^(HTTP|server)'
docker logs lx-nginx 2>&1 | tail -n 2
خروجی
NAMES IMAGE STATUS PORTS
lx-nginx nginx:alpine Up 1 second 0.0.0.0:8091->80/tcp
nginx version: nginx/1.31.6
HTTP/1.1 200 OK
Server: nginx/1.31.6
2026/10/04 12:37:07 [notice] 1#1: start worker process 24
172.17.0.1 - - [04/Oct/2026:12:37:09 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/8.5.0" "-"
  • نسخه‌ی ایمیج (1.31.x) از نسخه‌ی مخزن Ubuntu (1.24) جدیدتر است؛ این یکی از دلیل‌های استفاده از داکر است. (اگر نسخه‌ی ثابت می‌خواهی، tag دقیق بنویس، مثلاً nginx:1.31-alpine.)
  • docker logs لاگ دسترسی Nginx را نشان می‌دهد؛ در ایمیج رسمی، لاگ‌ها به stdout و stderr کانتینر فرستاده می‌شوند.

سایت خودت را با یک bind mount (درس volume در دوره‌ی داکر) جای صفحه‌ی پیش‌فرض بگذار:

Terminal window
mkdir -p site
echo '<h1>Coming soon: LoopX shop</h1>' > site/index.html
docker rm -f lx-nginx > /dev/null
docker run -d --name lx-nginx -p 8091:80 -v "$PWD/site:/usr/share/nginx/html:ro" nginx:alpine > /dev/null
sleep 1
curl -s http://localhost:8091/
docker rm -f lx-nginx > /dev/null
خروجی
<h1>Coming soon: LoopX shop</h1>

در ایمیج رسمی، پوشه‌ی سایت /usr/share/nginx/html است (نه /var/www/html مثل Ubuntu). :ro یعنی فقط‌خواندنی؛ کانتینر نمی‌تواند فایل‌های سایتت را عوض کند.

پشت پرده: سرویس nginx در systemd چطور تعریف شده؟

Section titled “پشت پرده: سرویس nginx در systemd چطور تعریف شده؟”

systemctl cat فایل سرویس را نشان می‌دهد:

Terminal window
systemctl cat nginx --no-pager | grep -vE '^\s*(#|$)'
خروجی
[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
ConditionFileIsExecutable=/usr/sbin/nginx
[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed
[Install]
WantedBy=multi-user.target
  • ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;': قبل از هر شروع، تنظیمات آزمایش می‌شود (برای همین در مثال ۲ دلیل شکست، ExecStartPre بود).
  • ExecStart: خود Nginx.
  • ExecReload: اول nginx -t و بعد nginx -s reload. یعنی systemctl reload در واقع به پروسه‌ی master یک سیگنال می‌فرستد.
  • PIDFile=/run/nginx.pid: شماره‌ی پروسه‌ی master اینجا نوشته می‌شود.

خود Nginx هم دستور کنترل دارد: nginx -s SIGNAL. reload همان سیگنال HUP است که به master فرستاده می‌شود:

Terminal window
echo "master: $(cat /run/nginx.pid) | workers: $(pgrep -d ' ' -f 'nginx: worker')"
kill -HUP "$(cat /run/nginx.pid)"
sleep 1
echo "master: $(cat /run/nginx.pid) | workers: $(pgrep -d ' ' -f 'nginx: worker')"
خروجی
master: 17827 | workers: 17828 17829 17830 17831
master: 17827 | workers: 17849 17850 17851 17852

با kill -HUP دستی همان اتفاق reload افتاد: worker های تازه، master ثابت. روی سرور systemd‌دار همیشه از systemctl استفاده کن (تا systemd وضعیت را بداند)؛ ولی داخل کانتینر داکر که systemd نیست، nginx -s reload راه اصلی است (درس Nginx در داکر).

دستورهای سرویس:

دستور کار
sudo apt install nginx نصب (و فعال‌سازی و شروع سرویس)
sudo systemctl status nginx وضعیت، PID، چند خط آخر لاگ
sudo systemctl start / stop nginx شروع / توقف
sudo systemctl reload nginx خواندن دوباره‌ی تنظیمات بدون قطع (با تنظیم خراب، قبلی می‌ماند)
sudo systemctl restart nginx توقف و شروع دوباره (با تنظیم خراب، خاموش می‌ماند)
sudo systemctl enable / disable nginx اجرای خودکار هنگام بوت، روشن / خاموش
sudo systemctl enable --now nginx فعال و همین الان شروع
systemctl is-active / is-enabled nginx جواب یک‌کلمه‌ای (مناسب اسکریپت)
sudo journalctl -u nginx لاگ‌های systemd برای nginx
sudo nginx -t آزمایش تنظیمات
sudo nginx -s reload reload با سیگنال (داخل کانتینر)
sudo dpkg --configure -a تمام کردن پیکربندی بسته‌های نیمه‌کاره
sudo systemctl reset-failed nginx صفر کردن شمارنده‌ی شکست (بعد از Start request repeated too quickly)
sudo apt remove nginx / purge nginx حذف برنامه / حذف با فایل‌های تنظیمات

مسیرهای مهم در Ubuntu:

مسیر چیست
/etc/nginx/ همه‌ی تنظیمات (درس بعد)
/var/www/html/ سایت پیش‌فرض
/var/log/nginx/access.log، error.log لاگ‌ها (درس لاگ‌ها)
/run/nginx.pid PID پروسه‌ی master
/usr/lib/systemd/system/nginx.service فایل سرویس

۱) پورت ۸۰ را برنامه‌ی دیگری گرفته

Section titled “۱) پورت ۸۰ را برنامه‌ی دیگری گرفته”
Terminal window
systemctl stop nginx
(exec python3 -m http.server 80 --bind 0.0.0.0) > /dev/null 2>&1 &
sleep 1
systemctl reset-failed nginx
systemctl start nginx 2>&1 | head -n 1
journalctl -u nginx --no-pager | grep 'Address already in use' | tail -n 1 | sed -E 's/^[A-Z][a-z]{2} [0-9]+ [0-9:]+ //'
ss -tlnp 'sport = :80' | tail -n 1 | grep -o 'users:.*'
pkill -f 'http.server 80'
sleep 1
systemctl reset-failed nginx
systemctl start nginx && echo "nginx: $(systemctl is-active nginx)"
خروجی
Job for nginx.service failed because the control process exited with error code.
server nginx[17865]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
users:(("python3",pid=17858,fd=3))
nginx: active

bind() to 0.0.0.0:80 failed (98: Address already in use): برنامه‌ی دیگری (اینجا پایتون؛ در دنیای واقعی معمولاً Apache که از قبل نصب بوده) پورت را گرفته. ss -tlnp اسم پروسه را نشان داد. راه‌حل: برنامه‌ی دیگر را متوقف یا روی پورت دیگری ببر (sudo systemctl disable --now apache2).

Terminal window
su - ali -c 'nginx -t' 2>&1
خروجی
2026/10/04 12:42:52 [warn] 17889#17889: the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /etc/nginx/nginx.conf:1
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
2026/10/04 12:42:52 [emerg] 17889#17889: open() "/run/nginx.pid" failed (13: Permission denied)
nginx: configuration file /etc/nginx/nginx.conf test failed

کاربر معمولی به لاگ و فایل PID دسترسی ندارد و آزمایش شکست می‌خورد؛ این خطای تنظیمات نیست. راه‌حل: sudo nginx -t.

مثال ۴: با تنظیم خراب، restart سایت را پایین می‌آورد. راه‌حل: sudo nginx -t && sudo systemctl reload nginx.

۴) حذف و نصب دوباره به‌جای خواندن خطا

Section titled “۴) حذف و نصب دوباره به‌جای خواندن خطا”

مثال ۱ و ۲: apt خطا داد ولی بسته‌ها نصب بودند. حذف و نصب دوباره همان خطا را تکرار می‌کرد. راه‌حل: systemctl status، journalctl -u nginx و nginx -t؛ بعد اصلاح و dpkg --configure -a.

روی سرور، Nginx بالاست و curl localhost جواب می‌دهد، ولی از مرورگر خودت صفحه باز نمی‌شود. راه‌حل: sudo ufw status و sudo ufw allow 'Nginx Full' (و فایروال پنل ابری‌ات، اگر داری).

✎ تمرینآسان

تمرین اصلی درس: Nginx را نصب کن، صفحه‌ی پیش‌فرض را با curl ببین، بعد index.html خودت را در /var/www/html بگذار و ثابت کن صفحه عوض شده. در پایان مطمئن شو سرویس enabled است (یعنی بعد از ریبوت هم بالا می‌آید).

دیدن جواب
Terminal window
echo "--- قبل:"
curl -s http://localhost/ | grep -o '<title>.*</title>'
echo '<!doctype html><title>My first site</title><h1>Hello, Nginx!</h1>' > /var/www/html/index.html
echo "--- بعد:"
curl -s http://localhost/ | grep -o '<title>.*</title>'
systemctl is-enabled nginx
rm /var/www/html/index.html
خروجی
--- قبل:
<title>Welcome to nginx!</title>
--- بعد:
<title>My first site</title>
enabled

روی سرور خودت: sudo apt install nginx، بعد curl http://localhost یا آدرس IP سرور در مرورگر، و echo '...' | sudo tee /var/www/html/index.html. چون index.html در فهرست index قبل از index.nginx-debian.html آمده، Nginx همان را نشان داد. لازم نیست Nginx را reload کنی؛ فایل‌های سایت با هر درخواست از دیسک خوانده می‌شوند (فقط تغییر تنظیمات reload می‌خواهد).

✎ تمرینمتوسط

با داکر دو Nginx همزمان اجرا کن: یکی با نسخه‌ی nginx:alpine روی پورت ۸۰۹۲ و یکی با سایت خودت (bind mount) روی پورت ۸۰۹۳. با docker ps هر دو را ببین، با curl به هر دو درخواست بفرست، و با docker logs ثابت کن هر کدام لاگ خودش را دارد. در پایان هر دو را پاک کن.

دیدن جواب
Terminal window
mkdir -p mysite && echo '<h1>my site on 8093</h1>' > mysite/index.html
docker run -d --name lx-ng-a -p 8092:80 nginx:alpine > /dev/null
docker run -d --name lx-ng-b -p 8093:80 -v "$PWD/mysite:/usr/share/nginx/html:ro" nginx:alpine > /dev/null
sleep 1
docker ps --filter name=lx-ng- --format '{{.Names}} {{.Ports}}' | sed 's/, \[::\][^ ]*//' | sort
curl -s http://localhost:8092/ | grep -o '<title>.*</title>'
curl -s http://localhost:8093/
curl -s -o /dev/null http://localhost:8093/missing.html
echo "--- لاگ lx-ng-a:"
docker logs lx-ng-a 2>/dev/null | grep -c 'GET /'
echo "--- لاگ lx-ng-b:"
docker logs lx-ng-b 2>/dev/null | grep 'GET /' | awk '{print $6, $7, $9}'
docker rm -f lx-ng-a lx-ng-b > /dev/null
خروجی
lx-ng-a 0.0.0.0:8092->80/tcp
lx-ng-b 0.0.0.0:8093->80/tcp
<title>Welcome to nginx!</title>
<h1>my site on 8093</h1>
--- لاگ lx-ng-a:
1
--- لاگ lx-ng-b:
"GET / 200
"GET /missing.html 404

هر کانتینر یک Nginx کاملاً جداست: پورت جدا، فایل‌های جدا، لاگ جدا. در لاگ lx-ng-b درخواست موفق (۲۰۰) و درخواست فایل ناموجود (۴۰۴) را می‌بینی. docker logs فقط stdout (لاگ دسترسی) را به grep داد چون stderr را با 2>/dev/null دور ریختیم.

✎ تمرینسخت

یک اسکریپت کوچک safe-reload.sh بنویس که: ۱) nginx -t بزند و اگر شکست خورد، خطا را نشان دهد و با کد ۱ خارج شود (بدون reload)؛ ۲) اگر موفق بود reload کند؛ ۳) بعد با curl بررسی کند سایت جواب ۲۰۰ می‌دهد. یک بار با تنظیمات سالم و یک بار با یک فایل خراب در conf.d اجرایش کن و نشان بده سایت در هر دو حالت بالا ماند.

دیدن جواب
cat > /usr/local/bin/safe-reload.sh <<'EOF'
#!/usr/bin/env bash
# safe-reload.sh: test nginx config, reload only if valid, then check the site
set -euo pipefail
url=${1:-http://localhost/}
if ! out=$(nginx -t 2>&1); then
echo "config test FAILED, not reloading:" >&2
echo "$out" | sed 's/^/ /' >&2
exit 1
fi
systemctl reload nginx
sleep 1
code=$(curl -s -o /dev/null -w '%{http_code}' "$url")
echo "reloaded; $url -> HTTP $code"
[[ $code == 200 ]]
EOF
chmod +x /usr/local/bin/safe-reload.sh
echo "=== تنظیمات سالم:"
safe-reload.sh; echo "کد خروج: $?"
echo "=== تنظیمات خراب:"
printf 'server { listen 8090 }\n' > /etc/nginx/conf.d/lx-bad.conf
safe-reload.sh; echo "کد خروج: $?"
echo "سایت: $(curl -s -o /dev/null -w '%{http_code}' http://localhost/)"
rm /etc/nginx/conf.d/lx-bad.conf /usr/local/bin/safe-reload.sh
خروجی
=== تنظیمات سالم:
reloaded; http://localhost/ -> HTTP 200
کد خروج: 0
=== تنظیمات خراب:
config test FAILED, not reloading:
2026/10/04 12:42:53 [emerg] 17913#17913: unexpected "}" in /etc/nginx/conf.d/lx-bad.conf:1
nginx: configuration file /etc/nginx/nginx.conf test failed
کد خروج: 1
سایت: 200

if ! out=$(nginx -t 2>&1) هم خروجی را نگه می‌دارد و هم شکست را بررسی می‌کند (درس مدیریت خطا). با فایل خراب، اسکریپت پیام دقیق Nginx را نشان داد و reload نکرد؛ سایت با همان تنظیمات قبلی بالا ماند.

⚡ بررسی سریع

تنظیمات Nginx را عوض کرده‌ای و نمی‌دانی درست است یا نه. امن‌ترین کار؟

؟ آزمونک
  1. apt install nginx با «Errors were encountered while processing: nginx» تمام شد. اولین کار؟

  2. فرق systemctl disable nginx و systemctl stop nginx؟

  3. با یک فایل تنظیمات خراب، کدام دستور سایت را از دسترس خارج می‌کند؟

  4. nginx شروع نمی‌شود و در journalctl می‌بینی bind() to 0.0.0.0:80 failed (98: Address already in use). یعنی چه؟

  5. در docker run -d -p 8080:80 nginx:alpine، عدد ۸۰۸۰ چیست؟

  6. systemctl reload nginx در عمل چه می‌کند؟

  • نصب روی سرور: sudo apt install nginx؛ سرویس enabled و شروع می‌شود و سایت پیش‌فرض در /var/www/html است. نسخه‌ی مخزن را با apt-cache policy nginx ببین.
  • کنترل: systemctl status|start|stop|enable|disable nginx؛ is-active و is-enabled برای اسکریپت.
  • بعد از تغییر تنظیمات: sudo nginx -t && sudo systemctl reload nginx. reload بدون قطع است و با تنظیم خراب قبلی را نگه می‌دارد؛ restart با تنظیم خراب سایت را پایین می‌آورد.
  • عیب‌یابی: systemctl status nginx ← journalctl -u nginx ← nginx -t. خطاهای رایج: پورت گرفته‌شده (Address already in use، با ss -tlnp)، IPv6 نبودن (Address family not supported)، اجرای بدون sudo. بعد از اصلاح: dpkg --configure -a.
  • فایروال: sudo ufw allow 'Nginx Full' (و SSH را فراموش نکن).
  • داکر: docker run -d -p 8080:80 nginx:alpine؛ سایت در /usr/share/nginx/html با -v ...:ro؛ لاگ‌ها در docker logs؛ داخل کانتینر nginx -s reload.
برگه‌ی تقلب این درس
دستورکاری که می‌کند
sudo apt install nginxنصب روی Ubuntu
apt-cache policy nginxنسخه‌ی موجود در مخزن
sudo systemctl status nginxوضعیت و چند خط آخر لاگ
sudo systemctl enable --now nginxفعال در بوت و شروع همین الان
sudo nginx -t && sudo systemctl reload nginxآزمایش و اعمال امن تنظیمات
sudo journalctl -u nginx --no-pager | tailلاگ سرویس برای عیب‌یابی
sudo dpkg --configure -aکامل کردن نصب نیمه‌کاره
sudo ss -tlnp "sport = :80"چه کسی پورت ۸۰ را گرفته؟
sudo ufw allow 'Nginx Full'باز کردن ۸۰ و ۴۴۳ در فایروال
docker run -d -p 8080:80 nginx:alpineNginx در داکر
docker run -d -p 8091:80 -v "$PWD/site:/usr/share/nginx/html:ro" nginx:alpineسرو کردن پوشه‌ی خودت
docker exec CONTAINER nginx -s reloadreload داخل کانتینر