Déploiement
GISPulse se déploie en local, sur un VPS ou en cluster. Ce guide couvre les configurations de production.
Local (développement)
pip install "gispulse[all]"
gispulse portal --host 127.0.0.1 --port 8001Docker Compose — développement
Stack avec hot-reload pour le développement :
# docker-compose.yml
services:
postgis:
image: postgis/postgis:16-3.4
ports:
- "5433:5432"
environment:
POSTGRES_USER: gispulse
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: gispulse
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U gispulse"]
interval: 10s
timeout: 5s
retries: 5
gispulse-api:
build: .
ports:
- "8001:8001"
environment:
- GISPULSE_ENGINE=gpkg
- GISPULSE_STORAGE=sqlite
volumes:
# Hot-reload des modules Python
- ./core:/app/core
- ./capabilities:/app/capabilities
- ./rules:/app/rules
- ./orchestration:/app/orchestration
- ./persistence:/app/persistence
- ./adapters:/app/adapters
command: uvicorn adapters.http.app:create_app --host 0.0.0.0 --port 8001 --reload --factory
depends_on:
postgis:
condition: service_healthy
portal:
image: node:20-alpine
ports:
- "8080:5173"
working_dir: /app
volumes:
- ./portal:/app
- portal_node_modules:/app/node_modules
command: sh -c "npm install && npm run dev -- --host 0.0.0.0"
volumes:
pgdata:
gispulse_data:
portal_node_modules:docker compose up -dDocker Compose — production
Le répertoire deploy/ contient une stack production complète :
deploy/
├── docker-compose.prod.yml # Stack complète
├── caddy/
│ └── Caddyfile # Reverse proxy + TLS automatique
├── prometheus/
│ └── prometheus.yml # Métriques
└── grafana/
└── provisioning/ # DashboardsServices production
# deploy/docker-compose.prod.yml (simplifié)
services:
postgis:
image: postgis/postgis:16-3.4
deploy:
resources:
limits: { memory: 2G, cpus: "2" }
volumes:
- pgdata:/var/lib/postgresql/data
- ./docker/init.sql:/docker-entrypoint-initdb.d/init.sql
gispulse-api:
build: .
ports:
- "8001:8001"
environment:
- GISPULSE_ENGINE=postgis
- GISPULSE_DSN=postgresql://gispulse:${POSTGRES_PASSWORD}@postgis:5432/gispulse
- GISPULSE_ENV=production
- GISPULSE_API_KEYS=${API_KEYS}
- GISPULSE_CORS_ORIGINS=https://${DOMAIN}
deploy:
resources:
limits: { memory: 4G, cpus: "4" }
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8001/health"]
interval: 30s
caddy:
image: caddy:2-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./caddy/Caddyfile:/etc/caddy/Caddyfile
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus:/prometheus
command: --storage.tsdb.retention.time=30d
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
volumes:
- grafana:/var/lib/grafana
pg-backup:
image: prodrigestivill/postgres-backup-local
environment:
- POSTGRES_HOST=postgis
- POSTGRES_USER=gispulse
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- SCHEDULE=@daily
- BACKUP_KEEP_DAYS=30
volumes:
- ./backups:/backupsCaddyfile
gispulse.example.com {
reverse_proxy gispulse-api:8001
encode gzip
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Content-Type-Options nosniff
X-Frame-Options DENY
}
}Lancement :
cd deploy/
cp .env.example .env
# Éditer .env avec vos valeurs
docker compose -f docker-compose.prod.yml up -dCaddy obtient automatiquement un certificat Let's Encrypt pour votre domaine.
Terraform (IaC)
Le répertoire deploy/ inclut des modules Terraform pour DigitalOcean et Hetzner :
deploy/
├── digitalocean/ # Droplet + cloud-init
├── hetzner/ # Bare metal
└── modules/
└── gispulse-stack/ # Module réutilisable (compose + Caddy + monitoring)cd deploy/digitalocean
terraform init
terraform apply -var="domain=gispulse.example.com"Dockerfile — build multi-stage
Le Dockerfile utilise un build en 3 étapes :
- portal-build (node:20-slim) — Build React portal
- viewer-build (node:20-slim) — Build deck.gl viewer
- Python runtime (python:3.12-slim) — GDAL + Python + frontends
# Build local
make docker-build
# Point d'entrée
uvicorn adapters.http.app:create_app --host 0.0.0.0 --port 8001 --factoryVariables d'environnement
Moteur et stockage
GISPULSE_ENGINE=gpkg # gpkg | duckdb | postgis | hybrid
GISPULSE_STORAGE=sqlite # sqlite | memory
GISPULSE_DSN=postgresql://... # DSN PostGIS (mode postgis/hybrid)
GISPULSE_ENV=production # development | productionAuthentification et sécurité
GISPULSE_API_KEYS=sk-gp-key1,sk-gp-key2 # Clés API (virgule-séparées)
GISPULSE_CORS_ORIGINS=https://example.com # Origines CORS autoriséesTier et licence
GISPULSE_TIER=community # community | pro | enterprise
GISPULSE_LICENSE_KEY=... # Requis pour pro/enterpriseOIDC / SSO (Enterprise)
GISPULSE_OIDC_ISSUER=https://auth.example.com
GISPULSE_OIDC_CLIENT_ID=gispulse
GISPULSE_OIDC_CLIENT_SECRET=secret
GISPULSE_OIDC_REDIRECT_URI=https://gispulse.example.com/auth/callback
GISPULSE_SESSION_SECRET=... # Requis en production avec OIDCServices optionnels
GISPULSE_REDIS_URL=redis://localhost:6379
GISPULSE_RATE_LIMIT_STORAGE=redis://localhost:6379 # ou memory://
GISPULSE_POSTGIS_DSN=... # DSN spécifique pour les requêtes SQL portalPortal frontend
VITE_API_URL=http://localhost:8001 # URL API pour le frontendSécurisation
Middleware de production
En mode GISPULSE_ENV=production, le ProductionAuthMiddleware est activé automatiquement et force l'authentification sur tous les endpoints.
Firewall / réseau
- Exposez uniquement le port 443 (Caddy) publiquement
- PostGIS ne doit pas être accessible depuis l'extérieur
- Utilisez des variables d'environnement pour tous les secrets
- DSN PostGIS uniquement en variable d'environnement (
GISPULSE_DSN), jamais dans les requêtes
Protection SSRF
Les endpoints d'upload et d'import OGC vérifient les URLs contre une blocklist d'IPs privées.
Rate Limiting
300 requêtes/minute par défaut. Redis-backed en production, in-memory en développement.
Monitoring (Pro)
La stack production inclut Prometheus + Grafana :
- Prometheus : métriques d'exécution des jobs, latences API, état PostGIS
- Grafana : dashboards préconfigurés sur le port 3000
Métriques exposées :
gispulse_job_duration_seconds— Durée d'exécution des jobsgispulse_jobs_total— Compteur de jobsgispulse_jobs_failed— Compteur d'échecsgispulse_features_processed— Features traitées
Mise à jour
docker compose pull
docker compose up -dLes données PostGIS sont dans un volume Docker — pas de perte lors de la mise à jour.
Checklist avant production
- [ ]
GISPULSE_ENV=productiondéfini - [ ]
GISPULSE_API_KEYSconfiguré avec des clés fortes - [ ]
GISPULSE_CORS_ORIGINSrestreint à votre domaine - [ ]
GISPULSE_SESSION_SECRETdéfini (si OIDC) - [ ]
GISPULSE_DSNuniquement en variable d'environnement - [ ] Sauvegardes PostGIS configurées (pg-backup)
- [ ] HTTPS via Caddy actif
- [ ]
gispulse doctorretourne tout vert - [ ] Monitoring Prometheus actif
- [ ] Redis configuré pour le rate limiting en production