在轻量级服务器搭建Halo

Reno 于 2024-11-13 发布

博客配置

1c-1g-30G/postgres+halo

搭建步骤

配置环境

截止博客更新时, Halo 要求 JRE 版本 ≥ 17前往官网 下载最新版本

  1. 下载java
     wget -qO- https://download.java.net/java/GA/jdk23/3c5b90190c68498b986a97f276efd28a/37/GPL/openjdk-23_linux-x64_bin.tar.gz | sudo tar -xz -C /opt/
    
  2. 更新环境变量
     sudo cat <<EOF >> /etc/profile
     export JAVA_HOME=/opt/jdk-23
     export PATH=\$PATH:\$JAVA_HOME/bin
     EOF
    
  3. 更新系统默认Java版本

     sudo update-alternatives --install /usr/bin/java java /opt/jdk-23/bin/java 1
     sudo update-alternatives --install /usr/bin/javac javac /opt/jdk-23/bin/javac 1
    
  4. 检查是否配置正确

     sudo update-alternatives --config java
     sudo update-alternatives --config javac
     java -version
    

配置数据库

  1. 安装postgres

    sudo apt update
    sudo apt install postgresql postgresql-contrib
    
  2. 优化配置文件
    sudo vi /etc/postgresql/{version}/main/postgresql.conf 
    

    修改以下配置项

    shared_buffers = 32MB
    work_mem = 1MB
    maintenance_work_mem = 16MB
    autovacuum = on
    
  3. 创建数据库

    sudo -u postgres psql
    
    CREATE DATABASE halo;
    CREATE USER halo_user WITH PASSWORD 'secure_password';
    ALTER ROLE halo_user SET client_encoding TO 'utf8';
    ALTER ROLE halo_user SET default_transaction_isolation TO 'read committed';
    ALTER ROLE halo_user SET timezone TO 'UTC';
    GRANT ALL PRIVILEGES ON DATABASE halo TO halo_user;
    \q
    

