Files
Panama/user/agents/skills/infisical-self-host/references/docker-deployment.md
T
Gabriel Brown 89761a7da3 Keep the personal half of the desktop in one place, and ask before installing it
Agent instructions, skills, SSH host aliases and expansion triggers are worth
having identical on every machine one person owns, and belong in none of the
shared configuration. They live in user/ now, with a manifest saying where each
piece goes and a link-user stage that puts it there.

That stage does nothing unless the machine said yes. Somebody who clones Panama
to try the desktop keeps their own ~/.claude/CLAUDE.md exactly where it was;
the question names the destinations and defaults to no. Anything displaced goes
to config/old rather than being deleted.

~/.claude/CLAUDE.md and ~/.codex/AGENTS.md were byte-identical copies of one
file, which is the drift this exists to prevent.

Also adds the vitals toggles for the battery and Claude usage readouts, which
had preferences and no way to reach them.
2026-08-22 08:54:43 -04:00

8.2 KiB

Docker Deployment Guide

Deploy Infisical using Docker or Docker Compose for flexible, containerized self-hosted environments.

Docker Standalone Container

Quick Start

  1. Pull the image:
docker pull infisical/infisical:latest
  1. Create a .env file with required configuration:
ENCRYPTION_KEY=$(openssl rand -hex 16)
AUTH_SECRET=$(openssl rand -base64 32)
DB_CONNECTION_URI="postgresql://user:[email protected]:5432/infisical"
REDIS_URL="redis://redis.example.com:6379"
SITE_URL="https://secrets.example.com"
SMTP_HOST="smtp.example.com"
SMTP_PORT="587"
SMTP_USERNAME="[email protected]"
SMTP_PASSWORD="password"
SMTP_FROM_ADDRESS="[email protected]"
  1. Run the container:
docker run -d \
  --name infisical \
  --env-file .env \
  -p 8080:8080 \
  infisical/infisical:latest
  1. Verify the container is running:
curl http://localhost:8080/api/status

Image Variants

Standard Image

docker pull infisical/infisical:latest
docker pull infisical/infisical:v0.110.0  # Specific version

FIPS 140-2 Compliant Image

Use the FIPS image for regulated environments requiring FIPS compliance:

docker pull infisical/infisical:latest-fips

When using the FIPS image, set:

FIPS_ENABLED=true
NODE_OPTIONS="--max-old-space-size=8192 --force-fips"

Docker Compose Deployment (Production)

The repository includes docker-compose.prod.yml for complete production setups with PostgreSQL and Redis.

Basic docker-compose.yml

Create a docker-compose.yml file:

version: '3.8'

services:
  postgres:
    image: postgres:14-alpine
    container_name: infisical-postgres
    environment:
      POSTGRES_USER: infisical
      POSTGRES_PASSWORD: infisical_db_password
      POSTGRES_DB: infisical
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - infisical-network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U infisical"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    container_name: infisical-redis
    volumes:
      - redis_data:/data
    networks:
      - infisical-network
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  infisical:
    image: infisical/infisical:latest
    container_name: infisical-api
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    environment:
      ENCRYPTION_KEY: ${ENCRYPTION_KEY}
      AUTH_SECRET: ${AUTH_SECRET}
      DB_CONNECTION_URI: postgresql://infisical:infisical_db_password@postgres:5432/infisical
      REDIS_URL: redis://redis:6379
      SITE_URL: https://secrets.example.com
      SMTP_HOST: ${SMTP_HOST}
      SMTP_PORT: ${SMTP_PORT}
      SMTP_USERNAME: ${SMTP_USERNAME}
      SMTP_PASSWORD: ${SMTP_PASSWORD}
      SMTP_FROM_ADDRESS: ${SMTP_FROM_ADDRESS}
    ports:
      - "80:8080"
    networks:
      - infisical-network
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/api/status"]
      interval: 30s
      timeout: 10s
      retries: 3

volumes:
  postgres_data:
  redis_data:

networks:
  infisical-network:
    driver: bridge

Configuration

Create a .env file in the same directory:

# Generated keys
ENCRYPTION_KEY=a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8
AUTH_SECRET=VUJrQV9FbmNyeXB0aW9uS2V5XzMyQnl0ZXNfQmFzZTY0RW5jb2RlZA==

# SMTP Configuration
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=[email protected]
SMTP_PASSWORD=your-app-password
SMTP_FROM_ADDRESS=[email protected]

