本文详细叙述从服务器配置,到安装博客程序的全过程。博客程序以Movable Type(以下简称MT)为例。如果您安装WordPress、Typecho等,方法与此相同。
为什么选择安装MT?因为它曾经和WordPress一样较为出名,而且我没折腾过。
MT的主要特点是:不开源、不免费、动态博客纯静态化。开发者为了在开源市场占有一席之地,曾发布过开源版本,最新的开源版本为2015年更新的5.2.13。后来,MT的商业化版本针对单用户、单网站实行免费策略,如需在程序内建立多个用户,或建立多个网站,则需要付费。
MT动态博客纯静态化,是一个特色。在MT后台修改模板、修改设置、发布日志等,如需让修改生效,需要对网站进行手动编译(Build)。编译后,会在指定的目录(默认为根目录)生成html、css等文件。访客访问时,读取的是这些html文件,这就是动态博客纯静态化。当访客提交评论后,MT会自动编译生成新的html文件,并将评论写入数据库。著名的独立博客之一“阮一峰的网络日志”便是使用MT搭建的。
写作本文时,我使用的是MT 7.0.1,已提前打好此版本的修复补丁。
准备安装
我使用的VPS操作系统为Debian 9.5,是当前Debian Stable的最新版本。我选定这个操作系统,原因有二:第一,我的电脑使用的操作系统便是Debian 9.5,我对这个系统较为熟悉,软件仓库的软件版本,我在物理机的新立得软件包管理器便可查询(我知道还有其他办法可以查询,但我不会操作);第二,这个系统的软件仓库包含的软件,虽然版本大多不是最新的,但却是经过足够的测试,保证是稳定的,不容易出现问题。
为保证稳定性,并节省安装时间,我采用的安装方法是逐个安装网站所需环境。这样安装的优点是,通过软件仓库直接安装软件包,可节省大量的时间,且运行足够稳定。缺点是无法切换版本。如果您不想逐个安装,可以使用LAMP或LNMP一键安装包,再安装一键安装包中不包含的软件包。注意:宝塔面板为用户安装的各种网站环境与此不兼容。
安装Webmin
Webmin的特点是,可以使用操作系统的系统用户(包括普通用户和root)的用户名和密码登录,在面板内进行文件管理、数据库管理、邮件服务器管理、模块管理等众多操作,简化了大量的操作。
本文写作时,Webmin最新版本为1.890。如需查看最新版本或历史版本信息,可进入https://sourceforge.net/projects/webadmin/files/webmin/ 查看。
wget http://prdownloads.sourceforge.net/webadmin/webmin_1.890_all.deb
dpkg --install webmin_1.890_all.deb
apt install -f
部分命令,可使用TAB补全,具体不予赘述。
安装完成后,可使用
https://ip:10000
访问。务必手动填写https://
,否则会无法访问。
访问时,会提示你证书错误。忽略此错误,继续访问即可。Firefox用户可添加安全例外。
如果手动填写https://
也无法访问,请确认VPS对应的安全组是否打开了10000端口。
如果面板访问速度较慢,可在侧边栏找到Webmin Configuration,将主题换成Gray Framed theme。为保证使用方便,可将语言改为简体中文。
软件版本
为保证运行MT,需要安装nginx、mysql、php。
这几个软件的版本如图所示。

