docs Configuración
Configuración
La configuración a nivel de instancia se hace mediante variables de entorno en .env.
Dónde vive la configuración
Una instalación de producción lee /opt/deploykit/.env. El instalador lo genera por ti; en una instalación manual, parte de .env.production. docker-compose.prod.yml construye algunas variables por sí mismo — DATABASE_URL, REDIS_URL, WEB_URL, NODE_ENV=production, API_PORT=4000 y COMPOSE_ROOT — y esos valores prevalecen sobre cualquier cosa que pongas en .env. El resto de variables se leen del archivo .env que se copia en la imagen de la API cuando se construye.
Aplicar los cambios: tras editar .env, reconstruye y recrea los contenedores — cd /opt/deploykit && docker compose -f docker-compose.prod.yml up -d --build. Un simple deploykit restart no recoge los nuevos valores.
Variables de entorno obligatorias
# Panel domain and Let's Encrypt email (production)
DOMAIN=panel.yourdomain.com
ACME_EMAIL=you@example.com
# PostgreSQL — production builds DATABASE_URL from these
DB_USER=deploykit
DB_PASSWORD=<openssl rand -hex 24>
DB_NAME=deploykit
# Redis password — required in production since v0.6.0.
# Hex only: it is embedded in redis://:<password>@redis:6379
REDIS_PASSWORD=<openssl rand -hex 32>
# JWT signing secrets (openssl rand -base64 32)
JWT_SECRET=<your-jwt-secret>
JWT_REFRESH_SECRET=<your-refresh-secret>
# AES-256-GCM key for secrets at rest (openssl rand -hex 32)
ENCRYPTION_KEY=<64-character-hex-string>
# Development / external services only — production sets these itself
DATABASE_URL=postgresql://user:password@localhost:5432/deploykit
REDIS_URL=redis://localhost:6379Con NODE_ENV=production la API se niega a arrancar si JWT_SECRET, JWT_REFRESH_SECRET o ENCRYPTION_KEY falta, tiene menos de 32 caracteres o todavía contiene un marcador CHANGE_ME; en desarrollo solo muestra un aviso.
Advertencia: no cambies nunca ENCRYPTION_KEY una vez que existan datos. Las variables de entorno, los tokens de origen, las claves SSH y otros secretos almacenados se cifran con ella y se vuelven ilegibles con una clave nueva. Guarda una copia de tu .env en un lugar seguro.
URL pública (WEB_URL)
WEB_URL es la URL pública de tu instancia. Los orígenes de CORS y Socket.IO, los enlaces que DeployKit pone en los estados de commit de GitHub, y las URLs de webhook y de redirección registradas en una GitHub App se construyen a partir de ella. DeployKit nunca la deriva de la cabecera Host de la petición, que controla el cliente.
En producción no la defines: el archivo Compose la deriva como https://${DOMAIN}, porque Traefik sirve el dashboard y la API en el mismo host. En desarrollo vale por defecto http://localhost:5173; para registrar una GitHub App desde una máquina de desarrollo, apúntala a un túnel público (cloudflared, ngrok): la URL del webhook de la App debe ser accesible para GitHub.
Cambiar DOMAIN: una GitHub App conserva la URL de webhook con la que se registró. Si cambias DOMAIN después de registrar una, desconecta y registra la App de nuevo (o edita sus URLs en GitHub), o los pushes dejarán de lanzar despliegues.
Variables de entorno opcionales
# Default HMAC secret for GitHub/GitLab webhooks and the generic webhook
# (X-Webhook-Token). Without it, GitLab webhooks — and GitHub webhooks for
# apps with no per-app secret and no GitHub App — are rejected.
# Optional for GitHub once a GitHub App is registered.
WEBHOOK_SECRET=<openssl rand -base64 32>
# Set to "true" ONLY when every request reaches the API through a trusted
# proxy that sets X-Forwarded-For. Otherwise the header is ignored, so
# clients cannot spoof their IP in rate limits and audit logs. Default: false
TRUST_PROXY=false
# "production" enables HSTS and the fail-fast secret check (set by the prod compose)
NODE_ENV=development
# API port (default 3001; production fixes it to 4000 behind Traefik)
API_PORT=3001
# Docker socket path — auto-detected; override only if non-standard
DOCKER_SOCKET=/var/run/docker.sock
# Retention
AUDIT_RETENTION_DAYS=90 # audit log entries (pruned daily at 04:00)
LOG_RETENTION_DAYS=7 # persistent container logs
METRICS_RAW_RETENTION_HOURS=48 # 1-minute metric samples
METRICS_HISTORY_RETENTION_DAYS=90 # 1-hour metric rollups
LOG_BUFFER_MAX=5000 # log lines buffered before writing; excess is droppedStacks de Compose y plantillas
# Where stack directories live. Must be bind-mounted from the host at the
# SAME absolute path (production fixes it to /var/lib/deploykit/compose).
COMPOSE_ROOT=/var/lib/deploykit/compose
# Wildcard domain pointing at this host, used for template hostnames when
# you don't supply one (*.apps.yourdomain.com). The only option that can
# get a real Let's Encrypt certificate.
TEMPLATES_BASE_DOMAIN=apps.yourdomain.com
# Fallback without a wildcard domain: this host's public IPv4. Templates get
# <name>-<rand>.<ip>.sslip.io hostnames — no DNS setup, but plain HTTP only.
PUBLIC_IP=203.0.113.10
# Template registry. Point it at a fork or private mirror to publish your own
# blueprints. If unreachable, the catalogue bundled in the image is used.
TEMPLATES_REGISTRY_URL=https://raw.githubusercontent.com/deploykithq/deploykit-templates/masterServidores de juegos
# Host port range DeployKit suggests free ports from when a game's default
# port is taken. Players connect straight to these ports — open them in your
# provider's firewall.
GAME_PORT_RANGE=20000-40000
# Largest file the game server Files tab accepts as an upload, in bytes (256 MiB)
GAME_UPLOAD_MAX_BYTES=268435456Las API keys de CurseForge y Steam no son variables de entorno: un administrador las define en Settings → Game mods, donde se almacenan cifradas. Del mismo modo, la GitHub App se registra desde Settings → GitHub App — las antiguas variables GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET ya no se usan.
Análisis de vulnerabilidades (Trivy)
# Scan built images by default. Only the exact value "true" enables it;
# unset means off. Each application can override this in its General tab.
SCAN_ENABLED=true
TRIVY_IMAGE=aquasec/trivy:latest # scanner image
TRIVY_CACHE_VOLUME=deploykit-trivy-cache # volume caching the vulnerability DB
TRIVY_TIMEOUT_SECONDS=300 # per-scan timeoutLos análisis son informativos —los resultados se registran en el despliegue y nunca lo bloquean— y solo se ejecutan para aplicaciones del servidor local.
Configuración de seguridad
DeployKit incluye funciones de seguridad integradas que se configuran automáticamente:
- Rate limiting — Global: 200 req/min por IP en /trpc y /api; login y registro: 10 req/min; webhooks: 120 req/min
- Tamaño de petición — 1 MiB por cuerpo de petición, excepto la importación de configuración (4 MiB)
- Cifrado — Variables de entorno, tokens, claves SSH y credenciales de integraciones cifrados con AES-256-GCM
- Cabeceras de seguridad — X-Content-Type-Options, X-Frame-Options, Referrer-Policy, una CSP estricta y HSTS en producción
- Ocultación de secretos — Los logs de build eliminan automáticamente tokens, contraseñas y claves
- CORS — Solo se permite WEB_URL, tanto para la API como para Socket.IO
- Aislamiento — Redis requiere contraseña, Traefik lee Docker a través de un proxy de solo lectura y cada contenedor de producción se ejecuta con no-new-privileges
Entorno de desarrollo
# Requires Node.js 20+, pnpm 9+ and Docker
pnpm install
cp .env.example .env # fill in the secrets
# Start PostgreSQL, Redis and Traefik
docker compose up -d
# Apply migrations, then start API + Web in dev mode
pnpm db:migrate
pnpm dev
# Or start individually
pnpm dev:api # API on :3001
pnpm dev:web # Web on :5173
# Other commands
pnpm db:studio # Open Drizzle Studio GUI
pnpm build # Production build
pnpm lint # Type check all packages
pnpm clean # Remove dist/ directoriesNo ejecutes pnpm db:generate ni drizzle-kit push: el generador compara contra una base desactualizada y produce una migración rota. Las nuevas migraciones se escriben a mano en SQL.