
به اشتراک بگذارید

به اشتراک بگذارید
نصب وردپرس روی سرور مجازی یعنی وبسرور، مفسر PHP و دیتابیس را خودتان روی یک ماشین لینوکسی سوار کنید. وردپرس بدون واسطه کنترل پنل بالا میآید. این راهنما همین مسیر را با Nginx، PHP-FPM و MariaDB روی Ubuntu 24.04 جلو میبرد؛ از اولین دستور apt تا گواهی HTTPS و بکاپ.
| مرحله | ابزار اصلی | نشانه درست بودن |
|---|---|---|
| آمادهسازی سرور | دستور apt و رکورد DNS | دامنه به IP سرور اشاره کند |
| نصب سرویسها | بستههای nginx و php8.3-fpm | هر سه سرویس active باشند |
| دیتابیس و فایلها | دستورهای mariadb و chown | مالکیت پوشه با www-data |
| سرور بلاک و نصب | فایل sites-available | صفحه نصب وردپرس باز شود |
| بعد از نصب | فایروال، certbot و بکاپ | بازگردانی آزمایشی موفق |
💡 نکته کلیدی
وردپرس یک برنامه PHP است و برای اجرا به وبسرور، مفسر PHP و دیتابیس نیاز دارد.
✅ نسخهها را از مستندات رسمی وردپرس بردارید.
✅ وبداده امکان تست ساعتی رایگان سرور را میدهد؛ یک بار تمرین کنید.
فرق این مسیر با هاست اشتراکی در یک جمله خلاصه میشود: هیچکس جای شما تصمیم نمیگیرد. نسخه PHP، تعداد پروسههای FPM و مجوز پوشهها را خودتان انتخاب میکنید و همان انتخابها بعداً در قالب خطا برمیگردند. پس از جایی شروع میکنیم که اغلب آموزشها از آن میپرند: پیشنیازها.
📌 آنچه در این مقاله میخوانید
◀️ پیشنیازها؛ سیستمعامل، منابع و دامنه
◀️ نصب Nginx، PHP-FPM و MariaDB
◀️ ساخت دیتابیس و سرور بلاک Nginx
◀️ امنیت، HTTPS و بکاپ پس از نصب