图:mysql(mariadb)、nginx、php版本(2018年10月31日查询)
数据库可选择安装mysql或mariadb。安装mysql-server,实际上安装的是mariadb,版本相同。如果安装mariadb 10.1.26,建议VPS的RAM不低于2G。
如需安装更高的版本,可以使用Ubuntu系统(建议);也可以使用Debian的testing或sid分支(命令行下面操作繁琐,因此不建议)。
为何不用Apache
实际上apache可以支撑MT的运行,我在apache的虚拟主机上面试验过。
但我为何不使用apache呢?因为我参考的资料使用的nginx。我使用过apache环境的主机,但我用的是虚拟主机,不是vps。
所以,如果我在vps上使用apache,有些地方我不会配置,2333。
如何对vps上的apache进行配置,是我的下一个学习目标。
安装Nginx
apt install nginx
安装结束后,使用ip访问,即可弹出nginx默认页。
安装Mysql(Mariadb)
以安装5.5.9为例。
apt install mysql-server
此时,在Webmin左侧边栏最下方点击“刷新模块”,刷新后可在侧边栏“服务器”一栏看到Mysql的有关设置。在这里可新建、管理、删除数据库,可操作数据库的授权用户等。这至关重要,安装博客程序时,需要这些信息。
安装PHP
从上面的图中可以知道,Debian 9.5稳定版的软件仓库中,php版本为7.0。
apt install -y php7.0 php7.0-fpm php7.0-cli php7.0-common php7.0-mbstring php7.0-gd php7.0-intl php7.0-xml php7.0-mysql php7.0-zip php7.0-json php7.0-curl
如需查看已安装php版本,可执行
php -v
查看php7.0-fpm是否运行
service php7.0-fpm status
程序配置
下面进入繁琐、闹心的配置过程。
假设您的域名是domainexample.com,VPS默认普通用户是username,ip地址为23.231.232.233。此处仅作为举例,实际安装过程中,请务必使用真实数据。
DNS
首先,请在DNS服务商那里,将你的域名指向VPS的IP地址。DNS全球生效的时间大约在10分钟~72小时,取决于DNS服务商的服务质量及你的网络情况。如果着急,可修改本机hosts文件,将域名直接指向该IP地址。具体修改方法,针对不同操作系统而有所区别。
假如您的物理机使用的Linux系统,安装的是Mate桌面,可以使用pluma打开hosts文件。如果您使用的Gnome或Unity桌面,可以使用gedit。如果您使用的KDE桌面,可使用Kedit(好像是这个名字,很久没用KDE了有点忘了)。以pluma文本编辑器为例,切换到root用户,执行
pluma /etc/hosts
加入
23.231.232.233 domainexample.com
保存并关闭,重启系统。
Nginx
VPS由于不具有图形化界面,为保证操作简便,这里使用nano作为命令行界面的文本编辑器,不建议使用vi或vim。但如果您偏爱vi或vim,请嘴下留情,谢谢。
nginx的配置相当麻烦。
在普通用户主目录新建文件夹,文件夹名字为“domainexample.com”,便于识别。后面网站文件全部上传到这里。可在Webmin面板的File Manager里操作。
新建主机配置文件:
nano /etc/nginx/conf.d/domainexample.conf
写入如下内容:
log_format main '$remote_addr - $remote_user [$time_local] $status '
'"$request" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
server {
listen 80;
server_name domainexample.com www.domainexample.com;
access_log /var/log/nginx/host.access.log main;
root /home/username/domainexample.com;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ = 404;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
location ~ /\.ht {
deny all;
}
}
请根据你实际的域名、目录位置和php版本,修改上述代码。
用下面命令查看是否配置正确。
nginx -t
如果出现下列内容,配置就是正确的。
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
重启nginx:
service nginx restart
检测是否配置成功,方法如下。
在/home/username/domainexample.com下新建文件info.php,写入下列内容:
<?php
phpinfo();
打开桌面浏览器,访问domainexample.com/info.php,如果出现php信息列表页面,则访问正常。
如果出现错误,可查看如下配置文件:
- /var/log/nginx/host.access.log
- /var/log/nginx/error.log
根据配置文件内提示的错误内容进行排查。
SSL证书
使用Neilpang的脚本安装。此处使用文件验证,申请的证书为DV型。如需申请免费的通配符证书,或使用DNS验证,请参考官方文档进行操作。
curl https://get.acme.sh | sh
新建目录。
mkdir -p /home/username/domainexample.com/.well-known/acme-challenge
将下列代码,添加到nginx个人配置文件最后一个“}”前面。
location /.well-known/acme-challenge/ {
alias /home/username/domainexample.com/.well-known/acme-challenge;
}
重启nginx服务,命令在本文前面有。
此时需要重启一下VPS,使acme.sh命令生效,否则执行时会出现命令不存在的情况。可以在主机商网站后台管理页面重启,也可以在VPS内执行
reboot
重启。重启时,SSH会被断开连接,等待1~3分钟后重新连接即可。
申请证书。最后一个参数是采用椭圆函数加密,具体啥叫椭圆函数我也不知道,反正申请下来是ECC的证书,不是传统的RSA。
acme.sh --issue -d domainexample.com -d www.domainexample.com -w /home/username/domainexample.com --keylength ec-384
签发后的证书在~/.acme.sh/domainexample.com_ecc/ 下面。准备把证书安装到 /etc/nginx/ssl/domainexample.com。
新建目录,授予权限:
mkdir -p /etc/nginx/ssl/domainexample.com
chmod 777 /etc/nginx/ssl/domainexample.com
安装证书:
acme.sh --install-cert -d domainexample.com \
--cert-file /etc/nginx/ssl/domainexample.com/cert \
--key-file /etc/nginx/ssl/domainexample.com/key \
--fullchain-file /etc/nginx/ssl/domainexample.com/fullchain \
--reloadcmd "systemctl reload nginx.service" --ecc
生成一个 4096 位的 dhparam 文件。如果没有这个文件,安全性会降低。
这个过程时间很长,需要等待。为了保证SSH操作正常稳定,建议使用screen执行。
screen -S name
cd /etc/nginx/ssl
openssl dhparam -out dhparam.pem 4096
执行过程中,先按住键盘上的Ctrl,再依次按a d,即可退出screen,此时不影响上述命令执行,即便关闭SSH连接也不影响。你可以过一会儿重新连接SSH,然后执行
screen -r name
即可回到这个操作过程页面。
确认nginx和openssl版本:
root@ip:~# nginx -v
nginx version: nginx/1.10.3
root@ip:~# openssl version
OpenSSL 1.1.0f 25 May 2017
在Mozilla SSL Configuration Generator生成配置文件,需要用到版本信息。推荐Modern方式,不要开启HSTS,否则可能出现nginx服务启动失败。
此时,根据需要编辑nginx配置文件。
log_format main '$remote_addr - $remote_user [$time_local] $status '
'"$request" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name domainexample.com www.domainexample.com;
access_log /var/log/nginx/host.access.log main;
# certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
ssl_certificate /etc/nginx/ssl/domainexample.com/fullchain;
ssl_certificate_key /etc/nginx/ssl/domainexample.com/key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
# intermediate configuration. tweak to your needs.
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;
# OCSP Stapling ---
# fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on;
## verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /etc/nginx/ssl/domainexample.com/fullchain;
resolver 8.8.8.8;
root /home/username/domainexample.com;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ = 404;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
location ~ /\.ht {
deny all;
}
location /.well-known/acme-challenge/ {
alias /home/username/domainexample.com/.well-known/acme-challenge/;
}
}
配置好后,去SSL Labs检测,结果是A+。
安装Perl-Fastcgi
如果使用WordPress、Typecho且不使用perl模块,这个步骤可以省略。如果使用MT,则需要进行这个步骤。
apt install libfcgi-perl spawn-fcgi fcgiwrap
然后执行
service fcgiwrap start
将如下内容写入nginx个人配置文件,注意写在最后一个“}”前面:
location ~ \.pl|cgi$ {
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_index index.pl;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
保存,重启nginx服务。
检测是否配置成功,方法如下。
在/home/username/domainexample.com下,新建index.pl,写入如下内容:
#!/usr/bin/perl
print "Content-type:text/html\n\n";
print <<EndOfHTML;
<html><head><title>Perl Environment Variables</title></head>
<body>
<h1>Perl Environment Variables</h1>
EndOfHTML
foreach $key (sort(keys %ENV)) {
print "$key = $ENV{$key}<br>\n";
}
print "</body></html>";
赋予权限,否则会出现403错误:
chmod a+x index.pl
在浏览器中访问该文件。如果可正常访问,则配置成功。
其他配置
(1)301跳转:下面的配置文件中,将www跳转到@,http强制跳转到https。
(2)调整文件上传大小:调整文件上传大小为100M(如不调整,默认2M)。
最终得到的总体nginx配置文件如下:
log_format main '$remote_addr - $remote_user [$time_local] $status '
'"$request" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
server {
listen 80;
server_name domainexample.com;
return 301 https://$server_name$request_uri;
}
server {
listen *:80;
listen *:443 ssl;
listen [::]:80;
listen [::]:443 ssl;
server_name www.domainexample.com;
ssl_certificate /etc/nginx/ssl/domainexample.com/fullchain;
ssl_certificate_key /etc/nginx/ssl/domainexample.com/key;
return 301 https://domainexample.com$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name domainexample.com;
access_log /var/log/nginx/host.access.log main;
client_max_body_size 100M;
# certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
ssl_certificate /etc/nginx/ssl/domainexample.com/fullchain;
ssl_certificate_key /etc/nginx/ssl/domainexample.com/key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
# intermediate configuration. tweak to your needs.
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;
# OCSP Stapling ---
# fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on;
## verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /etc/nginx/ssl/domainexample.com/fullchain;
resolver 8.8.8.8;
root /home/username/domainexample.com;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ = 404;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
location ~ /\.ht {
deny all;
}
location /.well-known/acme-challenge/ {
alias /home/username/domainexample.com/.well-known/acme-challenge/;
}
location ~ \.pl|cgi$ {
fastcgi_pass unix:/var/run/fcgiwrap.socket;
fastcgi_index index.pl;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
(3)安装imagemagick模块,保证MT后台不报错:
apt install imagemagick libimage-magick-perl
(4)安装sendmail:
apt install sendmail
配置可在Webmin中操作。
(5)调整perl编码识别,以防出现错误:
在Webmin面板,以root登录,在File Manager中,修改/usr/lib/x86_64-linux-gnu/perl/5.24/Encode.pm,在第201行else {
后面,添加
Encode::_utf8_off($octets);
点击最下方Save and close(保存并关闭)即可。
好了,配置完成。
接下来,上传文件、设置数据库,以至于后期的备份数据库、修改文件等,均可在Webmin面板操作。
清除缓存软件包
从Debian和Ubuntu的软件仓库下载的软件包并不会默认删除。为释放被占用的空间,可执行
apt clean
即可删除软件仓库下载的软件包。
安装Movable Type
安装步骤可参见官方文档,但官方文档说的太复杂了。此处则简略的一下。
将mt-static目录独立出来,剩余的文件放在同一个目录,命名为cgi-bin。将cgi-bin和mt-static上传到网站根目录。
访问domainexample.com/cgi-bin/mt/mt.cgi,进入安装过程。
安装过程中,有一步是发送邮件设置。如果使用sendmail,需要输入路径。本文前面安装的sendmail所在路径为:
/usr/lib/sendmail
最后写入数据库这一步需要注意,如果在浏览器端,可能长时间没有反应。解决方法:使用手机浏览器访问,即可正常进行最后写入数据库这一步。这可能是bug。
部分文件夹需要将权限设置为777,待安装结束后,进入后台,按警告内容提示操作。
示例站点:https://iyfy.top 。注:如果示例站点不能访问,可能的原因有:
- VPS宕机、过期或被删除
- 后期折腾时操作出现错误,或网站运行中出现我无法解决的错误
- 我主动关停了这个站点
- 我被迫关停了这个站点
- 网络原因或境内电信运营商原因
- ip、域名或DNS服务器被X
- 域名被注册局(-江苏邦宁科技有限公司)或注册商(阿里云)停止解析
- 域名过期
最后,感谢某大佬提供了为期一年的VPS供我折腾。
善意的提醒一下:VPS属于无服务模式,除非付费寻求技术服务,一切使用和维护工作均只能由用户独立完成。当出现故障时,需用户自行保证数据安全。如果没有足够的VPS管理经验,却也想自己折腾一下,请不要将重要数据放到VPS上。
好折腾啊……刚开始还以为是 MT 的介绍安装部署,看到后面简直是服务器的完整配置。
回过头来看标题,确实是。
就是服务器的完整配置,哈哈。
MT比普通PHP程序多了一步,就是安装perl-fastcgi。当然前面的webmin面板,对perl有依赖。
我现在真的懒得折腾这些,一般都装个 VPS 面板。
你用的是什么面板?我这次折腾,用webmin面板替代命令行执行一些东西,比如文件管理、数据库管理这些……
宝塔,如果用 PHP 的话很方便了。
折腾的大佬~= =、
弱弱地问一句,有demo看看吗?
去文章里找“示例站点”,你可以用ctrl+f搜索这个关键词。
看起来我翻的太快了。
哈哈,文章太长了。你要不要也折腾一下?
web环境以前我也是自己一个一个安装,后来发现安装类似LNMP之类的非常方便,省力不少!
确实。一个一个安装,最主要就是节省时间,而步骤要复杂点。LNMP这类的安装时间较长,但一般内置了多个版本,可以切换,当然最主要是省心省力。
写的非常详实了,不过勒~~总会在实际操做中出现小问题的哈哈哈
我也是出现过小问题,连续排查,最终确定了没有问题的方法,写成了此文,哈哈。
看起来安装比较复杂,我现在只想用简单点的,WordPress都懒得安装折腾了。
安装不复杂,配置复杂。配置当中,nginx比apache复杂很多。
好详细的文章! 赞
谢谢大佬的鼓励!
看来还是用宝塔比较好啊,哈哈
宝塔是方便,然而呢,我折腾的时候总是有环境安装失败,比如php 7.0~7.2,mysql 5.1。又没有我看得懂的警告信息。不知道怎么回事。