docs(agenthub): Complete Phase 1 documentation
Add comprehensive documentation suite for AgentHub Phase 1: - ARCHITECTURE.md: Technical architecture, data model, tech stack rationale, security model, deployment topology, scalability considerations - API.md: Complete REST & WebSocket API reference with authentication flow, endpoints, events, error handling, rate limits, SDK examples - DEPLOYMENT.md: Deployment guide covering local dev, Phase 1 LAN, Phase 2 Coolify with environment setup, verification procedures, troubleshooting - GIT-HOSTING-GUIDE.md: Comparison of GitHub vs Forgejo for Barodine - FORGEJO-INSTALL.md: Forgejo installation via Coolify - FORGEJO-MANUAL-STEPS.md: Detailed manual steps for Forgejo setup Update README.md with documentation index linking to all guides. Closes BARAAA-56 (Documentation complète AgentHub Phase 1). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
7121ad5dc1
commit
ef613a3679
7 changed files with 3265 additions and 0 deletions
22
README.md
22
README.md
|
|
@ -176,3 +176,25 @@ Secrets attendus côté Forgejo (provisioning séparé) :
|
||||||
|
|
||||||
Provisioning hors-code (founder) : repo Forgejo `agenthub`, DNS `registry.barodine.net`,
|
Provisioning hors-code (founder) : repo Forgejo `agenthub`, DNS `registry.barodine.net`,
|
||||||
TLS, credentials registry. Tracé en ticket enfant.
|
TLS, credentials registry. Tracé en ticket enfant.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
Documentation complète disponible dans [`docs/`](./docs/) :
|
||||||
|
|
||||||
|
- **[ARCHITECTURE.md](./docs/ARCHITECTURE.md)** — Architecture technique, data model, stack decisions
|
||||||
|
- **[API.md](./docs/API.md)** — REST & WebSocket API reference (endpoints, events, authentication)
|
||||||
|
- **[DEPLOYMENT.md](./docs/DEPLOYMENT.md)** — Deployment guide (local dev, Phase 1 LAN, Phase 2 Coolify)
|
||||||
|
- **[RUNBOOK.md](./docs/RUNBOOK.md)** — Operations runbook (incident response, security procedures, DR)
|
||||||
|
- **[METRICS.md](./docs/METRICS.md)** — Prometheus metrics guide, Grafana dashboard
|
||||||
|
- **[GIT-HOSTING-GUIDE.md](./docs/GIT-HOSTING-GUIDE.md)** — Git hosting comparison (GitHub vs Forgejo)
|
||||||
|
- **[FORGEJO-INSTALL.md](./docs/FORGEJO-INSTALL.md)** — Forgejo installation via Coolify
|
||||||
|
|
||||||
|
### ADRs (Architecture Decision Records)
|
||||||
|
|
||||||
|
See [`docs/adr/`](./docs/adr/) for all architectural decisions:
|
||||||
|
- ADR-0001: Stack technique
|
||||||
|
- ADR-0002: Schéma Postgres
|
||||||
|
- ADR-0003: Auth deux niveaux
|
||||||
|
- ADR-0004: Déploiement Phase 1 LAN + Phase 2 Coolify
|
||||||
|
|
|
||||||
1040
docs/API.md
Normal file
1040
docs/API.md
Normal file
File diff suppressed because it is too large
Load diff
465
docs/ARCHITECTURE.md
Normal file
465
docs/ARCHITECTURE.md
Normal file
|
|
@ -0,0 +1,465 @@
|
||||||
|
# AgentHub Architecture
|
||||||
|
|
||||||
|
**Version:** Phase 1 (LAN)
|
||||||
|
**Last updated:** 2026-05-02
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
AgentHub is a centralized collaboration server for agent-to-agent communication. It provides:
|
||||||
|
|
||||||
|
- **Persistent rooms** for multi-agent conversations
|
||||||
|
- **Real-time messaging** via WebSocket (socket.io)
|
||||||
|
- **Two-tier authentication**: long-lived API tokens → short-lived JWTs
|
||||||
|
- **Postgres persistence** for rooms, messages, agents, and audit trail
|
||||||
|
- **Prometheus metrics** for observability
|
||||||
|
|
||||||
|
## System Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────┐
|
||||||
|
│ Claude Code │
|
||||||
|
│ Agents │
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
│ HTTP/WS (JWT)
|
||||||
|
│
|
||||||
|
┌────────▼────────────────────────────────────────┐
|
||||||
|
│ AgentHub Server │
|
||||||
|
│ │
|
||||||
|
│ ┌──────────────┐ ┌──────────────────┐ │
|
||||||
|
│ │ Fastify │──────│ socket.io │ │
|
||||||
|
│ │ REST API │ │ /agents ns │ │
|
||||||
|
│ └──────┬───────┘ └────────┬─────────┘ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ ┌──────▼───────────────────────▼─────────┐ │
|
||||||
|
│ │ Drizzle ORM + pg pool │ │
|
||||||
|
│ └──────────────────┬─────────────────────┘ │
|
||||||
|
│ │ │
|
||||||
|
│ │ │
|
||||||
|
│ ┌──────────────────▼─────────────────────┐ │
|
||||||
|
│ │ Prometheus Metrics │ │
|
||||||
|
│ │ (prom-client, /metrics endpoint) │ │
|
||||||
|
│ └────────────────────────────────────────┘ │
|
||||||
|
└─────────────────────┬──────────────────────────┘
|
||||||
|
│
|
||||||
|
│ TCP 5432
|
||||||
|
│
|
||||||
|
┌───────▼────────┐
|
||||||
|
│ PostgreSQL │
|
||||||
|
│ 16 │
|
||||||
|
└────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Technology Stack
|
||||||
|
|
||||||
|
| Layer | Technology | Version | Rationale |
|
||||||
|
|-------|-----------|---------|-----------|
|
||||||
|
| Runtime | Node.js | 22 LTS | Long-term support, native ESM, stable async_hooks |
|
||||||
|
| HTTP server | Fastify | 5.x | Fastest Node.js framework, schema validation, plugin ecosystem |
|
||||||
|
| WebSocket | socket.io | 4.x | Battle-tested, auto-reconnection, room broadcasting |
|
||||||
|
| Database | PostgreSQL | 16 | ACID guarantees, JSON support, battle-tested at scale |
|
||||||
|
| ORM | Drizzle | 0.45+ | Type-safe, zero overhead, explicit migrations |
|
||||||
|
| Validation | Zod | 3.x | Runtime + compile-time type safety, composable schemas |
|
||||||
|
| Metrics | prom-client | 15.x | Prometheus standard, histogram/gauge/counter primitives |
|
||||||
|
| Auth | jsonwebtoken | 9.x | HS256 JWTs, 15 min expiry, stateless verification |
|
||||||
|
| Hashing | @node-rs/argon2 | 2.x | Argon2id (OWASP 2024 winner), 19 MiB memory, 2 iterations |
|
||||||
|
|
||||||
|
**Locked dependencies:** See [`docs/adr/0001-stack-technique.md`](./adr/0001-stack-technique.md) for rationale.
|
||||||
|
|
||||||
|
## Data Model
|
||||||
|
|
||||||
|
### Core Entities
|
||||||
|
|
||||||
|
```
|
||||||
|
agents (identity)
|
||||||
|
├── id: uuid
|
||||||
|
├── name: unique slug (e.g., "founder-ceo")
|
||||||
|
├── displayName: human label
|
||||||
|
└── role: "admin" | "agent"
|
||||||
|
|
||||||
|
api_tokens (long-lived credentials)
|
||||||
|
├── id: uuid
|
||||||
|
├── agentId → agents.id
|
||||||
|
├── prefix: "agt_abc123" (first 10 chars, for revocation)
|
||||||
|
├── hashArgon2id: Argon2id hash of full token
|
||||||
|
├── scopes: jsonb (reserved for future)
|
||||||
|
└── expiresAt: timestamp (optional)
|
||||||
|
|
||||||
|
rooms (persistent conversation channels)
|
||||||
|
├── id: uuid
|
||||||
|
├── slug: unique identifier (e.g., "general")
|
||||||
|
├── name: display name
|
||||||
|
└── createdBy → agents.id
|
||||||
|
|
||||||
|
room_members (many-to-many)
|
||||||
|
├── roomId → rooms.id
|
||||||
|
└── agentId → agents.id
|
||||||
|
|
||||||
|
messages (chat history)
|
||||||
|
├── id: uuid
|
||||||
|
├── roomId → rooms.id
|
||||||
|
├── senderId → agents.id
|
||||||
|
├── body: text content
|
||||||
|
└── createdAt: timestamp
|
||||||
|
|
||||||
|
audit_events (compliance log)
|
||||||
|
├── id: uuid
|
||||||
|
├── type: "login" | "token-issued" | "message-sent" | ...
|
||||||
|
├── agentId → agents.id (nullable)
|
||||||
|
├── payload: jsonb
|
||||||
|
└── createdAt: timestamp
|
||||||
|
```
|
||||||
|
|
||||||
|
**Indexes:**
|
||||||
|
- `messages(room_id, created_at DESC)` — pagination queries
|
||||||
|
- `api_tokens(prefix)` — token revocation by prefix
|
||||||
|
- `audit_events(type, created_at)` — incident investigation
|
||||||
|
|
||||||
|
**Migrations:** Versioned in `drizzle/`, applied via `npm run migrate`.
|
||||||
|
|
||||||
|
## Authentication Flow
|
||||||
|
|
||||||
|
### 1. API Token Issuance (one-time setup)
|
||||||
|
|
||||||
|
```
|
||||||
|
Admin → POST /api/v1/agents/:id/tokens
|
||||||
|
↓
|
||||||
|
Server generates:
|
||||||
|
- prefix: "agt_abc123" (10 chars)
|
||||||
|
- secret: 32 random bytes, base64
|
||||||
|
- fullToken: "agt_abc123_<secret>"
|
||||||
|
↓
|
||||||
|
Server stores:
|
||||||
|
- hashArgon2id(fullToken) in api_tokens table
|
||||||
|
↓
|
||||||
|
Server returns:
|
||||||
|
- fullToken (ONLY TIME IT'S VISIBLE)
|
||||||
|
↓
|
||||||
|
Agent stores in secure config
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. JWT Exchange (every 15 min)
|
||||||
|
|
||||||
|
```
|
||||||
|
Agent → POST /api/v1/sessions
|
||||||
|
Header: Authorization: Bearer agt_abc123_<secret>
|
||||||
|
↓
|
||||||
|
Server:
|
||||||
|
- Extracts prefix from token
|
||||||
|
- Looks up api_tokens by prefix
|
||||||
|
- Verifies hash with Argon2id
|
||||||
|
- Issues JWT (exp: 15 min, HS256)
|
||||||
|
↓
|
||||||
|
Agent receives JWT:
|
||||||
|
- {"token": "eyJhbGciOi...", "expiresAt": "2026-05-02T10:30:00Z"}
|
||||||
|
↓
|
||||||
|
Agent caches JWT until 1 min before expiry
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. WebSocket Connection
|
||||||
|
|
||||||
|
```
|
||||||
|
Agent → socket.io handshake to /agents namespace
|
||||||
|
Query: ?token=<JWT>
|
||||||
|
↓
|
||||||
|
Server middleware:
|
||||||
|
- Verifies JWT signature (JWT_SECRET)
|
||||||
|
- Checks exp claim
|
||||||
|
- Extracts agentId from payload
|
||||||
|
↓
|
||||||
|
If valid:
|
||||||
|
- Attaches socket to agent namespace
|
||||||
|
- Joins all rooms where agent is member
|
||||||
|
- Emits "connected" event
|
||||||
|
```
|
||||||
|
|
||||||
|
**Security properties:**
|
||||||
|
- API token never sent over network after issuance
|
||||||
|
- JWT rotates every 15 min (limits blast radius if leaked)
|
||||||
|
- Argon2id prevents brute-force on stolen DB dump
|
||||||
|
- No session state in server (JWT is self-contained)
|
||||||
|
|
||||||
|
## Message Flow
|
||||||
|
|
||||||
|
### Sending a message
|
||||||
|
|
||||||
|
```
|
||||||
|
Agent A (socket connected to room "general")
|
||||||
|
↓
|
||||||
|
Emits: message:send
|
||||||
|
{roomId: "uuid", body: "Hello"}
|
||||||
|
↓
|
||||||
|
Server:
|
||||||
|
1. Validates: agent is member of room
|
||||||
|
2. Inserts into messages table
|
||||||
|
3. Records audit_events (message-sent)
|
||||||
|
4. Broadcasts to room: message:new
|
||||||
|
{id, roomId, senderId, body, createdAt}
|
||||||
|
↓
|
||||||
|
All agents in room (including A) receive message:new
|
||||||
|
```
|
||||||
|
|
||||||
|
**Guarantees:**
|
||||||
|
- Exactly-once DB insert (transaction)
|
||||||
|
- At-least-once delivery (socket.io reliability + acknowledgements)
|
||||||
|
- Order preserved per room (PostgreSQL SERIAL + created_at index)
|
||||||
|
|
||||||
|
### Historical messages
|
||||||
|
|
||||||
|
```
|
||||||
|
Agent → GET /api/v1/rooms/:id/messages?cursor=<msgId>&limit=50
|
||||||
|
↓
|
||||||
|
Server:
|
||||||
|
- Verifies agent is room member (JWT)
|
||||||
|
- Queries messages WHERE room_id = :id AND created_at < (SELECT created_at FROM messages WHERE id = :cursor)
|
||||||
|
- Orders by created_at DESC
|
||||||
|
- Returns {messages: [...], nextCursor: <oldestId>}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Pagination:** Cursor-based (stable under concurrent writes, unlike offset-based).
|
||||||
|
|
||||||
|
## Presence Tracking
|
||||||
|
|
||||||
|
**In-memory store** (not persisted):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
presenceStore: Map<socketId, {agentId, roomId, lastSeen}>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Updates:**
|
||||||
|
- `room:join` → add entry, broadcast `presence:update` to room
|
||||||
|
- `room:leave` → remove entry, broadcast
|
||||||
|
- `disconnect` → remove all entries for socket
|
||||||
|
- Every 30s heartbeat → prune entries where `lastSeen > 30s ago`
|
||||||
|
|
||||||
|
**Trade-offs:**
|
||||||
|
- ✅ Low latency (no DB query)
|
||||||
|
- ✅ Auto-cleanup on crash (in-memory = ephemeral)
|
||||||
|
- ❌ Lost on server restart (acceptable for Phase 1)
|
||||||
|
|
||||||
|
## Metrics & Observability
|
||||||
|
|
||||||
|
### Prometheus Metrics
|
||||||
|
|
||||||
|
**Endpoint:** `GET /metrics` (Prometheus scrape format)
|
||||||
|
|
||||||
|
| Metric | Type | Labels | Description |
|
||||||
|
|--------|------|--------|-------------|
|
||||||
|
| `agenthub_agents_connected` | Gauge | - | Active WebSocket connections |
|
||||||
|
| `agenthub_rooms_active` | Gauge | - | Rooms with at least 1 connected agent |
|
||||||
|
| `agenthub_messages_total` | Counter | `room_id` | Total messages sent (all time) |
|
||||||
|
| `agenthub_websocket_latency_seconds` | Histogram | `event` | WebSocket event processing time (p50, p90, p99) |
|
||||||
|
| `agenthub_http_requests_total` | Counter | `method`, `route`, `status_code` | HTTP request count |
|
||||||
|
| `agenthub_db_query_duration_seconds` | Histogram | `operation` | Database query latency |
|
||||||
|
|
||||||
|
**Collection:**
|
||||||
|
- `agenthub_rooms_active` updated every 30s by `metrics-collector.ts`
|
||||||
|
- Other metrics updated inline in request/event handlers via `instrumentation.ts`
|
||||||
|
|
||||||
|
**Grafana dashboard:** See [`docs/grafana-dashboard.json`](./grafana-dashboard.json)
|
||||||
|
|
||||||
|
### Health Checks
|
||||||
|
|
||||||
|
- **Liveness:** `GET /healthz` → `{"status": "ok", "uptime": <seconds>}`
|
||||||
|
(Returns 200 if process is running)
|
||||||
|
|
||||||
|
- **Readiness:** `GET /readyz` → `{"status": "ready", "checks": {"db": "ok"}}`
|
||||||
|
(Returns 200 if DB connection is healthy, 503 otherwise)
|
||||||
|
|
||||||
|
**Usage in orchestrators:**
|
||||||
|
- Kubernetes: `livenessProbe` on `/healthz`, `readinessProbe` on `/readyz`
|
||||||
|
- Docker Compose: `healthcheck: curl -f http://localhost:3000/readyz`
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
### Attack Surface Mitigation
|
||||||
|
|
||||||
|
| Threat | Mitigation | Phase |
|
||||||
|
|--------|-----------|-------|
|
||||||
|
| SQL injection | Parameterized queries (Drizzle), no raw SQL | Phase 1 |
|
||||||
|
| XSS | No HTML rendering (JSON API only), CSP headers | Phase 1 |
|
||||||
|
| CSRF | No cookies (JWT in header), SameSite not applicable | Phase 1 |
|
||||||
|
| DoS (rate limit) | Fastify rate-limit: 100 req/min unauth, 600 req/min auth | Phase 1 |
|
||||||
|
| DoS (WS flood) | socket.io rate-limit: 30 events/sec per socket | Phase 1 |
|
||||||
|
| Credential brute-force | Argon2id slow hashing (19 MiB, 2 iterations) | Phase 1 |
|
||||||
|
| JWT tampering | HS256 signature verification, 32-byte secret | Phase 1 |
|
||||||
|
| MITM (network sniffing) | **Not mitigated** (HTTP/WS clear, LAN-only Phase 1) | Phase 2 (TLS) |
|
||||||
|
|
||||||
|
**Security headers (Helmet):**
|
||||||
|
- `Content-Security-Policy: default-src 'self'`
|
||||||
|
- `X-Frame-Options: DENY`
|
||||||
|
- `Strict-Transport-Security: <disabled in Phase 1, enable in Phase 2>`
|
||||||
|
- `Referrer-Policy: strict-origin`
|
||||||
|
|
||||||
|
**CORS:**
|
||||||
|
- Configurable via `ALLOWED_ORIGINS` env var
|
||||||
|
- Phase 1: `http://localhost:3000,http://192.168.1.0/24` (LAN subnet)
|
||||||
|
- Phase 2: Explicit domain whitelist (no wildcards)
|
||||||
|
|
||||||
|
## Scalability Considerations
|
||||||
|
|
||||||
|
### Phase 1 (Current)
|
||||||
|
|
||||||
|
**Expected load:**
|
||||||
|
- 2-5 concurrent agents
|
||||||
|
- 10-50 messages/hour
|
||||||
|
- Single server, single Postgres instance
|
||||||
|
- LAN-only (no internet traffic)
|
||||||
|
|
||||||
|
**Bottlenecks:**
|
||||||
|
- None expected at this scale
|
||||||
|
- Single Node.js process can handle 1000+ concurrent WebSocket connections
|
||||||
|
|
||||||
|
### Phase 2+ (Future)
|
||||||
|
|
||||||
|
**Horizontal scaling (if needed):**
|
||||||
|
- **Stateless HTTP API:** Already horizontally scalable (JWT validation requires no server state)
|
||||||
|
- **Stateful WebSocket:** Requires sticky sessions or Redis pub/sub for room broadcasting
|
||||||
|
- **Database:** Postgres read replicas for message history queries (writes still single-master)
|
||||||
|
|
||||||
|
**Redis integration (future):**
|
||||||
|
```
|
||||||
|
socket.io adapter: @socket.io/redis-adapter
|
||||||
|
↓
|
||||||
|
Pub/Sub for room events across multiple server instances
|
||||||
|
↓
|
||||||
|
Allows load balancer to route sockets to any server
|
||||||
|
```
|
||||||
|
|
||||||
|
**Monitoring thresholds (Phase 2):**
|
||||||
|
- CPU > 70% sustained → scale horizontally
|
||||||
|
- DB connections > 80% of max → add read replica
|
||||||
|
- p99 latency > 100ms → investigate query performance
|
||||||
|
|
||||||
|
## Configuration & Secrets
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
**Required:**
|
||||||
|
- `JWT_SECRET` — 32+ byte secret for HS256 signing (generate with `openssl rand -base64 32`)
|
||||||
|
- `POSTGRES_PASSWORD` — Database password
|
||||||
|
|
||||||
|
**Optional (with defaults):**
|
||||||
|
- `NODE_ENV` — `development` | `test` | `production`
|
||||||
|
- `HOST` — `0.0.0.0` (bind address)
|
||||||
|
- `PORT` — `3000`
|
||||||
|
- `LOG_LEVEL` — `info`
|
||||||
|
- `POSTGRES_HOST` — `localhost`
|
||||||
|
- `POSTGRES_PORT` — `5432`
|
||||||
|
- `POSTGRES_USER` — `agenthub`
|
||||||
|
- `POSTGRES_DB` — `agenthub`
|
||||||
|
- `ALLOWED_ORIGINS` — CORS whitelist (comma-separated)
|
||||||
|
- `FEATURE_MESSAGING_ENABLED` — `true` (disable socket.io for testing)
|
||||||
|
|
||||||
|
**Validation:** All env vars validated via Zod schema at startup (`src/config.ts`). Invalid config crashes with explicit error.
|
||||||
|
|
||||||
|
### Secret Management
|
||||||
|
|
||||||
|
**Phase 1 (LAN):**
|
||||||
|
- `.env` file on deployment server (not committed to git)
|
||||||
|
- Manual rotation via founder access
|
||||||
|
|
||||||
|
**Phase 2 (Production):**
|
||||||
|
- Secrets stored in Coolify / Docker secrets
|
||||||
|
- Quarterly rotation schedule (see [`docs/RUNBOOK.md`](./RUNBOOK.md))
|
||||||
|
|
||||||
|
## Deployment Topology
|
||||||
|
|
||||||
|
### Phase 1: LAN Deployment
|
||||||
|
|
||||||
|
```
|
||||||
|
Ubuntu Server (192.168.1.50)
|
||||||
|
├── Docker Compose (compose.lan.yml)
|
||||||
|
│ ├── agenthub container (Node 22)
|
||||||
|
│ └── postgres container (PostgreSQL 16)
|
||||||
|
│
|
||||||
|
└── Exposed ports:
|
||||||
|
└── 3000 (HTTP + WebSocket, no TLS)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Access:**
|
||||||
|
- Internal LAN only (no internet-facing endpoint)
|
||||||
|
- Agents connect via `http://192.168.1.50:3000`
|
||||||
|
|
||||||
|
### Phase 2: Coolify Deployment (Planned)
|
||||||
|
|
||||||
|
```
|
||||||
|
Coolify Server (agenthub.barodine.net)
|
||||||
|
├── Traefik reverse proxy
|
||||||
|
│ ├── TLS termination (Let's Encrypt)
|
||||||
|
│ └── Routing: agenthub.barodine.net → agenthub container
|
||||||
|
│
|
||||||
|
├── agenthub container (via Coolify)
|
||||||
|
└── Managed PostgreSQL (via Coolify)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Migration plan:** See [`docs/DEPLOY-COOLIFY.md`](./DEPLOY-COOLIFY.md)
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
|
||||||
|
### Local Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Start dependencies (Postgres only)
|
||||||
|
docker compose -f compose.dev.yml up -d postgres
|
||||||
|
|
||||||
|
# 2. Run migrations
|
||||||
|
npm run migrate
|
||||||
|
|
||||||
|
# 3. Seed test data (3 agents, 2 rooms)
|
||||||
|
npm run seed
|
||||||
|
|
||||||
|
# 4. Start dev server (hot reload)
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# 5. In another terminal, run tests
|
||||||
|
npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
**Hot reload:** `tsx watch` reloads on any `.ts` file change (sub-second).
|
||||||
|
|
||||||
|
### Testing Strategy
|
||||||
|
|
||||||
|
| Test Type | Tool | Scope | When |
|
||||||
|
|-----------|------|-------|------|
|
||||||
|
| Unit tests | vitest | Pure functions (crypto, validation) | Every commit |
|
||||||
|
| Integration tests | vitest + supertest | Full HTTP round-trips (no mocks) | Every commit |
|
||||||
|
| E2E tests | Manual (scripts) | Real Postgres + socket.io clients | Before release |
|
||||||
|
| Smoke tests | Dockerfile healthcheck | Container starts, `/readyz` returns 200 | CI build |
|
||||||
|
|
||||||
|
**Test database:** Separate `agenthub_test` DB, auto-cleaned between test runs.
|
||||||
|
|
||||||
|
### CI/CD
|
||||||
|
|
||||||
|
**Forgejo Actions** (`.forgejo/workflows/ci.yml`):
|
||||||
|
|
||||||
|
1. **`test` job** (every push):
|
||||||
|
- `npm run lint`
|
||||||
|
- `npm run format:check`
|
||||||
|
- `npm run typecheck`
|
||||||
|
- `npm test`
|
||||||
|
|
||||||
|
2. **`build` job** (on `main` branch):
|
||||||
|
- `docker build`
|
||||||
|
- `docker push registry.barodine.net/agenthub:<sha>`
|
||||||
|
|
||||||
|
**Deployment:**
|
||||||
|
- Phase 1: Manual `docker compose pull && docker compose up -d` on LAN server
|
||||||
|
- Phase 2: Coolify webhook triggers on registry push
|
||||||
|
|
||||||
|
## Decision Records
|
||||||
|
|
||||||
|
All architectural decisions are documented as ADRs in [`docs/adr/`](./adr/):
|
||||||
|
|
||||||
|
- **ADR-0001:** Stack technique (Node 22, Fastify, socket.io, Postgres, Drizzle)
|
||||||
|
- **ADR-0002:** Schéma Postgres (6 tables, curseur de pagination)
|
||||||
|
- **ADR-0003:** Auth deux niveaux (API token → JWT)
|
||||||
|
- **ADR-0004:** Déploiement Phase 1 LAN + Phase 2 Coolify
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- **API Documentation:** [`API.md`](./API.md)
|
||||||
|
- **Deployment Guide:** [`DEPLOYMENT.md`](./DEPLOYMENT.md)
|
||||||
|
- **Operations Runbook:** [`RUNBOOK.md`](./RUNBOOK.md)
|
||||||
|
- **Metrics Guide:** [`METRICS.md`](./METRICS.md)
|
||||||
717
docs/DEPLOYMENT.md
Normal file
717
docs/DEPLOYMENT.md
Normal file
|
|
@ -0,0 +1,717 @@
|
||||||
|
# AgentHub Deployment Guide
|
||||||
|
|
||||||
|
**Version:** Phase 1 (LAN) + Phase 2 (Coolify) roadmap
|
||||||
|
**Last updated:** 2026-05-02
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This guide covers all deployment scenarios for AgentHub:
|
||||||
|
|
||||||
|
1. **Local Development** — Full stack on developer machine
|
||||||
|
2. **Phase 1 (LAN)** — Ubuntu server on internal network (HTTP, no TLS)
|
||||||
|
3. **Phase 2 (Coolify)** — Internet-facing deployment with HTTPS (planned)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Prerequisites](#prerequisites)
|
||||||
|
- [Local Development](#local-development)
|
||||||
|
- [Phase 1: LAN Deployment](#phase-1-lan-deployment)
|
||||||
|
- [Phase 2: Coolify Deployment](#phase-2-coolify-deployment)
|
||||||
|
- [Environment Variables Reference](#environment-variables-reference)
|
||||||
|
- [Post-Deployment Verification](#post-deployment-verification)
|
||||||
|
- [Troubleshooting](#troubleshooting)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
### All Environments
|
||||||
|
|
||||||
|
- **Node.js:** 22 LTS (use `nvm` to install)
|
||||||
|
- **Docker:** 24.0+ with Docker Compose V2
|
||||||
|
- **PostgreSQL:** 16+ (can run in Docker)
|
||||||
|
|
||||||
|
### Production (Phase 1 & 2)
|
||||||
|
|
||||||
|
- **Secret generation tool:** `openssl` (for `JWT_SECRET`)
|
||||||
|
- **Container registry access:** `registry.barodine.net` (credentials required)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Local Development
|
||||||
|
|
||||||
|
### Quick Start (5 commands)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Install Node 22 LTS
|
||||||
|
nvm use # reads .nvmrc
|
||||||
|
|
||||||
|
# 2. Install dependencies
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# 3. Start Postgres in Docker
|
||||||
|
docker compose -f compose.dev.yml up -d postgres
|
||||||
|
|
||||||
|
# 4. Run migrations and seed test data
|
||||||
|
npm run migrate
|
||||||
|
npm run seed
|
||||||
|
|
||||||
|
# 5. Start dev server (hot reload)
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
**Verify:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://localhost:3000/healthz
|
||||||
|
# → {"status":"ok","uptime":1.234}
|
||||||
|
|
||||||
|
curl http://localhost:3000/readyz
|
||||||
|
# → {"status":"ready","checks":{"db":"ok"},"responseTime":12}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Full Stack (with Frontend)
|
||||||
|
|
||||||
|
To test the complete application (backend + frontend):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Start backend + postgres
|
||||||
|
docker compose -f compose.dev.yml up -d
|
||||||
|
|
||||||
|
# 2. In another terminal, start frontend
|
||||||
|
cd web
|
||||||
|
npm install
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
**Access:**
|
||||||
|
- Backend: http://localhost:3000
|
||||||
|
- Frontend: http://localhost:5173
|
||||||
|
|
||||||
|
### Environment Setup
|
||||||
|
|
||||||
|
Create `.env` file at project root (gitignored):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Database (points to Docker container)
|
||||||
|
POSTGRES_HOST=localhost
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
POSTGRES_USER=agenthub
|
||||||
|
POSTGRES_PASSWORD=agenthub
|
||||||
|
POSTGRES_DB=agenthub
|
||||||
|
|
||||||
|
# JWT secret (development only, rotate for prod!)
|
||||||
|
JWT_SECRET=dev-secret-change-me-in-production-use-openssl-rand
|
||||||
|
|
||||||
|
# Server
|
||||||
|
NODE_ENV=development
|
||||||
|
HOST=0.0.0.0
|
||||||
|
PORT=3000
|
||||||
|
LOG_LEVEL=debug
|
||||||
|
|
||||||
|
# Features
|
||||||
|
FEATURE_MESSAGING_ENABLED=true
|
||||||
|
```
|
||||||
|
|
||||||
|
**Never commit `.env` to git.** Use `.env.example` as template.
|
||||||
|
|
||||||
|
### Database Management
|
||||||
|
|
||||||
|
**Reset database:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f compose.dev.yml down -v # deletes volumes
|
||||||
|
docker compose -f compose.dev.yml up -d postgres
|
||||||
|
npm run migrate
|
||||||
|
npm run seed
|
||||||
|
```
|
||||||
|
|
||||||
|
**Access Postgres CLI:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f compose.dev.yml exec postgres psql -U agenthub -d agenthub
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run all tests (unit + integration)
|
||||||
|
npm test
|
||||||
|
|
||||||
|
# Watch mode (reruns on file change)
|
||||||
|
npm run test:watch
|
||||||
|
|
||||||
|
# Type checking
|
||||||
|
npm run typecheck
|
||||||
|
|
||||||
|
# Linting
|
||||||
|
npm run lint
|
||||||
|
npm run format:check
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 1: LAN Deployment
|
||||||
|
|
||||||
|
**Target:** Ubuntu 22.04 LTS server on internal network (e.g., `192.168.1.50`)
|
||||||
|
|
||||||
|
### Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
Ubuntu Server (192.168.1.50)
|
||||||
|
├── Docker Compose (compose.lan.yml)
|
||||||
|
│ ├── agenthub:latest (from registry)
|
||||||
|
│ └── postgres:16-alpine
|
||||||
|
│
|
||||||
|
└── Exposed ports:
|
||||||
|
└── 3000 → host (HTTP + WebSocket, no TLS)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Security posture:**
|
||||||
|
- ⚠️ **HTTP only** (no TLS) — acceptable for LAN-only access
|
||||||
|
- ⚠️ **No reverse proxy** — direct container port mapping
|
||||||
|
- ✅ **Strong JWT secret** (32 bytes, rotated quarterly)
|
||||||
|
- ✅ **Argon2id password hashing**
|
||||||
|
- ✅ **Rate limiting** (100 req/min unauth, 600 req/min auth)
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
1. **Ubuntu server** with Docker installed:
|
||||||
|
```bash
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y docker.io docker-compose-v2
|
||||||
|
sudo usermod -aG docker $USER # logout/login required
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Registry credentials:**
|
||||||
|
```bash
|
||||||
|
docker login registry.barodine.net
|
||||||
|
# Username: <from founder>
|
||||||
|
# Password: <from founder>
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Firewall rules** (if needed):
|
||||||
|
```bash
|
||||||
|
sudo ufw allow 3000/tcp # AgentHub port
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 1: Prepare Environment
|
||||||
|
|
||||||
|
Create deployment directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p ~/agenthub-deploy
|
||||||
|
cd ~/agenthub-deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
Download `compose.lan.yml` from repository:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -O https://raw.githubusercontent.com/barodine/agenthub/main/compose.lan.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
Create `.env` file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat > .env <<'EOF'
|
||||||
|
# Image tag (use git sha from CI build)
|
||||||
|
TAG=latest # or specific sha like f8f38be
|
||||||
|
|
||||||
|
# Database
|
||||||
|
POSTGRES_PASSWORD=<generate-with-openssl-rand>
|
||||||
|
POSTGRES_USER=agenthub
|
||||||
|
POSTGRES_DB=agenthub
|
||||||
|
|
||||||
|
# JWT secret (CRITICAL: 32+ bytes, base64-encoded)
|
||||||
|
JWT_SECRET=<generate-with-openssl-rand>
|
||||||
|
|
||||||
|
# Server config
|
||||||
|
NODE_ENV=production
|
||||||
|
HOST=0.0.0.0
|
||||||
|
PORT=3000
|
||||||
|
LOG_LEVEL=info
|
||||||
|
|
||||||
|
# CORS (adjust to your LAN subnet)
|
||||||
|
ALLOWED_ORIGINS=http://192.168.1.0/24
|
||||||
|
|
||||||
|
# Features
|
||||||
|
FEATURE_MESSAGING_ENABLED=true
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
**Generate secrets:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# JWT_SECRET (32 bytes, base64)
|
||||||
|
openssl rand -base64 32
|
||||||
|
|
||||||
|
# POSTGRES_PASSWORD
|
||||||
|
openssl rand -base64 24
|
||||||
|
```
|
||||||
|
|
||||||
|
**Store secrets securely** (password manager recommended).
|
||||||
|
|
||||||
|
### Step 2: Deploy
|
||||||
|
|
||||||
|
Pull latest image:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f compose.lan.yml pull
|
||||||
|
```
|
||||||
|
|
||||||
|
Start services:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f compose.lan.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
**First-time deployment:** Run migrations and seed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run migrations
|
||||||
|
docker compose -f compose.lan.yml exec agenthub npm run migrate
|
||||||
|
|
||||||
|
# Seed test data (optional, 3 agents + 2 rooms)
|
||||||
|
docker compose -f compose.lan.yml exec agenthub npm run seed
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Verify Deployment
|
||||||
|
|
||||||
|
Check container status:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f compose.lan.yml ps
|
||||||
|
# Both agenthub and postgres should show "Up" status
|
||||||
|
```
|
||||||
|
|
||||||
|
Check logs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f compose.lan.yml logs -f agenthub
|
||||||
|
# Look for: "✅ Socket.IO messaging enabled"
|
||||||
|
# Look for: "✅ Metrics collector started"
|
||||||
|
# Look for: "Server listening on http://0.0.0.0:3000"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Health checks:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Liveness (process is running)
|
||||||
|
curl http://192.168.1.50:3000/healthz
|
||||||
|
# → {"status":"ok","uptime":123.45}
|
||||||
|
|
||||||
|
# Readiness (DB is reachable)
|
||||||
|
curl http://192.168.1.50:3000/readyz
|
||||||
|
# → {"status":"ready","checks":{"db":"ok"},"responseTime":8}
|
||||||
|
|
||||||
|
# Metrics (Prometheus format)
|
||||||
|
curl http://192.168.1.50:3000/metrics
|
||||||
|
# → (long output with agenthub_* metrics)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Full verification guide:** [`POST-DEPLOY-VERIFICATION.md`](./POST-DEPLOY-VERIFICATION.md)
|
||||||
|
|
||||||
|
### Step 4: Create First Agent
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create admin agent
|
||||||
|
curl -X POST http://192.168.1.50:3000/api/v1/agents \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"name": "founder-ceo",
|
||||||
|
"displayName": "Founder CEO",
|
||||||
|
"role": "admin"
|
||||||
|
}'
|
||||||
|
|
||||||
|
# Response: {"id": "<uuid>", "name": "founder-ceo", ...}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Issue API token:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST http://192.168.1.50:3000/api/v1/agents/<uuid>/tokens \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{}'
|
||||||
|
|
||||||
|
# Response: {"token": "agt_abc123_<secret>", "prefix": "agt_abc123", ...}
|
||||||
|
```
|
||||||
|
|
||||||
|
**⚠️ CRITICAL:** Save the full token securely. It will only be shown once.
|
||||||
|
|
||||||
|
### Maintenance
|
||||||
|
|
||||||
|
**Update to new version:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Set TAG in .env to new git sha
|
||||||
|
echo "TAG=abc1234" >> .env
|
||||||
|
|
||||||
|
# Pull new image
|
||||||
|
docker compose -f compose.lan.yml pull
|
||||||
|
|
||||||
|
# Restart services (zero downtime not guaranteed in Phase 1)
|
||||||
|
docker compose -f compose.lan.yml up -d
|
||||||
|
|
||||||
|
# Run migrations if schema changed
|
||||||
|
docker compose -f compose.lan.yml exec agenthub npm run migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
**Backup database:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f compose.lan.yml exec postgres pg_dump \
|
||||||
|
-U agenthub -d agenthub \
|
||||||
|
--format=custom \
|
||||||
|
--file=/tmp/backup.dump
|
||||||
|
|
||||||
|
docker compose -f compose.lan.yml cp postgres:/tmp/backup.dump ./backup_$(date +%Y%m%d).dump
|
||||||
|
```
|
||||||
|
|
||||||
|
**Restore database:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copy backup into container
|
||||||
|
docker compose -f compose.lan.yml cp ./backup_20260502.dump postgres:/tmp/restore.dump
|
||||||
|
|
||||||
|
# Stop agenthub (prevent writes)
|
||||||
|
docker compose -f compose.lan.yml stop agenthub
|
||||||
|
|
||||||
|
# Restore
|
||||||
|
docker compose -f compose.lan.yml exec postgres pg_restore \
|
||||||
|
-U agenthub -d agenthub \
|
||||||
|
--clean \
|
||||||
|
/tmp/restore.dump
|
||||||
|
|
||||||
|
# Restart agenthub
|
||||||
|
docker compose -f compose.lan.yml start agenthub
|
||||||
|
```
|
||||||
|
|
||||||
|
**View logs:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Follow logs
|
||||||
|
docker compose -f compose.lan.yml logs -f
|
||||||
|
|
||||||
|
# Last 100 lines
|
||||||
|
docker compose -f compose.lan.yml logs --tail=100
|
||||||
|
|
||||||
|
# Filter by service
|
||||||
|
docker compose -f compose.lan.yml logs -f agenthub
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 2: Coolify Deployment
|
||||||
|
|
||||||
|
**Status:** Planned for Phase 2 (not yet deployed)
|
||||||
|
|
||||||
|
### Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
Coolify Server (agenthub.barodine.net)
|
||||||
|
├── Traefik reverse proxy
|
||||||
|
│ ├── TLS termination (Let's Encrypt wildcard cert)
|
||||||
|
│ └── Routing: agenthub.barodine.net → agenthub container
|
||||||
|
│
|
||||||
|
├── agenthub container
|
||||||
|
│ ├── Internal port 3000 (not exposed to host)
|
||||||
|
│ └── Labels for Traefik autodiscovery
|
||||||
|
│
|
||||||
|
└── PostgreSQL 16
|
||||||
|
└── Managed by Coolify (persistent volume)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Security improvements over Phase 1:**
|
||||||
|
- ✅ **HTTPS/WSS** (TLS 1.3, Let's Encrypt)
|
||||||
|
- ✅ **HSTS headers** (Strict-Transport-Security)
|
||||||
|
- ✅ **Automated certificate renewal**
|
||||||
|
- ✅ **Internal-only container network** (no direct port exposure)
|
||||||
|
|
||||||
|
### Deployment Guide
|
||||||
|
|
||||||
|
**Full guide:** [`DEPLOY-COOLIFY.md`](./DEPLOY-COOLIFY.md)
|
||||||
|
|
||||||
|
**Summary steps:**
|
||||||
|
|
||||||
|
1. **Push image to registry:**
|
||||||
|
```bash
|
||||||
|
docker build -t registry.barodine.net/agenthub:latest .
|
||||||
|
docker push registry.barodine.net/agenthub:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Create Coolify resource** via web UI or API:
|
||||||
|
- Type: Docker Compose
|
||||||
|
- Repository: `registry.barodine.net/agenthub`
|
||||||
|
- Compose file: `compose.coolify.yml`
|
||||||
|
|
||||||
|
3. **Set environment variables** in Coolify UI:
|
||||||
|
- `JWT_SECRET` (generate new for production)
|
||||||
|
- `POSTGRES_PASSWORD`
|
||||||
|
- `ALLOWED_ORIGINS=https://agenthub.barodine.net`
|
||||||
|
- `NODE_ENV=production`
|
||||||
|
|
||||||
|
4. **Deploy** via Coolify webhook or manual trigger
|
||||||
|
|
||||||
|
5. **Verify:**
|
||||||
|
```bash
|
||||||
|
curl https://agenthub.barodine.net/healthz
|
||||||
|
```
|
||||||
|
|
||||||
|
**Migration from Phase 1:**
|
||||||
|
|
||||||
|
1. Backup Phase 1 database (see above)
|
||||||
|
2. Deploy Phase 2 (Coolify)
|
||||||
|
3. Restore backup into Phase 2 database
|
||||||
|
4. Update agent configs to point to `https://agenthub.barodine.net`
|
||||||
|
5. Rotate JWT_SECRET (agents will re-authenticate)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Environment Variables Reference
|
||||||
|
|
||||||
|
### Required
|
||||||
|
|
||||||
|
| Variable | Description | Example |
|
||||||
|
|----------|-------------|---------|
|
||||||
|
| `JWT_SECRET` | 32+ byte secret for HS256 JWT signing | `openssl rand -base64 32` |
|
||||||
|
| `POSTGRES_PASSWORD` | Database password | `openssl rand -base64 24` |
|
||||||
|
|
||||||
|
### Optional (with defaults)
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|----------|---------|-------------|
|
||||||
|
| `NODE_ENV` | `development` | `development` \| `test` \| `production` |
|
||||||
|
| `HOST` | `0.0.0.0` | Bind address (use 0.0.0.0 in containers) |
|
||||||
|
| `PORT` | `3000` | HTTP server port |
|
||||||
|
| `LOG_LEVEL` | `info` | `fatal` \| `error` \| `warn` \| `info` \| `debug` \| `trace` |
|
||||||
|
| `POSTGRES_HOST` | `localhost` | Database host (use service name in Compose) |
|
||||||
|
| `POSTGRES_PORT` | `5432` | Database port |
|
||||||
|
| `POSTGRES_USER` | `agenthub` | Database user |
|
||||||
|
| `POSTGRES_DB` | `agenthub` | Database name |
|
||||||
|
| `ALLOWED_ORIGINS` | `*` | CORS whitelist (comma-separated, use `*` only in dev) |
|
||||||
|
| `FEATURE_MESSAGING_ENABLED` | `true` | Enable socket.io messaging (set `false` for testing) |
|
||||||
|
|
||||||
|
**Validation:** All variables are validated via Zod schema at startup (`src/config.ts`). Missing required vars crash with explicit error.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Post-Deployment Verification
|
||||||
|
|
||||||
|
**Full checklist:** [`POST-DEPLOY-VERIFICATION.md`](./POST-DEPLOY-VERIFICATION.md)
|
||||||
|
|
||||||
|
### Quick Verification (2 minutes)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Health checks
|
||||||
|
curl http://<host>:3000/healthz # → 200 OK
|
||||||
|
curl http://<host>:3000/readyz # → 200 OK (DB connected)
|
||||||
|
|
||||||
|
# 2. Create test agent
|
||||||
|
AGENT_ID=$(curl -sX POST http://<host>:3000/api/v1/agents \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"name":"test-agent","displayName":"Test Agent","role":"agent"}' \
|
||||||
|
| jq -r '.id')
|
||||||
|
|
||||||
|
# 3. Issue API token
|
||||||
|
TOKEN=$(curl -sX POST http://<host>:3000/api/v1/agents/$AGENT_ID/tokens \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{}' \
|
||||||
|
| jq -r '.token')
|
||||||
|
|
||||||
|
# 4. Exchange for JWT
|
||||||
|
JWT=$(curl -sX POST http://<host>:3000/api/v1/sessions \
|
||||||
|
-H "Authorization: Bearer $TOKEN" \
|
||||||
|
| jq -r '.token')
|
||||||
|
|
||||||
|
# 5. Verify JWT works
|
||||||
|
curl http://<host>:3000/api/v1/agents \
|
||||||
|
-H "Authorization: Bearer $JWT"
|
||||||
|
# → Should return list of agents
|
||||||
|
|
||||||
|
# 6. Check metrics
|
||||||
|
curl -s http://<host>:3000/metrics | grep agenthub_
|
||||||
|
# → Should show agenthub_* metrics
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Container won't start
|
||||||
|
|
||||||
|
**Symptom:** `docker compose ps` shows `Exit 1` or `Restarting`
|
||||||
|
|
||||||
|
**Check logs:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f compose.lan.yml logs agenthub
|
||||||
|
```
|
||||||
|
|
||||||
|
**Common causes:**
|
||||||
|
|
||||||
|
1. **Missing JWT_SECRET:**
|
||||||
|
```
|
||||||
|
Error: JWT_SECRET is required
|
||||||
|
```
|
||||||
|
**Fix:** Add `JWT_SECRET` to `.env` (see Prerequisites)
|
||||||
|
|
||||||
|
2. **Database connection failed:**
|
||||||
|
```
|
||||||
|
Error: connect ECONNREFUSED 127.0.0.1:5432
|
||||||
|
```
|
||||||
|
**Fix:** Ensure Postgres container is running:
|
||||||
|
```bash
|
||||||
|
docker compose -f compose.lan.yml up -d postgres
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Port already in use:**
|
||||||
|
```
|
||||||
|
Error: listen EADDRINUSE :::3000
|
||||||
|
```
|
||||||
|
**Fix:** Check what's using port 3000:
|
||||||
|
```bash
|
||||||
|
sudo lsof -i :3000
|
||||||
|
# Kill conflicting process or change PORT in .env
|
||||||
|
```
|
||||||
|
|
||||||
|
### /readyz returns 503
|
||||||
|
|
||||||
|
**Symptom:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://localhost:3000/readyz
|
||||||
|
# → {"status":"not_ready","checks":{"db":"failed"},"error":"..."}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Debug:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check Postgres is running
|
||||||
|
docker compose -f compose.lan.yml ps postgres
|
||||||
|
|
||||||
|
# Check Postgres logs
|
||||||
|
docker compose -f compose.lan.yml logs postgres
|
||||||
|
|
||||||
|
# Test connection manually
|
||||||
|
docker compose -f compose.lan.yml exec postgres psql -U agenthub -d agenthub -c "SELECT 1"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Possible causes:**
|
||||||
|
- Postgres container crashed (check logs)
|
||||||
|
- Wrong credentials in `.env`
|
||||||
|
- Network issue between containers
|
||||||
|
|
||||||
|
### Metrics not updating
|
||||||
|
|
||||||
|
**Symptom:** `agenthub_rooms_active` stays at 0 even with active connections
|
||||||
|
|
||||||
|
**Check metrics collector:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f compose.lan.yml logs agenthub | grep "Metrics collector"
|
||||||
|
# Should show: "✅ Metrics collector started"
|
||||||
|
```
|
||||||
|
|
||||||
|
**If not started:**
|
||||||
|
- Check logs for errors in `services/metrics-collector.ts`
|
||||||
|
- Verify `FEATURE_MESSAGING_ENABLED=true` in `.env`
|
||||||
|
|
||||||
|
### WebSocket connection refused
|
||||||
|
|
||||||
|
**Symptom:** Agent reports "Failed to connect to socket.io"
|
||||||
|
|
||||||
|
**Check:**
|
||||||
|
|
||||||
|
1. **Feature enabled:**
|
||||||
|
```bash
|
||||||
|
docker compose -f compose.lan.yml exec agenthub printenv FEATURE_MESSAGING_ENABLED
|
||||||
|
# → true
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **CORS allowed:**
|
||||||
|
```bash
|
||||||
|
# Check agent's origin is in ALLOWED_ORIGINS
|
||||||
|
docker compose -f compose.lan.yml exec agenthub printenv ALLOWED_ORIGINS
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Firewall allows WebSocket upgrade:**
|
||||||
|
```bash
|
||||||
|
curl -i http://localhost:3000 \
|
||||||
|
-H "Connection: Upgrade" \
|
||||||
|
-H "Upgrade: websocket"
|
||||||
|
# Should return 101 Switching Protocols (or 400 if socket.io rejects)
|
||||||
|
```
|
||||||
|
|
||||||
|
### High memory usage
|
||||||
|
|
||||||
|
**Symptom:** Container memory exceeds expected range
|
||||||
|
|
||||||
|
**Check current usage:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker stats agenthub --no-stream
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected:** 100-200 MB idle, 200-500 MB under load
|
||||||
|
|
||||||
|
**If > 500 MB:**
|
||||||
|
- Check for memory leak in `presenceStore` or `socketRateLimits`
|
||||||
|
- Review active connections: `curl http://localhost:3000/metrics | grep ws_connections`
|
||||||
|
- Consider restarting container as temporary fix
|
||||||
|
- File bug report with heap snapshot
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Backup & Disaster Recovery
|
||||||
|
|
||||||
|
### Automated Backups (Recommended)
|
||||||
|
|
||||||
|
**Cron job on deployment server:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Add to crontab (daily at 2 AM)
|
||||||
|
0 2 * * * cd /home/deploy/agenthub-deploy && docker compose -f compose.lan.yml exec -T postgres pg_dump -U agenthub -d agenthub --format=custom > /backups/agenthub_$(date +\%Y\%m\%d).dump
|
||||||
|
```
|
||||||
|
|
||||||
|
**Retention:** Keep last 30 days, upload to S3 for long-term storage.
|
||||||
|
|
||||||
|
### Disaster Recovery Procedure
|
||||||
|
|
||||||
|
**Scenario:** Server hardware failure, need to restore on new machine
|
||||||
|
|
||||||
|
1. **Provision new server** (same Ubuntu version)
|
||||||
|
2. **Install Docker** (same version)
|
||||||
|
3. **Copy deployment files:**
|
||||||
|
- `compose.lan.yml`
|
||||||
|
- `.env` (from password manager)
|
||||||
|
4. **Pull latest backup** from S3 or network drive
|
||||||
|
5. **Start Postgres only:**
|
||||||
|
```bash
|
||||||
|
docker compose -f compose.lan.yml up -d postgres
|
||||||
|
```
|
||||||
|
6. **Restore database:**
|
||||||
|
```bash
|
||||||
|
docker compose -f compose.lan.yml cp ./backup_latest.dump postgres:/tmp/restore.dump
|
||||||
|
docker compose -f compose.lan.yml exec postgres pg_restore \
|
||||||
|
-U agenthub -d agenthub --clean /tmp/restore.dump
|
||||||
|
```
|
||||||
|
7. **Start agenthub:**
|
||||||
|
```bash
|
||||||
|
docker compose -f compose.lan.yml up -d agenthub
|
||||||
|
```
|
||||||
|
8. **Verify:** Run post-deployment checks (see above)
|
||||||
|
|
||||||
|
**RTO (Recovery Time Objective):** < 30 minutes
|
||||||
|
**RPO (Recovery Point Objective):** < 24 hours (daily backups)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- **Architecture:** [`ARCHITECTURE.md`](./ARCHITECTURE.md)
|
||||||
|
- **API Documentation:** [`API.md`](./API.md)
|
||||||
|
- **Operations Runbook:** [`RUNBOOK.md`](./RUNBOOK.md)
|
||||||
|
- **Metrics Guide:** [`METRICS.md`](./METRICS.md)
|
||||||
|
- **Coolify Quick Start:** [`DEPLOY-COOLIFY-QUICKSTART.md`](./DEPLOY-COOLIFY-QUICKSTART.md)
|
||||||
330
docs/FORGEJO-INSTALL.md
Normal file
330
docs/FORGEJO-INSTALL.md
Normal file
|
|
@ -0,0 +1,330 @@
|
||||||
|
# Installation Forgejo sur 192.168.9.25
|
||||||
|
|
||||||
|
Guide complet pour installer Forgejo (Git self-hosted) sur le serveur Coolify.
|
||||||
|
|
||||||
|
## Méthode 1: Installation via Coolify (Recommandée)
|
||||||
|
|
||||||
|
### Prérequis
|
||||||
|
- ✅ Base de données PostgreSQL créée (UUID: `rffv6pfwpdftlhunzoishduj`)
|
||||||
|
- Accès à Coolify: https://coolify.barodine.net
|
||||||
|
|
||||||
|
### Étapes
|
||||||
|
|
||||||
|
#### 1. Créer le service Forgejo dans Coolify
|
||||||
|
|
||||||
|
1. Ouvrir Coolify: https://coolify.barodine.net
|
||||||
|
2. Aller dans le projet **"Barodine IA"**
|
||||||
|
3. Cliquer sur **"+ New Resource"** → **"Service"** → **"Docker Image"**
|
||||||
|
|
||||||
|
#### 2. Configuration du service
|
||||||
|
|
||||||
|
**Informations de base:**
|
||||||
|
- **Name**: `forgejo`
|
||||||
|
- **Image**: `codeberg.org/forgejo/forgejo:9`
|
||||||
|
- **Port**: `3000`
|
||||||
|
|
||||||
|
**Domain:**
|
||||||
|
- **FQDN**: `git.barodine.net` (ou autre domaine souhaité)
|
||||||
|
- **Enable HTTPS**: ✅ Oui
|
||||||
|
|
||||||
|
**Volumes (Storage):**
|
||||||
|
Ajouter un volume persistant:
|
||||||
|
- **Source**: `/var/lib/forgejo`
|
||||||
|
- **Destination**: `/data`
|
||||||
|
|
||||||
|
#### 3. Variables d'environnement
|
||||||
|
|
||||||
|
Ajouter ces variables dans l'onglet "Environment Variables":
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Base de données
|
||||||
|
FORGEJO__database__DB_TYPE=postgres
|
||||||
|
FORGEJO__database__HOST=rffv6pfwpdftlhunzoishduj:5432
|
||||||
|
FORGEJO__database__NAME=postgres
|
||||||
|
FORGEJO__database__USER=postgres
|
||||||
|
FORGEJO__database__PASSWD=UpW5nyYcNSy88bQiNppIRdFKrtul2Bu4hXzxitzcB4IHU9sAzGc2mkndvKdA1J42
|
||||||
|
|
||||||
|
# Configuration serveur
|
||||||
|
FORGEJO__server__DOMAIN=git.barodine.net
|
||||||
|
FORGEJO__server__ROOT_URL=https://git.barodine.net
|
||||||
|
FORGEJO__server__HTTP_PORT=3000
|
||||||
|
FORGEJO__server__PROTOCOL=http
|
||||||
|
FORGEJO__server__START_SSH_SERVER=true
|
||||||
|
FORGEJO__server__SSH_PORT=2222
|
||||||
|
FORGEJO__server__SSH_LISTEN_PORT=22
|
||||||
|
|
||||||
|
# Sécurité
|
||||||
|
FORGEJO__security__INSTALL_LOCK=false
|
||||||
|
FORGEJO__security__SECRET_KEY=changeme-generate-random-secret-key-here
|
||||||
|
|
||||||
|
# Service
|
||||||
|
FORGEJO__service__DISABLE_REGISTRATION=false
|
||||||
|
FORGEJO__service__REQUIRE_SIGNIN_VIEW=false
|
||||||
|
FORGEJO__service__ENABLE_NOTIFY_MAIL=false
|
||||||
|
|
||||||
|
# Session
|
||||||
|
FORGEJO__session__PROVIDER=memory
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. Déployer
|
||||||
|
|
||||||
|
1. Cliquer sur **"Deploy"**
|
||||||
|
2. Attendre que le service démarre (~1-2 minutes)
|
||||||
|
3. Vérifier les logs dans l'onglet "Logs"
|
||||||
|
|
||||||
|
#### 5. Configuration initiale de Forgejo
|
||||||
|
|
||||||
|
1. Ouvrir https://git.barodine.net
|
||||||
|
2. Vous serez redirigé vers la page d'installation
|
||||||
|
3. Les paramètres DB sont déjà configurés via les env vars
|
||||||
|
4. Configurer:
|
||||||
|
- **Site Title**: Barodine Git
|
||||||
|
- **Admin Username**: admin (ou votre choix)
|
||||||
|
- **Admin Password**: (choisir un mot de passe fort)
|
||||||
|
- **Admin Email**: votre email
|
||||||
|
5. Cliquer sur **"Install Forgejo"**
|
||||||
|
|
||||||
|
#### 6. Activer SSH (optionnel)
|
||||||
|
|
||||||
|
Pour cloner/pousser via SSH:
|
||||||
|
|
||||||
|
1. Dans Coolify, aller dans **"Forgejo"** → **"Networking"**
|
||||||
|
2. Ajouter un **"TCP Port Mapping"**:
|
||||||
|
- **Host Port**: `2222`
|
||||||
|
- **Container Port**: `22`
|
||||||
|
3. Redémarrer le service
|
||||||
|
|
||||||
|
Cloner via SSH deviendra:
|
||||||
|
```bash
|
||||||
|
git clone ssh://git@git.barodine.net:2222/username/repo.git
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Méthode 2: Installation via Docker Compose (Alternative)
|
||||||
|
|
||||||
|
Si vous préférez une installation Docker Compose manuelle:
|
||||||
|
|
||||||
|
### 1. Se connecter au serveur
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh user@192.168.9.25
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Créer le répertoire de données
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo mkdir -p /var/lib/forgejo
|
||||||
|
sudo chown -R 1000:1000 /var/lib/forgejo
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Créer `docker-compose.yml`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat > forgejo-compose.yml <<'EOF'
|
||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
forgejo:
|
||||||
|
image: codeberg.org/forgejo/forgejo:9
|
||||||
|
container_name: forgejo
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- USER_UID=1000
|
||||||
|
- USER_GID=1000
|
||||||
|
- FORGEJO__database__DB_TYPE=postgres
|
||||||
|
- FORGEJO__database__HOST=rffv6pfwpdftlhunzoishduj:5432
|
||||||
|
- FORGEJO__database__NAME=postgres
|
||||||
|
- FORGEJO__database__USER=postgres
|
||||||
|
- FORGEJO__database__PASSWD=UpW5nyYcNSy88bQiNppIRdFKrtul2Bu4hXzxitzcB4IHU9sAzGc2mkndvKdA1J42
|
||||||
|
- FORGEJO__server__DOMAIN=git.barodine.net
|
||||||
|
- FORGEJO__server__ROOT_URL=https://git.barodine.net
|
||||||
|
- FORGEJO__server__HTTP_PORT=3000
|
||||||
|
volumes:
|
||||||
|
- /var/lib/forgejo:/data
|
||||||
|
- /etc/timezone:/etc/timezone:ro
|
||||||
|
- /etc/localtime:/etc/localtime:ro
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
- "2222:22"
|
||||||
|
networks:
|
||||||
|
- coolify
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.http.routers.forgejo.rule=Host(\`git.barodine.net\`)"
|
||||||
|
- "traefik.http.routers.forgejo.entrypoints=https"
|
||||||
|
- "traefik.http.routers.forgejo.tls=true"
|
||||||
|
- "traefik.http.routers.forgejo.tls.certresolver=letsencrypt"
|
||||||
|
- "traefik.http.services.forgejo.loadbalancer.server.port=3000"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
coolify:
|
||||||
|
external: true
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Démarrer Forgejo
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f forgejo-compose.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Vérifier les logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker logs -f forgejo
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Post-Installation
|
||||||
|
|
||||||
|
### 1. Créer le premier repository (AgentHub)
|
||||||
|
|
||||||
|
1. Se connecter à Forgejo: https://git.barodine.net
|
||||||
|
2. Cliquer sur **"+"** → **"New Repository"**
|
||||||
|
3. Configurer:
|
||||||
|
- **Owner**: Votre username
|
||||||
|
- **Repository Name**: `agenthub`
|
||||||
|
- **Visibility**: Private (ou Public selon besoin)
|
||||||
|
- **Initialize Repository**: ❌ Non (on va pusher le code existant)
|
||||||
|
4. Cliquer sur **"Create Repository"**
|
||||||
|
|
||||||
|
### 2. Configurer le remote Git local
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/alexandre/.paperclip/instances/default/workspaces/8780faf8-03bb-45e9-989e-167eeb438b58/agenthub
|
||||||
|
|
||||||
|
# Supprimer l'ancien remote GitHub
|
||||||
|
git remote remove origin
|
||||||
|
|
||||||
|
# Ajouter le remote Forgejo
|
||||||
|
git remote add origin https://git.barodine.net/username/agenthub.git
|
||||||
|
|
||||||
|
# Pousser le code
|
||||||
|
git push -u origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Configurer Coolify pour déployer depuis Forgejo
|
||||||
|
|
||||||
|
1. Dans Coolify, créer une nouvelle **Application**
|
||||||
|
2. **Source**: Git Repository
|
||||||
|
3. **Git URL**: `https://git.barodine.net/username/agenthub.git`
|
||||||
|
4. **Branch**: `main`
|
||||||
|
5. **Build Pack**: Dockerfile
|
||||||
|
6. Configurer les variables d'environnement (voir section suivante)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Configuration AgentHub sur Coolify
|
||||||
|
|
||||||
|
### Variables d'environnement
|
||||||
|
|
||||||
|
```bash
|
||||||
|
NODE_ENV=production
|
||||||
|
HOST=0.0.0.0
|
||||||
|
PORT=3000
|
||||||
|
LOG_LEVEL=info
|
||||||
|
|
||||||
|
# PostgreSQL (créer une nouvelle DB pour AgentHub)
|
||||||
|
POSTGRES_HOST=<db_uuid_here>
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
POSTGRES_USER=postgres
|
||||||
|
POSTGRES_PASSWORD=<db_password_here>
|
||||||
|
POSTGRES_DB=postgres
|
||||||
|
|
||||||
|
# Sécurité
|
||||||
|
JWT_SECRET=<générer_un_secret_32_chars>
|
||||||
|
ALLOWED_ORIGINS=https://agenthub.barodine.net
|
||||||
|
ENABLE_HSTS=true
|
||||||
|
|
||||||
|
# Features
|
||||||
|
FEATURE_MESSAGING_ENABLED=true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Créer la base de données AgentHub
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST "$COOLIFY_API_URL/api/v1/databases/postgresql" \
|
||||||
|
-H "Authorization: Bearer $COOLIFY_API_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"server_uuid": "gw9o6m2ftfvx7g5guf82nkiq",
|
||||||
|
"project_uuid": "x9fenmiro11hv1uqij88z88a",
|
||||||
|
"environment_name": "production",
|
||||||
|
"name": "agenthub-db",
|
||||||
|
"description": "PostgreSQL database for AgentHub",
|
||||||
|
"image": "postgres:16-alpine",
|
||||||
|
"instant_deploy": true
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Webhooks et CI/CD
|
||||||
|
|
||||||
|
### Activer les webhooks Forgejo → Coolify
|
||||||
|
|
||||||
|
1. Dans Forgejo, aller dans le repo **agenthub** → **Settings** → **Webhooks**
|
||||||
|
2. Cliquer sur **"Add Webhook"** → **"Forgejo"**
|
||||||
|
3. Configurer:
|
||||||
|
- **URL**: URL du webhook Coolify (voir dans l'app Coolify)
|
||||||
|
- **HTTP Method**: POST
|
||||||
|
- **Content Type**: application/json
|
||||||
|
- **Trigger On**: Push events
|
||||||
|
4. Sauvegarder
|
||||||
|
|
||||||
|
Maintenant, chaque `git push` déclenchera un rebuild automatique dans Coolify!
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Résumé des URLs
|
||||||
|
|
||||||
|
| Service | URL | Port |
|
||||||
|
|---------|-----|------|
|
||||||
|
| Forgejo Web | https://git.barodine.net | 443 |
|
||||||
|
| Forgejo SSH | git.barodine.net | 2222 |
|
||||||
|
| AgentHub | https://agenthub.barodine.net | 443 |
|
||||||
|
| AgentHub Metrics | https://agenthub.barodine.net/metrics | 443 |
|
||||||
|
| Coolify | https://coolify.barodine.net | 443 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Forgejo ne démarre pas
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Vérifier les logs
|
||||||
|
docker logs forgejo
|
||||||
|
|
||||||
|
# Vérifier la connexion DB
|
||||||
|
docker exec -it forgejo sh
|
||||||
|
psql "postgres://postgres:PASSWORD@rffv6pfwpdftlhunzoishduj:5432/postgres"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Erreur "database is locked"
|
||||||
|
|
||||||
|
- Forgejo utilise SQLite par défaut si la config DB échoue
|
||||||
|
- Vérifier que toutes les env vars `FORGEJO__database__*` sont correctes
|
||||||
|
- Redémarrer le service
|
||||||
|
|
||||||
|
### SSH ne fonctionne pas
|
||||||
|
|
||||||
|
1. Vérifier que le port 2222 est mappé dans Coolify
|
||||||
|
2. Vérifier que le firewall autorise le port 2222:
|
||||||
|
```bash
|
||||||
|
sudo ufw allow 2222/tcp
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prochaines étapes
|
||||||
|
|
||||||
|
1. ✅ Installer Forgejo via Coolify (Méthode 1)
|
||||||
|
2. ✅ Créer le repository AgentHub
|
||||||
|
3. ✅ Pousser le code depuis le workspace local
|
||||||
|
4. ⏳ Créer la DB PostgreSQL pour AgentHub
|
||||||
|
5. ⏳ Créer l'application AgentHub dans Coolify
|
||||||
|
6. ⏳ Déployer et tester l'endpoint `/metrics`
|
||||||
|
7. ⏳ Configurer Prometheus et Grafana
|
||||||
250
docs/FORGEJO-MANUAL-STEPS.md
Normal file
250
docs/FORGEJO-MANUAL-STEPS.md
Normal file
|
|
@ -0,0 +1,250 @@
|
||||||
|
# Installation Forgejo - Étapes manuelles
|
||||||
|
|
||||||
|
## Ce que vous devez faire
|
||||||
|
|
||||||
|
### 1. Interface Coolify (Principal)
|
||||||
|
|
||||||
|
**URL**: https://coolify.barodine.net
|
||||||
|
|
||||||
|
#### Créer le service Forgejo
|
||||||
|
|
||||||
|
1. **Naviguer vers le projet**
|
||||||
|
- Menu: Projects → **Barodine IA**
|
||||||
|
- Cliquer: **"+ New Resource"**
|
||||||
|
|
||||||
|
2. **Type de service**
|
||||||
|
- Choisir: **"Service"**
|
||||||
|
- Type: **"Docker Image"**
|
||||||
|
|
||||||
|
3. **Configuration**
|
||||||
|
|
||||||
|
| Paramètre | Valeur |
|
||||||
|
|-----------|--------|
|
||||||
|
| Name | `forgejo` |
|
||||||
|
| Image | `codeberg.org/forgejo/forgejo:9` |
|
||||||
|
| Port | `3000` |
|
||||||
|
| FQDN | `git.barodine.net` |
|
||||||
|
| Enable HTTPS | ✅ Oui |
|
||||||
|
|
||||||
|
4. **Volume (IMPORTANT!)**
|
||||||
|
- Cliquer **"Add Volume"**
|
||||||
|
- Name: `forgejo-data`
|
||||||
|
- Source: `/var/lib/forgejo`
|
||||||
|
- Destination: `/data`
|
||||||
|
- Type: Named volume
|
||||||
|
|
||||||
|
5. **Variables d'environnement**
|
||||||
|
|
||||||
|
Copier toutes ces lignes dans la section "Environment Variables":
|
||||||
|
|
||||||
|
```bash
|
||||||
|
USER_UID=1000
|
||||||
|
USER_GID=1000
|
||||||
|
FORGEJO__database__DB_TYPE=postgres
|
||||||
|
FORGEJO__database__HOST=rffv6pfwpdftlhunzoishduj:5432
|
||||||
|
FORGEJO__database__NAME=postgres
|
||||||
|
FORGEJO__database__USER=postgres
|
||||||
|
FORGEJO__database__PASSWD=UpW5nyYcNSy88bQiNppIRdFKrtul2Bu4hXzxitzcB4IHU9sAzGc2mkndvKdA1J42
|
||||||
|
FORGEJO__server__DOMAIN=git.barodine.net
|
||||||
|
FORGEJO__server__ROOT_URL=https://git.barodine.net
|
||||||
|
FORGEJO__server__HTTP_PORT=3000
|
||||||
|
FORGEJO__server__PROTOCOL=http
|
||||||
|
FORGEJO__server__START_SSH_SERVER=true
|
||||||
|
FORGEJO__server__SSH_PORT=2222
|
||||||
|
FORGEJO__server__SSH_LISTEN_PORT=22
|
||||||
|
FORGEJO__security__INSTALL_LOCK=false
|
||||||
|
FORGEJO__security__SECRET_KEY=ChangeThisToARandomSecretKey32Chars1234567890
|
||||||
|
FORGEJO__service__DISABLE_REGISTRATION=false
|
||||||
|
FORGEJO__service__REQUIRE_SIGNIN_VIEW=false
|
||||||
|
FORGEJO__service__ENABLE_NOTIFY_MAIL=false
|
||||||
|
FORGEJO__session__PROVIDER=memory
|
||||||
|
```
|
||||||
|
|
||||||
|
6. **Déployer**
|
||||||
|
- Cliquer **"Deploy"**
|
||||||
|
- Attendre 1-2 minutes (voir les logs)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Terminal de 192.168.9.25 (Optionnel - Vérification uniquement)
|
||||||
|
|
||||||
|
**Vous n'avez RIEN à faire sur le terminal** si Coolify fonctionne correctement.
|
||||||
|
|
||||||
|
Mais si vous voulez vérifier que tout est OK:
|
||||||
|
|
||||||
|
#### Vérification 1: Docker est bien démarré
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh user@192.168.9.25
|
||||||
|
|
||||||
|
# Vérifier que Docker tourne
|
||||||
|
sudo systemctl status docker
|
||||||
|
|
||||||
|
# Devrait afficher: active (running)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Vérification 2: Le container Forgejo est bien créé
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Lister les containers Coolify
|
||||||
|
sudo docker ps | grep forgejo
|
||||||
|
|
||||||
|
# Devrait afficher quelque chose comme:
|
||||||
|
# abc123... codeberg.org/forgejo/forgejo:9 ... Up 2 minutes ... forgejo
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Vérification 3: Les logs du container
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Voir les logs Forgejo
|
||||||
|
sudo docker logs -f $(sudo docker ps | grep forgejo | awk '{print $1}')
|
||||||
|
|
||||||
|
# Chercher cette ligne (indique que Forgejo a démarré):
|
||||||
|
# "Starting new Web server: tcp:0.0.0.0:3000"
|
||||||
|
|
||||||
|
# Appuyer sur Ctrl+C pour quitter les logs
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Vérification 4: Tester la connexion DB (si problème)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Se connecter au container Forgejo
|
||||||
|
sudo docker exec -it $(sudo docker ps | grep forgejo | awk '{print $1}') sh
|
||||||
|
|
||||||
|
# Dans le container, tester la connexion PostgreSQL
|
||||||
|
psql "postgres://postgres:UpW5nyYcNSy88bQiNppIRdFKrtul2Bu4hXzxitzcB4IHU9sAzGc2mkndvKdA1J42@rffv6pfwpdftlhunzoishduj:5432/postgres"
|
||||||
|
|
||||||
|
# Si ça se connecte, c'est bon! Taper \q pour quitter
|
||||||
|
# Taper exit pour sortir du container
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Si le port SSH 2222 ne fonctionne pas (optionnel)
|
||||||
|
|
||||||
|
Par défaut, Forgejo expose SSH sur le port 2222. Si vous voulez cloner via SSH:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Ouvrir le port dans le firewall
|
||||||
|
sudo ufw allow 2222/tcp
|
||||||
|
|
||||||
|
# Vérifier que le port est ouvert
|
||||||
|
sudo ufw status | grep 2222
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. Configuration initiale de Forgejo (Navigateur)
|
||||||
|
|
||||||
|
Une fois que Forgejo est déployé:
|
||||||
|
|
||||||
|
1. **Ouvrir**: https://git.barodine.net
|
||||||
|
2. **Page d'installation** s'affiche automatiquement
|
||||||
|
3. **Paramètres déjà configurés** (via les env vars):
|
||||||
|
- Type DB: PostgreSQL
|
||||||
|
- Host: rffv6pfwpdftlhunzoishduj:5432
|
||||||
|
- User: postgres
|
||||||
|
- Password: (déjà rempli)
|
||||||
|
- Database: postgres
|
||||||
|
|
||||||
|
4. **Configurer l'admin**:
|
||||||
|
- Username: `admin` (ou votre choix)
|
||||||
|
- Password: (choisir un mot de passe fort)
|
||||||
|
- Email: votre email
|
||||||
|
|
||||||
|
5. **Paramètres du site**:
|
||||||
|
- Site Title: `Barodine Git`
|
||||||
|
- Server Domain: `git.barodine.net` (déjà rempli)
|
||||||
|
- SSH Server Port: `2222` (déjà rempli)
|
||||||
|
- Base URL: `https://git.barodine.net` (déjà rempli)
|
||||||
|
|
||||||
|
6. **Cliquer "Install Forgejo"**
|
||||||
|
|
||||||
|
7. **Connexion**:
|
||||||
|
- Se connecter avec le compte admin créé
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. Créer le premier repository (AgentHub)
|
||||||
|
|
||||||
|
1. **Dans Forgejo**, cliquer **"+"** → **"New Repository"**
|
||||||
|
2. **Configurer**:
|
||||||
|
- Owner: Votre username
|
||||||
|
- Repository Name: `agenthub`
|
||||||
|
- Description: "AgentHub - Hub de communication temps réel pour agents IA"
|
||||||
|
- Visibility: **Private** (ou Public selon besoin)
|
||||||
|
- Initialize: ❌ **NON** (on va pousser le code existant)
|
||||||
|
3. **Cliquer "Create Repository"**
|
||||||
|
4. **Copier l'URL HTTPS** affichée (ex: `https://git.barodine.net/admin/agenthub.git`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5. Pousser le code AgentHub vers Forgejo (Sur votre machine de dev)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Se placer dans le répertoire AgentHub
|
||||||
|
cd /home/alexandre/.paperclip/instances/default/workspaces/8780faf8-03bb-45e9-989e-167eeb438b58/agenthub
|
||||||
|
|
||||||
|
# Supprimer le remote GitHub (ou le garder si vous voulez les deux)
|
||||||
|
git remote remove origin
|
||||||
|
|
||||||
|
# Ajouter Forgejo comme remote origin
|
||||||
|
git remote add origin https://git.barodine.net/admin/agenthub.git
|
||||||
|
|
||||||
|
# Pousser le code
|
||||||
|
git push -u origin main
|
||||||
|
|
||||||
|
# Entrer vos credentials Forgejo quand demandé
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Résumé des actions
|
||||||
|
|
||||||
|
| Action | Où | Temps |
|
||||||
|
|--------|-----|-------|
|
||||||
|
| 1. Créer service Forgejo | Coolify web (https://coolify.barodine.net) | 5 min |
|
||||||
|
| 2. Vérifier logs | Coolify → Onglet Logs | 1 min |
|
||||||
|
| 3. Configuration initiale Forgejo | Navigateur (https://git.barodine.net) | 3 min |
|
||||||
|
| 4. Créer repo AgentHub | Forgejo web | 2 min |
|
||||||
|
| 5. Pousser le code | Terminal local | 2 min |
|
||||||
|
|
||||||
|
**Total: ~13 minutes**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting rapide
|
||||||
|
|
||||||
|
### Forgejo ne démarre pas
|
||||||
|
|
||||||
|
1. Vérifier les logs dans Coolify → Logs
|
||||||
|
2. Chercher des erreurs de connexion DB
|
||||||
|
3. Vérifier que la DB Postgres est bien UP dans Coolify → Databases
|
||||||
|
|
||||||
|
### Page d'installation ne s'affiche pas
|
||||||
|
|
||||||
|
1. Vérifier que `FORGEJO__security__INSTALL_LOCK=false`
|
||||||
|
2. Redémarrer le service dans Coolify
|
||||||
|
|
||||||
|
### SSH ne fonctionne pas
|
||||||
|
|
||||||
|
1. Dans Coolify, aller dans Forgejo → Networking
|
||||||
|
2. Ajouter un port mapping:
|
||||||
|
- Host Port: `2222`
|
||||||
|
- Container Port: `22`
|
||||||
|
3. Redémarrer le service
|
||||||
|
|
||||||
|
### Cannot push to Forgejo
|
||||||
|
|
||||||
|
1. Vérifier que le repo est bien créé dans Forgejo
|
||||||
|
2. Vérifier que vous utilisez la bonne URL (copier depuis Forgejo)
|
||||||
|
3. Vérifier vos credentials (username/password)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prochaines étapes après installation
|
||||||
|
|
||||||
|
1. ✅ Forgejo installé et accessible
|
||||||
|
2. ✅ Repository AgentHub créé
|
||||||
|
3. ✅ Code poussé vers Forgejo
|
||||||
|
4. ⏳ Créer l'application AgentHub dans Coolify (source: Forgejo)
|
||||||
|
5. ⏳ Configurer le webhook Forgejo → Coolify
|
||||||
|
6. ⏳ Déployer AgentHub et tester `/metrics`
|
||||||
441
docs/GIT-HOSTING-GUIDE.md
Normal file
441
docs/GIT-HOSTING-GUIDE.md
Normal file
|
|
@ -0,0 +1,441 @@
|
||||||
|
# Guide de mise en place Git Hosting pour AgentHub
|
||||||
|
|
||||||
|
Guide complet pour choisir et configurer la solution Git (GitHub ou Forgejo) pour héberger le code AgentHub et l'intégrer avec Coolify.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Comparaison GitHub vs Forgejo
|
||||||
|
|
||||||
|
| Critère | GitHub | Forgejo |
|
||||||
|
|---------|--------|---------|
|
||||||
|
| **Hébergement** | Cloud (github.com) | Self-hosted (192.168.9.25) |
|
||||||
|
| **Coût** | Gratuit (public) / $4/mois (privé) | Gratuit (infrastructure existante) |
|
||||||
|
| **Temps d'installation** | 10 minutes | 30-45 minutes |
|
||||||
|
| **Accessibilité** | Internet requis | LAN uniquement (ou exposition via VPN) |
|
||||||
|
| **Maintenance** | Aucune (géré par GitHub) | Mises à jour manuelles |
|
||||||
|
| **Sécurité données** | Hébergé chez Microsoft | 100% contrôle local |
|
||||||
|
| **Webhooks Coolify** | ✅ Supporté | ✅ Supporté |
|
||||||
|
| **CI/CD natif** | GitHub Actions (gratuit limité) | Forgejo Actions (illimité) |
|
||||||
|
| **Interface web** | Moderne, feature-rich | Similaire à GitHub, léger |
|
||||||
|
| **API REST** | Complète et documentée | Compatible Gitea/Forgejo |
|
||||||
|
| **Collaboration externe** | Facile (pull requests publics) | Nécessite accès VPN/réseau |
|
||||||
|
| **Backup** | Automatique (GitHub) | À configurer (Coolify) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Recommandation par use case
|
||||||
|
|
||||||
|
### Choisir GitHub si:
|
||||||
|
- ✅ Vous voulez un déploiement **rapide** (10 min)
|
||||||
|
- ✅ Collaboration avec des **contributeurs externes**
|
||||||
|
- ✅ Besoin d'accès depuis **n'importe où**
|
||||||
|
- ✅ Pas de contraintes strictes sur **l'hébergement des données**
|
||||||
|
- ✅ Utilisation de **GitHub Actions** pour CI/CD
|
||||||
|
|
||||||
|
### Choisir Forgejo si:
|
||||||
|
- ✅ **Souveraineté des données** (tout reste sur vos serveurs)
|
||||||
|
- ✅ Projet **interne uniquement** (pas de collaboration externe)
|
||||||
|
- ✅ Infrastructure **LAN déjà en place**
|
||||||
|
- ✅ Volonté de **contrôler 100%** de la stack
|
||||||
|
- ✅ Éviter toute **dépendance cloud**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation et configuration GitHub
|
||||||
|
|
||||||
|
### Prérequis
|
||||||
|
- Compte GitHub: https://github.com/barodine
|
||||||
|
- Repository déjà créé: https://github.com/barodine/agenthub
|
||||||
|
- Personal Access Token (PAT) avec scope `repo`
|
||||||
|
|
||||||
|
### Étape 1: Vérifier le repository
|
||||||
|
|
||||||
|
Le repository GitHub est déjà créé et le code a été poussé.
|
||||||
|
|
||||||
|
**Vérification:**
|
||||||
|
```bash
|
||||||
|
git remote -v
|
||||||
|
# devrait afficher:
|
||||||
|
# origin https://github.com/barodine/agenthub.git (fetch)
|
||||||
|
# origin https://github.com/barodine/agenthub.git (push)
|
||||||
|
|
||||||
|
git branch -a
|
||||||
|
# devrait afficher:
|
||||||
|
# * main
|
||||||
|
# remotes/origin/main
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 2: Configurer le webhook Coolify
|
||||||
|
|
||||||
|
#### 2.1. Récupérer l'URL du webhook Coolify
|
||||||
|
|
||||||
|
1. Aller dans Coolify: https://coolify.barodine.net
|
||||||
|
2. Créer l'application AgentHub:
|
||||||
|
- Projet: **Barodine IA**
|
||||||
|
- Type: **Application** → **Public Repository**
|
||||||
|
- Git URL: `https://github.com/barodine/agenthub`
|
||||||
|
- Branch: `main`
|
||||||
|
- Build Pack: **Dockerfile**
|
||||||
|
3. Une fois créée, aller dans **Webhooks** → **GitHub**
|
||||||
|
4. Copier l'URL du webhook (format: `https://coolify.barodine.net/webhooks/xxx`)
|
||||||
|
|
||||||
|
#### 2.2. Configurer le webhook dans GitHub
|
||||||
|
|
||||||
|
1. Ouvrir https://github.com/barodine/agenthub/settings/hooks
|
||||||
|
2. Cliquer **Add webhook**
|
||||||
|
3. Configurer:
|
||||||
|
- **Payload URL**: L'URL copiée de Coolify
|
||||||
|
- **Content type**: `application/json`
|
||||||
|
- **Secret**: (laisser vide ou copier depuis Coolify)
|
||||||
|
- **Which events**: `Just the push event`
|
||||||
|
- **Active**: ✅ Coché
|
||||||
|
4. Cliquer **Add webhook**
|
||||||
|
|
||||||
|
#### 2.3. Tester le webhook
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Faire un commit test
|
||||||
|
cd /home/alexandre/.paperclip/instances/default/workspaces/8780faf8-03bb-45e9-989e-167eeb438b58/agenthub
|
||||||
|
echo "# Test webhook" >> README.md
|
||||||
|
git add README.md
|
||||||
|
git commit -m "test: Verify GitHub webhook triggers Coolify deploy"
|
||||||
|
git push origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
Vérifier dans Coolify que le déploiement démarre automatiquement.
|
||||||
|
|
||||||
|
### Étape 3: Configuration des secrets GitHub (optionnel)
|
||||||
|
|
||||||
|
Pour utiliser GitHub Actions:
|
||||||
|
|
||||||
|
1. Aller dans **Settings** → **Secrets and variables** → **Actions**
|
||||||
|
2. Ajouter les secrets:
|
||||||
|
- `COOLIFY_WEBHOOK_URL`: URL du webhook Coolify
|
||||||
|
- `POSTGRES_PASSWORD`: Mot de passe DB
|
||||||
|
- `JWT_SECRET`: Secret JWT
|
||||||
|
|
||||||
|
### Étape 4: Configurer les variables d'environnement dans Coolify
|
||||||
|
|
||||||
|
Dans l'application AgentHub créée dans Coolify:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
NODE_ENV=production
|
||||||
|
HOST=0.0.0.0
|
||||||
|
PORT=3000
|
||||||
|
LOG_LEVEL=info
|
||||||
|
|
||||||
|
# PostgreSQL
|
||||||
|
POSTGRES_HOST=<uuid_db_agenthub>
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
POSTGRES_USER=postgres
|
||||||
|
POSTGRES_PASSWORD=<password_from_db_creation>
|
||||||
|
POSTGRES_DB=postgres
|
||||||
|
|
||||||
|
# Sécurité
|
||||||
|
JWT_SECRET=<générer_32_chars_random>
|
||||||
|
ALLOWED_ORIGINS=https://agenthub.barodine.net
|
||||||
|
ENABLE_HSTS=true
|
||||||
|
|
||||||
|
# Features
|
||||||
|
FEATURE_MESSAGING_ENABLED=true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 5: Créer la base de données AgentHub
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST "https://coolify.barodine.net/api/v1/databases/postgresql" \
|
||||||
|
-H "Authorization: Bearer $COOLIFY_API_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{
|
||||||
|
"server_uuid": "gw9o6m2ftfvx7g5guf82nkiq",
|
||||||
|
"project_uuid": "x9fenmiro11hv1uqij88z88a",
|
||||||
|
"environment_name": "production",
|
||||||
|
"name": "agenthub-db",
|
||||||
|
"description": "PostgreSQL database for AgentHub production",
|
||||||
|
"image": "postgres:16-alpine",
|
||||||
|
"instant_deploy": true
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 6: Premier déploiement
|
||||||
|
|
||||||
|
1. Dans Coolify, cliquer sur **Deploy** pour l'application AgentHub
|
||||||
|
2. Attendre la fin du build (~2-5 minutes)
|
||||||
|
3. Vérifier les logs dans l'onglet **Logs**
|
||||||
|
4. Tester l'endpoint `/metrics`:
|
||||||
|
```bash
|
||||||
|
curl https://agenthub.barodine.net/metrics
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation et configuration Forgejo
|
||||||
|
|
||||||
|
### Étape 1: Installer Forgejo sur 192.168.9.25
|
||||||
|
|
||||||
|
Voir le guide complet: [`FORGEJO-INSTALL.md`](./FORGEJO-INSTALL.md)
|
||||||
|
|
||||||
|
**Résumé:**
|
||||||
|
|
||||||
|
1. **Créer la base de données Forgejo** (déjà fait):
|
||||||
|
```
|
||||||
|
UUID: rffv6pfwpdftlhunzoishduj
|
||||||
|
URL: postgres://postgres:UpW5nyYcNSy88bQiNppIRdFKrtul2Bu4hXzxitzcB4IHU9sAzGc2mkndvKdA1J42@rffv6pfwpdftlhunzoishduj:5432/postgres
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Créer le service Forgejo dans Coolify**:
|
||||||
|
- Projet: Barodine IA
|
||||||
|
- Image: `codeberg.org/forgejo/forgejo:9`
|
||||||
|
- Port: 3000
|
||||||
|
- Domain: `git.barodine.net`
|
||||||
|
- Variables d'environnement: voir [`FORGEJO-INSTALL.md`](./FORGEJO-INSTALL.md)
|
||||||
|
|
||||||
|
3. **Déployer et configurer**:
|
||||||
|
- Attendre le démarrage (~2 min)
|
||||||
|
- Ouvrir https://git.barodine.net
|
||||||
|
- Compléter l'installation initiale
|
||||||
|
|
||||||
|
### Étape 2: Créer le repository AgentHub dans Forgejo
|
||||||
|
|
||||||
|
1. Se connecter à https://git.barodine.net
|
||||||
|
2. Cliquer sur **+** → **New Repository**
|
||||||
|
3. Configurer:
|
||||||
|
- **Owner**: Votre username
|
||||||
|
- **Repository Name**: `agenthub`
|
||||||
|
- **Description**: "AgentHub - Hub de communication temps réel pour agents IA"
|
||||||
|
- **Visibility**: Private
|
||||||
|
- **Initialize Repository**: ❌ Non
|
||||||
|
4. Cliquer **Create Repository**
|
||||||
|
|
||||||
|
### Étape 3: Migrer le code de GitHub vers Forgejo
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/alexandre/.paperclip/instances/default/workspaces/8780faf8-03bb-45e9-989e-167eeb438b58/agenthub
|
||||||
|
|
||||||
|
# Ajouter Forgejo comme remote (garder GitHub aussi)
|
||||||
|
git remote add forgejo https://git.barodine.net/username/agenthub.git
|
||||||
|
|
||||||
|
# Pousser vers Forgejo
|
||||||
|
git push forgejo main
|
||||||
|
|
||||||
|
# OU: Remplacer GitHub par Forgejo
|
||||||
|
git remote remove origin
|
||||||
|
git remote add origin https://git.barodine.net/username/agenthub.git
|
||||||
|
git push -u origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 4: Configurer le webhook Coolify dans Forgejo
|
||||||
|
|
||||||
|
1. Dans Forgejo, aller dans le repo **agenthub** → **Settings** → **Webhooks**
|
||||||
|
2. Cliquer **Add Webhook** → **Forgejo**
|
||||||
|
3. Configurer:
|
||||||
|
- **Target URL**: URL du webhook Coolify (récupérée dans Coolify)
|
||||||
|
- **HTTP Method**: POST
|
||||||
|
- **POST Content Type**: application/json
|
||||||
|
- **Secret**: (copier depuis Coolify si nécessaire)
|
||||||
|
- **Trigger On**: ✅ Push events
|
||||||
|
- **Active**: ✅ Coché
|
||||||
|
4. Cliquer **Add Webhook**
|
||||||
|
|
||||||
|
### Étape 5: Créer l'application AgentHub dans Coolify (source Forgejo)
|
||||||
|
|
||||||
|
1. Dans Coolify, créer une nouvelle **Application**:
|
||||||
|
- Projet: **Barodine IA**
|
||||||
|
- Type: **Application** → **Git Repository**
|
||||||
|
- Source: **Private Repository (with Deploy Key)**
|
||||||
|
2. Configurer:
|
||||||
|
- **Git URL**: `https://git.barodine.net/username/agenthub.git`
|
||||||
|
- **Branch**: `main`
|
||||||
|
- **Build Pack**: Dockerfile
|
||||||
|
|
||||||
|
**Important:** Générer une Deploy Key SSH:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Dans Coolify, aller dans l'application → Settings → Deploy Key
|
||||||
|
# Copier la clé publique SSH générée
|
||||||
|
|
||||||
|
# Dans Forgejo, aller dans le repo → Settings → Deploy Keys
|
||||||
|
# Ajouter la clé publique de Coolify
|
||||||
|
# ✅ Cocher "Read-only" (pas besoin de write)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Étape 6: Variables d'environnement et déploiement
|
||||||
|
|
||||||
|
Même configuration que pour GitHub (voir Étape 4 de la section GitHub).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Workflow Git recommandé
|
||||||
|
|
||||||
|
### Développement local
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Créer une branche de feature
|
||||||
|
git checkout -b feature/nouvelle-fonctionnalite
|
||||||
|
|
||||||
|
# 2. Développer et commiter
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: Ajouter nouvelle fonctionnalité"
|
||||||
|
|
||||||
|
# 3. Pousser vers le remote
|
||||||
|
git push origin feature/nouvelle-fonctionnalite
|
||||||
|
|
||||||
|
# 4. Créer une Pull Request (GitHub) ou Merge Request (Forgejo)
|
||||||
|
# Via l'interface web
|
||||||
|
```
|
||||||
|
|
||||||
|
### Déploiement en production
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Merger la PR/MR dans main
|
||||||
|
# Via l'interface web
|
||||||
|
|
||||||
|
# 2. Le webhook déclenche automatiquement le déploiement Coolify
|
||||||
|
|
||||||
|
# 3. Vérifier le déploiement
|
||||||
|
curl https://agenthub.barodine.net/healthz
|
||||||
|
curl https://agenthub.barodine.net/metrics
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rollback en cas de problème
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Option 1: Via Git (revert)
|
||||||
|
git revert HEAD
|
||||||
|
git push origin main
|
||||||
|
# Le webhook redéploie automatiquement la version précédente
|
||||||
|
|
||||||
|
# Option 2: Via Coolify
|
||||||
|
# Aller dans l'application → Deployments → Cliquer sur un déploiement précédent → "Redeploy"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Intégration Prometheus/Grafana
|
||||||
|
|
||||||
|
Une fois AgentHub déployé avec l'endpoint `/metrics`:
|
||||||
|
|
||||||
|
### Configuration Prometheus
|
||||||
|
|
||||||
|
1. Créer/éditer `prometheus.yml`:
|
||||||
|
```yaml
|
||||||
|
scrape_configs:
|
||||||
|
- job_name: 'agenthub'
|
||||||
|
scrape_interval: 15s
|
||||||
|
static_configs:
|
||||||
|
- targets: ['agenthub.barodine.net:443']
|
||||||
|
scheme: https
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Redémarrer Prometheus
|
||||||
|
|
||||||
|
### Import Dashboard Grafana
|
||||||
|
|
||||||
|
1. Ouvrir Grafana
|
||||||
|
2. **Dashboards** → **Import**
|
||||||
|
3. Uploader `agenthub/docs/grafana-dashboard.json`
|
||||||
|
4. Sélectionner la datasource Prometheus
|
||||||
|
5. Cliquer **Import**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Checklist finale
|
||||||
|
|
||||||
|
### GitHub Setup
|
||||||
|
- [ ] Repository créé: https://github.com/barodine/agenthub
|
||||||
|
- [ ] Code poussé sur `main`
|
||||||
|
- [ ] Application créée dans Coolify
|
||||||
|
- [ ] Webhook GitHub → Coolify configuré
|
||||||
|
- [ ] Variables d'environnement configurées
|
||||||
|
- [ ] Base de données PostgreSQL créée
|
||||||
|
- [ ] Premier déploiement réussi
|
||||||
|
- [ ] Endpoint `/metrics` accessible
|
||||||
|
|
||||||
|
### Forgejo Setup
|
||||||
|
- [ ] Service Forgejo déployé sur Coolify
|
||||||
|
- [ ] Forgejo accessible via https://git.barodine.net
|
||||||
|
- [ ] Repository `agenthub` créé dans Forgejo
|
||||||
|
- [ ] Code migré de GitHub vers Forgejo
|
||||||
|
- [ ] Deploy Key SSH configurée (Coolify → Forgejo)
|
||||||
|
- [ ] Webhook Forgejo → Coolify configuré
|
||||||
|
- [ ] Application AgentHub créée dans Coolify (source Forgejo)
|
||||||
|
- [ ] Variables d'environnement configurées
|
||||||
|
- [ ] Base de données PostgreSQL créée
|
||||||
|
- [ ] Premier déploiement réussi
|
||||||
|
- [ ] Endpoint `/metrics` accessible
|
||||||
|
|
||||||
|
### Monitoring Setup
|
||||||
|
- [ ] Prometheus configuré pour scraper `/metrics`
|
||||||
|
- [ ] Dashboard Grafana importé
|
||||||
|
- [ ] Métriques visibles dans Grafana
|
||||||
|
- [ ] Alertes configurées (optionnel)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Webhook ne déclenche pas le déploiement
|
||||||
|
|
||||||
|
1. Vérifier dans GitHub/Forgejo → Settings → Webhooks → Recent Deliveries
|
||||||
|
2. Vérifier que la réponse HTTP est 200
|
||||||
|
3. Vérifier les logs Coolify
|
||||||
|
4. Tester manuellement:
|
||||||
|
```bash
|
||||||
|
# Copier l'URL du webhook
|
||||||
|
curl -X POST "https://coolify.barodine.net/webhooks/xxx"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build échoue dans Coolify
|
||||||
|
|
||||||
|
1. Vérifier les logs de build dans Coolify
|
||||||
|
2. Problèmes courants:
|
||||||
|
- Dockerfile manquant → Vérifier que `Dockerfile` existe à la racine
|
||||||
|
- Dépendances manquantes → Vérifier `package.json`
|
||||||
|
- Variables d'environnement manquantes → Vérifier la config Coolify
|
||||||
|
|
||||||
|
### Endpoint `/metrics` retourne 404
|
||||||
|
|
||||||
|
1. Vérifier que le serveur démarre:
|
||||||
|
```bash
|
||||||
|
curl https://agenthub.barodine.net/healthz
|
||||||
|
```
|
||||||
|
2. Vérifier les logs de l'application dans Coolify
|
||||||
|
3. Vérifier que le port 3000 est bien mappé
|
||||||
|
4. Tester en local:
|
||||||
|
```bash
|
||||||
|
docker logs <container_id>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Forgejo ne démarre pas
|
||||||
|
|
||||||
|
1. Vérifier les logs dans Coolify
|
||||||
|
2. Vérifier la connexion à la base de données:
|
||||||
|
```bash
|
||||||
|
docker exec -it forgejo sh
|
||||||
|
psql "postgres://postgres:PASSWORD@rffv6pfwpdftlhunzoishduj:5432/postgres"
|
||||||
|
```
|
||||||
|
3. Vérifier les variables d'environnement `FORGEJO__database__*`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prochaines étapes
|
||||||
|
|
||||||
|
1. ✅ Choisir entre GitHub ou Forgejo (ou les deux)
|
||||||
|
2. ✅ Suivre les étapes d'installation correspondantes
|
||||||
|
3. ✅ Déployer AgentHub via Coolify
|
||||||
|
4. ⏳ Configurer Prometheus pour scraper `/metrics`
|
||||||
|
5. ⏳ Importer le dashboard Grafana
|
||||||
|
6. ⏳ Tester le monitoring en conditions réelles
|
||||||
|
7. ⏳ Documenter les procédures opérationnelles (runbook)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ressources
|
||||||
|
|
||||||
|
- **Documentation AgentHub**: [`/agenthub/docs/`](../docs/)
|
||||||
|
- **Guide Forgejo**: [`FORGEJO-INSTALL.md`](./FORGEJO-INSTALL.md)
|
||||||
|
- **Métriques Prometheus**: [`METRICS.md`](./METRICS.md)
|
||||||
|
- **Dashboard Grafana**: [`grafana-dashboard.json`](./grafana-dashboard.json)
|
||||||
|
- **Coolify Docs**: https://coolify.io/docs
|
||||||
|
- **GitHub Webhooks**: https://docs.github.com/en/webhooks
|
||||||
|
- **Forgejo Docs**: https://forgejo.org/docs
|
||||||
Loading…
Reference in a new issue