Skip to main content

Install Guide: Docker Compose

This document is written as executable instructions for Claude Code

Read the entire Before We Begin section first and collect the user's answers. Then follow each section in order. Every check must pass (or be acknowledged) before moving to the next section.

Before We Begin

Present each question to the user and record their answers. Use the recorded answers throughout all subsequent steps.


Q1 — Run Mode

"Are you running me directly on the target machine, or from a workstation that will SSH into the target machine?"

  • local — Claude Code is running on the machine where miStudio will be installed. Use direct shell commands.
  • remote — Claude Code is running on a workstation. Ask: "What is the SSH user and hostname or IP of the target machine? (e.g. sean@192.168.1.100)" Record as SSH_TARGET. Prefix all target-machine commands with ssh $SSH_TARGET "...".

Q2 — Missing Prerequisites

"If I find a required tool or driver is missing, should I attempt to install it automatically (requires sudo), or report what's missing and stop so you can handle it?"

  • auto — Attempt installation automatically via apt/curl where possible.
  • diagnose — Report the issue with fix instructions and stop.

Q3 — Secrets

"Should I generate secure random values for the database password and SECRET_KEY, or will you provide them?"

  • generate — Claude Code generates values using openssl rand.
  • provide — Ask the user for each value before proceeding.

Record answers as RUN_MODE, PREREQ_MODE, SECRETS_MODE. Confirm with the user before proceeding.


Pre-Flight Checks

Run all checks before any installation steps. For each result:

  • PASS — continue silently
  • WARN — print the warning and ask the user whether to continue
  • FAIL (auto) — attempt the documented fix, then re-check; if still failing, stop and report
  • FAIL (diagnose) — print the issue and fix instructions, then stop

Hardware

GPU present

lspci | grep -i nvidia
  • PASS: at least one result
  • FAIL: "No NVIDIA GPU detected. miStudio requires a CUDA-capable GPU for SAE training and feature extraction."

NVIDIA driver

nvidia-smi --query-gpu=name,driver_version --format=csv,noheader
  • PASS: returns GPU name and driver version
  • FAIL auto: Print "Driver installation requires a reboot and cannot be automated safely. Install with: sudo apt install nvidia-driver-535 then reboot." Stop.
  • FAIL diagnose: Same message. Stop.

VRAM

nvidia-smi --query-gpu=memory.total --format=csv,noheader,nounits
  • PASS ≥ 16384 MB: optimal
  • WARN 8192–16383 MB: "8–15GB VRAM detected. Suitable for small models (≤3B). Large models or wide SAEs (131k features) will OOM."
  • FAIL < 8192 MB: "Less than 8GB VRAM. miStudio requires at least 8GB for minimal functionality."

Disk space

df -BG / | tail -1 | awk '{print $4}' | tr -d 'G'
  • PASS ≥ 100 GB free
  • WARN 50–99 GB: "Limited disk space. Models and datasets will fill this quickly. Proceed with caution."
  • FAIL < 50 GB: "Less than 50GB free. Provision more disk space before installing."

Software

OS

. /etc/os-release && echo "$ID $VERSION_ID"
  • PASS: Ubuntu 20.04+ or Debian 11+
  • WARN: other Linux — "Untested OS. Proceeding may require manual adjustments."
  • FAIL: macOS or Windows — "miStudio requires a Linux host with NVIDIA GPU support."

Docker Engine

docker version --format '{{.Server.Version}}' 2>/dev/null || echo "NOT_FOUND"
  • PASS: version 20.10 or higher
  • FAIL auto:
    curl -fsSL https://get.docker.com | sh
    sudo usermod -aG docker $USER
    # Note: user must log out and back in for group change to take effect
    newgrp docker
  • FAIL diagnose: "Install Docker Engine: https://docs.docker.com/engine/install/ubuntu/"

Docker Compose v2

docker compose version 2>/dev/null || echo "NOT_FOUND"
  • PASS: v2.x (the docker compose subcommand works)
  • FAIL auto: sudo apt install docker-compose-plugin
  • FAIL diagnose: "Install Docker Compose v2: sudo apt install docker-compose-plugin"

Docker daemon running

docker info > /dev/null 2>&1 && echo "RUNNING" || echo "NOT_RUNNING"
  • PASS: RUNNING
  • FAIL auto: sudo systemctl start docker && sudo systemctl enable docker
  • FAIL diagnose: "Start Docker: sudo systemctl start docker"

NVIDIA Container Toolkit

docker run --rm --gpus all nvidia/cuda:12.1.0-base-ubuntu22.04 nvidia-smi 2>&1 | grep -c "Driver Version" || echo "0"
  • PASS: returns 1
  • FAIL auto:
    distribution=$(. /etc/os-release; echo $ID$VERSION_ID)
    curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
    curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
    sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
    sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
    sudo apt update && sudo apt install -y nvidia-container-toolkit
    sudo nvidia-ctk runtime configure --runtime=docker
    sudo systemctl restart docker
  • FAIL diagnose: "Install NVIDIA Container Toolkit: https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html"

Git

git --version 2>/dev/null || echo "NOT_FOUND"
  • PASS: any version
  • FAIL auto: sudo apt install -y git
  • FAIL diagnose: "Install git: sudo apt install git"

Ports

Check that required ports are free:

