<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[一叶轻舟]]></title><description><![CDATA[记录人生旅途的轻声细语]]></description><link>https://but.bio</link><image><url>https://img.pub/p/7d0aee1e7f69e747b24c.jpg</url><title>一叶轻舟</title><link>https://but.bio</link></image><generator>Shiro (https://github.com/Innei/Shiro)</generator><lastBuildDate>Wed, 06 May 2026 13:46:24 GMT</lastBuildDate><atom:link href="https://but.bio/feed" rel="self" type="application/rss+xml"/><pubDate>Wed, 06 May 2026 13:46:24 GMT</pubDate><language><![CDATA[zh-CN]]></language><item><title><![CDATA[Mix Space 博客搭建指南]]></title><description><![CDATA[<div><blockquote>该渲染由 Shiro API 生成，可能存在排版问题，最佳体验请前往：<a href="https://but.bio/posts/default/mix-space-blog-guide">https://but.bio/posts/default/mix-space-blog-guide</a></blockquote><div><h2 id="docker-">入门篇：Docker 部署</h2><p><strong>推荐指数</strong>：★★★★★</p><p><strong>难度指数</strong>：★</p><p>使用 Docker 部署，前后端不做分离，部署要求如下：</p><ul><li>1台服务器，要求内存 &gt;<strong>1G</strong></li><li>1个域名（国内服务器需备案）</li></ul><p><strong>注意</strong>：后端默认不带主题，运行服务后还需登入后台管理界面 <code>https://www.blog.com/proxy/qaqdmin</code> 参照 <strong>云函数</strong> 配置主题</p><h3 id="">配置文件</h3><p>文件目录结构如下，<code>.env</code> 和 <code>docker-compose.yml</code>需要用户创建，<strong>data</strong> 目录在容器运行后自动生成</p><pre class=""><code class="">📂 ~/mix-space
│
├── 📜 .env
├── 📜 docker-compose.yml
└── 📂 data
    ├── 📂 mongo
    ├── 📂 redis
    └── 📂 core</code></pre><h4 id="env">.env</h4><p><strong>注意</strong>：API 相关配置 一般不需修改</p><pre class="language-ini lang-ini"><code class="language-ini lang-ini"># 💻 前端配置
# 🌐 API 相关配置
NEXT_PUBLIC_API_URL=http://core:2333/api/v2
NEXT_PUBLIC_GATEWAY_URL=http://core:2333/

# 🔑 认证 &amp; API 密钥
TMDB_API_KEY=
GH_TOKEN=

# 🖥️ 后端配置
# 🔐 安全性配置
JWT_SECRET=G7xJpQzW8mV4L2YfK9N6T1RbX3dMC0H(32位)
ALLOWED_ORIGINS=
ENCRYPT_KEY=593f62860255feb0a914534a43814b9809cc7534da7f5485cd2e3d3c8609acab(64位)
ENCRYPT_ENABLE=false

# 🚀 缓存相关配置
CDN_CACHE_HEADER=true
FORCE_CACHE_HEADER=false

# 🛢 数据库配置
MONGO_CONNECTION=

