Monorepo for Tangled tangled.org
README.md

pc #

process-compose runs the localinfra stack as plain processes on your machine. each service is wrapped in offline, so it only reaches loopback unless its yaml says otherwise.

nix run .#localinfra                    # start the stack
bin/up                                  # without nix, running doctor and setup first
bin/up --online                         # skip offline sandboxing
bin/up --profile spindle                # add an optional profile
bin/pc process list                     # check running services
bin/pc process restart knot2            # restart one service
bin/pc down                             # stop the stack

nix run .#localinfra brings the monorepo toolchain, so it needs no nix develop and runs fine from inside one. extra arguments go to bin/up. without nix, bin/up runs bin/doctor for missing programs, then bin/setup to fetch and build.

bin/up --exec selftest checks that the offline sandbox works. TNGL_ONLINE=1 disables it.

optional services #

some services only run under a profile:

  • spindle: spindle with the dummy engine, so no kvm
  • ncps: ncps and its migration, the nix cache spindle uses
  • microvm: linux only. spindle with the real microvm engine, implying spindle and ncps. wants /dev/kvm, /dev/vhost-vsock and /dev/net/tun writable
  • observability: prometheus, loki, tempo, otlp gateway and grafana
  • pdsls: pds browser, needs bun and a cpu with avx2
  • sites: the sites worker under wrangler with its local r2 bridge, and sitesd

pass --profile <name> to bin/up, or set TNGL_PROFILES=a,b.

swapping what a service runs #

localinfra/pc/.env overrides commands, ports and urls. FOO_BIN swaps a service's program and keeps our flags, FOO_CMD replaces the whole command as a shell string that runs after its env is set. names and defaults are in the commands.env files.

services run what is already built, so build and restart to pick up edits. knot2, bobbin, knotmirror and tranquil-gate build into this checkout's target/:

cargo build -p knot-server && bin/pc process restart knot2

to run your own checkout, put the build in the command:

PDS_CMD='cd ~/proj/atproto/services/pds && exec node --enable-source-maps --import=@atproto/pds/telemetry index.ts'
PLC_CMD='cd ~/proj/did-method-plc/packages/server && DATABASE_URL=postgres://tnglr:tnglr@127.0.0.1:$TNGL_PG_PORT/plc PORT=$TNGL_PLC_PORT exec node dist/bin.js'

your plc checkout has to be built already for PLC_CMD (node build.js), and the atproto one for PDS_CMD (pnpm build).

on macos cargo builds here need nix develop, because .cargo/config.toml names a nix linker.

process-compose.override.yaml merges over the stack yaml: is_disabled: "true" drops a service, a watch block restarts one when files change.

fixtures #

init-data runs localinfra/scripts/init-data.sh for the accounts and repos compose has. later runs skip it while .localinfra/data/init-data.stamp matches, delete the stamp to reseed. after a failed import delete .localinfra/data/knot2, since a rerun skips repos the knot already has.

machine setup #

  • trust localinfra/certs/root.crt in your browser.

  • host dns: *.tngl.boltless.dev must resolve on the host, the pds checks handles over dns. on macos:

    sudo mkdir -p /etc/resolver
    printf 'nameserver 127.0.0.1\nport 5354\n' | sudo tee /etc/resolver/tngl.boltless.dev
    
  • linux ports: sysctl net.ipv4.ip_unprivileged_port_start=443 lets the forwarder bind 443 without root, and doctor says so when it can't.

  • loopback alias: if using TNGL_IP=11.0.0.253 (for a hydrant older than HYDRANT_ALLOW_PRIVATE_NETWORKS), macos needs sudo ifconfig lo0 alias 11.0.0.253/32 (lost on reboot) and --online.

  • caddy binds 443. if colima or podman holds it, set TNGL_HTTPS_PORT in localinfra/pc/.env.

layout #

process-compose.yaml    dns, postgres, pg-init, plc, caddy, pds, init-data, knot2, hydrant
Caddyfile               shared config, each service adds its vhosts
ports.env               host ports, and TNGL_FORWARD
commands.env            *_BIN defaults of the core programs
airgap.sb               macos sandbox profile behind offline
bin/
  up                    parses its flags, runs setup, doctor, then process-compose
  setup                 the only part that may use the internet
  doctor                checks the needed programs and the host
  env.sh                sets TNGL_* and PATH, sources every service's env files
  services              lists the active services
  profile-on            exit 0 when a profile is on
  offline               wraps a command so its only way out is loopback
  linux-ns, ns-inner    linux user and network namespace
  pc                    process-compose against the stack's socket
  tcp-up                exit 0 once something accepts connections on a host and port
  selftest              checks the offline wrapper, run as `up --exec selftest`
  patch-workerd         points npm's workerd at the nix loader on nixos
  svc/                  launch scripts for the core services
services/               one directory per service, see services/README.md