在 LEMP Stack 的单个 VPS 上搭建多个 WordPress 站点

最近几天,之前一直使用的 VPS 被墙得厉害,不墙的时候连接也很不稳定,于是换了另一家的 VPS,顺便把 Apache 换成了 Nginx。本文整理了博客迁移过程中,在 LEMP Stack 的单 VPS 上搭建多个 WordPress 站点的方法(多个 WordPress 实例,非 Multisite),使用系统为 Ubuntu 17.04 x64。

0. 初始配置和安装

  服务器的初始配置和 LEMP 的安装不是本文重点,这里给出两篇文章以供参考。

0.1. 服务器初始配置

  关于服务器的初始配置,可以参考 Initial Server Setup with Ubuntu 16.04 这篇文章,这里不在赘述。

0.2. LEMP 的安装

  LEMP 指的是 Linux、Nginx、MySQL/MariaDB, 和 PHP,安装过程可以参考 How To Install Linux, Nginx, MySQL, PHP (LEMP stack) in Ubuntu 16.04 这篇文章。

1. 场景整理

  下面开始正题,本文的场景为,在一个 LEMP Stack 的 VPS 上,安装并运行两个 WordPress 站点,两个站点有不同的域名,相互独立、互不可见,区别于 Multisite 这种在一个 WordPres 实例中管理多个用户的场景。安装单个 WordPress 的方法参考自 How To Install WordPress with LEMP on Ubuntu 16.04,不得不说,DigitalOcean 的文档真是全。

  为了方便后续说明,假设站点信息如下,操作时注意根据实际情况替换。

第一个站点 第二个站点
域名 firstsite.com secondsite.com
网站地址 www.firstsite.com www.secondsite.com
数据库名 firstdb seconddb
数据库用户 firstdbuser seconddbuser
数据库密码 firstdbpw seconddbpw
WordPress 安装路径 /var/www/firstblog /var/www/secondblog

2. 创建数据库

  首先分别为两个站点创建对应的数据库。使用 root 登录 MySQL:

mysql -u root -p

之后需要输入 MySQL 的 root 密码,这个密码是在安装和配置 MySQL 时设置的,具体步骤可以参考 How To Install Linux, Nginx, MySQL, PHP (LEMP stack) in Ubuntu 16.04 的 “Step 2: Install MySQL to Manage Site Data” 一节。

  成功登入后,提示符会变成 mysql>,下面为第一个站点(firstsite)创建名为 firstdb 的数据库:

CREATE DATABASE firstdb DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;

  然后为 firstdb 创建用户 firstdbuser,并设置密码为 firstdbpw:

mysel>

GRANT ALL ON firstdb.* TO 'firstdbuser'@'localhost' IDENTIFIED BY 'firstdbpw';

  继续为第二个站点(secondsite)创建数据库 seconddb,创建用户 seconddbuser 并设置密码为 seconddbpw:

CREATE DATABASE seconddb DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
GRANT ALL ON seconddb.* TO 'seconddbuser'@'localhost' IDENTIFIED BY 'seconddbpw';

  最后刷新权限并退出:

FLUSH PRIVILEGES;
EXIT;

3. 配置 Nginx

3.1. 配置第一个站点

  首先复制一份配置文件:

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/firstsite

  接着打开刚才复制的配置文件:

sudo nano /etc/nginx/sites-available/firstsite

  需要修改的主要有三个地方:

    root /var/www/firstblog; 
    index index.php index.html index.htm index.nginx-debian.html; 

    server_name firstsite.com;

    location / {
        #try_files $uri $uri/ =404;
        try_files $uri $uri/ /index.php$is_args$args;
    }

  • 把 root 字段改为第一个站点的 WordPress 的安装路径(安装 WordPress 的步骤在后面),也就是 /var/www/firstblog
  • 在 index 后面添加
    index.php
  • 把 server_name 字段改为 firstsite.com,如果想使用子域名,也在这里设置,另外 server_name 可以使用通配符,如 *.firstsite.com,也可输入多个域名,详见官方文档
  • 把 location / 下的 try_files $uri $uri/ =404; 注释掉,加入