Start the Services

docker-compose up -d

Monitor logs:

docker-compose logs -f infisical

Upgrade

  1. Backup the PostgreSQL database:
docker-compose exec postgres pg_dump -U infisical infisical > backup.sql
  1. Pull the new image:
docker pull infisical/infisical:latest
  1. Restart the services:
docker-compose down
docker-compose up -d

Schema migrations run automatically on startup.

External Databases

If using managed PostgreSQL (RDS, Cloud SQL, Azure Database) or managed Redis (ElastiCache, Cloud Memorystore, Azure Cache), configure the connection URIs directly:

environment:
  DB_CONNECTION_URI: postgresql://user:[email protected]:5432/infisical
  DB_ROOT_CERT: ${DB_ROOT_CERT}  # Set if TLS certificate verification is required
  REDIS_URL: rediss://redis-instance.cache.amazonaws.com:6380  # TLS enabled

For TLS certificates, base64-encode and pass as DB_ROOT_CERT:

cat /path/to/ca.pem | base64 -w 0 > /tmp/cert.b64
export DB_ROOT_CERT=$(cat /tmp/cert.b64)

Production Hardening

Read-Only Root Filesystem

Run the container with a read-only root filesystem and temporary writable mounts:

infisical:
  image: infisical/infisical:latest
  read_only: true
  tmpfs:
    - /tmp
    - /app/node_modules/.cache

This limits the attack surface if the container is compromised.

Drop Capabilities

Drop unnecessary Linux capabilities:

infisical:
  image: infisical/infisical:latest
  cap_drop:
    - ALL
  cap_add:
    - NET_BIND_SERVICE

Resource Limits

Set memory and CPU limits:

infisical:
  image: infisical/infisical:latest
  deploy:
    resources:
      limits:
        cpus: '2'
        memory: 4G
      reservations:
        cpus: '1'
        memory: 2G

Adjust based on your expected load.

Network Security

Restrict network access:

networks:
  infisical-network:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.name: br-infisical

Use separate networks for different components (application, database, cache).

Health Checks

The Infisical container exposes a health check endpoint:

GET /api/status

This returns HTTP 200 if the service is healthy.

Docker Compose Health Check Configuration

infisical:
  image: infisical/infisical:latest
  healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost:8080/api/status"]
    interval: 30s
    timeout: 10s
    retries: 3
    start_period: 40s

Logging

JSON Logging

Logs are output as JSON for better integration with log aggregation systems:

docker-compose logs infisical | jq '.msg'

Log File Output

Mount a volume to persist logs:

infisical:
  image: infisical/infisical:latest
  volumes:
    - ./logs:/app/logs
  environment:
    LOG_DIR: /app/logs

Networking

Reverse Proxy (Nginx)

Use Nginx to reverse proxy traffic to Infisical:

upstream infisical {
  server infisical:8080;
}

server {
  listen 443 ssl http2;
  server_name secrets.example.com;

  ssl_certificate /etc/letsencrypt/live/secrets.example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/secrets.example.com/privkey.pem;

  location / {
    proxy_pass http://infisical;
    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;
  }
}

In your .env, set:

SITE_URL=https://secrets.example.com

Load Balancing

Deploy multiple Infisical containers behind a load balancer:

infisical-1:
  image: infisical/infisical:latest
  environment:
    DB_CONNECTION_URI: postgresql://...
    REDIS_URL: redis://...

infisical-2:
  image: infisical/infisical:latest
  environment:
    DB_CONNECTION_URI: postgresql://...
    REDIS_URL: redis://...

infisical-3:
  image: infisical/infisical:latest
  environment:
    DB_CONNECTION_URI: postgresql://...
    REDIS_URL: redis://...

loadbalancer:
  image: nginx:latest
  ports:
    - "80:80"
    - "443:443"
  volumes:
    - ./nginx.conf:/etc/nginx/nginx.conf:ro

All instances share the same PostgreSQL and Redis, making the service stateless and scalable.

Backup and Recovery

Backup PostgreSQL

docker-compose exec postgres pg_dump -U infisical infisical > backup_$(date +%s).sql

Restore PostgreSQL

docker-compose exec -T postgres psql -U infisical infisical < backup.sql

Backup Redis

docker-compose exec redis redis-cli BGSAVE
docker cp infisical-redis:/data/dump.rdb ./redis_backup.rdb

Always backup before upgrading or making configuration changes.