Update DEV_CONTAINER_SPEC — remove Traefik model, document API proxy + Headscale access
This commit is contained in:
parent
d128d92d15
commit
1c28ecbb7c
@ -1,18 +1,22 @@
|
|||||||
# ZeroLagHub Developer Container Architecture
|
# ZeroLagHub Developer Container Architecture
|
||||||
|
|
||||||
This document describes how developer containers are provisioned and managed by the zlh-agent.
|
This document describes how developer containers are provisioned and accessed.
|
||||||
|
|
||||||
It is intended for engineers and AI assistants working on the ZeroLagHub platform.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
Developer containers provide ephemeral development environments for building and testing software.
|
Developer containers provide ephemeral development environments.
|
||||||
|
|
||||||
They support multiple runtimes and optional development tooling.
|
Provisioning is performed by the **zlh-agent** using runtime artifacts.
|
||||||
|
|
||||||
Provisioning is performed by the zlh-agent using an artifact-driven runtime system.
|
Supported runtimes:
|
||||||
|
|
||||||
|
- node
|
||||||
|
- python
|
||||||
|
- go
|
||||||
|
- java
|
||||||
|
- dotnet
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -20,135 +24,41 @@ Provisioning is performed by the zlh-agent using an artifact-driven runtime syst
|
|||||||
|
|
||||||
Provisioning flow:
|
Provisioning flow:
|
||||||
|
|
||||||
1. Portal sends dev container request
|
1. Portal sends dev request
|
||||||
2. API builds agent provisioning payload
|
2. API builds provisioning payload
|
||||||
3. Agent validates request
|
3. Agent installs runtime
|
||||||
4. Agent creates dev environment
|
4. Agent installs addons
|
||||||
5. Agent installs runtime from artifact server
|
5. Agent marks container ready
|
||||||
6. Agent optionally installs addons
|
|
||||||
7. Agent marks container ready
|
|
||||||
8. API applies dev routing if code-server is enabled
|
|
||||||
|
|
||||||
High-level architecture:
|
Architecture:
|
||||||
|
|
||||||
```
|
```
|
||||||
Portal
|
Portal
|
||||||
↓
|
↓
|
||||||
zlh-api
|
zpack-api
|
||||||
↓
|
↓
|
||||||
zlh-agent
|
zlh-agent
|
||||||
↓
|
↓
|
||||||
Artifact Server
|
Artifact Server
|
||||||
```
|
```
|
||||||
|
|
||||||
If `enable_code_server=true`, the API additionally performs:
|
|
||||||
|
|
||||||
- Cloudflare DNS record creation
|
|
||||||
- Technitium DNS record creation
|
|
||||||
- Traefik dynamic config write on `zlh-zpack-proxy`
|
|
||||||
|
|
||||||
This routing path is additive and does not modify the game publish flow.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Dev Provisioning Payload
|
## Dev Environment
|
||||||
|
|
||||||
The API sends configuration to the agent via:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
POST http://<agent-ip>:18888/config
|
user: dev
|
||||||
|
home: /home/dev
|
||||||
|
workspace: /home/dev/workspace
|
||||||
```
|
```
|
||||||
|
|
||||||
Dev payload example:
|
Console sessions run as the dev user.
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"container_type": "dev",
|
|
||||||
"runtime": "node",
|
|
||||||
"version": "22",
|
|
||||||
"memory_mb": 2048,
|
|
||||||
"enable_code_server": true
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Fields:
|
|
||||||
|
|
||||||
| Field | Description |
|
|
||||||
|-------|-------------|
|
|
||||||
| `container_type` | must be `"dev"` |
|
|
||||||
| `runtime` | runtime id |
|
|
||||||
| `version` | runtime version |
|
|
||||||
| `memory_mb` | container memory |
|
|
||||||
| `enable_code_server` | optional addon |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Runtime Catalog
|
|
||||||
|
|
||||||
All dev runtimes are defined by the artifact server catalog.
|
|
||||||
|
|
||||||
Catalog location:
|
|
||||||
|
|
||||||
```
|
|
||||||
http://<artifact-server>/devcontainer/_catalog.json
|
|
||||||
```
|
|
||||||
|
|
||||||
Example catalog:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"runtimes": [
|
|
||||||
{ "id": "go", "versions": ["1.22", "1.25"] },
|
|
||||||
{ "id": "java", "versions": ["17", "19", "21"] },
|
|
||||||
{ "id": "node", "versions": ["20", "22", "24"] },
|
|
||||||
{ "id": "python", "versions": ["3.10", "3.11", "3.12", "3.13"] },
|
|
||||||
{ "id": "dotnet", "versions": ["8.0", "10.0"] }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The agent validates runtime/version against this catalog before installation.
|
|
||||||
|
|
||||||
Invalid combinations cause provisioning to fail.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Artifact Server Layout
|
|
||||||
|
|
||||||
Dev runtime artifacts:
|
|
||||||
|
|
||||||
```
|
|
||||||
devcontainer/
|
|
||||||
_catalog.json
|
|
||||||
go/
|
|
||||||
node/
|
|
||||||
python/
|
|
||||||
java/
|
|
||||||
dotnet/
|
|
||||||
```
|
|
||||||
|
|
||||||
Example runtime artifact:
|
|
||||||
|
|
||||||
```
|
|
||||||
devcontainer/node/22/node-22.tar.xz
|
|
||||||
```
|
|
||||||
|
|
||||||
Addon artifacts:
|
|
||||||
|
|
||||||
```
|
|
||||||
addons/
|
|
||||||
code-server/
|
|
||||||
```
|
|
||||||
|
|
||||||
Artifacts are downloaded at provisioning time.
|
|
||||||
|
|
||||||
Nothing is preinstalled inside containers.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Runtime Installation
|
## Runtime Installation
|
||||||
|
|
||||||
Runtime install path:
|
Runtime path:
|
||||||
|
|
||||||
```
|
```
|
||||||
/opt/zlh/runtimes/<runtime>/<version>
|
/opt/zlh/runtimes/<runtime>/<version>
|
||||||
@ -167,110 +77,19 @@ Install guards prevent reinstall — if the directory already exists, installati
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Dev Environment
|
|
||||||
|
|
||||||
Every dev container has a dedicated development user.
|
|
||||||
|
|
||||||
```
|
|
||||||
user: dev
|
|
||||||
home: /home/dev
|
|
||||||
workspace: /home/dev/workspace
|
|
||||||
ownership: dev:dev
|
|
||||||
```
|
|
||||||
|
|
||||||
The workspace is where developers store source code.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Console Behavior
|
|
||||||
|
|
||||||
Dev console sessions run as the dev user.
|
|
||||||
|
|
||||||
Shell properties:
|
|
||||||
|
|
||||||
```
|
|
||||||
user: dev
|
|
||||||
cwd: /home/dev/workspace
|
|
||||||
HOME=/home/dev
|
|
||||||
TERM=xterm-256color
|
|
||||||
```
|
|
||||||
|
|
||||||
This prevents root access in development environments.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## File System Access
|
|
||||||
|
|
||||||
Dev containers expose a file browser rooted at:
|
|
||||||
|
|
||||||
```
|
|
||||||
/home/dev/workspace
|
|
||||||
```
|
|
||||||
|
|
||||||
Portal displays this as `workspace/`.
|
|
||||||
|
|
||||||
Uploads and file operations are restricted to this directory.
|
|
||||||
|
|
||||||
Dev containers have unrestricted read/write access inside `/home/dev/workspace`. No allowlist. The only hard rule is the root sandbox — nothing can escape the workspace.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Dotnet Runtime
|
|
||||||
|
|
||||||
Dotnet uses the official installer script.
|
|
||||||
|
|
||||||
Installer source:
|
|
||||||
|
|
||||||
```
|
|
||||||
http://artifact-server/devcontainer/dotnet/dotnet-install.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Installation:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./dotnet-install.sh --channel 8.0
|
|
||||||
```
|
|
||||||
|
|
||||||
Installed to:
|
|
||||||
|
|
||||||
```
|
|
||||||
/opt/zlh/runtimes/dotnet/8.0
|
|
||||||
```
|
|
||||||
|
|
||||||
Supported channels: `8.0`, `10.0`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Code Server Addon
|
## Code Server Addon
|
||||||
|
|
||||||
Code-server provides a browser IDE.
|
Code-server provides browser IDE access.
|
||||||
|
|
||||||
Enabled via provisioning flag:
|
Install location:
|
||||||
|
|
||||||
```json
|
|
||||||
"enable_code_server": true
|
|
||||||
```
|
|
||||||
|
|
||||||
Artifact location:
|
|
||||||
|
|
||||||
```
|
|
||||||
http://artifact-server/addons/code-server/code-server.zip
|
|
||||||
```
|
|
||||||
|
|
||||||
Installed to:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
/opt/zlh/services/code-server
|
/opt/zlh/services/code-server
|
||||||
```
|
```
|
||||||
|
|
||||||
Launch behavior:
|
Port: `6000`
|
||||||
|
|
||||||
- process runs inside the container
|
Observed process:
|
||||||
- binds to `0.0.0.0:6000`
|
|
||||||
- workspace root is `/home/dev/workspace`
|
|
||||||
- current auth mode observed in runtime is password-based
|
|
||||||
|
|
||||||
Observed process shape:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
/opt/zlh/services/code-server/lib/node /opt/zlh/services/code-server \
|
/opt/zlh/services/code-server/lib/node /opt/zlh/services/code-server \
|
||||||
@ -281,62 +100,100 @@ Observed process shape:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Dev Routing
|
## Dev IDE Access Model
|
||||||
|
|
||||||
When code-server is enabled, the API creates a dev-only routing path.
|
The previous model using Cloudflare DNS, Traefik, and per-container subdomains has been removed.
|
||||||
|
|
||||||
Current implementation:
|
|
||||||
|
|
||||||
- creates Technitium A record for `dev-<vmid>.<domain>`
|
|
||||||
- creates Cloudflare A record for `dev-<vmid>.<domain>`
|
|
||||||
- writes Traefik dynamic config on the proxy VM via SSH service account `zlh`
|
|
||||||
- dynamic file path: `/etc/traefik/dynamic/dev-<vmid>.yml`
|
|
||||||
|
|
||||||
Current backend target model:
|
|
||||||
|
|
||||||
```
|
|
||||||
Host(`dev-<vmid>.<domain>`)
|
|
||||||
→ Traefik (websecure)
|
|
||||||
→ http://<container-ip>:6000
|
|
||||||
```
|
|
||||||
|
|
||||||
Status: routing generation is implemented, but external browser access remains under active validation.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Agent Status Model
|
### Browser IDE Access (Primary)
|
||||||
|
|
||||||
Status delivery model is unchanged:
|
IDE is accessed through the API proxy.
|
||||||
|
|
||||||
- API polls agent `/status`
|
```
|
||||||
- agent does not push state to API
|
Browser
|
||||||
|
↓
|
||||||
|
Portal
|
||||||
|
↓
|
||||||
|
API
|
||||||
|
↓
|
||||||
|
container:6000
|
||||||
|
```
|
||||||
|
|
||||||
Status content now includes dev/container fields:
|
URL format: `/dev/<vmid>/ide`
|
||||||
|
|
||||||
- `workspaceRoot`
|
code-server launch flags required:
|
||||||
- `serverRoot`
|
|
||||||
- `runtimeInstallPath`
|
|
||||||
- `runtimeInstalled`
|
|
||||||
- `devProvisioned`
|
|
||||||
- `devReadyAt`
|
|
||||||
- `codeServerInstalled`
|
|
||||||
- `codeServerRunning`
|
|
||||||
- `lastCrashClassification`
|
|
||||||
|
|
||||||
The API now exposes this polled state back to the frontend through a server status endpoint so console and host-state UI can update correctly.
|
```
|
||||||
|
--base-path /dev/<vmid>/ide --auth none
|
||||||
|
```
|
||||||
|
|
||||||
|
Portal JWT authentication gates access. The API verifies container ownership before proxying.
|
||||||
|
|
||||||
|
WebSocket support is mandatory — code-server is heavily WebSocket-based:
|
||||||
|
|
||||||
|
- `http-proxy-middleware` with `ws: true`
|
||||||
|
- `server.on('upgrade', proxy.upgrade)` must be wired up
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Local Development Access (Advanced Users)
|
||||||
|
|
||||||
|
Advanced users may connect via **Headscale/Tailscale**.
|
||||||
|
|
||||||
|
Benefits:
|
||||||
|
|
||||||
|
- SSH
|
||||||
|
- VS Code Remote
|
||||||
|
- full local tooling
|
||||||
|
|
||||||
|
Implementation:
|
||||||
|
|
||||||
|
- dev container installs `tailscaled` as an addon
|
||||||
|
- API generates Headscale auth key on provisioning
|
||||||
|
- customer joins tailnet once, gets stable container IP
|
||||||
|
|
||||||
|
Restrictions:
|
||||||
|
|
||||||
|
- no exit nodes
|
||||||
|
- `magic_dns: false`
|
||||||
|
- no DNS takeover on customer machine
|
||||||
|
|
||||||
|
Headscale server: `zlh-ctl` (status to be confirmed)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Security Model
|
## Security Model
|
||||||
|
|
||||||
Dev containers are isolated LXC containers.
|
- Portal authentication controls IDE access
|
||||||
|
- API verifies container ownership before proxying
|
||||||
Security controls:
|
- Containers are never exposed directly to the public internet
|
||||||
|
|
||||||
- Runtime installs limited to `/opt/zlh`
|
|
||||||
- File browser limited to workspace
|
|
||||||
- Shell runs as non-root `dev` user
|
- Shell runs as non-root `dev` user
|
||||||
- Artifacts fetched only from trusted artifact server
|
- File browser limited to workspace root
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Browser
|
||||||
|
|
||||||
|
Workspace root: `/home/dev/workspace`
|
||||||
|
|
||||||
|
Portal displays this as `workspace/`.
|
||||||
|
|
||||||
|
Uploads cannot escape this directory.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Agent Status
|
||||||
|
|
||||||
|
Status is polled by API via `/status`. Agent does not push state.
|
||||||
|
|
||||||
|
Dev fields in `/status`:
|
||||||
|
|
||||||
|
- `workspaceRoot`
|
||||||
|
- `runtimeInstallPath`
|
||||||
|
- `runtimeInstalled`
|
||||||
|
- `codeServerInstalled`
|
||||||
|
- `codeServerRunning`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -347,6 +204,7 @@ Security controls:
|
|||||||
3. Runtime catalog is the source of truth
|
3. Runtime catalog is the source of truth
|
||||||
4. Installs must be idempotent
|
4. Installs must be idempotent
|
||||||
5. Containers must remain reproducible
|
5. Containers must remain reproducible
|
||||||
|
6. Dev services are never publicly exposed directly
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -355,12 +213,5 @@ Security controls:
|
|||||||
- Runtime checksum validation
|
- Runtime checksum validation
|
||||||
- Runtime upgrades / removal
|
- Runtime upgrades / removal
|
||||||
- Artifact metadata support
|
- Artifact metadata support
|
||||||
- Service port auto-detection
|
- Tailscale addon implementation
|
||||||
- Dev service routing / proxy exposure
|
- Headscale auth key portal UI
|
||||||
- IDE launch integration from portal
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
Developer containers in ZeroLagHub provide isolated development environments with multiple runtime support, artifact-driven installs, optional browser IDE on port 6000, and consistent reproducible provisioning.
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user