A secure key management service inspired by Azure Key Vault and 1Password, written in Go with PostgreSQL storage. App Vault provides enterprise-grade secret management with strong encryption and multiple authentication methods.
- Strong Encryption: XChaCha20-Poly1305 AEAD encryption for all secrets
- Zero-Knowledge Architecture: Server never sees unencrypted secrets
- Key Derivation: Argon2id with secure parameters for master key derivation
- Vault Key Management: Per-user encryption keys with rotation support
- Dual Authentication: User accounts and service principals (client credentials)
- Key Rotation: Automatic re-encryption during vault key rotation
- Audit Logging: Complete audit trail of all operations
- Secret Versioning: Track changes to secrets over time
- Expiration Support: Set expiration dates for secrets
- RESTful API: Simple HTTP/JSON API
- TLS 1.3: Strong transport security with modern cipher suites
- Rate Limiting: Per-IP and per-service-principal rate limiting
- Metrics & Monitoring: Prometheus-compatible metrics endpoint
- Security Headers: HSTS, CSP, X-Frame-Options, and more
- Health Checks: Built-in liveness and readiness probes
- Request Size Limits: DoS protection via request body size limits
- Getting Started - Quick setup guide
- API Documentation - Complete API reference
- Deployment Guide - Production deployment with TLS, monitoring, and best practices
- Testing Guide - Load testing, security testing, and validation procedures
- Security - Security features, compliance, and vulnerability reporting
- Examples - Code examples for common use cases
- Contributing - How to contribute to the project
App Vault implements a 1Password-inspired security model:
- Master Key: Derived from
password + secretKeyusing Argon2id - Vault Key: Per-user encryption key for secrets
- Key Encryption: Vault Key encrypted with Key Encryption Key (KEK) derived from Master Key
- Secret Encryption: All secrets encrypted with Vault Key using XChaCha20-Poly1305
- Argon2id: Time=3, Memory=64MB, Threads=4, KeyLength=32 bytes
- HKDF: SHA-256 for deriving Key Encryption Key
- XChaCha20-Poly1305: 192-bit nonce, 256-bit key
- Go 1.23 or later
- PostgreSQL 12 or later
- Clone the repository:
git clone https://github.com/App Vault/app-vault.git
cd app-vault- Install dependencies:
go mod download- Set up PostgreSQL:
createdb App Vault- Configure environment variables:
export DATABASE_URL="postgres://postgres:postgres@localhost:5432/App Vault?sslmode=disable"
export JWT_SECRET="your-secret-key-change-this-in-production"
export SERVER_PORT="8080"- Run the server:
go run cmd/server/main.goThe server will start on http://localhost:8080.
Creates a new user account and returns a secret key.
POST /api/v1/auth/register
Content-Type: application/json
{
"email": "user@example.com",
"password": "securepassword123"
}Response:
{
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com",
"secret_key": "A3-abcd1234-efgh5678-ijkl9012-mnop3456"
}secret_key securely. It cannot be recovered.
Authenticates a user and returns a JWT token.
POST /api/v1/auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "securepassword123",
"secret_key": "A3-abcd1234-efgh5678-ijkl9012-mnop3456"
}Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"email": "user@example.com"
}All secret operations require:
Authorization: Bearer <token>headerX-Vault-Password: <password>headerX-Vault-Secret-Key: <secret_key>header
Creates or updates a secret.
POST /api/v1/secrets
Authorization: Bearer <token>
X-Vault-Password: securepassword123
X-Vault-Secret-Key: A3-abcd1234-efgh5678-ijkl9012-mnop3456
Content-Type: application/json
{
"name": "database-password",
"value": "super-secret-password",
"secret_type": "password",
"tags": ["production", "database"],
"expires_at": "2026-12-31T23:59:59Z"
}Response:
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"name": "database-password",
"version": 1,
"created_at": "2026-01-30T10:00:00Z"
}Retrieves a secret by name.
GET /api/v1/secrets/by-name?name=database-password
Authorization: Bearer <token>
X-Vault-Password: securepassword123
X-Vault-Secret-Key: A3-abcd1234-efgh5678-ijkl9012-mnop3456Response:
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"name": "database-password",
"value": "super-secret-password",
"secret_type": "password",
"version": 1,
"tags": ["production", "database"],
"created_at": "2026-01-30T10:00:00Z",
"updated_at": "2026-01-30T10:00:00Z",
"expires_at": "2026-12-31T23:59:59Z",
"access_count": 1,
"last_accessed_at": "2026-01-30T10:05:00Z"
}Retrieves a secret by ID.
GET /api/v1/secrets/660e8400-e29b-41d4-a716-446655440001
Authorization: Bearer <token>
X-Vault-Password: securepassword123
X-Vault-Secret-Key: A3-abcd1234-efgh5678-ijkl9012-mnop3456Lists all secrets (without values).
GET /api/v1/secrets
Authorization: Bearer <token>Response:
[
{
"id": "660e8400-e29b-41d4-a716-446655440001",
"name": "database-password",
"secret_type": "password",
"version": 1,
"tags": ["production", "database"],
"created_at": "2026-01-30T10:00:00Z",
"updated_at": "2026-01-30T10:00:00Z",
"expires_at": "2026-12-31T23:59:59Z",
"access_count": 5,
"last_accessed_at": "2026-01-30T12:00:00Z"
}
]Deletes a secret.
DELETE /api/v1/secrets/660e8400-e29b-41d4-a716-446655440001
Authorization: Bearer <token>Response: 204 No Content
Rotates the vault key and re-encrypts all secrets.
POST /api/v1/keys/rotate
Authorization: Bearer <token>
Content-Type: application/json
{
"password": "securepassword123",
"secret_key": "A3-abcd1234-efgh5678-ijkl9012-mnop3456",
"reason": "scheduled rotation"
}Response:
{
"new_key_version_id": "770e8400-e29b-41d4-a716-446655440002",
"secrets_reencrypted": 42,
"duration_ms": 1234
}Retrieves key version history.
GET /api/v1/keys/status
Authorization: Bearer <token>Response:
[
{
"id": "770e8400-e29b-41d4-a716-446655440002",
"version": 2,
"status": "active",
"created_at": "2026-01-30T10:00:00Z",
"rotation_reason": "scheduled rotation"
},
{
"id": "770e8400-e29b-41d4-a716-446655440001",
"version": 1,
"status": "deprecated",
"created_at": "2026-01-01T00:00:00Z",
"destroy_at": "2026-01-31T10:00:00Z",
"rotation_reason": "initial key"
}
]Changes the user's password (master key rotation).
POST /api/v1/auth/change-password
Authorization: Bearer <token>
Content-Type: application/json
{
"old_password": "securepassword123",
"new_password": "newsecurepassword456",
"secret_key": "A3-abcd1234-efgh5678-ijkl9012-mnop3456"
}Response:
{
"success": true
}generic- Generic secret (default)password- Passwordapi_key- API keycertificate- Certificateconnection- Connection string
| Variable | Description | Default |
|---|---|---|
DATABASE_URL |
PostgreSQL connection string | postgres://postgres:postgres@localhost:5432/App Vault?sslmode=disable |
JWT_SECRET |
Secret key for JWT signing | your-secret-key-change-this-in-production |
SERVER_PORT |
Server port | 8080 |
MIGRATIONS_PATH |
Path to SQL migration files | migrations |
# All tests
go test ./...
# With coverage
go test -cover ./...
# Specific package
go test ./internal/crypto -vSee TESTING.md for comprehensive testing guide including load testing and security testing.
# Development build
go build -o bin/App Vault cmd/server/main.go
# Production build with optimizations
go build -ldflags="-s -w" -o bin/App Vault cmd/server/main.goMigrations are automatically run on startup. To run them manually:
psql -U postgres -d App Vault -f migrations/001_initial_schema.sqlFor production deployments, see the comprehensive DEPLOYMENT.md guide which covers:
- TLS configuration with Let's Encrypt
- Rate limiting setup
- Prometheus metrics integration
- Security hardening checklist
- Reverse proxy configuration (Nginx/Caddy)
- Systemd service setup
- Performance tuning
Quick production setup:
# 1. Set up environment variables
cp .env.example .env
# Edit .env with production values
# 2. Generate TLS certificates
./scripts/generate-certs.sh # Linux/Mac
# or
.\scripts\generate-certs.ps1 # Windows
# 3. Build and run
go build -o bin/App Vault cmd/server/main.go
./bin/App VaultApp Vault implements multiple layers of security. Key points:
- Change JWT Secret: Always use a strong, random JWT secret in production
- Use TLS: Enable TLS 1.3 for all production deployments
- Secure Database: Use strong PostgreSQL passwords and SSL connections
- Rate Limiting: Enabled by default to prevent abuse
- Backup Secret Key: Users must securely store their secret key
- Key Rotation: Implement regular vault key rotation policies
- Audit Logs: Monitor audit logs for suspicious activity
- Security Headers: Automatically applied to all responses
For detailed security information, see SECURITY.md including:
- Encryption details (XChaCha20-Poly1305, Argon2id)
- Authentication mechanisms (JWT, MFA)
- TLS configuration
- Rate limiting implementation
- OWASP Top 10 compliance
- Vulnerability reporting process
┌─────────────┐
│ Client │
└──────┬──────┘
│ (HTTPS)
▼
┌─────────────────┐
│ API Layer │ ← JWT Auth, Rate Limiting
└──────┬──────────┘
│
┌──────▼──────────┐
│ Service Layer │ ← Business Logic
│ - Auth │
│ - Vault │
│ - Rotation │
└──────┬──────────┘
│
┌──────▼──────────┐
│ Crypto Layer │ ← Encryption/Decryption
└──────┬──────────┘
│
┌──────▼──────────┐
│ Database │ ← PostgreSQL
│ (Encrypted) │
└─────────────────┘
- users - User accounts with encrypted vault keys
- service_principals - Application credentials for API access
- key_versions - Key rotation history
- secrets - Encrypted secrets with versioning
- audit_logs - Complete audit trail
- rate_limits - Rate limiting state
MIT License - see LICENSE file for details.
Contributions are welcome! Please read the contributing guidelines before submitting pull requests.
For issues and questions, please open an issue on GitHub.