This guide provides security hardening recommendations for production Infisical deployments. Infisical manages runtime secrets and machine identities, making security paramount. Follow these guidelines to protect your secret management infrastructure.
Current Version: v0.158.5 (February 2026)
| Standard | Status | Notes |
|---|---|---|
| SOC 2 Type II | π In Progress | Expected completion 2026 |
| GDPR | β Compliant | EU data protection |
| FIPS 140-3 | β οΈ Available | FIPS Docker image available for enterprise |
| HIPAA | β οΈ Possible | Self-hosted can be configured for HIPAA compliance |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Security Layers β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Network Security β β
β β β’ TLS 1.3 encryption β β
β β β’ Network policies / Firewall rules β β
β β β’ Private subnets for database/cache β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Application Security β β
β β β’ End-to-end AES-GCM-256 encryption β β
β β β’ JWT authentication with short lifetimes β β
β β β’ RBAC with least privilege β β
β β β’ Audit logging for all operations β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Data Security β β
β β β’ Client-side encryption before transmission β β
β β β’ Encrypted database storage β β
β β β’ Encrypted backups β β
β β β’ Secure key escrow β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Operational Security β β
β β β’ MFA enforcement β β
β β β’ SSO integration β β
β β β’ Session management β β
β β β’ Incident response procedures β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Generate encryption key (32 hex characters for AES-256)
ENCRYPTION_KEY=$(openssl rand -hex 16)
echo "ENCRYPTION_KEY=$ENCRYPTION_KEY"
# Generate auth secret for JWT signing (base64)
AUTH_SECRET=$(openssl rand -base64 32)
echo "AUTH_SECRET=$AUTH_SECRET"
# Generate database password
DB_PASSWORD=$(openssl rand -base64 24 | tr -d '=+')
echo "DB_PASSWORD=$DB_PASSWORD"
β οΈ Critical: Store these keys securely. The
ENCRYPTION_KEYcannot be recovered if lost. All secrets encrypted with this key will be unrecoverable.
| Method | Security Level | Use Case |
|---|---|---|
| Hardware Security Module (HSM) | Highest | Enterprise, compliance-required |
| Cloud KMS | High | Cloud deployments |
| Encrypted offline storage | Medium-High | Self-hosted, air-gapped backup |
| Password manager | Medium | Small teams, development |
# Short-lived authentication tokens
JWT_AUTH_LIFETIME=15m
# Refresh tokens for extended sessions
JWT_REFRESH_LIFETIME=24h
# Service tokens for machine identities
JWT_SERVICE_LIFETIME=1h
# Machine identity tokens
JWT_MACHINE_IDENTITY_LIFETIME=24h
# Force HTTPS
HTTPS_ENABLED=true
# Database SSL
DB_CONNECTION_URI="postgresql://user:pass@host:5432/db?sslmode=require"
DB_ROOT_CERT="<base64-encoded-certificate>"
# Redis SSL
REDIS_URL="rediss://user:password@redis:6380"
# Production: Use Let's Encrypt or enterprise CA
# cert-manager for Kubernetes
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: security@example.com
privateKeySecretRef:
name: letsencrypt-prod-key
solvers:
- http01:
ingress:
class: nginx
# Ingress with TLS
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: infisical
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- infisical.example.com
secretName: infisical-tls
# CORS configuration
CORS_ALLOWED_ORIGINS=["https://app.example.com"]
# Block internal IP connections (prevent SSRF)
ALLOW_INTERNAL_IP_CONNECTIONS=false
# Trusted proxies (load balancers, ingress)
TRUSTED_PROXIES=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
# UFW configuration (Debian/Ubuntu)
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow SSH (from trusted IPs)
sudo ufw allow from 10.0.0.0/8 to any port 22
# Allow HTTPS
sudo ufw allow 443/tcp
# Allow HTTP for Let's Encrypt only
sudo ufw allow 80/tcp
# Block direct database access
sudo ufw deny 5432/tcp
# Block direct Redis access
sudo ufw deny 6379/tcp
sudo ufw --force enable
# Required - absolute URL with protocol
SITE_URL="https://infisical.example.com"
# Instance branding (optional)
INSTANCE_NAME="Company Secret Vault"
# Security banner for regulated industries
INSTANCE_BANNER='{"text":"Authorized Personnel Only - All Access Logged","color":"#dc3545","enabled":true}'
SMTP_HOST="smtp.example.com"
SMTP_PORT="587"
SMTP_USERNAME="noreply@example.com"
SMTP_PASSWORD="your-secure-smtp-password"
SMTP_FROM_ADDRESS="noreply@example.com"
SMTP_FROM_NAME="Infisical"
SMTP_REQUIRE_TLS=true
SMTP_IGNORE_TLS=false
# Disable telemetry (recommended for production)
TELEMETRY_ENABLED=false
# Disable error reporting to external services
ERROR_REPORTING_ENABLED=false
# Configure read replicas for HA
DB_READ_REPLICAS='[
{"DB_CONNECTION_URI":"postgresql://user:pass@replica1:5432/db?sslmode=require"},
{"DB_CONNECTION_URI":"postgresql://user:pass@replica2:5432/db?sslmode=require"}
]'
-- Create dedicated user with minimal privileges
CREATE USER infisical WITH PASSWORD 'secure-password';
GRANT CONNECT ON DATABASE infisical TO infisical;
GRANT USAGE ON SCHEMA public TO infisical;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO infisical;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO infisical;
-- Revoke dangerous operations
REVOKE CREATE ON SCHEMA public FROM infisical;
REVOKE ALL ON DATABASE infisical FROM infisical;
services:
backend:
image: infisical/infisical:v0.93.1-postgres # Use specific version, not 'latest'
# Read-only root filesystem
read_only: true
# Temporary writable directories
tmpfs:
- /tmp:rw,exec,size=1G
# Drop all capabilities
cap_drop:
- ALL
# Prevent privilege escalation
security_opt:
- no-new-privileges:true
# Resource limits
deploy:
resources:
limits:
cpus: '2.0'
memory: 2G
reservations:
cpus: '0.5'
memory: 512M
# Network isolation
networks:
- infisical-internal
# User namespace
user: "1001:1001"
| Setting | Purpose | Implementation |
|---|---|---|
| Specific image tags | Prevent unexpected changes | v0.93.1-postgres not latest |
| Read-only filesystem | Prevent runtime modifications | read_only: true |
| Drop capabilities | Minimize kernel access | cap_drop: [ALL] |
| No new privileges | Prevent setuid binaries | no-new-privileges:true |
| Resource limits | Prevent DoS | deploy.resources.limits |
| Network isolation | Limit blast radius | Custom networks |
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/api/status"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
apiVersion: v1
kind: Namespace
metadata:
name: infisical
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
apiVersion: apps/v1
kind: Deployment
metadata:
name: infisical
namespace: infisical
spec:
template:
spec:
# Pod-level security
securityContext:
runAsNonRoot: true
runAsUser: 1001
fsGroup: 1001
seccompProfile:
type: RuntimeDefault
# Service account
serviceAccountName: infisical
automountServiceAccountToken: false
containers:
- name: infisical
# Container-level security
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
runAsNonRoot: true
runAsUser: 1001
capabilities:
drop:
- ALL
# Resource limits
resources:
limits:
memory: 2Gi
cpu: 2
requests:
memory: 512Mi
cpu: 350m
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: infisical-netpol
namespace: infisical
spec:
podSelector:
matchLabels:
app: infisical
policyTypes:
- Ingress
- Egress
ingress:
# Allow from ingress controller only
- from:
- namespaceSelector:
matchLabels:
name: ingress-system
ports:
- protocol: TCP
port: 8080
egress:
# Allow to PostgreSQL
- to:
- podSelector:
matchLabels:
app: postgresql
ports:
- protocol: TCP
port: 5432
# Allow to Redis
- to:
- podSelector:
matchLabels:
app: redis
ports:
- protocol: TCP
port: 6379
# Allow DNS
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
# Encrypt etcd at rest
# On control plane nodes, configure:
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-key>
- identity: {}
# Create dedicated system user
sudo useradd --system --shell /bin/false --home-dir /opt/infisical infisical
# Create directories with proper permissions
sudo mkdir -p /opt/infisical
sudo chown infisical:infisical /opt/infisical
sudo chmod 755 /opt/infisical
[Unit]
Description=Infisical Secret Management
After=network.target
[Service]
Type=simple
User=infisical
Group=infisical
WorkingDirectory=/opt/infisical
ExecStart=/opt/infisical/infisical-linux-amd64
Restart=always
# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/infisical
PrivateTmp=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
RestrictSUIDSGID=true
LimitCORE=0
MemorySwapMax=0
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
RestrictNamespaces=true
LockPersonality=true
MemoryDenyWriteExecute=true
# Resource limits
LimitNOFILE=65536
LimitNPROC=64
[Install]
WantedBy=multi-user.target
# Disable memory swapping
sudo swapoff -a
sudo sed -i '/swap/d' /etc/fstab
# Disable core dumps
echo "* hard core 0" | sudo tee -a /etc/security/limits.conf
# Enable automatic security updates
sudo apt-get install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
| Role | Permissions | Use Case |
|---|---|---|
| Super Admin | Full system access | Platform administrators |
| Organization Admin | Manage org, users, projects | Team leads |
| Project Admin | Manage project settings | Project managers |
| Developer | Read/write secrets in assigned environments | Developers |
| Operator | Read production secrets | SRE, operations |
| Auditor | Read-only access to secrets and logs | Compliance |
| Service Account | Programmatic access to specific secrets | CI/CD, applications |
# Keycloak settings
SSO_ENABLED=true
SSO_PROVIDER=keycloak
SSO_ISSUER_URL=https://sso.example.com/realms/myrealm
SSO_CLIENT_ID=infisical
SSO_CLIENT_SECRET=your-client-secret
SSO_CALLBACK_URL=https://infisical.example.com/api/v1/auth/sso/callback
# OIDC group mapping
OIDC_GROUP_MAPPING_ENABLED=true
OIDC_GROUPS_CLAIM=groups
OIDC_GROUP_ADMIN=infisical-admins
OIDC_GROUP_USER=infisical-users
SAML_ENABLED=true
SAML_ISSUER=infisical.example.com
SAML_ENTRY_POINT=https://login.microsoftonline.com/tenant-id/saml2
SAML_CERT=/path/to/saml-cert.pem
SAML_CALLBACK_URL=https://infisical.example.com/api/v1/auth/saml/callback
# Enforce MFA for all users
MFA_ENFORCED=true
# Grace period for MFA setup (days)
MFA_GRACE_PERIOD_DAYS=7
# Allowed MFA methods
MFA_METHODS=totp,webauthn
# WebAuthn settings
WEBAUTHN_RP_NAME="Company Infisical"
WEBAUTHN_RP_ID=infisical.example.com
# Environment isolation policy
environments:
development:
allowed_roles:
- developer
- admin
ip_whitelist: []
staging:
allowed_roles:
- developer
- operator
- admin
ip_whitelist:
- 10.0.0.0/8
production:
allowed_roles:
- operator
- admin
ip_whitelist:
- 10.0.0.0/8
- 192.168.1.0/24 # CI/CD servers
require_approval: true
approvers:
- platform-team
# Multi-step approval for sensitive operations
approval_workflows:
- name: Production Secret Change
trigger:
environment: production
action: [create, update, delete]
approvals_required: 2
approvers:
- role: project-admin
- role: security-team
timeout_hours: 24
- name: Service Token Creation
trigger:
resource_type: service-token
scope: production
approvals_required: 1
approvers:
- role: organization-admin
# Enable audit logging
AUDIT_LOG_ENABLED=true
# Retention period
AUDIT_LOG_RETENTION_DAYS=365
# Export configuration
AUDIT_LOG_EXPORT_ENABLED=true
AUDIT_LOG_EXPORT_PATH=/var/log/infisical/audit/
AUDIT_LOG_EXPORT_FORMAT=json
# SIEM integration
AUDIT_LOG_SIEM_ENABLED=true
AUDIT_LOG_SIEM_ENDPOINT=https://siem.example.com/api/logs
AUDIT_LOG_SIEM_TOKEN=your-siem-token
AUDIT_LOG_SIEM_BATCH_SIZE=100
AUDIT_LOG_SIEM_INTERVAL=60
Configure alerts for:
#!/bin/bash
# Secure backup script
BACKUP_DIR="/secure/backups/infisical"
DATE=$(date +%Y%m%d_%H%M%S)
ENCRYPTION_KEY_FILE="/secure/keys/backup-key"
# Create backup
pg_dump "$DB_CONNECTION_URI" | gzip > "$BACKUP_DIR/db_$DATE.sql.gz"
# Encrypt backup
gpg --batch --yes --passphrase-file "$ENCRYPTION_KEY_FILE" \
--cipher-algo AES256 --symmetric \
--output "$BACKUP_DIR/db_$DATE.sql.gz.gpg" \
"$BACKUP_DIR/db_$DATE.sql.gz"
# Securely delete unencrypted backup
shred -u "$BACKUP_DIR/db_$DATE.sql.gz"
# Verify encrypted backup
gpg --batch --yes --passphrase-file "$ENCRYPTION_KEY_FILE" \
--decrypt "$BACKUP_DIR/db_$DATE.sql.gz.gpg" | gunzip -t
Store encryption keys in multiple secure locations:
# Quarterly recovery test procedure
recovery_test:
frequency: quarterly
steps:
- Restore database from encrypted backup
- Verify decryption with escrowed keys
- Start Infisical in isolated environment
- Validate API authentication
- Test secret retrieval for sample application
- Document results and update runbooks
Infisical supports SOC 2 compliance through:
For healthcare deployments:
For government and regulated industries:
# Use FIPS-compliant Docker image
image: infisical/infisical-fips:v0.93.1
# Configure FIPS mode
FIPS_MODE_ENABLED=true
For EU data protection:
# Key security metrics to monitor
security_metrics:
- infisical_auth_failures_total
- infisical_secret_access_total
- infisical_policy_changes_total
- infisical_service_tokens_created_total
- infisical_mfa_challenges_total
- infisical_audit_events_total
# Prometheus alerting rules
groups:
- name: infisical-security
rules:
- alert: InfisicalHighAuthFailures
expr: rate(infisical_auth_failures_total[5m]) > 10
for: 5m
labels:
severity: warning
annotations:
summary: High authentication failure rate
- alert: InfisicalProductionSecretAccess
expr: rate(infisical_secret_access_total{environment="production"}[1m]) > 100
for: 5m
labels:
severity: warning
annotations:
summary: Unusual production secret access pattern
- alert: InfisicalPolicyChange
expr: rate(infisical_policy_changes_total[5m]) > 0
labels:
severity: info
annotations:
summary: Policy change detected
incident_contacts:
security_team: security@example.com
platform_team: platform@example.com
on_call: +1-555-0100
escalation:
- platform-lead
- security-lead
- cto
Any questions?
Feel free to contact us. Find all contact information on our contact page.