This commit is contained in:
Bastien COIGNOUX
2026-05-03 22:17:48 +02:00
parent bd325fe456
commit 7b3e50ff29
5 changed files with 390 additions and 0 deletions

116
Makefile Normal file
View File

@ -0,0 +1,116 @@
# ============================================================
# Makefile — Raccourcis pour le projet mb-app
# Usage : make <commande>
# ============================================================
.PHONY: help dev dev-stop prod prod-stop logs status setup-nas deploy
# Affiche l'aide
help:
@echo ""
@echo " Développement local"
@echo " ─────────────────────────────────────────"
@echo " make dev → Lance PocketBase en local"
@echo " make dev-stop → Arrête le conteneur local"
@echo " make logs → Logs PocketBase en temps réel"
@echo " make status → État des conteneurs"
@echo ""
@echo " Production NAS"
@echo " ─────────────────────────────────────────"
@echo " make prod → Lance la stack complète NAS"
@echo " make prod-stop → Arrête tout"
@echo " make deploy → git pull + restart (sur le NAS)"
@echo ""
@echo " Setup"
@echo " ─────────────────────────────────────────"
@echo " make setup → Crée les dossiers manquants"
@echo " make ssl → Obtient le certificat SSL (1ère fois)"
@echo " make renew-ssl → Renouvelle le certificat SSL"
@echo ""
# ── DÉVELOPPEMENT LOCAL ──────────────────────────────────────
dev:
@echo "🚀 Lancement PocketBase en local..."
@[ -f .env.local ] || (echo "❌ Fichier .env.local manquant ! Copier .env.example" && exit 1)
docker compose -f docker/docker-compose.dev.yml up -d
@echo "✅ PocketBase : http://localhost:8090"
@echo "✅ Admin : http://localhost:8090/_/"
dev-stop:
docker compose -f docker/docker-compose.dev.yml down
dev-reset:
@echo "⚠️ Supprime les données locales de dev !"
@read -p "Confirmer ? (oui/non) : " c; [ "$$c" = "oui" ] || exit 1
docker compose -f docker/docker-compose.dev.yml down
rm -rf pocketbase/pb_data
@echo "✅ Données supprimées"
# ── PRODUCTION NAS ───────────────────────────────────────────
prod:
@echo "🚀 Lancement stack production..."
@[ -f .env.production ] || (echo "❌ Fichier .env.production manquant !" && exit 1)
docker compose -f docker/docker-compose.prod.yml up -d
@echo "✅ Stack lancée"
prod-stop:
docker compose -f docker/docker-compose.prod.yml down
deploy:
@echo "📦 Déploiement en cours..."
git pull origin main
docker compose -f docker/docker-compose.prod.yml restart pocketbase
@echo "✅ Déployé"
# ── LOGS & STATUS ────────────────────────────────────────────
logs:
docker compose -f docker/docker-compose.dev.yml logs -f pocketbase
logs-prod:
docker compose -f docker/docker-compose.prod.yml logs -f pocketbase
status:
docker compose -f docker/docker-compose.dev.yml ps
# ── SETUP ────────────────────────────────────────────────────
setup:
@echo "📁 Création des dossiers..."
mkdir -p pocketbase/pb_data
mkdir -p pocketbase/pb_hooks
mkdir -p pocketbase/pb_migrations
@[ -f .env.local ] || cp .env.example .env.local
@echo "✅ Structure prête"
@echo "👉 Éditer .env.local avec votre clé Anthropic"
setup-nas:
@echo "📁 Création des dossiers sur le NAS..."
mkdir -p /volume1/docker/mb-app/pb_data
mkdir -p /volume1/docker/mb-app/ssl
mkdir -p /volume1/docker/mb-app/duckdns
@[ -f .env.production ] || cp .env.example .env.production
@echo "✅ Dossiers NAS créés"
@echo "👉 Éditer .env.production"
ssl:
@echo "🔐 Obtention certificat SSL..."
@[ -f .env.production ] || (echo "❌ .env.production manquant" && exit 1)
@source .env.production && docker run --rm \
-v /volume1/docker/mb-app/ssl:/etc/letsencrypt \
-v /tmp/certbot-webroot:/var/www/certbot \
-p 80:80 \
certbot/certbot certonly --standalone \
-d $$DUCKDNS_SUBDOMAINS.duckdns.org \
--non-interactive --agree-tos \
--email admin@example.com
@echo "✅ Certificat obtenu"
renew-ssl:
docker run --rm \
-v /volume1/docker/mb-app/ssl:/etc/letsencrypt \
certbot/certbot renew --quiet
docker compose -f docker/docker-compose.prod.yml restart nginx
@echo "✅ Certificat renouvelé"

