Skip to content

x71c9/dogma

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dogma

Bridges secrets from vault backends and infrastructure outputs into sops-encrypted files, then deploys them to NixOS machines. Also spawns pre-credentialed shells and exports all secrets as environment variables.

Crate: dogma-rust — Binary: dogma

Quick start

# dogma.yml
name: myproject
env: [dev, prod]
admin:
  - gpg: 3246EC6F403D8F3403E34A90BCDABC277B1ED8AB

vault:
  hcloud-token:
    pass: myproject/{env}/hcloud-token
  stripe-webhook-secret:
    pass: myproject/{env}/stripe-webhook-secret

infra:
  credentials:
    TF_VAR_hcloud_token:
      from: vault
      ref: hcloud-token

machines:
  backend:
    hostname: myproject-{env}
    ip: { from: infra, unit: hetzner, output: server_ip }
    secrets: [backend]

secrets:
  backend:
    stripe_webhook_secret: { from: vault, ref: stripe-webhook-secret }
    server_ip: { from: infra, unit: hetzner, output: server_ip }
$ dogma deploy prod --new
dogma: checking dependencies...
dogma: normalizing config...
dogma: refreshing infra cache (hetzner)...
dogma: generating .sops.yaml from SSH host keys...
dogma: encrypting secrets for myproject-prod...
dogma: deploying backend (1.2.3.4)...
  → nixos-rebuild switch --target-host root@1.2.3.4 --flake .#myproject-prod
dogma: tagging deploy/v26.06.0001
dogma: done in 142s
$ dogma infra apply prod hetzner
dogma: normalizing config...
dogma: resolving credentials...
dogma: tofu init...
dogma: tofu apply...
  hcloud_server.backend: Creating...
  hcloud_server.backend: Creation complete (id=12345678)
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
$ dogma shell prod
dogma: resolving TF_VAR_hcloud_token...
dogma: entering prod shell (exit to return)
[dogma-prod 14:23:01] ~/myproject $
$ dogma env prod
export BACKEND_STRIPE_WEBHOOK_SECRET='whsec_...'
export BACKEND_SERVER_IP='1.2.3.4'

Install

cargo install dogma-rust          # binary installed as `dogma`
# or from source
cargo build --release             # binary at target/release/dogma

Set DOGMA_VAULT per developer in .bashrc or per project in shell.nix:

export DOGMA_VAULT=pass           # or: envvar (default)

Shell completion

Bash — add to ~/.bashrc:

source <(dogma completions bash)

Zsh — add to ~/.zshrc:

source <(dogma completions zsh)

Fish — install once:

dogma completions fish > ~/.config/fish/completions/dogma.fish

<env> is completed from dogma.yml. <unit> is completed from subdirectories of infra.path. <host> is completed from machine names in dogma.yml.

Commands

dogma credentials <env>

Prints export VAR='value' for all infra.credentials. Eval to load.

eval $(dogma credentials dev)

dogma env <env>

Prints export GROUP_FIELD='value' for every secret, uppercased.

eval $(dogma env dev)
# → export BACKEND_API_KEY='...'
# → export BACKEND_SERVER_IP='...'

dogma output <env> [unit] [key]

Reads from .dogma/cache/<env>.json.

dogma output dev                        # full JSON
dogma output dev hetzner                # one unit
dogma output dev hetzner server_ip      # raw value

dogma shell <env>

Spawns a new shell with infra.credentials loaded. Prompt shows [dogma-<env> HH:MM:SS]. Exit to return.

dogma shell dev

dogma infra apply <env> <unit>

Runs: normalize → validate → tofu inittofu apply. Credentials injected as env vars.

dogma infra apply dev hetzner
dogma infra apply dev hetzner --migrate-state

dogma infra destroy <env> <unit>

Same as apply but runs tofu destroy.


dogma deploy <env> [host]

Full deploy pipeline.

dogma deploy dev --new                         # new CalVer version, full pipeline
dogma deploy dev --latest                      # promote latest deploy/* tag
dogma deploy dev --version deploy/v26.06.0001  # promote specific tag
dogma deploy dev                               # interactive: pick from tag list
dogma deploy dev backend --new                 # one host only

--new pipeline:

