yiye

一叶轻舟

记录人生旅途的轻声细语

Mix Space Blog Setup Guide

Getting Started: Docker Deployment#

Recommendation Level: ★★★★★

Difficulty Level: ★

Using Docker for deployment, with no separation between front-end and back-end, the deployment requirements are as follows:

  • 1 server, with memory > 1G
  • 1 domain name (domestic servers need to be filed)

Note: The back-end does not come with a theme by default. After running the service, you need to log in to the back-end management interface https://www.blog.com/proxy/qaqdmin to configure the theme according to Cloud Functions.

Configuration Files#

The file directory structure is as follows. The .env and docker-compose.yml need to be created by the user, and the data directory will be automatically generated after the container runs.

📂 ~/mix-space

├── 📜 .env
├── 📜 docker-compose.yml
└── 📂 data
    ├── 📂 mongo
    ├── 📂 redis
    └── 📂 core

.env#

Note: API-related configurations generally do not need to be modified.

# 💻 Front-end Configuration
# 🌐 API-related Configuration
NEXT_PUBLIC_API_URL=http://core:2333/api/v2
NEXT_PUBLIC_GATEWAY_URL=http://core:2333/

# 🔑 Authentication & API Keys
TMDB_API_KEY=
GH_TOKEN=

# 🖥️ Back-end Configuration
# 🔐 Security Configuration
JWT_SECRET=G7xJpQzW8mV4L2YfK9N6T1RbX3dMC0H(32 characters)
ALLOWED_ORIGINS=
ENCRYPT_KEY=593f62860255feb0a914534a43814b9809cc7534da7f5485cd2e3d3c8609acab(64 characters)
ENCRYPT_ENABLE=false

# 🚀 Cache-related Configuration
CDN_CACHE_HEADER=true
FORCE_CACHE_HEADER=false

# 🛢 Database Configuration
MONGO_CONNECTION=

# ⚡ Request Throttling
THROTTLE_TTL=10
THROTTLE_LIMIT=20

docker-compose.yml#

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:
      - "127.0.0.1:2323:2323"
    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:
      - "127.0.0.1:2333:2333"
    depends_on:
      - mongo
      - redis
    networks:
      - mix-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/mongo:/data/db
    networks:
      - mix-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:
      - mix-space
    restart: unless-stopped

networks:
  mix-space:
    driver: bridge

Nginx Reverse Proxy#

Please add an A record pointing to the server IP for the domain name (using www.blog.com as an example), then add the following server block.

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 "upgrade"; 
    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 "Upgrade"; 
        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 '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'; 
    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; 
}

Advanced: Traditional Method Deployment#

Recommendation Level: ★★★

Difficulty Level: ★★★

Build and deploy with front-end and back-end separation. The deployment requirements are as follows:

  • Simple Deployment/Automatic Deployment:
    • 1 server, with memory > 1G
    • 2 domain names, which can be subdomains.
  • Manual Deployment:
    • 1 server, with memory > 2G
    • 2 domain names, which can be subdomains.

Note: The back-end does not come with a theme by default. After running the service, you need to log in to the back-end management interface https://backend.blog.com/proxy/qaqdmin to configure the theme according to Cloud Functions.

Build Back-end#

Prepare Environment#

  • Install Node.js, it is recommended to install version 20.12.2.

    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
    
  • Install Redis.

    sudo apt-get install redis-server
    
  • Install MongoDB, taking Ubuntu 24.04 as an example.

    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 "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" | 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
    

    For other system installations, please refer to: MongoDB Official Documentation.

Simple Deployment#

Back-end repository: Mix Space/core

  • Directly download the built Linux version.

    mkdir ~/mix-space/core && cd $_
    curl -L -O https://github.com/mx-space/core/releases/latest/download/release-linux.zip
    unzip release-linux.zip
    rm release-linux.zip
    
  • Generate 32-bit and 64-bit characters.

    openssl rand -base64 24 | cut -c1-32 # For jwt_secret
    openssl rand -base64 48 | cut -c1-64 # For encrypt key
    
  • Edit ecosystem.config.js.

    const { cpus } = require('os');
    const { execSync } = require('child_process');
    const nodePath = execSync(`npm root --quiet -g`, { encoding: 'utf-8' }).trim();
    const cpuLen = cpus().length;
    
    module.exports = {
      apps: [
        {
          name: 'mix-space',
          script: 'index.js',
          autorestart: true,
          exec_mode: 'cluster',
          watch: false,
          instances: cpuLen,
          max_memory_restart: '500M',
          args: [
            '--color',
            '--encrypt_enable',
            '--encrypt_key ********************************(64 characters)',
            '--port 2333',
            '--allowed_origins example1.com,example2.com,localhost',
            '--jwt_secret ********************(16~32 characters)',
          ].join(' '),
          env: {
            NODE_ENV: 'production',
            NODE_PATH: nodePath,
          },
        },
      ],
    };
    
  • Start the back-end service.

    npm install -g pm2
    pm2 start ecosystem.config.js
    

