Skip to content

Commit a7df295

Browse files
bs10081claude
andcommitted
feat: add one-click installer and server Docker bundle
On-Device Agent (curl|bash): - dist/install-agent.sh: interactive full installer — apt deps, downloads agent payload from server, runs pi-agent/install/install.sh, registers node via /api/agents/register, installs Alloy log forwarder - dist/build-agent-payload.sh: packages pi-agent/ into aads-agent.tgz - pi-agent/alloy/config.alloy.tmpl: Alloy config template with __NODE_ID__/__LOKI_URL__ placeholders filled at install time Server Docker bundle (prebuilt registry images): - docker-compose.prod.yaml: mirrors dev compose but pulls ghcr.io/bs10081/aads-* images; mounts ./dist into dashboard for self-serve agent installer downloads - dist/bootstrap-server.sh: interactive server bootstrap — generates secrets, writes .env, builds agent payload, compose pull+up, verifies DB, prints ready-to-paste agent install command - .github/workflows/build-images.yml: builds and pushes 6 service images to GHCR on tag push; attaches agent payload to releases Supporting changes: - dashboard/app.py: add /install-agent.sh and /aads-agent.tgz static routes so targets download payload from the server without external net - .env.example: add AADS_IMAGE_REGISTRY/TAG keys for prod compose - .gitignore: stop ignoring dist/ scripts; only ignore dist/aads-agent.tgz - DEPLOYMENT.md: rewrite for one-click server-first → agent flow - docs/lab-deploy-plan.md: track lab deploy plan (untracked file) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 560fdd2 commit a7df295

11 files changed

Lines changed: 1497 additions & 31 deletions

File tree

.env.example

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22
# AI Auto Debug System - Environment Variables
33
# ============================================
44

5+
# ============================================
6+
# Prebuilt service images (docker-compose.prod.yaml)
7+
# ============================================
8+
# Where the 6 custom service images are pulled from. Built/pushed by
9+
# .github/workflows/build-images.yml. Used only by docker-compose.prod.yaml.
10+
AADS_IMAGE_REGISTRY=ghcr.io/bs10081
11+
AADS_IMAGE_TAG=latest
12+
513
# ============================================
614
# Layer 0: TimescaleDB 持久化存儲
715
# ============================================

.github/workflows/build-images.yml

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
name: build-images
2+
3+
# Build & push the 6 custom AADS service images to GHCR, and publish the
4+
# On-Device Agent payload as a release asset. The server bootstrap
5+
# (dist/bootstrap-server.sh) pulls these images; targets download the payload.
6+
#
7+
# Triggers on version tags (v*) and can be run manually (pushes :latest).
8+
9+
on:
10+
push:
11+
tags:
12+
- 'v*'
13+
workflow_dispatch:
14+
15+
env:
16+
REGISTRY: ghcr.io
17+
18+
jobs:
19+
images:
20+
runs-on: ubuntu-latest
21+
permissions:
22+
contents: read
23+
packages: write
24+
strategy:
25+
matrix:
26+
include:
27+
- name: aads-layer1-filter
28+
context: ./layer1-filter
29+
- name: aads-ingester
30+
context: ./layer1-filter/ingester
31+
- name: aads-layer2-analyzer
32+
context: ./layer2-analyzer
33+
- name: aads-layer4-executor
34+
context: ./layer4-executor
35+
- name: aads-dashboard
36+
context: ./dashboard
37+
- name: aads-log-archiver
38+
context: ./layer0-storage/sync
39+
steps:
40+
- uses: actions/checkout@v4
41+
42+
- name: Log in to GHCR
43+
uses: docker/login-action@v3
44+
with:
45+
registry: ${{ env.REGISTRY }}
46+
username: ${{ github.actor }}
47+
password: ${{ secrets.GITHUB_TOKEN }}
48+
49+
- name: Image metadata
50+
id: meta
51+
uses: docker/metadata-action@v5
52+
with:
53+
images: ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ matrix.name }}
54+
tags: |
55+
type=ref,event=tag
56+
type=raw,value=latest
57+
58+
- name: Build and push
59+
uses: docker/build-push-action@v6
60+
with:
61+
context: ${{ matrix.context }}
62+
push: true
63+
tags: ${{ steps.meta.outputs.tags }}
64+
labels: ${{ steps.meta.outputs.labels }}
65+
66+
agent-payload:
67+
runs-on: ubuntu-latest
68+
permissions:
69+
contents: write
70+
steps:
71+
- uses: actions/checkout@v4
72+
73+
- name: Build agent payload
74+
run: bash dist/build-agent-payload.sh "$GITHUB_WORKSPACE/dist/aads-agent.tgz"
75+
76+
- name: Attach to release
77+
if: startsWith(github.ref, 'refs/tags/')
78+
uses: softprops/action-gh-release@v2
79+
with:
80+
files: |
81+
dist/aads-agent.tgz
82+
dist/install-agent.sh

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ venv/
99
.venv/
1010
.venv-test/
1111
*.egg-info/
12-
dist/
1312
build/
1413

14+
# Deployment scripts live in dist/ (tracked); only the built agent payload is ignored.
15+
dist/aads-agent.tgz
16+
1517
# PyTorch/Transformers models
1618
*.bin
1719
*.pt

DEPLOYMENT.md

Lines changed: 72 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,79 @@
11
# 🚀 Deployment Guide
22

