git-remote-gcrypt pushes a GnuPG encrypted repository to a plain file host
PGP-encrypted git remotes
At a glance
- What is it?
- git-remote-gcrypt is a git remote helper that stores a repository as a GnuPG encrypted bundle on any rsync, sftp or plain git host, so a team can collaborate on a private repository without trusting the host. The interesting engineering is in the participants model, in the choice of backend, and in a setting that turns git's implicit force push into an explicit one.
- Who is it for?
- git-remote-gcrypt suits a team that needs to keep a repository confidential on storage it does not control, such as a credential store or an internal project on a plain file host, and it suits a sysadmin who is comfortable with GPG key management.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 69 days ago.
- What is it written in?
- Mainly Shell, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A remote helper for repositories you cannot store in the clear
git-remote-gcrypt is a git remote helper to push and pull from repositories encrypted with GnuPG, using a custom format, and it handles URIs prefixed with gcrypt::. The stated aim is to provide confidential, authenticated git storage and collaboration using typical untrusted file hosts or services.
That is a narrow goal and a useful one. The obvious alternative to a hosted private repository, when you do not want to run a server, is a bare git repository on a file host over rsync, and the obvious problem is that the objects in it are readable by the host. A remote helper that encrypts the repository before it leaves the machine changes that, and because it is a helper rather than a server, the client keeps doing the git work and only the storage is different.
The quickstart shows the shape of it. You add a remote with a gcrypt prefixed URI, and you push:
git remote add cryptremote gcrypt::rsync://example.com/repo
git push cryptremote master
> gcrypt: Setting up new repository
> gcrypt: Remote ID is :id:7VigUnLVYVtZx8oir34R
> [ more lines .. ]
> To gcrypt::[...]
> * [new branch] master -> masterThe remote ID appears on the first push, and the documentation is careful about what it is and is not. It is not secret, and it exists only to ensure that two repositories signed by the same user can be distinguished. You will see a warning if it changes, which should only happen if the remote was re-created.
Installation is either a distribution package, with Debian, Ubuntu, Fedora, Arch and some smaller distributions known to have them, or the supplied install.sh script on other systems. The licence is GPL-3.0 and the main executable is a POSIX compliant shell script, with the heavy lifting done by rsync, curl, rclone and GPG.
The backend decides whether this scales, and one of them should be avoided
The supported backends are local, rsync:// and sftp://, where the repository is stored as a set of files, and alternatively any giturl, where gcrypt stores the same representation in a git repository bridged over arbitrary git transport. There is also an experimental rclone:// backend, described as being for early adopters only, with a warning attached.
The performance section is the most important passage in the documentation, and it is a warning rather than a description. Using an arbitrary giturl or an sftp:// URI requires uploading the entire repository history with each push, which means pushes get slower as the history grows, and it can easily reach the point where continued use is impractical.
The guidance is therefore to use those backends only when you know the repository will not ever grow very large, not merely that it is not large now, and the documentation says that this makes them inappropriate for most repositories and likely suitable only for unusual cases such as small credential stores. And even then, use rsync:// if you can.
The rsync:// backend is therefore the default choice, and it has one limitation that matters: it will not work with a repository hosting service such as Gitolite, GitHub or GitLab, because those speak git rather than rsync. If your storage is a hosted git service, the choices are the giturl backend with its full history upload, or a plain file host reachable by rsync or sftp.
The rsync URI format is worth getting right too. It is rsync://user@host/path, which translates to the rsync location user@host:/path accessed over ssh, and the path is absolute rather than relative to the home directory. An earlier non-standard format, rsync://user@host:path, is also supported.
Participants are the access control list
The configuration model has one setting that carries the security, and it is the participants list.
The gcrypt-participants setting, which can be set per remote or per repository, is a space-separated list of GPG key identifiers. The remote is encrypted to these participants and only signatures from these are accepted. The documentation points at gpg -k to list the public keys you know, which is how you find the identifiers of your collaborators.
What happens when the setting is absent is the part to notice. If the option is not set, the remote is encrypted to your default key and any valid signature is accepted. That default is convenient and it is the weakest setting in the tool, because a repository encrypted to one key and accepting any signature is a repository anyone with a key can push to. The documentation notes that this behaviour can also be requested explicitly by setting participants to simple, which is a good API decision, because it turns the loose default into a named mode you can search for in a configuration review.
Precedence is defined as well: the setting on the remote takes precedence over the repository variable, so a per remote configuration wins over a repository wide one.
For a team setting this up for the first time, the sequence is the one in the documentation's examples: add the remote, set the participants list to the keys of everyone involved, and push. A remote is created on the first push, and the encryption of the manifest is updated for each push to match the participant configuration, so the access list is a property of the remote rather than of a single push.
That last point has a practical consequence. The documentation states that each pushing user must have the public keys of all collaborators and the correct participant config, which means that adding a collaborator is a two sided operation: their key has to be in the list, and they have to have the keys of everyone else, or the manifest update will fail for them.
Obscuring the participant list, and why it annoys people
One setting in this tool is unusual enough to deserve its own explanation, because it trades a security property for a convenience one and the documentation is honest about both.
By default, the gpg key ids of the participants are obscured by encrypting with the recipient key option, gpg -R. Setting gcrypt-publish-participants to true disables that measure, and the documentation explains the problem it causes: to decrypt, gpg tries each available secret key in turn until it finds a usable key, which can result in unnecessary passphrase prompts.
So the default hides the list of who can read the repository from anyone who can see the encrypted manifest, and the cost of that is that your own gpg agent will offer you a passphrase for every key in your ring until it finds the right one. A user with a dozen keys will notice this immediately, and the setting that turns it off is the one they will set, which means the list of participants is published in practice even though the default tries to keep it private.
Two other settings are more mundane. gcrypt.gpg-args passes its contents as arguments to gpg, for example to use the agent. And there is a per remote signing key setting, with the note that you should set the ordinary user signing key if your default signing key is not part of the participant list, and that the per remote version lets you sign different remotes with different keys, which is what you need when one person participates in several repositories with different key sets.
There is also a per remote and global rsync put flags setting, so the flags passed to rsync when uploading can differ per remote, with the global ones not applied to a remote that has its own.
Turning git's implicit force push into an explicit one
One setting in this tool exists because of a longstanding git behaviour, and the explanation is the clearest argument in the documentation.
The setting is gcrypt-require-explicit-force-push, and the reason is stated as a bug: every git push effectively has a force in it. If the setting is true, git-remote-gcrypt will refuse to push unless force is passed, or the refspecs are prefixed with a plus. The documentation links a potential solution in the Debian bug tracker.
For a project whose whole point is confidential, authenticated storage, this is the setting that closes the obvious hole. A force push to an encrypted remote can rewrite history, and if the participants list has changed, or if a collaborator has pushed something you have not seen, a force push can replace it. Making that an explicit act rather than the default behaviour of an ordinary push is the difference between a shared remote and a fragile one.
There is one more environment variable worth knowing. GCRYPT_FULL_REPACK, when set to anything other than the empty string, forces a full repack when pushing, which is a recovery tool rather than a setting you would leave on.
The rest of the operational notes are short. Both GPG 1.4 and 2 are supported, you need a personal GPG key, and the GPG configuration applies to the algorithm choices for public key encryption, symmetric encryption and signing, with the man page for gpg as the reference.
For a team that has never used GPG keys beyond signing commits, that last point is the real prerequisite: the key management, the passphrase agent, the participant lists and the export of public keys are all part of adopting this tool, and none of them are about git.
Editorial conclusion
git-remote-gcrypt suits a team that needs to keep a repository confidential on storage it does not control, such as a credential store or an internal project on a plain file host, and it suits a sysadmin who is comfortable with GPG key management. It is the wrong choice for a repository that will grow, because the git and sftp backends upload the entire history on every push and become impractical over time, and a poor match if you want to host on a service such as GitHub or GitLab, since the rsync backend cannot talk to those. Before adopting, choose a backend on the basis of how large the repository will get, set the participants list explicitly rather than relying on the default of accepting any valid signature, and read the force push setting before your first push to an existing remote.
Frequently asked questions
What does git-remote-gcrypt do?
It is a git remote helper that pushes and pulls repositories encrypted with GnuPG using a custom format, handling URIs prefixed with gcrypt::. The aim is confidential, authenticated git storage and collaboration on typical untrusted file hosts or services, with the repository stored as a set of files or inside a git repository.
Which backend should I use for a gcrypt remote?
Prefer local or rsync://, and avoid the arbitrary giturl and sftp:// backends unless the repository will never grow large, because they upload the entire history with each push. Note that rsync:// will not work with a hosting service such as Gitolite, GitHub or GitLab, and the rclone backend is experimental.
How do I control who can read a gcrypt remote?
Set gcrypt-participants to a space-separated list of GPG key identifiers, which encrypts the remote to those participants and accepts only their signatures, and the per remote setting takes precedence over the repository wide one. If the option is not set the remote is encrypted to your default key and any valid signature is accepted, which is also available explicitly as the simple mode.
What is the gcrypt Remote ID for?
It is not secret. It exists so that two repositories signed by the same user can be distinguished, and you will see a warning if it changes, which should only happen if the remote was re-created.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/spwhitton-git-remote-gcrypt)Was this useful?