{
  "manifest_version": "1",
  "slug": "tangled",
  "title": "Tangled knot",
  "headline": "Host your Tangled repos on your own knot",
  "description": "Run a Tangled knot on an exe.dev VM: your git repositories on your own server, with issues, pull requests and stars on tangled.org under your atproto handle.",
  "category": "dev-tools",
  "tags": [
    "tangled",
    "tangled knot",
    "atproto git",
    "bluesky git hosting",
    "self-hosted git",
    "decentralized github",
    "git forge",
    "tangled spindle"
  ],
  "url": "https://exe.dev/deploy/tangled",
  "markdown_url": "https://exe-staging.dev/deploy/tangled.md",
  "upstream": {
    "website": "https://tangled.org",
    "source": "https://tangled.org/tangled.org/core",
    "docs": "https://tangled.org/docs",
    "license": "MIT"
  },
  "example_vm_name": "my-knot",
  "time": "30 minutes, most of it compiling",
  "stack": [
    {
      "name": "Tangled knot 1.20",
      "detail": "`knot-server`, the Rust knot, built from the v1.20.0 tag, as a systemd service",
      "port": 8000,
      "data": "/var/lib/knot"
    },
    {
      "name": "Knot SSH",
      "detail": "the knot's own SSH server, for git push, reached through exe.dev's SSH",
      "port": 2222
    },
    {
      "name": "Nightly backup",
      "detail": "a systemd timer; keeps two weeks",
      "data": "/var/backups/knot"
    }
  ],
  "access": [
    {
      "url": "https://my-knot.exe.xyz/",
      "who": "public",
      "what": "the knot, for tangled.org and anyone cloning; pushes need your atproto identity"
    },
    {
      "url": "ssh -J my-knot.exe.xyz -p 2222 git@localhost",
      "who": "private",
      "what": "git push over SSH, for you, through exe.dev's SSH"
    }
  ],
  "inputs": [
    {
      "name": "TANGLED_HANDLE",
      "description": "the handle you sign in to tangled.org with: `alice.tngl.sh` if you signed up there with an email, or your Bluesky handle; it becomes the knot's owner"
    },
    {
      "name": "KNOT_CONTACT_EMAIL",
      "description": "an email address the knot publishes for abuse reports and questions"
    }
  ],
  "delivers": [
    "Tangled's knot 1.20 at `https://my-knot.exe.xyz/`, owned by your atproto DID, restarted on failure and after a reboot.",
    "`/xrpc/_health` and `/.well-known/did.json` answering on the knot's address, ready to add on tangled.org.",
    "`knot-member add \u003chandle\u003e` on the VM, to let other people create repositories on the knot.",
    "The knot's SSH server on port 2222, for pushes through exe.dev's SSH.",
    "Repositories, keys and settings in `/var/lib/knot` and `/etc/knot`, backed up nightly to `/var/backups/knot`, with a restore checked."
  ],
  "owner_runs_after": [
    "ssh exe.dev share set-public my-knot",
    "ssh my-knot.exe.xyz sudo systemctl restart knot.service"
  ],
  "deployable": true,
  "deploy": {
    "new_vm_url": "https://exe-staging.dev/new?prompt=TANGLED_HANDLE%3D%3Cfill-this-in%3E%0AKNOT_CONTACT_EMAIL%3D%3Cfill-this-in%3E%0A%0ASet%20up%20Tangled%20knot%20on%20this%20VM%20by%20following%20the%20exe.dev%20recipe%20at%20https%3A%2F%2Fexe-staging.dev%2Fdeploy%2Ftangled.md%20from%20top%20to%20bottom.%0A%0AThe%20values%20at%20the%20top%20of%20this%20message%20are%20mine%3A%0A-%20TANGLED_HANDLE%3A%20the%20handle%20you%20sign%20in%20to%20tangled.org%20with%3A%20%60alice.tngl.sh%60%20if%20you%20signed%20up%20there%20with%20an%20email%2C%20or%20your%20Bluesky%20handle%3B%20it%20becomes%20the%20knot%27s%20owner%0A-%20KNOT_CONTACT_EMAIL%3A%20an%20email%20address%20the%20knot%20publishes%20for%20abuse%20reports%20and%20questions%0AAsk%20me%20for%20any%20that%20still%20say%20%3Cfill-this-in%3E%20before%20you%20need%20them.%0A%0AThe%20recipe%27s%20example%20VM%20name%20is%20my-knot.%20This%20VM%27s%20name%20is%20the%20output%20of%20%60hostname%60%3A%20use%20it%20wherever%20the%20recipe%20writes%20my-knot.%20Skip%20the%20step%20that%20creates%20the%20VM%3B%20you%20are%20on%20it.%0A%0AYou%20are%20done%20when%20all%20of%20these%20are%20true.%20Check%20each%20one%20yourself%3A%0A-%20Tangled%27s%20knot%201.20%20at%20%60https%3A%2F%2Fmy-knot.exe.xyz%2F%60%2C%20owned%20by%20your%20atproto%20DID%2C%20restarted%20on%20failure%20and%20after%20a%20reboot.%0A-%20%60%2Fxrpc%2F_health%60%20and%20%60%2F.well-known%2Fdid.json%60%20answering%20on%20the%20knot%27s%20address%2C%20ready%20to%20add%20on%20tangled.org.%0A-%20%60knot-member%20add%20%3Chandle%3E%60%20on%20the%20VM%2C%20to%20let%20other%20people%20create%20repositories%20on%20the%20knot.%0A-%20The%20knot%27s%20SSH%20server%20on%20port%202222%2C%20for%20pushes%20through%20exe.dev%27s%20SSH.%0A-%20Repositories%2C%20keys%20and%20settings%20in%20%60%2Fvar%2Flib%2Fknot%60%20and%20%60%2Fetc%2Fknot%60%2C%20backed%20up%20nightly%20to%20%60%2Fvar%2Fbackups%2Fknot%60%2C%20with%20a%20restore%20checked.%0A%0ARead%20the%20whole%20recipe%2C%20closed%20details%20included%2C%20and%20follow%20%22Set%20up%20by%0Ahand%22%20in%20order%2C%20skipping%20VM%20creation%3B%20the%20walkthrough%20above%20it%20is%20for%0Athe%20owner.%20Resolve%20TANGLED_HANDLE%20to%20a%20DID%20as%20written%20and%20stop%20if%20it%0Adoesn%27t%20resolve.%20The%20build%20takes%2015-25%20minutes%3A%20run%20it%20in%20the%0Abackground.%20On%20an%20existing%20VM%2C%20ask%20before%20replacing%20anything%20on%20port%0A8000.%20Don%27t%20make%20the%20VM%20public%20yourself%3A%20the%20owner%20runs%20%60ssh%20exe.dev%0Ashare%20set-public%60%20on%20their%20computer.%20Show%20the%20owner%20the%20master%20key%27s%0Aline%20from%20%2Fetc%2Fknot%2Fknot.env%20once%2C%20and%20tell%20them%20to%20store%20it%20off%20the%0AVM.%20Finish%20with%20the%20%60set-public%60%20command%2C%20then%20%22Add%20the%20knot%20on%0Atangled.org%22%20and%20%22Push%20over%20SSH%22%20for%20the%20owner%20to%20follow.%0A%0AFinish%20with%20the%20URLs%20I%20should%20open%20and%20these%20commands%2C%20which%20only%20I%20can%20run%2C%20from%20my%20own%20computer%20%28with%20this%20VM%27s%20name%20in%20them%29%3A%0A%20%20ssh%20exe.dev%20share%20set-public%20my-knot%0A%20%20ssh%20my-knot.exe.xyz%20sudo%20systemctl%20restart%20knot.service%0A",
    "terminal": "curl -fsSL https://exe-staging.dev/deploy/tangled/prompt.txt | ssh exe.dev new --prompt=/dev/stdin",
    "prompt": "TANGLED_HANDLE=\u003cfill-this-in\u003e\nKNOT_CONTACT_EMAIL=\u003cfill-this-in\u003e\n\nSet up Tangled knot on this VM by following the exe.dev recipe at https://exe-staging.dev/deploy/tangled.md from top to bottom.\n\nThe values at the top of this message are mine:\n- TANGLED_HANDLE: the handle you sign in to tangled.org with: `alice.tngl.sh` if you signed up there with an email, or your Bluesky handle; it becomes the knot's owner\n- KNOT_CONTACT_EMAIL: an email address the knot publishes for abuse reports and questions\nAsk me for any that still say \u003cfill-this-in\u003e before you need them.\n\nThe recipe's example VM name is my-knot. This VM's name is the output of `hostname`: use it wherever the recipe writes my-knot. Skip the step that creates the VM; you are on it.\n\nYou are done when all of these are true. Check each one yourself:\n- Tangled's knot 1.20 at `https://my-knot.exe.xyz/`, owned by your atproto DID, restarted on failure and after a reboot.\n- `/xrpc/_health` and `/.well-known/did.json` answering on the knot's address, ready to add on tangled.org.\n- `knot-member add \u003chandle\u003e` on the VM, to let other people create repositories on the knot.\n- The knot's SSH server on port 2222, for pushes through exe.dev's SSH.\n- Repositories, keys and settings in `/var/lib/knot` and `/etc/knot`, backed up nightly to `/var/backups/knot`, with a restore checked.\n\nRead the whole recipe, closed details included, and follow \"Set up by\nhand\" in order, skipping VM creation; the walkthrough above it is for\nthe owner. Resolve TANGLED_HANDLE to a DID as written and stop if it\ndoesn't resolve. The build takes 15-25 minutes: run it in the\nbackground. On an existing VM, ask before replacing anything on port\n8000. Don't make the VM public yourself: the owner runs `ssh exe.dev\nshare set-public` on their computer. Show the owner the master key's\nline from /etc/knot/knot.env once, and tell them to store it off the\nVM. Finish with the `set-public` command, then \"Add the knot on\ntangled.org\" and \"Push over SSH\" for the owner to follow.\n\nFinish with the URLs I should open and these commands, which only I can run, from my own computer (with this VM's name in them):\n  ssh exe.dev share set-public my-knot\n  ssh my-knot.exe.xyz sudo systemctl restart knot.service\n",
    "prompt_url": "https://exe-staging.dev/deploy/tangled/prompt.txt"
  },
  "updated": "2026-11-04",
  "verified": "2026-11-04",
  "related": [
    "forgejo",
    "gitea",
    "github-actions",
    "code-server",
    "linux-desktop",
    "docker-host"
  ],
  "alternatives": [
    "GitHub",
    "Codeberg",
    "Forgejo"
  ]
}
