generated from vincent/template-projet
Compare commits
20 Commits
feature/ci
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
| e91bf6db8d | |||
| 69678fcb06 | |||
| 5afad53aa9 | |||
| 230f018f47 | |||
| 32c6bd56a5 | |||
| 5b870e1eb5 | |||
| 88c3088cc1 | |||
| ae32eabc9c | |||
| 69a3e55aa9 | |||
| 001209d12c | |||
| c8088251dd | |||
| 7cc7ba66d8 | |||
| 3c6356b578 | |||
| 87d2f0add3 | |||
| 4eae30c0e5 | |||
| a39ff7b3b1 | |||
| c535d00947 | |||
| 12cfb49c87 | |||
| 046f542f6a | |||
| f733cd7d5b |
@@ -11,7 +11,7 @@ DEBUG=false
|
||||
# --- Base de données PostgreSQL ---
|
||||
POSTGRES_DB=auditshield
|
||||
POSTGRES_USER=auditshield
|
||||
POSTGRES_PASSWORD=changeme-strong-password
|
||||
POSTGRES_PASSWORD=AuditShield!
|
||||
|
||||
# Construit automatiquement par docker-compose, à définir manuellement en dev local :
|
||||
DATABASE_URL=postgresql://auditshield:changeme-strong-password@localhost:5432/auditshield
|
||||
|
||||
@@ -24,18 +24,38 @@ jobs:
|
||||
echo "PROJECT_PATH=/volume1/docker/auditshield-dev" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Deploy to NAS
|
||||
uses: appleboy/ssh-action@v1
|
||||
with:
|
||||
host: ${{ secrets.NAS_HOST }}
|
||||
username: ${{ secrets.NAS_USER }}
|
||||
key: ${{ secrets.NAS_SSH_KEY }}
|
||||
script: |
|
||||
mkdir -p ${{ steps.env.outputs.PROJECT_PATH }}
|
||||
cd ${{ steps.env.outputs.PROJECT_PATH }}
|
||||
git clone https://gitea.rigolet.tech/vincent/auditshield.git . 2>/dev/null || git pull
|
||||
cp .env.example .env 2>/dev/null || true
|
||||
sudo docker compose -f ${{ steps.env.outputs.COMPOSE_FILE }} up -d --build --remove-orphans
|
||||
sudo docker image prune -f
|
||||
- name: Setup SSH key
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
echo "${{ secrets.NAS_SSH_KEY_B64 }}" | base64 -d > ~/.ssh/nas_key
|
||||
chmod 600 ~/.ssh/nas_key
|
||||
ssh-keyscan -p 22 ${{ secrets.NAS_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
|
||||
|
||||
- name: Copy files to NAS
|
||||
run: |
|
||||
ssh -i ~/.ssh/nas_key -o StrictHostKeyChecking=no root@${{ secrets.NAS_HOST }} \
|
||||
"mkdir -p ${{ steps.env.outputs.PROJECT_PATH }}"
|
||||
tar --exclude='.git' --exclude='node_modules' --exclude='.env' -czf - . | \
|
||||
ssh -i ~/.ssh/nas_key -o StrictHostKeyChecking=no root@${{ secrets.NAS_HOST }} \
|
||||
"tar -xzf - -C ${{ steps.env.outputs.PROJECT_PATH }}"
|
||||
|
||||
- name: Setup env file
|
||||
run: |
|
||||
ssh -i ~/.ssh/nas_key -o StrictHostKeyChecking=no root@${{ secrets.NAS_HOST }} \
|
||||
"cat > ${{ steps.env.outputs.PROJECT_PATH }}/.env << 'EOF'
|
||||
SECRET_KEY=${{ secrets.APP_SECRET_KEY }}
|
||||
DEBUG=false
|
||||
POSTGRES_DB=auditshield
|
||||
POSTGRES_USER=auditshield
|
||||
POSTGRES_PASSWORD=${{ secrets.POSTGRES_PASSWORD }}
|
||||
DATABASE_URL=postgresql://auditshield:${{ secrets.POSTGRES_PASSWORD }}@postgres:5432/auditshield
|
||||
REDIS_URL=redis://redis:6379/0
|
||||
NEXT_PUBLIC_API_URL=https://auditshield.rigolet.tech
|
||||
DOMAIN=auditshield.rigolet.tech
|
||||
TAG=latest
|
||||
EOF"
|
||||
|
||||
- name: Deploy
|
||||
run: |
|
||||
ssh -i ~/.ssh/nas_key -o StrictHostKeyChecking=no root@${{ secrets.NAS_HOST }} \
|
||||
"cd ${{ steps.env.outputs.PROJECT_PATH }} && /usr/local/bin/docker compose -f ${{ steps.env.outputs.COMPOSE_FILE }} up -d --build --remove-orphans && /usr/local/bin/docker image prune -f"
|
||||
|
||||
12
CLAUDE.md
12
CLAUDE.md
@@ -40,8 +40,8 @@ backend/
|
||||
alembic/ # Migrations (env.py configuré)
|
||||
main.py # App FastAPI : CORS, rate limiting, routers
|
||||
docker/
|
||||
docker-compose.yml # Dev : postgres, redis, backend, frontend
|
||||
docker-compose.prod.yml # Prod : images registry + labels Traefik
|
||||
docker-compose.yml # Prod : images registry + labels Traefik (utilisé par Gitea Actions)
|
||||
docker-compose.prod.yml # Alias prod (identique, gardé pour référence)
|
||||
```
|
||||
|
||||
## Commandes
|
||||
@@ -129,14 +129,16 @@ Voir @docker/docker-compose.yml et @.gitea/workflows/deploy.yml
|
||||
- Le client API (`lib/api.ts`) passe toujours le token en paramètre explicite — pas de contexte global
|
||||
- Les nouvelles pages du dashboard vont dans `app/(dashboard)/[section]/page.tsx`
|
||||
- Les nouveaux composants UI shadcn vont dans `components/ui/`, les composants métier dans `components/`
|
||||
- Les rewrites `next.config.ts` proxifient `/api/*` vers le backend — en dev, définir `NEXT_PUBLIC_API_URL=http://localhost:8000`
|
||||
- Les rewrites `next.config.mjs` proxifient `/api/*` vers le backend — en dev, définir `NEXT_PUBLIC_API_URL=http://localhost:8000`
|
||||
- JWT stocké dans localStorage (simple pour MVP, à migrer vers HttpOnly cookie plus tard)
|
||||
|
||||
**Infrastructure :**
|
||||
- Le service `backend` dans docker-compose dépend de `postgres` avec `condition: service_healthy`
|
||||
- Le build frontend Next.js utilise `output: "standalone"` → le Dockerfile copie `.next/standalone`
|
||||
- Les variables d'env préfixées `NEXT_PUBLIC_` sont embarquées au build (pas au runtime)
|
||||
- `docker-compose.prod.yml` attend des images pré-buildées depuis `${REGISTRY}` — pas de build local
|
||||
- `docker-compose.yml` attend des images pré-buildées depuis `${REGISTRY}` — pas de build local (config prod)
|
||||
- Le `frontend/public/` doit exister (même vide avec `.gitkeep`) — le Dockerfile le copie dans le stage runner
|
||||
- `npm ci` exige un `package-lock.json` commité — toujours commiter le lockfile après `npm install`
|
||||
|
||||
### Pièges à éviter
|
||||
- Ne pas lancer `uvicorn main:app` depuis `backend/` — toujours depuis la racine avec le module complet
|
||||
@@ -145,3 +147,5 @@ Voir @docker/docker-compose.yml et @.gitea/workflows/deploy.yml
|
||||
- Ne pas faire de scans sans vérifier `cible.validee == True` côté backend
|
||||
- Ne pas commiter `.env` — seulement `.env.example`
|
||||
- Alembic `env.py` importe les modèles depuis `backend.models` — ajouter tout nouveau modèle dans `backend/models/__init__.py`
|
||||
- Ne pas utiliser `next.config.ts` — Next.js 14 ne supporte pas ce format, utiliser `next.config.mjs`
|
||||
- Ne pas utiliser `@radix-ui/react-badge` — ce package n'existe pas sur npm (Badge shadcn = div CVA)
|
||||
@@ -3,14 +3,14 @@ version: "3.8"
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
container_name: auditshield-db
|
||||
restart: unless-stopped
|
||||
container_name: auditshield-db-prod
|
||||
restart: always
|
||||
environment:
|
||||
POSTGRES_DB: ${POSTGRES_DB:-auditshield}
|
||||
POSTGRES_USER: ${POSTGRES_USER:-auditshield}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD required}
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
- postgres_data_prod:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-auditshield}"]
|
||||
interval: 10s
|
||||
@@ -21,36 +21,35 @@ services:
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: auditshield-redis
|
||||
restart: unless-stopped
|
||||
container_name: auditshield-redis-prod
|
||||
restart: always
|
||||
networks:
|
||||
- internal
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: ../backend
|
||||
dockerfile: Dockerfile
|
||||
container_name: auditshield-backend
|
||||
restart: unless-stopped
|
||||
env_file: ../.env
|
||||
image: ${REGISTRY}/auditshield-backend:${TAG:-latest}
|
||||
container_name: auditshield-backend-prod
|
||||
restart: always
|
||||
env_file: .env
|
||||
environment:
|
||||
DATABASE_URL: postgresql://${POSTGRES_USER:-auditshield}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-auditshield}
|
||||
REDIS_URL: redis://redis:6379/0
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_started
|
||||
networks:
|
||||
- internal
|
||||
- proxy
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.auditshield-api.rule=Host(`${DOMAIN}`) && PathPrefix(`/api`)"
|
||||
- "traefik.http.routers.auditshield-api.entrypoints=websecure"
|
||||
- "traefik.http.routers.auditshield-api.tls.certresolver=letsencrypt"
|
||||
|
||||
frontend:
|
||||
build:
|
||||
context: ../frontend
|
||||
dockerfile: Dockerfile
|
||||
container_name: auditshield-frontend
|
||||
restart: unless-stopped
|
||||
image: ${REGISTRY}/auditshield-frontend:${TAG:-latest}
|
||||
container_name: auditshield-frontend-prod
|
||||
restart: always
|
||||
environment:
|
||||
NEXT_PUBLIC_API_URL: ""
|
||||
depends_on:
|
||||
@@ -58,9 +57,14 @@ services:
|
||||
networks:
|
||||
- internal
|
||||
- proxy
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.auditshield.rule=Host(`${DOMAIN}`)"
|
||||
- "traefik.http.routers.auditshield.entrypoints=websecure"
|
||||
- "traefik.http.routers.auditshield.tls.certresolver=letsencrypt"
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
postgres_data_prod:
|
||||
|
||||
networks:
|
||||
internal:
|
||||
|
||||
16
plan.md
16
plan.md
@@ -9,7 +9,7 @@ Scans réseau + vulnérabilités + pentest → rapports PDF compréhensibles pou
|
||||
|
||||
## ✅ Phase 1 — Socle (terminée)
|
||||
|
||||
> Branche : `feature/phase-1-socle` → mergée dans `dev`
|
||||
> Branche : `feature/phase-1-socle` (PR ouverte, pas encore mergée dans `dev`)
|
||||
|
||||
### Ce qui a été créé
|
||||
|
||||
@@ -37,8 +37,8 @@ Scans réseau + vulnérabilités + pentest → rapports PDF compréhensibles pou
|
||||
- `lib/auth.ts` — helpers localStorage pour token JWT
|
||||
|
||||
**Infrastructure**
|
||||
- `docker/docker-compose.yml` — 4 services : postgres:16, redis:7, backend, frontend
|
||||
- `docker/docker-compose.prod.yml` — images registry + labels Traefik + Let's Encrypt
|
||||
- `docker/docker-compose.yml` — config prod : images registry + labels Traefik + Let's Encrypt (utilisé par Gitea Actions)
|
||||
- `docker/docker-compose.prod.yml` — alias prod identique (gardé pour référence)
|
||||
- `backend/Dockerfile` — Python 3.11-slim + WeasyPrint deps + alembic upgrade
|
||||
- `frontend/Dockerfile` — multi-stage Node 20 (deps → builder → runner standalone)
|
||||
- `.env.example` — toutes les variables documentées
|
||||
@@ -58,7 +58,7 @@ Scans réseau + vulnérabilités + pentest → rapports PDF compréhensibles pou
|
||||
| shadcn/ui + Radix | Accessibilité, composants non-opinionnés, facilement personnalisables |
|
||||
| JWT dans localStorage | Simple pour MVP — à migrer vers HttpOnly cookie en Phase 3 |
|
||||
| camelCase pour types TS, snake_case en DB | Convention JS vs convention Python/SQL |
|
||||
| Rewrites next.config.ts vers backend | Pas de CORS en prod, tout passe par Next.js |
|
||||
| Rewrites next.config.mjs vers backend | Pas de CORS en prod, tout passe par Next.js |
|
||||
|
||||
### État fonctionnel
|
||||
- ✅ Register/Login utilisateur avec JWT
|
||||
@@ -67,7 +67,7 @@ Scans réseau + vulnérabilités + pentest → rapports PDF compréhensibles pou
|
||||
- ✅ Dashboard avec stats temps réel
|
||||
- ✅ Pages liste clients et audits avec recherche
|
||||
- ✅ Guard auth côté frontend
|
||||
- ✅ Docker dev + prod prêt
|
||||
- ✅ Docker prod prêt (docker-compose.yml = config prod images registry + Traefik)
|
||||
- ⏳ Pages de formulaire (création/édition) non créées
|
||||
- ⏳ Pages détail client et audit non créées
|
||||
- ⏳ Scanners : dossier vide (placeholder Phase 2)
|
||||
@@ -118,9 +118,9 @@ Permettre le lancement d'un scan Nmap sur des cibles validées, afficher les ré
|
||||
|
||||
### Tâches infra
|
||||
|
||||
- [ ] Ajouter service `worker` dans docker-compose (image backend + command: celery worker)
|
||||
- [ ] Ajouter `python-nmap` dans requirements.txt
|
||||
- [ ] Première migration Alembic : `alembic revision --autogenerate -m "init"`
|
||||
- [ ] Ajouter service `worker` dans `docker-compose.yml` (image backend + command: celery worker) — attention, c'est la config prod
|
||||
- [ ] Ajouter `python-nmap` dans `requirements.txt`
|
||||
- [ ] Première migration Alembic : `alembic -c backend/alembic.ini revision --autogenerate -m "init"`
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user