GitHub

On this page

HashiCorp Vault Setup & Configuration

This guide covers the setup, configuration, and usage of HashiCorp Vault for secrets management at Orcta Technologies.

Overview

HashiCorp Vault is our centralized secrets management solution. It provides:

  • Centralized secret storage - All credentials in one secure location
  • Dynamic credentials - Auto-rotating database passwords
  • Audit logging - Complete trail of who accessed what
  • Least privilege access - Role-based policies for team members
  • Encryption as a service - Transit engine for data encryption

Current Setup

  • Vault Version: v2.0.3
  • Storage Backend: File (/opt/vault/data)
  • Listener: localhost:8200 (proxied via Caddy)
  • UI: Available at https://vault.orctatech.com/ui
  • Service: vault.service (systemd, starts on boot)

Access Points

Direct Access (via Tailscale)

ssh orcta_vps
export VAULT_SKIP_VERIFY=true
export VAULT_ADDR='https://127.0.0.1:8200'
vault login -method=userpass username=cto password='your-password'

Web UI Access

https://vault.orctatech.com/ui

Note: Requires DNS record vault.orctatech.com158.220.100.30

Team Access

Role Username Access Level Use Case
CTO cto Full access Infrastructure, secret rotation
DevOps devops Read all, write infra Deployment, monitoring
Developer developer1 Read-only dev/services Local development
CI/CD cicd Write CI, read services GitHub Actions, pipelines

Secret Structure

secret/
├── orcta/
│   ├── pss/                    # PSS Backend
│   │   ├── database            # PostgreSQL credentials
│   │   ├── valkey              # Valkey/Redis credentials
│   │   ├── jwt                 # JWT secrets
│   │   ├── uploadthing         # File upload service
│   │   ├── email               # Email service (Resend)
│   │   ├── auth                # Better Auth secrets
│   │   └── app                 # Application config
│   ├── stack/                  # Orcta Stack
│   ├── mentorship/             # Mentorship Platform
│   ├── docs-mcp/               # Documentation MCP
│   ├── dev/                    # Development secrets
│   ├── prod/                   # Production secrets
│   ├── infra/                  # Infrastructure secrets
│   └── admin/                  # Admin credentials

Common Operations

Login

export VAULT_SKIP_VERIFY=true
export VAULT_ADDR='https://127.0.0.1:8200'
vault login -method=userpass username=YOUR_USERNAME password=YOUR_PASSWORD

Read a Secret

vault kv get secret/orcta/pss/database
vault kv get -field=password secret/orcta/pss/database

Write a Secret

vault kv put secret/orcta/myapp/config \
  api_key="abc123" \
  db_password="secret456"

List Secrets

vault kv list secret/orcta/
vault kv list secret/orcta/pss/

Delete a Secret

vault kv delete secret/orcta/pss/old-secret

PSS Backend Integration

The PSS backend was our pilot project for Vault integration.

Fetch Script

/usr/local/bin/fetch-pss-secrets

This script:

  1. Authenticates to Vault
  2. Fetches all PSS secrets
  3. Generates .env file at /srv/apps/ORCTA-BACKEND-PSS/.env

Usage

# Manual fetch
/usr/local/bin/fetch-pss-secrets

# Or integrate into deployment
./fetch-pss-secrets && docker compose up -d

Caddy Proxy Configuration

Vault is proxied through Caddy for HTTPS access:

vault.orctatech.com {
    reverse_proxy localhost:8200 {
        transport http {
            tls_insecure_skip_verify
        }
    }
    encode zstd gzip
    log {
        output file /var/log/caddy/vault.access.log
        format json
    }
    import security
    
    header {
        X-Frame-Options "SAMEORIGIN"
    }
}

Unsealing Vault

Vault seals on restart and requires 3 of 5 unseal keys:

vault operator unseal <key1>
vault operator unseal <key2>
vault operator unseal <key3>

Unseal Keys (stored securely offline):