配置halo

  1. 创建用户目录

    useradd -m halo
    passwd halo
    su - halo
    
  2. 下载halo.jar

    在 ~/app 目录下载halo 最新版本的运行包,截止博客更新时,最新版本 v2.20.11,点击前往 发布页

    mkdir ~/app && curl -s https://api.github.com/repos/halo-dev/halo/releases/latest | grep "browser_download_url" | grep "\.jar\"" | cut -d '"' -f 4 | xargs curl -L -o ~/app/halo.jar
    
  3. 创建配置文件

    mkdir ~/.halo2 && cd ~/.halo2
    vim application.yaml
       
    server:
       
      # 运行端口
       
      port: 8080
    spring:
      r2dbc:
        url: r2dbc:pool:postgresql://localhost:5432/halo
        username: halo
        password: biubiubiu
      sql:
        init:
          mode: always
          platform: postgresql
    halo:
      caches:
        page:
          # 是否禁用页面缓存
          disabled: false
       
      # 工作目录位置
       
      work-dir: ${user.home}/.halo2
       
      # 外部访问地址
       
      external-url: http://localhost:8080
       
      # 附件映射配置,通常用于迁移场景
       
      attachment:
        resource-mappings:
          - pathPattern: /upload/**
            locations:
              - migrate-from-1.x
    
  4. 测试运行

    cd ~/app && java -Dfile.encoding=UTF-8 -jar halo.jar --spring.config.additional-location=optional:file:$HOME/.halo2/
    

打开 http://ip:8080 即可跳转到初始化页面

配置系统服务

  1. 切换回root用户创建 halo.service

    exit
    vim /etc/systemd/system/halo.service
       
    [Unit]
    Description=Halo Service
    Documentation=https://docs.halo.run
    After=network-online.target
    Wants=network-online.target
       
    [Service]
    Type=simple
    User=halo
    ExecStart=/usr/bin/java -Dfile.encoding=UTF-8 -server -Xms128m -Xmx192m -Xss256k -XX:+UseSerialGC -jar /home/halo/app/halo.jar --spring.config.additional-location=optional:file:/home/halo/.halo2/
    ExecStop=/bin/kill -s QUIT $MAINPID
    Restart=always
    RestartSec=60
    RuntimeMaxSec=259200
    OOMScoreAdjust=500
    StandardOutput=journal
    StandardError=inherit
       
    [Install]
    WantedBy=multi-user.target
    
  2. 运行服务

    sudo systemctl daemon-reload
    sudo systemctl start halo
    sudo systemctl enable halo
    
  3. 查看日志

    journalctl -n 20 -u halo
    

配置nginx

  1. 下载证书

    前往 ZeroSSL 下载90天证书并将证书解压到 /etc/nginx/ssl/domain.com

  2. 替换 /etc/nginx/nginx.conf

    user www-data;
    worker_processes 1;
    pid /run/nginx.pid;
       
    worker_rlimit_nofile 4096;
       
    events {
        worker_connections 1024;
        use epoll;
    }
       
    http {
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 30;
        types_hash_max_size 1024;
        client_max_body_size 128m;
        server_tokens off;
       
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
           
        access_log off;
        error_log /var/log/nginx/error.log;
           
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;
        ssl_session_cache shared:SSL:5m;
        ssl_session_timeout 10m;
           
        ssl_stapling on;
        ssl_stapling_verify on;
        resolver 8.8.8.8 8.8.4.4 valid=300s;
        resolver_timeout 5s;
           
        open_file_cache max=500 inactive=10s;
        open_file_cache_valid 20s;
        open_file_cache_min_uses 1;
        open_file_cache_errors on;
           
        server {
            listen 80;
            server_name domain.com;
            return 301 https://$host$request_uri;
        }
           
        server {
            listen 443 ssl;
            http2 on;
            server_name domain.com;
           
            ssl_certificate /etc/nginx/ssl/domain.com/certificate.crt;
            ssl_certificate_key /etc/nginx/ssl/domain.com/private.key;
            ssl_trusted_certificate /etc/nginx/ssl/domain.com/ca_bundle.crt;
           
            ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
           
            add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
            add_header X-Frame-Options SAMEORIGIN;
            add_header X-Content-Type-Options nosniff;
            add_header X-XSS-Protection "1; mode=block";
           
            location / {
                proxy_pass http://localhost:8080;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection 'upgrade';
                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;
                proxy_buffering on;
                proxy_buffer_size 64k;
                proxy_buffers 4 128k;
                proxy_busy_buffers_size 128k;
                proxy_connect_timeout 30s;
                proxy_send_timeout 30s;
                proxy_read_timeout 30s;
            }
        }
       
    }
    

备份和恢复

进入后台,点击左侧 备份 - + 创建备份,备份后依次点击右侧 ··· - 下载 下载到本地

进入后台,点击左侧 备份 - 恢复 - 我已阅读上方提示,开始恢复,选择备份文件进行恢复

更新

为避免破坏性更新,建议等待新版本发布一周后再考虑更新,更新前先停止服务

  1. 停止服务

    sudo systemctl stop halo
    
  2. 下载jar包

    切换到 halo 用户,在 ~/app 目录下载最新版本的 Halo 运行包,覆盖原有的运行包

    su halo
    curl -s https://api.github.com/repos/halo-dev/halo/releases/latest | grep "browser_download_url" | grep "\.jar\"" | cut -d '"' -f 4 | xargs curl -L -o ~/app/halo.jar
    
  3. 重启服务

    切换回管理员用户执行重启

    exit
    sudo systemctl start halo
    

番外一:配置Umami服务

Umami 是一款开源的类 Google Analytics 工具,Halo 已经提供了插件支持,可直接在插件市场搜索安装插件搭配 Umami 服务使用

容器部署

使用 render、koyeb这样的免费容器部署,克隆仓库:https://github.com/Raimbaulty/umami 后连接到仓库

环境变量

变量名称 示例值 描述
ALLOWED_FRAME_URLS https://example.com,https://domain.com 允许嵌入的站点地址,多个用逗号分隔
APP_SECRET your_app_secret_key 应用安全密钥,务必保密
DATABASE_TYPE postgres 数据库类型,如 mysql, postgres, sqlite
DATABASE_URL postgresql://user:password@host:port/db 数据库连接 URL
TRACKER_SCRIPT_NAME index.js 自命名追踪脚本,防止被广告拦截插件拦截

添加站点

服务运行后,访问容器地址使用默认用户名 admin 默认密码 umami登录,点击右上角 🌐 切换语言为中文

导航栏点击 设置+ 添加网站,填写网站名称和域名(不带 https:// 协议头)后 保存

点击 编辑,首先复制 网站 ID 保存,然后切换到 共享链接 标签,打开 启用共享链接 并复制 Your website stats are publicly available at the following URL: 的值作为下一步 共享链接 的值填入

配置插件

在应用市场搜索 Umami 并安装,然后在 插件 开启 Umami 并点击 ··· 进入 详情,切换到 设置 标签进行设置

传统部署

配置环境

su - halo
curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
source ~/.profile
nvm install 18
nvm use 18
npm install -g yarn

配置数据库

sudo -u postgres psql
CREATE DATABASE umami;
CREATE USER umami_user WITH PASSWORD 'secure_password';
ALTER ROLE umami_user SET client_encoding TO 'utf8';
ALTER ROLE umami_user SET default_transaction_isolation TO 'read committed';
ALTER ROLE umami_user SET timezone TO 'UTC';
GRANT ALL PRIVILEGES ON DATABASE umami TO umami_user;
\q

配置umami

su - halo
git clone https://github.com/umami-software/umami.git umami && cd $_
cat > .env <<EOF
DATABASE_URL=postgresql://umami_user:secure_password@localhost:5432/umami
EOF
yarn install
yarn build

如果是1C1G的轻量机,先终止其他服务释放内存然后执行下面的指令构建

NODE_OPTIONS="--max-old-space-size=1024" yarn build

配置服务

sudo cat <<EOF > /etc/systemd/system/umami.service
[Unit]
Description=Umami Service
After=network.target

[Service]
Type=simple
User=halo
ExecStart=/home/halo/.nvm/versions/node/v18.20.7/bin/yarn start
Restart=always
Environment=PATH=/usr/bin:/usr/local/bin:/home/halo/.nvm/versions/node/v18.20.7/bin
Environment=NODE_ENV=production
WorkingDirectory=/home/halo/umami

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl start umami
sudo systemctl enable umami
sudo systemctl status umami

配置nginx

注意替换umami.com为umami站点地址,domain.com为halo站点地址

server {
  listen 80;
  listen [::]:80;

  server_name umami.com;
  
  return 301 https://$host$request_uri;
}

server {
  listen 443 ssl http2;
  server_name umami.com;

  ssl on;
  ssl_certificate      /etc/nginx/cert/umami.com/certificate.crt;
  ssl_certificate_key  /etc/nginx/cert/umami.com/private.key;
  ssl_trusted_certificate /etc/nginx/ssl/umami.com/ca_bundle.crt;

  add_header Access-Control-Allow-Origin 'https://[halo.domain.com]';
  add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
  add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
  if ($request_method = 'OPTIONS') {
    return 204;
  }
  add_header Content-Security-Policy 'frame-ancestors domain.com'; 
  location / {
    proxy_pass http://localhost:3000;
    proxy_set_header HOST $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_hide_header 'Access-Control-Allow-Origin';
    proxy_hide_header 'Content-Security-Policy';
  }
}

更新

sudo systemctl stop umami
su - halo && cd umami
git pull
yarn install
yarn build
sudo systemctl start umami

番外二:部署Huggingface备份

以下教程使用 H2 数据库,只建议用作博客备份

创建空间

点击这里 创建,space name 填写 halo,License 选择 Apache2.0,点击 Docker - Blank,确认勾选 Public,然后点击 Create Space 创建

空间创建后,需要修改或创建以下文件,.gitattributes 无需修改

📦 main
├── 📄 .gitattributes
├── 📄 Dockerfile
├── 📄 sync_data.sh
└── 📄 README.md

下面依次介绍除 .gitattributes 外各文件配置

配置Dockerfile

配置sync_data.sh

配置README.md

添加Secrets

点击 Settings 菜单,下滑找到并点击New secret 按钮

变量名 示例值 描述
HF_TOKEN hf_xxxxxxxxxxxxxx Huggingface令牌:前往创建
变量名 示例值 描述
DATASET_ID Owner/data 数据集地址
SYNC_INTERVAL 36000 备份间隔,单位:秒
DATASET_N 10 备份容量
BACKUP_DIR $HOME/.halo2 备份目录

备份到Huggingface

参考链接