# ⚡ 请求限流（Throttle）
THROTTLE_TTL=10
THROTTLE_LIMIT=20
</code></pre>
<h4 id="dockers-composeyml">dockers-compose.yml</h4><pre class="language-yaml lang-yaml"><code class="language-yaml lang-yaml">services:
  shiro:
    container_name: shiro
    image: innei/shiro:latest
    volumes:
      - ./.env:/app/.env
    restart: always
    environment:
      - NEXT_SHARP_PATH=/usr/local/lib/node_modules/sharp
    ports:
      - &quot;127.0.0.1:2323:2323&quot;
    depends_on:
      - core
    networks:
      - mix-space

  core:
    container_name: core
    image: innei/mx-server:latest
    environment:
      - TZ=Asia/Shanghai
      - NODE_ENV=production
      - DB_HOST=mongo
      - REDIS_HOST=redis
    volumes:
      - ./data/core:/root/.mx-space
    ports:
      - &quot;127.0.0.1:2333:2333&quot;
    depends_on:
      - mongo
      - redis
    networks:
      - mix-space
    restart: unless-stopped
    healthcheck:
      test: [&quot;CMD&quot;, &quot;curl&quot;, &quot;-f&quot;, &quot;http://127.0.0.1:2333/api/v2/ping&quot;]
      interval: 1m30s
      timeout: 30s
      retries: 5
      start_period: 30s

  mongo:
    container_name: mongo
    image: mongo
    volumes:
      - ./data/mongo:/data/db
    networks:
      - mix-space
    restart: unless-stopped

  redis:
    image: redis:alpine
    container_name: redis
    volumes:
      - ./data/redis:/data
    healthcheck:
      test: [&quot;CMD-SHELL&quot;, &quot;redis-cli ping | grep PONG&quot;]
      start_period: 20s
      interval: 30s
      retries: 5
      timeout: 3s
    networks:
      - mix-space
    restart: unless-stopped

networks:
  mix-space:
    driver: bridge
</code></pre>
<h3 id="nginx">nginx反代</h3><p>请在域名（以<code>www.blog.com</code>为例）添加一条 A记录指向服务器 IP，然后添加以下 server 块</p><pre class="language-nginx lang-nginx"><code class="language-nginx lang-nginx">server {
    listen 80;
    listen 443 ssl http2 ; 
   
    server_name www.blog.com; 
    index index.html; 
    proxy_set_header Host $host; 
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
    proxy_set_header X-Forwarded-Host $server_name; 
    proxy_set_header Upgrade $http_upgrade; 
    proxy_set_header Connection &quot;upgrade&quot;; 
    error_log /www/sites/www.example.com/log/error.log;
    access_log /www/sites/www.example.com/log/access.log; 
    location /socket.io {
        proxy_set_header Upgrade $http_upgrade; 
        proxy_set_header Connection &quot;Upgrade&quot;; 
        proxy_set_header Host $host; 
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
        proxy_set_header X-Forwarded-Proto $scheme; 
        proxy_pass http://127.0.0.1:2333/socket.io; 
    }
    location /api/v2 {
        proxy_pass http://127.0.0.1:2333/api/v2; 
    }
    location /render {
        proxy_pass http://127.0.0.1:2333/render; 
    }
    location / {
        proxy_pass http://127.0.0.1:2323; 
    }
    location /qaqdmin {
        proxy_pass http://127.0.0.1:2333/proxy/qaqdmin;
    }
    location /proxy {
        proxy_pass http://127.0.0.1:2333/proxy;
    }
 
    location ~* \/(feed|sitemap|atom.xml) {
        proxy_pass http://127.0.0.1:2333/$1; 
    }
    ssl_certificate /www/sites/www.example.com/ssl/fullchain.pem; 
    ssl_certificate_key /www/sites/www.example.com/ssl/privkey.pem; 
    ssl_protocols TLSv1.3 TLSv1.2 TLSv1.1 TLSv1; 
    ssl_ciphers &#x27;ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK&#x27;; 
    ssl_prefer_server_ciphers on; 
    ssl_session_cache shared:SSL:10m; 
    ssl_session_timeout 10m; 
    error_page 497 https://$host$request_uri; 
    limit_conn perserver 300; 
    limit_conn perip 25; 
    limit_rate 512k; 
}
</code></pre>
<h2 id="">进阶篇：传统方法部署</h2><p><strong>推荐指数</strong>：★★★</p><p><strong>难度指数</strong>：★★★</p><p>构建部署，前后端分离，部署要求如下：</p><ul><li><p><strong>简单部署/自动部署</strong>：</p><ul><li><p>1台服务器，要求内存&gt;<strong>1G</strong></p></li><li><p>2个域名，可以是子域名</p></li></ul></li><li><p><strong>手动部署</strong></p><ul><li>1台服务器，要求内存&gt;<strong>2G</strong></li><li>2个域名，可以是子域名</li></ul></li></ul><p><strong>注意</strong>：后端默认不带主题，运行服务后还需登入后台管理界面 <code>https://backend.blog.com/proxy/qaqdmin</code> 参照 <strong>云函数</strong> 配置主题</p><h3 id="">构建后端</h3><h4 id="">准备环境</h4><ul><li><p>安装 nodejs，建议安装 20.12.2 版本</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">sudo apt-get install curl
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
nvm install 20.12.2
</code></pre>
</li><li><p>安装 redis</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">sudo apt-get install redis-server
</code></pre>
</li><li><p>安装 mongodb，这里以 <strong>Ubuntu 24.04</strong> 为例</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">sudo apt-get install gnupg

curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | \
   sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg \
   --dearmor
echo &quot;deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/8.0 multiverse&quot; | sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list

sudo apt-get update
sudo apt-get install -y mongodb-org
sudo systemctl start mongod
sudo systemctl enable mongod
sudo systemctl status mongod
</code></pre>
<p>其余系统安装可参考：<a href="https://www.mongodb.com/zh-cn/docs/manual/installation/">MongoDB 官方文档</a></p></li></ul><h4 id="">简单部署</h4><p>后端仓库：<a href="https://github.com/mx-space/core">Mix Space/core</a></p><ul><li><p>直接下载构建好的 linux 版</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">mkdir ~/mix-space/core &amp;&amp; cd $_
curl -L -O https://github.com/mx-space/core/releases/latest/download/release-linux.zip
unzip release-linux.zip
rm release-linux.zip
</code></pre>
</li><li><p>生成32位和64位字符</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">openssl rand -base64 24 | cut -c1-32 # 用于jwt_secret
openssl rand -base64 48 | cut -c1-64 # 用于encrypt key
</code></pre>
</li><li><p>编辑<code>ecosystem.config.js</code></p><pre class="language-js lang-js"><code class="language-js lang-js">const { cpus } = require(&#x27;os&#x27;);
const { execSync } = require(&#x27;child_process&#x27;);
const nodePath = execSync(`npm root --quiet -g`, { encoding: &#x27;utf-8&#x27; }).trim();
const cpuLen = cpus().length;

module.exports = {
  apps: [
    {
      name: &#x27;mix-space&#x27;,
      script: &#x27;index.js&#x27;,
      autorestart: true,
      exec_mode: &#x27;cluster&#x27;,
      watch: false,
      instances: cpuLen,
      max_memory_restart: &#x27;500M&#x27;,
      args: [
        &#x27;--color&#x27;,
        &#x27;--encrypt_enable&#x27;,
        &#x27;--encrypt_key ********************************(64位)&#x27;,
        &#x27;--port 2333&#x27;,
        &#x27;--allowed_origins example1.com,example2.com,localhost&#x27;,
        &#x27;--jwt_secret ********************(16~32位)&#x27;,
      ].join(&#x27; &#x27;),
      env: {
        NODE_ENV: &#x27;production&#x27;,
        NODE_PATH: nodePath,
      },
    },
  ],
};
</code></pre>
</li><li><p>启动后端服务</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">npm install -g pm2
pm2 start ecosystem.config.js
</code></pre>
</li></ul><h4 id="">手动部署</h4><ul><li><p>安装后端服务</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">mkdir ~/mix-space &amp;&amp; cd $_
git clone https://github.com/mx-space/core.git --depth=1
cd core
npm install -g pnpm
pnpm i
</code></pre>
</li><li><p>构建后端服务</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">pnpm build
pnpm bundle
</code></pre>
</li><li><p>创建符号链接，并参照 <strong>简单部署</strong> 修改 <code>ecosystem.config.js</code></p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">ln -s ./app/core/ecosystem.config.js ecosystem.config.js
</code></pre>
</li><li><p>启动后端服务</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">npm install -g pm2
pm2 start ecosystem.config.js
</code></pre>
</li></ul><h3 id="">构建前端</h3><h4 id="">准备环境</h4><ul><li><p>安装依赖</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
nvm install 20.12.2
npm install -g pnpm pm2 
npm i -g sharp
</code></pre>
</li></ul><h4 id="">简单部署</h4><ul><li><p>前端仓库：<a href="https://github.com/Innei/Shiro">Innie/Shiro</a></p></li><li><p>直接下载构建好的 linux 版</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">mkdir ~/mix-space/shiro &amp;&amp; cd $_
curl -L -O https://github.com/Innei/Shiro/releases/latest/download/release.zip
unzip release.zip
rm release.zip
</code></pre>
</li><li><p>编辑<code>ecosystem.config.js</code></p><pre class="language-js lang-js"><code class="language-js lang-js">module.exports = {
  apps: [
    {
      name: &#x27;shiro&#x27;,
      script: &#x27;server.js&#x27;,
      autorestart: true,
      watch: false,
      max_memory_restart: &#x27;500M&#x27;,
      env: {
        PORT: 2323,
        NODE_ENV: &#x27;production&#x27;,
        NEXT_SHARP_PATH: process.env.NEXT_SHARP_PATH,
        NEXT_PUBLIC_API_URL: &#x27;http://127.0.0.1:2323/api/v2&#x27;,
        NEXT_PUBLIC_GATEWAY_URL: &#x27;http://127.0.0.1:2323&#x27;
      },
      log_date_format: &#x27;YYYY-MM-DD HH:mm:ss&#x27;,
    },
  ],
}
</code></pre>
</li><li><p>启动前端服务</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">pm2 start ecosystem.config.js
</code></pre>
</li></ul><h4 id="">自动部署</h4><ul><li><p>创建前端目录</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">mkdir -p ~/mix-space/shiro &amp;&amp; cd $_
</code></pre>
<p>编辑环境变量<code>.env</code></p><pre class="language-ini lang-ini"><code class="language-ini lang-ini">NEXT_PUBLIC_API_URL=https://example.net/api/v2
NEXT_PUBLIC_GATEWAY_URL=https://example.net
TMDB_API_KEY=
GH_TOKEN=
</code></pre>
</li><li><p>Fork 前端仓库，等待完成后进入 <strong>Actions</strong> 标签启用 Workflow，接着进入 <strong>Settings</strong> 标签，左侧点击 [<strong>Secrets and variables]</strong> - [<strong>Actions] - [New repository secret]</strong> 添加以下变量</p></li></ul><table><thead><tr><th style="text-align:left"> <strong>Name</strong> </th><th style="text-align:left"> <strong>Secret</strong>                         </th><th style="text-align:left"> <strong>Description</strong>              </th></tr></thead><tbody><tr><td style="text-align:left"> HOST     </td><td style="text-align:left"> <a href="http://example.com/">example.com</a> </td><td style="text-align:left"> SSH 登录地址                 </td></tr><tr><td style="text-align:left"> PORT     </td><td style="text-align:left"> 22                                 </td><td style="text-align:left"> SSH 登录端口                 </td></tr><tr><td style="text-align:left"> USER     </td><td style="text-align:left"> admin                              </td><td style="text-align:left"> SSH 登录用户名               </td></tr><tr><td style="text-align:left"> PASSWORD </td><td style="text-align:left"> P@ssw0rd                           </td><td style="text-align:left"> SSH 登录密码，与 KEY 二选一  </td></tr><tr><td style="text-align:left"> KEY      </td><td style="text-align:left"> ssh-rsa<strong>*</strong>                       </td><td style="text-align:left"> SSH 私钥，与 PASSWORD 二选一 </td></tr></tbody></table><ul><li><p>切换到 <strong>Code</strong> 标签，新建<code>.github/workflows/deploy.yml</code></p><pre class="language-yaml lang-yaml"><code class="language-yaml lang-yaml">name: Deploy

on:
  push:
    branches: [main]

permissions:
  contents: write

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  build:
    name: Build artifact
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [20.x]
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
          lfs: true

      - name: Checkout LFS
        run: git lfs checkout

      - uses: pnpm/action-setup@v2
        with:
          version: 9.x.x

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: &#x27;pnpm&#x27;

      - uses: jongwooo/next-cache@v1

      - name: Install &amp; Build
        run: |
          pnpm install
          sh ./ci-release-build.sh

      - uses: actions/upload-artifact@v4
        with:
          name: release.zip
          path: assets/release.zip

  deploy:
    name: Deploy artifact
    runs-on: ubuntu-latest
    needs: build
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: release.zip

      - name: SCP Transfer
        uses: appleboy/scp-action@v0.1.7
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USER }}
          key: ${{ secrets.KEY }}
          password: ${{ secrets.PASSWORD }}
          port: ${{ secrets.PORT }}
          source: release.zip
          target: /tmp/shiro

      - name: Remote Deployment
        uses: appleboy/ssh-action@v0.1.7
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USER }}
          key: ${{ secrets.KEY }}
          password: ${{ secrets.PASSWORD }}
          port: ${{ secrets.PORT }}
          script: |
            set -ex
            source $HOME/.bashrc
            basedir=$HOME/mix-space/shiro
            workdir=$basedir/${{ github.sha }}
            mkdir -p $workdir
            mkdir -p $basedir/.cache
            mv /tmp/shiro/release.zip $workdir/release.zip
            rm -r /tmp/shiro
            cd $workdir
            unzip -qq -o $workdir/release.zip
            rm -rf $workdir/standalone/.env
            ln -s $HOME/shiro/.env $workdir/standalone/.env
            export NEXT_SHARP_PATH=$(npm root -g)/sharp
            # copy workdir ecosystem.config.js to basedir if not exists
            if [ ! -f $basedir/ecosystem.config.js ]; then
              cp $workdir/standalone/ecosystem.config.js $basedir/ecosystem.config.js
            fi
            # https://github.com/Unitech/pm2/issues/3054
            # symlink workdir node entry file to basedir
            ln -sf $workdir/standalone/server.js $basedir/server.js
            mkdir -p $workdir/standalone/.next
            rm -rf $workdir/standalone/.next/cache
            ln -sf $basedir/.cache $workdir/standalone/.next/cache
            cd $basedir
            pm2 reload ecosystem.config.js --update-env
            rm $workdir/release.zip
            pm2 save
            echo &quot;Deployed successfully&quot;
</code></pre>
</li><li><p>点击 <strong>Sync fork</strong> 可以同步官方仓库的更新，同步后会触发自动部署</p></li><li><p>另外，也可 <a href="https://vercel.com/new/clone?repository-url=https://github.com/Innei/Shiro&amp;env=NEXT_PUBLIC_API_URL,NEXT_PUBLIC_GATEWAY_URL&amp;envDescription=Mix-Space后端的配置">点击创建</a> 一键部署到vercel，注意添加环境变量，同步仓库也会自动更新</p></li></ul><h3 id="-nginx">配置 nginx</h3><ul><li><p>前端配置</p><pre class="language-nginx lang-nginx"><code class="language-nginx lang-nginx">location ~* \.(gif|png|jpg|css|js|woff|woff2|svg|webp)$ {
  proxy_pass http://127.0.0.1:2323;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header REMOTE-HOST $remote_addr;
  expires 30d;
}
location ~* \/(feed|sitemap|atom.xml) {
  proxy_pass http://127.0.0.1:2333/$1;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header REMOTE-HOST $remote_addr;
  add_header X-Cache $upstream_cache_status;
  add_header Cache-Control max-age=60;
}
location / {
  proxy_pass http://127.0.0.1:2323;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header REMOTE-HOST $remote_addr;
  add_header X-Cache $upstream_cache_status;
  add_header Cache-Control no-cache;
  proxy_intercept_errors on;
}
</code></pre>
</li><li><p>后端配置</p><pre class="language-nginx lang-nginx"><code class="language-nginx lang-nginx">location /socket.io {
  proxy_pass http://127.0.0.1:2333/socket.io; 
  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 REMOTE-HOST $remote_addr; 
  proxy_set_header Upgrade $http_upgrade; 
  proxy_set_header Connection &quot;upgrade&quot;; 
  proxy_buffering off;
  proxy_http_version 1.1; 
  add_header Cache-Control no-cache; 
}

location / {
  proxy_pass http://127.0.0.1:2333; 
  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 REMOTE-HOST $remote_addr; 
  add_header X-Cache $upstream_cache_status; 
}    
</code></pre>
</li></ul><h2 id="render-">特别篇一：render 部署</h2><p><strong>推荐指数</strong>：★★★★</p><p><strong>难度指数</strong>：★★★★</p><h3 id="">准备工作</h3><ol start="1"><li>注册 mongoDB</li><li>注册 github</li><li>注册 render</li><li>注册 vercel</li></ol><h3 id="">搭建框架</h3><ul><li>MongoDB 数据库</li><li>Render 部署 Redis 缓存</li><li>Vercel 托管的前端主题 Shiro</li><li>Render 部署后端 Mix Space</li></ul><pre class=""><code class="">📦 项目结构
├── 🗄️ 数据库 (MongoDB)
│   ├── 📂 用户数据
│   ├── 📂 文章数据
│   ├── 📂 其他业务数据
│
├── 🔥 缓存层 (Redis - Render 部署)
│   ├── ⚡ 存储会话信息
│   ├── ⚡ 存储热点数据
│   ├── ⚡ 降低数据库查询压力
│
├── 🎨 前端 (Shiro 主题 - Vercel 托管)
│   ├── 📦 依赖: Next.js / React
│   ├── 🎨 UI 组件
│   ├── 🔗 调用后端 API
│   ├── ⚙️ 状态管理
│
├── 🚀 后端 (Mix Space - Render 部署)
│   ├── 📦 依赖: Nest.js
│   ├── 🔗 连接 MongoDB
│   ├── 🔗 连接 Redis 缓存
│   ├── 🔒 认证 &amp; 授权
│   ├── 📡 API 处理
│
└── 🌐 部署
    ├── 📤 前端部署到 Vercel
    ├── 📤 后端 &amp; Redis 部署到 Render
    ├── 🛠️ CI/CD 自动化
</code></pre>
<p><strong>注意</strong>：后端默认不带主题，运行服务后还需登入后台管理界面 <code>https://www.blog.com/proxy/qaqdmin</code> 参照教程最后  <strong>云函数</strong> 配置主题</p><h3 id="">开始搭建</h3><ol start="1"><li><p><strong>数据库：MongoDB</strong></p><p>创建步骤参考 <a href="https://linux.do/t/topic/96509#p-657221-mongodb-5">抱脸部署LibreChat教程 </a>， 这里不再赘述</p></li><li><p><strong>缓存：Redis</strong></p><ul><li>登陆 render，依次点击右上角  <strong>+</strong>  →  <strong>Key Value</strong></li><li><strong>Name</strong> 填写 <strong>redis</strong></li><li><strong>Project</strong> 选择 <strong>Production</strong></li><li><strong>Region</strong> 选择 <strong>Singapore</strong></li><li><strong>Instance Type</strong> 选择 <strong>Free</strong></li><li>点击 <strong>Create Key Value Instance</strong> 创建</li><li>下拉在 <strong>Connections</strong> 下复制 <strong>Internal Key Value URL</strong>，形如 <code>redis://red-cvdd4eofnakc738i3f00:6379</code>，粘贴到剪贴板后只保留中间部分<code>red-cvdd4eofnakc738i3f00</code> 作为 <code>REDIS_HOST</code></li></ul></li><li><p><strong>前端：Shiro</strong></p><ul><li><p><a href="https://vercel.com/new/clone?repository-url=https://github.com/Innei/Shiro&amp;env=NEXT_PUBLIC_API_URL,NEXT_PUBLIC_GATEWAY_URL&amp;envDescription=Mix-Space后端的配置">点击创建</a>，名称填写 <code>shiro</code>，修改环境变量后点击 <strong>Deploy</strong> 部署</p><table><thead><tr><th> Name                    </th><th> Value                             </th><th> Description     </th></tr></thead><tbody><tr><td> NEXT<em>PUBLIC</em>API_URL     </td><td> <code>https://backend.blog.com/api/v2</code> </td><td> 后端API接口地址 </td></tr><tr><td> NEXT<em>PUBLIC</em>GATEWAY_URL </td><td> <code>https://backend.blog.com/</code>       </td><td> 后端域名        </td></tr></tbody></table></li><li><p>修改区域，在 <strong>Settings</strong><ul><li><strong>Functions</strong><ul><li><strong>Function Region</strong> 选择 <strong>Asia</strong><ul><li><strong>Hong Kong</strong>，注意先取消勾选再选择</li></ul></li></ul></li></ul></p></li><li><p>自定义域，注意 vercel 分配的域名国内无法直连需要添加自定义域：</p><ol start="1"><li>在 cloudflare 需要绑定的域名添加一条 A 记录指向 <code>76.223.126.88</code></li><li>进入 vercel 的 shiro 项目依次点击 <strong>Settings</strong><ul><li><strong>Domains</strong><ul><li><strong>Add</strong></li></ul></li></ul></li><li>输入绑定的域名，然后点击 <strong>Add Domain</strong>，注意勾选第三项后点击 <strong>Add</strong> 完成域名自定义</li></ol><p>这里假定添加的自定义域为 <code>frontend.blog.com</code></p></li></ul></li><li><p><strong>后端：Mix Space</strong></p><ul><li><p>登录 render，依次点击右上角  <strong>+</strong>  →  <strong>Web Service</strong></p></li><li><p>选择 <strong>Existing image</strong>，<strong>Image URL</strong> 输入 <code>innei/mx-server:latest</code></p></li><li><p>稍等几秒，点击 <strong>Connect</strong></p></li><li><p><strong>Name</strong> 修改为 <strong>core</strong></p></li><li><p><strong>Project</strong> 选择 <strong>Production</strong></p></li><li><p><strong>Region</strong> 选择 <strong>Singapore</strong></p></li><li><p><strong>Instance Type</strong> 选择 <strong>Free</strong></p></li><li><p><strong>Environment Variables</strong> 下方点击 <strong>Add from .env</strong>，修改以下环境变量后粘贴到输入框</p><pre class="language-ini lang-ini"><code class="language-ini lang-ini">ALLOWED_ORIGINS=frontend.blog.com
REDIS_HOST=red-cvdd4eofnakc738i3f00
DB_CONNECTION_STRING=mongodb+srv://&lt;DB_USER&gt;:&lt;DB_PASSWORD&gt;@&lt;DB_USER&gt;
JWT_SECRET=************************
</code></pre>
<p>其中<code>JWT_SECRET</code>可通过以下命令快速生成</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">openssl rand -base64 24 | cut -c1-32
</code></pre>
</li><li><p>点击 <strong>Deploy Web Service</strong> 部署</p></li><li><p>下滑在 <strong>Custom Domains</strong> 下方点击 <strong>+ Add Custom Domain</strong>，输入自定义域，格式如 <code>backend.blog.com</code></p></li><li><p>按提示前往域名托管处，如 cloudflare，添加一条 <strong>CNAME</strong> 记录后返回点击 <strong>verify</strong> 验证</p></li></ul></li></ol><h2 id="serv00-">特别篇二：serv00 部署</h2><p><strong>推荐指数</strong>：★★★</p><p><strong>难度指数</strong>：★★★★★</p><p>我的电铺现已上架一键安装脚本，简化了安装过程，能够更快速地完成安装，欢迎发电支持
https://afdian.com/a/ireno?tab=shop</p><p><strong>注意</strong>：后端默认不带主题，运行服务后还需登入后台管理界面 <code>https://后端域名/proxy/qaqdmin</code> 参照教程最后  <strong>云函数</strong> 配置主题</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash">alias node=node20
alias npm=npm20

mkdir -p ~/.npm-global &amp;&amp; npm config set prefix &quot;$HOME/.npm-global&quot; &amp;&amp; echo &#x27;export PATH=$HOME/.npm-global/bin:$PATH&#x27; &gt;&gt; ~/.profile &amp;&amp; source ~/.profile &amp;&amp; npm install -g pm2 &amp;&amp; pm2

mkdir ~/.mx-space
npm install sharp@0.32.5 --prefix ~/.mx-space

devil mongo db add core

devil port add tcp 2323
devil port add tcp 2333
devil port add tcp 5555
cd ~/domains/***.serv00.net

fetch https://raw.githubusercontent.com/redis/redis/7.4/redis.conf

sed -i &#x27;&#x27; &quot;s/^port .*/port 5555/&quot; redis.conf
sed -i &#x27;&#x27; -E &quot;s/^# requirepass .*/requirepass secure_pass/&quot; redis.conf
sed -i &#x27;&#x27; &#x27;s/^appendonly no$/appendonly yes/&#x27; redis.conf

mkdir -p ~/domains/***.serv00.net/mix-space/core &amp;&amp; cd $_
curl -L -O https://github.com/mx-space/core/releases/latest/download/release-linux.zip
unzip release-linux.zip
rm release-linux.zip

mkdir -p ~/domains/***.serv00.net/mix-space/shiro &amp;&amp; cd $_
curl -L -O https://github.com/Innei/Shiro/releases/latest/download/release.zip
unzip release.zip
rm release.zip

cat &gt; ~/domains/***.serv00.net/ecosystem.config.js &lt;&lt;EOF
const { execSync } = require(&#x27;node:child_process&#x27;);
const nodePath = execSync(`npm root --quiet -g`, { encoding: &#x27;utf-8&#x27; }).trim();
module.exports = {
  apps: [
    {
      name: &#x27;shiro&#x27;,
      script: &#x27;server.js&#x27;,
      autorestart: true,
      watch: false,
      max_memory_restart: &#x27;500M&#x27;,
      env: {
        PORT: 2323,
        NODE_ENV: &#x27;production&#x27;,
        NEXT_SHARP_PATH: process.env.NEXT_SHARP_PATH,
        NEXT_PUBLIC_API_URL: &#x27;http://127.0.0.1:2323/api/v2&#x27;,
        NEXT_PUBLIC_GATEWAY_URL: &#x27;http://127.0.0.1:2323&#x27;
      },
      log_date_format: &#x27;YYYY-MM-DD HH:mm:ss&#x27;,
    },  
    {
      name: &#x27;redis&#x27;,
      script: &#x27;redis-server&#x27;,
      args: &#x27;~/domains/***.serv00.net/mix-space/core/redis.conf&#x27;,
      autorestart: true,
      watch: false,
    },  
    {
      name: &#x27;core&#x27;,
      script: &#x27;index.js&#x27;,
      autorestart: true,
      watch: false,
      max_memory_restart: &#x27;500M&#x27;,
      args: [
        &#x27;--color&#x27;,
        &#x27;--encrypt_enable&#x27;,
        &#x27;--encrypt_key ********************(64位)&#x27;,
        &#x27;--redis_host 127.0.0.1&#x27;,
        &#x27;--redis_port 5555&#x27;,
        &#x27;--redis_password ********&#x27;,
        &#x27;--db_host mongo15.serv00.com&#x27;,
        &#x27;--collection_name mix-space&#x27;,
        &#x27;--db_user mix-space&#x27;,
        &#x27;--db_password ********&#x27;,
        &#x27;--port 2333&#x27;,
        &#x27;--allowed_origins example1.com,example2.com,localhost&#x27;,
        &#x27;--jwt_secret *************(32位)&#x27;,
      ].join(&#x27; &#x27;),
      env: {
        NODE_ENV: &#x27;production&#x27;,
        NODE_PATH: nodePath,
      },
    },
  ],
};
EOF

pm2 start ~/domains/***.serv00.net/ecosystem.config.js
</code></pre>
<h2 id="">云函数</h2><h3 id="shiro-">Shiro 主题</h3><ul><li><p>登入后台点击左侧底部 <strong>附加功能</strong> - <strong>配置与云函数</strong>，点击 <strong>+ 新建</strong></p></li><li><p><strong>名称</strong> 填写 <code>shiro</code> ，<strong>引用</strong> 填写 <code>theme</code> ，并在右侧代码区粘贴以下代码，请自行酌情修改</p><pre class="language-yaml lang-yaml"><code class="language-yaml lang-yaml">{
  &quot;footer&quot;: {
    &quot;otherInfo&quot;: {
      &quot;date&quot;: &quot;2020-{{now}}&quot;,
      &quot;icp&quot;: {
        &quot;text&quot;: &quot;萌 ICP 备 20236136 号&quot;,
        &quot;link&quot;: &quot;https://icp.gov.moe/?keyword=20236136&quot;
      }
    },
    &quot;linkSections&quot;: [
      {
        &quot;name&quot;: &quot;关于&quot;,
        &quot;links&quot;: [
          {
            &quot;name&quot;: &quot;关于本站&quot;,
            &quot;href&quot;: &quot;/about-site&quot;
          },
          {
            &quot;name&quot;: &quot;关于我&quot;,
            &quot;href&quot;: &quot;/about&quot;
          },
          {
            &quot;name&quot;: &quot;关于此项目&quot;,
            &quot;href&quot;: &quot;https://github.com/innei/Shiro&quot;,
            &quot;external&quot;: true
          }
        ]
      },
      {
        &quot;name&quot;: &quot;更多&quot;,
        &quot;links&quot;: [
          {
            &quot;name&quot;: &quot;时间线&quot;,
            &quot;href&quot;: &quot;/timeline&quot;
          },
          {
            &quot;name&quot;: &quot;友链&quot;,
            &quot;href&quot;: &quot;/friends&quot;
          },
          {
            &quot;name&quot;: &quot;监控&quot;,
            &quot;href&quot;: &quot;https://status.innei.in/status/main&quot;,
            &quot;external&quot;: true
          }
        ]
      },
      {
        &quot;name&quot;: &quot;联系&quot;,
        &quot;links&quot;: [
          {
            &quot;name&quot;: &quot;写留言&quot;,
            &quot;href&quot;: &quot;/message&quot;
          },
          {
            &quot;name&quot;: &quot;发邮件&quot;,
            &quot;href&quot;: &quot;mailto:i@innei.ren&quot;,
            &quot;external&quot;: true
          },
          {
            &quot;name&quot;: &quot;GitHub&quot;,
            &quot;href&quot;: &quot;https://github.com/innei&quot;,
            &quot;external&quot;: true
          }
        ]
      }
    ]
  },
  &quot;config&quot;: {
    &quot;color&quot;: {
      &quot;light&quot;: [
        &quot;#33A6B8&quot;,
        &quot;#FF6666&quot;,
        &quot;#26A69A&quot;,
        &quot;#fb7287&quot;,
        &quot;#69a6cc&quot;,
        &quot;#F11A7B&quot;,
        &quot;#78C1F3&quot;,
        &quot;#FF6666&quot;,
        &quot;#7ACDF6&quot;
      ],
      &quot;dark&quot;: [
        &quot;#F596AA&quot;,
        &quot;#A0A7D4&quot;,
        &quot;#ff7b7b&quot;,
        &quot;#99D8CF&quot;,
        &quot;#838BC6&quot;,
        &quot;#FFE5AD&quot;,
        &quot;#9BE8D8&quot;,
        &quot;#A1CCD1&quot;,
        &quot;#EAAEBA&quot;
      ]
    },
 
    &quot;bg&quot;: [
      &quot;https://github.com/Innei/static/blob/master/images/F0q8mwwaIAEtird.jpeg?raw=true&quot;,
      &quot;https://github.com/Innei/static/blob/master/images/IMG_2111.jpeg.webp.jpg?raw=true&quot;
    ],
    &quot;custom&quot;: {
      &quot;css&quot;: [],
      &quot;styles&quot;: [],
      &quot;js&quot;: [],
      &quot;scripts&quot;: []
    },
    &quot;site&quot;: {
      &quot;favicon&quot;: &quot;/innei.svg&quot;,
      &quot;faviconDark&quot;: &quot;/innei-dark.svg&quot;
    },
    &quot;hero&quot;: {
      &quot;title&quot;: {
        &quot;template&quot;: [
          {
            &quot;type&quot;: &quot;h1&quot;,
            &quot;text&quot;: &quot;Hi, I&#x27;m &quot;,
            &quot;class&quot;: &quot;font-light text-4xl&quot;
          },
          {
            &quot;type&quot;: &quot;h1&quot;,
            &quot;text&quot;: &quot;Innei&quot;,
            &quot;class&quot;: &quot;font-medium mx-2 text-4xl&quot;
          },
          {
            &quot;type&quot;: &quot;h1&quot;,
            &quot;text&quot;: &quot;👋。&quot;,
            &quot;class&quot;: &quot;font-light text-4xl&quot;
          },
          {
            &quot;type&quot;: &quot;br&quot;
          },
          {
            &quot;type&quot;: &quot;h1&quot;,
            &quot;text&quot;: &quot;A NodeJS Full Stack &quot;,
            &quot;class&quot;: &quot;font-light text-4xl&quot;
          },
          {
            &quot;type&quot;: &quot;code&quot;,
            &quot;text&quot;: &quot;&lt;Developer /&gt;&quot;,
            &quot;class&quot;: &quot;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&quot;
          },
          {
            &quot;type&quot;: &quot;span&quot;,
            &quot;class&quot;: &quot;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&quot;
          }
        ]
      },
      &quot;description&quot;: &quot;An independent developer coding with love.&quot;
    },
    &quot;module&quot;: {
      &quot;activity&quot;: {
        &quot;enable&quot;: true,
        &quot;endpoint&quot;: &quot;/fn/ps/update&quot;
      },
      &quot;donate&quot;: {
        &quot;enable&quot;: true,
        &quot;link&quot;: &quot;https://afdian.net/@Innei&quot;,
        &quot;qrcode&quot;: [
          &quot;https://cdn.jsdelivr.net/gh/Innei/img-bed@master/20191211132347.png&quot;,
          &quot;https://cdn.innei.ren/bed/2023/0424213144.png&quot;
        ]
      },
      &quot;bilibili&quot;: {
        &quot;liveId&quot;: 1434499
      }
    }
  }
}
</code></pre>
</li></ul><h3 id="ps-">PS 状态插件</h3><ul><li>登入后台点击左侧底部 <strong>附加功能</strong> - <strong>配置与云函数</strong>，点击 <strong>+ 新建</strong></li><li><strong>名称</strong> 填写 <code>update</code>，<strong>引用</strong> 填写 <code>ps</code>，<strong>数据类型</strong> 选择 <code>Function</code>，<strong>请求方式</strong> 选择 <code>POST</code>， <strong>Secret</strong> 左侧输入框填入 <code>key</code>，右侧填入key的值，然后 <a href="https://raw.githubusercontent.com/mx-space/snippets/refs/heads/main/shiro/functions/ps.ts">点击前往</a> 全选复制所有内容粘贴到右侧代码区，最后点击绿色按钮保存</li><li>下载安装 <a href="https://github.com/AlienFamilyHub/Kizuna">Kizuna</a>，Windows 系统快捷键  <code>WIN + R</code> 输入  <code>notepad %USERPROFILE%\AppData\Local\kizuna\config.yml</code> 编辑</li></ul><pre class="language-yaml lang-yaml"><code class="language-yaml lang-yaml">server_config:
  endpoint: &quot;https://backend.example.com/api/v2/fn/ps/update&quot; # https://api.example.com/api/v2/fn/ps/update
  token: &quot;YOUR-KEY-HERE&quot; # 设置的key
  report_time: 5 # 上报时间间隔，单位秒
rules: # 软件名的替换规则
  - match_application: WeChat
    replace:
      application: 微信
      description: 一个小而美的办公软件
  - match_application: QQ
    replace:
      application: QQ
      description: 一个多功能的通讯软件
  - match_application: Netease Cloud Music
    replace:
      application: 网易云音乐
      description: 一个音乐播放和分享的平台          
</code></pre>
<p>编辑好后 <code>CTRL + S</code> 保存并关闭，然后再运行 Kizuna，就会定时往定义的端点上传你的活动数据</p><h2 id="">参考链接</h2><p><a href="https://mx-space.js.org/docs/core">Mix Space 官方文档</a></p><p><a href="https://www.vlo.cc/posts/jc/shiro">Mix-Space部署最新前端Shiro</a></p><p><a href="https://blxcwg666.xlog.app/68.html">Mix-Space 搭建从入门到入土</a></p></div><p style="text-align:right"><a href="https://but.bio/posts/default/mix-space-blog-guide#comments">看完了？说点什么呢</a></p></div>]]></description><link>https://but.bio/posts/default/mix-space-blog-guide</link><guid isPermaLink="true">https://but.bio/posts/default/mix-space-blog-guide</guid><dc:creator><![CDATA[Reno]]></dc:creator><pubDate>Fri, 21 Mar 2025 00:32:23 GMT</pubDate></item></channel></rss>