Initial commit — GeoOptions Intelligence Cockpit v2.0
Stack: FastAPI + React/TypeScript + SQLite + GPT-4o Features: Radar géopolitique, Marchés, Régime Macro, Journal de Bord MTM, Rapport IA, Super Contexte (base de raisonnement évolutive), Boucle feedback IA. Deploy: Docker + docker-compose + nginx pour openfin.open-squared.tech Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
8
deploy/.env.example
Normal file
8
deploy/.env.example
Normal file
@@ -0,0 +1,8 @@
|
||||
# Copier ce fichier en .env et remplir les valeurs
|
||||
# cp .env.example .env
|
||||
|
||||
# Clé OpenAI pour GPT-4o (obligatoire pour les fonctionnalités IA)
|
||||
OPENAI_API_KEY=sk-...
|
||||
|
||||
# (Optionnel) Forcer la timezone du backend
|
||||
# TZ=Europe/Paris
|
||||
49
deploy/docker-compose.yml
Normal file
49
deploy/docker-compose.yml
Normal file
@@ -0,0 +1,49 @@
|
||||
services:
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: ../backend
|
||||
dockerfile: Dockerfile
|
||||
environment:
|
||||
- OPENAI_API_KEY=${OPENAI_API_KEY:-}
|
||||
volumes:
|
||||
- db_data:/app/data
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- internal
|
||||
healthcheck:
|
||||
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/api/health')"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
frontend:
|
||||
build:
|
||||
context: ../frontend
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- internal
|
||||
|
||||
nginx:
|
||||
image: nginx:1.27-alpine
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
- ./nginx/certs:/etc/letsencrypt:ro
|
||||
- ./nginx/certbot-webroot:/var/www/certbot:ro
|
||||
depends_on:
|
||||
- backend
|
||||
- frontend
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- internal
|
||||
|
||||
volumes:
|
||||
db_data:
|
||||
|
||||
networks:
|
||||
internal:
|
||||
driver: bridge
|
||||
25
deploy/nginx/nginx-http-init.conf
Normal file
25
deploy/nginx/nginx-http-init.conf
Normal file
@@ -0,0 +1,25 @@
|
||||
# Config temporaire HTTP-only — utilisée uniquement lors du premier setup
|
||||
# pour permettre à Certbot d'obtenir le certificat SSL.
|
||||
# Remplacée automatiquement par setup-vps.sh après obtention du cert.
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name openfin.open-squared.tech;
|
||||
|
||||
# Challenge ACME pour Let's Encrypt
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/certbot;
|
||||
}
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://backend:8000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_read_timeout 120s;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://frontend:80;
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
}
|
||||
61
deploy/nginx/nginx-https.conf
Normal file
61
deploy/nginx/nginx-https.conf
Normal file
@@ -0,0 +1,61 @@
|
||||
# Config HTTPS définitive avec SSL Let's Encrypt
|
||||
# Copiée vers nginx.conf par setup-vps.sh après obtention du certificat.
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name openfin.open-squared.tech;
|
||||
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/certbot;
|
||||
}
|
||||
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
http2 on;
|
||||
server_name openfin.open-squared.tech;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/openfin.open-squared.tech/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/openfin.open-squared.tech/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
|
||||
# Sécurité headers
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header X-Frame-Options SAMEORIGIN always;
|
||||
add_header X-Content-Type-Options nosniff always;
|
||||
|
||||
# API FastAPI
|
||||
location /api/ {
|
||||
proxy_pass http://backend:8000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_read_timeout 120s;
|
||||
proxy_buffering off;
|
||||
}
|
||||
|
||||
# Swagger docs FastAPI
|
||||
location /docs {
|
||||
proxy_pass http://backend:8000;
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
location /openapi.json {
|
||||
proxy_pass http://backend:8000;
|
||||
proxy_set_header Host $host;
|
||||
}
|
||||
|
||||
# Frontend React SPA
|
||||
location / {
|
||||
proxy_pass http://frontend:80;
|
||||
proxy_set_header Host $host;
|
||||
proxy_read_timeout 30s;
|
||||
}
|
||||
}
|
||||
93
deploy/setup-vps.sh
Normal file
93
deploy/setup-vps.sh
Normal file
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/env bash
|
||||
# setup-vps.sh — Premier déploiement complet sur VPS Ubuntu/Debian
|
||||
# Usage : bash setup-vps.sh
|
||||
set -euo pipefail
|
||||
|
||||
DOMAIN="openfin.open-squared.tech"
|
||||
EMAIL="opensquaredgeneva@gmail.com"
|
||||
REPO="https://gitea.open-squared.tech/admin/OpenFin.git"
|
||||
DEPLOY_DIR="/opt/openfin"
|
||||
|
||||
GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; NC='\033[0m'
|
||||
info() { echo -e "${GREEN}[INFO]${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
||||
abort() { echo -e "${RED}[ERR]${NC} $*"; exit 1; }
|
||||
|
||||
# ── 1. Docker ─────────────────────────────────────────────────────────────────
|
||||
info "Vérification de Docker..."
|
||||
if ! command -v docker &>/dev/null; then
|
||||
info "Installation de Docker..."
|
||||
curl -fsSL https://get.docker.com | sh
|
||||
systemctl enable docker
|
||||
systemctl start docker
|
||||
fi
|
||||
if ! docker compose version &>/dev/null; then
|
||||
info "Installation du plugin docker compose..."
|
||||
apt-get install -y docker-compose-plugin
|
||||
fi
|
||||
info "Docker $(docker --version | cut -d' ' -f3) OK"
|
||||
|
||||
# ── 2. Clone du repo ──────────────────────────────────────────────────────────
|
||||
if [ -d "$DEPLOY_DIR" ]; then
|
||||
warn "Le dossier $DEPLOY_DIR existe — pull de la dernière version..."
|
||||
git -C "$DEPLOY_DIR" pull
|
||||
else
|
||||
info "Clone du repo dans $DEPLOY_DIR..."
|
||||
git clone "$REPO" "$DEPLOY_DIR"
|
||||
fi
|
||||
cd "$DEPLOY_DIR/deploy"
|
||||
|
||||
# ── 3. Fichier .env ───────────────────────────────────────────────────────────
|
||||
if [ ! -f .env ]; then
|
||||
cp .env.example .env
|
||||
warn "Fichier .env créé. Remplis ta clé OpenAI :"
|
||||
warn " nano $DEPLOY_DIR/deploy/.env"
|
||||
warn "Puis relance ce script."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if grep -q "sk-\.\.\." .env; then
|
||||
abort "La clé OPENAI_API_KEY n'est pas configurée dans .env"
|
||||
fi
|
||||
|
||||
# ── 4. Créer les dossiers nécessaires ─────────────────────────────────────────
|
||||
mkdir -p nginx/certs nginx/certbot-webroot
|
||||
|
||||
# ── 5. Premier démarrage HTTP pour obtenir le cert SSL ────────────────────────
|
||||
info "Démarrage initial en HTTP pour la vérification Let's Encrypt..."
|
||||
cp nginx/nginx-http-init.conf nginx/nginx.conf
|
||||
docker compose up -d --build
|
||||
|
||||
info "Attente que le frontend soit prêt..."
|
||||
sleep 15
|
||||
|
||||
# ── 6. Certificat SSL Let's Encrypt ──────────────────────────────────────────
|
||||
info "Obtention du certificat SSL pour $DOMAIN..."
|
||||
docker run --rm \
|
||||
-v "$DEPLOY_DIR/deploy/nginx/certs:/etc/letsencrypt" \
|
||||
-v "$DEPLOY_DIR/deploy/nginx/certbot-webroot:/var/www/certbot" \
|
||||
certbot/certbot certonly \
|
||||
--webroot \
|
||||
--webroot-path=/var/www/certbot \
|
||||
-d "$DOMAIN" \
|
||||
--email "$EMAIL" \
|
||||
--agree-tos \
|
||||
--non-interactive \
|
||||
--expand
|
||||
|
||||
# ── 7. Passage en HTTPS ───────────────────────────────────────────────────────
|
||||
info "Activation de la config HTTPS..."
|
||||
cp nginx/nginx-https.conf nginx/nginx.conf
|
||||
docker compose restart nginx
|
||||
|
||||
# ── 8. Renouvellement automatique du cert (cron mensuel) ─────────────────────
|
||||
CRON_CMD="0 3 1 * * docker run --rm -v $DEPLOY_DIR/deploy/nginx/certs:/etc/letsencrypt -v $DEPLOY_DIR/deploy/nginx/certbot-webroot:/var/www/certbot certbot/certbot renew --quiet && docker compose -f $DEPLOY_DIR/deploy/docker-compose.yml restart nginx"
|
||||
(crontab -l 2>/dev/null | grep -v certbot; echo "$CRON_CMD") | crontab -
|
||||
info "Renouvellement SSL automatique configuré (1er de chaque mois à 3h)"
|
||||
|
||||
# ── 9. Résumé ─────────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
info "=== Déploiement terminé ==="
|
||||
info "Cockpit disponible sur : https://$DOMAIN"
|
||||
info "Statut des containers :"
|
||||
docker compose ps
|
||||
21
deploy/update.sh
Normal file
21
deploy/update.sh
Normal file
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
# update.sh — Mise à jour du cockpit depuis le repo Gitea
|
||||
# Usage : bash update.sh
|
||||
set -euo pipefail
|
||||
|
||||
DEPLOY_DIR="/opt/openfin"
|
||||
cd "$DEPLOY_DIR"
|
||||
|
||||
echo "[UPDATE] Pull de la dernière version..."
|
||||
git pull
|
||||
|
||||
cd deploy
|
||||
|
||||
echo "[UPDATE] Rebuild et redémarrage des containers..."
|
||||
docker compose up -d --build
|
||||
|
||||
echo "[UPDATE] Nettoyage des images orphelines..."
|
||||
docker image prune -f
|
||||
|
||||
echo "[UPDATE] Done. Statut :"
|
||||
docker compose ps
|
||||
Reference in New Issue
Block a user