[{"data":1,"prerenderedAt":157},["ShallowReactive",2],{"seo-verification":3,"blog-desplegar-una-aplicacion-fastapi-en-un-vps-ma-es":6,"promo-bar-likely":156},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"key":7,"data":8},"blog-desplegar-una-aplicacion-fastapi-en-un-vps-ma-es",{"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":35,"sections":36,"ctaTitle":97,"ctaBody":98,"ctaButton":99,"ctaUrl":100,"relatedPosts":101},45,"desplegar-una-aplicacion-fastapi-en-un-vps",{"fr":12,"en":13,"ar":14,"es":10},"deployer-fastapi-vps","deploy-a-fastapi-application-on-a-vps","نشر-تطبيق-fastapi-على-vps","Desplegar FastAPI en un VPS: guía completa de producción","Despliegue FastAPI en un VPS con Docker multistage, Gunicorn, PostgreSQL, CI\u002FCD con GitHub Actions y monitoreo. Guía completa Python producción 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},"Desarrollo","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":33,"appSlug":34},"desarrollo","fastapi","FastAPI se ha impuesto como el framework Python de referencia para las API rápidas y tipadas, gracias a su soporte nativo de la asincronía y de la documentación OpenAPI. Desplegarlo en su propio VPS le da el control sobre el número de workers, los WebSocket y la latencia, sin techo impuesto por un servicio gestionado. Esta guía cubre la totalidad de la puesta en producción: contenedorización multistage, base de datos con migraciones Alembic, CI\u002FCD automatizado y resolución de errores frecuentes.",[37,41,51,54,79,82,85,88,91,94],{"type":38,"title":39,"body":40},"h2","¿Por qué autoalojar FastAPI en un VPS?","FastAPI obtiene todo su rendimiento del modelo ASGI asíncrono: conexiones WebSocket persistentes, streaming de respuestas y llamadas concurrentes a otros servicios. Las plataformas serverless suelen cortar las conexiones largas y facturan cada petición, lo que penaliza a una API de alto caudal o en tiempo real. En un VPS, usted lanza Uvicorn gobernado por Gunicorn con tantos workers como núcleos, mantiene las conexiones abiertas todo el tiempo que haga falta y coloca Nginx al frente para el TLS y el buffering. También controla el pool de conexiones hacia PostgreSQL y la caché Redis, dos palancas esenciales cuando sube la carga — el caudal realmente sostenido se mide sobre su propio tráfico.",{"type":42,"title":43,"items":44},"ul","Beneficios concretos de un FastAPI autoalojado",[45,46,47,48,49,50],"WebSockets y Server-Sent Events sin cortes de conexión ni timeout impuesto.","Ajuste fino de los workers Uvicorn\u002FGunicorn según el número de núcleos del VPS.","Ningún arranque en frío (cold start): el proceso permanece activo entre dos peticiones.","Documentación Swagger y ReDoc servida internamente, accesible o protegida a su conveniencia.","Integración directa con un pool asíncrono de PostgreSQL (asyncpg) y Redis.","Coste fijo sea cual sea el número de llamadas a la API, ideal para un backend de producción.",{"type":38,"title":52,"body":53},"Requisitos de hardware, software y versiones","Una API FastAPI es ligera: 1 vCPU y 1 GB de RAM bastan para empezar, pero apunte a **2 vCPU y 2 GB** en cuanto añada una base de datos y una caché en el mismo VPS. Para una carga sostenida (>100 req\u002Fs), prevea al menos 4 vCPU y 4 GB.\n\nVersiones recomendadas en 2025: **Python 3.11+** (3.12 para el máximo rendimiento), **FastAPI 0.115+** (soporte completo de Pydantic v2 y anotaciones Python 3.10+), **Uvicorn 0.30+** (correcciones de estabilidad del event loop). Instale con Docker usando la imagen `python:3.12-slim`, o desde el repositorio oficial con `pip install fastapi[standard]>=0.115 uvicorn[standard]>=0.30 gunicorn>=22.0`.\n\nEn cuanto a infraestructura: Docker Engine 24+, Docker Compose v2 (plugin integrado, `docker compose`), Nginx 1.24+ como reverse proxy, y un dominio apuntado al VPS para el certificado TLS. Ubuntu 22.04\u002F24.04 LTS es la base recomendada; Debian 12 también funciona.",{"type":55,"title":56,"steps":57},"steps","Desplegar FastAPI paso a paso",[58,61,64,67,70,73,76],{"title":59,"body":60},"Inicializar el VPS y la aplicación","Conéctese por SSH, instale Docker, clone su repositorio y cree un `.env` desde la plantilla `.env.example` incluida en su proyecto. Este archivo debe contener como mínimo:\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\nCompruebe que su punto de entrada expone efectivamente `app = FastAPI()` y que la aplicación carga su configuración desde variables de entorno (nunca codificadas en duro).",{"title":62,"body":63},"Contenedorizar con un Dockerfile multistage","El multistage separa la fase de build (compilación de dependencias, generación de wheels) de la imagen de runtime, reduciendo el tamaño final entre un 60 y un 80% y eliminando las herramientas de compilación de la superficie de ataque:\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\nAñada un endpoint `\u002Fhealth` en su aplicación para los healthchecks:\n\n```python\n@app.get(\"\u002Fhealth\")\nasync def health():\n    return {\"status\": \"ok\"}\n```",{"title":65,"body":66},"Ajustar los workers de Gunicorn de forma óptima","La fórmula `(2 × núcleos) + 1` es el punto de partida para workers **CPU-bound**. Como FastAPI es ASGI\u002Fasíncrono, cada worker gestiona múltiples peticiones de forma concurrente mediante el event loop — para cargas típicas **I\u002FO-bound** (llamadas a DB, HTTP externas), el rango `núcleos + 1` a `2 × núcleos` es más adecuado.\n\nPase el valor mediante una variable de entorno para ajustarlo sin reconstruir la imagen:\n\n```bash\nWEB_CONCURRENCY=4  # en .env o 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\nBajo carga elevada, supervise el uso de CPU por worker (`docker stats`) y el número de peticiones en espera en los logs de Gunicorn (`--access-logfile -`) antes de aumentar el número de workers.",{"title":68,"body":69},"Orquestar los servicios con Docker Compose","En `docker-compose.yml`, declare el servicio `api`, un servicio `db` PostgreSQL y un servicio `redis`. Utilice `depends_on` con `condition: service_healthy` para que la API espere a que la base de datos esté lista antes de arrancar:\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":71,"body":72},"Colocar Nginx como reverse proxy","Configure un bloque de servidor con `proxy_pass http:\u002F\u002Fapi:8000` y, para los WebSockets, añada las cabeceras necesarias. Desactive el buffering para el streaming si es necesario:\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;\n    }\n}\n```",{"title":74,"body":75},"Asegurar con un certificado TLS","Obtenga un certificado Let's Encrypt mediante Certbot o un contenedor companion, fuerce el HTTPS y redirija el HTTP. Recuerde restringir el acceso a `\u002Fdocs` y `\u002Fopenapi.json` en producción si la API no es pública.",{"title":77,"body":78},"Lanzar y probar","Arranque con `docker compose up -d`, compruebe el estado mediante el endpoint `\u002Fhealth` que habrá añadido, y pruebe la documentación interactiva. Vigile los registros de Uvicorn para ajustar el número de workers bajo carga real.",{"type":80,"body":81},"tip","Para las tareas largas (envío de correos, procesamiento de imágenes, llamadas externas lentas), no bloquee el event loop: derívelas a un worker en segundo plano con `BackgroundTasks` para los casos sencillos, o a Celery\u002FARQ con Redis para los procesamientos pesados. Una API que responde rápido y delega el trabajo asíncrono se mantiene reactiva incluso con alta concurrencia.",{"type":38,"title":83,"body":84},"Base de datos y migraciones","Para las aplicaciones FastAPI en producción, **asyncpg** combinado con **SQLAlchemy 2.x** (modo async) ofrece el mejor equilibrio entre rendimiento y mantenibilidad. Configure el pool de conexiones según la carga esperada:\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,        # conexiones persistentes\n    max_overflow=20,     # conexiones adicionales bajo pico\n    pool_timeout=30,     # segundos antes de error\n    pool_recycle=1800,   # reciclado tras 30 min para evitar timeouts PostgreSQL\n    echo=False,\n)\n\nAsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)\n```\n\nInyecte la sesión en sus rutas mediante una dependencia FastAPI:\n\n```python\nasync def get_db():\n    async with AsyncSessionLocal() as session:\n        yield session\n```\n\nPara las migraciones de esquema, **Alembic** es la herramienta estándar. Inicialícelo en su proyecto (`alembic init migrations`) y configure `alembic.ini` para apuntar a su `DATABASE_URL`. Los comandos esenciales:\n\n```bash\n# Generar una migración desde sus modelos SQLAlchemy\nalembic revision --autogenerate -m \"add_users_table\"\n\n# Aplicar las migraciones pendientes\nalembic upgrade head\n\n# Verificar el estado actual\nalembic current\n```\n\nEn producción, ejecute `alembic upgrade head` **antes** de arrancar la API — añádalo como comando de inicio en su `docker-compose.yml` o en un script de arranque separado. Nunca ejecute las migraciones desde múltiples instancias simultáneamente.",{"type":38,"title":86,"body":87},"CI\u002FCD y despliegues automatizados","Un pipeline sencillo de GitHub Actions es suficiente para la mayoría de los proyectos FastAPI: build de la imagen, push a un registry y despliegue en el VPS por SSH con 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\nLa opción `--no-deps` en `docker compose up` reinicia únicamente el contenedor `api` sin tocar `db` ni `redis`, lo que garantiza el **zero-downtime** para los servicios auxiliares. Para despliegues más robustos con rollback instantáneo, etiquete sus imágenes con el SHA del commit y conserve las últimas 3 versiones localmente.",{"type":38,"title":89,"body":90},"Monitoreo y logs","Acceda a los logs de Uvicorn directamente desde Docker:\n\n```bash\n# Logs en tiempo real\ndocker compose logs -f api\n\n# Últimas 100 líneas\ndocker compose logs --tail=100 api\n```\n\nPara logs estructurados en JSON (indexables por un agregador como Loki o Elasticsearch), sustituya el logger estándar de Python por **loguru** o **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\nPara exponer métricas Prometheus, añada un endpoint `\u002Fmetrics` con **prometheus-fastapi-instrumentator**:\n\n```python\nfrom prometheus_fastapi_instrumentator import Instrumentator\n\nInstrumentator().instrument(app).expose(app, endpoint=\"\u002Fmetrics\")\n```\n\nRestrinja luego `\u002Fmetrics` a su red interna desde Nginx (`allow 127.0.0.1; deny all;`) para evitar exponer las métricas públicamente.",{"type":38,"title":92,"body":93},"Resolución de errores frecuentes","**Worker timed out (pid XXXXX)** — Gunicorn mata un worker que no respondió en el plazo `--timeout`. Causas frecuentes: una ruta síncrona (`def` en lugar de `async def`) bloquea el event loop, o una operación bloqueante (lectura de archivo, llamada de red) se ejecuta sin `asyncio.run_in_executor`. Aumentar `--timeout` enmascara el problema; la corrección correcta es hacer la ruta asíncrona o delegar el trabajo bloqueante.\n\n**Address already in use (puerto 8000)** — Un proceso Gunicorn anterior aún está activo. En Docker: `docker compose down` y luego `docker compose up -d` fuerza la recreación del contenedor y libera el puerto. Compruebe con `docker ps -a` que ningún contenedor zombie esté en marcha.\n\n**502 Bad Gateway tras un despliegue** — Nginx redirigió la petición a la API durante su reinicio. Espere 10-15 segundos a que el healthcheck de Docker confirme que el nuevo contenedor está `healthy` antes de considerar el despliegue completado. Añada `proxy_read_timeout 60;` en Nginx para absorber los arranques lentos.\n\n**CORS en producción: `No 'Access-Control-Allow-Origin' header`** — FastAPI sirve los orígenes declarados en `CORSMiddleware`. Verifique que `CORS_ORIGINS` en su `.env` contiene exactamente la URL del frontend (protocolo + dominio + puerto si no es estándar, sin barra al final). Un valor `[\"*\"]` funciona en desarrollo pero nunca debe ir a producción.\n\n**Conexión DB rechazada al arrancar** — La API arranca antes de que PostgreSQL esté lista. El `depends_on` con `condition: service_healthy` en Docker Compose resuelve este caso. En Kubernetes o en despliegues sin Compose, implemente un bucle de reintentos con backoff exponencial en el código de inicio de la aplicación.",{"type":38,"title":95,"body":96},"Desplegar FastAPI con un clic desde el Marketplace ServOrbit","El Marketplace ServOrbit ofrece una plantilla FastAPI Stack preconfigurada: Python 3.12, Uvicorn, Gunicorn, Nginx y PostgreSQL 16 se instalan automáticamente en su VPS desde el pedido. Sin sesión SSH para la instalación de base — llega directamente al paso de clonar su repositorio y de lanzar Uvicorn. La ficha del marketplace contiene las especificaciones exactas, los casos de uso y una guía de primera conexión.","Despliegue su FastAPI Stack en unos minutos","La plantilla FastAPI Stack de ServOrbit instala Python 3.12, Uvicorn, Gunicorn, Nginx y PostgreSQL 16 en su VPS. Lance su API de inmediato.","Desplegar FastAPI Stack","\u002Fapplications\u002Fdesarrollo\u002Ffastapi",[102,120,138],{"id":103,"slug":104,"slugs":105,"title":109,"excerpt":110,"readTime":18,"views":111,"isPinned":19,"noindex":19,"publishedAt":112,"updatedAt":113,"category":114,"categories":115,"featuredImage":29,"bgImage":30,"posterImage":117,"relatedSolution":118},5,"desplegar-laravel-en-un-vps",{"fr":106,"en":107,"ar":108,"es":104},"deployer-laravel-vps","deploying-laravel-on-a-vps-a-production-guide","نشر-laravel-على-خادم-vps-دليل-الإنتاج","Desplegar Laravel en un VPS: guía de producción","Ponga Laravel en producción en un VPS: PHP, workers, caché, base de datos, reverse proxy y HTTPS bien configurados.",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},[116],{"id":18,"name":23,"slug":24,"color":25,"icon":26},"\u002Fblog\u002Fcovers\u002Fdeployer-laravel-vps-poster.svg",{"categorySlug":26,"appSlug":119},"laravel-stack",{"id":121,"slug":122,"slugs":123,"title":127,"excerpt":128,"readTime":129,"views":111,"isPinned":19,"noindex":19,"publishedAt":130,"updatedAt":131,"category":132,"categories":133,"featuredImage":29,"bgImage":30,"posterImage":135,"relatedSolution":136},43,"desplegar-una-aplicacion-nodejs-en-un-vps",{"fr":124,"en":125,"ar":126,"es":122},"deployer-nodejs-vps","deploy-a-nodejs-application-on-a-vps","نشر-تطبيق-nodejs-على-vps","Desplegar una aplicación Node.js en un VPS","Despliegue una aplicación Node.js en producción en un VPS: PM2, reverse proxy Nginx, SSL Let's Encrypt y arranque automático con el sistema.",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},[134],{"id":18,"name":23,"slug":24,"color":25,"icon":26},"\u002Fblog\u002Fcovers\u002Fdeployer-nodejs-vps-poster.svg",{"categorySlug":33,"appSlug":137},"nodejs-stack",{"id":139,"slug":140,"slugs":141,"title":145,"excerpt":146,"readTime":147,"views":148,"isPinned":19,"noindex":19,"publishedAt":149,"updatedAt":21,"category":150,"categories":151,"featuredImage":29,"bgImage":30,"posterImage":153,"relatedSolution":154},44,"desplegar-una-aplicacion-django-en-un-vps",{"fr":142,"en":143,"ar":144,"es":140},"deployer-django-vps","deploy-a-django-application-on-a-vps","نشر-تطبيق-django-على-vps","Desplegar una aplicación Django en un VPS","Despliegue Django en un VPS: Gunicorn, Nginx, PostgreSQL, Docker y SSL. Guía completa para desarrolladores Python que quieren autoalojar.",3,7,"2026-05-07T00:00:00+00:00",{"id":18,"name":23,"slug":24,"color":25,"icon":26},[152],{"id":18,"name":23,"slug":24,"color":25,"icon":26},"\u002Fblog\u002Fcovers\u002Fdeployer-django-vps-poster.svg",{"categorySlug":33,"appSlug":155},"django",true,1794270594805]