- Rust 86.2%
- Python 12.6%
- Nix 0.9%
- Just 0.3%
|
Some checks failed
Checks / checks (push) Failing after 39s
Cap connections across both listeners at 1,024 globally and 64 per client, including TLS handshakes. Require HTTP/2 negotiation and the first request within 10 seconds, then close idle connections after 30 seconds. Give HTTPS redirects a separate 10/s, burst-20 allowance and aggregate their logs without request paths. Preserve the normal HTTPS allowance. Only count Authorization as a Lightning payment attempt when L402 is enabled, preserving backend authentication on x402-only sites. Add regression coverage for connection admission and release, startup deadlines, backend authorization, and redirect limits and logging. Document the transport limits and separate redirect allowance. |
||
|---|---|---|
| .github/workflows | ||
| crates/geata | ||
| docs | ||
| examples | ||
| tests | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| DEVELOPMENT.md | ||
| flake.lock | ||
| flake.nix | ||
| justfile | ||
| LICENSE | ||
| README.md | ||
| rust-toolchain.toml | ||
Geata
Repository note: The main repository is git.cashu.dev/thesimplekid/geata. github.com/thesimplekid/geata is a mirror.
Geata (Irish for “gate”) is a Rust reverse proxy that lets clients pay for requests using Cashu or Lightning (L402 and x402), with an optional free allowance. It combines Caddy-style configuration and automatic HTTPS with payment handling at the proxy.
For sites with payments enabled, every request requires payment unless a free allowance is configured. If configured, each client IP gets a free request allowance. When payment is needed, Geata returns 402 Payment Required with the price and configured payment options. The client can wait for a configured allowance to refill, or pay with a Cashu token or a Lightning invoice and retry with the payment proof. Geata verifies and settles the payment before forwarding the request, so your backend does not need payment logic.
lightning my_node {
endpoint https://localhost:3536
macaroon_file /var/lib/ldk-server/bitcoin/macaroons/geata.macaroon
tls_cert_file /var/lib/ldk-server/tls.crt
network mainnet
pay_to YOUR_66_CHARACTER_COMPRESSED_NODE_PUBLIC_KEY
}
example.com {
rate_limit 10/s burst 20
pay 2 sat https://mint.example.com
lightning_pay 2 sat my_node
lightning_protocols x402 l402
lightning_headers accept content-encoding content-type cookie range
reverse_proxy localhost:3000
}
Here, each IP gets a bucket of 20 free requests that refills at 10 per second. Beyond that allowance, clients can pay with Cashu tokens, Lightning x402, or Lightning L402. Each method costs a fixed 2 sats per request attempt; Cashu also requires mint input fees, and Lightning routing fees may apply. The price does not rise with traffic.
Remove rate_limit to charge for every request. Use pay for Cashu,
lightning_pay for Lightning, or both to offer either method. These replace the
former pay_over_limit and lightning_over_limit directives; the old names are
no longer accepted.
Try the hosted example endpoint, or use the Rust client example to walk through a Lightning payment.
The Lightning receiver requires a separate LDK Server with incoming liquidity. Replace its endpoint, credential paths, and node public key with your own values. See Lightning payments for setup and Cashu payments for token requirements and recovery.
Built on Pingora, Geata can also serve plain-text responses directly.
An early implementation for a single Linux server; see current scope.
Payment options
Cashu and Lightning can be offered together or on their own:
| Payment method | Receiver | Where proceeds go |
|---|---|---|
| Cashu tokens | Cashu mint | Geata's Cashu wallet |
| Lightning L402 | LDK Server or Cashu mint | Your Lightning node or Geata's Cashu wallet |
| Lightning x402 | LDK Server | Your Lightning node |
For Lightning, define a named receiver and reference it with
lightning_pay. Select lightning_protocols x402 l402 to offer both
protocols through LDK Server; the default is x402. To accept Lightning without
running your own node, use a Cashu mint receiver with lightning_protocols l402.
Lightning payments are bound to the request and buy one request attempt.
Enabling L402 reserves the Authorization header for payment credentials,
including on free requests. See Lightning payments for
complete configurations, client payment flows, and backend authentication options.
To try either protocol against a URL, run the Rust client example.
Try it locally
Build with Nix and run the included Hello world example—no backend required:
nix build path:.
./result/bin/geata run --config examples/Geatafile.local \
--http-listen 127.0.0.1:8080 --https-listen 127.0.0.1:8443
In another terminal, run curl http://localhost:8080.
Other build options include Cargo without Nix.
Use your domain
Replace the example domain, mint URL, backend address, and LDK receiver settings
above with your own, then save the configuration as Geatafile. Point your
domain's DNS at the server and make ports 80 and 443 reachable. Then run:
./result/bin/geata validate
./result/bin/geata run
The process needs permission to bind those ports. Geata obtains and renews certificates automatically, redirects HTTP to HTTPS, and reloads valid config changes. See HTTPS and operation for deployment details.
Traffic demo
nix develop path:. -c just demo
Open http://127.0.0.1:9090 to watch request rates, generate traffic, and try Cashu payments. The demo guide explains how to choose a test or real mint and set the price.
Documentation
- Build and run
- Configuration — proxying, direct responses, reloads
- Rate limiting — per-IP allowances and burst limits
- Lightning payments — x402 with LDK Server, L402 with LDK or a Cashu mint, request binding, replay protection
- Cashu payments — pricing, tokens, wallets, recovery
- HTTPS and operation — certificates, storage, deployment limits
- Development — contributor workflow and tests