docs: update dev environment config and documentation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-23 20:51:39 +00:00
parent b414502062
commit 5c78a4051a
3 changed files with 162 additions and 243 deletions

View File

@@ -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=<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.<n>.rule=Host(`subdomain.resolutionflow.com`)"
- "traefik.http.routers.<n>.entrypoints=websecure"
- "traefik.http.routers.<n>.tls.certresolver=letsencrypt"
- "traefik.http.services.<n>.loadbalancer.server.port=<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 <tool>
```
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 <container_name> --tail 30
docker logs <container_name> --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 <port>
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 <command>
## DNS Records (resolutionflow.com)
# As root
docker exec -u root code-server <command>
| 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 <new-tool> && 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 <new-tool>
```
- **Context Menu:** `Alt + Right Click`