# Run a knot

> Run a knot, the server that stores your git repositories.

A knot stores your git repositories. You can run it on NixOS or in a container.

If you already run the Go knot, follow [Golang to Rust knot migration guide](/docs/upgrading/knot-2/) instead.

## Before you start

You need:

* A Linux machine that stays online.
* A DNS name for the knot, for example `knot.example.com`. Choose a name that you will keep, because the knot uses it as its identity.
* Your DID. If you do not know it, look up your handle at [pds.ls](https://pds.ls).
* A reverse proxy, for example Caddy, to give the knot TLS.

Make a master key and keep it in an env file:

```sh
printf 'KNOT_MASTER_KEY=%s\n' "$(openssl rand -base64 32)" > knot.env
chmod 600 knot.env
```

> **Caution**
>
> Keep a backup copy of the master key on a different machine. If you lose it, the knot cannot control your repositories.

## Run on NixOS

Put `knot.env` at `/etc/knot/knot.env`. Then add the Tangled flake and enable the `knot-rs` module:

```nix
{
  inputs.tangled.url = "git+https://tangled.org/did:plc:j5hmlfdrwkvtxm7cjmu7j2is";
  outputs = { nixpkgs, tangled, ... }: {
    nixosConfigurations.knot = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [ tangled.nixosModules.knot-rs ./knot.nix ];
    };
  };
}
```

```nix
# knot.nix
{
  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`. Point your reverse proxy at it.

## Run with Docker

Make a `config.toml`:

```toml
[server]
hostname = "knot.example.com"
admins = ["did:plc:yourdid"]
listen_addr = "[::]:5555"
ssh_host_key_file = "/data/ssh/host_key"


[repo]
scan_path = "/data/repos"


[secrets]
sealed_key_file = "/data/secrets/sealed-keys"
master_key_env = "KNOT_MASTER_KEY"


[atproto]
plc_directory = "https://plc.directory"
```

Make a `compose.yaml`:

```yaml
services:
  knot:
    image: atcr.io/tangled.org/knot:2
    restart: unless-stopped
    env_file: ./knot.env
    command: ["--config", "/etc/knot/config.toml"]
    environment:
      KNOT_SCAN_PATH: /data/repos
      KNOT_SEALED_KEY_FILE: /data/secrets/sealed-keys
      KNOT_SSH_HOST_KEY_FILE: /data/ssh/host_key
      KNOT_MASTER_KEY_ENV: KNOT_MASTER_KEY
    ports:
      - "2222:2222"
      - "127.0.0.1:5555:5555"
    volumes:
      - ./config.toml:/etc/knot/config.toml:ro
      - ./repos:/data/repos
      - ./secrets:/data/secrets
      - ./ssh:/data/ssh
```

Then start it:

```sh
mkdir -p repos secrets ssh
sudo chown -R 1000:1000 repos secrets ssh
docker compose up -d
```

Point your reverse proxy at `127.0.0.1:5555`.

## Check that it works

```sh
curl https://knot.example.com/xrpc/_health
```

Then, in the Tangled web app, go to Settings → Knots and add your knot. You can now make a repository on it and push to it.

Users clone over SSH on port 2222. To use port 22, see the [Rust based knot README](https://tangled.org/did:plc:j5hmlfdrwkvtxm7cjmu7j2is/blob/master/knot2/README.md). [Self-hosting](/docs/knots/self-hosting/) explains a knot in detail. [Knot Configuration](/docs/reference/knot-config/) lists all settings.