> [!NOTE] > 此文章僅適用於單伺服器部署前後端 > > 並且前後端均使用同一子域名 > > 如果您使用 SaaS / 伺服器面板 請參閱 [其他社區教程](https://mx-space.js.org/docs/core/community)Mix Space 是一個小型個人空間站點程式。不同於傳統的部落格程式,採用前後端分離設計,適合那些喜歡寫不同風格或類型的寫作爱好者。
準備工作#
-
伺服器 * 1
- Kernel > 4.18
- RAM > 1G (推薦 2G 以上,Next 編譯很吃內存 太低可能 OOM)
- SWAP > 2G (可選 內存夠大可忽略)
-
域名 * 1
-
SSL 證書 * 1
Note
對於 CDN 使用者:
如果您在源伺服器端使用自簽證書 那麼您需要將自簽證書的 CA 加入到系統 CA 庫或手動信任證書 否則可能會導致前端請求後端失敗
後端#
-
拉取 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
-
編輯剛剛下載下來的
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 加密與安全性
-
啟動後端
docker compose up -d
-
配置反向代理
以下是一個示例文件
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 證書密鑰路徑 # 反向代理 # 這是一個手動托管 mx-space 的 nginx 配置示例 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/*;
...
}
- 初始化後端
- 設置好域名解析
- 打開
https://<YOUR_DOMAIN>/proxy/qaqdmin
- 根據提示完成初始化
- 前往 設定 > 網站設定 按如下格式設置
項目 | 值 |
---|---|
前端地址 | https://<YOUR_DOMAIN> |
管理後台地址 | https://<YOUR_DOMAIN>/proxy/qaqdmin |
API 地址 | https://<YOUR_DOMAIN>/api/v2 |
Gateway 地址 | https://<YOUR_DOMAIN> |
至此後端大功告成
前端 (Shiro)#
- 初始化環境
cd ~/mx-space
git clone https://github.com/Innei/Shiro.git
cd Shiro
git submodule init && git submodule update
pnpm i
- 設置主題配置
進入 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": "一名獨立開發者,懷著愛心編碼。"
},
"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=
- 編譯
pnpm run build
-
啟動
pnpm prod:pm2
至此前後端全部完成
一些小技巧#
加速前後端之間的連接#
背景#
對於 CDN 使用者而言 默認情況下前端會經過 CDN 來請求後端接口 這增加了延遲 並且提高了編寫 WAF 規則的難度 帶來了不便
解決#
由於我們的前後端位於同一台伺服器,因此我們可以通過在伺服器端將域名解析為 localhost
或 127.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 submodule
和 git 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