پیش از اولین دستور، چهار چیز باید آماده باشد. توزیعی با پشتیبانی بلندمدت مثل Ubuntu 24.04 LTS، دسترسی sudo از طریق SSH، دامنهای با رکورد A و AAAA به IP سرور، و نسخههای سازگار PHP و دیتابیس. اگر یکی آماده نباشد، مرحله بعد با خطا متوقف میشود.
انتخاب بین cPanel و نصب دستی سلیقهای نیست. تفاوت در هزینه لایسنس، مصرف منابع و میزان کنترل روی پیکربندی است. جدول زیر این سه را کنار هم میگذارد.
| معیار | نصب دستی با Nginx و PHP-FPM | نصب روی کنترل پنل |
|---|---|---|
| هزینه نرمافزار | بدون لایسنس تجاری | نیازمند لایسنس تجاری |
| سرویسهای در حال اجرا | فقط آنچه نصب کردهاید | سرویسهای پنل هم اجرا میشوند |
| کنترل روی پیکربندی | کامل؛ هر تنظیم دست شماست | محدود به رابط پنل |
| نگهداری و وصله امنیتی | بر عهده شما | بخشی با پنل انجام میشود |
اگر به رابط گرافیکی عادت کردهاید، مسیر کوتاهتر همان نصب وردپرس در سیپنل است. اما اگر چند سایت دارید یا تنظیمات اختصاصی Nginx میخواهید، مسیر دستی انعطاف بیشتری میدهد.
طبق صفحه الزامات رسمی وردپرس، نسخه پیشنهادی PHP برابر 8.3 یا بالاتر است. دیتابیس باید MariaDB نسخه 10.11 یا MySQL نسخه 8.0 به بالا باشد. همان صفحه Apache یا Nginx را پیشنهاد و پشتیبانی از HTTPS را توصیه میکند.
این نسخهها را در صفحه الزامات وردپرس ببینید. عادت خوبی است پیش از هر نصب تازه یک بار همین صفحه را باز کنید.
رکورد A و AAAA دامنه را به IP سرور ببرید و از همان سرور با SSH وارد شوید. نام میزبان و منطقه زمانی را هم همین ابتدا تنظیم کنید؛ لاگها و زمانبند تمدید گواهی به ساعت درست سرور تکیه میکنند.
# اتصال و آمادهسازی اولیه
ssh root@SERVER_IP
hostnamectl set-hostname web1.example.ir
timedatectl set-timezone Asia/Tehran
apt update && apt -y install bind9-dnsutils
# بررسی اینکه دامنه به همین سرور اشاره میکند
dig +short A example.ir
dig +short AAAA example.ir
⚠️ دو نکته که بعداً وقت میگیرند
در چالش HTTP-01 که حالت پیشفرض Certbot است، صدور گواهی به دامنهای نیاز دارد که روی پورت 80 به همین سرور برسد؛ مستندات Let’s Encrypt میگوید این چالش فقط روی پورت 80 انجام میشود. چالش DNS-01 این شرط را ندارد و با یک رکورد TXT کار میکند.
🔶 سروری که این مسیر را ساده میکند
سرور مجازی ایران وبداده در دیتاسنتر تهران و روی شبکه رسپینا میزبانی میشود. هر سرور IP مستقیم دارد که از اینترنت بینالملل هم در دسترس است و IPv4 و IPv6 پشتیبانی میشود. پلنها را در صفحه سرور مجازی ایران ببینید.
سه سرویس را از مخزن رسمی توزیع نصب میکنید: Nginx بهعنوان وبسرور، بسته php8.3-fpm بهعنوان مفسر و mariadb-server بهعنوان دیتابیس. تا وقتی systemctl برای هر سه active نشان نمیدهد، سراغ فایلهای وردپرس نروید.
اگر apt update با خطای Timeout متوقف شد، مشکل از دسترسی به مخزن خارجی است، نه از سرور. راه پایدار، معرفی یک میرور داخلی و نگهداشتن یک نسخه از فایل منابع بهعنوان بکاپ است.
cp /etc/apt/sources.list.d/ubuntu.sources /root/ubuntu.sources.bak
apt update && apt -y upgrade
apt -y install curl tar unzip ca-certificates
دستور زیر وبسرور، مفسر و دیتابیس را یکجا نصب میکند. بستههای جانبی PHP کامل آورده شدهاند تا بعداً مجبور به نصب تکتک آنها و راهاندازی دوباره FPM نشوید.
apt -y install nginx mariadb-server \
php8.3-fpm php8.3-mysql php8.3-curl php8.3-gd php8.3-mbstring \
php8.3-xml php8.3-zip php8.3-intl php8.3-imagick
systemctl enable --now nginx php8.3-fpm mariadb
systemctl is-active nginx php8.3-fpm mariadb
در عمل، سنگینترین تصمیم در نصب وردپرس روی سرور مجازی همین انتخاب نسخه PHP و بستههای جانبی آن است. بقیه مراحل تکرارشدنی و قابل اسکریپتکردن هستند.
طبق مستندات رسمی PHP، پارامتر pm تعیین میکند مدیر پروسه چطور فرزندها را کنترل کند و سه مقدار static، dynamic و ondemand را میپذیرد. در حالت dynamic، تعداد پروسهها با چهار پارامتر تنظیم میشود. همان مستندات تأکید میکند pm.max_children سقف درخواستهای همزمان را هم مشخص میکند.
| حالت pm | رفتار پروسهها | مناسب برای |
|---|---|---|
| static | تعداد پروسه ثابت و برابر pm.max_children | بار یکنواخت |
| dynamic | تعداد پروسه بین حد پایین و سقف | اکثر سایتهای وردپرسی |
| ondemand | پروسه فقط هنگام رسیدن درخواست | چند سایت کمبازدید |
به جای کپی کردن عدد از آموزشها، مصرف واقعی را اندازه بگیرید. دستور زیر میانگین حافظه هر پروسه FPM را بر حسب مگابایت میدهد. رم قابل تخصیص یعنی کل رم منهای سهم سیستم و MariaDB؛ سقف پروسهها حاصل تقسیم آن بر میانگین است.
# میانگین مصرف حافظه هر پروسه php-fpm (مگابایت)
ps --no-headers -o rss -C php-fpm8.3 \
| awk '{s+=$1; n++} END {if (n) print s/n/1024; else print "no fpm process"}'
# ویرایش استخر؛ مقادیر نمونه برای میانگین 40 مگابایت و 800 مگابایت رم قابل تخصیص
nano /etc/php/8.3/fpm/pool.d/www.conf
# pm = dynamic
# pm.max_children = 20
# pm.start_servers = 4
# pm.min_spare_servers = 2
# pm.max_spare_servers = 6
systemctl reload php8.3-fpm
⚠️ سقف بیش از اندازه، بدتر از سقف کم است
اگر pm.max_children را بزرگتر از رم سرور بگذارید، در اوج بازدید سرور به swap میافتد. خطای 502 فقط بخشی از درخواستها را رد میکند، اما swap کل سایت را کند میکند.

