---
title: Hacking on Tangled
description: Set up a dev environment and run the appview, knots, and spindles locally.
---


We highly recommend [installing
Nix](https://nixos.org/download/) (the package manager)
before working on the codebase. The Nix flake provides a lot
of helpers to get started and most importantly, builds and
dev shells are entirely deterministic.

To set up your dev environment:

```bash
nix develop
```

Non-Nix users can look at the `devShell` attribute in the
`flake.nix` file to determine necessary dependencies.

## Running the appview

The appview requires Redis and OAuth JWKs. Start these
first, before launching the appview itself.

```bash
# OAuth JWKs should already be set up by the Nix devshell:
echo $TANGLED_OAUTH_CLIENT_SECRET
z42ty4RT1ovnTopY8B8ekz9NuziF2CuMkZ7rbRFpAR9jBqMc

echo $TANGLED_OAUTH_CLIENT_KID
1761667908

# if not, you can set it up yourself:
goat key generate -t P-256
Key Type: P-256 / secp256r1 / ES256 private key
Secret Key (Multibase Syntax): save this securely (eg, add to password manager)
        z42tuPDKRfM2mz2Kv953ARen2jmrPA8S9LX9tRq4RVcUMwwL
Public Key (DID Key Syntax): share or publish this (eg, in DID document)
        did:key:zDnaeUBxtG6Xuv3ATJE4GaWeyXM3jyamJsZw3bSPpxx4bNXDR

# the secret key from above
export TANGLED_OAUTH_CLIENT_SECRET="z42tuP..."

# Run Redis in a new shell to store OAuth sessions
redis-server
```

The Nix flake exposes a few `app` attributes (run `nix
flake show` to see a full list of what the flake provides),
one of the apps runs the appview with the `air`
live-reloader:

```bash
TANGLED_DEV=true nix run .#watch-appview

# TANGLED_DB_PATH might be of interest to point to
# different sqlite DBs

# in a separate shell, you can live-reload tailwind
nix run .#watch-tailwind
```

## Running knots and spindles

An end-to-end knot setup requires setting up a machine with
`sshd`, `AuthorizedKeysCommand`, and a Git user, which is
quite cumbersome. So the Nix flake provides a
`nixosConfiguration` to do so.

<details>
  <summary><strong>macOS users will have to set up a Nix Builder first</strong></summary>

In order to build Tangled's dev VM on macOS, you will
first need to set up a Linux Nix builder. The recommended
way to do so is to run a [`darwin.linux-builder`
VM](https://nixos.org/manual/nixpkgs/unstable/#sec-darwin-builder)
and to register it in `nix.conf` as a builder for Linux
with the same architecture as your Mac (`linux-aarch64` if
you are using Apple Silicon).

If you're on nix-darwin, you can simply add

```
nix.linux-builder.enable = true;
```

to your host's `configuration.nix`.

Alternatively, you can use any other method to set up a
Linux machine with Nix installed that you can `sudo ssh`
into (in other words, root user on your Mac has to be able
to ssh into the Linux machine without entering a password)
and that has the same architecture as your Mac. See
[remote builder
instructions](https://nix.dev/manual/nix/2.28/advanced-topics/distributed-builds.html#requirements)
for how to register such a builder in `nix.conf`.

> WARNING: If you'd like to use
> [`nixos-lima`](https://github.com/nixos-lima/nixos-lima) or
> [Orbstack](https://orbstack.dev/), note that setting them up so that `sudo
ssh` works can be tricky. It seems to be [possible with
> Orbstack](https://github.com/orgs/orbstack/discussions/1669).

</details>

To begin, grab your DID from http://localhost:3000/settings.
Then, set `TANGLED_VM_KNOT_OWNER` and
`TANGLED_VM_SPINDLE_OWNER` to your DID. You can now start a
lightweight NixOS VM like so:

```bash
nix run --impure .#vm

# type `poweroff` at the shell to exit the VM
```

This starts a knot on port 6444, a spindle on port 6555
with `ssh` exposed on port 2222.

Once the services are running, head to
http://localhost:3000/settings/knots and hit "Verify". It should
verify the ownership of the services instantly if everything
went smoothly.

You can push repositories to this VM with this ssh config
block on your main machine:

```bash
Host nixos-shell
    Hostname localhost
    Port 2222
    User git
    IdentityFile ~/.ssh/my_tangled_key
```

Set up a remote called `local-dev` on a git repo:

```bash
git remote add local-dev git@nixos-shell:user/repo
git push local-dev main
```

The above VM should already be running a spindle on
`localhost:6555`. Head to http://localhost:3000/settings/spindles and
hit "Verify". You can then configure each repository to use
this spindle and run CI jobs.

Of interest when debugging spindles:

```
# Service logs from journald:
journalctl -xeu spindle

# CI job logs from disk:
ls /var/log/spindle

# Debugging spindle database:
sqlite3 /var/lib/spindle/spindle.db

# litecli has a nicer REPL interface:
litecli /var/lib/spindle/spindle.db
```

If for any reason you wish to disable either one of the
services in the VM, modify [nix/vm.nix](https://tangled.org/@tangled.org/core/blob/master/nix/vm.nix) and set
`services.tangled.spindle.enable` (or
`services.tangled.knot.enable`) to `false`.
