[{"data":1,"prerenderedAt":156},["ShallowReactive",2],{"seo-verification":3,"blog-deployer-fastapi-vps-ma-fr":6,"promo-bar-likely":155},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-deployer-fastapi-vps-ma-fr",{"id":9,"slug":10,"slugs":11,"title":15,"excerpt":16,"readTime":17,"views":18,"isPinned":19,"noindex":19,"publishedAt":20,"updatedAt":21,"category":22,"categories":27,"featuredImage":29,"bgImage":30,"posterImage":31,"relatedSolution":32,"intro":34,"sections":35,"ctaTitle":96,"ctaBody":97,"ctaButton":98,"ctaUrl":99,"relatedPosts":100},45,"deployer-fastapi-vps",{"fr":10,"en":12,"ar":13,"es":14},"deploy-a-fastapi-application-on-a-vps","نشر-تطبيق-fastapi-على-vps","desplegar-una-aplicacion-fastapi-en-un-vps","Déployer FastAPI sur un VPS : guide complet production","Déployez FastAPI sur un VPS avec Docker multi-stage, Gunicorn, PostgreSQL, CI\u002FCD GitHub Actions et monitoring. Guide Python production 2025.",10,4,false,"2026-05-06T00:00:00+00:00","2026-11-04T16:30:25+00:00",{"id":18,"name":23,"slug":24,"color":25,"icon":26},"Développement","developpement","bg-warning\u002F10 text-warning","dev",[28],{"id":18,"name":23,"slug":24,"color":25,"icon":26},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fdeployer-fastapi-vps-poster.svg",{"categorySlug":24,"appSlug":33},"fastapi","FastAPI s'est imposé comme le framework Python de choix pour les API rapides et typées, grâce à son support natif de l'asynchrone et de la documentation OpenAPI. Le déployer sur votre propre VPS vous donne la main sur le nombre de workers, le WebSocket et la latence, sans plafond imposé par un service managé. Ce guide couvre l'intégralité de la mise en production : conteneurisation multi-stage, base de données avec migrations Alembic, CI\u002FCD automatisé et dépannage des erreurs fréquentes.",[36,40,50,53,78,81,84,87,90,93],{"type":37,"title":38,"body":39},"h2","Pourquoi self-héberger FastAPI sur un VPS ?","FastAPI tire toute sa performance du modèle ASGI asynchrone : connexions WebSocket persistantes, streaming de réponses et appels concurrents vers d'autres services. Les plateformes serverless coupent souvent les connexions longues et facturent chaque requête, ce qui pénalise une API à fort débit ou temps réel. Sur un VPS, vous lancez Uvicorn piloté par Gunicorn avec autant de workers que de cœurs, vous gardez les connexions ouvertes aussi longtemps que nécessaire et vous placez Nginx en frontal pour le TLS et le buffering. Vous contrôlez aussi le pool de connexions vers PostgreSQL et le cache Redis, deux leviers essentiels quand la charge monte — le débit réellement tenu se mesure sur votre propre trafic.",{"type":41,"title":42,"items":43},"ul","Bénéfices concrets d'un FastAPI auto-hébergé",[44,45,46,47,48,49],"WebSockets et Server-Sent Events sans coupure de connexion ni timeout imposé.","Réglage fin des workers Uvicorn\u002FGunicorn selon le nombre de cœurs du VPS.","Aucun démarrage à froid (cold start) : le processus reste debout entre deux requêtes.","Documentation Swagger et ReDoc servies en interne, accessibles ou protégées à votre guise.","Intégration directe avec un pool asynchrone PostgreSQL (asyncpg) et Redis.","Coût fixe quel que soit le nombre d'appels API, idéal pour un backend de production.",{"type":37,"title":51,"body":52},"Prérequis matériels, logiciels et versions","Une API FastAPI est légère : 1 vCPU et 1 Go de RAM suffisent pour démarrer, mais visez **2 vCPU et 2 Go** dès que vous ajoutez une base de données et un cache sur le même VPS. Pour une charge soutenue (>100 req\u002Fs), comptez 4 vCPU et 4 Go minimum.\n\nVersions recommandées en 2025 : **Python 3.11+** (3.12 pour les performances maximales), **FastAPI 0.115+** (support complet de Pydantic v2 et des annotations Python 3.10+), **Uvicorn 0.30+** (correctifs de stabilité event loop). Installez via Docker avec l'image `python:3.12-slim` pour un démarrage rapide, ou depuis le dépôt officiel avec `pip install fastapi[standard]>=0.115 uvicorn[standard]>=0.30 gunicorn>=22.0`.\n\nDu côté infrastructure : Docker Engine 24+, Docker Compose v2 (plugin intégré, `docker compose`), Nginx 1.24+ en reverse proxy, et un domaine pointé vers le VPS pour le certificat TLS. Ubuntu 22.04\u002F24.04 LTS est la base recommandée ; Debian 12 fonctionne également.",{"type":54,"title":55,"steps":56},"steps","Déployer FastAPI étape par étape",[57,60,63,66,69,72,75],{"title":58,"body":59},"Initialiser le VPS et l'application","Connectez-vous en SSH, installez Docker, clonez votre dépôt et créez un `.env` depuis le modèle `.env.example` fourni avec votre projet. Ce fichier doit contenir au minimum :\n\n```bash\nDATABASE_URL=postgresql+asyncpg:\u002F\u002Fuser:password@db:5432\u002Fappdb\nREDIS_URL=redis:\u002F\u002Fredis:6379\u002F0\nSECRET_KEY=changeme-in-production\nCORS_ORIGINS=[\"https:\u002F\u002Fyourdomain.com\"]\nENVIRONMENT=production\n```\n\nVérifiez que votre point d'entrée expose bien `app = FastAPI()` et que l'application charge sa configuration depuis les variables d'environnement (jamais en dur).",{"title":61,"body":62},"Conteneuriser avec un Dockerfile multi-stage","Le multi-stage sépare l'étape de build (compilation des dépendances, génération de wheels) de l'image de runtime, ce qui réduit la taille finale de 60 à 80 % et élimine les outils de compilation de la surface d'attaque :\n\n```dockerfile\n# ── Stage 1 : build ──────────────────────────────────────\nFROM python:3.12-slim AS builder\nWORKDIR \u002Fapp\nCOPY requirements.txt .\nRUN pip install --upgrade pip && \\\n    pip wheel --no-cache-dir --wheel-dir \u002Fwheels -r requirements.txt\n\n# ── Stage 2 : runtime ────────────────────────────────────\nFROM python:3.12-slim\nWORKDIR \u002Fapp\nCOPY --from=builder \u002Fwheels \u002Fwheels\nRUN pip install --no-cache-dir \u002Fwheels\u002F* && rm -rf \u002Fwheels\nCOPY . .\nEXPOSE 8000\nCMD [\"gunicorn\", \"main:app\", \"-k\", \"uvicorn.workers.UvicornWorker\",\n     \"--bind\", \"0.0.0.0:8000\", \"--workers\", \"4\",\n     \"--timeout\", \"120\", \"--keep-alive\", \"5\"]\n```\n\nAjoutez un endpoint `\u002Fhealth` dans votre application pour les healthchecks :\n\n```python\n@app.get(\"\u002Fhealth\")\nasync def health():\n    return {\"status\": \"ok\"}\n```",{"title":64,"body":65},"Régler les workers Gunicorn de façon optimale","La formule `(2 × cœurs) + 1` est le point de départ pour des workers **CPU-bound**. FastAPI étant ASGI\u002Fasynchrone, chaque worker gère plusieurs requêtes en concurrence via l'event loop — la règle devient plutôt `cœurs + 1` à `2 × cœurs` pour des charges **I\u002FO-bound** classiques (appels DB, HTTP externes).\n\nPassez la valeur via une variable d'environnement pour l'ajuster sans reconstruire l'image :\n\n```bash\nWEB_CONCURRENCY=4  # dans .env ou docker-compose.yml\n```\n\n```dockerfile\nCMD [\"gunicorn\", \"main:app\", \"-k\", \"uvicorn.workers.UvicornWorker\",\n     \"--bind\", \"0.0.0.0:8000\",\n     \"--workers\", \"${WEB_CONCURRENCY:-4}\"]\n```\n\nSous forte charge, surveillez l'utilisation CPU par worker (`docker stats`) et le nombre de requêtes en attente dans les logs Gunicorn (`--access-logfile -`) avant d'augmenter le nombre de workers.",{"title":67,"body":68},"Orchestrer les services avec Docker Compose","Dans `docker-compose.yml`, déclarez le service `api`, un service `db` PostgreSQL et un service `redis`. Utilisez `depends_on` avec `condition: service_healthy` pour que l'API attende que la base soit prête avant de démarrer :\n\n```yaml\nservices:\n  api:\n    build: .\n    env_file: .env\n    ports: [\"8000:8000\"]\n    depends_on:\n      db:\n        condition: service_healthy\n      redis:\n        condition: service_started\n    healthcheck:\n      test: [\"CMD\", \"curl\", \"-f\", \"http:\u002F\u002Flocalhost:8000\u002Fhealth\"]\n      interval: 30s\n      retries: 3\n\n  db:\n    image: postgres:16-alpine\n    environment:\n      POSTGRES_USER: user\n      POSTGRES_PASSWORD: password\n      POSTGRES_DB: appdb\n    volumes: [\"pgdata:\u002Fvar\u002Flib\u002Fpostgresql\u002Fdata\"]\n    healthcheck:\n      test: [\"CMD\", \"pg_isready\", \"-U\", \"user\"]\n      interval: 10s\n      retries: 5\n\n  redis:\n    image: redis:7-alpine\n\nvolumes:\n  pgdata:\n```",{"title":70,"body":71},"Placer Nginx en reverse proxy","Configurez un bloc serveur avec `proxy_pass http:\u002F\u002Fapi:8000` et, pour les WebSockets, ajoutez les headers nécessaires. Désactivez le buffering pour le streaming si nécessaire :\n\n```nginx\nserver {\n    listen 443 ssl;\n    server_name api.yourdomain.com;\n\n    location \u002F {\n        proxy_pass http:\u002F\u002Fapi:8000;\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection \"upgrade\";\n        proxy_buffering off;  # pour le streaming\n    }\n}\n```",{"title":73,"body":74},"Sécuriser avec un certificat TLS","Obtenez un certificat Let's Encrypt via Certbot ou un conteneur companion, forcez le HTTPS et redirigez le HTTP. Pensez à restreindre l'accès à `\u002Fdocs` et `\u002Fopenapi.json` en production si l'API n'est pas publique.",{"title":76,"body":77},"Lancer et tester","Démarrez avec `docker compose up -d`, vérifiez la santé via le endpoint `\u002Fhealth` que vous aurez ajouté, et testez la documentation interactive. Surveillez les logs Uvicorn pour ajuster le nombre de workers sous charge réelle.",{"type":79,"body":80},"tip","Pour les tâches longues (envoi d'emails, traitement d'images, appels externes lents), ne bloquez pas l'event loop : déportez-les vers un worker en arrière-plan avec `BackgroundTasks` pour les cas simples, ou vers Celery\u002FARQ avec Redis pour les traitements lourds. Une API qui répond vite et délègue le travail asynchrone reste réactive même sous forte concurrence.",{"type":37,"title":82,"body":83},"Base de données et migrations","Pour les applications FastAPI en production, **asyncpg** combiné à **SQLAlchemy 2.x** (mode async) offre un excellent équilibre entre performances et maintenabilité. Configurez le pool de connexions en fonction de la charge attendue :\n\n```python\nfrom sqlalchemy.ext.asyncio import create_async_engine, AsyncSession\nfrom sqlalchemy.orm import sessionmaker\n\nengine = create_async_engine(\n    DATABASE_URL,\n    pool_size=10,        # connexions persistantes\n    max_overflow=20,     # connexions supplémentaires sous pic\n    pool_timeout=30,     # secondes avant erreur\n    pool_recycle=1800,   # recycle après 30 min pour éviter les timeouts PostgreSQL\n    echo=False,\n)\n\nAsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)\n```\n\nInjectez la session dans vos routes via une dépendance FastAPI :\n\n```python\nasync def get_db():\n    async with AsyncSessionLocal() as session:\n        yield session\n```\n\nPour les migrations de schéma, **Alembic** est l'outil standard. Initialisez-le dans votre projet (`alembic init migrations`) puis configurez `alembic.ini` pour pointer sur votre `DATABASE_URL`. Les commandes essentielles :\n\n```bash\n# Générer une migration depuis vos modèles SQLAlchemy\nalembic revision --autogenerate -m \"add_users_table\"\n\n# Appliquer les migrations en attente\nalembic upgrade head\n\n# Vérifier l'état courant\nalembic current\n```\n\nEn production, exécutez `alembic upgrade head` **avant** de démarrer l'API — ajoutez-le comme commande d'init dans votre `docker-compose.yml` ou dans un script de démarrage séparé. Ne lancez jamais les migrations depuis plusieurs instances simultanément.",{"type":37,"title":85,"body":86},"CI\u002FCD et déploiements automatisés","Un pipeline GitHub Actions simple suffit pour la majorité des projets FastAPI : build de l'image, push vers un registry, et déploiement sur le VPS par SSH avec zero-downtime.\n\n```yaml\n# .github\u002Fworkflows\u002Fdeploy.yml\nname: Deploy FastAPI\non:\n  push:\n    branches: [main]\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n\n      - name: Build & push Docker image\n        run: |\n          docker build -t ghcr.io\u002F${{ github.repository }}:${{ github.sha }} .\n          echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin\n          docker push ghcr.io\u002F${{ github.repository }}:${{ github.sha }}\n\n      - name: Deploy via SSH\n        uses: appleboy\u002Fssh-action@v1\n        with:\n          host: ${{ secrets.VPS_HOST }}\n          username: deploy\n          key: ${{ secrets.VPS_SSH_KEY }}\n          script: |\n            cd \u002Fopt\u002Fmyapp\n            export IMAGE_TAG=${{ github.sha }}\n            docker compose pull api\n            docker compose up -d --no-deps api\n            docker compose exec api alembic upgrade head\n```\n\nL'option `--no-deps` sur `docker compose up` redémarre uniquement le conteneur `api` sans toucher `db` ni `redis`, ce qui garantit un **zero-downtime** pour les services tiers. Docker Compose démarre le nouveau conteneur avant d'arrêter l'ancien (rolling update interne).\n\nPour des déploiements plus robustes avec rollback instantané, envisagez de tagger vos images avec le SHA du commit et de conserver les 3 dernières versions localement — `docker image prune` avec `--filter until=72h` nettoie les anciennes images automatiquement.",{"type":37,"title":88,"body":89},"Monitoring et logs","Accédez aux logs Uvicorn directement via Docker :\n\n```bash\n# Logs en temps réel\ndocker compose logs -f api\n\n# 100 dernières lignes\ndocker compose logs --tail=100 api\n```\n\nPour des logs structurés en JSON (indexables par un agrégateur comme Loki ou Elasticsearch), remplacez le logger Python standard par **loguru** ou **structlog** :\n\n```python\nfrom loguru import logger\nimport sys\n\nlogger.remove()\nlogger.add(sys.stdout, format=\"{time} {level} {message}\", serialize=True)\n\n@app.middleware(\"http\")\nasync def log_requests(request, call_next):\n    logger.info(\"request\", method=request.method, url=str(request.url))\n    response = await call_next(request)\n    logger.info(\"response\", status=response.status_code)\n    return response\n```\n\nPour exposer des métriques Prometheus, ajoutez un endpoint `\u002Fmetrics` basique avec **prometheus-fastapi-instrumentator** :\n\n```python\nfrom prometheus_fastapi_instrumentator import Instrumentator\n\nInstrumentator().instrument(app).expose(app, endpoint=\"\u002Fmetrics\")\n```\n\nRestrictez ensuite `\u002Fmetrics` à votre réseau interne depuis Nginx (directive `allow 127.0.0.1; deny all;`) pour éviter d'exposer les métriques publiquement.",{"type":37,"title":91,"body":92},"Dépannage des erreurs fréquentes","**Worker timed out (pid XXXXX)** — Gunicorn tue un worker qui n'a pas répondu dans le délai `--timeout`. Causes fréquentes : une route synchrone (`def` au lieu de `async def`) bloque l'event loop, ou une opération bloquante (lecture fichier, appel réseau) s'exécute sans `asyncio.run_in_executor`. Augmenter `--timeout` masque le problème ; la bonne correction est de rendre la route asynchrone ou de déléguer le travail bloquant.\n\n**Address already in use (port 8000)** — Un processus Gunicorn précédent est encore actif. En Docker : `docker compose down` puis `docker compose up -d` force la recréation du conteneur et libère le port. Vérifiez avec `docker ps -a` qu'aucun conteneur zombie ne tourne.\n\n**502 Bad Gateway après un déploiement** — Nginx a transmis la requête à l'API pendant son redémarrage. Attendez 10-15 secondes que le healthcheck Docker confirme que le nouveau conteneur est `healthy` avant de considérer le déploiement terminé. Ajoutez `proxy_read_timeout 60;` dans Nginx pour absorber les démarrages lents.\n\n**CORS en production : `No 'Access-Control-Allow-Origin' header`** — FastAPI sert les origines déclarées dans `CORSMiddleware`. Vérifiez que `CORS_ORIGINS` dans votre `.env` contient exactement l'URL du frontend (protocole + domaine + port si non standard, sans slash final). Une valeur `[\"*\"]` fonctionne en développement mais ne doit jamais partir en production.\n\n**Connexion DB refusée au démarrage** — L'API démarre avant que PostgreSQL soit prêt. Le `depends_on` avec `condition: service_healthy` dans Docker Compose résout ce cas. En Kubernetes ou sur des déploiements sans Compose, implémentez une boucle de retry avec backoff exponentiel dans le code de démarrage de l'application.",{"type":37,"title":94,"body":95},"Déployer FastAPI en un clic depuis le Marketplace ServOrbit","Le Marketplace ServOrbit propose un template FastAPI Stack préconfiguré : Python 3.12, Uvicorn, Gunicorn, Nginx et PostgreSQL 16 sont installés automatiquement sur votre VPS dès la commande. Pas de session SSH pour l'installation de base — vous arrivez directement à l'étape de cloner votre dépôt et de lancer Uvicorn. La fiche marketplace contient les spécifications exactes, les cas d'usage et un guide de première connexion.","Déployez votre FastAPI Stack en quelques minutes","Le template FastAPI Stack ServOrbit installe Python 3.12, Uvicorn, Gunicorn, Nginx et PostgreSQL 16 sur votre VPS. Lancez votre API immédiatement.","Déployer FastAPI Stack","\u002Fapplications\u002Fdeveloppement\u002Ffastapi",[101,119,137],{"id":102,"slug":103,"slugs":104,"title":108,"excerpt":109,"readTime":18,"views":110,"isPinned":19,"noindex":19,"publishedAt":111,"updatedAt":112,"category":113,"categories":114,"featuredImage":29,"bgImage":30,"posterImage":116,"relatedSolution":117},5,"deployer-laravel-vps",{"fr":103,"en":105,"ar":106,"es":107},"deploying-laravel-on-a-vps-a-production-guide","نشر-laravel-على-خادم-vps-دليل-الإنتاج","desplegar-laravel-en-un-vps","Déployer Laravel sur un VPS : guide production","Passez Laravel en production sur VPS : PHP, workers, cache, base de données, reverse proxy et HTTPS proprement configurés.",1,"2026-02-09T00:00:00+00:00","2026-09-07T11:26:10+00:00",{"id":18,"name":23,"slug":24,"color":25,"icon":26},[115],{"id":18,"name":23,"slug":24,"color":25,"icon":26},"\u002Fblog\u002Fcovers\u002Fdeployer-laravel-vps-poster.svg",{"categorySlug":26,"appSlug":118},"laravel-stack",{"id":120,"slug":121,"slugs":122,"title":126,"excerpt":127,"readTime":128,"views":110,"isPinned":19,"noindex":19,"publishedAt":129,"updatedAt":130,"category":131,"categories":132,"featuredImage":29,"bgImage":30,"posterImage":134,"relatedSolution":135},43,"deployer-nodejs-vps",{"fr":121,"en":123,"ar":124,"es":125},"deploy-a-nodejs-application-on-a-vps","نشر-تطبيق-nodejs-على-vps","desplegar-una-aplicacion-nodejs-en-un-vps","Déployer une application Node.js sur un VPS","Déployez une application Node.js en production sur un VPS : PM2, reverse proxy Nginx, SSL Let's Encrypt et démarrage automatique au boot.",8,"2026-05-08T00:00:00+00:00","2026-11-08T01:13:12+00:00",{"id":18,"name":23,"slug":24,"color":25,"icon":26},[133],{"id":18,"name":23,"slug":24,"color":25,"icon":26},"\u002Fblog\u002Fcovers\u002Fdeployer-nodejs-vps-poster.svg",{"categorySlug":24,"appSlug":136},"nodejs-stack",{"id":138,"slug":139,"slugs":140,"title":144,"excerpt":145,"readTime":146,"views":147,"isPinned":19,"noindex":19,"publishedAt":148,"updatedAt":21,"category":149,"categories":150,"featuredImage":29,"bgImage":30,"posterImage":152,"relatedSolution":153},44,"deployer-django-vps",{"fr":139,"en":141,"ar":142,"es":143},"deploy-a-django-application-on-a-vps","نشر-تطبيق-django-على-vps","desplegar-una-aplicacion-django-en-un-vps","Déployer une application Django sur un VPS","Déployez Django sur un VPS : Gunicorn, Nginx, PostgreSQL, Docker et SSL. Guide complet pour développeurs Python qui veulent self-héberger.",3,7,"2026-05-07T00:00:00+00:00",{"id":18,"name":23,"slug":24,"color":25,"icon":26},[151],{"id":18,"name":23,"slug":24,"color":25,"icon":26},"\u002Fblog\u002Fcovers\u002Fdeployer-django-vps-poster.svg",{"categorySlug":24,"appSlug":154},"django",true,1794270696827]