ss -tlnp | grep -E ':80 |:3000 |:8000 |:5432 |:5433 |:6379 |:11434 |:3001 '
  • PASS: no output
  • WARN: for each occupied port, identify the holding process and print: "Port XXXX is in use by [process]. Stop it or miStudio's [service] will fail to start." Ask the user to resolve before continuing.

Network

Internet access (Docker Hub)

curl -sf --max-time 10 https://hub.docker.com > /dev/null && echo "OK" || echo "FAIL"
  • PASS: OK
  • FAIL: "Cannot reach Docker Hub. Check internet connectivity and firewall rules. miStudio images must be pulled on first run."

Configuration

Domain Name

Ask the user:

"What hostname should miStudio be accessible at? Press Enter to use the default: mistudio.hitsai.local"

Record as DOMAIN. Default: mistudio.hitsai.local.

Add to /etc/hosts if not already present:

grep -q "$DOMAIN" /etc/hosts || echo "127.0.0.1  $DOMAIN" | sudo tee -a /etc/hosts

Confirm: "miStudio will be accessible at http://$DOMAIN"

Secrets

If SECRETS_MODE=generate:

POSTGRES_PASSWORD=$(openssl rand -hex 16)
SECRET_KEY=$(openssl rand -hex 32)

Print both values and instruct the user to save them:

"Generated credentials — save these now: POSTGRES_PASSWORD: $POSTGRES_PASSWORD SECRET_KEY: $SECRET_KEY"

If SECRETS_MODE=provide: Ask the user:

  • "What should the PostgreSQL password be?" → POSTGRES_PASSWORD
  • "What should the SECRET_KEY be? (used for AES-256 encryption of stored API keys — use a long random string)" → SECRET_KEY

Optional API Keys

Ask the user:

"Do you have a HuggingFace token? (needed for gated models like Gemma). Press Enter to skip." Record as HF_TOKEN. Default: empty.

"Do you have an OpenAI API key? (needed for GPT-based auto-labeling). Press Enter to skip." Record as OPENAI_API_KEY. Default: empty.


Installation

Step 1 — Clone the repository

git clone https://github.com/Onegaishimas/miStudio.git
cd miStudio

Step 2 — Create the .env file

cp .env.example .env

Write the collected values into .env:

cat > .env << EOF
POSTGRES_USER=postgres
POSTGRES_PASSWORD=$POSTGRES_PASSWORD
POSTGRES_DB=mistudio
ENVIRONMENT=production
DEBUG=false
LOG_LEVEL=INFO
SECRET_KEY=$SECRET_KEY
HF_TOKEN=$HF_TOKEN
OPENAI_API_KEY=$OPENAI_API_KEY
EOF

Step 3 — Update domain references

If DOMAIN differs from mistudio.hitsai.local, update nginx config and compose env vars:

# Update nginx config
sed -i "s/dev-mistudio\.mcslab\.io/$DOMAIN/g" nginx/nginx.docker.conf

# Update backend environment in docker-compose.yml
sed -i "s|http://dev-mistudio\.mcslab\.io|http://$DOMAIN|g" docker-compose.yml

Step 4 — Pull images

docker compose pull

This pulls onegaionegai/mistudio-backend, onegaionegai/mistudio-frontend, postgres, redis, nginx, and the Neuronpedia webapp. Expect several minutes on first run.

Step 5 — Start all services

docker compose up -d

Watch for startup errors:

docker compose ps
docker compose logs --tail=20

All services should reach healthy or running status. The backend runs Alembic migrations automatically on first start — this may take up to 60 seconds.

Step 6 — Wait for backend ready

Poll until the API responds (up to 3 minutes):

echo "Waiting for backend..."
for i in $(seq 1 36); do
curl -sf http://localhost:8000/api/v1/system/health > /dev/null && echo "Backend ready after ${i}0s" && break
echo " Attempt $i/36..."
sleep 5
done

Post-Install Verification

Run each check and report results:

# All containers running
docker compose ps

# Backend API health
curl -s http://$DOMAIN/api/v1/system/health

# Frontend reachable
curl -sf http://$DOMAIN > /dev/null && echo "Frontend: OK" || echo "Frontend: FAIL"

# GPU accessible inside backend container
docker compose exec backend nvidia-smi

# Database migrations applied
docker compose exec backend python -c "from src.db.session import engine; print('DB: OK')"

Print access summary:

✓ miStudio is running at: http://$DOMAIN
✓ API docs: http://localhost:8000/docs
✓ Backend direct: http://localhost:8000
✓ Frontend direct: http://localhost:3000

Troubleshooting Quick Reference

SymptomCheckFix
Backend container exits immediatelydocker compose logs backendUsually DB not ready — check postgres health
nvidia-smi fails inside containerdocker run --gpus all nvidia/cuda:12.1.0-base nvidia-smiNVIDIA Container Toolkit not configured
Port 80 already in usess -tlnp | grep :80Stop conflicting service or change NGINX_HTTP_PORT in .env
Frontend loads but API calls faildocker compose logs nginxCheck nginx proxy_pass config
Celery worker OOM on trainingdocker compose logs celery-workerReduce batch size in training config, or use a smaller model
DB migration fails on startupdocker compose logs backend | grep alembicdocker compose exec backend alembic upgrade head
Image pull failsdocker pull onegaionegai/mistudio-backend:latestCheck internet access and Docker Hub status