Installation
One-Line Installer (Recommended)
The interactive installer detects your OS, installs Docker if needed, generates secrets, configures TLS, and starts everything.
curl -fsSL https://vaultctl.vinelabs.de/install.sh | bashWhat it does:
- Checks for Docker (installs if missing)
- Pulls the latest vaultctl + PostgreSQL images
- Generates cryptographic secrets (JWT, HMAC, encryption keys)
- Asks for your domain name
- Configures Caddy for automatic HTTPS via Let's Encrypt
- Starts all services
- Runs database migrations
- Prints your vault URL
The installer is fully interactive — it prompts before every action. You can review each step before proceeding.
Docker Images
Official multi-arch images (linux/amd64, linux/arm64) are published to both registries on every release. All images are signed with cosign (opens in a new tab) keyless signatures.
docker pull vineethnkrishnan/vaultctl:latest
# or pin to a specific version
docker pull vineethnkrishnan/vaultctl:1.1.3Verify image signature
cosign verify vineethnkrishnan/vaultctl:latest \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp 'github\.com/vineethkrishnan/vaultctl'Run directly
docker run -d --name vaultctl \
-p 8080:8080 \
-e VAULTCTL_DATABASE_URL="postgres://user:pass@host:5432/vaultctl?sslmode=disable" \
-e VAULTCTL_JWT_SECRET_CURRENT="$(openssl rand -base64 32)" \
-e VAULTCTL_SERVER_PEPPER="$(openssl rand -base64 32)" \
-e VAULTCTL_ENUMERATION_PEPPER="$(openssl rand -base64 32)" \
-e VAULTCTL_DATA_ENCRYPTION_KEY="$(openssl rand -base64 32)" \
vineethnkrishnan/vaultctl:latestAlways put a TLS-terminating reverse proxy (Caddy, nginx, Traefik) in front. Never expose port 8080 directly to the internet.
Docker Compose
Two compose variants are provided in the repository.
Full Stack — Caddy + vaultctl + PostgreSQL
Includes Caddy for automatic HTTPS via Let's Encrypt.
Clone the repository
git clone https://github.com/vineethkrishnan/vaultctl.git
cd vaultctlConfigure environment
cp .env.example .envEdit .env and set these required values:
VAULTCTL_ENV=production
VAULTCTL_BASE_URL=https://vault.yourdomain.com
VAULTCTL_DB_PASSWORD=<generate-a-strong-password>
# Generate each with: openssl rand -base64 32
VAULTCTL_JWT_SECRET_CURRENT=<generate>
VAULTCTL_SERVER_PEPPER=<generate>
VAULTCTL_ENUMERATION_PEPPER=<generate>
VAULTCTL_DATA_ENCRYPTION_KEY=<generate>Generate secrets
for var in JWT_SECRET_CURRENT SERVER_PEPPER ENUMERATION_PEPPER DATA_ENCRYPTION_KEY; do
echo "VAULTCTL_${var}=$(openssl rand -base64 32)"
done >> .envStart services
docker compose up -dVerify
curl https://vault.yourdomain.com/api/v1/health
# → {"status":"ok"}Binary
Pre-built binaries are available on GitHub Releases (opens in a new tab) for all major platforms. Each release includes SHA-256 checksums signed with cosign and per-archive SBOMs.
# amd64
curl -L https://github.com/vineethkrishnan/vaultctl/releases/latest/download/vaultctl_linux_amd64.tar.gz | tar xz
# arm64
curl -L https://github.com/vineethkrishnan/vaultctl/releases/latest/download/vaultctl_linux_arm64.tar.gz | tar xz
sudo mv vaultctl /usr/local/bin/Verify checksums
# Download checksums and signature
curl -LO https://github.com/vineethkrishnan/vaultctl/releases/latest/download/checksums.txt
curl -LO https://github.com/vineethkrishnan/vaultctl/releases/latest/download/checksums.txt.sig
curl -LO https://github.com/vineethkrishnan/vaultctl/releases/latest/download/checksums.txt.pem
# Verify signature
cosign verify-blob checksums.txt \
--signature checksums.txt.sig \
--certificate checksums.txt.pem \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp 'github\.com/vineethkrishnan/vaultctl'
# Verify file integrity
sha256sum -c checksums.txt --ignore-missingPrerequisites
- PostgreSQL 16+ running and accessible
- A reverse proxy (Caddy or nginx) for TLS termination
Run
# Run database migrations
vaultctl migrate up
# Start the server (listens on :8080)
vaultctl serverKubernetes
A Helm chart is planned for a future release. For now, use the Docker image directly:
apiVersion: apps/v1
kind: Deployment
metadata:
name: vaultctl
spec:
replicas: 1
selector:
matchLabels:
app: vaultctl
template:
metadata:
labels:
app: vaultctl
spec:
containers:
- name: vaultctl
image: ghcr.io/vineethkrishnan/vaultctl:latest
ports:
- containerPort: 8080
envFrom:
- secretRef:
name: vaultctl-secrets
livenessProbe:
httpGet:
path: /api/v1/health
port: 8080
initialDelaySeconds: 5
readinessProbe:
httpGet:
path: /api/v1/health
port: 8080
initialDelaySeconds: 3
---
apiVersion: v1
kind: Service
metadata:
name: vaultctl
spec:
selector:
app: vaultctl
ports:
- port: 80
targetPort: 8080Create a Secret with all required environment variables. See the Configuration page for the complete list.
You can use either ghcr.io/vineethkrishnan/vaultctl or vineethnkrishnan/vaultctl (Docker Hub) — both are identical multi-arch images.
Post-Installation
After installation, open your browser and navigate to your server URL.
- Click Create Account
- Follow the Your First Account guide
- Install the Browser Extension
Security reminder: Each cryptographic secret (JWT_SECRET, SERVER_PEPPER, ENUMERATION_PEPPER, DATA_ENCRYPTION_KEY) must be unique. Never reuse secrets across deployments. Store them separately from database backups.