Self-Hosting Infisical with Docker Compose

What Is Infisical?

Infisical is an open-source secrets management platform. It stores API keys, database credentials, tokens, and environment variables in an encrypted vault with team-based access control, versioning, and automatic syncing to your applications. It replaces Doppler, HashiCorp Vault (for simple use cases), and scattered .env files. Official site

The Problem It Solves

Every self-hosted service needs credentials — database passwords, API keys, SMTP settings. Most people manage these in .env files scattered across servers, copy-pasted between services, with no version history and no access control. Infisical centralizes all of that:

Without InfisicalWith Infisical
.env files on each serverSingle encrypted vault
Copy-paste credentialsSync to applications automatically
No audit trailFull version history and access logs
Everyone has all secretsRole-based access per project
No rotationSecret rotation workflows
Plain text on diskEnd-to-end encrypted

Prerequisites

  • A Linux server (Ubuntu 22.04+ recommended)
  • Docker and Docker Compose installed (guide)
  • 1 GB of free RAM
  • A domain name (recommended for team access)

Docker Compose Configuration

services:
  infisical-db:
    image: postgres:16-alpine
    container_name: infisical-db
    environment:
      POSTGRES_DB: infisical
      POSTGRES_USER: infisical
      POSTGRES_PASSWORD: change-this-db-password
    volumes:
      - infisical-db:/var/lib/postgresql/data
    networks:
      - infisical
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U infisical"]
      interval: 10s
      timeout: 5s
      retries: 5

  infisical-redis:
    image: redis:7.4-alpine
    container_name: infisical-redis
    volumes:
      - infisical-redis:/data
    networks:
      - infisical
    restart: unless-stopped

  infisical:
    image: infisical/infisical:v0.158.13
    container_name: infisical
    ports:
      - "8080:8080"
    environment:
      # Encryption key (generate with: openssl rand -hex 16)
      ENCRYPTION_KEY: generate-a-32-char-hex-string
      # Auth secret (generate with: openssl rand -base64 32)
      AUTH_SECRET: generate-a-random-base64-string
      # Database
      DB_CONNECTION_URI: postgresql://infisical:change-this-db-password@infisical-db:5432/infisical
      # Redis
      REDIS_URL: redis://infisical-redis:6379
      # Application
      SITE_URL: https://secrets.example.com
      TELEMETRY_ENABLED: "false"
      # SMTP (optional — for invitations and 2FA recovery)
      SMTP_HOST: smtp.example.com
      SMTP_PORT: 587
      SMTP_USERNAME: [email protected]
      SMTP_PASSWORD: change-this-mail-password
      SMTP_FROM_ADDRESS: [email protected]
      SMTP_FROM_NAME: Infisical
    networks:
      - infisical
    depends_on:
      infisical-db:
        condition: service_healthy
      infisical-redis:
        condition: service_started
    restart: unless-stopped

networks:
  infisical:

volumes:
  infisical-db:
  infisical-redis:

Generate Required Keys

Before starting, generate the encryption and auth keys:

# Encryption key (32-character hex)
echo "ENCRYPTION_KEY: $(openssl rand -hex 16)"

# Auth secret (base64)
echo "AUTH_SECRET: $(openssl rand -base64 32)"

Replace the placeholder values in docker-compose.yml, then:

docker compose up -d

Access the web UI at http://your-server:8080 and create your admin account.

Core Concepts

ConceptDescription
OrganizationTop-level group (your company or homelab)
ProjectA set of related secrets (e.g., “Production Stack”, “Dev Environment”)
EnvironmentDev, staging, production — each has its own secret values
FolderOrganize secrets within an environment
SecretKey-value pair (e.g., DB_PASSWORD=hunter2)
Service tokenMachine-readable token for automated secret fetching

Setting Up Your First Project

  1. Create an organization (done during signup)
  2. Create a project — e.g., “Homelab Production”
  3. Add secrets — click + to add key-value pairs
  4. Create environments — default: Development, Staging, Production
  5. Invite team members — by email, with role-based access

Injecting Secrets into Applications

Using the Infisical CLI

# Install CLI
curl -1sLf 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.deb.sh' | bash
apt-get install infisical

# Login
infisical login

# Run a command with secrets injected as environment variables
infisical run --env=prod -- docker compose up -d

# Export secrets to .env file
infisical export --env=prod > .env

Using Service Tokens (for CI/CD and automation)

  1. In the Infisical dashboard, create a Service Token for your project
  2. Set the token as an environment variable: INFISICAL_TOKEN
  3. Use the CLI or API to fetch secrets:
export INFISICAL_TOKEN="st.xxxx..."
infisical export --env=prod --format=dotenv > .env

Using the REST API

curl -X GET "https://secrets.example.com/api/v3/secrets/raw?workspaceSlug=homelab&environment=prod" \
  -H "Authorization: Bearer $INFISICAL_TOKEN"

Integration with Docker Compose

Infisical can inject secrets directly into Docker Compose workflows:

# Instead of maintaining .env files, run:
infisical run --env=prod -- docker compose up -d

This passes all secrets from the Infisical project as environment variables to Docker Compose. No .env file on disk.

Security Features

FeatureDetails
End-to-end encryptionSecrets encrypted client-side before reaching the server
Role-based accessViewer, developer, admin roles per project
Audit logsFull history of who accessed which secret and when
Secret versioningRoll back to any previous value
IP allowlistingRestrict API access by IP
2FATOTP-based two-factor authentication
Secret rotationScheduled rotation for database credentials
Point-in-time recoveryRestore all secrets to a specific timestamp

Reverse Proxy

Behind Nginx Proxy Manager:

Proxy Host: secrets.example.com → http://infisical:8080
Enable: WebSocket Support, Force SSL

HTTPS is strongly recommended — this service handles your most sensitive data.

Backup

VolumeContainsPriority
infisical-dbAll secrets (encrypted), projects, usersCritical
infisical-redisSession cache (regenerated)Low

Critical: Also back up your ENCRYPTION_KEY. Without it, database backups are useless — secrets cannot be decrypted.

# Database backup
docker exec infisical-db pg_dump -U infisical infisical > infisical-backup-$(date +%Y%m%d).sql

# Store ENCRYPTION_KEY separately from the database backup

See Backup Strategy.

Troubleshooting

”Invalid encryption key” on startup

Symptom: Infisical fails to start with encryption errors. Fix: ENCRYPTION_KEY must be exactly 32 hex characters (16 bytes). Generate correctly: openssl rand -hex 16. Do NOT change this key after initial setup — existing secrets become unreadable.

Cannot invite team members

Symptom: Email invitations not sent. Fix: SMTP must be configured correctly. Test with a simple email first. Check docker logs infisical for SMTP errors.

Service token returns 401

Symptom: API calls with a service token return unauthorized. Fix: Verify the token hasn’t expired (tokens have configurable TTLs). Ensure the token has access to the correct project and environment.

Resource Requirements

  • RAM: ~300 MB idle (Infisical + PostgreSQL + Redis), ~500 MB under load
  • CPU: Low — mostly I/O bound (database queries and encryption)
  • Disk: ~200 MB for application, database grows slowly (secrets are small)

Verdict

Infisical is the best self-hosted secrets manager for teams and homelabs. It’s easier to set up and use than HashiCorp Vault, which is overkill for most self-hosting scenarios. The CLI integration with Docker Compose is the killer feature — inject secrets without ever writing them to disk. If you need a simpler, single-user solution, a Vaultwarden vault with secure notes also works. But for team access control, auditing, and environment-specific secrets, Infisical is the right tool.

Comments