Skip to content

Migrating to the new Tangled knot2

Tangled is a Github alternative built on atproto. I've previously shown you how to set up the self-hosted repo server, here I go through migrating to knot2.

johanna
Aug 23, 20265 min read

angled are in the process of migrating to the new knot implementation, knot2. As a quick reminder, the knot is a self-hostable server capable of serving git repos that uses atproto to share information with the ATmosphere, and the Tangled AppView. This means you can self-host your own repo, like gitea or forgejo, while still being able to interact with other people in a single place.

I recently wrote about setting up knot and spindle. I had gotten everything working a week earlier, but it was while I was writing the blog post that I found out about knot2. Oh, well, migrating can’t be too bad, right? And there’s actually a great guide already written up, as well as tooling to help you. This write up provides a more Docker focused version of the migration guide, with my personal experience.

Prep

Okay, I hit the first challenge right off the bat. The Containerfile provided by the Tangled repo pins an amd64 arch runner image that I can’t use, so I stripped that out to clone and build the image locally. The docker image contains the migration script, so that’s why I’m building it locally first.

[object Object],[object Object],[object Object],[object Object]

And we have to create the KNOT_MASTER_KEY. Run this and store the value in a password manager.

[object Object]

Okay, and the final little bit of setup before we do the dry-run.

[object Object]

You need to have the KNOT_MASTER_KEY in the shell, so export it, and then run.

[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]

This is just a dry run. It’ll print out some information. Make sure it says everything looks good! You can run this any number of times. Here’s what my output looked like.

[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]

This is the last step before we go into the “scary” part, so make sure you’re happy with the output!

The migration

Okay, game day. It’s time to do this for real. Start by stopping your knot and do a backup.

[object Object],[object Object]

And here’s the non-dry-run version of the migration command.

[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]

Here’s my output so you know what to look for.

[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]

Okay! Unlike knot1, knot2 wants a nice config file with lots of explicit and clean options.

[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]

With most of the configuration done, the compose entry is pretty minimal. If you followed my previous guide, you can replace the previous knot service in place.

[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]

Now we’re ready to go:

[object Object]

here are some commands you can run to verify it works

[object Object],[object Object],[object Object],[object Object]

If something did not go as expected, you should be able to bring the old knot back by restoring the compose file and running docker compose up -d. We haven’t actually deleted anything, it’s all still there.

Caveat, I briefly had it start on me before I had properly filled in the config.toml file. If you see logs on startup about generating a new SSH host key, the paths in your config file don’t match your actual migrated file paths. Delete secrets/ and ssh/ folders in the mounted directory, fix the config file, and then start the compose again.

Clean up

Assuming your migration has gone well, you want to delete the migrated signing keys. They were stored in plain text for the migration, so let’s clear those away.

[object Object]

Once you’re comfortable that the migration went well, and you’ve got backups of the new volume, you can delete any other migration leftovers: server/ , repositories/, /var/tmp, and /tmp/tangled-core.

Closing notes

Big thank you to the Tangled team and @oyster.cafe for providing great documentation and a clean migration path. The new knot looks really slick. One of the big new things is that it doesn’t actually delegate to git under the hood, it comes with a full Rust git implementation instead. So, hopefully fewer CVEs 🤞

Did you enjoy this article?

Recommend it — Standard Reader surfaces well-loved writing to more readers across the network.

Across the AtmosphereDiscussions