Add SecretsByType grouping to vault list handler that was referenced in the template but not populated. Replace base/paginate template with custom pagination to match vault UI styling.
GitCaddy Vault
Encrypted Secrets Management for GitCaddy
GitCaddy Vault is a commercial module compiled directly into GitCaddy Server that provides enterprise-grade secrets management within your GitCaddy repositories. Store, version, and securely access credentials, API keys, certificates, and other sensitive data without leaving your Git workflow.
Features
Core Capabilities
- Encrypted Storage - All secrets encrypted at rest using AES-256-GCM with per-repository encryption keys
- Version History - Full version tracking with rollback capability for all secrets
- Audit Logging - Complete audit trail of all secret access and modifications
- CI/CD Tokens - Scoped tokens for secure automated access during builds and deployments
Secret Types
| Type | Description |
|---|---|
key-value |
Simple key-value pairs |
env-file |
Environment file format (KEY=value) |
file |
Arbitrary file content |
certificate |
TLS/SSL certificates |
ssh-key |
SSH private keys |
Security Architecture
┌─────────────────────────────────────────────────────────┐
│ GitCaddy Server │
├─────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Web UI │ │ REST API │ │ CI/CD API │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └──────────────────┼──────────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ Vault Service │ │
│ └────────┬────────┘ │
│ │ │
│ ┌──────────────────┼──────────────────┐ │
│ ┌─────▼─────┐ ┌──────▼──────┐ ┌──────▼──────┐ │
│ │ Crypto │ │ Models │ │ License │ │
│ │ Engine │ │ (XORM) │ │ Manager │ │
│ └───────────┘ └─────────────┘ └─────────────┘ │
│ │
│ (Compiled into GitCaddy Server) │
└─────────────────────────────────────────────────────────┘
Encryption Hierarchy:
- Master Key (KEK) - Server-level key encryption key
- Repository DEK - Per-repository data encryption key, encrypted by KEK
- Secret Values - Encrypted using repository DEK with AES-256-GCM
Installation
Requirements
- GitCaddy Server v1.0.0 or later (Vault is included automatically)
- Valid GitCaddy Vault license
Setup
GitCaddy Vault is compiled directly into GitCaddy Server - no separate installation required.
-
Add your license key via environment variable or file:
# Option 1: Environment variable export GITCADDY_LICENSE_KEY="<your-base64-license>" # Option 2: License file cp license.key /etc/gitcaddy/license.key -
Restart GitCaddy Server to activate the license
Configuration
Environment Variables
| Variable | Description | Default |
|---|---|---|
GITCADDY_LICENSE_KEY |
Base64-encoded license key | - |
GITCADDY_LICENSE_FILE |
Path to license file | /etc/gitcaddy/license.key |
GITCADDY_VAULT_KEK |
Master key encryption key (32 bytes, hex) | Auto-generated |
GITCADDY_DEV_MODE |
Skip license validation (dev only) | 0 |
License File Locations
GitCaddy Server searches for license files in this order:
- Path specified by
GITCADDY_LICENSE_FILE /etc/gitcaddy/license.key./custom/license.key./license.key
Usage
Web Interface
Access the Vault tab in any repository where you have admin permissions:
https://your-gitcaddy-instance/owner/repo/vault
Managing Secrets:
- Navigate to Repository > Vault > Secrets
- Click "New Secret" to create a secret
- Use dot notation for organization:
prod.database.password,staging.api.key
Creating CI/CD Tokens:
- Navigate to Repository > Vault > CI/CD Tokens
- Click "New Token"
- Define the scope (e.g.,
read:*,read:prod.*,write:db.credentials) - Set expiration time
- Copy the token immediately (shown only once)
REST API
All API endpoints require a valid vault token in the Authorization header.
Authentication:
# Bearer token format
Authorization: Bearer gvt_abc123...
# Or token format
Authorization: token gvt_abc123...
List Secrets:
curl -H "Authorization: Bearer $VAULT_TOKEN" \
https://gitcaddy.example.com/api/v1/repos/owner/repo/vault/secrets
Get Secret Value:
curl -H "Authorization: Bearer $VAULT_TOKEN" \
https://gitcaddy.example.com/api/v1/repos/owner/repo/vault/secrets/prod.database.password
Create Secret:
curl -X POST \
-H "Authorization: Bearer $VAULT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "prod.database.password",
"description": "Production database credentials",
"type": "key-value",
"value": "secret-password-here"
}' \
https://gitcaddy.example.com/api/v1/repos/owner/repo/vault/secrets
Update Secret:
curl -X PUT \
-H "Authorization: Bearer $VAULT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "key-value",
"value": "new-secret-value",
"comment": "Rotated credentials"
}' \
https://gitcaddy.example.com/api/v1/repos/owner/repo/vault/secrets/prod.database.password
Delete Secret:
curl -X DELETE \
-H "Authorization: Bearer $VAULT_TOKEN" \
https://gitcaddy.example.com/api/v1/repos/owner/repo/vault/secrets/prod.database.password
CI/CD Integration
GitHub Actions / Gitea Actions:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Fetch secrets
run: |
DB_PASSWORD=$(curl -s -H "Authorization: Bearer ${{ secrets.VAULT_TOKEN }}" \
"${{ github.server_url }}/api/v1/repos/${{ github.repository }}/vault/secrets/prod.database.password" \
| jq -r '.value')
echo "::add-mask::$DB_PASSWORD"
echo "DB_PASSWORD=$DB_PASSWORD" >> $GITHUB_ENV
GitLab CI:
deploy:
script:
- |
export DB_PASSWORD=$(curl -s -H "Authorization: Bearer $VAULT_TOKEN" \
"$CI_SERVER_URL/api/v1/repos/$CI_PROJECT_PATH/vault/secrets/prod.database.password" \
| jq -r '.value')
Token Scopes
Token scopes control access to secrets using a simple grammar:
| Scope | Description |
|---|---|
read:* |
Read access to all secrets |
write:* |
Read and write access to all secrets |
read:prod.* |
Read access to secrets starting with prod. |
write:db.credentials |
Write access to specific secret db.credentials |
admin |
Full administrative access |
Multiple scopes: Separate with commas: read:prod.*,write:staging.*
License Tiers
| Feature | Solo | Pro | Team | Enterprise |
|---|---|---|---|---|
| Users | 1 | 5 | 25 | Unlimited |
| Secrets per repo | 5 | Unlimited | Unlimited | Unlimited |
| Audit retention | 7 days | 90 days | 1 year | Custom |
| Version history | No | Yes | Yes | Yes |
| CI/CD tokens | No | Yes | Yes | Yes |
| SSO integration | No | No | Yes | Yes |
| Priority support | No | No | No | Yes |
Database Schema
GitCaddy Vault uses the following tables:
vault_secret- Secret metadatavault_secret_version- Versioned secret values (encrypted)vault_repo_key- Per-repository encryption keysvault_token- CI/CD access tokensvault_audit_entry- Audit log entries
Development
Architecture: Vault ↔ Server Sync
Important for contributors and AI assistants:
GitCaddy Vault is the source of truth for vault-related templates and locales. Due to Go plugin compilation limitations, vault code is compiled directly into GitCaddy Server rather than loaded as a dynamic plugin.
┌─────────────────────────────────────────────────────────────────┐
│ gitcaddy-vault (this repo) │
│ SOURCE OF TRUTH for: │
│ • templates/repo/vault/*.tmpl → UI templates │
│ • locale/*.json → Translation strings │
│ • models/, services/, crypto/ → Business logic │
│ • license/ → License validation │
└─────────────────────────┬───────────────────────────────────────┘
│
BUILD TIME SYNC
(scripts/sync-vault.sh)
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ gitcaddy-server │
│ RECEIVES from vault: │
│ • templates/repo/vault/*.tmpl ← Copied from vault │
│ • options/locale/*.json ← vault.* keys merged │
│ │
│ SERVER-ONLY (not in vault): │
│ • templates/repo/vault/feature_upgrade.tmpl │
│ • templates/repo/vault/not_installed.tmpl │
│ • templates/repo/vault/upgrade.tmpl │
│ • routers/web/repo/vault/vault.go ← Router glue code │
│ • services/vault/vault.go ← Service wrappers │
└─────────────────────────────────────────────────────────────────┘
When making changes:
- Edit templates/locales in gitcaddy-vault (this repo)
- The CI build automatically syncs to gitcaddy-server
- Server-specific templates (upgrade prompts) stay in server repo
- Go router code stays in server repo (thin integration layer)
Why not Go plugins? Go plugins require exact compiler version and dependency matches between plugin and host. This is fragile in practice, so we compile vault directly into the server binary.
Building
The Vault module is compiled directly into GitCaddy Server. To build the server with Vault:
# Clone GitCaddy Server (includes Vault)
git clone https://git.marketally.com/gitcaddy/server.git
cd server
# Build the server (Vault is included automatically)
make build
# Run tests
go test ./...
Keygen Utility
The license key generation tool is built separately:
# Clone the vault repository
git clone https://git.marketally.com/gitcaddy/vault.git
cd vault
# Build the keygen utility
go build -o keygen ./cmd/keygen
Generating License Keys
# Generate a new keypair (do this once, keep private key secure!)
go run ./cmd/keygen -generate-keys
# Sign a license
go run ./cmd/keygen -sign \
-email customer@example.com \
-tier pro \
-duration 365d \
-private-key /secure/path/private.key
Local Development
Set GITCADDY_DEV_MODE=1 to skip license validation during development:
export GITCADDY_DEV_MODE=1
Security Considerations
- Key Management - The master KEK should be stored securely (HSM, KMS, or secure environment variable)
- Token Storage - Vault tokens are hashed with SHA-256 before storage
- Audit Trail - All access is logged with IP address and user information
- Soft Delete - Deleted secrets are retained for recovery before permanent deletion
- TLS Required - Always use HTTPS in production
Support
- Documentation: https://docs.gitcaddy.com/vault
- Issues: https://git.marketally.com/gitcaddy/vault/issues
- Email: support@marketally.com
License
Business Source License 1.1 - See LICENSE file for details.
Copyright 2026 MarketAlly. All rights reserved.