در این مرحله یک دیتابیس و کاربر اختصاصی در MariaDB میسازید و فایلهای وردپرس را در مسیر /var/www باز میکنید. بعد سرور بلاکی مینویسید که درخواست PHP را به سوکت FPM بدهد. خروجی درست، باز شدن صفحه نصب در مرورگر است.
کاربر root دیتابیس را برای وردپرس استفاده نکنید. یک کاربر با دسترسی محدود به همان یک دیتابیس بسازید تا اگر wp-config.php لو رفت، بقیه دیتابیسها دستنخورده بمانند. در پرسشهای mariadb-secure-installation، گذاشتن رمز root و حذف کاربر ناشناس و دیتابیس test را بپذیرید.
openssl rand -base64 24 # رمز تصادفی بسازید و جایی امن نگه دارید
mariadb-secure-installation
mariadb -u root -p
CREATE DATABASE wp_site CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wp_user'@'localhost' IDENTIFIED BY 'PASTE_RANDOM_PASSWORD';
GRANT ALL PRIVILEGES ON wp_site.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
rm -f ~/.mysql_history ~/.mariadb_history # رمز در تاریخچه میماند
نسخه فارسی وردپرس را از fa.wordpress.org بگیرید و فایلها را زیر مسیر سایت باز کنید. مالکیت را به کاربری بدهید که Nginx با آن اجرا میشود. در بستههای اوبونتو این کاربر www-data است و با ps -o user -C nginx بررسی میشود. دادن 777 به پوشهها رایجترین اشتباه این مرحله است.
mkdir -p /var/www/example.ir
cd /root
curl -LO https://fa.wordpress.org/latest-fa_IR.tar.gz
tar -xzf latest-fa_IR.tar.gz --strip-components=1 -C /var/www/example.ir
rm -f /root/latest-fa_IR.tar.gz
chown -R www-data:www-data /var/www/example.ir
find /var/www/example.ir -type d -exec chmod 755 {} \;
find /var/www/example.ir -type f -exec chmod 644 {} \;
حساسترین بخش نصب وردپرس روی سرور مجازی همین فایل است. راهنمای مقدماتی رسمی nginx میگوید رفتار nginx در فایل پیکربندی تعیین میشود، پس فایل htaccess نقشی ندارد. قاعده پیوندهای یکتا با try_files نوشته میشود و درخواست PHP با fastcgi_pass به سوکت FPM میرسد.
# /etc/nginx/sites-available/example.ir
server {
listen 80;
listen [::]:80;
server_name example.ir www.example.ir;
root /var/www/example.ir;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~ /\.ht { deny all; }
location = /wp-config.php { deny all; }
}
سه نکته در این فایل ارزش توضیح دارند. اول، طبق مستندات ماژول FastCGI در nginx پارامتر fastcgi_pass آدرس سرور FastCGI را میگیرد و سوکت یونیکس هم میپذیرد. دوم، همان مستندات برای fastcgi_split_path_info یک regex با دو گروه میخواهد؛ نوشتن اشتباهش مسیرهای جعلی را به مفسر میرساند. سوم، فایل snippets/fastcgi-php.conf در مستندات nginx نیامده و بخشی از بسته توزیع شماست؛ خودش هم آن regex و هم محافظ try_files با =404 را دارد.
rm -f /etc/nginx/sites-enabled/default # سایت پیشفرض را غیرفعال کنید
ln -s /etc/nginx/sites-available/example.ir /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
دامنه را در مرورگر باز کنید. وردپرس نام دیتابیس، کاربر و رمز را میپرسد و فایل wp-config.php را میسازد. بعد چند خط را پیش از سطر /* That’s all, stop editing! */ اضافه کنید.
طبق مستندات wp-config.php، چهار کلید AUTH_KEY، SECURE_AUTH_KEY، LOGGED_IN_KEY و NONCE_KEY الزامی هستند و چهار salt هم توصیه شدهاند. سرویس رسمی تولید کلید در api.wordpress.org هر هشت سطر را یکجا میدهد؛ هر هشت را در فایل بگذارید. تعریف DISALLOW_FILE_EDIT هم ویرایشگر فایل افزونه و قالب را غیرفعال میکند.
define( 'DISALLOW_FILE_EDIT', true );
define( 'WP_DEBUG', false );

