learning_ai_common_plat/docs/devops/single_azure_vm/docker
2026-03-31 06:52:01 +00:00
..
Caddyfile.bytelyst.example docs(devops): add Track A handoff and prep gateway changes 2026-03-29 23:57:03 +00:00
DEPLOYMENT_STATUS_2026-03-29.md docs(devops): add phased VM stack recommendations 2026-03-31 06:52:01 +00:00
prompt.md docs(docker): rewrite prompt.md as execution guide for Codex agent on fresh VM 2026-03-28 02:06:52 -07:00
README.md docs(devops): add Track A handoff and prep gateway changes 2026-03-29 23:57:03 +00:00
SECURE_API_EXPOSURE.md docs(devops): add secure single-vm api exposure guidance 2026-03-29 22:29:08 +00:00
setup.sh chore(platform): align docker and package outputs 2026-03-29 23:41:08 +00:00
test-plan.md feat(docker): add --dry-run mode + test-plan.md, complete all 7 prompt tasks 2026-03-28 01:58:15 -07:00

ByteLyst Single-VM Deployment

Deploy the entire ByteLyst ecosystem (31 services, 11 products) on a single raw Azure VM. Nothing pre-installed required — the script handles everything from a blank Ubuntu machine. Two files: this README and setup.sh. Copy both to the VM and run the script.

Related:


Prerequisites

  • Azure VM: Ubuntu 24.04 LTS (or 22.04), Standard_D8s_v5 (8 vCPU, 32 GB RAM) recommended
  • Disk: 128 GB+ (Docker images, Cosmos emulator, Ollama models, build artifacts)
  • Network: NSG allowing inbound on ports: 22, 80, 1025, 1234, 3000-3003, 3030, 3035, 3040, 3045, 3050, 3055, 3060, 3070, 3075, 3100, 3300, 4003, 4005, 4007, 4010-4019, 8025, 8080, 10000, 11434
  • GitHub access: Repos must be accessible (public or GITHUB_TOKEN for private)
  • Nothing else needed — the script installs Docker, Node.js, pnpm, Gitea, Ollama, and everything

Quick Start

# 1. SSH into your Azure VM
ssh azureuser@<vm-ip>

# 2. Copy setup.sh and make executable
chmod +x setup.sh

# 3. Run — provide your GitHub username (repos are cloned via HTTPS)
#    If repos are private, also export GITHUB_TOKEN first.
sudo ./setup.sh

# 4. Wait ~15-25 minutes for full build + deploy

# 5. Verify
/opt/bytelyst/check-health.sh

Resume & Retry

Phase completion is tracked. If anything fails, you don't have to start over:

sudo ./setup.sh --phase=7          # Retry just the deploy phase
sudo ./setup.sh --resume           # Auto-resume after SSH disconnect
sudo ./setup.sh --resume-from=7    # Jump to deploy after manual fix
sudo ./setup.sh --status           # Check what's done
sudo ./setup.sh --reset            # Start completely over
sudo ./setup.sh --help             # Show full usage

What the Script Installs & Does

Software installed on the VM (from scratch)

Software Version Purpose
Docker CE latest Container runtime + Compose + BuildKit
Node.js 22 LTS Build toolchain for TypeScript packages
pnpm 10.6.5 Package manager (workspace-aware)
Gitea 1.22 (Docker) Local npm package registry on :3300
Ollama latest Local LLM inference for LocalMemGPT on :11434
git, jq, curl latest System utilities

Execution phases

