# VS Code: Server Deployment Procedure **Generated:** 2026-06-02 **Maintainer:** Artemis (AI Foreman) --- ## Overview This document describes the deployment of [Microsoft VS Code: Server](https://code.visualstudio.com/docs/remote/vscode-server) (via LinuxServer `openvscode-server` Docker image) on **MK7** (Swarm Manager) to replace the previous `code-server` deployment on Neo. The primary driver was to enable **native Remote-SSH** support, which is unavailable in OpenVSX-based alternatives. **Key advantage:** MK7's placement on the `192.168.7.x` LAN grants direct access to all fleet nodes and Proxmox VE workers via their LAN IPs. When deployed on Neo (192.168.192.x), the container was isolated from fleet subnets. --- ## Architecture | Component | Value | |-----------|-------| | **Host** | MK7 (mark-vii.ai.home) | | **Swarm Mode** | `replicated` with placement constraint `node.hostname == mark-vii.ai.home` | | **Container IP** | Swarm overlay (10.0.1.x/24) via `traefik-public` network | | **Internal Service Port** | `3000` | | **Traefik Endpoint** | `vscode.ai.home` → `http://192.168.7.7:8443` | | **DNS Record** | `CNAME` `vscode.ai.home` → `traefik.ai.home` (Technitium) | | **Image** | `lscr.io/linuxserver/openvscode-server:latest` | | **Marketplace** | Microsoft (official) — Remote-SSH available natively | --- ## Prerequisites - MK7 Docker Swarm active with `traefik-public` overlay network - Traefik reverse proxy running on `traefik.ai.home` - Technitium DNS authoritative for `ai.home` zone - SSH key pair (`vscode_ed25519`) deployed to all fleet nodes - `/home/jarvis/.vscode-ssh` directory created on MK7 host with: - `config` — SSH aliases for all fleet nodes - `vscode_ed25519` — private key (mode 600) - `vscode_ed25519.pub` — public key (mode 644) --- ## Deployment Steps ### 1. Prepare SSH Key Directory on MK7 ```bash mkdir -p /home/jarvis/.vscode-ssh chmod 700 /home/jarvis/.vscode-ssh # Copy vscode_ed25519 key pair + config from source node scp source:/path/to/vscode_ed25519* /home/jarvis/.vscode-ssh/ chmod 600 /home/jarvis/.vscode-ssh/vscode_ed25519 chmod 644 /home/jarvis/.vscode-ssh/vscode_ed25519.pub chmod 644 /home/jarvis/.vscode-ssh/config ``` ### 2. Compose File (`vscode-server-compose.yaml`) ```yaml version: '3.8' services: vscode: image: lscr.io/linuxserver/openvscode-server:latest environment: - PUID=1000 - PGID=1000 - TZ=America/New_York # Generate a random hex token: openssl rand -hex 16 - CONNECTION_TOKEN= - DEFAULT_WORKSPACE=/config/workspace volumes: - vscode_data:/config/workspace - type: bind source: /home/jarvis/.vscode-ssh target: /config/.ssh networks: - traefik-public deploy: placement: constraints: - node.hostname == mark-vii.ai.home labels: - "traefik.enable=true" - "traefik.http.routers.vscode.rule=Host(`vscode.ai.home`)" - "traefik.http.routers.vscode.entrypoints=websecure" - "traefik.http.routers.vscode.tls=true" - "traefik.http.services.vscode.loadbalancer.server.port=3000" volumes: vscode_data: driver: local networks: traefik-public: external: true ``` **Note:** Traefik on this cluster uses the **file provider** (not Docker provider). Swarm labels are informational only. You must also add a route file to Traefik's dynamic config directory. ### 3a. Traefik Route File Create `/opt/iron-legion/docker-swarm/traefik/dynamic/vscode.yml` on the MK7 host: ```yaml http: routers: vscode-http: rule: "Host(`vscode.ai.home`)" entryPoints: - web service: vscode vscode-https: rule: "Host(`vscode.ai.home`)" entryPoints: - websecure service: vscode tls: {} services: vscode: loadBalancer: servers: - url: "http://192.168.7.7:8443" passHostHeader: true ``` Traefik auto-reloads file provider configs on change. ### 3. Deploy via Swarm ```bash sudo docker stack deploy -c vscode-server-compose.yaml vscode ``` ### 4. Verify Startup ```bash sudo docker service ls | grep vscode sudo docker service ps vscode_vscode sudo docker logs $(docker ps -q -f name=vscode) ``` --- ## Access URLs | Direct (HTTP) | `http://192.168.7.7:8443/?tkn=` | Lan-only, no SSL (if port published) | | Via Traefik (HTTPS) | `https://vscode.ai.home/?tkn=` | Recommended — CNAME to traefik.ai.home | **Token location:** Set in compose `CONNECTION_TOKEN` env var. --- ## Fleet Node SSH Config The container mounts `/config/.ssh` containing a standard OpenSSH `config` file with all fleet aliases. Remote-SSH extension reads this automatically. **Format example:** ```ssh-config Host artemis HostName 192.168.15.182 User jarvis IdentityFile ~/.ssh/vscode_ed25519 IdentitiesOnly yes ``` **PVE nodes (mk33/34/39):** Present but `User root` — key deployment pending. --- ## Why MK7 Over Neo | Factor | Neo (Previous) | MK7 (Current) | |--------|---------------|----------------| | Network | Isolated subnet (192.168.192.x) | Core LAN (192.168.7.x) | | Swarm | Standalone | Manager | | Traefik | Manual or absent | Already deployed | | Remote-SSH | Unavailable (OpenVSX) | Available (Microsoft) | | Fleet Reach | None | Direct SSH to all nodes | --- ## Troubleshooting **Port 8443 not reachable externally:** - Check Swarm ingress: `sudo iptables -t nat -L DOCKER-INGRESS | grep 8443` - Verify container binding: `sudo ss -tlnp | grep 8443` **Container fails to start with mount error:** - Ensure `/home/jarvis/.vscode-ssh` exists on MK7 host before deploy - Swarm bind mounts require host path existence at deploy time **Token rejected:** - Tokens must be hex-only characters (0-9, a-f) - Regenerate with: `openssl rand -hex 16` **Traefik route not found:** - Verify `traefik-public` network exists: `docker network ls | grep traefik` - Check Traefik dashboard at `https://traefik.ai.home:8080` --- ## References - [LinuxServer OpenVSCode-Server Docker](https://github.com/linuxserver/docker-openvscode-server) - [VS Code: Server Documentation](https://code.visualstudio.com/docs/remote/vscode-server) - [Remote-SSH Extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh) --- *End of document*