1. 7GUabmWbJNrw3IHRiBCugkCsaghxAGIrf7Cq0Kx27d+N
2. u053Y77SME9N5jXdlOosmuAnXHueO8nPC0J9DdZIhdIH
3. rsTB0S4oDjkHjB4UU+YZdjcS/EslKKNzByXTKcDNgoYV
4. kRrQcZ5J01jiSExyOO7GWQQkaTvX+Z0pWMC9daifBbje
5. oyQqHhJ1FfHXcIcf3dJ+3pEudqF7Rt0tUwjW8ZzJxdaq

Audit Logging

All Vault operations are logged to /var/log/vault/audit.log.

View Logs

sudo tail -f /var/log/vault/audit.log

Search for User

sudo grep "username" /var/log/vault/audit.log

systemd Service

Vault runs as a systemd service:

# Check status
sudo systemctl status vault

# Restart
sudo systemctl restart vault

# View logs
sudo journalctl -u vault -f

Security Best Practices

Do’s

✅ Use short-lived tokens - Login again when token expires
✅ Store tokens securely - Never commit to git
✅ Use least privilege - Only access what you need
✅ Rotate secrets regularly - Use Vault’s rotation features
✅ Audit access - Check /var/log/vault/audit.log

Don’ts

❌ Never hardcode secrets - Always use Vault
❌ Never share tokens - Each user gets their own
❌ Never store tokens in git - Use .gitignore
❌ Never use root token - Use your personal token
❌ Never disable audit logging - Compliance requirement

Troubleshooting

“Permission Denied” Error

# Check your policies
vault token lookup

# Check what you can access
vault kv list secret/orcta/

“Vault is Sealed” Error

# Unseal Vault (need 3 of 5 keys)
vault operator unseal <key1>
vault operator unseal <key2>
vault operator unseal <key3>

“Token Expired” Error

# Re-login
vault login -method=userpass username=YOUR_USERNAME password=YOUR_PASSWORD

Check Audit Logs

# View recent audit events
sudo tail -f /var/log/vault/audit.log

# Search for specific user
sudo grep "username" /var/log/vault/audit.log

Environment Variables

Set these in your shell profile (~/.bashrc or ~/.zshrc):

# Vault
export VAULT_SKIP_VERIFY=true
export VAULT_ADDR='https://127.0.0.1:8200'

# Or for remote access via Tailscale
export VAULT_ADDR='https://100.125.3.44:8200'

API Usage

REST API Example

# Login
curl -s -k -X POST https://127.0.0.1:8200/v1/auth/userpass/login/cto \
  -d '{"password":"your-password"}'

# Read secret
curl -s -k -H "X-Vault-Token: YOUR_TOKEN" \
  https://127.0.0.1:8200/v1/secret/data/orcta/pss/database

# Write secret
curl -s -k -X POST -H "X-Vault-Token: YOUR_TOKEN" \
  -d '{"data":{"key":"value"}}' \
  https://127.0.0.1:8200/v1/secret/data/orcta/myapp/config

JavaScript/Node.js

const axios = require('axios');

const VAULT_ADDR = 'https://127.0.0.1:8200';
const VAULT_TOKEN = 'your-token';

async function getSecret(path) {
  const response = await axios.get(
    `${VAULT_ADDR}/v1/secret/data/${path}`,
    { 
      headers: { 'X-Vault-Token': VAULT_TOKEN },
      httpsAgent: new (require('https').Agent)({ rejectUnauthorized: false })
    }
  );
  return response.data.data.data;
}

// Usage
const dbSecret = await getSecret('orcta/pss/database');
console.log(dbSecret.password);

Backup & Recovery

Backup

# Backup Vault data
sudo tar -czf /backup/vault-backup-$(date +%Y%m%d).tar.gz /opt/vault/data

Recovery

# Stop Vault
sudo systemctl stop vault

# Restore data
sudo tar -xzf /backup/vault-backup-YYYYMMDD.tar.gz -C /

# Start Vault
sudo systemctl start vault

# Unseal
vault operator unseal <key1>
vault operator unseal <key2>
vault operator unseal <key3>

Next Steps

Support

Edit this page
Last modified: 2026-08-03