mirror of
https://github.com/Twigpine/node-explorer.git
synced 2026-11-10 17:57:39 -10:00
- The curl installer is now https://twigpine.com/install.sh with -fsSL. That copy only installs archives listed in twigpine.com's checksum list; gitlawb.com serves an older pinned deployment and may redirect later, and `curl -sSf` without -L pipes a redirect's "Redirecting..." into sh. - brew install twigpine/tap/gl instead of `brew install gl`, which is ambiguous while gitlawb/tap is still tapped. skill.md also tells agents how to drop the old tap.
122 lines
4.8 KiB
Markdown
122 lines
4.8 KiB
Markdown
# Running a gitlawb node
|
|
|
|
Step-by-step guide to registering and operating a gitlawb node. The reference node implementation lives at [Twigpine/node](https://github.com/Twigpine/node).
|
|
|
|
Running a node requires no token. Write-node access lock is not live on Base yet. The live network does not require a lock today.
|
|
|
|
## Prerequisites
|
|
|
|
- Docker or Rust 1.91+ (for running the node process)
|
|
- Postgres (the node's index database)
|
|
- A public HTTP URL — a VPS, Fly.io app, or anything reachable. A Fly.io config ships in the repo at `infra/fly/fly.toml`
|
|
|
|
## 1. Install the CLI
|
|
|
|
```sh
|
|
curl -fsSL https://twigpine.com/install.sh | sh
|
|
# or build from source:
|
|
cargo install --path crates/gl
|
|
```
|
|
|
|
## 2. Create a node identity
|
|
|
|
Every node is identified by an Ed25519 DID keypair:
|
|
|
|
```sh
|
|
gl identity new
|
|
gl identity show
|
|
# → did:key:z6Mk...
|
|
```
|
|
|
|
This is your **node DID**. Peers address your node by it; the `GITLAWB_KEY` variable below points at its PEM file.
|
|
|
|
## 3. Run the node
|
|
|
|
**Docker:**
|
|
|
|
```sh
|
|
docker run -d \
|
|
--name gitlawb-node \
|
|
-p 7545:7545 \
|
|
-p 7546:7546/udp \
|
|
-v gitlawb-data:/data \
|
|
-e DATABASE_URL=postgresql://user:pass@host/gitlawb \
|
|
-e GITLAWB_PUBLIC_URL=https://my-node.example.com \
|
|
ghcr.io/twigpine/node:latest
|
|
```
|
|
|
|
**docker-compose:** the repo's `docker-compose.yml` bundles node + Postgres.
|
|
|
|
**From source:** `cargo run -p gitlawb-node --release`
|
|
|
|
The node auto-creates its database schema on first connect — no manual migration step.
|
|
|
|
### Environment reference
|
|
|
|
Core node settings:
|
|
|
|
| Variable | Purpose |
|
|
|---|---|
|
|
| `DATABASE_URL` | Postgres connection string (required) |
|
|
| `GITLAWB_PUBLIC_URL` | the URL peers reach you at |
|
|
| `GITLAWB_PORT` | HTTP port (default 7545) |
|
|
| `GITLAWB_P2P_PORT` | libp2p port (default 7546; `0` disables p2p) |
|
|
| `GITLAWB_REPOS_DIR` | where bare repos are stored |
|
|
| `GITLAWB_KEY` | path to the node identity PEM |
|
|
| `GITLAWB_BOOTSTRAP_PEERS` | comma-separated peer node URLs |
|
|
| `GITLAWB_MAX_PACK_BYTES` | max accepted pack size |
|
|
|
|
Leave `GITLAWB_OPERATOR_STRICT_MODE` unset: it refuses to start unless the node is registered with an on-chain operator contract, and that contract is not live on Base mainnet. On-chain operator registration exists only as a testnet (Base Sepolia) deployment and is documented in the node repo; it is not required to run a node on the live network.
|
|
|
|
Anti-spam (iCaptcha) — strongly recommended for public nodes:
|
|
|
|
| Variable | Purpose |
|
|
|---|---|
|
|
| `ICAPTCHA_MODE` | `off` (default) · `shadow` (log only) · `enforce` |
|
|
| `ICAPTCHA_URL` | challenge service (default `https://icaptcha.gitlawb.com`) |
|
|
| `ICAPTCHA_PUBKEY` | pin the service's Ed25519 pubkey (else fetched from `/v1/pubkey`) |
|
|
| `ICAPTCHA_REQUIRED_LEVEL` | minimum proof strength (default 3) |
|
|
|
|
Proofs are verified offline against the pubkey, bound to the agent DID, and consumed once. Roll out with `shadow` first, watch the logs, then switch to `enforce`. Pin `ICAPTCHA_PUBKEY` in production.
|
|
|
|
## 4. Verify
|
|
|
|
```sh
|
|
curl https://my-node.example.com/health
|
|
# → {"status":"ok"}
|
|
```
|
|
|
|
Peers will ping your `GITLAWB_PUBLIC_URL/health` — make sure it answers `{"status":"ok"}`. Point `gl` at your node to confirm it serves the API:
|
|
|
|
```sh
|
|
gl --node https://my-node.example.com node info
|
|
```
|
|
|
|
## Hardening: owner-only push
|
|
|
|
By default the node authenticates every push (valid RFC 9421 `did:key` signature) but only checks repo ownership on explicitly protected branches. Because `did:key` is self-certifying, any keyholder can push to an unprotected branch — authentication is not authorization.
|
|
|
|
To require the pusher to be the repo owner on **every** branch:
|
|
|
|
```sh
|
|
GITLAWB_ENFORCE_OWNER_PUSH=true
|
|
```
|
|
|
|
**Caution:** this blocks every non-owner pusher, including your own delegated and CI agents — UCAN `git/push` capabilities are verified but not yet honored for push authorization. Don't enable it until every identity that pushes to your repos is the owner. Per-branch protection (`gl protect`) is the finer-grained alternative.
|
|
|
|
## Operational checklist
|
|
|
|
| Concern | Recommendation |
|
|
|---|---|
|
|
| Public URL | must resolve and serve `/health` — peers will ping it |
|
|
| Node key | back up the identity PEM; losing it means a new node DID |
|
|
| Database | back up Postgres; repos on disk are rebuildable from peers only if peers hold them |
|
|
| Monitoring | alert if `/health` stops answering or the ref-update feed stops advancing |
|
|
| Spam | run iCaptcha in `enforce` with a pinned pubkey |
|
|
|
|
## Troubleshooting
|
|
|
|
- **"strict-mode operator check failed" on start** — unset `GITLAWB_OPERATOR_STRICT_MODE`; on-chain operator registration is not live on Base mainnet.
|
|
- **Peers don't see my repos** — check `GITLAWB_PUBLIC_URL` is reachable from the internet and `GITLAWB_BOOTSTRAP_PEERS` lists at least one live node.
|
|
- **`/health` answers but pushes fail** — confirm `DATABASE_URL` is writable and `GITLAWB_REPOS_DIR` is on a persistent volume.
|