stackctl

module
v0.0.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 29, 2026 License: Apache-2.0

README

stackctl

Small teams and indie projects deserve solid infrastructure tooling — without the enterprise overhead.

stackctl brings together Kubernetes config management, HashiCorp Vault secrets, and NetBird VPN into a single CLI with a consistent interface. The goal is to let a small team operate securely and confidently: secrets are never exposed in plain text, kubeconfigs are stored centrally in Vault, VPN access is automated, and everything can run inside a CI/CD pipeline with no extra tooling.

Whether you are a solo developer, a startup, or a small ops team, stackctl gives you the same security practices used at scale — without the complexity.

go install github.com/eliasmeireles/stackctl/cmd/stackctl@latest

Run stackctl with no arguments to open the interactive TUI.


Vault Authentication

All Vault commands resolve credentials in this order:

Priority Source
1 CLI flags: --addr, --token, --role-id/--secret-id, --k8s-role
2 Env vars: VAULT_ADDR, VAULT_TOKEN, VAULT_ROLE_ID, VAULT_SECRET_ID, VAULT_K8S_ROLE
3 ~/.vault-token file (written by vault login)
Auth method Required
Token VAULT_ADDR + VAULT_TOKEN
AppRole VAULT_ADDR + VAULT_ROLE_ID + VAULT_SECRET_ID
Kubernetes SA VAULT_ADDR + VAULT_K8S_ROLE (+ optional VAULT_K8S_MOUNT_PATH, VAULT_SA_TOKEN_PATH)

Global Flags

Flag Default Description
--output / -o table Output format: table, json, yaml

When --output json or --output yaml is used, decorative emoji and progress messages are suppressed so the output is machine-readable.

stackctl database postgres list --host localhost --admin-user postgres --admin-password secret --output json
stackctl vault secret list --output yaml

Project Context — stackctl context

Avoid repeating --host, --port, --admin-user on every command by storing defaults in a .stackctl.yaml file. The file is searched hierarchically from the current directory up to your home directory.

# Create .stackctl.yaml interactively in the current directory
stackctl context init

# Show the active configuration
stackctl context show

.stackctl.yaml format:

version: "1"
databases:
  postgres:
    host: localhost
    port: 5432
    user: postgres
    vault-login: secret/databases/postgres/admin   # optional
  mysql:
    host: localhost
    port: 3306
    user: root
  mongodb:
    host: localhost
    port: 27017
    user: admin
messagebrokers:
  rabbitmq:
    host: localhost
    port: 5672
    user: guest

Note: Add .stackctl.yaml to your .gitignore — it may contain passwords or Vault paths.

Explicit CLI flags always override context defaults.


Commands

Interactive TUI
stackctl

Navigates all features via a menu. Every sub-menu shows a contextual note explaining what the current step is about, and input screens display the full navigation breadcrumb plus a step counter (step N of M).

Key interactive features:

  • Vault path browsing — navigate the Vault KV tree to pick admin credentials instead of typing a path
  • Auto-generate password — type auto or auto:<size> to generate a random password (printed after TUI exits)
  • Database selection — choose from a numbered list of existing databases or type a new name
  • Missing KV engine — auto-created when a --vault-path target does not exist yet

Automatically retries Vault authentication every 5 seconds if the token is not yet available.

TUI color customization (ANSI 256-color codes):

Env var Default Controls
STACK_CTL_TITLE_COLOR 86 Menu title
STACK_CTL_ITEM_COLOR 86 List items
STACK_CTL_SELECTED_ITEM_COLOR 82 Selected item

Kubeconfig — stackctl kubeconfig
Subcommand Description
list-contexts List all local contexts
get-context <name> [--encode] Print a context (optionally Base64)
set-context <name> Switch current context
set-namespace <ns> [--context <name>] Set default namespace
clean Remove duplicate entries
add Import config (see flags below)
remove <name> Remove a context
save-to-vault <name> Upload context to Vault
add-from-vault <path> Download and merge from Vault
contexts List kubeconfigs stored in Vault

add flags:

Flag Description
<base64> Positional: import from Base64 string
--file <path> Import from local file
--host <ip> --ssh-user <user> Import via SSH
--k3s Use default k3s path (/etc/rancher/k3s/k3s.yaml)
-r <name> Rename the imported context
stackctl kubeconfig add --k3s --host 192.168.1.10 --ssh-user root -r home-lab
stackctl kubeconfig save-to-vault home-lab
stackctl kubeconfig add-from-vault secret/data/kubeconfig/home-lab

