summaryrefslogtreecommitdiffstats
path: root/content/en/articles
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-11-06 12:59:28 +0100
committerDanilo M. <danix@danix.xyz>2026-11-06 12:59:28 +0100
commitefbe3e713c46be480c5fd87eb78105630ca46cd2 (patch)
tree0c9855e612b15eafdf5a84fce1a075971effb0f6 /content/en/articles
parent25571b8fc544f8910db3e9190a75027eb478f434 (diff)
downloaddanixxyz-efbe3e713c46be480c5fd87eb78105630ca46cd2.tar.gz
danixxyz-efbe3e713c46be480c5fd87eb78105630ca46cd2.zip
content: add "Your own password store" series as drafts
Three-part beginner tutorial, in English and Italian: creating a store with pass, GPG and git, choosing where to host it, and using it on the phone with HardenedPass. Screenshots are from the 0.3.3 release build on the test store. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'content/en/articles')
-rw-r--r--content/en/articles/your-own-password-store-part-1/how-it-works.svg67
-rw-r--r--content/en/articles/your-own-password-store-part-1/index.md169
-rw-r--r--content/en/articles/your-own-password-store-part-2/index.md139
-rw-r--r--content/en/articles/your-own-password-store-part-3/entry.pngbin0 -> 120733 bytes
-rw-r--r--content/en/articles/your-own-password-store-part-3/generator.pngbin0 -> 168517 bytes
-rw-r--r--content/en/articles/your-own-password-store-part-3/index.md133
-rw-r--r--content/en/articles/your-own-password-store-part-3/menu.pngbin0 -> 137529 bytes
-rw-r--r--content/en/articles/your-own-password-store-part-3/new-entry.pngbin0 -> 153509 bytes
-rw-r--r--content/en/articles/your-own-password-store-part-3/passphrase.pngbin0 -> 151180 bytes
-rw-r--r--content/en/articles/your-own-password-store-part-3/pgp-import.pngbin0 -> 147211 bytes
-rw-r--r--content/en/articles/your-own-password-store-part-3/repository.pngbin0 -> 144192 bytes
-rw-r--r--content/en/articles/your-own-password-store-part-3/ssh-generate.pngbin0 -> 137342 bytes
-rw-r--r--content/en/articles/your-own-password-store-part-3/ssh-key.pngbin0 -> 104249 bytes
-rw-r--r--content/en/articles/your-own-password-store-part-3/ssh-public.pngbin0 -> 199833 bytes
-rw-r--r--content/en/articles/your-own-password-store-part-3/store-list.pngbin0 -> 96216 bytes
-rw-r--r--content/en/articles/your-own-password-store-part-3/welcome.pngbin0 -> 133771 bytes
16 files changed, 508 insertions, 0 deletions
diff --git a/content/en/articles/your-own-password-store-part-1/how-it-works.svg b/content/en/articles/your-own-password-store-part-1/how-it-works.svg
new file mode 100644
index 0000000..c69b088
--- /dev/null
+++ b/content/en/articles/your-own-password-store-part-1/how-it-works.svg
@@ -0,0 +1,67 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 688" role="img" aria-labelledby="t d" font-family="'JetBrains Mono', ui-monospace, 'DejaVu Sans Mono', monospace">
+ <title id="t">How pass, GPG and git work together</title>
+ <desc id="d">On your devices, pass turns a password into a named entry and GPG encrypts it into a file. Git copies that encrypted file to and from the server. The private key and passphrase stay on your devices.</desc>
+ <defs>
+ <marker id="a" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0 0L10 5L0 10z" fill="#7a9bb8"/></marker>
+ <marker id="g" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0 0L10 5L0 10z" fill="#38bdf8"/></marker>
+ <marker id="k" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0 0L10 5L0 10z" fill="#00ff88"/></marker>
+ <symbol id="lock" viewBox="0 0 16 18"><path d="M4 8V5a4 4 0 0 1 8 0v3" fill="none" stroke="currentColor" stroke-width="2"/><rect x="1" y="8" width="14" height="10" rx="2" fill="currentColor"/></symbol>
+ </defs>
+
+ <rect width="520" height="688" rx="10" fill="#060b10"/>
+
+ <!-- your devices -->
+ <rect x="14" y="14" width="492" height="472" rx="8" fill="#101e2d" stroke="#182840" stroke-width="2"/>
+ <text x="32" y="44" font-size="14" font-weight="700" letter-spacing="2" fill="#7a9bb8">YOUR DEVICES</text>
+
+ <rect x="32" y="60" width="270" height="70" rx="6" fill="#060b10" stroke="#304860"/>
+ <text x="48" y="87" font-size="14" fill="#7a9bb8">your password</text>
+ <text x="48" y="114" font-size="19" fill="#c4d6e8">hunter2</text>
+
+ <path d="M66 132V188" stroke="#7a9bb8" stroke-width="2" marker-end="url(#a)"/>
+ <text x="82" y="155" font-size="17" font-weight="700" fill="#a855f7">pass</text>
+ <text x="82" y="175" font-size="14" fill="#c4d6e8">gives it a name</text>
+
+ <rect x="32" y="192" width="270" height="70" rx="6" fill="#060b10" stroke="#304860"/>
+ <text x="48" y="219" font-size="14" fill="#7a9bb8">an entry in your store</text>
+ <text x="48" y="246" font-size="19" fill="#c4d6e8">example.org</text>
+
+ <path d="M66 264V320" stroke="#7a9bb8" stroke-width="2" marker-end="url(#a)"/>
+ <text x="82" y="287" font-size="17" font-weight="700" fill="#a855f7">GPG</text>
+ <text x="82" y="307" font-size="14" fill="#c4d6e8">locks it with public key</text>
+
+ <rect x="32" y="324" width="270" height="70" rx="6" fill="#060b10" stroke="#a855f7" stroke-width="2"/>
+ <text x="48" y="351" font-size="14" fill="#7a9bb8">encrypted file</text>
+ <text x="48" y="378" font-size="19" fill="#c4d6e8">example.org.gpg</text>
+ <use href="#lock" x="268" y="346" width="20" height="23" color="#a855f7"/>
+
+ <!-- private key -->
+ <rect x="330" y="192" width="158" height="146" rx="6" fill="#060b10" stroke="#00ff88" stroke-width="2"/>
+ <text x="344" y="220" font-size="15" font-weight="700" fill="#00ff88">private key</text>
+ <text x="344" y="240" font-size="15" font-weight="700" fill="#00ff88">+ passphrase</text>
+ <text x="344" y="270" font-size="14" fill="#c4d6e8">unlock the</text>
+ <text x="344" y="289" font-size="14" fill="#c4d6e8">files, and never</text>
+ <text x="344" y="308" font-size="14" fill="#c4d6e8">leave here</text>
+ <path d="M409 340V359H306" fill="none" stroke="#00ff88" stroke-width="2" stroke-dasharray="6 5" marker-end="url(#k)"/>
+
+ <!-- server panel, under the git arrow -->
+ <rect x="14" y="510" width="492" height="164" rx="8" fill="#101e2d" stroke="#182840" stroke-width="2" stroke-dasharray="8 6"/>
+ <text x="488" y="540" text-anchor="end" font-size="14" font-weight="700" letter-spacing="2" fill="#7a9bb8">SERVER</text>
+
+ <!-- git crosses the line -->
+ <path d="M66 398V568" stroke="#38bdf8" stroke-width="2" marker-start="url(#g)" marker-end="url(#g)"/>
+ <text x="82" y="432" font-size="17" font-weight="700" fill="#38bdf8">git</text>
+ <text x="82" y="452" font-size="14" fill="#c4d6e8">push and pull copy the</text>
+ <text x="82" y="471" font-size="14" fill="#c4d6e8">encrypted file, nothing else</text>
+
+ <!-- server -->
+
+ <rect x="32" y="574" width="270" height="70" rx="6" fill="#060b10" stroke="#a855f7" stroke-width="2"/>
+ <text x="48" y="601" font-size="14" fill="#7a9bb8">encrypted file</text>
+ <text x="48" y="628" font-size="19" fill="#c4d6e8">example.org.gpg</text>
+ <use href="#lock" x="268" y="596" width="20" height="23" color="#a855f7"/>
+
+ <text x="330" y="596" font-size="14" fill="#f59e0b">the name is</text>
+ <text x="330" y="615" font-size="14" fill="#f59e0b">visible, what's</text>
+ <text x="330" y="634" font-size="14" fill="#f59e0b">inside is not</text>
+</svg>
diff --git a/content/en/articles/your-own-password-store-part-1/index.md b/content/en/articles/your-own-password-store-part-1/index.md
new file mode 100644
index 0000000..7ba9d93
--- /dev/null
+++ b/content/en/articles/your-own-password-store-part-1/index.md
@@ -0,0 +1,169 @@
++++
+title = "Your own password store #1"
+author = "Danilo M."
+type = "tech"
+date = "2026-11-06T10:01:00+01:00"
+draft = true
+description = "Build a password store from scratch with pass, GPG and git, even if you've never touched any of them."
+excerpt = "Build a password store from scratch with pass, GPG and git, even if you've never touched any of them."
+image = "/uppies/2026/11/hardenedpass-banner.png"
+tags = ["pass", "gnupg", "git", "android", "hardenedpass", "security", "tutorial"]
+categories = ["Code", "DIY"]
++++
+
+## Build the store
+
+I've been using [pass](https://www.passwordstore.org/) for years now. No cloud vault, no subscription, no company holding my passwords: just a folder of encrypted files in a git repository, which I can read with any tool I like. When the Android app I used to read that folder on my phone was archived, I forked it, and that's how [HardenedPass](https://danix.xyz/hardenedpass/) was born.
+
+The thing is, every time I try to explain this setup to someone I see their eyes glaze over at the third acronym. GPG, SSH, git, remotes, keys... it sounds like a lot, and honestly the first time it is a bit of work. But you do it once, and it's a lot less scary than it looks.
+
+So I'll take you by the hand and we'll build a password store from scratch, starting from nothing, and by the end you'll have your passwords on your phone, encrypted and synced. You don't need to know anything about git or GPG, I'll explain what you need as we go, and you can copy and paste every command.
+
+This is a series in three parts. Today we create the store, in [part two](../your-own-password-store-part-2/) we give it a home on a server, and in [part three](../your-own-password-store-part-3/) we put it on your phone and start using it.
+
+<!--more-->
+
+## What are we building?
+
+Three tools, each doing one job:
+
+- **pass** keeps every password in its own small file, and folders group them. That folder is called the *store*.
+- **GPG** (the program that does OpenPGP encryption) locks those files. You get a pair of keys: the **public key** locks, the **private key** unlocks, and a **passphrase** protects the private key.
+- **git** keeps track of the changes and copies the store between your devices, going through a *remote*, which is simply a copy of the repository living on a server.
+
+Here's the part that makes all of this work: the server only ever sees encrypted files. It can't read your passwords, and neither can anybody who breaks into it. Decryption happens on your devices only, with a key that never goes to the server.
+
+{{< image src="how-it-works.svg" alt="Diagram. On your devices, pass turns the password hunter2 into an entry called example.org, and GPG locks it into the encrypted file example.org.gpg. Git pushes and pulls that encrypted file to and from the server. The private key and passphrase unlock the files and stay on your devices. On the server the file name is visible, but its content is not." class="max-w-md mx-auto rounded-lg border border-border" />}}
+
+{{< callout type="warning" title="What the server can see" >}}
+Passwords and everything else inside an entry are encrypted, but **file names are not**. If you have an entry called `bank/mybank.example.org`, whoever can read the repository knows you have an account there, and git history tells them when you changed it. That's why we'll keep the repository private, even if the content is encrypted.
+{{< /callout >}}
+
+## Computer or phone only?
+
+You have two ways of doing this, and both end in the same place.
+
+| | With a computer | Phone only |
+|---|---|---|
+| Typing commands | Real keyboard, copy and paste | On a phone screen, in a terminal |
+| Extra software | `pass`, GPG and git, usually one command | [Termux](https://termux.dev/), a terminal app for Android |
+| Backup of your key | Easy, on a USB stick | You must find a way to get it off the phone |
+| Using the store on a computer later | Already there | Needs the key moved over |
+
+HardenedPass can't create OpenPGP keys, it only imports them, so *something* has to make the key for you. If you have access to a Linux computer, even for half an hour, take that road: it's more comfortable, and backing up the key is much easier. It's what I'll describe first. If you only have your phone it's perfectly doable, follow along anyway because I'll explain everything here, and then jump to [the phone only route](../your-own-password-store-part-2/#the-phone-only-route) in part two, which uses the same commands.
+
+## Install the tools
+
+On Linux everything's in your distribution's repositories:
+
+```bash
+# Debian, Ubuntu, Mint
+sudo apt install gnupg pass git
+
+# Fedora
+sudo dnf install gnupg2 pass git
+
+# Arch
+sudo pacman -S gnupg pass git
+```
+
+On Slackware you already have GPG and git, and `password-store` is on [SlackBuilds.org](https://slackbuilds.org/).
+
+**On macOS** you can get the same tools from [Homebrew](https://brew.sh/) with `brew install gnupg pass git`. **On Windows** `pass` doesn't run natively, so install [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) with its default Ubuntu and use the Debian command above inside it. From here on, all the commands are the same.
+
+Now tell git who you are. This is only a label on your changes, it doesn't need to be your real name:
+
+```bash
+git config --global user.name "Your Name"
+git config --global user.email "you@example.org"
+```
+
+## Create your key
+
+```bash
+gpg --full-generate-key
+```
+
+GPG will ask you a few questions. Here's what I'd answer:
+
+1. **Kind of key:** press Enter to accept the default. On a recent GPG that's *ECC (sign and encrypt)*.
+2. **Elliptic curve:** press Enter again, for *Curve 25519*.
+3. **How long the key should be valid:** press Enter for *does not expire*, then `y` to confirm.
+4. **Real name and email address:** they don't have to be real, but remember the address, you'll need it in a minute. Leave the comment empty and press `O` to confirm.
+5. **Passphrase:** this one deserves its own section, see below.
+
+The defaults are good, but you have alternatives:
+
+- **RSA** (option 1) is the old reliable: bigger and slower keys, but it works everywhere. Pick it only if you have a reason to, for example an old tool that doesn't understand the newer curves.
+- **ECC and Kyber** is the new post-quantum option in the latest GPG versions. Stay away from it for now: it's very new and not everything can read it.
+- **An expiry date**, like `2y`, is a safety net: a key you lost stops being valid by itself. The price is that you must remember to extend it, so if this is your first key I'd rather keep it simple and not set one.
+
+### Choosing a passphrase
+
+The passphrase is the last line of defence: if somebody gets a copy of your private key, this is the only thing between them and all of your passwords, and they can try guessing it on their own machine as fast as they like. So it has to be strong, but you also have to remember it and type it, because **nobody can recover it for you**. There's no "forgot my password" link here.
+
+There are two ways of making a strong one:
+
+| | Random characters | Diceware |
+|---|---|---|
+| Looks like | `q7#Vm2!xTz9&Lp4w` | `smartness-dayroom-celtic-cheer-anointer-pulley` |
+| Strength | 16 characters: about 105 bits | 6 words: about 77 bits, 7 words: about 90 bits |
+| Easy to remember | No | Yes, after a few days |
+| Easy to type on a phone | Painful | Quite easy |
+| Good for | What a password manager remembers for you | What *you* have to remember |
+
+**Diceware** means picking random words from a list of 7776, traditionally by rolling five dice for each word. The trick is that the words must be picked *at random*: a sentence you came up with yourself, or your favourite song lyric, is much weaker than it looks, because people are terrible at being random. Each word adds about 12.9 bits, which is why length matters more than the words themselves.
+
+Random characters pack more strength in less space, but you'll never remember them. So my advice is: **7 diceware words for your GPG passphrase**, the one thing you need to memorize, and let the app generate everything else. The [EFF wordlist and instructions](https://www.eff.org/dice) are all you need, plus real dice if you have them. Write the passphrase on paper while you learn it, and keep the paper somewhere safe at home.
+
+When you're done, GPG prints a summary with a line looking like this:
+
+```
+pub ed25519 2026-11-06 [SC]
+ 1905811B654B494FBD151671593A16E792BC639D
+uid Your Name <you@example.org>
+sub cv25519 2026-11-06 [E]
+```
+
+That long string is your key's *fingerprint*. GPG also made you a **revocation certificate**, a file in `~/.gnupg/openpgp-revocs.d/` which tells the world the key shouldn't be used anymore, in case you lose control of it.
+
+## Back up your key, now
+
+If you lose your private key, your passwords are gone forever. There's no way around this: it's the same encryption that protects you from everyone else. So let's do this before we put anything important in the store.
+
+```bash
+gpg --armor --export-secret-keys you@example.org > private-key.asc
+```
+
+GPG asks for the passphrase and writes your private key in `private-key.asc`. Copy that file and the revocation certificate on a USB stick that stays at home, preferably an encrypted one, and keep the file around for now, because the phone will need it in part three.
+
+## Create the store
+
+Use the address you gave to your key:
+
+```bash
+pass init you@example.org
+pass git init
+```
+
+The first command creates the store in `~/.password-store`, and the second turns it into a git repository. From now on `pass` saves every change in git by itself.
+
+Let's add a first entry, to have something to test with. The first line is always the password, anything below it is extra information. Type this and finish with `Ctrl+D`:
+
+```bash
+pass insert -m example.org
+```
+
+```
+hunter2
+username: alice
+url: https://example.org
+```
+
+Check that it works with `pass show example.org`: GPG asks for your passphrase and you should see those three lines.
+
+## Up next
+
+If you made it up to here, you have a working password store, but for now it only lives on this computer. In [part two](../your-own-password-store-part-2/) we'll choose where to keep a copy of it, and I'll go through the options, from the big hosted services to your own server.
+
+See you on the next one 👋
diff --git a/content/en/articles/your-own-password-store-part-2/index.md b/content/en/articles/your-own-password-store-part-2/index.md
new file mode 100644
index 0000000..16f47df
--- /dev/null
+++ b/content/en/articles/your-own-password-store-part-2/index.md
@@ -0,0 +1,139 @@
++++
+title = "Your own password store #2"
+author = "Danilo M."
+type = "tech"
+date = "2026-11-06T10:02:00+01:00"
+draft = true
+description = "Choose where your encrypted password store lives, from hosted git services to your own server."
+excerpt = "Choose where your encrypted password store lives, from hosted git services to your own server."
+image = "/uppies/2026/11/hardenedpass-banner.png"
+tags = ["pass", "gnupg", "git", "android", "hardenedpass", "security", "tutorial"]
+categories = ["Code", "DIY"]
++++
+
+## Give it a home
+
+In [part one](../your-own-password-store-part-1/) we made a GPG key and created a password store, but so far it lives on a single machine. Today we'll give it a home on a server, so that your phone can reach it and you have a copy if that machine dies. If you don't have a computer at all, this is also where you'll find the phone only route.
+
+<!--more-->
+
+## Pick a home for your store
+
+You need a git server to sync through. Since your store is encrypted you have more freedom here than you'd think, these are all good options:
+
+| Provider | Cost | Run by | Good to know |
+|---|---|---|---|
+| [Codeberg](https://codeberg.org/) | Free | German non-profit | Private repositories have limits, read below |
+| [GitHub](https://github.com/) | Free | Microsoft | Easiest to find help for, private repositories included |
+| [GitLab](https://gitlab.com/) | Free | GitLab Inc. | 10 GiB per project, far more than you'll ever need |
+| [SourceHut](https://sourcehut.org/) | Optional, from €4 a month | SourceHut | Minimal, no JavaScript needed, SSH only |
+| Your own server | What you already pay | You | The most private, but keeping it alive is on you |
+
+A store is tiny, a few KB per password, so storage limits aren't a concern anywhere. What you're really choosing is who you're comfortable with holding your file names and your history. With a hosted service you're trusting a company or an association, with your own server you're trusting yourself.
+
+If you don't know what to pick: **GitHub or GitLab** are the easiest to start with, **Codeberg** is the one I'd pick if you already contribute to free software, and **your own server** is what I use myself, once you're comfortable with the rest.
+
+Whichever you pick, you'll need two things: an **SSH key**, which is how your computer proves who it is without a password, and an **empty, private repository**. Let's make the key first, it's the same for all of them:
+
+```bash
+ssh-keygen -t ed25519
+```
+
+Press Enter to accept the file name, and give it a passphrase if you want one. Then print the public part, which is the one you'll paste on the provider's website:
+
+```bash
+cat ~/.ssh/id_ed25519.pub
+```
+
+As with GPG, the public half isn't a secret. The file without `.pub` is, and it never leaves your computer.
+
+### GitHub
+
+1. Create an account, then go to **Settings**, **SSH and GPG keys**, **New SSH key**, and paste your key.
+2. Go to [github.com/new](https://github.com/new), name the repository `password-store` and choose **Private**. Don't add a README, a license or a `.gitignore`: the repository must be empty.
+3. Your address is `git@github.com:you/password-store.git`.
+
+### GitLab
+
+1. Create an account, then in your profile's preferences open **SSH Keys** and add your key.
+2. Go to [New project](https://gitlab.com/projects/new), choose **Create blank project**, name it `password-store`, set the visibility to **Private** and untick the option that creates a README.
+3. Your address is `git@gitlab.com:you/password-store.git`.
+
+### Codeberg
+
+Codeberg is a non-profit for free software, and it's upfront about it: [private repositories](https://docs.codeberg.org/getting-started/faq/) are meant for people who contribute to free software, with a limit of 100 MB, and its [terms](https://codeberg.org/Codeberg/org/src/branch/main/TermsOfUse.md) allow "really small & personal stuff", but not a personal cloud. A password store is small and personal, but if you don't contribute to free software at all, please pick another provider and leave those resources to the people they're meant for.
+
+1. Create an account, then go to **Settings**, **SSH / GPG keys**, and add your key.
+2. Go to [New repository](https://codeberg.org/repo/create), name it `password-store`, tick **Make repository private** and leave everything else unticked so it stays empty.
+3. Your address is `git@codeberg.org:you/password-store.git`.
+
+### SourceHut
+
+I've never used SourceHut for my store, so this comes from [their documentation](https://man.sr.ht/tutorials/set-up-account-and-git.md). It's a small, independent and very no-nonsense service. Git hosting doesn't require a paid account while the service is in alpha, but paying is how it stays alive.
+
+1. Register at [meta.sr.ht](https://meta.sr.ht/) and add your key at [meta.sr.ht/keys](https://meta.sr.ht/keys).
+2. You don't even need to create the repository: it's created on your first push, and it's **private by default**.
+3. Your address is `git@git.sr.ht:~you/password-store`.
+
+### Your own server
+
+Any machine you can reach with SSH will do: a VPS, a NAS, a Raspberry Pi in the closet. All you need there is git and an empty repository:
+
+```bash
+git init --bare ~/password-store.git
+```
+
+Your address is `you@server.example.org:password-store.git`, and if SSH doesn't run on port 22, use the long form: `ssh://you@server.example.org:2222/home/you/password-store.git`.
+
+If you want a web interface as well, [Forgejo](https://forgejo.org/) is a lightweight self-hosted GitHub alternative, and it's what powers Codeberg. Once it's installed the steps are the same as Codeberg's. Just remember that a server you own only stays safe if you keep it updated.
+
+## Send your store to the server
+
+Use your own address here:
+
+```bash
+pass git remote add origin git@github.com:you/password-store.git
+pass git push -u origin HEAD
+```
+
+The first time SSH shows you the server's fingerprint and asks if you trust it. Type `yes`. To be thorough, compare it with the one on the provider's documentation first.
+
+That's it, your store now lives on the server too. If you open the repository in your browser you'll see `example.org.gpg`, and if you open it you'll see nothing useful. Good.
+
+## The phone only route
+
+No computer? Your phone can do everything we did above, thanks to [Termux](https://f-droid.org/packages/com.termux/). Install it from F-Droid or from its GitHub releases, not from the Play Store, and open it. I'll only tell you what's different, the explanations above are still valid.
+
+First update everything, **this is not optional**. If you skip it, GPG refuses to start with `libgcrypt is too old`. During the upgrade you may be asked what to do with some configuration files: just press Enter to keep the default.
+
+```bash
+pkg upgrade
+pkg install gnupg pass git openssh
+```
+
+Let Termux reach your Download folder, and tap **Allow** when Android asks:
+
+```bash
+termux-setup-storage
+```
+
+Now it's the same as in part one: [tell git who you are](../your-own-password-store-part-1/#install-the-tools), [create your key](../your-own-password-store-part-1/#create-your-key) and [your store](../your-own-password-store-part-1/#create-the-store), [make an SSH key](#pick-a-home-for-your-store), and [send it all to the server](#send-your-store-to-the-server). A couple of notes:
+
+- GPG asks for the passphrase in a text box inside the terminal. Type it, move to the Repeat field with the Tab key (it's on the extra row above the keyboard), type it again, press Tab to reach **OK** and then Enter.
+- To copy your public SSH key on the provider's website, run `cat ~/.ssh/id_ed25519.pub`, long-press the text in Termux and select it.
+
+Then export your key where the app can find it:
+
+```bash
+gpg --armor --export-secret-keys you@example.org > ~/storage/downloads/private-key.asc
+```
+
+{{< callout type="warning" title="Your phone is now your only copy" >}}
+With this route, your key lives only on your phone. If the phone dies or gets stolen you lose every password, even though the encrypted files are safe on the server. Before you put real passwords in the store, copy `private-key.asc` somewhere safe: a USB stick through an OTG adapter works. Don't send it through email or a cloud drive.
+{{< /callout >}}
+
+## Up next
+
+You made it, now your store is safe on a server, and that was the boring part. In [part three](../your-own-password-store-part-3/) we'll install HardenedPass, connect it to your store and see how to use it every day.
+
+cheers 👋
diff --git a/content/en/articles/your-own-password-store-part-3/entry.png b/content/en/articles/your-own-password-store-part-3/entry.png
new file mode 100644
index 0000000..ad84bac
--- /dev/null
+++ b/content/en/articles/your-own-password-store-part-3/entry.png
Binary files differ
diff --git a/content/en/articles/your-own-password-store-part-3/generator.png b/content/en/articles/your-own-password-store-part-3/generator.png
new file mode 100644
index 0000000..015ad0d
--- /dev/null
+++ b/content/en/articles/your-own-password-store-part-3/generator.png
Binary files differ
diff --git a/content/en/articles/your-own-password-store-part-3/index.md b/content/en/articles/your-own-password-store-part-3/index.md
new file mode 100644
index 0000000..642a4c7
--- /dev/null
+++ b/content/en/articles/your-own-password-store-part-3/index.md
@@ -0,0 +1,133 @@
++++
+title = "Your own password store #3"
+author = "Danilo M."
+type = "tech"
+date = "2026-11-06T10:03:00+01:00"
+draft = true
+description = "Install HardenedPass, connect it to your store and use your passwords every day on your phone."
+excerpt = "Install HardenedPass, connect it to your store and use your passwords every day on your phone."
+image = "/uppies/2026/11/hardenedpass-banner.png"
+tags = ["pass", "gnupg", "git", "android", "hardenedpass", "security", "tutorial"]
+categories = ["Code", "DIY"]
++++
+
+## Use it daily
+
+This is the part where it all pays off. In [part one](../your-own-password-store-part-1/) we created a key and a password store, and in [part two](../your-own-password-store-part-2/) we sent it to a server. Today we'll put it on your phone, and then we'll see how to live with it day by day. You'll need the address of your repository and the `private-key.asc` file you exported.
+
+<!--more-->
+
+## Install HardenedPass
+
+Go to the [latest release](https://github.com/danixland/HardenedPass/releases/latest) and download `HardenedPass_vX.Y.Z.apk` and `HardenedPass_vX.Y.Z.apk.sha256`. You need Android 12 or newer, and no Google services at all, it runs perfectly on GrapheneOS.
+
+A password manager is a really bad thing to install from a tampered file, so check the download. In the folder with the two files, on your computer or in Termux, run:
+
+```bash
+sha256sum -c HardenedPass_vX.Y.Z.apk.sha256
+```
+
+It must say `OK`. The [install page]({{< relref "/hardenedpass/getting-started/install" >}}) also explains how to verify who signed the APK, which is the stronger check. Copy the APK on the phone if it isn't already there, open it from your file manager and allow the install.
+
+## Connect the app
+
+Open the app and tap **Clone Remote Repo**.
+
+{{< image src="welcome.png" alt="Welcome screen with the buttons Clone Remote Repo, Create Local Repo and Settings." class="max-w-sm mx-auto rounded-lg border border-border" />}}
+
+{{< callout type="note" title="Don't use Create Local Repo for now" >}}
+Create Local Repo is fine for a store living only on your phone, but right now a store made this way can't pull changes if you add a server to it later. Since you already have a repository, you don't need it.
+{{< /callout >}}
+
+Paste your repository's address in **Repository URL**. **SSH key** is already selected, and it's what we want.
+
+{{< image src="repository.png" alt="Repository information screen with the address filled in and SSH key selected." class="max-w-sm mx-auto rounded-lg border border-border" />}}
+
+Your phone needs its own SSH key. Tap **Manage**, then **Generate SSH key pair**.
+
+{{< image src="ssh-key.png" alt="SSH key screen with the buttons Import SSH key and Generate SSH key pair." class="max-w-sm mx-auto rounded-lg border border-border" />}}
+
+Choose **Ed25519**, leave **Protect with screen lock credential** on and tap **Generate**. Now the app will ask for your fingerprint or PIN every time it uses this key, and the private half never leaves the phone.
+
+{{< image src="ssh-generate.png" alt="Generate SSH key pair screen with Ed25519 selected and the screen lock protection turned on." class="max-w-sm mx-auto rounded-lg border border-border" />}}
+
+The app shows you the public key. Tap **Share** to send it to yourself, then add it on your provider's website, in the same place where you [added the first one](../your-own-password-store-part-2/#pick-a-home-for-your-store). A separate key for each device means that if you lose the phone, you can remove that key alone.
+
+{{< image src="ssh-public.png" alt="Dialog showing the generated public key, with the buttons Later and Share." class="max-w-sm mx-auto rounded-lg border border-border" />}}
+
+Go back to the repository screen and tap **Clone**. The first time you connect, the app remembers the server's identity, and from then on it refuses to connect if that changes.
+
+Once the clone is done, the app tells you which key the store is encrypted for. Copy `private-key.asc` on the phone over USB, unless it's already in your Download folder, tap **Import PGP key** and pick the file.
+
+{{< image src="pgp-import.png" alt="Import PGP key screen listing the store's recipient you@example.org, with an Import PGP key button." class="max-w-sm mx-auto rounded-lg border border-border" />}}
+
+And there's your store!
+
+{{< image src="store-list.png" alt="The store list, showing the entry example.org." class="max-w-sm mx-auto rounded-lg border border-border" />}}
+
+{{< callout type="warning" title="Delete the key file" >}}
+The app keeps its own copy, so delete `private-key.asc` from the phone's storage right now, and from your computer's disk too. The only other copy should be your offline backup.
+{{< /callout >}}
+
+Tap your entry. The app asks for the passphrase of your GPG key (the box just says *Password*), and shows you what's inside.
+
+{{< image src="passphrase.png" alt="Dialog asking for the password, with the keyboard open." class="max-w-sm mx-auto rounded-lg border border-border" />}}
+
+{{< image src="entry.png" alt="Entry example.org, showing password, username and url with buttons to copy each one." class="max-w-sm mx-auto rounded-lg border border-border" />}}
+
+If you got here, it works, and the hard part is over. You did it!
+
+## Daily use
+
+### Adding a password
+
+Tap **New entry**, then **Create new password**. Give it a name, usually the site's address, so that autofill can find it later. A folder helps too, if you like to keep things tidy.
+
+{{< image src="new-entry.png" alt="New entry editor with name, folder, password, username and extra content fields." class="max-w-sm mx-auto rounded-lg border border-border" />}}
+
+Tap the three dots in the password field to open the generator. **Random** makes character passwords and **Diceware** makes word passwords. For most logins go with Random: you'll never type them anyway, the app does it for you. Diceware is better for the few you must type by hand, like the password of your TV's streaming account.
+
+{{< image src="generator.png" alt="Password generator sheet on the Diceware tab, with a five word password, length and separator." class="max-w-sm mx-auto rounded-lg border border-border" />}}
+
+Tap **Use**, then **Save**. There's more on [entries in the docs]({{< relref "/hardenedpass/using/entries" >}}), including [one-time codes]({{< relref "/hardenedpass/using/otp" >}}) if you want to keep your 2FA in the store.
+
+### Syncing
+
+This is the one thing to get used to: saving an entry on the phone doesn't send it anywhere. It stays on your phone until you sync. Pull down on the list, or use the menu in the search bar and tap **Synchronize repository**.
+
+{{< image src="menu.png" alt="The list's menu with Synchronize repository, Pull from remote, Push to remote, Settings and About." class="max-w-sm mx-auto rounded-lg border border-border" />}}
+
+If you don't want to think about it, turn on **Push after each change** in **Settings**, **Repository**. On the computer the same thing takes two commands:
+
+```bash
+pass git pull
+pass git push
+```
+
+Sync often, and always before you edit something on another device: two devices changing the same entry is the one situation where git needs your help. The [sync page]({{< relref "/hardenedpass/using/sync" >}}) explains how to get out of that.
+
+### Autofill
+
+Copy and paste works, but filling your logins directly is much nicer. Open **Settings**, **Autofill**, turn on **Enable Autofill** and choose HardenedPass in the system dialog. It only trusts browsers it knows, and Firefox has the best support. The [autofill page]({{< relref "/hardenedpass/using/autofill" >}}) has the whole list.
+
+## When things go wrong
+
+**You lost your phone.** Your entries are encrypted and the key inside the app is protected by your passphrase, so don't panic. Go on your provider's website and remove the phone's SSH key, so it can't reach the repository anymore, then set up the app on the new phone from your backup. If you think somebody may have your passphrase too, read the next one.
+
+**You think your private key was stolen.** Assume your passwords will be read: create a new key, re-encrypt the store with `pass init new@example.org`, and change the passwords that matter, starting from your email. Moving to a new key doesn't help with old copies of the files, because git history keeps them.
+
+**You forgot your passphrase.** I'm sorry, but this is the end of the road. Nobody can help you, and that's the whole point of encryption. This is why it's on paper, in a drawer, while you learn it.
+
+**You lost your key, and you have no backup.** Same as above. Back up your key.
+
+**Something else broke.** Have a look at the [troubleshooting page]({{< relref "/hardenedpass/reference/troubleshooting" >}}), and if it's a bug, [let me know](https://github.com/danixland/HardenedPass/issues).
+
+## What's next
+
+You now have a password manager which you fully control, that doesn't depend on any company, and that works with any tool that speaks `pass`. If tomorrow I stop working on HardenedPass, your passwords are still right there, and that's the whole reason I like this setup.
+
+There's still more you can do to make this safer: two-factor authentication on your git account, keys limited to a single repository, hiding your entry names, hardware keys. That's a topic of its own and I'll cover it in a future post, for now enjoy your new password store.
+
+The [complete documentation](https://danix.xyz/hardenedpass/) has all the details about everything we've seen here, and if you get stuck somewhere, let me know.
+
+I'll see you on the next one 👋
diff --git a/content/en/articles/your-own-password-store-part-3/menu.png b/content/en/articles/your-own-password-store-part-3/menu.png
new file mode 100644
index 0000000..53fab2e
--- /dev/null
+++ b/content/en/articles/your-own-password-store-part-3/menu.png
Binary files differ
diff --git a/content/en/articles/your-own-password-store-part-3/new-entry.png b/content/en/articles/your-own-password-store-part-3/new-entry.png
new file mode 100644
index 0000000..cc47d1d
--- /dev/null
+++ b/content/en/articles/your-own-password-store-part-3/new-entry.png
Binary files differ
diff --git a/content/en/articles/your-own-password-store-part-3/passphrase.png b/content/en/articles/your-own-password-store-part-3/passphrase.png
new file mode 100644
index 0000000..48a80bc
--- /dev/null
+++ b/content/en/articles/your-own-password-store-part-3/passphrase.png
Binary files differ
diff --git a/content/en/articles/your-own-password-store-part-3/pgp-import.png b/content/en/articles/your-own-password-store-part-3/pgp-import.png
new file mode 100644
index 0000000..0546df3
--- /dev/null
+++ b/content/en/articles/your-own-password-store-part-3/pgp-import.png
Binary files differ
diff --git a/content/en/articles/your-own-password-store-part-3/repository.png b/content/en/articles/your-own-password-store-part-3/repository.png
new file mode 100644
index 0000000..67173fe
--- /dev/null
+++ b/content/en/articles/your-own-password-store-part-3/repository.png
Binary files differ
diff --git a/content/en/articles/your-own-password-store-part-3/ssh-generate.png b/content/en/articles/your-own-password-store-part-3/ssh-generate.png
new file mode 100644
index 0000000..5ff7d8b
--- /dev/null
+++ b/content/en/articles/your-own-password-store-part-3/ssh-generate.png
Binary files differ
diff --git a/content/en/articles/your-own-password-store-part-3/ssh-key.png b/content/en/articles/your-own-password-store-part-3/ssh-key.png
new file mode 100644
index 0000000..b454f1a
--- /dev/null
+++ b/content/en/articles/your-own-password-store-part-3/ssh-key.png
Binary files differ
diff --git a/content/en/articles/your-own-password-store-part-3/ssh-public.png b/content/en/articles/your-own-password-store-part-3/ssh-public.png
new file mode 100644
index 0000000..8ff56ad
--- /dev/null
+++ b/content/en/articles/your-own-password-store-part-3/ssh-public.png
Binary files differ
diff --git a/content/en/articles/your-own-password-store-part-3/store-list.png b/content/en/articles/your-own-password-store-part-3/store-list.png
new file mode 100644
index 0000000..38e71bc
--- /dev/null
+++ b/content/en/articles/your-own-password-store-part-3/store-list.png
Binary files differ
diff --git a/content/en/articles/your-own-password-store-part-3/welcome.png b/content/en/articles/your-own-password-store-part-3/welcome.png
new file mode 100644
index 0000000..de5a82d
--- /dev/null
+++ b/content/en/articles/your-own-password-store-part-3/welcome.png
Binary files differ