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.
8.2 KiB
Docker Deployment Guide
Deploy Infisical using Docker or Docker Compose for flexible, containerized self-hosted environments.
Docker Standalone Container
Quick Start
- Pull the image:
docker pull infisical/infisical:latest
- Create a
.envfile 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]"
- Run the container:
docker run -d \
--name infisical \
--env-file .env \
-p 8080:8080 \
infisical/infisical:latest
- 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
- Backup the PostgreSQL database:
docker-compose exec postgres pg_dump -U infisical infisical > backup.sql
- Pull the new image:
docker pull infisical/infisical:latest
- 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.