nyaruta

nyaruta

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

Mix-Space + Shiro Setup

Mix Space is a small personal space station program. Unlike traditional blogging programs, it adopts a front-end and back-end separation design, suitable for those who enjoy writing in different styles or types.

> [!NOTE] > This article is only applicable to single server deployments for both front-end and back-end > > and both front-end and back-end use the same subdomain > > If you are using SaaS/server panels, please refer to [other community tutorials](https://mx-space.js.org/docs/core/community)

Preparation#

  • Server * 1

    • Kernel > 4.18
    • RAM > 1G (recommended 2G or more, Next compilation is memory-intensive, too low may cause OOM)
    • SWAP > 2G (optional, can be ignored if memory is large enough)
  • Domain name * 1

  • SSL certificate * 1

    Note

    For CDN users:

If you are using a self-signed certificate on the source server, you need to add the CA of the self-signed certificate to the system CA library or manually trust the certificate; otherwise, it may cause front-end requests to fail to reach the back-end.

Back-end#

  1. Pull the Docker Compose configuration file template

    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. Edit the downloaded 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 # Add your domain here, separated by commas
           - JWT_SECRET=YOUR_SUPER_SECURED_JWT_SECRET_STRING # Generate one using openssl
           - ENCRYPT_ENABLE=false # Whether to enable encryption, generally do not change it
           - ENCRYPT_KEY=069d51c5e6f09e1d806e4dedb1c7bc620c29a67c91a984547911be8a846cf6cb # Example value
         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

If encryption is enabled, note that the key length must be 64 bits and consist only of lowercase letters and numbers; otherwise, an error will occur during initialization. Note that this is irreversible, so be sure to save your key. Therefore, it is not highly recommended to use it unless you really need to encrypt the API Key.

The key can be generated using the command openssl rand -hex 32. Please remember it.

See Key Encryption and Security

  1. Start the back-end

    docker compose up -d
    
  2. Configure reverse proxy

    Below is an example file

    server {
     listen 80;
     listen 443 ssl;
     listen 443 quic; # Only available for nginx version 1.25.0 and above, please remove this line for other versions
     server_name YOUR_SERVER_NAME; # Change to your domain
     ssl_certificate path/to/certificate; # SSL certificate path
     ssl_certificate_key path/to/key; # SSL certificate key path
     # Reverse proxy
     # This is an example for nginx configuration 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;
     }
    

}


Reference this file in `nginx.conf`

```nginx filename="/etc/nginx/nginx.conf"
http {
   ...
   include /etc/nginx/sites-enabled/*;
   ...
}
  1. Initialize the back-end
    1. Set up domain name resolution
    2. Open https://<YOUR_DOMAIN>/proxy/qaqdmin
    3. Complete initialization according to the prompts
    4. Go to Settings > Site Settings and set as follows
ItemValue
Front-end Addresshttps://<YOUR_DOMAIN>
Admin Backend Addresshttps://<YOUR_DOMAIN>/proxy/qaqdmin
API Addresshttps://<YOUR_DOMAIN>/api/v2
Gateway Addresshttps://<YOUR_DOMAIN>

Thus, the back-end is complete.

Front-end (Shiro)#

  1. Initialize the environment
```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 - ``` Re-login to the server ```shell sudo pacman -S nodejs npm pnpm pm2 ``` 2. Pull the repository & install dependencies
cd ~/mx-space
git clone https://github.com/Innei/Shiro.git
cd Shiro
git submodule init && git submodule update
pnpm i
  1. Set theme configuration

Enter the Mix Space backend, go to the "Configuration and Cloud Functions" page, click the add button in the upper right corner, and fill in the following settings:

Important

Please note that you need to modify this configuration to meet your needs. Directly using the configuration below may cause your blog to not function as expected.

The following configuration may not be complete; for more configuration item information, please refer to Configuration Items.

Additionally, the configuration can also be written in YAML format, in which case the data type should be selected as YAML.

For details on the "My Dynamics" feature, see the official documentation.

- Name: `shiro`
- Reference: `theme`
- Data Type: `JSON`
- Data: (click the button below to copy)

```json
{
"footer": {
    "otherInfo": {
        "date": "2020-{{now}}",
        "icp": {
            "text": "Meng ICP Record No. 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:[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
        }
    }
}

}

```
Save changes

4. Modify environment variables

nano .env

Example:

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>
# The following are optional
TMDB_API_KEY=
GH_TOKEN=
  1. Compile

    pnpm run build
    
  2. Start

    pnpm prod:pm2
    

Thus, the front-end and back-end are all complete.

Some Tips#

Speeding up the connection between front-end and back-end#

Background#

For CDN users, by default, the front-end requests the back-end interface through the CDN, which increases latency and complicates the writing of WAF rules, causing inconvenience.

Solution#

Since our front-end and back-end are on the same server, we can speed up the process by resolving the domain name to localhost or 127.0.0.1 on the server side, allowing requests to go directly to the back-end without going through the CDN.

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

Important

Please carefully check if your hosts file is managed by cloud-init.

If so, you need to change the cloud-init template instead of directly modifying /etc/hosts.

About favicon#

Background#

Although the favicon can be modified through the configuration file, in some cases (such as Cloudflare challenges), the favicon obtained is the default favicon of Shiro, which is somewhat frustrating.

Solution#

I decided to use git alias, git submodule, and git hooks to solve this. First, create a Git repository to store the favicon.
Example

Delete the original public folder and add the submodule.

  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

Set 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'

Add 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

Add execution permissions

   chmod +x .git/hooks/post-merge

This way, every time you pull the repository, just replace git pull with git pull-clean to execute our changes to the favicon without causing conflicts.

Important

After adding Git Hooks, you need to add the --ignore-scripts parameter when executing pnpm install, otherwise, the prepare script will automatically execute and overwrite our hook.

Alright, I can't think of any new tips for now, so let's leave it at that.

This article is synchronized and updated to xLog by Mix Space. The original link is https://lar.moe/posts/deploy/mx-space

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