Self-hosting
Run your own knot to keep your repositories on a server you control.
The web app still shows them, and people can still open issues and pull
requests against them. The knot is a single Rust binary,
knot-server, with no database: git is the only store, plus a sealed
key file. Run a knot is the short version of
this page.
If you already run the Go knot, follow Upgrading to Knot 2 instead.
Requirements
Section titled “Requirements”- A Linux machine that stays online.
- A DNS name. It becomes the knot’s identity,
did:web:<hostname>, so choose one you’ll keep. - Your DID, which becomes the first admin.
- TLS, from a reverse proxy or from the knot itself.
Master key and sealed keys
Section titled “Master key and sealed keys”The knot keeps its signing keys in a sealed file, encrypted with a master key from an environment variable. Make the key once:
printf 'KNOT_MASTER_KEY=%s\n' "$(openssl rand -base64 32)" > knot.envSSH port
Section titled “SSH port”The knot runs its own SSH server on port 2222. To use port 22, move the
system sshd first, or bind the knot to a second IP address. The
knot 2 README
shows how.
Configuration
Section titled “Configuration”knot-server config-template > config.tomlknot-server --config config.toml validateThe required keys are server.hostname, server.admins,
server.ssh_host_key_file, repo.scan_path, secrets.sealed_key_file,
secrets.master_key_env and atproto.plc_directory. Any key can also
come from a KNOT_* environment variable.
Install on NixOS
Section titled “Install on NixOS”{ imports = [ tangled.nixosModules.knot-rs ];
services.tangled.knot-rs = { enable = true; environmentFile = "/etc/knot/knot.env"; settings = { server = { hostname = "knot.example.com"; admins = [ "did:plc:yourdid" ]; }; atproto.plc_directory = "https://plc.directory"; }; };}The knot listens on 127.0.0.1:5555 and keeps its state in
/var/lib/knot.
Install with a container
Section titled “Install with a container”Use atcr.io/tangled.org/knot:2. It runs as uid 1000, so chown your
data directories to 1000:1000, and set KNOT_SCAN_PATH,
KNOT_SEALED_KEY_FILE and KNOT_SSH_HOST_KEY_FILE to your mounted
paths. Run a knot has a full
compose file.
Behind a reverse proxy. Proxy to port 5555, and set
xrpc.trusted_proxy_header and xrpc.trusted_proxies so rate limits
apply per client. Don’t add CORS headers at the proxy.
In the knot. Set tls.acme_enabled = true and listen on 443. This
is the only way to get HTTP/3.
First run
Section titled “First run”curl https://knot.example.com/xrpc/_healthThen add the knot under Settings → Knots in the web app.
Members and invites
Section titled “Members and invites”By default only admins can create repositories. Set
acl.admission = "open" to let anyone in, or add members with the
admin commands. These need acl.legacy_admin_secret_env set:
knot-server --config config.toml admin member add did:plc:friendknot-server --config config.toml admin create-invite-codeGit LFS
Section titled “Git LFS”Set lfs.store_path to turn on Git LFS over SSH and HTTPS.
Updates
Section titled “Updates”Stop the knot, replace the binary or image, and start it again. Read Upgrading knots and spindles first.
Troubleshooting
Section titled “Troubleshooting”- The knot won’t start: run
knot-server validatewith the same config and environment. - A push is rejected for an SSH key: publish the key on the user’s PDS, then wait up to an hour for the knot’s cache.
- Every user is rate-limited together: set
xrpc.trusted_proxy_headerandxrpc.trusted_proxies.
Knot Configuration lists every setting.