163
README.md Normal file
View File

@ -0,0 +1,163 @@
# mb-app — Application Marchand de Biens
Application mobile et web pour la gestion quotidienne d'une activité de marchand de biens immobiliers.
**Stack :** React Native (Expo) + PocketBase (self-hosted sur NAS Synology) + IA Claude
---
## Démarrage rapide
### Prérequis
- Docker Desktop (Mac/Windows) ou Docker Engine (Linux/NAS)
- Node.js 18+
- Un compte DuckDNS (gratuit) pour l'accès distant
### 1. Cloner le projet
```bash
git clone https://github.com/VOUS/mb-app.git
cd mb-app
```
### 2. Setup initial
```bash
make setup
# → Crée les dossiers nécessaires
# → Copie .env.example en .env.local
```
Éditer `.env.local` :
```
EXPO_PUBLIC_PB_URL=http://localhost:8090
ANTHROPIC_API_KEY=sk-ant-VOTRE_CLE
```
### 3. Lancer en développement
```bash
# Terminal 1 — Backend PocketBase
make dev
# → PocketBase sur http://localhost:8090
# → Admin sur http://localhost:8090/_/
# Terminal 2 — App Expo
cd app
npm install
npx expo start
```
**Première fois :** Aller sur http://localhost:8090/_/ → créer le compte admin
→ Settings → Import collections → coller le contenu de `pocketbase/pb_collections.json`
---
## Déploiement sur le NAS Synology
### 1. Cloner sur le NAS
```bash
# Se connecter en SSH au NAS
ssh admin@IP_DU_NAS
# Cloner le projet
git clone https://github.com/VOUS/mb-app.git /volume1/docker/mb-app
cd /volume1/docker/mb-app
```
### 2. Configurer l'environnement production
```bash
make setup-nas
# Puis éditer .env.production :
nano .env.production
```
```
EXPO_PUBLIC_PB_URL=https://mon-sous-domaine.duckdns.org
ANTHROPIC_API_KEY=sk-ant-VOTRE_CLE
DUCKDNS_SUBDOMAINS=mon-sous-domaine
DUCKDNS_TOKEN=VOTRE_TOKEN_DUCKDNS
```
### 3. Ouvrir les ports sur votre box internet
- Port 80 → IP du NAS, port 80
- Port 443 → IP du NAS, port 443
### 4. Obtenir le certificat SSL
```bash
make ssl
```
### 5. Lancer la stack
```bash
make prod
```
### Mettre à jour après un git push
```bash
# Sur le NAS :
make deploy
# → git pull + restart PocketBase (les hooks sont rechargés)
```
---
## Workflow de développement
```
[Local] Coder + tester
git add . && git commit -m "feat: module visites"
git push origin main
[NAS] make deploy
```
Les **données** (`pb_data/`) restent sur chaque machine et ne sont jamais dans Git.
Le **code** (hooks, migrations, app) est versionné et déployé via Git.
---
## Structure du projet
```
mb-app/
├── app/ ← Code React Native (Expo Router)
├── pocketbase/
│ ├── pb_hooks/ ← Hooks JS côté serveur (IA, etc.)
│ ├── pb_migrations/ ← Migrations auto PocketBase
│ └── pb_collections.json ← Schéma des collections
├── docker/
│ ├── docker-compose.dev.yml
│ ├── docker-compose.prod.yml
│ └── nginx.prod.conf
├── .cursorrules ← Contexte pour Cursor AI
├── AGENTS.md ← Suivi des sessions de développement
└── Makefile ← Raccourcis commandes
```
---
## Commandes utiles
| Commande | Description |
|---|---|
| `make dev` | Lance PocketBase en local |
| `make dev-stop` | Arrête le dev |
| `make logs` | Logs en temps réel |
| `make prod` | Lance la stack NAS |
| `make deploy` | git pull + redémarre (sur NAS) |
| `make renew-ssl` | Renouvelle le certificat SSL |
---
## Backup des données
Les données PocketBase sont dans `pb_data/` (exclu du Git).
Configurer une tâche Synology Hyper Backup sur `/volume1/docker/mb-app/pb_data/`.