Vault — stackctl vault
Secrets
stackctl vault secret list [path]
stackctl vault secret get <path>
stackctl vault secret put <path> key=value [key=value ...]
stackctl vault secret delete <path>

Default list path: secret/metadata/resources/kubeconfig

Policies
stackctl vault policy list
stackctl vault policy get <name>
stackctl vault policy put <name> <file.hcl>
stackctl vault policy delete <name>
Auth methods
stackctl vault auth list
stackctl vault auth enable <type> [--path <path>] [--description <desc>]
stackctl vault auth disable <path>
Secrets engines
stackctl vault engine list
stackctl vault engine enable <type> [--path <path>] [--description <desc>]
stackctl vault engine disable <path>
Roles
stackctl vault role list <auth-mount>
stackctl vault role get <auth-mount> <name>
stackctl vault role put <auth-mount> <name> [flags]
stackctl vault role delete <auth-mount> <name>

role put flags: --bound-sa-names, --bound-sa-namespaces, --policies, --token-policies, --ttl, --token-max-ttl, --secret-id-ttl, --secret-id-num-uses

Declarative apply
stackctl vault apply -f vault-config.yaml

Applies engines → auth → policies → roles → secrets in order. See example/vault-config.yaml.

Fetch (CI/CD)

Fetch a secret and merge it as a kubeconfig, or export fields as env vars. Auth flags (--addr, --token, --role-id, etc.) are inherited from the vault parent command.

stackctl vault fetch \
  --addr $VAULT_ADDR \
  --role-id $VAULT_ROLE_ID --secret-id $VAULT_SECRET_ID \
  --secret-path secret/data/ci/kubeconfig/prod \
  -r prod-cluster
Flag Description
--secret-path KV v2 path to the secret
--secret-field Field to read (default: kubeconfig)
--as-kubeconfig Merge field value (Base64) into local kubeconfig (default)
--export-env Export all fields as environment variables
--github-env Also write to $GITHUB_ENV
-r Rename the context when importing

Secret management — stackctl get secret

Get secrets from Vault and copy to clipboard or save to file. The secret value is never printed to the terminal.

Path handling: All paths are automatically prepended with secret/data/ for KV v2 compatibility.

# Copy a secret to clipboard
stackctl get secret <KEY>

# Get from custom path (secret/data/ is auto-prepended)
stackctl get secret <KEY> --path resources/vps/elias-oracle

# Save to file
stackctl get secret PUB_KEY --path resources/vps/elias-oracle --to-file ~/.ssh/id_rsa.pub

# Decode from base64 before saving
stackctl get secret ENCODED_KEY --path apps/production --to-file ./decoded.txt --decode-from-b64

# Replace existing file
stackctl get secret PUB_KEY --to-file ~/.ssh/id_rsa.pub --replace

Flags:

Flag Description
--path <path> Vault path (without secret/data/ prefix)
--to-file <filepath> Save secret to file instead of clipboard
--decode-from-b64 Decode secret from base64 before saving/copying
--replace Replace file if it already exists (only with --to-file)
STACK_CTL_DEFAULT_SECRET_PATH Env var to set default path (without secret/data/ prefix)
(default path) users/all/passwords (becomes secret/data/users/all/passwords)

Password management commands:

# Add a password (auto-generated if --pass omitted; auto-gen is also copied to clipboard)
stackctl add pass <KEY> [--pass <value>] [--size <bytes>]

# Update a password
stackctl update pass <KEY> [--pass <value>] [--size <bytes>]

# Delete a password
stackctl delete pass <KEY>

Generate — stackctl generate

Generate random passwords and usernames, automatically copied to the clipboard.

# Generate a random password (copied to clipboard)
stackctl generate password

# Generate a password of a specific size (bytes of entropy)
stackctl generate password --size 32

# Generate a random username
stackctl generate username

# Print value instead of copying (useful in scripts)
stackctl generate password --output json

When the clipboard is unavailable (e.g. in CI/CD), the generated value is saved to ~/.stackctl/pass.


NetBird VPN — stackctl netbird
stackctl netbird install
stackctl netbird up --netbird-key <key> [--api-host <host>] [--wait-dns]
stackctl netbird status
Env var Description
STACK_CLT_NETBIRD_KEY Setup key
API_HOST Management API host (default: api.netbird.io)

Database Management — stackctl database

Manage databases, users, schemas, and test connections (PostgreSQL, MySQL, MongoDB).

Commands follow a db-type-first hierarchy: stackctl database {postgres|mysql|mongodb} {list|create|delete|test} ...

# List databases and users
stackctl database postgres list \
  --host localhost \
  --admin-user postgres \
  --admin-password secret

