# DevServer01 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 ## Docker Setup Docker was installed via the official convenience script: ```bash curl -fsSL https://get.docker.com | sh sudo usermod -aG docker michael ``` Docker Compose is included with this installation. ## Code-Server ### Overview 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 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 ``` ### Key Details - **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` ### SSL Certificates Location: `~/docker/code-server/certs/` A custom Certificate Authority (CA) was created for the homelab: - `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 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." ### Volume Mapping Reference | 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 | ## Patherly / ResolutionFlow Dev Environment ### Docker Compose (Dev) 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 ### Environment Files - `~/docker/projects/patherly/.env` — Backend secrets (SECRET_KEY, API keys, etc.) - `~/docker/projects/patherly/frontend/.env` — Frontend config (VITE_API_URL) ### Critical Configuration for Remote Access Since the dev environment is accessed from other machines on the LAN (not localhost), these settings are required: **Frontend `.env`:** ``` VITE_API_URL=http://192.168.0.9:8000 ``` **Backend CORS_ORIGINS in `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"] ``` 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 ```bash cd ~/docker/projects/patherly docker compose -f docker-compose.dev.yml up -d ``` ### Running Migrations (Fresh Database) ```bash docker compose -f docker-compose.dev.yml run --rm backend alembic upgrade head ``` ### Seeding Test Users ```bash docker exec resolutionflow_backend python -m scripts.seed_test_users ``` ### Rebuilding After Frontend .env Changes Vite bakes environment variables at build time, so changes to `VITE_API_URL` require a rebuild: ```bash docker compose -f docker-compose.dev.yml down docker compose -f docker-compose.dev.yml up -d --build ``` Backend environment changes (like CORS_ORIGINS) only need a restart, not a rebuild. ### Access URLs - **Frontend:** `http://192.168.0.9:5173` - **Backend API:** `http://192.168.0.9:8000` - **API Docs:** `http://192.168.0.9:8000/docs` ## Known Issues & Fixes ### iptables DROP Rules Blocking Docker Traffic 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:** ```bash sudo iptables -L DOCKER -n --line-numbers ``` 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: ```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/ ``` ### 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 ``` ## Useful Commands ### Check all running containers ```bash docker ps ``` ### View logs for a specific container ```bash docker logs --tail 30 ``` ### Restart code-server ```bash cd ~/docker docker compose up -d ``` ### Rebuild code-server (after Dockerfile changes) ```bash cd ~/docker docker compose down docker compose up -d --build ``` ### Restart dev environment ```bash cd ~/docker/projects/patherly docker compose -f docker-compose.dev.yml down docker compose -f docker-compose.dev.yml up -d ``` ### SSH into devserver01 ```bash ssh michael@192.168.0.9 ``` ### Check what's listening on ports ```bash sudo ss -tlnp | grep ``` ### Check firewall / iptables ```bash sudo ufw status sudo iptables -L -n --line-numbers sudo iptables -L DOCKER -n --line-numbers ``` ### Execute commands inside containers ```bash # As default user docker exec code-server # As root docker exec -u root code-server # Interactive shell docker exec -it code-server bash ``` ## Network Info - **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 ## 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+` `` - **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 ```