No description https://sweetgrass.garden
  • Lua 67.5%
  • Go 20.3%
  • JavaScript 3.7%
  • Rust 3.5%
  • Shell 2.9%
  • Other 2.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
9f357525 3c82f1822f
Some checks failed
Lint / added-lines (push) Successful in 17s
build / build (push) Successful in 57s
Tests / lua-tests (push) Failing after 6m43s
press: comments in the template stay out of rendered pages
Every page shipped the default template's comments, about 5 KB of
developer notes per page on sweetgrass.online, plus qrencode's
"Created with" line inside the QR. press now strips comments once, from
the prepared template, after the unbranded cut (the garden markers are
comments too). Authors' own comments in their content are untouched. An
unclosed comment in a site's template stops the build with a message
instead of swallowing the rest of the template.

The template's comments shrink to what someone customising it needs,
with the slot list corrected (NAV_OPEN, LANG_NAV and SITE_CHANNEL were
missing) and the line-replacing slots named. qrencode's stderr now
reaches the build log.

ci-test.sh asserts no comment reaches the page; watched red at baseline
(19 comments) and with the qrencode deletion undone (1).
2026-10-12 19:07:46 +00:00
.forgejo/workflows fail2ban: our filters can no longer be replaced by the image's, and verify checks that each one catches its attack 2026-10-12 13:14:52 +00:00
ci ci: a "Merge" subject must be a merge; lint-added-lines --worktree checks without staging 2026-10-12 15:19:38 +00:00
groundwork press: comments in the template stay out of rendered pages 2026-10-12 19:07:46 +00:00
keepers/keys keepers: the escrow leaves the repo — public ring versioned, ciphertext never 2026-09-13 19:32:57 +00:00
lua ceph: nodes mount CephFS as the filesystem's own client, never with the admin key 2026-10-12 18:19:25 +00:00
plant The docs tell the truth again: 150-finding accuracy audit applied 2026-08-07 22:20:48 +00:00
press Say the checkable thing instead of the impressive one 2026-09-16 07:04:55 +00:00
seeds seeds: sync pool (f44351cf5407) 2026-07-25 06:31:25 +00:00
soils image seed --ap: the board as its own 5 GHz access point, sharing its Ethernet out 2026-10-04 01:51:35 +00:00
weeds node-out: the agent, the lease, and os_updates delivering them — a node takes its own reboot gated by the garden 2026-10-08 18:22:09 +00:00
.dev-keys.example Add --dev flag for installing dev SSH keys 2026-01-16 02:49:34 +00:00
.gitignore almanac: comments say the current state and the reason; the narration is here 2026-10-10 16:11:41 +00:00
.pressignore Rename garden/ -> groundwork/ (the directory now matches the vocabulary) 2026-08-06 18:52:42 +00:00
_CONVERGENCE.md _CONVERGENCE: the bar, where things stand, the arcs in flight, and the gaps tracked nowhere else 2026-10-12 18:37:43 +00:00
_DOC-BURNDOWN.md docs: repair the podman-cut cruft the runtime deletion left behind 2026-09-16 00:46:05 +00:00
_EDGE-CONTRACT.md Fold six shipped plans into the code's own why-comments and delete them 2026-09-11 15:32:52 +00:00
_GARDEN.md Community garden admission is by lottery, not invitation 2026-09-16 18:33:08 +00:00
_GOTCHAS.md Restart identity: what a container reads, observed on the node — not the source dir 2026-09-05 23:55:29 +00:00
_MIRRORING.md _CONVERGENCE: the bar, where things stand, the arcs in flight, and the gaps tracked nowhere else 2026-10-12 18:37:43 +00:00
_Municipal.md Make doc citations checkable, and stop one that had already rotted 2026-08-10 08:04:24 +00:00
_PLAN-asset-compaction.md Blob control plane: consumers stop signing — one credential holder, one Lua HMAC, no secret on argv 2026-09-12 19:33:42 +00:00
_PLAN-batch-nodes.md docs: give every plan an expiry, and fix three that mislead 2026-08-10 06:58:33 +00:00
_PLAN-bus-operator-mode.md bus: one NATS user per service, credentials delivered by the cellar — no anonymous door 2026-09-18 05:40:53 +00:00
_PLAN-cellar.md _PLAN-cellar: three refutations from a cold read, taken; wait_delivered's inventory-only "every node" to _TODO 2026-10-10 19:39:45 +00:00
_PLAN-domains.md plans: three status blocks said less was built than is 2026-10-12 18:40:16 +00:00
_PLAN-identity-clusters.md _PLAN-cellar: the keychain is the primary shape; the custodian on every node is one replica of it 2026-10-10 19:35:53 +00:00
_PLAN-node-orchestration.md docs: give every plan an expiry, and fix three that mislead 2026-08-10 06:58:33 +00:00
_PLAN-weather-trips.md plans: three status blocks said less was built than is 2026-10-12 18:40:16 +00:00
_QUICKSTART.md prepare.sh: install the Lua we require, instead of naming a package that doesn't exist 2026-08-12 07:21:01 +00:00
_RECOVERY.md keepers: the escrow leaves the repo — public ring versioned, ciphertext never 2026-09-13 19:32:57 +00:00
_SMELLS.md run/remote: one local runner, one remote caller, one log channel 2026-09-17 00:08:59 +00:00
_STATE-MODEL.md _CONVERGENCE: the bar, where things stand, the arcs in flight, and the gaps tracked nowhere else 2026-10-12 18:37:43 +00:00
_TODO.md _TODO: ~30 still-open entries corrected to what the code does now 2026-10-12 18:58:18 +00:00
_TRUST-SURFACE.md firewall: govern Docker-published ports too (close the FORWARD-path hole) 2026-09-22 04:02:43 +00:00
_WELL-KNOWN.md weather: no report is a report, and it isn't sunny (S) 2026-08-12 01:00:24 +00:00
about.md Rewrite index opening, drop stale 7k line count everywhere 2026-03-27 17:59:50 +00:00
building.md ci/post-commit: a commit straight to main is announced to the sessions in flight 2026-09-19 05:47:43 +00:00
config.lua.example Three found by audit: the wildcard twin, a real crash, a dead knob 2026-08-10 01:11:07 +00:00
LICENSE.txt Update LICENSE.txt 2026-01-12 06:00:28 +00:00
plant.lua plant --dry-run writes no garden identity, lock or credential; known_broken holds what is left 2026-10-12 16:34:26 +00:00
prepare.sh prepare.sh: install the Lua we require, instead of naming a package that doesn't exist 2026-08-12 07:21:01 +00:00
privacy.md docs: fix my own over-correction — the anonymized-logs model IS real 2026-07-15 00:41:14 +00:00
README.md Docs stop pontificating: say what is, and fix the links that 404 2026-08-26 09:40:56 +00:00
social-contract.md social contract: name the Four Agreements as the spirit, up top 2026-06-30 07:57:08 +00:00
tend.lua weather and plant: six places the tools said something other than what was true 2026-10-05 16:15:45 +00:00
test.lua Retire _PLAN-test-suite: its two hazards now head test.lua, its residue is one _TODO item 2026-10-12 18:39:09 +00:00