Manual Deployment#

  • Install the back-end service.

    mkdir ~/mix-space && cd $_
    git clone https://github.com/mx-space/core.git --depth=1
    cd core
    npm install -g pnpm
    pnpm i
    
  • Build the back-end service.

    pnpm build
    pnpm bundle
    
  • Create a symbolic link and modify ecosystem.config.js according to Simple Deployment.

    ln -s ./app/core/ecosystem.config.js ecosystem.config.js
    
  • Start the back-end service.

    npm install -g pm2
    pm2 start ecosystem.config.js
    

Build Front-end#

Prepare Environment#

  • Install dependencies.

    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
    

Simple Deployment#

  • Front-end repository: Innie/Shiro

  • Directly download the built Linux version.

    mkdir ~/mix-space/shiro && cd $_
    curl -L -O https://github.com/Innei/Shiro/releases/latest/download/release.zip
    unzip release.zip
    rm release.zip
    
  • Edit ecosystem.config.js.

    module.exports = {
      apps: [
        {
          name: 'shiro',
          script: 'server.js',
          autorestart: true,
          watch: false,
          max_memory_restart: '500M',
          env: {
            PORT: 2323,
            NODE_ENV: 'production',
            NEXT_SHARP_PATH: process.env.NEXT_SHARP_PATH,
    	    NEXT_PUBLIC_API_URL: 'http://127.0.0.1:2323/api/v2',
    	    NEXT_PUBLIC_GATEWAY_URL: 'http://127.0.0.1:2323'
          },
          log_date_format: 'YYYY-MM-DD HH:mm:ss',
        },
      ],
    }
    
  • Start the front-end service.

    pm2 start ecosystem.config.js
    

Automatic Deployment#

  • Create the front-end directory.

    mkdir -p ~/mix-space/shiro && cd $_
    

    Edit the environment variable .env.

    NEXT_PUBLIC_API_URL=https://example.net/api/v2
    NEXT_PUBLIC_GATEWAY_URL=https://example.net
    TMDB_API_KEY=
    GH_TOKEN=
    
  • Fork the front-end repository, wait for it to complete, then go to the Actions tab to enable the Workflow. Next, go to the Settings tab, click on [Secrets and variables] - [Actions] - [New repository secret] to add the following variables.

NameSecretDescription
HOSTexample.comSSH login address
PORT22SSH login port
USERadminSSH login username
PASSWORDP@ssw0rdSSH login password, either this or KEY
KEYssh-rsa*****SSH private key, either this or PASSWORD
  • Switch to the Code tab, create .github/workflows/deploy.yml.

    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: 'pnpm'
    
          - uses: jongwooo/next-cache@v1
    
          - name: Install & 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 "Deployed successfully"
    
  • Click Sync fork to synchronize updates from the official repository. Syncing will trigger automatic deployment.

  • Additionally, you can [click to create](https://vercel.com/new/clone?repository-url=https://github.com/Innei/Shiro&env=NEXT_PUBLIC_API_URL,NEXT_PUBLIC_GATEWAY_URL&envDescription=Mix-Space backend configuration) to deploy to Vercel with one click, making sure to add environment variables. Syncing the repository will also automatically update.

Configure Nginx#

  • Front-end configuration.

    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;
    }
    
  • Back-end configuration.

    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 "upgrade"; 
      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; 
    }    
    

Special Edition 1: Render Deployment#

Recommendation Level: ★★★★

Difficulty Level: ★★★★

Preparation Work#

  1. Register for MongoDB.
  2. Register for GitHub.
  3. Register for Render.
  4. Register for Vercel.

Build Framework#

  • MongoDB Database
  • Render-deployed Redis Cache
  • Vercel-hosted Front-end Theme Shiro
  • Render-deployed Back-end Mix Space
📦 Project Structure
├── 🗄️ Database (MongoDB)
│   ├── 📂 User Data
│   ├── 📂 Article Data
│   ├── 📂 Other Business Data

├── 🔥 Cache Layer (Redis - Render Deployment)
│   ├── ⚡ Store Session Information
│   ├── ⚡ Store Hot Data
│   ├── ⚡ Reduce Database Query Pressure

├── 🎨 Front-end (Shiro Theme - Vercel Hosted)
│   ├── 📦 Dependencies: Next.js / React
│   ├── 🎨 UI Components
│   ├── 🔗 Call Back-end API
│   ├── ⚙️ State Management