Step Action
0 Dep check: ssh-keyscan, ssh-to-age, sops, nixos-rebuild
1 Normalize + validate dogma.yml
2 Dirty tree check — commit or abort
3 Pre-deploy hooks
4 Infra cache refresh (all envs)
5 Generate .sops.yaml from SSH host keys
6 Encrypt secrets with sops, commit
7 nixos-rebuild switch per host
8 Git tags + push
9 Post-deploy hooks

Flags:

Flag Description
--new Create new CalVer version, run full pipeline
--latest Promote latest deploy/* tag (no hooks)
--version <tag> Promote specific tag (no hooks)
--skip-infra Use existing infra cache
--skip-sops Use existing .sops.yaml
--refetch Clear all caches and re-fetch
-m <msg> Commit message for dirty tree (only with --new)

--time

Global flag. Prints elapsed ms to stderr after any command.

dogma --time deploy dev --new

dogma.yml reference

name: myproject             # used in auto-derived vault paths

env:                        # list of environments
  - dev
  - prod

admin:                      # age/gpg/ssh keys for sops encryption
  - gpg: <fingerprint>
  - age: age1...
  - ssh: ~/.ssh/id_ed25519.pub

infra:
  cli: tofu                 # or: terraform (default: tofu)
  path: ./infra             # default: ./infra
  credentials:
    STATIC_VAR: value       # injected as-is into tofu
    SECRET_VAR:
      from: vault
      ref: <vault-key>

vault:
  <key>:
    pass: path/{env}/key    # {env} substituted per environment
    envvar: MY_VAR          # flat string or per-env map; auto-derived if omitted

machines:
  <name>:
    hostname: host-{env}    # {env} substituted; or per-env map
    user: deployer          # default: root
    ip: "1.2.3.4"           # static IP
    ip:                     # or from infra output
      from: infra
      unit: <unit>
      output: <output-key>
    secrets:                # secret groups to encrypt for this machine
      - <group>
    deployer: nixos-rebuild # default; only option currently

secrets:
  <group>:
    <field>:
      from: vault
      ref: <vault-key>
    <field>:
      from: infra
      unit: <unit>
      output: <output-key>

nix:
  path: ./nix               # default: ./nix
  secrets: ./nix/secrets    # default: ./nix/secrets
  sops: ./nix/.sops.yaml    # default: ./nix/.sops.yaml

deploy:
  strategy: nixos-rebuild   # default

hooks:
  pre-deploy:
    - ./custom/bump-version.sh
  post-deploy:
    - ./custom/notify-slack.sh

Vault backends

Set DOGMA_VAULT per developer — not in dogma.yml.

Backend DOGMA_VAULT How it resolves
envvar (default) Reads $VAR from process env. Var name from vault.<key>.envvar.<env>, auto-derived as UPPER_SNAKE if omitted
pass pass Calls pass <path>. Path from vault.<key>.pass.<env>, auto-derived as <name>/<env>/<key> if omitted

Hooks

Scripts must be executable. Both hooks receive:

Variable Example Notes
DOGMA_VERSION deploy/v26.06.0001 CalVer tag
DOGMA_ENV dev Target environment
DOGMA_HOSTS backend\nworker Newline-separated machine names
DOGMA_DEPLOYED_IPS deployer@1.2.3.4 Post-deploy only
#!/usr/bin/env bash
# custom/bump-version.sh — write version into package.json
version="${DOGMA_VERSION#deploy/}"
jq --arg v "$version" '.version = $v' backend/package.json > tmp && mv tmp backend/package.json

Generated files

Add to .gitignore:

.dogma/dogma-expanded.yml
.dogma/cache/
.dogma/age-keys/
File Purpose
.dogma/dogma-expanded.yml Normalized config with all defaults filled in
.dogma/cache/<env>.json Cached infra outputs
.dogma/age-keys/<host>.pub Cached SSH→age host keys

Runtime dependencies

The binary runs on any Linux with no runtime deps. External tools are checked lazily — only when the command that needs them actually runs.

Tool Required by
pass DOGMA_VAULT=pass
tofu / terraform infra apply, infra destroy, deploy
ssh-keyscan deploy --new
ssh-to-age deploy --new
sops deploy --new
nixos-rebuild deploy (nixos-rebuild strategy)

About

CLI to bridge secrets from any vault backend and infra outputs into sops-encrypted files, deployed to your machines — driven by a single dogma.yml

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors