Skip to main content

docusaurus仓库搭建

使用github,既然内容都是公开的,那么使用开源项目即可,仓库地址:https://github.com/gqcn/johns-blog

docusaurus静态页面构建

使用githubaction即可,workflow配置:https://github.com/gqcn/johns-blog/blob/main/.github/workflows/build-and-deploy.yml

main 有推送时:yarn 安装依赖,make build 产出 ./build,再用 peaceiris/actions-gh-pages@v4 发到 gh-pages

同时需要配置github pages部署的分支,在Environments / Configure github-pages中配置:

GitHub Pages部署分支配置界面

线上站点并不直接给访客走 GitHub Pages,而是服务器每 5 分钟从 gh-pages 拉构建结果。GitHub Pages 仍作为这份静态产物的托管分支。

压缩仓库体积

Docusaurus 每次构建都会生成带 hash 的 JS/CSS/图片。peaceiris/actions-gh-pages 默认在 gh-pages 上追加 commit,旧构建产物全部留在 Git 对象库里。

只把 main squash 成 1 条提交,体积几乎不会下降:gh-pages 和其它旧分支仍引用那些 blob。压缩前远端大约是:

分支提交数说明
main1reinit
gh-pages6692025-02 起每次部署追加一条 deploy: <sha>
其它残留分支可能仍指向压缩前的 main例如用完未删的 Copilot 分支

当时整个 GitHub 仓库报表体积约 1.27 GiB,主要是 gh-pages 里的历史静态文件。

每次部署只留 1 条 gh-pages

deploy 步骤打开 force_orphan: true。每次发布会把 gh-pages 写成一条没有 parent 的 orphan commit,只包含当前 ./build

.github/workflows/build-and-deploy.yml
      - name: Deploy to github pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./build
force_orphan: true

效果:

  • 远端 gh-pages 永远只有最新 1 条记录,历史 hashed 资源不再进分支
  • 已有 clone 无法对这次改写做 git pull(非快进 / unrelated histories
  • git clone --depth 1 --branch gh-pages 不受影响
  • GitHub 报表体积要等他们 GC 不可达对象,不会立刻变小;长期不用的旧分支也应删掉,否则对象仍被引用

服务器同步方式见下面的定时任务:必须 fetch + reset --hard,不能再 git pull

服务器配置

我没有使用github pages,而是使用的是某云的Linux服务器,国内访问会快一些。

SSL证书申请

关闭nginx服务,避免80端口占用,随后通过以下命令申请SSL证书:

certbot certonly --standalone -d johng.cn --staple-ocsp -m john@johng.cn --agree-tos
certbot certonly --standalone -d www.johng.cn --staple-ocsp -m john@johng.cn --agree-tos

这里申请了两个域名的证书,带www的和不带www的。

配置nginx

配置文件如下:

# johng.cn:80 -> 443
server {
listen 80;
server_name johng.cn;
location / {
rewrite ^/(.*) https://johng.cn permanent;
}
}


# www.johng.cn:443
server {
listen 443 ssl;
server_name www.johng.cn;
ssl_certificate /etc/letsencrypt/live/www.johng.cn/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.johng.cn/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;

access_log /var/log/nginx/www.johng.cn.access.log;
error_log /var/log/nginx/www.johng.cn.error.log;

location / {
rewrite ^/(.*) https://johng.cn/$1 permanent;
}
}

# johng.cn:443
server {
listen 443 ssl;
server_name johng.cn;
ssl_certificate /etc/letsencrypt/live/johng.cn/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/johng.cn/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;

root /home/www/johng.cn;
index index.html index.htm;

access_log /var/log/nginx/johng.cn.access.log;
error_log /var/log/nginx/johng.cn.error.log;

location ~ /\.git {
deny all;
return 403;
}

location / {
try_files $uri $uri.html $uri/ =404;
}

location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
access_log off;
}

gzip on;
gzip_types text/css application/javascript application/x-javascript text/javascript;
gzip_min_length 1024;
}

修改nginx运行用户

修改nginx运行用户,默认用户为www-data,需要修改为root,为避免nginx无法访问/home/www/路径下的网站文件,会报错Permission denied

/etc/nginx/nginx.conf
user root;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;

# ...

配置定时任务

配置定时任务,自动从github同步最新构建结果,并且自动续期SSL证书。定时任务配置文件路径/etc/crontab。站点目录是 www 用户的浅克隆:

sudo -u www -H git clone --depth 1 --branch gh-pages https://github.com/gqcn/johns-blog.git /home/www/johng.cn

gh-pages 每次部署都是 orphan,已有仓库不能快进。+gh-pages:... 强制更新远端跟踪分支,reset --hard 把工作区对齐到最新树,git clean -fd 清掉工作区多余文件,git gc --prune=now 丢掉本机已不可达的旧对象:

# 定时同步最新的官网静态页构建结果。
# gh-pages 每次部署都会 orphan 成 1 条提交,普通 git pull 无法快进,必须 fetch + reset。
*/5 * * * * www (cd /home/www/johng.cn && git fetch --depth=1 origin +gh-pages:refs/remotes/origin/gh-pages && git reset --hard origin/gh-pages && git clean -fd && git gc --prune=now --quiet) > /home/www/github-pull-johng.cn.log 2>&1

# 每天尝试续期一次,证书续期需要先关闭80端口的WebServer监听
0 3 * * * root service nginx stop
5 3 * * * root certbot renew --quiet
8 3 * * * root service nginx start

如果没有启动cron服务的话,需要启动cron服务:

service cron start