├── 🚀 Back-end (Mix Space - Render Deployment)
│   ├── 📦 Dependencies: Nest.js
│   ├── 🔗 Connect MongoDB
│   ├── 🔗 Connect Redis Cache
│   ├── 🔒 Authentication & Authorization
│   ├── 📡 API Handling

└── 🌐 Deployment
    ├── 📤 Front-end deployed to Vercel
    ├── 📤 Back-end & Redis deployed to Render
    ├── 🛠️ CI/CD Automation

Note: The back-end does not come with a theme by default. After running the service, you need to log in to the back-end management interface https://www.blog.com/proxy/qaqdmin to configure the theme according to the tutorial's final Cloud Functions.

Start Building#

  1. Database: MongoDB

    Refer to the steps in Deploying LibreChat Tutorial, which will not be elaborated here.

  2. Cache: Redis

    • Log in to Render, click the upper right corner +Key Value.
    • Fill in Name as redis.
    • Choose Project as Production.
    • Choose Region as Singapore.
    • Choose Instance Type as Free.
    • Click Create Key Value Instance to create.
    • Scroll down and copy the Internal Key Value URL under Connections, which looks like redis://red-cvdd4eofnakc738i3f00:6379, and paste it to the clipboard, keeping only the middle part red-cvdd4eofnakc738i3f00 as REDIS_HOST.
  3. Front-end: Shiro

    • [Click to create](https://vercel.com/new/clone?repository-url=https://github.com/Innei/Shiro&env=NEXT_PUBLIC_API_URL,NEXT_PUBLIC_GATEWAY_URL&envDescription=Mix-Space backend configuration), fill in the name as shiro, modify the environment variables, and then click Deploy.

      NameValueDescription
      NEXT_PUBLIC_API_URLhttps://backend.blog.com/api/v2Back-end API address
      NEXT_PUBLIC_GATEWAY_URLhttps://backend.blog.com/Back-end domain
    • Modify the region in Settings - Functions - Function Region to select Asia - Hong Kong, making sure to uncheck and then select.

    • For custom domains, note that the domain assigned by Vercel cannot be directly connected domestically, so you need to add a custom domain:

      1. Add an A record pointing to 76.223.126.88 for the domain you need to bind in Cloudflare.
      2. Go to the Vercel Shiro project, click Settings - Domains - Add.
      3. Enter the bound domain, then click Add Domain, making sure to check the third option before clicking Add to complete the custom domain.

      Here, we assume the added custom domain is frontend.blog.com.

  4. Back-end: Mix Space

    • Log in to Render, click the upper right corner +Web Service.

    • Select Existing image, and enter innei/mx-server:latest for Image URL.

    • Wait a few seconds, then click Connect.

    • Change Name to core.

    • Choose Project as Production.

    • Choose Region as Singapore.

    • Choose Instance Type as Free.

    • Click Add from .env under Environment Variables, modify the following environment variables, and paste them into the input box.

      ALLOWED_ORIGINS=frontend.blog.com
      REDIS_HOST=red-cvdd4eofnakc738i3f00
      DB_CONNECTION_STRING=mongodb+srv://<DB_USER>:<DB_PASSWORD>@<DB_USER>
      JWT_SECRET=************************
      

      The JWT_SECRET can be quickly generated using the following command.

      openssl rand -base64 24 | cut -c1-32
      
    • Click Deploy Web Service to deploy.

    • Scroll down and click + Add Custom Domain under Custom Domains, entering the custom domain in the format backend.blog.com.

    • Follow the prompts to go to the domain hosting provider, such as Cloudflare, to add a CNAME record, then return and click verify to validate.

Special Edition 2: serv00 Deployment#

Recommendation Level: ★★★

Difficulty Level: ★★★★★

Prepare Environment#

mkdir -p ~/.npm-global && npm config set prefix "$HOME/.npm-global" && echo 'export PATH=$HOME/.npm-global/bin:$PATH' >> ~/.profile && source ~/.profile && npm install -g pm2 && pm2

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

Prepare Storage#

devil mongo db add core

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

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

sed -i '' "s/^port .*/port 5555/" redis.conf
sed -i '' -E "s/^# requirepass .*/requirepass secure_pass/" redis.conf
sed -i '' 's/^appendonly no$/appendonly yes/' redis.conf

screen redis-server redis.conf

Press CTRL+A+D to exit the screen, then test Redis.

redis-cli -h 127.0.0.1 -p 5555 -a secure_pass ping

If successful, it will return PONG.

Install Back-end#

Note: The back-end does not come with a theme by default. After running the service, you need to log in to the back-end management interface https://www.blog.com/proxy/qaqdmin to configure the theme according to the tutorial's final Cloud Functions.

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

cat > ecosystem.config.js <<EOF
const { execSync } = require('node:child_process');
const nodePath = execSync(`npm root --quiet -g`, { encoding: 'utf-8' }).trim();
module.exports = {
  apps: [
    {
      name: 'core',
      script: 'index.js',
      autorestart: true,
      watch: false,
      max_memory_restart: '500M',
      args: [
        '--color',
        '--encrypt_enable',
        '--encrypt_key ********************(64 characters)',
        '--redis_host 127.0.0.1',
        '--redis_port 5555',
        '--redis_password ********',
        '--db_host mongo15.serv00.com',
        '--collection_name mix-space',
        '--db_user mix-space',
        '--db_password ********',
        '--port 2333',
        '--allowed_origins example1.com,example2.com,localhost',
        '--jwt_secret *************(32 characters)',
      ].join(' '),
      env: {
        NODE_ENV: 'production',
        NODE_PATH: nodePath,
      },
    },
  ],
};
EOF

pm2 start ecosystem.config.js

Install Front-end#

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

cat > ecosystem.config.js <<EOF 
module.exports = {
  apps: [
    {
      name: 'shiro',
      script: 'server.js',
      autorestart: true,
      watch: false,
      max_memory_restart: '500M',
      env: {
        PORT: 2323,
        NODE_ENV: 'production',
        NEXT_SHARP_PATH: process.env.NEXT_SHARP_PATH,
	    NEXT_PUBLIC_API_URL: 'http://127.0.0.1:2323/api/v2',
	    NEXT_PUBLIC_GATEWAY_URL: 'http://127.0.0.1:2323'
      },
      log_date_format: 'YYYY-MM-DD HH:mm:ss',
    },
  ],
}
EOF

pm2 start ecosystem.config.js

Cloud Functions#

Shiro Theme#

  • Log in to the back-end, click on the bottom left Additional Features - Configuration and Cloud Functions, and click + New.

  • Fill in Name as shiro, Reference as theme, and paste the following code into the code area on the right. Please modify as appropriate.

    {
      "footer": {
        "otherInfo": {
          "date": "2020-{{now}}",
          "icp": {
            "text": "萌 ICP 备 20236136 号",
            "link": "https://icp.gov.moe/?keyword=20236136"
          }
        },
        "linkSections": [
          {
            "name": "About",
            "links": [
              {
                "name": "About this site",
                "href": "/about-site"
              },
              {
                "name": "About me",
                "href": "/about"
              },
              {
                "name": "About this project",
                "href": "https://github.com/innei/Shiro",
                "external": true
              }
            ]
          },
          {
            "name": "More",
            "links": [
              {
                "name": "Timeline",
                "href": "/timeline"
              },
              {
                "name": "Friend Links",
                "href": "/friends"
              },
              {
                "name": "Monitoring",
                "href": "https://status.innei.in/status/main",
                "external": true
              }
            ]
          },
          {
            "name": "Contact",
            "links": [
              {
                "name": "Leave a message",
                "href": "/message"
              },
              {
                "name": "Send an email",
                "href": "mailto:i@innei.ren",
                "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
          }
        }
      }
    }
    

PS Status Plugin#

  • Log in to the back-end, click on the bottom left Additional Features - Configuration and Cloud Functions, and click + New.
  • Fill in Name as update, Reference as ps, select Data Type as Function, select Request Method as POST, input key in the left input box for Secret, and fill in the value of the key on the right. Then click here to copy all content and paste it into the code area on the right. Finally, click the green button to save.
  • Download and install Kizuna, for Windows systems, use the shortcut WIN + R to input notepad %USERPROFILE%\AppData\Local\kizuna\config.yml to edit.
server_config:
  endpoint: "https://backend.example.com/api/v2/fn/ps/update" # https://api.example.com/api/v2/fn/ps/update
  token: "YOUR-KEY-HERE" # Set key
  report_time: 5 # Reporting interval in seconds
rules: # Replacement rules for software names
  - match_application: WeChat
    replace:
      application: 微信
      description: 一个小而美的办公软件
  - match_application: QQ
    replace:
      application: QQ
      description: 一个多功能的通讯软件
  - match_application: Netease Cloud Music
    replace:
      application: 网易云音乐
      description: 一个音乐播放和分享的平台          

After editing, save with CTRL + S and close, then run Kizuna, which will periodically upload your activity data to the defined endpoint.

Mix Space Official Documentation

Deploy Latest Front-end Shiro for Mix Space

From Getting Started to Grounded with Mix-Space

This article is synchronized and updated to xLog by Mix Space. The original link is https://reno.zone.id/posts/default/mix-space-blog-guide

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.