diff --git a/DEV-ENV.md b/DEV-ENV.md index 7a65f77c..67db033b 100644 --- a/DEV-ENV.md +++ b/DEV-ENV.md @@ -1,154 +1,135 @@ -# DevServer01 Environment Setup & Operations Guide +# ResolutionFlow Dev Environment Setup & Operations Guide ## Server Overview -- **Hostname:** devserver01 -- **IP Address:** 192.168.0.9 -- **OS:** Ubuntu 25.10 (Questing Quokka) -- **CPU:** AMD Ryzen 3 PRO 3200GE w/ Radeon Vega Graphics -- **RAM:** ~5.2GB (some reserved by Vega iGPU) -- **Disk:** 57GB LVM volume (`/dev/mapper/ubuntu--vg-ubuntu--lv`), ~47GB free -- **Hardware:** Lenovo ThinkCentre Micro Tower +- **Provider:** Hostinger KVM VPS (srv1522117) +- **IP Address:** 46.202.92.250 +- **OS:** Ubuntu 24.04 LTS +- **CPU:** 2 vCPU cores +- **RAM:** 8GB +- **Disk:** 100GB NVMe SSD +- **Swap:** 4GB (`/swapfile`, swappiness=10) -## Docker Setup +## Architecture -Docker was installed via the official convenience script: +All services run as Docker containers on the host, managed via SSH or from the VS Code Server integrated terminal. -```bash -curl -fsSL https://get.docker.com | sh -sudo usermod -aG docker michael +``` +Host (root@srv1522117) +├── Traefik → reverse proxy + auto SSL (Let's Encrypt) +├── VS Code Server → browser IDE at https://code.resolutionflow.com +└── ResolutionFlow Stack + ├── resolutionflow_frontend → Vite/React on port 5173 + ├── resolutionflow_backend → FastAPI/Uvicorn on port 8000 + └── resolutionflow_postgres → PostgreSQL 16 + pgvector on port 5432 ``` -Docker Compose is included with this installation. +## Access URLs -## Code-Server +| Service | URL | +|---|---| +| VS Code Server | https://code.resolutionflow.com | +| Frontend (dev) | http://46.202.92.250:5173 | +| Backend API | http://46.202.92.250:8000 | +| API Docs | http://46.202.92.250:8000/docs | -### Overview +## Docker Layout -Code-server (codercom/code-server) runs in a Docker container, providing a browser-accessible VS Code instance at `https://192.168.0.9:8080`. It uses a custom Dockerfile to include additional tools like `gh` (GitHub CLI). - -### Custom Dockerfile - -Location: `~/docker/Dockerfile.code-server` - -```dockerfile -FROM codercom/code-server:latest - -USER root -RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg && \ - chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg && \ - echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null && \ - apt update && apt install -y gh && \ - rm -rf /var/lib/apt/lists/* -USER coder +``` +/docker/ +├── traefik/ +│ ├── docker-compose.yml → Traefik reverse proxy +│ └── .env → ACME_EMAIL for Let's Encrypt +└── vscode/ + ├── docker-compose.yml → VS Code Server + └── .env → CODE_PASSWORD ``` -### Docker Compose File - -Location: `~/docker/docker-compose.yml` - -```yaml -services: - code-server: - build: - context: . - dockerfile: Dockerfile.code-server - container_name: code-server - environment: - - PASSWORD= - volumes: - - ./code-server/config/data:/home/coder/.local/share/code-server - - ./code-server/config/extensions:/home/coder/.local/share/code-server/extensions - - ./code-server/config/.config/code-server:/home/coder/.config/code-server - - ./projects:/projects - - ./code-server/certs:/certs - - /home/michael/.claude:/home/coder/.claude - ports: - - 8080:8443 - command: --bind-addr 0.0.0.0:8443 --cert /certs/cert.pem --cert-key /certs/key.pem /projects - user: "1000:1000" - restart: unless-stopped +Project lives inside the VS Code Server Docker volume: +``` +/var/lib/docker/volumes/vscode_vscode-data/_data/resolutionflow/ ``` -### Key Details +## VS Code Server - **Container user:** `coder` (UID 1000) -- **Home directory inside container:** `/home/coder` -- **Projects mount:** Host `~/docker/projects` → Container `/projects` -- **Claude Code config mount:** Host `/home/michael/.claude` → Container `/home/coder/.claude` -- **HTTPS:** Self-signed certs via a custom Homelab CA -- **Internal port:** 8443 (code-server listens here) -- **External port:** 8080 (mapped to 8443 internally) -- **Access URL:** `https://192.168.0.9:8080` +- **Home directory:** `/home/coder` +- **Project location:** `/home/coder/resolutionflow` +- **Host volume path:** `/var/lib/docker/volumes/vscode_vscode-data/_data` +- **Access URL:** `https://code.resolutionflow.com` +- **HTTPS:** Auto-provisioned via Traefik + Let's Encrypt -### SSL Certificates +### Compose File Location +`/docker/vscode/docker-compose.yml` -Location: `~/docker/code-server/certs/` +## Traefik -A custom Certificate Authority (CA) was created for the homelab: +Handles reverse proxying and automatic SSL for all services. HTTP automatically redirects to HTTPS. -- `ca.key` — CA private key -- `ca.crt` — CA certificate (imported into browsers to trust all homelab certs) -- `key.pem` — code-server private key -- `cert.pem` — code-server certificate (signed by CA) -- `server.cnf` — OpenSSL config with SANs for devserver01 +### Adding A New Service Behind Traefik -The CA cert (`ca.crt`) has been imported into Firefox on client machines under Settings → Privacy & Security → Certificates → View Certificates → Authorities → Import → "Trust this CA to identify websites." +Add these labels to any new Docker service: -### Volume Mapping Reference +```yaml +labels: + - "traefik.enable=true" + - "traefik.http.routers..rule=Host(`subdomain.resolutionflow.com`)" + - "traefik.http.routers..entrypoints=websecure" + - "traefik.http.routers..tls.certresolver=letsencrypt" + - "traefik.http.services..loadbalancer.server.port=" +``` -| Host Path | Container Path | Purpose | -|---|---|---| -| `~/docker/code-server/config/data` | `/home/coder/.local/share/code-server` | VS Code user data, settings | -| `~/docker/code-server/config/extensions` | `/home/coder/.local/share/code-server/extensions` | VS Code extensions | -| `~/docker/code-server/config/.config/code-server` | `/home/coder/.config/code-server` | code-server config | -| `~/docker/projects` | `/projects` | All project repos | -| `~/docker/code-server/certs` | `/certs` | SSL certificates | -| `/home/michael/.claude` | `/home/coder/.claude` | Claude Code config, plugins, skills, history | +Also create an A record in DNS pointing the subdomain to `46.202.92.250`. -## Patherly / ResolutionFlow Dev Environment +## ResolutionFlow Dev Stack -### Docker Compose (Dev) +### Important: No Docker Inside VS Code Container -Location: `~/docker/projects/patherly/docker-compose.dev.yml` - -This runs the full Patherly/ResolutionFlow stack: - -- **PostgreSQL** (pgvector/pgvector:pg16) on port 5432 -- **Backend** (FastAPI/Uvicorn) on port 8000 -- **Frontend** (Vite/React) on port 5173 +The VS Code Server container does NOT have Docker. All `docker compose` commands must be run via SSH as root on the host. ### Environment Files -- `~/docker/projects/patherly/.env` — Backend secrets (SECRET_KEY, API keys, etc.) -- `~/docker/projects/patherly/frontend/.env` — Frontend config (VITE_API_URL) +| File | Purpose | +|---|---| +| `.env` | Root — Docker Compose interpolation (`SECRET_KEY`, `ANTHROPIC_API_KEY`, `GOOGLE_AI_API_KEY`, `POSTGRES_PORT`) | +| `backend/.env` | Backend source of truth — all FastAPI settings, API keys, DB URLs, CORS | +| `frontend/.env` | Frontend — `VITE_API_URL` pointing to backend | -### Critical Configuration for Remote Access +### Critical Remote Access Config -Since the dev environment is accessed from other machines on the LAN (not localhost), these settings are required: - -**Frontend `.env`:** +**`frontend/.env`:** ``` -VITE_API_URL=http://192.168.0.9:8000 +VITE_API_URL=http://46.202.92.250:8000 ``` -**Backend CORS_ORIGINS in `docker-compose.dev.yml`:** +**`backend/.env`:** +``` +CORS_ORIGINS=["http://localhost:3000","http://localhost:5173","http://127.0.0.1:3000","http://127.0.0.1:5173","http://46.202.92.250:5173","http://46.202.92.250:3000","https://resolutionflow.com","https://www.resolutionflow.com"] +FRONTEND_URL=http://46.202.92.250:5173 +DATABASE_URL=postgresql+asyncpg://postgres:postgres@db:5432/resolutionflow +DATABASE_URL_SYNC=postgresql://postgres:postgres@db:5432/resolutionflow +``` + +Note: `DATABASE_URL` uses `@db:5432` (Docker service name), not `@localhost`. + +**`docker-compose.dev.yml`:** ```yaml -- CORS_ORIGINS=["http://localhost:3000","http://localhost:5173","http://127.0.0.1:3000","http://127.0.0.1:5173","http://192.168.0.9:5173","http://192.168.0.9:3000"] +- VITE_API_URL=http://46.202.92.250:8000 ``` -The `192.168.0.9` entries are required because browsers make requests from the client machine, where `localhost` refers to the client — not devserver01. - ### Starting the Dev Environment +SSH into host as root: + ```bash -cd ~/docker/projects/patherly +cd /var/lib/docker/volumes/vscode_vscode-data/_data/resolutionflow docker compose -f docker-compose.dev.yml up -d ``` ### Running Migrations (Fresh Database) ```bash +cd /var/lib/docker/volumes/vscode_vscode-data/_data/resolutionflow docker compose -f docker-compose.dev.yml run --rm backend alembic upgrade head ``` @@ -158,193 +139,124 @@ docker compose -f docker-compose.dev.yml run --rm backend alembic upgrade head docker exec resolutionflow_backend python -m scripts.seed_test_users ``` -### Rebuilding After Frontend .env Changes +Test accounts (password: `TestPass123!`): -Vite bakes environment variables at build time, so changes to `VITE_API_URL` require a rebuild: +| Email | Role | Plan | +|---|---|---| +| admin@resolutionflow.example.com | Owner | Team | +| pro@resolutionflow.example.com | Owner | Pro | +| teamadmin@resolutionflow.example.com | Owner | Team | +| engineer@resolutionflow.example.com | Engineer | Shared | +### Rebuilding After Config Changes + +**Frontend** (Vite bakes env vars at build time — requires rebuild): +```bash +cd /var/lib/docker/volumes/vscode_vscode-data/_data/resolutionflow +docker compose -f docker-compose.dev.yml up -d --build frontend +``` + +**Backend** (restart only): +```bash +docker compose -f docker-compose.dev.yml restart backend +``` + +**Full restart:** ```bash docker compose -f docker-compose.dev.yml down -docker compose -f docker-compose.dev.yml up -d --build +docker compose -f docker-compose.dev.yml up -d ``` -Backend environment changes (like CORS_ORIGINS) only need a restart, not a rebuild. +## Installed Tools (Inside VS Code Server Container) -### Access URLs +Installed in `/home/coder` — persists via Docker volume: -- **Frontend:** `http://192.168.0.9:5173` -- **Backend API:** `http://192.168.0.9:8000` -- **API Docs:** `http://192.168.0.9:8000/docs` +- **nvm** — Node version manager +- **Node.js 20.x** — via nvm, default alias set +- **npm** — latest +- **GitHub CLI (gh)** — authenticated via personal access token +- **Claude Code CLI** — `@anthropic-ai/claude-code` (global npm) -## Known Issues & Fixes +### Permanent Tool Installs -### iptables DROP Rules Blocking Docker Traffic +Tools installed via `apt` inside the container do NOT survive container rebuilds. To add permanently, modify the VS Code Server Docker image and rebuild. -Docker routes container traffic through the FORWARD chain. Rogue DROP rules in the DOCKER chain can block all container networking. - -**Symptoms:** Container shows as running, port is listening via `ss`, but `curl` returns "Connection reset by peer" or "Connection refused" from other machines. - -**Diagnosis:** +Temporary (session only): ```bash -sudo iptables -L DOCKER -n --line-numbers +sudo apt update && sudo apt install -y ``` -Look for blanket DROP rules: -``` -2 DROP all -- 0.0.0.0/0 0.0.0.0/0 -3 DROP all -- 0.0.0.0/0 0.0.0.0/0 -``` - -**Fix:** -```bash -# Remove DROP rules (remove highest numbered first) -sudo iptables -D DOCKER 3 -sudo iptables -D DOCKER 2 -``` - -If the FORWARD chain has `policy DROP` and Docker containers can't communicate: -```bash -sudo systemctl restart docker -``` - -Docker rebuilds its iptables chains on restart. These rules don't persist across reboots by default — if they come back, something else is creating them. - -### Code-Server Port Mismatch - -The codercom/code-server image listens on port **8443** internally, not 8080. The compose file must map `8080:8443`: - -```yaml -ports: - - 8080:8443 -``` - -The code-server config file (`/home/coder/.config/code-server/config.yaml`) must bind to `0.0.0.0`, not `127.0.0.1`: - -```yaml -bind-addr: 0.0.0.0:8443 -``` - -If it says `127.0.0.1`, it will only accept connections from inside the container. - -### Permission Issues Inside Container - -The container runs as user `coder` (UID 1000). Host files mounted into the container must be owned by UID 1000: +## SSH Access ```bash -# Fix project permissions -sudo chown -R 1000:1000 ~/docker/projects - -# Fix code-server config permissions -sudo chown -R 1000:1000 ~/docker/code-server/config/ - -# Fix Claude Code config permissions -sudo chown -R 1000:1000 ~/.claude/ +ssh root@46.202.92.250 ``` -### GitHub CLI (gh) Auth - -gh stores its config at `/home/coder/.config/gh/`. If it fails with permission denied: - -```bash -docker exec -u root code-server mkdir -p /home/coder/.config/gh -docker exec -u root code-server chown -R 1000:1000 /home/coder/.config -``` +Key auth configured via `~/.ssh/authorized_keys` on host. ## Useful Commands ### Check all running containers ```bash -docker ps +docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" ``` -### View logs for a specific container +### View container logs ```bash -docker logs --tail 30 +docker logs --tail 30 -f ``` -### Restart code-server +### Restart VS Code Server ```bash -cd ~/docker -docker compose up -d +cd /docker/vscode && docker compose restart ``` -### Rebuild code-server (after Dockerfile changes) +### Restart Traefik ```bash -cd ~/docker -docker compose down -docker compose up -d --build +cd /docker/traefik && docker compose restart ``` -### Restart dev environment +### Restart dev stack ```bash -cd ~/docker/projects/patherly +cd /var/lib/docker/volumes/vscode_vscode-data/_data/resolutionflow docker compose -f docker-compose.dev.yml down docker compose -f docker-compose.dev.yml up -d ``` -### SSH into devserver01 +### Check swap ```bash -ssh michael@192.168.0.9 +free -h && swapon --show ``` -### Check what's listening on ports +### Check disk ```bash -sudo ss -tlnp | grep +df -h ``` -### Check firewall / iptables +### Check memory + container usage ```bash -sudo ufw status -sudo iptables -L -n --line-numbers -sudo iptables -L DOCKER -n --line-numbers +free -h && docker stats --no-stream ``` -### Execute commands inside containers -```bash -# As default user -docker exec code-server +## DNS Records (resolutionflow.com) -# As root -docker exec -u root code-server +| Type | Name | Value | Purpose | +|---|---|---|---| +| A | code | 46.202.92.250 | VS Code Server | -# Interactive shell -docker exec -it code-server bash -``` +## Security Notes -## Network Info +- UFW is inactive — Traefik and Docker manage port exposure +- All public-facing services run through Traefik with valid HTTPS certs +- PostgreSQL port 5432 is exposed on all interfaces — restrict if needed in production +- Rotate API keys (Anthropic, Voyage) if ever exposed in logs or chat +- Never commit `.env` files to Git -- **Server IP:** 192.168.0.9 -- **Docker bridge network:** 172.17.0.0/16 and 172.18.0.0/16 -- **Host user:** michael (UID 1000) -- **Container user:** coder (UID 1000) — same UID allows seamless file sharing via volume mounts +## VS Code Server Browser Tips -## Code-Server Browser Tips - -- **Command Palette:** `F1` (not Ctrl+Shift+P, which opens Firefox private window) -- **Context Menu (right-click):** `Alt + Right Click` -- **Terminal:** `` Ctrl+` `` +- **Command Palette:** `F1` +- **Terminal:** Ctrl+` - **Rename file:** `F2` - **Go to definition:** `F12` - **Find references:** `Shift+F12` - -## Adding New Tools to Code-Server - -To permanently add tools (survive container restarts), add them to `~/docker/Dockerfile.code-server`: - -```dockerfile -USER root -RUN apt update && apt install -y && rm -rf /var/lib/apt/lists/* -USER coder -``` - -Then rebuild: -```bash -cd ~/docker -docker compose down -docker compose up -d --build -``` - -For temporary installs (gone after restart): -```bash -docker exec -u root code-server apt update -docker exec -u root code-server apt install -y -``` \ No newline at end of file +- **Context Menu:** `Alt + Right Click` \ No newline at end of file diff --git a/backend/.env.example b/backend/.env.example index 087d1a6a..0d6a3e5a 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -1,10 +1,10 @@ # Application -APP_NAME=Patherly +APP_NAME=ResolutionFlow DEBUG=true # Database -DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/patherly -DATABASE_URL_SYNC=postgresql://postgres:postgres@localhost:5432/patherly +DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/resolutionflow +DATABASE_URL_SYNC=postgresql://postgres:postgres@localhost:5432/resolutionflow # JWT Settings - CHANGE THESE IN PRODUCTION # Generate with: openssl rand -hex 32 @@ -15,3 +15,10 @@ REFRESH_TOKEN_EXPIRE_DAYS=7 # CORS CORS_ORIGINS=["http://localhost:3000","http://localhost:5173"] + +# Anthropic API Key +ANTHROPIC_API_KEY= +VOYAGE_API_KEY= + +# ConnectWise PSA Integration +CW_CLIENT_ID= \ No newline at end of file diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index f6111f7e..7aed2104 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -39,7 +39,7 @@ services: - AI_PROVIDER=anthropic - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} - GOOGLE_AI_API_KEY=${GOOGLE_AI_API_KEY} - - CORS_ORIGINS=["http://localhost:3000","http://localhost:5173","http://127.0.0.1:3000","http://127.0.0.1:5173","http://192.168.0.9:5173","http://192.168.0.9:3000"] + - CORS_ORIGINS=["http://localhost:3000","http://localhost:5173","http://127.0.0.1:3000","http://127.0.0.1:5173","http://46.202.92.250:5173","http://46.202.92.250:3000","https://resolutionflow.com","https://www.resolutionflow.com"] depends_on: db: condition: service_healthy @@ -55,7 +55,7 @@ services: - ./frontend:/app - /app/node_modules environment: - - VITE_API_URL=http://192.168.0.9:8000 + - VITE_API_URL=http://46.202.92.250:8000 depends_on: - backend