# Create a user (auto-generate password; list existing databases interactively)
stackctl database postgres create user \
  --host localhost \
  --admin-user postgres \
  --admin-password secret \
  --username myapp_user \
  --password auto \
  --vault-path secret/databases/postgres/myapp_user

# Create a user with explicit password and database
stackctl database postgres create user \
  --vault-login secret/databases/postgres/admin \
  --username myapp_user \
  --password myapp_pass \
  --database myapp_db \
  --vault-path secret/databases/postgres/myapp_user

# Delete a user — omit --username to see a numbered list and select interactively
stackctl database postgres delete user \
  --host localhost \
  --admin-user postgres \
  --admin-password secret

# Delete a specific user directly (prompts for irreversible-action confirmation)
stackctl database postgres delete user \
  --host localhost \
  --admin-user postgres \
  --admin-password secret \
  --username old_user

# Delete a database — omit --database to select from list; --force skips confirmation
stackctl database postgres delete database \
  --host localhost \
  --admin-user postgres \
  --admin-password secret \
  --database old_db \
  --force

# Test user credentials
stackctl database postgres test user \
  --host localhost \
  --username myapp_user \
  --password myapp_pass \
  --database myapp_db

Supported databases: PostgreSQL · MySQL · MongoDB

See DATABASE_COMMANDS.md for the full command reference.


Message Broker Management — stackctl messagebroker

Manage message broker users and credentials (RabbitMQ).

# Create a RabbitMQ user
stackctl messagebroker rabbitmq create user \
  --host localhost \
  --admin-user admin \
  --admin-password secret \
  --username myapp_user \
  --password myapp_pass \
  --tags "administrator,management" \
  --vault-path secret/messagebroker/rabbitmq/myapp_user

# List all users
stackctl messagebroker rabbitmq list user \
  --host localhost \
  --admin-user admin \
  --admin-password secret

# Delete a user — omit --username to see a numbered list and select interactively
stackctl messagebroker rabbitmq delete user \
  --host localhost \
  --admin-user admin \
  --admin-password secret

# Test user credentials
stackctl messagebroker rabbitmq test-user \
  --host localhost \
  --username myapp_user \
  --password myapp_pass

Supported message brokers: RabbitMQ

Common RabbitMQ tags: administrator · management · policymaker · monitoring

See MESSAGEBROKER_COMMANDS.md for the full command reference.


CI/CD example (GitHub Actions)

- name: Install stackctl
  run: go install github.com/eliasmeireles/stackctl/cmd/stackctl@latest

- name: Connect VPN
  run: |
    stackctl netbird install
    stackctl netbird up --netbird-key ${{ secrets.NETBIRD_KEY }} --wait-dns

- name: Fetch kubeconfig
  env:
    VAULT_ADDR: ${{ secrets.VAULT_ADDR }}
    VAULT_ROLE_ID: ${{ secrets.VAULT_ROLE_ID }}
    VAULT_SECRET_ID: ${{ secrets.VAULT_SECRET_ID }}
  run: |
    stackctl vault fetch \
      --secret-path secret/data/ci/kubeconfig/prod \
      -r prod-cluster

- name: Deploy
  run: kubectl apply -f k8s/

Testing

Running Tests
# Run all tests
make test

# Run tests with coverage
go test -cover ./...

# Run specific package tests
go test ./cmd/stackctl/cmd/vault/...
Local Development Environment

For integration testing and local development, you can spin up a complete Vault + Kubernetes environment using Multipass:

# Bootstrap a local k3s cluster with Vault
make multipass

# This creates a VM with:
# - k3s Kubernetes cluster
# - HashiCorp Vault (auto-initialized and unsealed)
# - NGINX Ingress Controller
# - stackctl CLI pre-installed

See .dev/multipass/README.md for detailed setup instructions and requirements.


Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Directories

Path Synopsis
cmd
stackctl command
stackctl/cmd/context
Package context provides the `stackctl context` subcommand for managing project-level .stackctl.yaml configuration files.
Package context provides the `stackctl context` subcommand for managing project-level .stackctl.yaml configuration files.
stackctl/internal/context
Package context provides hierarchical project-level configuration for stackctl.
Package context provides hierarchical project-level configuration for stackctl.
stackctl/internal/feature/kubeconfig
Package kubeconfig provides Kubernetes configuration management capabilities.
Package kubeconfig provides Kubernetes configuration management capabilities.
stackctl/internal/output
Package output provides structured output formatting for the stackctl CLI.
Package output provides structured output formatting for the stackctl CLI.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL