A guide on how to deploy static pages generated by your static site generator to self-hosted websites.
使用静态网站生成器 (例如 VuePress/VitePress/Hexo/Hugo 等) 生成静态页面之后, 需要将生成的静态页面部署到自托管的网站上, 之后才能对公网开放, 允许其他人访问. 本文将介绍如何使用 Nginx 将静态页面部署到自托管网站的步骤.
仍然首先将涉及到的概念和 Workflow 介绍一下, 帮助理解我们每一步在做些什么东西.
root 权限. 和它相对的是使用第三方托管服务 (例如 GitHub Pages, Vercel 等), 这些服务器通常有预配置好的构建流水线和部署方式, 需要按照它们的要求来进行部署.所以我们的 Workflow 就很明确了:
接下来我们将按照这个 Workflow 逐步进行介绍. 一个额外的环节是使用 CDN 加速静态资产分发 (例如图片, 音频), 这会放在最后介绍.
购买域名的过程
在服务器上安装 Nginx 非常简单, 以 Ubuntu 为例, 只需要运行以下命令:
sudo apt update
sudo apt install nginx但是通常包管理器里的 Nginx 版本比较老, 一般会建议尽量跟主线版本保持一致来获取更好的安全更新(不过对于个人网站也差别不大). 这里推荐使用 Nginx 的官方源来安装最新版本的 Nginx, 参考 Nginx 官方文档 进行安装. 根据自己的 Linux 发行版选择对应的安装方式即可.
安装后记得启动 Nginx 服务并且设置开机自启:
sudo systemctl start nginx
sudo systemctl enable nginx另一种方式是使用 Docker 来运行 Nginx, 这里就暂且不介绍了.
通常情况下 Nginx 的默认配置文件在 /etc/nginx/nginx.conf, 这是配置文件的主入口, 但通常我们不会直接修改这个文件, 而是将配置放在 /etc/nginx/conf.d/ 目录下的单独文件里, 在主配置中 include 进去(默认配置已经包含好了). 这样主要是为了方便后续维护.
安装好 Nginx 之后你可能会注意到系统多了一个或者两个用户, nginx 和 www-data, 这是 Nginx 运行时使用的用户和组, 它用来运行 Nginx Worker 进程, 但除此之外几乎什么都不做. 这个用户被设计成无法远程登录, 所以如果尝试在 SSH Shell 里面 su nginx 是会失败的.
这样引入了一个权限管理的问题, 也就是 Nginx 进程需要有权限读取静态资产文件, 因为它需要将这些文件返回给用户. 所以我们需要确保静态资产文件所在的目录对 nginx 或者 www-data 用户是可读的. 一个推荐的做法是
sudo groupadd webassets
sudo usermod -aG webassets nginx
sudo usermod -aG webassets $USER
sudo chown -R :webassets /path/to/static/assets
sudo find /path/to/static/assets -type d -exec chmod 750 {} \;
sudo find /path/to/static/assets -type f -exec chmod 640 {} \;这创建了一个新的用户组, 并且将静态文件的所有权交给这个用户组, 这样 Nginx 进程和你自己的用户都可以访问这些文件, 但其他用户则无法访问. 如果直接使用 chown -R nginx:nginx 会导致你自己的账户反而无法访问这些文件, 每次都强制 sudo 又会引入新的权限问题.
Nginx 的配置比较套路化, 对于大多数个人网站来说设置都是差不多的. 这里推荐从 Mozilla 的 SSL Configuration Generator 生成一份基础的 Nginx 配置, 然后在这个基础上进行一些修改. 这个需要根据机器上实际安装的 Nginx 版本和 OpenSSL 版本进行选择.
nginx -v
openssl version对于一个 Web 服务器, Nginx 配置结构很简单
http {
server {
# add your server configuration here
}
}每个 server 块都是一个虚拟主机, 它会监听来自某个域名和端口的请求, 并且根据预先写好的配置将请求映射到静态资产文件上. 下面是一个最简的 Nginx 配置示例:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}在这里它监听来自 example.com 和 www.example.com 的 80 端口请求. 文件的映射规则很简单, 假设用户请求 http://example.com/some/page.html, 其中 $uri 就是 /some/page.html, Nginx 会将这个路径拼接到 root 指定的目录上, 也就是 /var/www/html/some/page.html, 然后尝试从服务器的这个路径读取文件并返回给用户. 如果文件不存在则返回 404 错误.
这是一个直接映射的例子, 你也可以配置复杂的映射规则, 这个非常灵活.
但在现代网站中, 通常使用 HTTPS 进行连接, 对于传统的 HTTP 流量, 会直接将它重定向到 HTTPS 上. 所以你只需要:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}得, 这就完成了 HTTP 到 HTTPS 的重定向, 而且是现代的推荐做法.
另外, 我们通常会定义一个 Fallback Server, 用来处理所有没有匹配到的请求. 否则用户可能可以直接通过 IP 地址访问你的服务器, 或者你的服务器可能被域名劫持.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _; # a catch-all server name
return 444;
}