91 lines
4.0 KiB
Markdown
91 lines
4.0 KiB
Markdown
# Seiche
|
|
|
|
Appli web auto-hébergée, **réseau local uniquement, mono-utilisateur** : gère un service externe via son API REST, protégée par mot de passe.
|
|
|
|
**Stack** : TypeScript strict · Node 22 + Fastify 5 · SQLite (libsql + Drizzle) · Vite + React 19 + Tailwind 4 · 1 conteneur (API + front statique).
|
|
|
|
- Doc de projet / décisions / plan : [REPRISE.md](REPRISE.md)
|
|
- Détail backend : [server/README.md](server/README.md) · Détail front : [web/README.md](web/README.md)
|
|
|
|
## Prérequis
|
|
|
|
- Node ≥ 22, pnpm (workspace)
|
|
- Docker + compose (pour la prod)
|
|
|
|
## Démarrage en développement
|
|
|
|
```bash
|
|
pnpm install
|
|
pnpm dev:server # terminal 1 — API sur http://localhost:8787
|
|
pnpm dev:web # terminal 2 — Vite sur http://localhost:5173 (proxy /api → 8787)
|
|
```
|
|
|
|
Premier compte (nécessaire une seule fois, idempotent) :
|
|
|
|
```bash
|
|
SEICHE_ADMIN_USERNAME=admin SEICHE_ADMIN_PASSWORD='<≥12 caractères>' pnpm setup
|
|
```
|
|
|
|
Puis ouvrir http://localhost:5173 et se connecter.
|
|
|
|
## Production (LXC Proxmox + nginx-proxy-manager)
|
|
|
|
Déploiement retenu (REPRISE.md §5 q12) : **LXC sur Proxmox** (Docker + compose dedans), TLS terminé par **nginx-proxy-manager** (Let's Encrypt).
|
|
|
|
```bash
|
|
# Dans le LXC :
|
|
docker compose up -d --build
|
|
|
|
# Premier compte (dans le conteneur, base vide) :
|
|
docker compose exec seiche sh -c \
|
|
"SEICHE_ADMIN_USERNAME=admin SEICHE_ADMIN_PASSWORD='<≥12 caractères>' pnpm setup"
|
|
```
|
|
|
|
Puis dans NPM : **Add Site** → hostname (ex. `seiche.mondomaine.fr`), **Proxy to** `IP_DU_LXC:8787`, **Let's Encrypt** activé.
|
|
|
|
Le compose active `SEICHE_COOKIE_SECURE=1` + `SEICHE_TRUST_PROXY=1` (TLS + `X-Forwarded-For` derrière NPM). **Sans proxy TLS** (test Docker en LAN) : passer ces deux variables à `0`, sinon les cookies `Secure` ne sont pas envoyés en HTTP.
|
|
|
|
Le conteneur écoute `0.0.0.0:8787` (API + front buildé, servi par Fastify). La base SQLite persiste dans le volume `seiche-data` (`/data`). Healthcheck : `GET /api/health`.
|
|
|
|
## Variables d'environnement
|
|
|
|
Référent complet : [.env.example](.env.example) (copier dans `.env` pour la dev — **jamais committer le `.env`**).
|
|
|
|
| Variable | Défaut | Rôle |
|
|
|---|---|---|
|
|
| `SEICHE_PORT` / `SEICHE_HOST` | `8787` / `127.0.0.1` | Écoute du serveur (Docker force `0.0.0.0`) |
|
|
| `SEICHE_DATA_DIR` | `./data` | Dossier SQLite (volume `/data` en Docker) |
|
|
| `SEICHE_SESSION_TTL_MS` | 8 h | Durée de vie d'une session |
|
|
| `SEICHE_SESSION_ABSOLUTE_TTL_MS` | 7 j | Durée absolue max |
|
|
| `SEICHE_MAX_LOGIN_ATTEMPTS_PER_MINUTE` | `5` | Rate-limit `/login` par IP |
|
|
| `SEICHE_COOKIE_SECURE` | `0` | `1` derrière un proxy TLS (cookies `Secure`) |
|
|
| `SEICHE_TRUST_PROXY` | `0` | `1` derrière un proxy (lit `X-Forwarded-For`) |
|
|
| `SEICHE_EXTERNAL_*` | `example` | Service REST externe (adaptateur, URL, clé, cache…) |
|
|
|
|
## Sauvegarde
|
|
|
|
```bash
|
|
./scripts/backup.sh [dir_sortie] # défaut : ./backups/
|
|
```
|
|
|
|
Snapshot cohérente **en ligne** (`VACUUM INTO` dans le conteneur, le serveur continue de servir) → copie **hors** du volume → vérification de l'en-tête SQLite. Prérequis : conteneur en marche. Penser à cronner et à stocker les `.db` ailleurs que sur la machine (le dossier `backups/` est gitignoré).
|
|
|
|
## Sécurité — non négociables
|
|
|
|
- Mot de passe **Argon2id** (sel par compte), jamais en clair ni dans les logs.
|
|
- **Rate-limit** sur `/login` (anti brute-force, par IP client).
|
|
- Session : cookie **httpOnly + SameSite=Lax**, durée limitée, révocation au logout ; **CSRF** (double-submit) sur toutes les mutations.
|
|
- Secrets uniquement en variables d'environnement ; SQLite hors de l'image (volume + backup).
|
|
- **TLS** : en prod derrière nginx-proxy-manager (Let's Encrypt) → cookies `Secure` + `trustProxy` (déjà dans le compose). En dev LAN sans proxy : HTTP (mots de passe en clair, dév uniquement).
|
|
- API minimale : `/api/health` public, tout le reste protégé.
|
|
|
|
## Structure
|
|
|
|
```
|
|
seiche/
|
|
├── server/ # Fastify : routes /api/v1/*, auth, DB, client externe
|
|
├── web/ # Vite + React : login, dashboard, client API
|
|
├── scripts/ # backup.sh
|
|
└── docker-compose.yml · Dockerfile · .env.example
|
|
```
|