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`,
|
||||
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