HomeArchiveBlog


Original contents are licensed under CC BY-NC 4.0. All rights reserved © 2026 Kai.
Back to Archives
Deploying Static Pages to Self-Hosted Sites

A guide on how to deploy static pages generated by your static site generator to self-hosted websites.

Sun Nov 16 2025
Wed Dec 31 2025
Static PagesDeploymentSelf-HostedNginx
On this page
  • Deploying Static Pages to Self-Hosted Sites
    • 涉及到的概念
    • 获取域名和证书
    • 配置自托管服务器
      • 安装 Nginx
      • 配置 Nginx

Deploying Static Pages to Self-Hosted Sites

使用静态网站生成器 (例如 VuePress/VitePress/Hexo/Hugo 等) 生成静态页面之后, 需要将生成的静态页面部署到自托管的网站上, 之后才能对公网开放, 允许其他人访问. 本文将介绍如何使用 Nginx 将静态页面部署到自托管网站的步骤.

涉及到的概念

仍然首先将涉及到的概念和 Workflow 介绍一下, 帮助理解我们每一步在做些什么东西.

  • 使用静态网站生成器生成出来的静态页面, 包括引用的图片, 使用到的 HTML/CSS/JS 等文件, 它们本身在编译完后就不会再发生改变了, 因此这些文件被称为静态资产 (Static Assets).
  • 所以访问页面这个事情, 本质上就是在获取这些静态资产文件, 然后在浏览器中进行渲染.
  • 因此我们需要有一台或者一些服务器, 它监听来自公网的请求, 当有用户请求到达时, 根据需要将对应的静态资产文件返回给用户.
  • 这样的服务器通常被称为 Web 服务器, 常见的 Web 服务器软件有 Nginx, Apache 等. 本文将以 Nginx 为例进行介绍.
  • 自托管网站, 指的是你自己拥有服务器的完全控制权, 你可以在服务器上安装和配置任何你想要的软件, 包括 Web 服务器软件. 这通常意味着你有一台能够连接到公网的服务器, 并且有 root 权限. 和它相对的是使用第三方托管服务 (例如 GitHub Pages, Vercel 等), 这些服务器通常有预配置好的构建流水线和部署方式, 需要按照它们的要求来进行部署.
  • 自托管的好处是可以自定制很多配置, 例如 GeoIP 限制, 访问日志分析等, 但缺点是需要自己维护服务器.

所以我们的 Workflow 就很明确了:

  1. 使用静态网站生成器生成静态页面. (假设已经做好)
  2. 配置一台自托管的服务器, 包括获取域名, 配置 DNS 解析, 安装证书等.
  3. 在服务器上安装 Nginx, 并配置 Nginx 如何响应来自公网的请求, 将请求映射到静态资产文件上.
  4. 将生成的静态资产文件上传到服务器上 Nginx 配置好的目录里.
  5. 测试公网访问.

接下来我们将按照这个 Workflow 逐步进行介绍. 一个额外的环节是使用 CDN 加速静态资产分发 (例如图片, 音频), 这会放在最后介绍.

获取域名和证书

购买域名的过程

配置自托管服务器

安装 Nginx

在服务器上安装 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

通常情况下 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;
}