try_files $uri $uri/ /index.php$is_args$args;

  另外需要在配置文件里添加以下内容:

    location = /favicon.ico { log_not_found off; access_log off; }
    location = /robots.txt { log_not_found off; access_log off; allow all; }
    location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
        expires max;
        log_not_found off;
    }

  最后得到的完整配置文件形如:

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/firstblog;

        # Add index.php to the list if you are using PHP
        index index.php index.html index.htm index.nginx-debian.html;

        server_name firstsite.com;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                #try_files $uri $uri/ =404;
                try_files $uri $uri/ /index.php$is_args$args;
        }

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        }

        location ~ /\.ht {
                deny all;
        }

        location = /favicon.ico { log_not_found off; access_log off; }
        location = /robots.txt { log_not_found off; access_log off; allow all; }
        location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
                expires max;
                log_not_found off;
        }
}

  保存(Ctrl + O,然后回车确认文件名)并退出(Ctrl + X)编辑器。接下来建立从 sites-available 到 sites-enabled 的符号链接:

sudo ln -s /etc/nginx/sites-available/firstsite /etc/nginx/sites-enabled/firstsite

  记得要删除原有的 default 配置文件,default 和 firstsite 都在 listen 后使用了 default_server,二者不能共存:

sudo rm /etc/nginx/sites-available/default

  使用以下命令确认配置是否正确:

sudo nginx -t

  Reload Nginx,使配置生效:

sudo systemctl reload nginx

  现在访问 www.firstsite.com,会看到 Nginx 的报错页面,因为还没有把 WordPress 安装到 /var/www/firstblog。

3.2. 配置第二个站点

  接下来配置第二个站点,先复制 firstsite ,命名为 secondsite 并打开:

sudo cp /etc/nginx/sites-available/firstsite /etc/nginx/sites-available/secondsite
sudo nano /etc/nginx/sites-available/secondsite

  第二个站点的配置也和上面类似,注意要删掉 listen 后面的 default_server,并替换域名和安装路径等信息,如:

server {
        listen 80;
        listen [::]:80;

        root /var/www/secondblog;

        # Add index.php to the list if you are using PHP
        index index.php index.html index.htm index.nginx-debian.html;

        server_name secondsite.com;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                #try_files $uri $uri/ =404;
                try_files $uri $uri/ /index.php$is_args$args;
        }

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        }

        location ~ /\.ht {
                deny all;
        }

        location = /favicon.ico { log_not_found off; access_log off; }
        location = /robots.txt { log_not_found off; access_log off; allow all; }
        location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
                expires max;
                log_not_found off;
        }
}

  保存后,建立符号链接,确认配置正确,并 Reload Nginx:

sudo ln -s /etc/nginx/sites-available/secondsite /etc/nginx/sites-enabled/secondsite
sudo nginx -t
sudo systemctl reload nginx

4. 安装 WordPress

4.1. 安装 PHP 扩展

  安装 WordPress 之前,先要安装一些依赖:

sudo apt-get update
sudo apt-get install php-curl php-gd php-mbstring php-mcrypt php-xml php-xmlrpc

  然后重启 PHP-FPM 令安装生效:

sudo systemctl restart php7.0-fpm

4.2. 下载 WordPress

  把 WordPress 下载到 /tmp 下并解压:

cd /tmp
curl -O https://wordpress.org/latest.tar.gz
tar xzvf latest.tar.gz

  以 wp-config-sample.php 为模板,复制一份 wp-config.php 待用:

cp /tmp/wordpress/wp-config-sample.php /tmp/wordpress/wp-config.php

  手动创建 upgrade 文件夹,避免 WordPress 自动更新的权限问题:

mkdir /tmp/wordpress/wp-content/upgrade

  把 WordPress 复制到 /var/www/firstblog 和 /var/www/secondblog,也就是之前在 Nginx 配置文件里 root 字段指定的位置:

sudo cp -a /tmp/wordpress/. /var/www/firstblog

sudo cp -a /tmp/wordpress/. /var/www/secondblog

4.3 配置第一个站点

4.3.1. 配置文件权限

  为了确保安全性,首先要配置一下文件权限。把 /var/www/firstblog 的所有权设置给 www-data 用户组(把 mylinuxuser 替换为你的有 sudo 权限的 Linux 用户):