description nav_order
Your own web hosting, file sharing, email, and video calls — on a server you share with friends.
social-contract
about
groundwork
soils
plant
press
privacy
records
weeds
seeds

Sweetgrass 🌱

Information wants to be free. The internet should be a commons where we all have our place, not an endless series of toll roads controlled by a tiny minority of wealthy and powerful companies.

The trap

Building a website — even a small social network for the people you know — was never the hard part. You could host that yourself, today, for pennies.

The trap is what happens when it grows. The resources a thing needs scale with the people using it, so if you're giving it away, success makes it enormous — and paying for enormous pushes you toward the things that ruin it: advertising, selling data, manipulating attention. Even if you never meant to. And it leaves you — not the people using what you built — holding the keys.

Selling it as a service is the same trap mirrored: now extraction is the business. That's how you get thirty dollars a month for a site that costs pennies to serve — the difference isn't covering anyone's costs, it's enriching whoever owns the ground.

Neither story needs villains. It's what the economics do to whoever stands in that position. The way out isn't a better company standing in the same position — it's a world where no one stands there.

The way out

A garden, not a service. Nobody owns it. Someone tends it. The community grows in it.

A garden is infrastructure you plant and tend — yourself, or with a few friends. You cover the resources at their real cost, which is small, because nobody is there to make money; you're there to share. Nobody holds keys over anyone, because everyone can leave with everything, any time. And the tools are built so that a person with some computer literacy can set them up, understand what they do, and fix what breaks — like an old car you can pop the hood on. If you can't look under the hood, you can't trust it; if you can't leave, it isn't yours.

