WIUNIX ACADEMY
آموزش نصب وردپرس با Nginx و کش FastCGI در اوبونتو و دبیان
صفحهٔ 2 از 4؛ مراحل قبلی و پیشنیازها را پیش از ادامه مرور کن.
آموزش متناسب با محیط تو
کجا اجرا میکنی؟
سیستمعامل و نسخه را انتخاب کن تا مراحل، دستورها و راهحلها برای همان محیط نمایش داده شوند.
آموزش متناسب با مقادیر تو
تنظیمات این آموزش
مقادیر نمونه را برای محیط خودت تنظیم کن؛ متن و دستورهای مرتبط با هم تغییر میکنند. رمز، کلید خصوصی و توکن وارد نکن. مقادیر فقط در همین زبانه نگهداری میشوند و به سرور یا لینک اشتراکگذاری فرستاده نمیشوند. پیش از اجرا، DNS، گواهیها و سیاست شبکهٔ واقعی را بررسی کن.
ویرایش 4 مقدار این آموزش
قدم بعدی
کنترل نحو و مجوزها
این کنترلها محتوای خصوصی تنظیمات را چاپ نمیکنند.
ترمینال Bash سرور وردپرس، حساب مدیر دارای sudo.
(
set -euo pipefail
sudo php8.2 -l /var/www/wordpress/wp-config.php
if sudo grep -q REPLACE_ /var/www/wordpress/wp-config.php; then
echo 'Replace all configuration placeholders first' >&2; exit 1
fi
sudo -u wp-php test -r /var/www/wordpress/wp-config.php
sudo -u wp-php test ! -w /var/www/wordpress/wp-config.php
sudo -u wp-php test -w /var/www/wordpress/wp-content/uploads
)
PHP تنظیمات را میخواند اما نمینویسد؛ uploads قابلنوشتن است و جایگاه خالی باقی نمانده.
آمادهسازی پوشه و سیاست کش
پوشه در اختیار worker است. تنظیم پیشفرض توزیع، conf.d را داخل http وارد میکند؛ آزمون کامل این فرض را بررسی میکند. map را داخل server نگذارید.
ترمینال Bash سرور وردپرس، حساب مدیر دارای sudo.
sudo install -d -o www-data -g www-data -m 0700 /var/cache/nginx/wordpress
sudo nano /etc/nginx/conf.d/wordpress-cache.conf
بررسی موفق است؛ در صورت خطا، پیش از ادامه علت را برطرف کنید.
قدم بعدی
کش فقط برای صفحات عمومیِ مشخص
تنها صفحهٔ نخست و sample-page مجازند. تمام مسیرهای دیگر، از جمله ورود و مدیریت، پیشنمایش، API، cron، خرید و حساب، خوراک، جستوجو و برگهٔ رمزدار خارج از فهرستاند. هر کوکی، Authorization، پارامتر، روش غیر از GET یا مسیر percent-encoded هم خواندن و هم نوشتن کش را متوقف میکند. کوکی ورود، رمز نوشته، دیدگاه و نشست ناشناختهٔ افزونه نیز پوشش داده میشود. پیش از خصوصی یا رمزدارکردن صفحه، آن را از فهرست بردارید و نسل کلید را عوض کنید. محتوای وابسته به مکان، دستگاه یا کاربر را بدون بررسی جداگانهٔ کلید و هدرها اضافه نکنید. حتی UTM عمداً bypass میشود؛ نادیدهگرفتن آن نیازمند بررسی برنامه است.
محتوای فایل؛ در فایل مشخصشده ذخیره شود، نه در پوسته.
# http context: included by the stock Debian/Ubuntu nginx.conf
fastcgi_cache_path /var/cache/nginx/wordpress levels=1:2 keys_zone=WORDPRESS:20m
max_size=512m inactive=10m use_temp_path=off;
map $request_method $wp_skip_method { default 1; GET 0; }
# Every cookie is private until separately assessed, including WordPress,
# wp-postpass, comment_author, WooCommerce and plugin session cookies.
map $http_cookie $wp_skip_cookie { default 1; "" 0; }
map $http_authorization $wp_skip_auth { default 1; "" 0; }
map $args $wp_skip_args { default 1; "" 0; }
# Opt in ONLY known public HTML URLs. Everything else stays dynamic.
map $request_uri $wp_skip_route {
default 1;
"/" 0;
"/sample-page/" 0;
}
# Defense in depth for the standard private/dynamic endpoints.
map $request_uri $wp_private_path {
default 0;
~*^/(wp-admin|wp-login\.php|wp-cron\.php|wp-json|xmlrpc\.php|cart|checkout|my-account|account)(/|\?|$) 1;
~*% 1;
}
سقف کش ۵۱۲ و ناحیهٔ کلید ۲۰ مگابایت تعریف شده؛ کش سایت هنوز خاموش است.
آمادهسازی HTTP فقط برای چالش
پورت ۸۰ باید برای مرجع صدور گواهی باز باشد. اگر گواهی از قبل مدیریت میشود، از همان روند مجاز و مسیر درست استفاده کنید و صدور موازی نسازید.
ترمینال Bash سرور وردپرس، حساب مدیر دارای sudo.
sudo install -d -o root -g root -m 0755 /var/lib/letsencrypt/.well-known/acme-challenge
sudo nano /etc/nginx/sites-available/wordpress
بررسی موفق است؛ در صورت خطا، پیش از ادامه علت را برطرف کنید.
قدم بعدی
نوشتن سایت موقت HTTP
دامنه را عوض کنید. در HTTP فقط چالش ACME ارائه میشود و وردپرس در دسترس عمومی نیست.
محتوای فایل؛ در فایل مشخصشده ذخیره شود، نه در پوسته.
server {
listen 80;
listen [::]:80;
server_name blog.example.com;
location ^~ /.well-known/acme-challenge/ {
root /var/lib/letsencrypt;
default_type text/plain;
try_files $uri =404;
}
location / { return 404; }
}
بررسی موفق است؛ در صورت خطا، پیش از ادامه علت را برطرف کنید.
قدم بعدی
فعالسازی و آزمون چالش
اگر لینک سایت از قبل وجود دارد، علت را بررسی کنید. reload فقط پس از اعتبارسنجی انجام میشود. پاسخ چالش را از بیرون سرور هم ببینید؛ دسترسی محلی برای اثبات دسترسی CA کافی نیست.
ترمینال Bash سرور وردپرس، حساب مدیر دارای sudo.
(
set -euo pipefail
sudo test ! -e /etc/nginx/sites-enabled/wordpress
sudo ln -s /etc/nginx/sites-available/wordpress /etc/nginx/sites-enabled/wordpress
sudo nginx -t
sudo systemctl reload nginx
printf 'acme-path-check\n' | sudo tee /var/lib/letsencrypt/.well-known/acme-challenge/academy-check >/dev/null
curl -fsS --connect-timeout 5 --max-time 15 http://blog.example.com/.well-known/acme-challenge/academy-check | grep -Fx acme-path-check
)
اعتبارسنجی موفق است و بدنه دقیقاً acme-path-check است.
قدم بعدی
دریافت TLS پیش از نصب وردپرس
ایمیل و دامنه را عوض کنید و پیش از agree-tos شرایط CA را بخوانید و بپذیرید. فرمان حساب و گواهی واقعی ایجاد میکند. چالش از HTTP موجود میگذرد. شکست صدور پیش از ویرایشگر متوقف میشود؛ پس از موفقیت پنل بعدی را جایگزین کنید. نصب را با استثنای خطای گواهی مرورگر یا curl -k ادامه ندهید.
ترمینال Bash سرور وردپرس، حساب مدیر دارای sudo.
(
set -euo pipefail
sudo certbot certonly --webroot -w /var/lib/letsencrypt -d blog.example.com --email YOUR_REAL_EMAIL --agree-tos
sudo test -s /etc/letsencrypt/live/blog.example.com/fullchain.pem
sudo test -s /etc/letsencrypt/live/blog.example.com/privkey.pem
sudo nano /etc/nginx/sites-available/wordpress
)
بررسی موفق است؛ در صورت خطا، پیش از ادامه علت را برطرف کنید.
قدم بعدی
حفاظت از نصب با TLS و محدودیت IP
دامنه، مسیر گواهی و IP مدیر را عوض کنید و کش را خاموش نگه دارید. محدودیت سطح server همهٔ فایلهای ایستا و PHP را میپوشاند. اجرای PHP در uploads و دریافت تنظیمات و فایلهای مخفی ممنوع است. HTTP پس از چالش به دامنهٔ ثابت HTTPS میرود.
محتوای فایل؛ در فایل مشخصشده ذخیره شود، نه در پوسته.
server {
listen 80;
listen [::]:80;
server_name blog.example.com;
location ^~ /.well-known/acme-challenge/ {
root /var/lib/letsencrypt;
default_type text/plain;
try_files $uri =404;
}
location / { return 301 https://blog.example.com$request_uri; }
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name blog.example.com;
if ($host != blog.example.com) { return 444; }
ssl_certificate /etc/letsencrypt/live/blog.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/blog.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
root /var/www/wordpress;
index index.php;
client_max_body_size 16m;
# Temporary installation gate. Replace with YOUR actual public admin IP.
allow 203.0.113.10;
deny all;
location / { try_files $uri $uri/ /index.php?$args; }
location ~* ^/wp-content/uploads/.*\.php(?:/|$) { return 403; }
location = /wp-config.php { deny all; }
location ~ /\. { deny all; }
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param HTTPS on;
fastcgi_pass unix:/run/php/wordpress.sock;
fastcgi_cache off;
fastcgi_cache_key "$scheme|$request_method|$host|$request_uri|wp-v1";
fastcgi_cache_methods GET;
fastcgi_cache_valid 200 60s;
fastcgi_cache_lock on;
fastcgi_cache_bypass $wp_skip_method $wp_skip_cookie $wp_skip_auth $wp_skip_args $wp_skip_route $wp_private_path;
fastcgi_no_cache $wp_skip_method $wp_skip_cookie $wp_skip_auth $wp_skip_args $wp_skip_route $wp_private_path;
add_header X-WP-Cache $upstream_cache_status always;
}
}
بررسی موفق است؛ در صورت خطا، پیش از ادامه علت را برطرف کنید.
قدم بعدی
آزمون TLS و دسترسی نصبکننده
اعتبارسنجی و reload روی سرور است. اگر خروجی سرور مجاز نیست، curl HTTPS را از سیستم مجاز اجرا کنید. شما باید نصبکننده را با ۲۰۰ و مبدأ مستقلِ غیرمجاز باید ۴۰۳ ببیند. برای عبور آزمون مجوز عمومی ندهید.
ترمینال سرور، مدیر دارای sudo.
(
set -euo pipefail
sudo nginx -t
sudo systemctl reload nginx
sudo ss -lntp 'sport = :443'
)
گواهی معتبر با دامنه تطبیق دارد و نصبکننده فقط از IP تعیینشده باز است.
کنترل پاسخ ۲۰۰ نصبکننده از کلاینت مجاز
از سیستم مجاز اجرا کنید؛ کنترل گواهی روشن بماند. از شبکهٔ مستقل غیرمجاز همین بررسی را با انتظار ۴۰۳ تکرار کنید؛ آن پاسخ منفی مجوز ادامهٔ نصب از مبدأ غیرمجاز نیست.
سیستم مجاز، Bash دارای curl.
(
set -euo pipefail
work=$(mktemp -d)
code=$(curl -sS --connect-timeout 5 --max-time 20 -D "$work/installer.h" -o "$work/installer.html" -w '%{http_code}' https://blog.example.com/wp-admin/install.php)
[ "$code" = 200 ]
grep -F WordPress "$work/installer.html"
)
HTTPS معتبر، پاسخ دقیق ۲۰۰ و بدنهٔ واقعی نصبکننده.
قدم بعدی
تکمیل نصب پشت محدودیت IP
از سیستم مجاز، نشانی نصب را باز کنید. عنوان سایت، نام مدیر غیرپیشفرض، رمز قوی و ایمیل واقعی را بدهید؛ نصب را تمام کنید و پیشخوان را ببینید. اطلاعات ورود در شواهد ثبت نشود. در STAGING برگهٔ نمونهٔ موجود را ویرایش کنید، نه اینکه نامک تکراری بسازید؛ نامک sample-page و متن PUBLIC_CACHE_MARKER باشد. برگهٔ جداگانهٔ Home با متن PUBLIC_HOME_MARKER را در تنظیمات ← خواندن، صفحهٔ نخست ایستا انتخاب کنید. پیوند یکتا را «نام نوشته» بگذارید و ذخیره کنید. برگهٔ sample-page عمومی بماند؛ برگهٔ رمزدار جدا با نامک locked-test و متن LOCKED_CONTENT_MARKER بسازید. نام نمایشی دو حساب آزمایشی CACHE_USER_A و CACHE_USER_B باشد و نوار ابزار سایت در شناسنامهٔ هر دو روشن شود. هر حساب باید نام خودش و پنجرهٔ خصوصی هیچکدام را نشان دهد. آزمونهای بعدی بر همین تفاوت واقعی بدنه تکیه دارند.
نوار نشانی مرورگر سیستم مجاز؛ نه پوستهٔ سرور.
https://blog.example.com/wp-admin/install.php
پیشخوان و جدولها آمادهاند و برگههای عمومی و رمزدارِ جدا، با کش خاموش درست نمایش داده میشوند.
قدم بعدی
بررسی دیتابیس و بدنهٔ عمومی
curl از IP مجاز اجرا شود. عنوان واقعی سایت را جایگزین کنید. پاسخ ۲۰۰ و بدنهٔ منطبق لازم است؛ هدایت به نصب موفقیت نیست.
ترمینال Bash سرور وردپرس، حساب مدیر دارای sudo.
(
set -euo pipefail
code=$(curl -sS --connect-timeout 5 --max-time 20 -o /tmp/wp-installed-public.html -w '%{http_code}' https://blog.example.com/)
[ "$code" = 200 ]
grep -F 'YOUR_PUBLIC_SITE_TITLE' /tmp/wp-installed-public.html
sudo mariadb wordpress -e "SHOW TABLES LIKE 'wp_options';"
)
عنوان در صفحهٔ نخست است و wp_options وجود دارد.