No description
  • Lua 66.7%
  • Go 10.9%
  • Shell 9.5%
  • Rust 7.1%
  • CSS 1.9%
  • Other 3.9%
Find a file
15ebd47c fc3843f5c7
Some checks failed
Build Files / build (push) Successful in 9s
Tests / lua-tests (push) Failing after 10s
Build Press / build (push) Successful in 4s
Doctor checks and repairs overlay network before setup hooks
When the VXLAN tunnel breaks (a known Docker Swarm failure mode),
every container's overlay interface goes DOWN. Services report as
running but can't communicate. Walk says , setup hooks hang.

Doctor now checks overlay health first — reads eth0 operstate from
any container on the sweetgrass network. If it's down:
  1. Diagnoses: "overlay network down — services can't communicate"
  2. Treats: rolling Docker restart on each node
  3. Verifies: overlay recovered before proceeding to setup hooks

This is the pattern for doctor going forward: check the foundation
before checking what's built on it. The overlay is the foundation.
2026-04-19 05:53:48 +00:00
.claude/memory Remove site_domain from enrollment, move to provisioning 2026-04-11 02:22:29 +00:00
.forgejo/workflows feat: files stack — personal file sharing with WebDAV sync 2026-04-08 01:01:45 +00:00
ci CI/CD: separate build from deploy, shared push-image script 2026-04-02 01:39:30 +00:00
domains Self-hosted DNS as default, postgres in core 2026-04-19 03:29:47 +00:00
garden Fix dns stack: schema init in pre_deploy, resolved fix, path corrections 2026-04-19 05:27:16 +00:00
keepers Rename stewards → keepers 2026-04-19 01:01:58 +00:00
lua Doctor checks and repairs overlay network before setup hooks 2026-04-19 05:53:48 +00:00
plant Hetzner Cloud DNS as automatic secondary 2026-04-19 04:17:38 +00:00
seeds Move 13 media file(s) to asset storage 2026-04-14 05:11:00 +00:00
weeds Route initial render through NATS instead of fragile webhook forgery 2026-04-16 17:41:55 +00:00
.dev-keys.example Add --dev flag for installing dev SSH keys 2026-01-16 02:49:34 +00:00
.gitignore plant: restore by default, --fresh to skip; fix render trigger 2026-04-05 18:24:11 +00:00
.pressignore Repo is the site: stacks→garden rename, .pressignore, content at root 2026-03-23 03:29:15 +00:00
_BUILDING.md Remove startup framing from docs, fix plant.lua arg parsing 2026-04-12 18:45:26 +00:00
_BYOH.md Hetzner default + BYOH docs 2026-03-25 23:11:57 +00:00
_CONVERGENCE.md Update convergence doc: .social planted, soil rename, cert fix 2026-04-18 23:22:18 +00:00
_DIGITALOCEAN.md Seed template: drop combination count, use FQDN, rename clone dir 2026-03-28 03:26:51 +00:00
_GARDEN.md Remove startup framing from docs, fix plant.lua arg parsing 2026-04-12 18:45:26 +00:00
_GOTCHAS.md tend: consolidate check + status into walk 2026-04-02 18:46:18 +00:00
_LEGAL.md docs: fix stale references, broken links, and underscore convention 2026-04-03 23:19:17 +00:00
_PLAN-assets.md Convergence plan: rewrite as concurrent workstreams 2026-04-11 18:50:23 +00:00
_PLAN-garden-scope.md Remove domain-scoping: all stacks are garden-scoped 2026-04-18 02:55:46 +00:00
_PLAN-invite-flow.md Convergence plan: rewrite as concurrent workstreams 2026-04-11 18:50:23 +00:00
_PLAN-next.md Convergence plan: rewrite as concurrent workstreams 2026-04-11 18:50:23 +00:00
_PRESS.md Remove startup framing from docs, fix plant.lua arg parsing 2026-04-12 18:45:26 +00:00
_QUICKSTART.md tend: consolidate check + status into walk 2026-04-02 18:46:18 +00:00
_RECOVERY.md Rename remove to prune, add domain and node pruning 2026-04-13 01:43:39 +00:00
_TODO.md Sync convergence doc and TODO from walk output 2026-04-17 01:14:29 +00:00
_WELL-KNOWN.md well-known convention, status banner, env export fix 2026-04-09 19:37:28 +00:00
about.md Rewrite index opening, drop stale 7k line count everywhere 2026-03-27 17:59:50 +00:00
config.lua.example tend: split commands into modules, update stale documentation 2026-04-02 04:14:05 +00:00
index.md Fix share preview: deduplicate title, add descriptions 2026-03-27 18:19:31 +00:00
LICENSE.txt Update LICENSE.txt 2026-01-12 06:00:28 +00:00
plant.lua Hetzner Cloud DNS as automatic secondary 2026-04-19 04:17:38 +00:00
prepare.sh Hetzner default in plant guide + DigitalOcean alternative doc 2026-03-26 05:22:03 +00:00
privacy.md privacy: backup retention split, identity privacy link, policy additions 2026-04-09 01:47:56 +00:00
README.md Remove startup framing from docs, fix plant.lua arg parsing 2026-04-12 18:45:26 +00:00
social-contract.md Update social-contract.md 2026-04-05 00:24:45 +00:00
tend.lua Rename provider → soil, fix walk stale message, roots label 2026-04-18 18:52:58 +00:00
test.lua Self-hosted DNS as default, postgres in core 2026-04-19 03:29:47 +00:00

