diff --git a/website/posts/git-authenticate.md b/website/posts/git-authenticate.md
new file mode 100644
index 0000000..9950b37
--- /dev/null
+++ b/website/posts/git-authenticate.md
@@ -0,0 +1,217 @@
+title: Authenticate your Git checkouts!
+author: Ludovic Courtès
+tags: Security, Software development
+date: 2024-05-06 14:14
+---
+
+You clone a Git repository, then pull from it.  How can you tell its
+contents are “authentic”—i.e., coming from the “genuine” project you
+think you’re pulling from, written by the fine human beings you've been
+working with?  With commit signatures and “verified” badges ✅
+flourishing, you’d think this has long been solved—but nope!
+
+Four years after Guix [deployed its own
+tool](https://guix.gnu.org/en/blog/2020/securing-updates/) to allow
+users to authenticate updates fetched with `guix pull` (which uses Git
+under the hood), the situation hasn’t changed all that much: the vast
+majority of developers using Git simply do not authenticate the code
+they pull.  That’s pretty bad.  It’s the modern-day equivalent of
+sharing unsigned tarballs and packages like we’d blissfully do in the
+past century.
+
+The authentication mechanism Guix uses for
+[channels](https://guix.gnu.org/manual/devel/en/html_node/Channels.html)
+is available to any Git user through the [`guix git
+authenticate`](https://guix.gnu.org/manual/devel/en/html_node/Invoking-guix-git-authenticate.html)
+command.  This post is a guide for Git users who are not necessarily
+Guix users but are interested in using this command for their own
+repositories.  Before looking into the command-line interface and how we
+improved it to make it more convenient, let’s dispel any
+misunderstandings or misconceptions.
+
+# Why you should care
+
+When you run `git pull`, you’re fetching a bunch of commits from a
+server.  If it’s over HTTPS, you’re authenticating *the server* itself,
+which is nice, but that does not tell you who the code actually comes
+from—the server might be compromised and an attacker pushed code to the
+repository.  Not helpful.  At all.
+
+But hey, maybe you think you’re good because everyone on your project is
+signing commits and tags, and because you’re disciplined, you routinely
+run `git log --show-signature` and check those “Good signature” GPG
+messages.  Maybe you even have those fancy “✅ verified” badges as found
+[on
+GitLab](https://docs.gitlab.com/ee/user/project/repository/signed_commits/gpg.html)
+and [on
+GitHub](https://docs.github.com/en/authentication/managing-commit-signature-verification).
+
+Signing commits is part of the solution, but it’s not enough to
+_authenticate_ a set of commits that you pull; all it shows is that,
+well, those commits are signed.  Badges aren’t much better: the presence
+of a “verified” badge only shows that the commit is signed by the
+OpenPGP key *currently registered* for the corresponding GitLab/GitHub
+account.  If you register a new key, or if you leave the project, your
+commits lose their badge.  Not helpful either, not to mention that this
+is all tied to the hosting site you’re on, outside of Git’s control.
+
+Being able to ensure that when you run `git pull`, you’re getting code
+that _genuinely_ comes from authorized developers of the project is
+basic security hygiene.  Obviously it cannot protect against efforts to
+infiltrate a project to eventually get commit access and insert
+malicious code—the kind of multi-year plot that led to the [xz
+backdoor](https://tukaani.org/xz-backdoor/)—but if you don’t even
+protect against unauthorized commits, then all bets are off.
+
+Authentication is something we naturally expect from `apt update`,
+`pip`, `guix pull`, and similar tools; why not treat `git pull` to the
+same standard?
+
+# Initial setup
+
+The [`guix git
+authenticate`](https://guix.gnu.org/manual/devel/en/html_node/Invoking-guix-git-authenticate.html)
+command authenticates Git checkouts, unsurprisingly.  It’s currently
+part of Guix because that’s where it was brought to life, but it can be
+used on any Git repository.  This section focuses on how to use it; you
+can learn about the motivation, its design, and its implementation in
+[the 2020 blog
+post](https://guix.gnu.org/en/blog/2020/securing-updates/), in the 2022
+peer-reviewed academic paper entitled [_Building a Secure Software
+Supply Chain with
+GNU Guix_](https://doi.org/10.22152/programming-journal.org/2023/7/1),
+or in this 20mn
+[presentation](https://archive.fosdem.org/2023/schedule/event/security_where_does_that_code_come_from/).
+
+To support authentication of your repository with `guix git
+authenticate`, you need to follow these steps:
+
+  0. Enable commit signing on your repo: `git config commit.gpgSign
+	 true`.  (Git now supports other signing methods but here we need
+	 OpenPGP signatures.)
+
+  1. Create a `keyring` branch containing all the OpenPGP keys of all
+	 the committers, along these lines:
+
+	 ```
+	 git checkout --orphan keyring
+	 git reset --hard
+	 gpg --export alice@example.org > alice.key
+	 …
+	 git add *.key
+	 git commit -a -m "Add committer keys."
+	 ```
+
+	 All the files must end in `.key`.  You must never remove keys from
+	 that branch: keys of users who left the project are necessary to
+	 authenticate past commits.
+
+  2. Back to the main branch, add a `.guix-authorizations` file, listing
+	 the OpenPGP keys of authorized committers—we’ll get back to its
+	 format below.
+
+  3. Commit!  This becomes the _introductory commit_ from which
+	 authentication can proceed.  The _introduction_ of your repository
+	 is the ID of this commit and the OpenPGP fingerprint of the key
+	 used to sign it.
+
+That’s it.  From now on, anyone who clones the repository can
+authenticate it.  The first time, run:
+
+```
+guix git authenticate COMMIT SIGNER
+```
+
+… where `COMMIT` is the commit ID of the introductory commit, and
+`SIGNER` is the OpenPGP fingerprint of the key used to sign that commit
+(make sure to enclose it in double quotes if there are spaces!).  As a
+repo maintainer, you must advertise this introductory commit ID and
+fingerprint on a web page or in a `README` file so others know what to
+pass to `guix git authenticate`.
+
+The commit and signer are now recorded on the first run in
+`.git/config`; next time, you can run it without any arguments:
+
+```
+guix git authenticate
+```
+
+The other new feature is that the first time you run it, the command
+installs *pre-push and pre-merge hooks* (unless preexisting hooks are
+found) such that your repository is automatically authenticated from
+there on every time you run `git pull` or `git push`.
+
+`guix git authenticate` exits with a non-zero code and an error message
+when it stumbles upon a commit that lacks a signature, that is signed by
+a key not in the `keyring` branch, or that is signed by a key not listed
+in `.guix-authorizations`.
+
+# Maintaining the list of authorized committers
+
+The `.guix-authorizations` file in the repository is central: it lists
+the OpenPGP fingerprints of authorized committers.  Any commit that is
+*not* signed by a key listed in the `.guix-authorizations` file of its
+parent commit(s) is considered inauthentic—and an error is reported.
+The [format of
+`.guix-authorizations`](https://guix.gnu.org/manual/devel/en/html_node/Specifying-Channel-Authorizations.html#channel_002dauthorizations)
+is based on [S-expressions](https://en.wikipedia.org/wiki/S-expression)
+and looks like this:
+
+```scheme
+;; Example '.guix-authorizations' file.
+
+(authorizations
+ (version 0)               ;current file format version
+
+ (("AD17 A21E F8AE D8F1 CC02  DBD9 F8AE D8F1 765C 61E3"
+   (name "alice"))
+  ("2A39 3FFF 68F4 EF7A 3D29  12AF 68F4 EF7A 22FB B2D5"
+   (name "bob"))
+  ("CABB A931 C0FF EEC6 900D  0CFB 090B 1199 3D9A EBB5"
+   (name "charlie"))))
+```
+
+The `name` bits are hints and do not have any effect; what matters is
+the fingerprints that are listed.  You can obtain them with GnuPG by
+running commands like:
+
+```
+gpg --fingerprint charlie@example.org
+```
+
+At any time you can add or remove keys from `.guix-authorizations` and
+commit the changes; those changes take effect for child commits.  For
+example, if we add Billie’s fingerprint to the file in commit _A_, then
+Billie becomes an authorized committer in *descendants* of commit _A_
+(we must make sure to add Billie’s key as a file in the `keyring`
+branch, too, as we saw above); Billie is still unauthorized in branches
+that lack _A_.  If we remove Charlie’s key from the file in commit _B_,
+then Charlie is no longer an authorized committer, except in branches
+that start before _B_.  This should feel rather natural.
+
+That’s pretty much all you need to know to get started!  [Check the
+manual](https://guix.gnu.org/manual/devel/en/html_node/Invoking-guix-git-authenticate.html)
+for more info.
+
+All the information needed to authenticate the repository is contained
+in the repository itself—it does not depend on a forge or key server.
+That’s a good property to allow anyone to authenticate it, to ensure
+determinism and transparency, and to avoid lock-in.
+
+# Interested? You can help!
+
+`guix git authenticate` is a great tool that you can start using today
+so you and fellow co-workers can be sure you’re getting the right code!
+It solves an important problem that, to my knowledge, hasn’t really been
+addressed by any other tool.
+
+Maybe you’re interested but don’t feel like installing Guix “just” for
+this tool.  Maybe you’re not into Scheme and Lisp and would rather use a
+tool written in your favorite language.  Or maybe you think—and
+rightfully so—that such a tool ought to be part of Git proper.
+
+That’s OK, we can talk!  We’re open to discussing with folks who’d like
+to come up with alternative implementations—check out the articles
+mentioned above if you’d like to take that route.  And we’re open to
+contributing to a standardization effort.  Let’s [get in
+touch](https://guix.gnu.org/contact/)!
