Skip to content

Deploy Backend

Run the MIP backend (NestJS + Redis + MongoDB) on your server using Docker Compose.

The primary tool is the MIP Control Panel — it manages the remote stack directly from your dev machine via DOCKER_HOST over SSH, so you never need to manually SCP files or SSH in just to restart a container.


Prerequisites

  • Server has Docker installed
  • You can SSH into the server (key-based auth, e.g. ssh ubuntu@SERVER_IP)
  • The KUBE credentials (KUBE_SERVER, KUBE_TOKEN, KUBE_CA) are filled in the backend env file — run Script 03 from the Kubes setup if not done yet

Overview

The backend stack runs three containers:

flowchart LR
    C[Game Clients] -- "REST + Socket.IO\nport 3000" --> BE[mip-be\nNestJS Backend]
    GS[Game Servers\nK8s Pods] -- "Socket.IO\nport 3000" --> BE
    BE -- "port 6379" --> R[Redis]
    BE -- "port 27017" --> M[MongoDB]
    R --- V1[Session Store\nPub/Sub\nRedlock]
    M --- V2[Player Data\nPersistence]

The compose file and env file both live on your dev machine. The Control Panel sends compose commands to the remote Docker daemon over SSH — no file transfer needed.


1 — Prepare the Env File

Edit the env file for your mode on your dev machine:

Mode Env file
Testing mip-be/scripts/test/.env.test
Shipping mip-be/scripts/shipping/.env.shipping

Required values to fill in

Variable What to set
REDIS_PASSWORD Strong password for Redis — must match between the redis container and backend
JWT_SECRET Strong secret for HS256 tokens (WebSocket auth, server SIO, user login)
MONGO_INITDB_ROOT_PASSWORD MongoDB admin password — must match the password in MONGO_DB_URL
MONGO_DB_URL Keep db:27017 (Docker service name). Update username/password to match the two fields above. Include ?authSource=admin
KUBE_SERVER K3s API endpoint — see step 03. Use https://127.0.0.1:6443 if backend and K3s are on the same server
KUBE_TOKEN Service account token — from script 03
KUBE_CA Cluster CA certificate (base64) — from script 03
JWT_PLAYER_RS256_PRIVATE_KEY_PEM RS256 private key — generate with the Gen RS256 Keys button (see below)
JWT_PLAYER_RS256_PUBLIC_KEY_PEM RS256 public key — generated alongside the private key

Warning

Change REDIS_PASSWORD, JWT_SECRET, and MONGO_INITDB_ROOT_PASSWORD to strong, unique values before deploying. Never use the example defaults in production.

Backend on the same server as K3s?

Set KUBE_SERVER=https://127.0.0.1:6443 instead of the Tailscale/external IP. See Deploy Master Node — Script 03 for the full explanation including the required network_mode: host change in docker-compose.

Variables that usually stay unchanged

Variable Value Notes
REDIS_ENDPOINT redis Docker service name
REDIS_PORT 6379
ALLOCATE_SERVER_PATH yamls/allocate-server.yaml Path inside the container
CREATE_FLEET_PATH yamls/create-fleet.yaml Path inside the container
CREATE_FLEET_AUTO_SCALE yamls/auto-scale.yaml Path inside the container

2 — Generate RS256 Keys

The backend uses RS256 key pairs for player join/travel JWTs. Both JWT_PLAYER_RS256_PRIVATE_KEY_PEM and JWT_PLAYER_RS256_PUBLIC_KEY_PEM must be set before starting the stack.

In the Control Panel, go to the Backend tab → BUILD section → click Gen RS256 Keys (scripts/test/.env.test).

This will:

  1. Run openssl genrsa to generate a 2048-bit RSA key pair
  2. Save jwt_player_private.pem and jwt_player_public.pem into mip-be/scripts/test/
  3. Write the \n-escaped PEM values directly into scripts/test/.env.test

Note

Requires openssl on PATH on your dev machine. Install with choco install openssl -y if missing (then open a new terminal).

Tip

If the RS256 keys are missing or empty when you click Up, the Control Panel will show an error and block the start — click Gen RS256 Keys first.


3 — Deploy via the Control Panel

Open the MIP Control Panel and switch the mode (top-right dropdown) to Testing or Shipping.

Go to the Backend tab → REMOTE DEPLOY section.

Set the server connection

Field What to enter
Server IP Tailscale hostname or IP of the server (e.g. mip-server or 100.x.x.x)
Username SSH user on the server (default: ubuntu)

The Control Panel connects via DOCKER_HOST=ssh://ubuntu@SERVER_IP, which forwards all docker compose commands to the remote Docker daemon over SSH. Your local compose and env files are used directly — nothing is copied to the server.

The four deploy buttons

Button What it does Equivalent command
Pull Pull the latest backend image from the registry docker compose pull
Up Start all containers in detached mode docker compose up -d
Down Stop and remove all containers docker compose down
Logs Stream live container logs docker compose logs -f --tail=100

First deploy:

  1. Click Pull — pulls mip-be-registry:latest from the GitLab registry
  2. Click Up — starts Redis, MongoDB, and the backend

Updating to a new version:

  1. Click Pull — fetches the new image
  2. Click Down — stops the running stack
  3. Click Up — starts with the new image

Output from every command streams into the Backend console pane at the bottom of the Control Panel.

Which files does the Control Panel use?

The Control Panel reads BE_COMPOSE_FILE and BE_ENV_FILE from MIPScripts/env/<mode>.env:

Mode Compose file Env file
Testing scripts/test/docker-compose-test.yml scripts/test/.env.test
Shipping scripts/shipping/docker-compose-shipping.yml scripts/shipping/.env.shipping

Both paths are relative to BE_LOCAL_PATH (the backend repo root on your dev machine). To change them, edit MIPScripts/env/test.env or MIPScripts/env/shipping.env.


4 — UFW Rules

Run these once on the server:

sudo ufw allow 3000/tcp comment 'Backend API'
sudo ufw reload
sudo ufw status numbered

Note

Game server UDP ports (7000:8000/udp) are opened during Setup Server.


Managing the Stack (Manual CLI Reference)

If you need to manage the stack directly on the server (useful for debugging):

ssh ubuntu@SERVER_IP
Action Command
Start docker compose -f /path/to/docker-compose-test.yml --env-file /path/to/.env.test up -d
Stop docker compose -f ... down
Pull latest docker compose -f ... pull
View backend logs docker logs -f mip_backend_test
All logs docker compose -f ... logs -f

Tip

The Control Panel does all of the above remotely — you only need the manual commands for advanced debugging.


Data Persistence

MongoDB data is stored in a Docker volume (mip_db_data_test / mip_db_data_shipping). The volume persists across container restarts and docker compose down. To fully reset the database:

docker volume rm mip-be_mip_db_data_test

Warning

Removing the volume deletes all player data permanently. Only do this for a clean start.