Skip to main content

Cloud tools collection -- AWS infrastructure, CDN, and DevOps automation

Project description

Granny

One CLI for the cloud chores you'd otherwise do across six tabs.

granny is a pragmatic, multi-provider DevOps toolkit with a strong bias toward European cloud infrastructure. It wraps the parts of provider APIs you actually use day-to-day — Bunny pull zones, Cloudflare DNS, Hetzner S3, Scaleway functions, Mailjet sender setup, INWX zones, AWS Lambda inventory — behind a single command:

granny dns add api.example.com --type A --value 203.0.113.4 --provider hetzner
granny cdn purge 12345
granny storage bunny upload my-zone ./dist
granny credentials status

What it is

  • Pragmatic, not exhaustive. Granny implements the parts of each provider API the maintainers needed in production. It will not cover every endpoint of every service — and it will not pretend to. Add what you need; the contributor guide explains how.
  • Multi-cloud, with a European tilt. First-class support for Bunny, Cloudflare, Hetzner, deSEC, ClouDNS, INWX, Scaleway, and Mailjet alongside AWS S3 / Lambda / WorkMail. The cloud world doesn't end at AWS, and granny doesn't pretend it does.
  • Secrets done right. Every credential goes through one resolver chain — environment variable first, optional Vaultwarden vault second, never hardcoded. .env and .deploy.env are auto-loaded; vault support is a one-line activation when you want it.
  • Library or CLI. Every CLI subcommand is a thin shim over a small Python module. Import granny.dns.cloudflare, granny.cdn.bunny, granny.cloudflare.d1 directly when you need to script something the CLI doesn't expose yet.
  • Small, composable, no plugin system. The whole package is one pip install away. No daemon, no service, no opinionated framework. Drop it into your CI image and call it a day.

Install

pip install granny-devops
# or
uv add granny-devops

Optional extras enable additional providers:

pip install "granny-devops[gcp]"     # GCP for granny analyze (gpus|credits|costs)
pip install "granny-devops[azure]"   # Azure for granny analyze (gpus|credits|costs)
pip install "granny-devops[cdn]"     # Cloudflare, Hetzner DNS

Tagged releases land on pypi.org and the public GitLab PyPI registry in parallel. If PyPI is propagating slowly, fall back to the registry:

pip install --extra-index-url https://gitlab.com/api/v4/projects/81189862/packages/pypi/simple granny-devops

For Vaultwarden (Locke) credential resolution, install separately:

pip install "locke @ git+https://gitlab.com/martin-wieser/locke.git#subdirectory=python"

Configure

Granny reads secrets from environment variables, falling back to a Vaultwarden vault when Locke is installed. Copy the example and fill in what you need:

cp .env.example .env

Common keys:

Provider Variables
Bunny BUNNY_API_KEY (+ BUNNY_API_KEY_<CUSTOMER> for multi-account)
Cloudflare CLOUDFLARE_API_TOKEN
Hetzner HETZNER_S3_ACCESS_KEY, HETZNER_S3_SECRET_KEY, HETZNER_DNS_API_TOKEN
Scaleway SCW_ACCESS_KEY, SCW_SECRET_KEY, SCW_DEFAULT_PROJECT_ID
Mailjet MAILJET_API_KEY, MAILJET_SECRET_KEY
deSEC DESEC_API_TOKEN
ClouDNS CLOUDNS_AUTH_ID/_PASSWORD (or _SUB_AUTH_ID/_SUB_AUTH_USER)
INWX INWX_USERNAME, INWX_PASSWORD, INWX_SHARED_SECRET (only with 2FA)
Docker Hub DOCKER_HUB_USER, DOCKER_HUB_TOKEN

Set only the ones you need. Use granny credentials status to verify what's configured at any time.

Use

granny --help                          # see every command group
granny <group> --help                  # drill into one

The CLI is organized by capability, not by provider. You pick the provider per command:

# DNS — same command, any of seven providers
granny dns list example.com --provider cloudflare
granny dns add www.example.com --type CNAME --value example.com --provider bunny
granny dns nameservers example.com --provider inwx

# CDN — Bunny pull zones
granny cdn list-zones
granny cdn purge 12345
granny cdn ssl www.example.com --dns01

# Object storage — three providers, one verb set
granny storage bunny create my-assets --region DE
granny storage hetzner create my-bucket --region fsn1 --public
granny storage aws create my-website --website

# AWS inventory (read-only)
granny analyze vpcs --json-output
granny analyze lambdas --region us-east-1 eu-west-1