32
docker-compose.dev.yml Normal file
View File

@ -0,0 +1,32 @@
version: '3.8'
# ============================================================
# DÉVELOPPEMENT LOCAL — docker compose -f docker/docker-compose.dev.yml up
# PocketBase accessible sur http://localhost:8090
# Admin PocketBase : http://localhost:8090/_/
# ============================================================
services:
pocketbase:
image: ghcr.io/muchobien/pocketbase:latest
container_name: mb-pocketbase-dev
restart: unless-stopped
ports:
- "8090:8090" # Accès direct sans Nginx en dev
volumes:
# Données locales (dans .gitignore)
- ../pocketbase/pb_data:/pb/pb_data
# Hooks JS versionnés dans Git ✅
- ../pocketbase/pb_hooks:/pb/pb_hooks
# Migrations versionnées dans Git ✅
- ../pocketbase/pb_migrations:/pb/pb_migrations
env_file:
- ../.env.local # Clé Anthropic en local
environment:
- TZ=Europe/Paris
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8090/api/health"]
interval: 15s
timeout: 5s
retries: 3

59
docker-compose.prod.yml Normal file
View File

@ -0,0 +1,59 @@
version: '3.8'
# ============================================================
# PRODUCTION NAS — docker compose -f docker/docker-compose.prod.yml up -d
# Accessible sur https://VOTRE_SOUS_DOMAINE.duckdns.org
# ============================================================
services:
pocketbase:
image: ghcr.io/muchobien/pocketbase:latest
container_name: mb-pocketbase
restart: unless-stopped
# Pas de port exposé directement : Nginx fait le proxy
expose:
- "8090"
volumes:
# Données persistantes NAS (dans .gitignore)
- /volume1/docker/mb-app/pb_data:/pb/pb_data
# Hooks et migrations versionnés dans Git ✅
- ../pocketbase/pb_hooks:/pb/pb_hooks
- ../pocketbase/pb_migrations:/pb/pb_migrations
env_file:
- ../.env.production
environment:
- TZ=Europe/Paris
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8090/api/health"]
interval: 30s
timeout: 10s
retries: 3
nginx:
image: nginx:alpine
container_name: mb-nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.prod.conf:/etc/nginx/nginx.conf:ro
- /volume1/docker/mb-app/ssl:/etc/nginx/ssl:ro
depends_on:
pocketbase:
condition: service_healthy
duckdns:
image: lscr.io/linuxserver/duckdns:latest
container_name: mb-duckdns
restart: unless-stopped
environment:
- TZ=Europe/Paris
- SUBDOMAINS=${DUCKDNS_SUBDOMAINS}
- TOKEN=${DUCKDNS_TOKEN}
- LOG_FILE=true
env_file:
- ../.env.production
volumes:
- /volume1/docker/mb-app/duckdns:/config

20
env.example.txt Normal file
View File

@ -0,0 +1,20 @@
# ============================================================
# .env.example — Copier en .env.local (dev) ou .env.production
# NE PAS mettre de vraies valeurs dans ce fichier
# ============================================================
# ── URL PocketBase ───────────────────────────────────────────
# Dev local :
EXPO_PUBLIC_PB_URL=http://localhost:8090
# Production NAS :
# EXPO_PUBLIC_PB_URL=https://VOTRE_SOUS_DOMAINE.duckdns.org
# ── PocketBase (côté serveur Docker) ─────────────────────────
ANTHROPIC_API_KEY=sk-ant-VOTRE_CLE_ICI
# ── DuckDNS (production uniquement) ──────────────────────────
DUCKDNS_SUBDOMAINS=VOTRE_SOUS_DOMAINE
DUCKDNS_TOKEN=VOTRE_TOKEN_DUCKDNS
# ── Expo (optionnel, pour EAS Build) ─────────────────────────
# EXPO_TOKEN=