iroh transport for git

2026 JUNE 18

Iroh is a pretty cool project by n0 computer. It provides a way for two computers behind NAT to connect. Even though none of them have a stable public IP or open ports in their router. This opens up quite a few possibilities. One of which is running a git server behind NAT on a normal computer. Let your co-workers and friends push directly to your repository. Pull and push from theirs. Turns out git has strong transport abstraction and iroh fits right in. Check it out here:

iroh-git on GitHub

Motivation

Game projects can grow quite large. Unfortunately, when repositories grow large GitHub’s size limits kick in. There must be a better way than storing our git repositories without third parties.

Fortunately for us, iroh reached version 1.0 recently and git allows for transport abstractions! With these two pieces we can stream huge git repositories directly to our friends peer-to-peer.

Download

The source code and pre-built binaries are available on GitHub:

iroh-git on GitHub

Installation

Download the pre-compiled Windows binaries, or compile your own from source. You need cargo then run cargo build --release.

Add the binaries to your PATH. This is required for git to find them, and for you to invoke them from the terminal.

The git-iroh binary is used to invoke git iroh commands for sharing repositories, managing access, and other chores. Required by both the server and the client.

The git-remote-iroh binary is used to resolve iroh:// style URLs when cloning a repository. Technically only required by the client.

The iroh-git-tray is the long running server that listens for incoming connections from git-remote-iroh. It provides a notification icon on Windows and a context menu with creature comforts such as “Start at login”.

The iroh-git-daemon is the same thing; but in CLI form.

This is also a good time to update your git installation to the latest version.

Sharing a repository

Let’s say you want to share the repository at C:/Repos/MyRepo with your friend. Three things must happen:

  1. Both need to install iroh-git
  2. You must run iroh-git-tray (a tray icon program) or iroh-git-daemon (for headless mode)
  3. You need to create an access ticket for your friend

The daemon is the long running server that listens for incoming connections, it facilitates access control, and it hands over incoming push/pull requests to your git installation. It’s a rather dumb pipe that ferries git packets back and forth. But, it will only serve git repositories you have authorized. And, it will only accept connections from members you’ve granted access.

You need to know your friend’s NODE_ID in order to grant them access to the repository. Iroh doesn’t use IP-addresses. Instead it uses stable public/private encryption key pairs. A NODE_ID is the public part of such a key. Each iroh-git client gets one, and each iroh-git server gets another. Iroh uses these NODE_IDs to facilitate end-to-end encryption and IP-lookup.

Your friend runs git iroh show-id. This prints their NODE_ID. Something like this:

$ git iroh show-id
877c36753fcc84f71f9f804010ab4d0941d0a88ab95c1afabc09d93c6be6712c

That NODE_ID is their unique identifier. It belongs to your friend, and them only. This is how they are identified. This is the public part of their cryptographic key.

The NODE_ID isn’t secret. It is the public part of the cryptographic key after all. But only people that possess your NODE_ID can attempt a connection. The NODE_ID is un-guessable, though. Don’t hand them out unnecessarily. They can be regenerated if you need to be forgotten. See git iroh help keygen.

They hand you their NODE_ID. You grant access to the repository:

$ cd C:/Repos/MyRepo
$ git iroh grant 877c36753fcc84f71f9f804010ab4d0941d0a88ab95c1afabc09d93c6be6712c --write --name friend
granted read-write access to C:/Repos/MyRepo
iroh://tfzuupmqj2mutd66lykmt7u4xstmidaht...eyh64bhxkjgwynbyr5xca/MyRepo.git

The --write flag grants push access. Without, they can only pull.

Push or pull access is granted on a per-repository and per-NODE_ID basis. All refs are visible to everyone with access. There is no access control for individual branches.

The --name flag is used to identify them in the list of shared repositories:

$ git iroh list
C:/Repos/MyRepo  [vxlmata73qe65je23buhchw4ia]
    rw  friend  (877c36753fcc84f71f9f804010ab4d0941d0a88ab95c1afabc09d93c6be6712c)

The resulting iroh-suffixed URL is used by your friend to clone the repository:

git clone iroh://tfzuupmqj2mutd66lykmt7u...zvs4l5n23aeyh64bhxkjgwynbyr5xca/MyRepo.git

This URL contains the server’s NODE_ID and a repository ID. The MyRepo.git part is only there to make git clone create a MyRepo directory.

The URL is unique per shared repository but only accessible to those you’ve granted access. The system knows your friend’s NODE_ID. It knows which cryptographic key to expect. Unknown NODE_IDs are rejected.

Removing access

List all repositories you’ve shared with git iroh list:

$ git iroh list
C:/Repos/MyRepo  [vxlmata73qe65je23buhchw4ia]
    rw  friend  (877c36753fcc84f71f9f804010ab4d0941d0a88ab95c1afabc09d93c6be6712c)

The vxlmata73qe65je23buhchw4ia is the SHARE_ID for the repository at C:/Repos/MyRepo. We can stop sharing this repository with:

$ git iroh stop vxlmata73qe65je23buhchw4ia

# or

$ cd C:/Repos/MyRepo
$ git iroh stop --this

It is also possible to revoke access for single member:

$ cd C:/Repos/MyRepo
$ git iroh revoke 877c36753fcc84f71f9f804010ab4d0941d0a88ab95c1afabc09d93c6be6712c

Curiosities

When sharing a repository, I suggest you share a bare repository. With a bare repository pushes and pulls works as expected. The one sharing a repository can simply create a new bare repository, set it as their origin then git push -u origin master as normal:

$ cd C:/Repos/MyRepoBare.git
$ git init --bare
$ git iroh grant 877c36753fcc...afabc09d93c6be6712c # Share with friend

$ cd C:/Repos/MyRepo
$ git remote add origin C:/Repos/MyRepoBare.git # Yes, a file path!
$ git push -u origin master

The downside, you now have two repositories on your hard-drive. A redundancy win though!

If instead, you share your checked out repository directly, git throws some nice error messages when your friend tries to push your checked out branch. Probably don’t disable those errors. Instead, either push to a non-checked out branch by following a successful Git branching model (good luck convincing your friend of that ;) Better yet, create a bare repository.

Discussion / contribution

Check out iroh-git on GitHub.