Ga naar inhoud

Installing a Node

Deze inhoud is nog niet vertaald.

Four steps on the box, and two things only you can do outside it: point DNS, and get your fingerprint verified.

If you were given an enrolment token, the whole of steps 0 to 2 collapses into one command. It downloads the code, extracts it to /opt/trusted-codes and runs tc-operator setup, which fetches this node’s operator.yaml from the token, installs the stack and self-enrols it.

Terminal window
curl -fsSL https://app.trusted.codes/download/install-node.sh | sudo bash -s -- <enrolment-token>

Leave the token off to be prompted for it, so it never lands in your shell history:

Terminal window
curl -fsSL https://app.trusted.codes/download/install-node.sh | sudo bash

The download is verified against the published release manifest, and the manifest itself against a pinned signing key.

Take the manual steps below instead if you want to inspect the archive first, pin a version, or install somewhere other than /opt/trusted-codes (--dir <path>).

Terminal window
sudo mkdir -p /opt/trusted-codes
sudo tar -xzf trusted-codes-operator-<version>.tar.gz -C /opt/trusted-codes
cd /opt/trusted-codes

The install preflight verifies the tree is complete and fails loudly, with this instruction, if it is not.

Terminal window
cp scripts/tc-operator/operator.yaml.example operator.yaml
chmod 600 operator.yaml
$EDITOR operator.yaml

Keep it mode 0600 — it holds your SMTP password. Two fields are required:

home_server: node1.example.com
admin_email: ops@example.com

Everything else has a working default. operator.yaml covers the rest of the file.

Terminal window
sudo scripts/tc-operator/tc-operator install --config operator.yaml

It is idempotent — safe to re-run, and re-running is the normal way to apply a new archive. It:

  1. Preflights the host: checks the OS, provisions a 4 GB swapfile, installs Docker if it is absent, allows 22, 80 and 443 through the firewall.
  2. Generates every secret and issues the node’s mTLS certificate.
  3. Boots the full stack in an isolated Docker project, with every published port bound to 127.0.0.1.
  4. Replays the schema — migrations, then reference seeds, then the operator override. A fresh database built by construction, never from a dump.
  5. Wires federation identity and flags, and turns WebFinger discovery on.
  6. Self-tests: an authenticated read, and the federation handler answering.
  7. Prints the DNS records you need and writes the admission payload.

It does not abort if your DNS is not pointed yet. TLS is a separate step.

The install is not gated behind a typed confirmation: it is your one command on your own box.

It writes /etc/trusted-codes/install.log with every command’s full output, and /etc/trusted-codes/README.md — an on-box reference naming every file in that directory, which ones are identity-critical, what each container does and what breaks when it is down. Start at those two when something looks wrong.

If you set admin_email, install also creates your first operator_admin for that address and prints a one-time temporary password. Log in to the node’s admin app and change it immediately; the temporary password has no recovery path.

That role administers this node only. It is denied every central screen — grants, entitlements, plans, feature flags — at the server, not merely in the interface, and there is no way to escalate it. See Running the node.

The installer prints the exact record. Set it at your DNS provider:

node1.example.com. A <your-box-ip>

Once it resolves:

Terminal window
sudo scripts/tc-operator/tc-operator finalize-tls --config operator.yaml

This polls until the A record resolves to the box, renders the proxy configuration, and brings up HTTPS with a Let’s Encrypt certificate.

Rehearse with --dry-run first. It uses the Let’s Encrypt staging environment: the certificate is untrusted, and you burn no rate limit. That matters, because the real rate limit is per-domain and you cannot undo hitting it.

The installer wrote /etc/trusted-codes/admission-payload.json. It contains only public key material: your federation signing public key and its fingerprint, your mTLS fingerprint, your domains and your capabilities.

Terminal window
scripts/tc-operator/tc-operator submit-admission

This signs the payload with your node’s federation key and posts it to the central review queue.

The signature proves your node holds the key. It does not prove you own the hostname — so tell Trusted Codes your public-key fingerprint through a separate channel. The command prints it. Somebody verifies that fingerprint by hand and then approves your node; there is no self-approval. Re-running the command refreshes the pending entry.

Once approved, and once the signed registry republishes, your node federates with the mesh. Until then the admin surface stays behind a “pending approval” screen.

The node runs the moment install finishes. That is not the same as being ready.

  • DNS records resolve to the box, and finalize-tls completed with a valid certificate.
  • Admission approved — your fingerprint verified, the node federating.
  • SMTP wired and verified. Send yourself a sign-in link and confirm it arrives.
  • The admin password changed from the temporary one.
  • /etc/trusted-codes/secrets.env copied somewhere offline. Losing it loses the node’s identity keys and makes any restored data unreadable.
  • Optional integration keys set, if you want those features.

A surface build was skipped. The other surfaces installed; only that portal was not built. Read the error in install.log — search for surface <name>: building. The usual cause is memory: a “killed” or signal 137 line means the box ran out. Add RAM or swap and re-run install, which retries the build. The node is usable meanwhile.

TLS did not finalise. Almost always DNS that has not propagated. Confirm with getent hosts <your-domain>, then run finalize-tls again.

Admission is stuck pending. Somebody at Trusted Codes must verify your fingerprint out of band and approve it. Re-submitting refreshes the entry; it does not approve it.