# Cross-cloud GPU / credit / cost inventory (AWS + GCP + Azure)
granny analyze gpus                                # running GPUs everywhere
granny analyze gpus --filter h100,h200             # find Hopper clusters
granny analyze gpus --include-reserved             # also capacity blocks / RIs
granny analyze gpus --provider aws --profile prod --profile dev
granny analyze credits                             # available balances
granny analyze costs                               # MTD + month-end forecast

# Cloudflare account resources (Workers, D1, R2, KV)
granny cloudflare d1 create my-app
granny cloudflare r2 create my-app-media
granny cloudflare site provision my-app --secret-from-vault MAILJET_API_KEY

# Multi-arch Docker builds with deterministic tags
granny docker build-base --image myapp-base --hash-file requirements.txt

# Scaleway FaaS
granny serverless deploy my-fn --source-dir ./dist --namespace my-app

# Mailjet + WorkMail
granny email mailjet setup-dns example.com
granny email workmail create-user example.com --email user@example.com

# One-shot infrastructure provisioning (dispatches granny/create/*.py)
granny create s3-website example.com --help
granny create scaleway-container --name my-app --port 3000
granny create mailjet-dns example.com

Capability matrix

Capability Providers
DNS Cloudflare, Bunny, Hetzner, deSEC, ClouDNS, INWX, manual
CDN Bunny
Edge scripting Bunny
Object storage AWS S3, Bunny Storage, Hetzner S3
Serverless functions Scaleway FaaS, Scaleway Containers
Workers / KV / D1 / R2 Cloudflare
Email send infra Mailjet, AWS SES, AWS WorkMail
AWS inventory VPCs, Lambdas
Cross-cloud inventory GPU instances + reservations, credit balances, MTD spend + forecast (AWS, GCP, Azure)
SSL automation Bunny, Cloudflare, ACM

As a library

Every CLI command is a thin wrapper. Import the underlying module when the CLI doesn't have what you need:

from granny.dns.factory import get_provider
from granny.cloudflare.d1 import D1Client
from granny.credentials import get_secret, load_secrets_into_env

# Multi-provider DNS
dns = get_provider("inwx")
zone = dns.get_zone_id("example.com")
dns.upsert_record(zone, "_acme-challenge", "TXT", "abc-token", ttl=300)

# Cloudflare D1 directly
db = D1Client().create_database("my-app", primary_location_hint="weur")

# Bulk-load registered secrets into os.environ for downstream tools
load_secrets_into_env()

Project layout

granny/
  cli/           Click command groups (granny <group> <verb>)
  analyze/      Cross-cloud inventory (AWS, GCP, Azure)
  cdn/          Bunny CDN
  cloudflare/   Cloudflare Workers / D1 / R2 / KV
  create/       Standalone setup scripts (granny create <name>)
  credentials/  Env + vault secret resolution
  dns/          Provider-agnostic DNS CRUD
  docker/       Multi-arch image builds
  edge/         Bunny Edge Scripting
  email/        Mailjet, WorkMail, SES forwarding
  serverless/   Scaleway FaaS
  storage/      Object storage (AWS / Bunny / Hetzner)

Where to look next

  • Project_Guidelines.md — contributor toolchain, conventions, extension checklists, release flow.
  • AGENTS.md — instructions for AI coding agents working in the repository (Claude Code reads CLAUDE.md which imports this).
  • .env.example — full list of supported environment variables.
  • granny --help and granny <group> --help — authoritative command docs, always in sync with the installed version.

License

MIT — see LICENSE. Built and maintained by Martin Wieser.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

granny_devops-0.7.0.tar.gz (212.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

granny_devops-0.7.0-py3-none-any.whl (251.6 kB view details)

Uploaded Python 3

File details

Details for the file granny_devops-0.7.0.tar.gz.

File metadata

  • Download URL: granny_devops-0.7.0.tar.gz
  • Upload date:
  • Size: 212.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for granny_devops-0.7.0.tar.gz
Algorithm Hash digest
SHA256 5307712d070bf5ecfb08bca5ce41fe6f268d73115eb3348963b2d59f909e054f
MD5 4e206f242dbfe6887541cb963cd4ef46
BLAKE2b-256 77a7ee7dc116b5a02ce2be39bb0dd1cc7bdcd594378e77e9c6ced2904a9cbc09

See more details on using hashes here.

File details

Details for the file granny_devops-0.7.0-py3-none-any.whl.

File metadata

  • Download URL: granny_devops-0.7.0-py3-none-any.whl
  • Upload date:
  • Size: 251.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for granny_devops-0.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3c0529b8d3bcbf066bb062a11783cce10c9918cda82e9efde6896be2c67754c9
MD5 f78020a72f8d1c67402d995745be2869
BLAKE2b-256 b27cbdad598de1aa9030e23d7d219226f2b9ea9ed88e7865b4a7a4774ca8e0b8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page