要完成本教程,你需要:

  • ⏳ 2~3 天时间(所有零碎时间拼起来的结果)
  • 💰 $70~$100/yr 的服务器 + 域名开销
  • 知道如何远程连接到一台 Linux 服务器,会 Linux 的一些基本操作
  • 自己建站的决心、耐力和热情

你可以得到:

  • 一个比较清爽的的个人博客,一切数据和功能由自己掌控
  • 可以在电脑、平板、手机等多个设备远程从网页端编辑,编辑器体验类似豆瓣,也可支持 Markdown
  • 一个自己的服务器(可以在上面干很多有趣的事情:有了一个 VPS 能做什么

如何选择建站方案

太长不看版(每种方案的痛点,请自行寻找 deal breaker):

  • Notion / Tumblr
    • 不太像一个博客,而且没有非常有效的方式折腾得像
    • 有被墙的风险,或已经被墙
  • wordpress.com
    • 网站默认模板比较丑(但可以调)
    • 💰 有三种 Plan,免费版有广告,$4/mo 的不能装插件,$20/mo 才能随便折腾
  • wordpress.org + VPS
  • Hexo + GitHub Pages
    • 手机和平板编辑没有实时渲染,传图很麻烦
    • 电脑编辑必须保存和用 git 同步博客源码,且每台电脑都需安装 hexo
    • 国内访问速度不稳定
    • 🛠️ 安装技术难度较高
  • write.as
    • 所有客户端没有实时渲染,传图很麻烦
    • 自定义极其有限(连字号都不能调)
  • Blogger
    • 网页端编辑器比较丑,iPad 端没有合适的编辑器

啰嗦版:

  • 一次性建站成本(只要在预算范围即可,非主要考虑因素):
 wordpress.comwordpress.org+VPSHexo + GitHub Pageswrite.asBlogger
时间成本~15min2-3 天1-2 天~15min~15min
金钱成本免费(有广告)~$20/mo(支持插件)$5/mo VPS
+ $10~$30/yr 域名
免费免费免费
隐私保护仅收集邮箱仅收集邮箱仅收集邮箱仅收集邮箱,支持匿名发帖仅收集邮箱
技术难度掌握 Linux 基础知识掌握 Linux 和 GitHub 基础知识
非技术难度约等于无需要买 VPS 和域名
配 DNS 时可能需要和两边客服沟通
  • 长期使用体验(主要考虑因素。我个人非常看重「多设备编辑」以及「随手记录」这两个点):
 wordpress.comwordpress.org+VPSHexo + GitHub Pageswrite.asBlogger
颜值尚可尚可NeXT,当之无愧的颜值之王demo,非常 minimalism尚可
移动端app 或网页端富文本编辑器app 或网页端富文本编辑器持续集成 + WorkingCopy,无即时渲染,插图麻烦app 或网页端 Markdown 编辑,无即时渲染,需图床网页端富文本编辑器(好像没有进行移动端适配,编辑体验不太行)
电脑端网页富文本或 Markdown 编辑器网页富文本或 Markdown 编辑器下载 hexo 源码后,本地 Typora Markdown 编辑网页端 Markdown 编辑,无即时渲染,需图床网页端富文本编辑
新建一键新建一键新建新建. md 文件,起名保存,加上 yaml 文件头一键新建一键新建
草稿箱未发布的文章自动存入草稿箱未发布的文章自动存入草稿箱可匿名发布,也可存草稿未发布的文章自动存为草稿
更新编辑后立即更新编辑后立即更新编辑后有~10min 延迟编辑后立即更新编辑后立即更新
自定义完备的插件系统,$20/mo 随便定制完备的插件系统,$5-$6/mo 随便定制,可装其他服务静态页面,插件多,可以定制但有限连字体大小都不能调……插件系统不活跃,可以定制但有限

我的建站方案:Wordpress + VPS 教程

🌏 购买 VPS 和域名

VPS(Virtual Private Server,个人虚拟主机)可以近似理解为一台 7×24 运行且永不关机的电脑,当你在浏览器中打下域名(比如 google.com)时,DNS(Domain Name System,域名系统)会负责找到这台电脑,从它上面请求网页,并把下载得到的网页渲染到你的浏览器上(详细解释见不只是 Blog——VPS 搭建 WordPress 记录)。

我的配置:

  • VPS:Hostwinds Umanaged Linux VPS 最低配,$4.99/mo,Ubuntu 18.04
  • 域名:Namecheap,$10~$30/yr(以下用 example.com 指代)
  • DNS 设置:
    1. 在 Namecheap 的 nameserver 一项里选择 Custom DNS,填入 Hostwinds 提供的 nameserver 域名
    2. 在 Hostwinds 里加 A record(example.com 和 www.example.com),将这两个域名都指向 VPS 的 IP

这一步结束之后,你应该可以 ssh 到你的 VPS 终端:

ssh root@example.com

🏡 安装 Wordpress 

为了能在一个 VPS、一个 IP 上部署多个服务(例如,通过 a.example.com 访问 A 服务,b.example.com 访问 B 服务,二者部署在同一主机的不同端口),我没有像网上的大多数教程那样,把 wordpress 直接部署在默认的 80 端口上,而是将它部署在我自定义的一个端口(如 8080)上,再利用 nginx 反向代理将原本发送给 80 端口的请求转发到 8080 端口上。换端口这一步稍微有一点点麻烦,但为了能尽情地胡作非为部署多个服务,这一步是必需的,也是值得的。

这一步主要参考了用 Nginx 反代实现 docker 安装 WordPress 与其他服务并存(by 云五,参考了 90%)、不只是 Blog——VPS 搭建 WordPress 记录(by 此方)以及 How To Install WordPress With Docker Compose(by DigitalOcean),在这三篇的基础上有少量改动。

[对于以上几位作者:如果您认为此文侵犯了您的版权,请联系我,我会立即将此文删除]

服务器环境配置

据说直接用 root 装网站是一个坏习惯,因此我们要做的第一件事就是用 root 登录,开一个新的有 sudo 权限的用户,之后的所有操作都用这个用户进行:

export $UNAME=<username>
useradd $UNAME -m
usermod -s /bin/bash $UNAME
passwd $UNAME
chmod u+w /etc/sudoers
# 在/etc/sudoers的root    ALL=(ALL:ALL) ALL后面添加
# <username> ALL=(ALL:ALL) ALL
chmod u-w /etc/sudoers

登出 root,登入新开的这个用户,安装一些部署用的库:

sudo apt install docker docker-compose
sudo apt install nginx

允许新用户不用 sudo 就能使用 docker:

sudo gpasswd -a $USER docker

(非必需)开启 Google BBR 拥塞控制算法,以加快网站访问速度:

sudo vim /etc/sysctl.conf

在文件末尾加上:

net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr

然后刷新:

sudo sysctl -p
# Test success
sysctl net.ipv4.tcp_congestion_control  
# should output `net.ipv4.tcp_congestion_control = bbr`

在 80 端口安装 Wordpress

开一个目录用于存放 wordpress 配置文件(我放在~/wordpress),并进入它:

# 我将教程中提到的几个配置文件打包放在一个github仓库里了
git clone https://github.com/maskbot/wordpress.git
cd wordpress

1. 将 nginx 配置文件中的域名修改成你自己的:

vi nginx-conf/nginx.conf

将其中所有的 example.com 都替换成你自己的域名。

2. 创建一个环境变量文件(用于设置你的 MySQL 数据库用户名和密码,以及 wordpress 使用的 HTTP 端口):

vim .env

.env 的内容如下(自行设置前三项的值,随便设置即可,密码别太弱):

MYSQL_ROOT_PASSWORD=your_mysql_root_password
MYSQL_USER=your_wordpress_database_user
MYSQL_PASSWORD=your_wordpress_database_password
HTTP_PORT=80

需要注意的是,.env 文件包含敏感信息,因此一定要避免它被加入 docker container 或上传到 github。在上面 clone 的 github repo 中,我已经将其加入了. dockerignore 和. gitignore。

此时你的~/wordpress 目录应该呈现以下结构:

.
├── .dockerignore
├── .env
├── .gitignore
├── docker-compose.yml
└── nginx-conf
    └── nginx.conf

最后,启动 wordpress 服务!🚀

docker-compose up -d

可以用 docker-compose ps 命令检查是否启动成功,如果成功的话,可以看到以下输出(所有 State 都应为 Up):

  Name                 Command               State          Ports
-------------------------------------------------------------------------
db          docker-entrypoint.sh --def ...   Up      3306/tcp, 33060/tcp
webserver   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:80->80/tcp
wordpress   docker-entrypoint.sh php-fpm     Up      9000/tcp

WordPress 前端初始化

要想将 Wordpress 改成自定义端口,必须先登录 WebUI 进行一些初始设置。

上一步的 docker-compose up 命令完成后,等待一小会(最多 10min 左右),从浏览器访问 http://example.com,即可看到 Wordpress 的 WebUI,让你设置语言、邮箱、密码等。设置完成后,登录进入 wordpress 管理后台界面。

此步完成后,再访问 example.com,显示的应为你的博客首页。

自定义 Wordpress 端口

现在我们要把 wordpress 挪到自定义端口啦(我的设置为 8080 端口)。

首先,停止 wordpress 服务:

docker-compose down

然后进入. env 文件,修改 HTTP 端口为你的自定义值:

HTTP_PORT=8080

然后重启 wordpress 服务 🚀:

docker-compose up -d

此时无法再从浏览器访问 example.com,因为 wordpress 服务已经被挪到 8080 端口了。从 VPS 的终端 curl,应该可以得到 301 Moved Permanently 的返回码:

curl -v http://localhost:8080

好,现在我们在 nginx 中设置一个反向代理(把发送给 example.com 80 端口的请求转发到你 VPS 的 8080 端口):

cd /etc/nginx/sites-enabled/
sudo rm -rf default
cd /etc/nginx/sites-available/
sudo vi wordpress.conf

wordpress.conf 的内容(将 example.com 替换成你自己的域名):

server {
    listen      80;
    listen [::]:80;
    server_name example.com;
    location / {
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:8080;
    }
}

然后开启这个反向代理 🚀:

cd /etc/nginx/sites-enabled/
sudo ln -s ../sites-available/wordpress.conf wordpress.conf
systemctl reload nginx

现在,再访问 http://example.com,就又可以看到你的博客首页了。

获取免费 SSL 证书以支持 https

如果你不在意浏览器地址栏左侧的 Not Secure 字样(表示你和该网站之间的通信未加密,可能遭到中间人攻击,换句话说你不能放心地在里面输入密码、邮箱等敏感信息)的话,那么其实你可以忽略此步,直接开始布置你的博客。但作为一个强迫症 + 轻微 paranoid 的程序员,我还是义无反顾地 walk the extra mile 了。

我们使用 Let’s Encrypt 提供的免费 SSL 服务(注意将 example.com 替换成你自己的域名,注意同意条款后问是否暴露邮箱时选 No,问是否强制 redirect https 时选否):

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com

完成后,修改反向代理配置文件,加入和调整 HTTPS 的设置:

cd /etc/nginx/sites-available/
sudo vi wordpress.conf

wordpress.conf 的新内容(注意将 example.com 替换成你的域名):

server {
    listen      80;
    listen [::]:80;
    server_name example.com;
    return 301 https://$host$request_uri;
}
server {
    listen 443 ssl;
    server_name example.com;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

刷新一下反向代理,现在我们可以用 https://example.com 来访问博客啦!🚀

systemctl reload nginx

恭喜🎉! 到这里,wordpress 的安装就结束了。之后的所有操作(改主题、装插件、写博客)都可以通过 wordpress 前端的 WebUI 完成。

🎄 博客个性化

数据备份

超好用的免费备份插件:UpdraftPlus。你可以设置它每天自动备份,并将备份文件自动上传到 Google Drive,保留最新的 X 个备份。这个备份文件中包括了你所有的博文、图片、网站主题、插件等等,亲测可以将你的博客一键恢复,哪怕你整个重置了服务器都没问题。

外观(主题、颜色、字体等)

博客外观:

  • 主题:Blocksy,干净好用(外观 > 自定义)
  • 颜色:我把字体调成了黑的,其他的没动(外观 > 自定义 > 颜色)
  • 字体:我把代码字体从 monospace 改成了 Roboto Mono,别的没动(外观 > 自定义 > 字体样式)
  • 摘要:我把博客语言调成了中文(设置 > 常规 > 站点语言),然后把摘要长度调成了 50 字(外观 > 自定义 > 博客文章 > 卡片选项 > 摘要)

后台界面:

  • 隐藏 Wordpress 屏幕上方的那条深蓝色工具栏:Better Admin Bar 插件,在设置里把所有透明度都调成 0%
  • 后台主题:Kodeo Admin UI 插件,个人认为比较清爽好看,而且首页不拥挤,第一个 widget 默认是「快速草稿」也是一个很大的加分项。

侧边工具栏(目录、超链接等)

启用侧边栏:

  • 首页侧边栏:外观 > 自定义 > 博客文章 > 侧边栏,选为 on
  • 文章内页侧边栏:外观 > 自定义 > 文章详情页 > 选择有侧边栏的设计

侧边栏加入管理菜单:

  1. 进入 widgets 编辑界面:外观 > 小工具
  2. 添加一个自定义 HTML 组件:从左侧选中「自定义 HTML」,将其拖拽到右侧的主边栏中
  3. 在其中添加如下代码(请将 example.com 替换成你自己的域名),会得到一个内容包括 Dashboard、New Post、Draft、Logout 4 项的工具菜单:
<div class="ct-widget widget_meta">
<ul>
    <li><a href="https://example.com/wp-admin/">Dashboard</a></li>
	<li><a href="https://example.com/wp-admin/post-new.php">New Post</a></li>
    <li><a href="https://example.com/wp-admin/edit.php?post_status=draft">Drafts</a></li>
    <li><a href="https://example.com/wp-login.php?action=logout">Logout</a></li>
</ul>
</div>

 

侧边栏显示文章目录:

  1. 如果是单独一篇文章想侧面显示文章目录,在编辑器的设置齿轮下改成有侧边栏的样式;否则在外观 > 自定义里全局改
  2. 安装 LuckyWP Table of Contents 插件
  3. 进入外观 > 小工具,将左侧的 LuckyWP 的目录 widget 拖入右侧的主边栏
  4. 自定义:最少标题数 = 3,深度 = 3(仅显示 h4 及以上标题),宽度 = 全宽,链接颜色 =#3eaf7c(主题色)
  5. 如果有一篇文章的目录特别长(如此篇),你希望侧边栏仅显示目录,则需要如下操作:
    1. 安装 Sidebar Manager 插件,然后在外观 > Sidebars 中添加一个新的 Sidebar,设置 Sidebar To Replace=主边栏,Description=文章目录,Display On=Specific Pages / Posts / …,并指定这篇文章
    2. 然后进入外观 > 小工具,将 LuckyWP 的目录 widget 拖入右侧的「文章目录」中

展示长毛象最新动态(导入RSS)

我实现的效果是,新开一个页面,然后这个页面上显示最新 20 条长毛象更新,并且保留原嘟文的格式(如换行等)。

  1. 安装 Super RSS Reader 插件
  2. 安装 Widgets for Shortcodes 插件
  3. 进入外观 > 小工具,将左侧的 Super RSS Reader 的 widget 拖入右侧的 Widgets for Shortcodes
  4. 将你的 Mastodon RSS(一般是https://example.com/@username.rss)复制粘贴到 widget 的 URL 一栏
  5. 在 widget 的 Content Tab 下,选择 Enable Rich Description,调大 Trim Length(我设置为 200)
  6. 新建一个页面(页面 > 新建页面),将刚才 Widgets for Shortcodes 底部显示的 shortcodes(在一个方括号里)复制粘贴到这个页面中,然后把这个页面加到博客主页上(例如,用它替换 Blocksy 主题自带的 sample page)

编辑器(Markdown、图片等)

编辑器

  • 如果你想用 Markdown 写作,并且能接受双栏渲染(而非像 Typora 一样所见即所得):安装 WP Githuber MD 插件。不过我用到目前为止,觉得 Blocksy 自带的富文本区块编辑器其实也还挺香的,跟豆瓣差不多,颜值也挺高,虽然偶尔有一些蛋疼的地方,但总体来讲蛋疼的程度在可以忍受的范围之内,而且相对来讲比较 distraction free,不至于打断写作思路
  • 可以切换 html 和富文本编辑,所以理论上你可以在博文里嵌入任何东西,包括各种乱七八糟的 JS 等等
  • 手机和平板上可以安装 wordpress 的 app,编辑体验一般吧,代码什么的都不能渲染,还是网页版编辑器方便一些

图片处理

  • 如果图片比较大,有的时候 wordpress 会自动把你上传的 jpg 给压缩得模糊不清。改成上传 png 貌似可以解决,但如果超过了 wordpress 允许的最大图片尺寸,则需要改用图床(我用 uPic)
  • 自动把复制的图片上传到 wordpress 后台:automatic upload images 插件,可以自动把你从别的网站或者图床上复制来的图片给长传到 wordpress 后台,这样哪怕原链接失效了,也还是可以正常显示图片。貌似这个插件还可以绕过 wordpress 对上传图片最大尺寸的限制?
  • 自动设置文章封面图片:Easy Add Thumbnail 插件,它会检查你的文章中是否至少存在一张图片,如果存在则自动将其设为封面(即 feature image)

网站测速和数据统计

  • 安装 Site Kit by Google 插件,可以显示你博客的点击量、点击量来源、访问速度等
  • 测试国内访问你博客的速度:我用过站长工具17ce,都能以地图形式看到你的网站在全国各地的访问速度

✍️ 写文章 

最终的多设备编辑 - 更新体验还是比较流畅顺滑的,这也是我在选择建站方案时最看重的一个因素:

  • 登录后,可以在界面上(文章末尾处)直接点击 “编辑” 按钮进入编辑器修改文章,非常方便。
  • 草稿箱功能非常实用,可以临时记录灵感,方便日后整理成文。
  • 每个设备都可以通过网页版编辑器进行编辑和上传,平板和手机可以选择使用 wordpress app

毕竟无障碍地写博客才是自己建站的核心目的,如果为了折腾而折腾就显得有些本末倒置了。

整个博客搭建好之后只有一个感觉:wordpress 真香!

定制RSSHub等其他服务

一些奇奇怪怪的坑点

总的来说,上面这堆东西全折腾完,零零碎碎的时间加起来怎么也有两三天吧。中间遇到了不少蛋疼的问题,不过好在最后都解决了 🐶。

作者此刻的心理状态⬆️

内存不足

我的服务器一共 1G 内存,光是 Wordpress 的数据库——MySQL 就占了 700-800G,导致我之后连 zsh 都装不上,一装就炸内存,更别提 RSSHub 之类的了。解决方案是参考此贴给服务器加了 1G 的 swap 空间(大概就是允许在内存不足的时候把一部分暂时用不到的数据给腾到硬盘上)。使用 free -h(或者 htop)命令可以查看你的服务器是否已经开启了 swap。如果没有(i.e. swap 容量为零),那么你可以通过开启 swap 来获得更多的虚拟内存:

# 开启1G的swap空间,扩大虚拟内存
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

SSL 超过使用频率限额

是的,免费的 SSL 提供服务 Let’s Encrypt 对每个域名申请 SSL 的频率有限制:Rate Limits – Let’s Encrypt,每周不能申请超过 50 张证书,每周相同的一组域名(比如 example.com 和 www.example.com 这个组合)不能重复申请超过 5 张证书(如果你违背了后面这个 limit,一个简单的 hack 是再加一个二级域名,比如 blog.example.com,然后连带着这个域名一起申请 SSL 证书,这样就不会被视为相同的一组域名了)。如果你在频繁地修改和测试网站,请在 certbot command 里加上--staging选项,测试完没问题了再申请正式 SSL 证书。