Infisical Secret Management
Panduan lengkap instalasi dan penggunaan Infisical sebagai platform secret management modern untuk Kubernetes dan development teams.
Pengenalan
Infisical adalah open-source secret management platform yang dirancang untuk teams, dengan fokus pada developer experience. Infisical menyediakan end-to-end encrypted secret management dengan UI yang user-friendly, CLI tools, dan native Kubernetes integration.
Mengapa Infisical?
- ✅ Open Source: Fully open source, self-hostable
- ✅ End-to-End Encryption: Secrets encrypted at rest dan in transit
- ✅ Developer Friendly: Modern UI, intuitive workflows
- ✅ Multi-Platform: Support Docker, Kubernetes, CI/CD, local dev
- ✅ Secret Versioning: Track changes dan rollback
- ✅ Access Control: Granular RBAC untuk teams
- ✅ Integrations: Native integrations dengan popular tools
- ✅ Secret Scanning: Detect secrets in git commits
Arsitektur
┌─────────────────────────────────────────┐
│ Infisical Platform │
│ ┌────────────────────────────────┐ │
│ │ Web Dashboard │ │
│ └────────────────────────────────┘ │
│ ┌────────────────────────────────┐ │
│ │ API Server │ │
│ └────────────────────────────────┘ │
│ ┌────────────────────────────────┐ │
│ │ PostgreSQL Database │ │
│ └────────────────────────────────┘ │
└──────────────────┬──────────────────────┘
│
┌─────────┼─────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│ CLI │ │ K8s │ │ SDK │
│ Client │ │Operator│ │ Client │
└────────┘ └────────┘ └────────┘
Self-Hosted Installation
Option 1: Docker Compose (Recommended untuk Testing)
1. Clone Repository:
git clone https://github.com/Infisical/infisical.git
cd infisical
2. Create docker-compose.yml:
version: '3.8'
services:
postgres:
image: postgres:15-alpine
container_name: infisical-postgres
restart: unless-stopped
environment:
POSTGRES_USER: infisical
POSTGRES_PASSWORD: infisical_password
POSTGRES_DB: infisical
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- infisical
redis:
image: redis:7-alpine
container_name: infisical-redis
restart: unless-stopped
volumes:
- redis_data:/data
networks:
- infisical
backend:
image: infisical/infisical:latest
container_name: infisical-backend
restart: unless-stopped
depends_on:
- postgres
- redis
environment:
NODE_ENV: production
PORT: 4000
# Database
DB_CONNECTION_URI: postgres://infisical:infisical_password@postgres:5432/infisical
# Redis
REDIS_URL: redis://redis:6379
# Encryption keys (CHANGE THESE!)
ENCRYPTION_KEY: "your-32-char-encryption-key-here"
AUTH_SECRET: "your-32-char-auth-secret-here"
# Site URL
SITE_URL: https://infisical.example.com
# SMTP (optional)
SMTP_HOST: smtp.gmail.com
SMTP_PORT: 587
SMTP_SECURE: false
SMTP_USERNAME: your-email@gmail.com
SMTP_PASSWORD: your-app-password
SMTP_FROM_ADDRESS: noreply@example.com
SMTP_FROM_NAME: Infisical
ports:
- "4000:4000"
networks:
- infisical
frontend:
image: infisical/infisical-web:latest
container_name: infisical-frontend
restart: unless-stopped
depends_on:
- backend
environment:
NEXT_PUBLIC_INFISICAL_API_URL: https://infisical.example.com/api
NEXT_PUBLIC_SITE_URL: https://infisical.example.com
ports:
- "3000:3000"
networks:
- infisical
volumes:
postgres_data:
redis_data:
networks:
infisical:
driver: bridge
3. Generate Encryption Keys:
# Generate encryption key
openssl rand -hex 32
# Generate auth secret
openssl rand -hex 32
# Update docker-compose.yml dengan keys yang digenerate
4. Start Services:
docker-compose up -d
# Check logs
docker-compose logs -f backend
5. Access Infisical:
http://localhost:3000
Option 2: Kubernetes Deployment
1. Create Namespace:
kubectl create namespace infisical
2. Create Secrets:
apiVersion: v1
kind: Secret
metadata:
name: infisical-secrets
namespace: infisical
type: Opaque
stringData:
ENCRYPTION_KEY: "your-32-char-encryption-key-here"
AUTH_SECRET: "your-32-char-auth-secret-here"
DB_PASSWORD: "secure-db-password"
SMTP_PASSWORD: "your-smtp-password"
Apply:
kubectl apply -f infisical-secrets.yaml
3. PostgreSQL Deployment:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-pvc
namespace: infisical
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
namespace: infisical
spec:
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15-alpine
ports:
- containerPort: 5432
env:
- name: POSTGRES_USER
value: infisical
- name: POSTGRES_DB
value: infisical
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: infisical-secrets
key: DB_PASSWORD
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: postgres-pvc
---
apiVersion: v1
kind: Service
metadata:
name: postgres
namespace: infisical
spec:
selector:
app: postgres
ports:
- port: 5432
targetPort: 5432
4. Redis Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
namespace: infisical
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
ports:
- containerPort: 6379
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 200m
memory: 128Mi
---
apiVersion: v1
kind: Service
metadata:
name: redis
namespace: infisical
spec:
selector:
app: redis
ports:
- port: 6379
targetPort: 6379
5. Infisical Backend Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: infisical-backend
namespace: infisical
spec:
replicas: 2
selector:
matchLabels:
app: infisical-backend
template:
metadata:
labels:
app: infisical-backend
spec:
containers:
- name: backend
image: infisical/infisical:latest
ports:
- containerPort: 4000
env:
- name: NODE_ENV
value: "production"
- name: PORT
value: "4000"
- name: DB_CONNECTION_URI
value: "postgres://infisical:$(DB_PASSWORD)@postgres:5432/infisical"
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: infisical-secrets
key: DB_PASSWORD
- name: REDIS_URL
value: "redis://redis:6379"
- name: ENCRYPTION_KEY
valueFrom:
secretKeyRef:
name: infisical-secrets
key: ENCRYPTION_KEY
- name: AUTH_SECRET
valueFrom:
secretKeyRef:
name: infisical-secrets
key: AUTH_SECRET
- name: SITE_URL
value: "https://infisical.example.com"
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
livenessProbe:
httpGet:
path: /api/status
port: 4000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /api/status
port: 4000
initialDelaySeconds: 10
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: infisical-backend
namespace: infisical
spec:
selector:
app: infisical-backend
ports:
- port: 4000
targetPort: 4000
6. Infisical Frontend Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: infisical-frontend
namespace: infisical
spec:
replicas: 2
selector:
matchLabels:
app: infisical-frontend
template:
metadata:
labels:
app: infisical-frontend
spec:
containers:
- name: frontend
image: infisical/infisical-web:latest
ports:
- containerPort: 3000
env:
- name: NEXT_PUBLIC_INFISICAL_API_URL
value: "https://infisical.example.com/api"
- name: NEXT_PUBLIC_SITE_URL
value: "https://infisical.example.com"
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
---
apiVersion: v1
kind: Service
metadata:
name: infisical-frontend
namespace: infisical
spec:
selector:
app: infisical-frontend
ports:
- port: 3000
targetPort: 3000
7. Ingress Configuration:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: infisical-ingress
namespace: infisical
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- infisical.example.com
secretName: infisical-tls
rules:
- host: infisical.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: infisical-backend
port:
number: 4000
- path: /
pathType: Prefix
backend:
service:
name: infisical-frontend
port:
number: 3000
8. Deploy All:
kubectl apply -f postgres.yaml
kubectl apply -f redis.yaml
kubectl apply -f infisical-backend.yaml
kubectl apply -f infisical-frontend.yaml
kubectl apply -f ingress.yaml
# Check status
kubectl get pods -n infisical
kubectl get svc -n infisical
Initial Setup
1. Create Account
- Access Infisical UI:
https://infisical.example.com - Click Sign Up
- Enter email dan password
- Verify email (jika SMTP configured)
2. Create Organization
Organization Settings → Create Organization
- Name: My Company
- Slug: my-company
3. Create Project
Projects → New Project
- Name: Production
- Environment: production, staging, development
4. Add Secrets
Project → Secrets → Add Secret
- Key: DATABASE_URL
- Value: postgres://user:pass@host:5432/db
- Environment: production
Kubernetes Operator
Installation
1. Install Infisical Kubernetes Operator:
helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/'
helm repo update
helm install infisical-operator infisical-helm-charts/secrets-operator \
--namespace infisical-operator-system \
--create-namespace
2. Verify Installation:
kubectl get pods -n infisical-operator-system
Create Service Token
- Go to Infisical Project
- Settings → Service Tokens
- Click Generate Token
- Select environment (e.g., production)
- Copy token
Create Kubernetes Secret for Token
apiVersion: v1
kind: Secret
metadata:
name: infisical-token
namespace: default
type: Opaque
stringData:
token: "st.xxxx.yyyy.zzzz"
Apply:
kubectl apply -f infisical-token.yaml
Create InfisicalSecret Resource
apiVersion: secrets.infisical.com/v1alpha1
kind: InfisicalSecret
metadata:
name: myapp-secrets
namespace: default
spec:
# Infisical host URL
hostAPI: https://infisical.example.com/api
# Resync interval
resyncInterval: 60
# Authentication
authentication:
serviceToken:
serviceTokenSecretReference:
secretName: infisical-token
secretNamespace: default
# Managed secret configuration
managedSecretReference:
secretName: myapp-credentials
secretType: Opaque
creationPolicy: "Orphan"
Apply:
kubectl apply -f infisical-secret.yaml
Verify Secret Created
# Check InfisicalSecret status
kubectl get infisicalsecret myapp-secrets -n default
# Check if Kubernetes Secret created
kubectl get secret myapp-credentials -n default
# View secret data
kubectl get secret myapp-credentials -n default -o yaml
Use Secret in Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:1.0.0
envFrom:
- secretRef:
name: myapp-credentials # Secret from Infisical
ports:
- containerPort: 8080
CLI Usage
Installation
Linux/MacOS:
curl -1sLf 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.deb.sh' | sudo -E bash
sudo apt-get update && sudo apt-get install -y infisical
MacOS (Homebrew):
brew install infisical/get-cli/infisical
Windows (Scoop):
scoop bucket add infisical https://github.com/Infisical/scoop-infisical.git
scoop install infisical
Login
# Login to Infisical
infisical login
# Or use service token
export INFISICAL_TOKEN=st.xxxx.yyyy.zzzz
Basic Commands
# List projects
infisical projects list
# Pull secrets
infisical secrets
# Pull secrets from specific environment
infisical secrets --env=production
# Export secrets as env vars
infisical export --env=production
# Run command with secrets
infisical run --env=production -- npm start
# Set secret
infisical secrets set DATABASE_URL postgres://... --env=production
# Delete secret
infisical secrets delete DATABASE_URL --env=production
Development Workflow
1. Create .infisical.json:
{
"workspaceId": "your-project-id",
"defaultEnvironment": "development"
}
2. Run App with Secrets:
# Development
infisical run --env=development -- npm run dev
# Production
infisical run --env=production -- npm start
Integration dengan CI/CD
GitHub Actions
name: Deploy with Infisical
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Infisical CLI
run: |
curl -1sLf 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.deb.sh' | sudo -E bash
sudo apt-get update && sudo apt-get install -y infisical
- name: Fetch secrets and deploy
env:
INFISICAL_TOKEN: ${{ secrets.INFISICAL_TOKEN }}
run: |
infisical export --env=production > .env
# Your deployment commands
docker build -t myapp:latest .
docker push myapp:latest
Gitea Actions
name: Deploy Application
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Infisical
run: |
curl -1sLf 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.deb.sh' | sudo -E bash
sudo apt-get update && sudo apt-get install -y infisical
- name: Build with secrets
env:
INFISICAL_TOKEN: ${{ secrets.INFISICAL_TOKEN }}
run: |
infisical run --env=production -- npm run build
- name: Deploy to Kubernetes
run: |
kubectl apply -f k8s/
kubectl rollout restart deployment/myapp -n production
GitLab CI
deploy:
image: ubuntu:latest
before_script:
- apt-get update && apt-get install -y curl
- curl -1sLf 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.deb.sh' | bash
- apt-get update && apt-get install -y infisical
script:
- infisical export --env=production > .env
- # Your deployment commands
only:
- main
Secret Scanning
Setup Secret Scanning
# Install pre-commit hook
infisical scan install --pre-commit-hook
# Manual scan
infisical scan
# Scan git history
infisical scan --git-history
CI/CD Integration
# .gitea/workflows/security.yml
name: Security Scan
on: [push, pull_request]
jobs:
secret-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Full history for scanning
- name: Install Infisical
run: |
curl -1sLf 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.deb.sh' | sudo -E bash
sudo apt-get update && sudo apt-get install -y infisical
- name: Scan for secrets
run: infisical scan --verbose
Best Practices
1. Use Service Tokens dengan Scope Minimal
✅ Create separate service tokens untuk setiap environment
✅ Set expiration untuk service tokens
✅ Rotate tokens regularly
2. Environment Separation
Development → development
Staging → staging
Production → production
3. Secret Naming Convention
DATABASE_URL # Good
db_url # Avoid
DatabaseConnectionUrl # Avoid
4. Access Control
Project Settings → Members
- Developers: Read access to dev/staging
- DevOps: Read/Write access to all environments
- CI/CD: Service tokens dengan minimal scope
5. Audit Logging
Organization Settings → Audit Logs
- Monitor secret access
- Track changes
- Review suspicious activity
6. Backup Secrets
# Export all secrets
infisical export --env=production --format=json > backup-prod-secrets.json
# Store securely (encrypted)
gpg --encrypt --recipient admin@example.com backup-prod-secrets.json
7. Secret Rotation
1. Update secret di Infisical
2. Kubernetes Operator akan auto-sync (based on resyncInterval)
3. Restart pods jika perlu (gunakan Reloader)
Monitoring
Health Checks
# Backend health
curl https://infisical.example.com/api/status
# Kubernetes Operator health
kubectl get pods -n infisical-operator-system
kubectl logs -n infisical-operator-system -l app.kubernetes.io/name=secrets-operator
Metrics (jika enabled)
# ServiceMonitor for Prometheus
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: infisical-operator
namespace: infisical-operator-system
spec:
selector:
matchLabels:
app.kubernetes.io/name: secrets-operator
endpoints:
- port: metrics
interval: 30s
Troubleshooting
Issue 1: InfisicalSecret Not Syncing
# Check InfisicalSecret status
kubectl describe infisicalsecret myapp-secrets -n default
# Check operator logs
kubectl logs -n infisical-operator-system -l app.kubernetes.io/name=secrets-operator
# Common causes:
# - Invalid service token
# - Network connectivity issues
# - Secret not found in Infisical project
Issue 2: Authentication Failed
# Verify service token
kubectl get secret infisical-token -n default -o yaml
# Test token manually
export INFISICAL_TOKEN=st.xxxx.yyyy.zzzz
infisical secrets
Issue 3: Secrets Not Updated
# Check resync interval
kubectl get infisicalsecret myapp-secrets -n default -o yaml | grep resyncInterval
# Force sync by deleting and recreating
kubectl delete infisicalsecret myapp-secrets -n default
kubectl apply -f infisical-secret.yaml
Migration dari Environment Variables
Step-by-Step
1. Audit current secrets:
kubectl get secrets --all-namespaces
2. Import ke Infisical:
# Via CLI
infisical secrets set DATABASE_URL postgres://... --env=production
infisical secrets set API_KEY xxx --env=production
# Via UI: Project → Secrets → Import
3. Setup Kubernetes Operator:
kubectl apply -f infisical-secret.yaml
4. Update Deployments:
# Before
env:
- name: DATABASE_URL
value: "postgres://..."
# After
envFrom:
- secretRef:
name: myapp-credentials # From InfisicalSecret
5. Verify dan Cleanup:
# Test application
kubectl logs deployment/myapp -n default
# Delete old secrets
kubectl delete secret old-secrets -n default
Comparison: Infisical vs Alternatives
| Feature | Infisical | HashiCorp Vault | Doppler | AWS Secrets Manager |
|---|---|---|---|---|
| Open Source | ✅ | ✅ | ❌ | ❌ |
| Self-Hosted | ✅ | ✅ | ❌ | ❌ |
| UI/UX | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
| K8s Integration | ✅ | ✅ | ✅ | ✅ |
| Secret Scanning | ✅ | ❌ | ✅ | ❌ |
| Cost | Free | Free/Paid | Paid | Paid |
| Learning Curve | Low | High | Low | Medium |
Kesimpulan
Infisical adalah modern secret management solution yang:
- ✅ Easy to setup dan use
- ✅ Developer-friendly
- ✅ Open source dan self-hostable
- ✅ Native Kubernetes integration
- ✅ Built-in secret scanning
Kapan Menggunakan Infisical?
✅ Recommended untuk:
- Small to medium teams
- Organizations yang ingin self-hosted solution
- Teams yang prioritize developer experience
- Projects yang butuh secret scanning
❌ Pertimbangkan alternatif jika:
- Enterprise dengan complex compliance requirements (consider Vault)
- Already invested in cloud provider ecosystem (AWS/GCP/Azure)
- Need advanced features seperti dynamic secrets, PKI