$linuxjunkies
>

Encrypt Files with age and rage

Learn to encrypt and decrypt files with age and rage: generate keys, encrypt for multiple recipients, use SSH keys, and integrate with the passage password manager.

BeginnerUbuntuDebianFedoraArch9 min readUpdated June 7, 2026

Before you start

  • A terminal with sudo access
  • Cargo installed if building rage from source (rustup.rs)
  • Basic familiarity with the command line and file paths

age is a modern, simple file encryption tool designed as a replacement for GPG's most common use case: encrypt a file for yourself or a recipient. It has a tiny attack surface, a clean key format, and predictable behaviour. rage is a Rust implementation of the same spec — compatible, fast, and available in most package managers. Both tools share identical command syntax, so everything here works for either.

Install age and rage

Debian / Ubuntu

sudo apt update && sudo apt install age

rage is not yet in the Ubuntu/Debian main repos on older LTS releases. Install it from a pre-built binary or via Cargo:

cargo install rage

Fedora / RHEL 9+ / Rocky 9+

sudo dnf install age

For rage on Fedora:

sudo dnf install rage-encryption

Arch Linux

sudo pacman -S age rage

Verify installation

age --version
rage --version

You should see a version string such as age v1.2.0. Either binary will do for everything below; substitute rage for age if that is what you installed.

Generate a Key Pair

age uses X25519 key pairs. The private key file holds both the private and public key. Keep the private key file safe — it is not passphrase-protected by default, so treat it like an SSH private key.

mkdir -p ~/.config/age
age-keygen -o ~/.config/age/identity.txt

Output looks like:

# Public key: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p

The file identity.txt contains a comment line with your public key and the secret key itself. Copy the public key string — it starts with age1 — for sharing with senders.

Protect the private key file

chmod 600 ~/.config/age/identity.txt

Optional: passphrase-protected identity

If you want the private key encrypted at rest, encrypt the identity file itself with a passphrase using age's -p flag and store the result instead:

age -p -o ~/.config/age/identity.txt.age ~/.config/age/identity.txt
rm ~/.config/age/identity.txt

You will be prompted for the passphrase on every decrypt. This is the right trade-off for keys stored on a shared or portable machine.

Encrypt a File

Encrypt for yourself (using your public key)

age -r age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p \
    -o secret.txt.age secret.txt

Replace the age1… string with your actual public key from the previous step.

Encrypt with a passphrase instead of a key

Useful for sharing over email or with someone who does not have an age key yet:

age -p -o secret.txt.age secret.txt

Encrypt for multiple recipients

Pass -r once per recipient. The file can be decrypted by any of them independently:

age \
  -r age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p \
  -r age1lggyhqr0e7j2a5uu8ltztm8g9e2pxq5m6pj2x6vq3z9u2krhqrqd8vpx2 \
  -o report.pdf.age report.pdf

Encrypt a directory (via tar)

age encrypts a single stream. Pipe tar into age to handle multiple files:

tar -czf - ~/Documents/project | \
  age -r age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p \
  -o project.tar.gz.age

Decrypt a File

With your identity file

age -d -i ~/.config/age/identity.txt -o secret.txt secret.txt.age

With a passphrase-encrypted identity

age -d -i ~/.config/age/identity.txt.age -o secret.txt secret.txt.age

age will prompt for the identity file passphrase first, then decrypt the payload.

Decrypt a tar archive

age -d -i ~/.config/age/identity.txt project.tar.gz.age | tar -xzf -

Working with Recipients Files

Typing public keys on the command line every time is error-prone. Use a recipients file — one public key per line, comments allowed with #:

cat ~/.config/age/recipients.txt
# Alice
age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
# Bob
age1lggyhqr0e7j2a5uu8ltztm8g9e2pxq5m6pj2x6vq3z9u2krhqrqd8vpx2
age -R ~/.config/age/recipients.txt -o report.pdf.age report.pdf

The -R flag (capital R) reads recipients from a file. This is equivalent to passing each key with its own -r flag.

Use an SSH Key as an age Identity

age supports Ed25519 and RSA SSH public keys as recipients. This is handy when the person you are encrypting for already has an SSH key on GitHub:

curl https://github.com/username.keys | \
  age -R - -o secret.txt.age secret.txt

Decryption uses the corresponding SSH private key:

age -d -i ~/.ssh/id_ed25519 -o secret.txt secret.txt.age

Note: RSA SSH keys work but Ed25519 is preferred. Do not rely on this feature for long-term archival without understanding the SSH key lifecycle.

Integrate age with pass

pass uses GPG by default, but the passage fork or the pass-age extension wraps age instead. The most practical approach without switching to a fork is passage:

Install passage

# Arch
sudo pacman -S passage

# Others: install from source
git clone https://github.com/FiloSottile/passage ~/.local/src/passage
cd ~/.local/src/passage
sudo make install

Initialise a passage store

passage init age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p

This creates ~/.passage/store and writes a .age-recipients file containing your public key. Your identity file at ~/.passage/identities must exist — symlink or copy it:

ln -s ~/.config/age/identity.txt ~/.passage/identities

Use passage like pass

# Insert a password
passage insert email/personal

# Retrieve it
passage email/personal

# Copy to clipboard (requires xclip or wl-clipboard)
passage -c email/personal

On Wayland, install wl-clipboard instead of xclip; passage will use wl-copy automatically when WAYLAND_DISPLAY is set.

Verify Encryption and Spot-Check Decryption

# Confirm the file is opaque binary (not plaintext)
file secret.txt.age
# Expected: secret.txt.age: data

# Confirm decryption round-trips correctly
age -d -i ~/.config/age/identity.txt secret.txt.age | diff - secret.txt && echo "OK"

A clean OK confirms the ciphertext decrypts to exactly the original file.

Troubleshooting

"no identity matched any of the file's recipients"

The identity file you passed with -i does not match the key used during encryption. Double-check you are using the correct identity file. If you have multiple keys, try each. The error is intentionally vague for security reasons.

Permission denied on identity.txt

age refuses to use a private key file readable by others. Fix it:

chmod 600 ~/.config/age/identity.txt

rage: command not found after cargo install

Cargo installs binaries to ~/.cargo/bin. Add it to your PATH:

echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

passage init fails with "no identities file"

passage looks for ~/.passage/identities. Create or symlink the file as shown above, then re-run passage init.

tested on:Ubuntu 24.04Fedora 40Arch rollingDebian 12

Frequently asked questions

What is the difference between age and rage?
rage is a Rust implementation of the same age encryption spec. Both produce and consume identical .age files; the choice is mainly about installation preference or performance on large files.
Can someone without an age key decrypt a file I encrypted with -p?
Yes. A passphrase-encrypted file only requires the correct passphrase, not an age key pair. Share the passphrase through a separate secure channel.
Is it safe to store the private key in ~/.config/age/identity.txt unencrypted?
Only if the machine has full-disk encryption and you are the sole user. For shared or portable machines, encrypt the identity file with a passphrase as described in the guide.
How does age compare to GPG for file encryption?
age is simpler: no key server, no web of trust, no complex configuration, and a much smaller codebase. It does not support signatures; use Minisign or SSH signing for that.
Can I use age to encrypt files for a team where members change over time?
Yes. Keep a recipients file and add or remove public keys as the team changes. Re-encrypting existing files for the new recipient set requires decrypting and re-encrypting each file.

Related guides