nyaruta

nyaruta

文章都是 mx-space 同步来的 如果有渲染问题请移步 lar.moe

Mix-Space + Shiro 搭建

Mix Space 是一个小型个人空间站点程序。不同于传统的博客程序,采用前后端分离设计, 适合那些喜欢写不同风格或类型的写作爱好者。

> [!NOTE] > 此文章仅适用于单服务器部署前后端 > > 并且前后端均使用同一子域名 > > 如果您使用 SaaS / 服务器面板 请参阅 [其他社区教程](https://mx-space.js.org/docs/core/community)

准备工作#

  • 服务器 * 1

    • Kernel > 4.18
    • RAM > 1G (推荐 2G 以上,Next 编译很吃内存 太低可能 OOM)
    • SWAP > 2G (可选 内存够大可忽略)
  • 域名 * 1

  • SSL 证书 * 1

    Note

    对于 CDN 用户:

如果您在源服务器端使用自签证书 那么您需要将自签证书的 CA 加入到系统 CA 库或手动信任证书 否则可能会导致前端请求后端失败

后端#

  1. 拉取 Docker Compose 配置文件模板

    cd && mkdir -p mx-space/core && cd $_
    curl https://https://raw.githubusercontent.com/mx-space/core/refs/heads/master/docker-compose.yml -o docker-compose.yml
    
  2. 编辑刚刚下载下来的 docker-compose.yml

     services:
       app:
         container_name: mx-server
         image: innei/mx-server:latest
         environment:
           - TZ=Asia/Shanghai
           - NODE_ENV=production
           - DB_HOST=mongo
           - REDIS_HOST=redis
           - ALLOWED_ORIGINS=localhost # 这里加上你的域名 用逗号分隔
           - JWT_SECRET=YOUR_SUPER_SECURED_JWT_SECRET_STRING # 这里用 openssl 生成一个
           - ENCRYPT_ENABLE=false # 是否启用加密 一般不动它
           - ENCRYPT_KEY=069d51c5e6f09e1d806e4dedb1c7bc620c29a67c91a984547911be8a846cf6cb # 示例值
         volumes:
           - ./data/mx-space:/root/.mx-space
         ports:
          - '2333:2333'
         depends_on:
           - mongo
           - redis
         networks:
           - mx-space
         restart: unless-stopped
         healthcheck:
           test: ['CMD', 'curl', '-f', 'http://127.0.0.1:2333/api/v2/ping']
           interval: 1m30s
           timeout: 30s
           retries: 5
           start_period: 30s
    
       mongo:
         container_name: mongo
         image: mongo
         volumes:
           - ./data/db:/data/db
         networks:
           - mx-space
         restart: unless-stopped
    
       redis:
         image: redis:alpine
         container_name: redis
         volumes:
           - ./data/redis:/data
         healthcheck:
         test: ['CMD-SHELL', 'redis-cli ping | grep PONG']
         start_period: 20s
         interval: 30s
         retries: 5
         timeout: 3s
     networks:
       - mx-space
     restart: unless-stopped
    
     networks:
       mx-space:
         driver: bridge
    

Important

若开启加密,则需注意密钥长度必须为 64 位且只有小写字母和数字,不然会在初始化时报错。注意这是不可逆的,务必保存自己的秘钥。所以并不是非常推荐使用,除非你真的需要加密 API Key.

密钥可以通过 openssl rand -hex 32 命令生成。请务必牢记。

参见 Key 加密与安全性

  1. 启动后端

    docker compose up -d
    
  2. 配置反向代理

    以下是一个示例文件

    server {
     listen 80;
     listen 443 ssl;
     listen 443 quic; # 仅 nginx 1.25.0 以上版本可用 其他版本请删去这行
     server_name YOUR_SERVER_NAME; #改成你的域名
     ssl_certificate path/to/certificate; # SSL 证书路径
     ssl_certificate_key path/to/key; # SSL 证书密钥路径
     # Reverse proxy
     # This is a example for nginx configure if you host mx-space manually
     location / {
         proxy_pass http://127.0.0.1:2323;
         proxy_set_header Host $host;
         proxy_intercept_errors on;
     }
     location ^~ /api/v2 {
         proxy_pass http://127.0.0.1:2333/api/v2;
         proxy_set_header Host $host;
         proxy_redirect off;
         proxy_buffering off;
     }
     location /proxy/qaqdmin {
         proxy_set_header Host $host;
         proxy_pass http://127.0.0.1:2333/proxy/qaqdmin;
     }
     location ^~ /proxy/ {
         proxy_set_header Host $host;
         proxy_pass http://127.0.0.1:2333/proxy/;
     }
     location ^~ /render/ {
         proxy_set_header Host $host;
         proxy_pass http://127.0.0.1:2333/render/;
     }
     location ^~ /socket.io {
         proxy_pass http://127.0.0.1:2333/socket.io;
         proxy_set_header Host $host;
         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_http_version 1.1;
         proxy_buffering off;
         proxy_redirect off;
         proxy_set_header Upgrade $http_upgrade;
         proxy_set_header Connection "Upgrade";
         proxy_set_header Host $host;
         proxy_set_header X-Forwarded-Proto $scheme;
     }
    

}


在 `nginx.conf` 中引用此文件

```nginx filename="/etc/nginx/nginx.conf"
http {
   ...
   include /etc/nginx/sites-enabled/*;
   ...
}
  1. 初始化后端
    1. 设置好域名解析
    2. 打开 https://<YOUR_DOMAIN>/proxy/qaqdmin
    3. 根据提示完成初始化
    4. 前往 设定 > 网站设置 按如下格式设置
项目
前端地址https://<YOUR_DOMAIN>
管理后台地址https://<YOUR_DOMAIN>/proxy/qaqdmin
API 地址https://<YOUR_DOMAIN>/api/v2
Gateway 地址https://<YOUR_DOMAIN>

至此后端大功告成

前端 (Shiro)#

  1. 初始化环境
```shell curl -fsSL https://deb.nodesource.com/setup_current.x | sudo bash - sudo apt-get install -y nodejs npm install -g pm2 curl -fsSL https://get.pnpm.io/install.sh | sh - ``` 重新登录服务器 ```shell sudo pacman -S nodejs npm pnpm pm2 ``` 2. 拉取仓库 & 安装依赖
cd ~/mx-space
git clone https://github.com/Innei/Shiro.git
cd Shiro
git submodule init && git submodule update
pnpm i
  1. 设置主题配置

进入 Mix Space 后台,进入「配置与云函数」页面,点击右上角的新增按钮,在编辑页面中,填入以下设置:

Important

请注意,这份配置你需要自行修改成符合你的需求的配置。直接使用下面的配置可能会导致你的博客无法按照你的预期运行。

下面的配置可能不全,更多配置项的信息请移步 配置项 了解

此外,配置也可写成 yaml 格式,此时数据类型应选择 YAML

关于 ” 我的动态 “ 功能 详见官方文档

- 名称:`shiro`
- 引用:`theme`
- 数据类型:`JSON`
- 数据:(点击下方的按钮复制)

```json
{
"footer": {
    "otherInfo": {
        "date": "2020-{{now}}",
        "icp": {
            "text": "萌 ICP 备 20236136 号",
            "link": "https://icp.gov.moe/?keyword=20236136"
        }
    },
    "linkSections": [
        {
            "name": "关于",
            "links": [
                {
                    "name": "关于本站",
                    "href": "/about-site"
                },
                {
                    "name": "关于我",
                    "href": "/about"
                },
                {
                    "name": "关于此项目",
                    "href": "https://github.com/innei/Shiro",
                    "external": true
                }
            ]
        },
        {
            "name": "更多",
            "links": [
                {
                    "name": "时间线",
                    "href": "/timeline"
                },
                {
                    "name": "友链",
                    "href": "/friends"
                },
                {
                    "name": "监控",
                    "href": "https://status.innei.in/status/main",
                    "external": true
                }
            ]
        },
        {
            "name": "联系",
            "links": [
                {
                    "name": "写留言",
                    "href": "/message"
                },
                {
                    "name": "发邮件",
                    "href": "mailto:[email protected]",
                    "external": true
                },
                {
                    "name": "GitHub",
                    "href": "https://github.com/innei",
                    "external": true
                }
            ]
        }
    ]
},
"config": {
    "color": {
        "light": [
            "#33A6B8",
            "#FF6666",
            "#26A69A",
            "#fb7287",
            "#69a6cc",
            "#F11A7B",
            "#78C1F3",
            "#FF6666",
            "#7ACDF6"
        ],
        "dark": [
            "#F596AA",
            "#A0A7D4",
            "#ff7b7b",
            "#99D8CF",
            "#838BC6",
            "#FFE5AD",
            "#9BE8D8",
            "#A1CCD1",
            "#EAAEBA"
        ]
    },
    "bg": [
        "https://github.com/Innei/static/blob/master/images/F0q8mwwaIAEtird.jpeg?raw=true",
        "https://github.com/Innei/static/blob/master/images/IMG_2111.jpeg.webp.jpg?raw=true"
    ],
    "custom": {
        "css": [],
        "styles": [],
        "js": [],
        "scripts": []
    },
    "site": {
        "favicon": "/innei.svg",
        "faviconDark": "/innei-dark.svg"
    },
    "hero": {
        "title": {
            "template": [
                {
                    "type": "h1",
                    "text": "Hi, I'm ",
                    "class": "font-light text-4xl"
                },
                {
                    "type": "h1",
                    "text": "Innei",
                    "class": "font-medium mx-2 text-4xl"
                },
                {
                    "type": "h1",
                    "text": "👋。",
                    "class": "font-light text-4xl"
                },
                {
                    "type": "br"
                },
                {
                    "type": "h1",
                    "text": "A NodeJS Full Stack ",
                    "class": "font-light text-4xl"
                },
                {
                    "type": "code",
                    "text": "<Developer />",
                    "class": "font-medium mx-2 text-3xl rounded p-1 bg-gray-200 dark:bg-gray-800/0 hover:dark:bg-gray-800/100 bg-opacity-0 hover:bg-opacity-100 transition-background duration-200"
                },
                {
                    "type": "span",
                    "class": "inline-block w-[1px] h-8 -bottom-2 relative bg-gray-800/80 dark:bg-gray-200/80 opacity-0 group-hover:opacity-100 transition-opacity duration-200 group-hover:animation-blink"
                }
            ]
        },
        "description": "An independent developer coding with love."
    },
    "module": {
        "activity": {
            "enable": true,
            "endpoint": "/fn/ps/update"
        },
        "donate": {
            "enable": true,
            "link": "https://afdian.net/@Innei",
            "qrcode": [
                "https://cdn.jsdelivr.net/gh/Innei/img-bed@master/20191211132347.png",
                "https://cdn.innei.ren/bed/2023/0424213144.png"
            ]
        },
        "bilibili": {
            "liveId": 1434499
        }
    }
}

}

```
保存修改

4. 修改环境变量

nano .env

示例:

NEXT_PUBLIC_API_URL=http://localhost:2333
NEXT_PUBLIC_GATEWAY_URL=http://localhost:2333

NEXT_PUBLIC_API_URL=https://<YOUR_DOMAIN>/api/v2
NEXT_PUBLIC_GATEWAY_URL=https://<YOUR_DOMAIN>
# 以下可选
TMDB_API_KEY=
GH_TOKEN=
  1. 编译
pnpm run build
  1. 启动

    pnpm prod:pm2
    

至此前后端全部完成

一些小技巧#

加速前后端之间的连接#

背景#

对于 CDN 用户而言 默认情况下前端会经过 CDN 来请求后端接口 这增加了延迟 并且提高了编写 WAF 规则的难度 带来了不便

解决#

由于我们的前后端位于同一台服务器 因此我们可以通过在服务器端将域名解析为 localhost127.0.0.1 的方式 使请求不经过 CDN 直达后端来达到加速的目的

echo -e "127.0.0.1 <YOUR_DOMAIN>" | sudo tee -a /etc/hosts

Important

请仔细检查你的 hosts 文件是否由 cloud-init 管辖

如果是 你需要更改 cloud-init 的模板而非直接更改 /etc/hosts

关于 favicon#

背景#

虽然可以通过配置文件来修改 favicon
但是在某些情况下 (比如 Cloudflare 质询) 获取到的 favicon 是 Shiro 默认 favicon
所以我有点难受

解决#

我决定使用 git alias git submodulegit hooks 来解决
首先 新建一个 Git 仓库用来存 favicon
示例

删除原来的 public 文件夹 并添加子模块

  rm -rf {SHIRO_PATH}/public && git rm -rfq public
  git submodule --quiet add --force {YOUR_REPO} public
  git submodule --quiet update --init --remote
  git submodule --quiet sync

设置 git alias

   git config --global alias.pull-clean '!git fetch && test $(git rev-list --count HEAD..@{upstream}) -gt 0 && git reset --hard && git clean -fd && git pull'

添加 post-merge Git Hook

  #!/bin/sh

  . git-sh-setup

  echo "Replacing public folder"
  rm -rf public && git rm -rfq public
  git submodule --quiet add --force https://github.com/nyaruta/Shiro-Assets.git public
  echo "Syncing submodules"
  git submodule --quiet update --init --remote
  git submodule --quiet sync

添加执行权限

   chmod +x .git/hooks/post-merge

这样每次拉取仓库时 把 git pull 替换为 git pull-clean 即可在不产生冲突的情况下执行我们对 favicon 的更改

Important

添加完 Git Hooks 之后执行 pnpm install 需要加 --ignore-scripts 参数 不然会自动执行 prepare 脚本覆盖掉我们的 hook

好了 暂时也没想到什么新的小技巧 就到此为止吧

此文由 Mix Space 同步更新至 xLog
原始链接为 https://lar.moe/posts/deploy/mx-space


加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。