کار با دیدن پیشخوان تمام نمیشود. سه قدم باقی مانده است: باز کردن پورتها و گرفتن گواهی TLS، سختسازی وردپرس و Nginx، و بکاپ قابل بازگردانی. بخش نهایی نصب وردپرس روی سرور مجازی همان چیزی است که بیشتر آموزشها جا میگذارند.
پیش از هر چیز پورت 80 و 443 را در فایروال باز کنید؛ شکست رایج Certbot همینجاست. مستندات Certbot میگوید پلاگین nginx برای بیشتر پیکربندیها کار میکند و با rollback میتوان تغییرها را برگرداند. در پرسش redirect، تغییر مسیر همه درخواستها به HTTPS را بزنید.
ufw allow 80,443/tcp
ufw status
apt -y install certbot python3-certbot-nginx
certbot --nginx -d example.ir -d www.example.ir
# بدون دستزدن به کانفیگ:
# certbot certonly --webroot -w /var/www/example.ir -d example.ir
systemctl list-timers | grep -i certbot
تمدید معمولاً از قبل با یک زمانبند فعال است. بر اساس همان مستندات، از نسخه 4.0.0 به بعد Certbot گواهی را وقتی آماده تمدید میداند که کمتر از یکسوم عمرش باقی مانده باشد. در نسخههای قدیمیتر عدد ثابت ۳۰ روز بود. جزئیات بیشتر در راهنمای نصب SSL رایگان با Let’s Encrypt آمده است.
بعد از HTTPS، نوبت کم کردن سطح حمله است. موارد زیر را یک بار انجام میدهید.
# در بلاک http
limit_req_zone $binary_remote_addr zone=wplogin:10m rate=20r/m;
# در سرور بلاک سایت
location = /wp-login.php {
limit_req zone=wplogin burst=5 nodelay;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
location ~* /wp-content/uploads/.*\.php$ { deny all; }
بکاپی که یک بار بازگردانی نشده باشد، بکاپ نیست. دو چیز را ذخیره کنید: پوشه سایت و دامپ دیتابیس. این آرشیو شامل wp-config.php با رمز دیتابیس است، پس در مسیر عمومی سایت نگذاریدش.
# گرفتن بکاپ
tar -czf /root/site-$(date +%F).tar.gz -C /var/www example.ir
mariadb-dump -u root -p --single-transaction wp_site > /root/db-$(date +%F).sql
# بازگردانی آزمایشی روی سرور دیگر
tar -xzf site-YYYY-MM-DD.tar.gz -C /var/www
mariadb -u root -p wp_site < db-YYYY-MM-DD.sql
🔶 چه چیزی این مسیر را کوتاهتر میکند
پنل اختصاصی وبداده ریبوت، نصب مجدد سیستمعامل، حالت Rescue، کنسول VNC و اسنپشات و بازگردانی را در اختیار شما میگذارد؛ پیش از هر تغییر پرخطر یک اسنپشات بگیرید.
اگر سایت شما روی cPanel، DirectAdmin یا Plesk است، انتقال رایگان سایت ارائه میشود.
| بررسی نهایی | دستور یا نشانه |
|---|---|
| هر سه سرویس بالا هستند | systemctl is-active nginx php8.3-fpm mariadb |
| پیوندهای یکتا کار میکنند | باز شدن یک نوشته بدون خطای 404 |
| گواهی معتبر است | خروجی certbot certificates |
| مجوز فایلها درست است | پوشه 755 و فایل 644 |
| بکاپ قابل بازگردانی است | باز کردن بکاپ روی سرور آزمایشی |
سوالهایی که کاربران ایرانی بیشتر از همه درباره این مسیر میپرسند، همینها هستند:
مستندات رسمی وردپرس هر دو را پیشنهاد میکند و هیچکدام را ترجیح نمیدهد. تفاوت عملی این است که Nginx فایل htaccess را نمیخواند؛ پس قاعده پیوندهای یکتا باید در سرور بلاک نوشته شود.
خوانده نمیشود و هیچ اثری ندارد. هر قاعدهای که در آن فایل داشتید باید معادل Nginx آن نوشته شود؛ برای پیوندهای یکتا همان خط try_files کافی است و برای بستن مسیرها deny all.
یعنی Nginx درخواست را به مفسر PHP داده و جوابی نگرفته است. دو علت رایج دارد: سرویس php8.3-fpm بالا نیست، یا مسیر سوکت در fastcgi_pass با فایل واقعی سوکت یکی نیست. با journalctl -u php8.3-fpm و error.log جدا کنید.
تقریباً همیشه یک خط گم شده است. در بلاک location اصلی باید try_files با مقدار $uri $uri/ /index.php?$args نوشته شده باشد و بعد از تغییر، nginx -t و reload اجرا شوند.
از سه چیز: نام یا رمز کاربر دیتابیس در wp-config.php اشتباه است، سرویس mariadb بالا نیست، یا دسترسی کاربر داده نشده است. با mariadb -u wp_user -p و بعد USE wp_site جدا میشوند.
نسخه پیشنهادی مستندات رسمی وردپرس 8.3 یا بالاتر است و بسته php8.3 در مخزن Ubuntu 24.04 موجود است. پیش از ارتقا، سازگاری قالب و افزونهها را بررسی کنید؛ قدیمیترین افزونه سقف نسخه شما را تعیین میکند.
بله. برای هر سایت یک پوشه زیر /var/www، یک دیتابیس و یک سرور بلاک جدا بسازید. اگر بار سایتها متفاوت است، در pool.d برای هر کدام فایل conf با user و listen جداگانه بسازید.
پوشهها 755 و فایلها 644، با مالکیت کاربری که وبسرور با آن اجرا میشود. از مجوز 777 پرهیز کنید. اگر وردپرس اطلاعات FTP خواست، معمولاً مالکیت فایلها اشتباه است، نه مجوزشان.
نه. اگر هاست فعلی cPanel، DirectAdmin یا Plesk است، انتقال سایت بدون نصب تازه انجام میشود و وبداده انتقال رایگان سایت را ارائه میکند.
جمعبندی؛ مسیر نصب وردپرس روی سرور مجازی در چهار قدم کار از تصمیم شروع میشود، نه از دستور. اول انتخاب میکنید که کنترل پنل میخواهید یا پیکربندی دستی، و نسخههای PHP و دیتابیس را از مستندات رسمی وردپرس برمیدارید نه از آموزشهای قدیمی. بعد سه سرویس Nginx، php8.3-fpm و mariadb-server را از مخزن رسمی توزیع نصب میکنید و استخر FPM را بر اساس مصرف واقعی هر پروسه تنظیم میکنید، نه عدد کپیشده. قدم سوم ساخت یک دیتابیس و کاربر محدود، باز کردن فایلها با مجوز 755 و 644، و نوشتن سرور بلاکی است که try_files و fastcgi_pass در آن درست باشد. قدم چهارم همان بخشی است که اغلب رها میشود: باز کردن پورت 80 و 443، گواهی TLS و تمدید خودکارش، و بکاپی که یک بار بازگردانیاش را آزمایش کرده باشید. پیشنهاد عملی: این مسیر را اول روی یک سرور آزمایشی اجرا کنید و فایل سرور بلاک خودتان را نگه دارید.
🚀 سرور را آماده کنید
اگر میخواهید همین مسیر را روی سروری با IP مستقیم و پنل اسنپشات و Rescue اجرا کنید، پلنها و سیستمعاملهای موجود را ببینید.
اگر سوالی داشتید، در بخش نظرات با ما در ارتباط باشید.