3+
AADS has two sides: a **server** (Docker Compose stack) and one or more
4+
**on-device agents** (installed on the machines you want auto-debugged).
5+
Deploy the server first — it mints the token the agents need.
6+
7+
## One-Click Deployment (recommended)
8+
9+
### 1. Server (run on the controller host)
10+
11+
From a repo checkout or the server bundle:
12+
13+
```bash
14+
bash dist/bootstrap-server.sh
15+
```
16+
17+
It interactively collects the upstream LLM API key (the only required value),
18+
auto-generates the remaining secrets, pulls the prebuilt images
19+
(`ghcr.io/bs10081/aads-*`), starts the stack, verifies the database, and prints
20+
the exact agent install command — with the token already filled in.
21+
22+
> Private registry? Authenticate once before running:
23+
> `echo $GHCR_TOKEN | docker login ghcr.io -u <github-user> --password-stdin`
24+
25+
### 2. On-Device Agent (run on each target)
26+
27+
Copy-paste the command the server printed. It looks like:
28+
29+
```bash
30+
curl -fsSL http://<server>:5000/install-agent.sh | sudo \
31+
AADS_SERVER=<server> \
32+
AADS_AGENT_TOKEN=<token> \
33+
AADS_ADMIN_API_KEY=<admin-key> bash
34+
```
35+
36+
This installs the On-Device Agent (V2 runner), auto-registers the node with the
37+
server, and installs the Alloy log forwarder pointed at the server's Loki. The
38+
installer downloads its payload (`aads-agent.tgz`) from the server itself — no
39+
external/GitHub access needed. Every prompt can be pre-set via environment
40+
variables (see the header of `dist/install-agent.sh`).
41+
42+
### 3. Verify
43+
44+
```bash
45+
# server
46+
docker compose -f docker-compose.prod.yaml --env-file .env ps
47+
curl -H "X-Admin-API-Key: <admin-key>" http://<server>:5000/api/agents
48+
49+
# target
50+
curl -H "Authorization: Bearer <token>" http://<target>:8090/v1/node/facts
51+
systemctl is-active aads-agent alloy
52+
```
53+
54+
## Building / publishing images
55+
56+
Images are built and pushed by `.github/workflows/build-images.yml` on a
57+
version tag (`git tag v1.0.0 && git push --tags`). It also attaches
58+
`aads-agent.tgz` + `install-agent.sh` to the GitHub release, so agents can
59+
alternatively pull from the release by setting `AADS_RELEASE_BASE_URL`.
60+
61+
## Manual / Dev Start (build locally)
62+
63+
```bash
64+
git clone https://github.com/bs10081/AADS
65+
cd AADS
66+
cp .env.example .env # edit secrets
67+
docker compose up -d --build # builds images locally instead of pulling
68+
docker compose ps
69+
curl http://localhost:8000/health # Ingester
70+
curl http://localhost:8080/health # Layer 2 Analyzer
71+
```
72+
373
## Prerequisites
474

5-
- Docker & Docker Compose
6-
- NVIDIA GPU (for LogBERT)
7-
- NVIDIA Container Toolkit
8-
9-
## Quick Start
10-
11-
1. **Clone the repository**
12-
```bash
13-
git clone https://github.com/bs10081/ADDS
14-
cd ADDS
15-
```
16-
17-
2. **Validate Alloy configuration**
18-
```bash
19-
docker run --rm -v $(pwd)/layer0-collector/alloy:/config \
20-
grafana/alloy:latest validate /config/config.alloy
21-
```
22-
23-
3. **Start all services**
24-
```bash
25-
docker compose up -d
26-
```
27-
28-
4. **Verify health**
29-
```bash
30-
docker compose ps
31-
curl http://localhost:8000/health # Ingester
32-
curl http://localhost:8080/health # Layer 2 Analyzer
33-
```
75+
- Docker & Docker Compose v2
76+
- (Optional) NVIDIA GPU + Container Toolkit for the GPU LogBERT profile
3477

3578
## Architecture
3679

dashboard/app.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Simple Dashboard for AI Auto-Debug System
33
Display anomalies and diagnosis reports
44
"""
5-
from flask import Flask, render_template, jsonify, request
5+
from flask import Flask, render_template, jsonify, request, send_from_directory
66
import asyncpg
77
import asyncio
88
import hashlib
@@ -262,6 +262,23 @@ def index():
262262
return render_template('index.html')
263263

264264

265+
# Self-serve On-Device Agent installer. The bootstrap script drops
266+
# install-agent.sh + aads-agent.tgz into AADS_DIST_DIR (mounted from ./dist),
267+
# so targets can `curl -fsSL http://<server>:5000/install-agent.sh | sudo bash`
268+
# without any external download source.
269+
DIST_DIR = os.getenv('AADS_DIST_DIR', '/app/dist')
270+
271+
272+
@app.route('/install-agent.sh')
273+
def serve_install_agent():
274+
return send_from_directory(DIST_DIR, 'install-agent.sh', mimetype='text/x-shellscript')
275+
276+
277+
@app.route('/aads-agent.tgz')
278+
def serve_agent_payload():
279+
return send_from_directory(DIST_DIR, 'aads-agent.tgz', mimetype='application/gzip')
280+
281+
265282
@app.route('/api/diagnosis')
266283
def api_diagnosis():
267284
"""API endpoint for diagnosis reports"""

0 commit comments

Comments
 (0)