Sweetgrass

Community infrastructure you can understand, modify, and share.


What this is

Sweetgrass is a set of tools for planting and tending your own corner of the internet — websites, publishing, email, git hosting, video calls — on small, affordable servers that you and your friends control.

Think of it like a community garden. You bring the seeds (your domain, your writing, your projects). The tools help you plant and tend. The infrastructure takes care of itself most of the time, and when it doesn't, you can read the code and fix it. All of it.

Where we are

We're building this right now. The tools work — we've planted multiple gardens and each planting gets smoother. Every one teaches us something new.

This is a barn raising, not a finished house. If that appeals to you — if you want to build something with people instead of buying something from a company — you're welcome here.

What you get

Three scripts named for what they do:

plant.lua    Create infrastructure from scratch
tend.lua     Deploy, update, backup, maintain
compost.lua  Tear everything down (safely, backups first)

The cycle is: plant, tend, compost, plant. Data survives destruction by default.

When you plant, you get a self-organizing cluster with:

your site ── static, always on
  identity ── passkeys and single sign-on
    git ──── your repos (Forgejo)
      press ── push markdown, get a website
        meet ── video conferencing (Jitsi)
  mail ──── email + webmail (docker-mailserver)

Automatic SSL. Encrypted daily backups. Rolling updates with zero downtime. Self-healing via Docker Swarm. The core stack (static through press) fits on a single small server. A 3-node cluster gives you failover and room for meet.

Two ways in

However you join, the social contract is the same: resilience through interdependence, no extraction, invite-based trust, portability.

Plant your own. Get together with friends. Pick your domains. Set up a few small servers. This is the way sweetgrass is meant to grow — many small gardens tended by the people who use them, sharing improvements through the same tools. See QUICKSTART.md.

Grow in the community garden. If you don't want to manage your own infrastructure, you're welcome in ours. It's free, it's invite-only, and your stuff is yours — you can transplant to your own garden or a friend's whenever you want. See GARDEN.md.

The philosophy

No magic. Every operation is a readable Lua script. No hidden state, no declarative DSLs, no frameworks. Just scripts that do things you could do by hand, reliably.

No lock-in. Your domains transplant between gardens. Your content is markdown files in git repos. Your infrastructure is standard Docker on standard servers. Nothing traps you here.

No extraction. We want you not to pay us. We want you to plant your own garden with friends and share what you grow. The code is AGPL — improve it, share it back. The more gardens, the more resilient every garden becomes.

Boring on purpose. The infrastructure is meant to be dull. Pages are simple and lightweight. Servers quietly do what they're supposed to. The most exciting thing about sweetgrass is that it works and you can understand why.

By planting sweetgrass, you're doing something quietly subversive. You're building infrastructure that's democratic by design and resistant to the patterns that turn tools into platforms and communities into products. It doesn't look like much. That's the point.

How it works

The tools call standard unix utilities — ssh, rsync, curl — plus your cloud provider's CLI (hcloud, doctl, or none for BYOH). Docker Swarm handles orchestration. We picked Swarm over Kubernetes because you can understand Swarm in an afternoon.

plant.lua              Create and configure infrastructure
tend.lua               Deploy, update, backup, maintain
lua/compost.lua        Full teardown (backups first)

lua/deploy/            Stack deployment, template rendering
lua/backup/            Encrypted backup to S3-compatible storage (restic)
lua/maintain/          Rolling updates, health, scaling
lua/intake.lua         SSH/rsync gateway for static content
lua/roots/             Swarm, DNS, and network primitives
lua/soil/              Provider layer (Hetzner, DigitalOcean, BYOH)

garden/<name>/conf.lua Stack definitions (self-describing)
domains/<name>.lua     Domain configurations

For the full technical story — why Lua, why Swarm, how the pieces fit, what we've learned — see BUILDING.md.

For the publishing system at the heart of it, see PRESS.md.

The name

Sweetgrass is a plant sacred to many Indigenous peoples of North America. It spreads through underground rhizomes, connecting in ways you can't see, binding the soil together. You can't eradicate it once it's established.

We chose the name because that's what we want this to be. Infrastructure that spreads through communities, that's impossible to shut down, that binds people together. Many small gardens, connected underground.

Contributing

This is community infrastructure. If you see something that could be better, make it better. The whole thing is readable. Start with BUILDING.md.

License

AGPL-3.0 — If you improve it, share it back.


Infrastructure doesn't have to be complicated. It doesn't have to be corporate. It can be ours.