Skip to main content

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

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

  1. Access Infisical UI: https://infisical.example.com
  2. Click Sign Up
  3. Enter email dan password
  4. 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

  1. Go to Infisical Project
  2. SettingsService Tokens
  3. Click Generate Token
  4. Select environment (e.g., production)
  5. 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

FeatureInfisicalHashiCorp VaultDopplerAWS Secrets Manager
Open Source
Self-Hosted
UI/UX⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
K8s Integration
Secret Scanning
CostFreeFree/PaidPaidPaid
Learning CurveLowHighLowMedium

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

Resources