Phase Duration Description
1. System ~3 min Pre-flight checks (disk ≥40 GB, RAM ≥16 GB), install Docker, Node.js 22, pnpm 10.6.5, Ollama, git, jq, build-essential
2. Gitea + CI ~2 min Start Gitea Docker container, admin + org + token, install act_runner
3. Clone ~3 min Clone all 12 repos to /opt/bytelyst/, push to Gitea for CI
4. Build ~5 min pnpm install && pnpm -r build all @bytelyst/* packages
5. Publish ~3 min Publish all packages to local Gitea npm registry
6. Env instant Generate .env.ecosystem with Cosmos emulator key, Azurite key, JWT secret
7. Deploy ~10 min Stop Ollama (free RAM), per-service Docker build + deploy (31 services, with fallback), prune build cache, restart Ollama
8. Verify ~1 min Health-check all 31+ endpoints + create /opt/bytelyst/check-health.sh

Port Map (after deployment)

Infrastructure (installed by setup.sh)

Service Port URL
Gitea (npm registry) 3300 http://<vm-ip>:3300
Ollama (LLM API) 11434 http://<vm-ip>:11434
Cosmos Data Explorer 1234 http://<vm-ip>:1234
Azurite (Blob) 10000 http://<vm-ip>:10000
Mailpit UI 8025 http://<vm-ip>:8025
Loki (Logs) 3100 http://<vm-ip>:3100/ready
Grafana 3000 http://<vm-ip>:3000
Traefik Dashboard 8080 http://<vm-ip>:8080

Platform Services

Service Port URL
platform-service 4003 http://<vm-ip>:4003/health
extraction-service 4005 http://<vm-ip>:4005/health
mcp-server 4007 http://<vm-ip>:4007/health

Platform Dashboards

Dashboard Port URL
Admin Console 3001 http://<vm-ip>:3001
Issue Tracker 3003 http://<vm-ip>:3003

Product Backends

Product Port Health
PeakPulse 4010 http://<vm-ip>:4010/health
ChronoMind 4011 http://<vm-ip>:4011/health
JarvisJr 4012 http://<vm-ip>:4012/health
NomGap 4013 http://<vm-ip>:4013/health
MindLyst 4014 http://<vm-ip>:4014/health
LysnrAI 4015 http://<vm-ip>:4015/health
NoteLett 4016 http://<vm-ip>:4016/health
FlowMonk 4017 http://<vm-ip>:4017/health
ActionTrail 4018 http://<vm-ip>:4018/health
LocalMemGPT 4019 http://<vm-ip>:4019/health

Product Web Apps

Product Port URL
LysnrAI Dashboard 3002 http://<vm-ip>:3002
ChronoMind 3030 http://<vm-ip>:3030
JarvisJr 3035 http://<vm-ip>:3035
FlowMonk 3040 http://<vm-ip>:3040
NoteLett 3045 http://<vm-ip>:3045
MindLyst 3050 http://<vm-ip>:3050
NomGap 3055 http://<vm-ip>:3055
ActionTrail 3060 http://<vm-ip>:3060
LocalMemGPT 3070 http://<vm-ip>:3070
LLM Lab Dashboard 3075 http://<vm-ip>:3075

Post-Deployment Commands

# Check all service health
/opt/bytelyst/check-health.sh

# View logs for a specific service
docker compose -f /opt/bytelyst/learning_ai_common_plat/docker-compose.ecosystem.yml \
  logs -f platform-service

# Restart a specific service
docker compose -f /opt/bytelyst/learning_ai_common_plat/docker-compose.ecosystem.yml \
  restart flowmonk-backend

# Stop everything
docker compose -f /opt/bytelyst/learning_ai_common_plat/docker-compose.ecosystem.yml down

# Stop and wipe all data
docker compose -f /opt/bytelyst/learning_ai_common_plat/docker-compose.ecosystem.yml down -v

Environment Variables

All optional — defaults work for most setups:

Variable Default Description
GITHUB_USER saravanakumardb1 GitHub org/user to clone repos from
GITHUB_TOKEN (empty) Set for private repos (HTTPS auth)
GITEA_ADMIN bytelyst-admin Gitea admin username
GITEA_PASS ByteLyst2026! Gitea admin password
OLLAMA_MODEL llama3.2:3b Default LLM model to pull
SKIP_CLONE 0 Set 1 to skip cloning (re-runs)
SKIP_BUILD 0 Set 1 to skip package build+publish (re-runs)

CLI Flags

Flag Description
--resume Auto-resume from last completed phase
--resume-from=N Resume from phase N (1-8)
--phase=N Run ONLY phase N (useful for retrying)
--dry-run Validate prerequisites without building or deploying
--reset Clear phase markers and start fresh
--status Show completed phases and exit
-h, --help Show usage help

Troubleshooting

  • Cosmos emulator slow: It needs 20-30s on first boot. Services wait via health checks.
  • Out of memory: Use at least 32 GB RAM. Cosmos emulator needs ~4 GB, Ollama needs ~4 GB for 3B models.
  • Build failures: Check Gitea is running (docker ps | grep gitea) and packages published (curl http://localhost:3300/api/packages/bytelyst/npm/). Per-service build logs: /opt/bytelyst/.setup-state/builds/<service>.log. Retry: sudo ./setup.sh --phase=7.
  • Ollama not responding: Check systemctl status ollama or curl http://localhost:11434/api/version.
  • Port conflicts: Ensure nothing else runs on the listed ports before deploying.
  • CORS errors in browser: The generated .env.ecosystem sets CORS_ORIGIN=* for dev/test. If you restrict it, update the value to match your access URL.
  • Services in development mode: .env.ecosystem now sets NODE_ENV=production for all services. If you need debug logging, remove or change this value.

HTTPS Gateway

  • Public backend access is intended to flow through Caddy on https://api.bytelyst.com, not direct backend port exposure.
  • The gateway config lives at /opt/bytelyst/Caddyfile and is mounted into the caddy container.
  • Backend routes are path-based and strip their prefixes before proxying:
    • /platform/*platform-service:4003
    • /extraction/*extraction-service:4005
    • /mcp/*mcp-server:4007
    • /peakpulse/*peakpulse-backend:4010
    • /chronomind/*chronomind-backend:4011
    • /jarvisjr/*jarvisjr-backend:4012
    • /nomgap/*nomgap-backend:4013
    • /mindlyst/*mindlyst-backend:4014
    • /lysnrai/*lysnrai-backend:4015
    • /notelett/*notelett-backend:4016
    • /flowmonk/*flowmonk-backend:4017
    • /actiontrail/*actiontrail-backend:4018
    • /localmemgpt/*localmemgpt-backend:4019
  • Keep backend ports closed publicly once DNS and NSG rules are aligned. Docker-internal service discovery remains unchanged.

Known Limitations

  • Remote browser access: Product web apps use http://localhost:<port> for browser-side API calls (baked at Next.js build time via NEXT_PUBLIC_* args). This works when browsing from the VM itself but not from a remote browser (e.g., laptop accessing http://<vm-ip>:3060). For remote access, use SSH port-forwarding:
    # Forward all product ports to your laptop (run from your laptop)
    ssh -N -L 3001:localhost:3001 -L 3002:localhost:3002 -L 3030:localhost:3030 \
      -L 3035:localhost:3035 -L 3040:localhost:3040 -L 3045:localhost:3045 \
      -L 3050:localhost:3050 -L 3055:localhost:3055 -L 3060:localhost:3060 \
      -L 3070:localhost:3070 -L 3075:localhost:3075 \
      -L 4003:localhost:4003 -L 4010:localhost:4010 -L 4011:localhost:4011 \
      -L 4012:localhost:4012 -L 4013:localhost:4013 -L 4014:localhost:4014 \
      -L 4015:localhost:4015 -L 4016:localhost:4016 -L 4017:localhost:4017 \
      -L 4018:localhost:4018 -L 4019:localhost:4019 \
      azureuser@<vm-ip>
    
    Then open http://localhost:3060 etc. on your laptop. Server-side code (API routes, SSR) uses Docker service names and works regardless.
  • Cosmos emulator is x86-only: Do not use ARM-based VMs (e.g., Dpsv6). Stick with Standard_D8s_v5 or similar Intel/AMD instances.
  • Memory pressure: Phase 7 automatically stops Ollama (~3 GB) during Docker builds and restarts it after. If builds still OOM on 32 GB, retry with sudo ./setup.sh --phase=7 (per-service fallback skips what already built).
  • Corporate proxy in Dockerfiles: Already removed at source across all repos. No runtime stripping needed.