sudo chown -R mylinuxuser:www-data /var/www/firstblog

如果不知道怎么添加 Linux 用户,可以参考 Initial Server Setup with Ubuntu 16.04 这篇文章的“Step Two — Create a New User”一节。

  然后为 /var/www/firstblog 配置 setgid,这样在 /var/www/firstblog 下新创建的文件会继承其父目录的组:

sudo find /var/www/firstblog -type d -exec chmod g+s {} \;

  接着,为 wp-content 文件夹设置组写入权限,并为其中的 themes 和 plugins 两个文件夹和其中的所有内容设置写入权限:

sudo chmod g+w /var/www/firstblog/wp-content
sudo chmod -R g+w /var/www/firstblog/wp-content/themes
sudo chmod -R g+w /var/www/firstblog/wp-content/plugins

4.3.2. 配置 wp-config.php

  wp-config.php 是 WordPress 的配置文件,在进行配置前,先使用如下命令获取一系列所需的秘钥:

curl -s https://api.wordpress.org/secret-key/1.1/salt/

得到的结果如:

define('AUTH_KEY',         'ckZrR+?nc!h!mKiF &A6$9_VsAAn_8Aos0)m-T1C@lTV#Zk]Qrwq~s?^B|J:vTZ2');
define('SECURE_AUTH_KEY',  'O|/t}b);er/C5vu@|?>$Ei|*hP((cYDG%053hVsT:zsPh8Ae<y@w)UFG)&4OCW@-');
define('LOGGED_IN_KEY',    'bnG2{#T:-.+xsgBQc{{EJS0}}$HO&2?aM#(');
define('AUTH_SALT',        'O[Pmpf|~rtWH b^aa@Rz(WYPUw:cg7P#{-tlnVz%H./4fZD+U*%{dwc:.1Y0a610');
define('SECURE_AUTH_SALT', ',{|,OlQ1zzDLqE^8}{r^cq/TkW{;6@HL.A<YoaGW>_::_^q|8gjsz_lQ[,6yi|){{EJS1}}~UL!HA^Md=wRn|9');

这是通过官方的秘钥生成器得到一系列秘钥,每次获取都不一样,复制起来备用(不要直接复制上面的内容,要自己去获取)。

  编辑第一个站点的 wp-config.php:

nano /var/www/firstblog/wp-config.php

  首先找到如下一段:

define('AUTH_KEY',         'put your unique phrase here');
define('SECURE_AUTH_KEY',  'put your unique phrase here');
define('LOGGED_IN_KEY',    'put your unique phrase here');
define('NONCE_KEY',        'put your unique phrase here');
define('AUTH_SALT',        'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT',   'put your unique phrase here');
define('NONCE_SALT',       'put your unique phrase here');

把这一大段替换为上一步获得的秘钥。

  然后找到文件开头的数据库配置,填入在最开始创建的数据库(firstdb)、数据库用户名(firstdbuser)和密码(firstdbpw):

/** The name of the database for WordPress */
define('DB_NAME', 'firstdb');

/** MySQL database username */
define('DB_USER', 'firstdbuser');

/** MySQL database password */
define('DB_PASSWORD', 'firstdbpw');

  最后再加入一行:

define('FS_METHOD', 'direct');

这样 WordPress 就会直接向硬盘写入数据,而不是使用 FTP。

  以上就是 wp-config.php 所需的配置,保存并退出编辑器。

4.3.3. WordPress 配置向导

  如果已经配置好了 DNS,那么现在打开 www.firstsite.com,应该就可以看到 WordPress 的设置向导了,做一些简单的用户和密码设置,就可以使用 WordPress 了。

4.4. 配置第二个站点

  第二个站点的配置和第一个完全一样,可以按照 4.3. 的步骤进行,注意在操作时替换相关名称,如把 firstblog 改为 secondblog 等。

4.5. 关于自动更新

  上面为 WordPress 设置的文件权限,不足以让 WordPress 进行自动更新或某些安装,如果 WordPress 自动执行某些操作时遇到权限问题,可以手动放开全部文件(如 /var/www/firstsite)的权限:

sudo chown -R www-data /var/www/firstsite

  之后记得再改回去:

sudo chown -R mylinuxuser /var/www/firstsite