And the fear that keeps everyone on the platforms — what if the thing I make gets popular? — is exactly what the rest of this is built toward, not finished yet and honestly marked: gardens syndicating and pooling their infrastructure, so that when something catches on it spreads across the gardens of everyone who values it, each covering their own small, tractable share. Popular things grow to internet scale with no center — no advertising forced on anyone, no giant to pay, no ground for anyone to own.

Sweetgrass is that garden's toolset — web hosting, publishing, file sharing, email, video calls — run by you and answerable only to the people using it.

Two doors in

Either way the social contract is the same, and everything you make is yours to take with you.

The community garden

If you don't want to manage infrastructure, there's space in the community garden at sweetgrass.online, tended by the Sweetgrass-Garden Cooperative — a worker-owned co-op that builds these tools and hosts residents. It's free, and everything we use to run it is the same stuff you'd use to run your own — nothing hidden, nothing special.

The garden only takes on what it can actually carry, so admission is by rolling lottery — when there's room for more people, more names are drawn; no need to know somebody. Residents can leave, and come back, whenever they like. Those who want to go deeper can put their name in to become paid, mentored apprentices on the road to co-op membership — how that works.

Everyone who can chips in — with time, money, or however they can. If you're using more than your share, we'll have an honest conversation. The books are open.

This isn't the "real" Sweetgrass. It's one garden among many. If it disappeared tomorrow, the pattern wouldn't.

Anything you plant in our garden you can easily transplant into your own.

Planting your own

This is the point. Get a few friends together, pick a domain, and grow a garden. One person tends the infrastructure — the tools walk them through it. You can host all of this for about the price of a cup of coffee a month, shared between you.

The code is open. Improve it, share it back — and when the garden doesn't have a tool you need, you can grow your own from the same parts. Gardens share with each other, so you're part of a network without depending on a center. By running your own, you make the whole thing more resilient. Enough gardens, sharing like this, can carry anything the big platforms carry — at internet scale, with no center to capture, nothing to control. Anyone can walk away at any time, and the pattern keeps going.

The principles

However you use Sweetgrass, we all agree to the social contract

Yours to keep. Everything you create is portable. Move it to another garden, to your own, or somewhere else entirely. If you can't leave, it's not interdependence — it's dependence.

No extraction. No ads, no tracking, no investors. This is built so nobody can use it to accumulate control or wealth. Not us, not anyone.

Simplicity. The technology is understandable by the people who depend on it. If you can't look under the hood, you can't trust it.

Resilience through interdependence. Gardens share each other's data. The more gardens, the more resilient every garden becomes. We're strong because we depend on each other, not because we're isolated.

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.

Under the hood

This page is also this repository's README: the website and the source are the same files, and everything here — this page included — is a markdown file you can read, edit, and carry away.

Three scripts named for what they do:

plant.lua        Create infrastructure from scratch
tend.lua         Deploy, update, backup, maintain
lua/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, and Docker Swarm restarts failed containers on its own. The core services fit on a single small server (where an update or reboot means brief downtime); a 3-node cluster adds failover and room for meet.

The tools call standard unix utilities — ssh, rsync, curl — plus your cloud provider's CLI (hcloud, doctl, or none for bring-your-own hardware — see soils). 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)

groundwork/<name>/conf.lua             Groundwork definitions (self-describing)
.gardens/<g>/domains/<d>.lua       Domain configurations (per garden)

Every piece of a running garden lives in groundwork/, each one a directory whose README is its documentation. No magic: every operation is a readable Lua script — no hidden state, no frameworks, just scripts that do things you could do by hand, reliably.

For the full technical story — the way the project thinks, the map of what lives where, and how a change actually reaches a running garden — see building. For the publishing system at the heart of it, see press. To plant your first garden, start with plant.

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.

License and agreements

The code is AGPL-3.0 — if you improve it, share it back.

The social contract is the garden agreement — how people in a garden agree to be with each other. It lives here because every garden has one.

Governance records of the Sweetgrass-Garden Cooperative — bylaws, meetings, proposals — live in the open at sweetgrass.garden/records (source: rhizome/records). They aren't part of this repository because not every garden is this organization.


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