Hosting my own code with a Tangled Knot

Back in August I took the leap and self hosted my PDS and after that I kept wondering “what else can I self host to own my data”. Turns out it was Tangled, the “GitHub for ATProto”.

I already had an account on Tangled and had a couple repositories hosted there (a couple of demos on building on ATProto with Go). But even though this was built on ATProto and my Tangled records were stored in my PDS (so I owned them), the actual code was hosted on one of the Tangled Knots (a lightweight Git server). If Tangled went away tomorrow, my code would go with it.

Thankfully they give you some nice instructions on setting up and hosting your own Knot. I like using Docker for things so opted for that approach, even though it’s not fully supported. That being said, they still helped out with some of the questions I had.

Since I had a server with my PDS already set up with Caddy, Docker etc I thought it would be a waste to not use it for my Knot as well.

Setting up the subdomain DNS record for my knot was easy (including the Caddy update) and getting the Docker container up and running with the provided Docker Compose file was also quite straight forward.

My first problem came when I couldn’t hit my server when trying to register it on Tangled. After a lot of restarting, and checking DNS I thought I’d see if my Caddy container was able to talk to my Knot container… and it could not. I took a look at the setup for the PDS Docker setup and finally noticed that the services defined in the Docker Compose file were all using the network mode host.

So I did the natural thing and made my Knot container also use host mode. That did not work. This was because the Knot container uses port 22 internally for SSH which meant the container failed to start due to port 22 on my server already being used for SSH.

I bravely opted (YOLO) to take the PDS containers off of host mode (backing all the config up), create a network for everything to talk to each other in Docker world, updated Caddy aaaaaaaaand it still didn’t work. But this time Caddy could talk to the Knot container so it was something else.

After a lot of reading and looking at the config I finally spotted in my Caddy file that I had a wildcard on my domain that redirects to the PDS container. This is used for other users on the PDS so that you have user1.domain.com. I suspected that when Tangled was calling my Knot, it was hitting that wildcard and redirecting to the PDS.

I didn't use a pds subdomain for my PDS by the way because Cloudflare wanted £10 a month for certificates for more than 1 level of subdomain, meaning that I wouldn't have been able to have user1.pds.mydomain.com

Since I was the only user on the PDS, other than my alt test account, I removed the wildcard and bingo, Tangled could talk to my Knot. Success!!! Also my alt test account broke, but that was a problem to fix another time, I had had enough of Caddy and DNS for a while. Apparently Caddy should be able to route correctly and have the wildcard as the last option but I couldn't get that to work. If someone could help me, that would be great!!

Next up was creating a repository and putting some code into it. The first bit was easy. Create a new repository with the UI and point it to the Knot I had registered. Took a look in my Knot container / the mount for it on my server and there was a new directory filed with default Git file stuff.

Next I needed to push some code to it, so I create a new git repository on my laptop, added the traditional hello world text file, committed, set the origin and everything but when it came to pushing, it hung and timed out.

This was a pain to figure out and I ended up asking on Bluesky and the Tangled Discord. Thankfully some helpful people pointed out that I needed to set my ssh config on my local laptop to point to port 2222 because that’s what the Docker container is using to map to the internal port 22. Without this I was attempting to push code to port 22 on my server, but there isn't a git server on my server at that port.

So I needed to do something like this in my ~/.ssh/config

Host knot.mydomain.com
User git
Hostname <IP HERE>
Port 2222

After doing that it worked, I pushed my hello world text file to my Knot!!!

So it seemed like setting up a self hosted Knot wasn’t too much of a pain if you didn’t make the silly mistakes like I did. I say silly mistakes, but because I hadn't done anything like this before, I didn't know any better. Thankfully there's a fantastic community out there to help and hopefully by writing my experience up in this post, it might help others out too!!!

So to sum up the issues:

1: Make sure that if using the same server as a PDS and you're using the same Caddy instance, that you take the PDS services out of host network mode in Docker

2: If you're using Cloudflare for your domain and you didn't use a subdomain for your PDS and you're using the same server, you need to remove the wildcard catch in the Caddyfile.

3: Ensure you have the correct config on your local machine which points to port 2222 of your server for SSH.