Encryption
Tar, encrypt, upload: using GPG to secure files before they hit the cloud
A no-nonsense tutorial on using GnuPG to encrypt files before they leave your machine. Works with any cloud provider, requires no new service, and keeps you in control of the keys. Plus when this is the right tool and when it isn't.
On this page
- Install GPG
- Choose: symmetric or public-key?
- The core workflow: tar, encrypt, upload
- Step 1: tar the directory
- Step 2: encrypt
- Step 3: verify and clean up
- Step 4: upload
- Step 5: decrypt (later, or on another machine)
- Scripting it for routine use
- The public-key variant
- Generate a key pair (once per person)
- Share your public key
- Import the recipient’s public key
- Encrypt for the recipient
- Decrypt (on the recipient’s side)
- When this is the right tool
- When it’s not the right tool
- A few gotchas worth knowing
GPG (GnuPG, the open implementation of the OpenPGP standard) is not the first tool a new user should reach for. It is command-line, it has a reputation for bad ergonomics, and for most consumer use cases a purpose-built tool like Cryptomator is a better fit.
But GPG is still the right tool for a specific, important job: taking a directory of files, turning it into a single encrypted archive, and uploading that archive to any cloud provider (or sending it through any transport) without the provider being able to read the contents. If you want client-side encryption that doesn’t depend on a specific vendor’s software and will still work in ten years, GPG is the correct answer.
This article walks through the workflow end to end.
Install GPG
macOS:
brew install gnupg
Windows (PowerShell):
winget install --id GnuPG.Gpg4win -e
Gpg4win installs GPG plus a GUI (Kleopatra) and integrations with
Windows Explorer. The command-line gpg is available in a new
terminal after install.
Linux:
sudo apt install gnupg # Debian/Ubuntu
sudo dnf install gnupg2 # Fedora
Verify:
gpg --version
You want version 2.2 or newer. Older 1.x versions are end-of-life.
Choose: symmetric or public-key?
GPG can encrypt in two fundamentally different ways, and most tutorials blur the distinction. Pick on purpose:
- Symmetric encryption — one passphrase encrypts and decrypts. Great for encrypting files for yourself (archival, cloud backup, offline storage). The only secret is the passphrase.
- Public-key encryption — you encrypt to someone using their public key; they decrypt with their private key. Great for sending files to other people. Requires key management on both sides.
For “encrypt before uploading to Dropbox”, you almost always want symmetric. You are the sender and the recipient. A passphrase is simpler and has fewer ways to go wrong.
For “send a file to my lawyer who also uses GPG”, you want public-key. Harder to set up; the right tool for the job.
The rest of this guide covers symmetric first, then covers public-key at the end.
The core workflow: tar, encrypt, upload
Step 1: tar the directory
tar (tape archive) bundles a directory into a single file. Most
backup and transport tools work better with one file than with a
thousand.
cd /path/to/parent
tar -cf ~/sensitive-docs.tar ./sensitive-docs
Flags used:
-ccreate an archive-fspecifies the archive filename
For smaller output, add compression. gzip is universal, zstd is
faster and smaller if both ends have modern tar:
tar -czf ~/sensitive-docs.tar.gz ./sensitive-docs # gzip
tar --zstd -cf ~/sensitive-docs.tar.zst ./sensitive-docs # zstd
Compression is applied before encryption, which is correct — ciphertext is incompressible, so compressing the plaintext is the only useful order.
Step 2: encrypt
gpg --symmetric \
--cipher-algo AES256 \
--s2k-mode 3 \
--s2k-digest-algo SHA512 \
--s2k-count 65011712 \
--output ~/sensitive-docs.tar.gz.gpg \
~/sensitive-docs.tar.gz
What each flag does:
--symmetric— passphrase-based encryption (as opposed to public-key).--cipher-algo AES256— AES with a 256-bit key. Default varies by GPG version; making it explicit is good hygiene.--s2k-mode 3— iterated+salted passphrase-to-key derivation (S2K). Protects against brute-force of the passphrase.--s2k-digest-algo SHA512— stronger hash than the default.--s2k-count 65011712— high iteration count; slows brute-force attempts on the passphrase. (65011712 is the maximum; slower to unlock but much harder to attack.)--output— the encrypted output file.
GPG will prompt for a passphrase. Use a strong one. A 5+ word Diceware-style passphrase or a 16+ character random string from your password manager. Anything weaker is the limiting factor in the whole setup.
Step 3: verify and clean up
Verify the encrypted file exists and the plaintext tarball can be removed:
ls -lh ~/sensitive-docs.tar.gz.gpg
gpg --list-packets ~/sensitive-docs.tar.gz.gpg | head
rm ~/sensitive-docs.tar.gz # plaintext tarball, no longer needed
The --list-packets output confirms the file is a GPG-encrypted
blob and shows which cipher was used. If it doesn’t say AES256, check
your flags.
Then delete the source plaintext if you want to — for archival scenarios, you usually keep the original working copy somewhere controlled and hand only the encrypted blob to the cloud.
Step 4: upload
# Any of these works — the encrypted file is opaque to all of them.
aws s3 cp ~/sensitive-docs.tar.gz.gpg s3://my-bucket/sensitive/
rclone copy ~/sensitive-docs.tar.gz.gpg remote:Dropbox/encrypted/
cp ~/sensitive-docs.tar.gz.gpg ~/Dropbox/ # Dropbox sync picks it up
The provider sees ciphertext. They don’t know what’s in it, they can’t search it, they can’t preview it.
Step 5: decrypt (later, or on another machine)
gpg --output ~/sensitive-docs.tar.gz --decrypt ~/sensitive-docs.tar.gz.gpg
tar -xzf ~/sensitive-docs.tar.gz
GPG prompts for the passphrase, writes the plaintext tarball, then
tar extracts. You now have the original directory back.
Scripting it for routine use
If you do this often, wrap it:
#!/usr/bin/env bash
# encrypt-upload.sh <source-dir> <s3-path>
set -euo pipefail
SRC="$1"
DEST="$2"
TMP="$(mktemp -d)"
NAME="$(basename "$SRC")-$(date +%Y%m%d-%H%M%S)"
echo "==> Taring $SRC..."
tar -czf "$TMP/$NAME.tar.gz" -C "$(dirname "$SRC")" "$(basename "$SRC")"
echo "==> Encrypting..."
gpg --symmetric \
--cipher-algo AES256 \
--s2k-mode 3 \
--s2k-digest-algo SHA512 \
--s2k-count 65011712 \
--output "$TMP/$NAME.tar.gz.gpg" \
"$TMP/$NAME.tar.gz"
echo "==> Uploading to $DEST..."
aws s3 cp "$TMP/$NAME.tar.gz.gpg" "$DEST/$NAME.tar.gz.gpg"
echo "==> Cleaning up..."
rm -rf "$TMP"
echo "==> Done: $DEST/$NAME.tar.gz.gpg"
Save as encrypt-upload.sh, make executable (chmod +x), and run:
./encrypt-upload.sh ~/Documents/Taxes s3://my-backups/taxes
Each invocation produces a dated archive. GPG will prompt for the passphrase on each run; for unattended use see the passphrase-in-file options in the GPG manual (but understand the tradeoff — a stored passphrase reduces the protection).
The public-key variant
For sending files to someone else, symmetric is wrong; you don’t want to send the passphrase through the same channel as the file. Public-key encryption solves this:
Generate a key pair (once per person)
gpg --full-generate-key
Choose:
- Key type:
ECC (sign and encrypt)(modern default — Curve 25519). AlternativelyRSA and RSAwith 4096-bit keys for maximum compatibility. - Expiration: pick something — “never” is a bad habit. 2–5 years is reasonable; you can extend later.
- Real name and email: identifies the key. The email doesn’t have to be your real one.
Share your public key
gpg --armor --export you@example.com > you.asc
Publish you.asc somewhere the recipient can fetch it — your
website, a keyserver, or just email it. Your private key never
leaves your machine.
Import the recipient’s public key
gpg --import lawyer.asc
gpg --list-keys
Verify the fingerprint by calling them or meeting in person. The fingerprint is a unique identifier of the public key:
gpg --fingerprint lawyer@example.com
Compare the printed fingerprint with the one they read out loud. This one-time verification is what prevents a man-in-the-middle from substituting their own key.
Encrypt for the recipient
gpg --encrypt --armor --recipient lawyer@example.com document.pdf
Produces document.pdf.asc (ASCII-armored) or document.pdf.gpg
(binary, without --armor). Either can be emailed, dropped in a
shared folder, or sent through any channel — only the recipient’s
private key can decrypt it.
Decrypt (on the recipient’s side)
gpg --decrypt document.pdf.asc > document.pdf
GPG uses their private key automatically if it’s in their keyring.
When this is the right tool
GPG is the right choice when you need:
- Long-term archival.
.tar.gz.gpgfiles written today will be readable in twenty years with standard tools. No vendor lock-in. - Provider independence. The encrypted blob is portable. Move between AWS, Backblaze, Dropbox, a friend’s NAS — the file doesn’t care.
- Scriptability. Automating encryption in backup pipelines, batch jobs, build systems.
- Send-to-a-specific-person. Public-key encryption is the cleanest model when the recipient is known and has a key.
When it’s not the right tool
Don’t use GPG when:
- You want a folder you can just edit files in. That is a Cryptomator use case, not a GPG one. GPG is for discrete encrypt and decrypt operations, not live working folders.
- You need to share with non-technical people. Getting a non-technical recipient to install GnuPG, generate a keypair, verify fingerprints, and use the command line is usually not feasible. For those situations, see Expiring links and sharing to non-technical people.
- You want ephemeral, forward-secret messaging. Use Signal.
- You need to collaborate on live documents. Use a platform with proper access control.
A few gotchas worth knowing
- GPG’s default cipher has changed over time. Old files
(pre-2017-ish) may use CAST5 or Blowfish. New files should be
AES-256. Being explicit with
--cipher-algo AES256avoids surprises. --armorproduces ASCII output (.ascfiles) that survives email transport. Without it, GPG produces binary output (.gpg) that is ~33% smaller but shouldn’t be pasted into plain text.- Keyring location. On most systems, GPG stores keys in
~/.gnupg/. Back that directory up. If you lose it, you lose every decrypted file ever encrypted with those keys. - Subkeys. A mature GPG setup uses a primary key kept offline (for certification) and subkeys on day-to-day devices (for signing and encryption). Complicated; worth reading about once you’re comfortable with the basics.
--trust-model alwaysis a shortcut people use to skip fingerprint verification. It is the shortcut that turns GPG into a less-safe version of itself. Don’t use it for anything sensitive.
GPG is not for everyone. For the cases where it fits, it is remarkable how much control it gives you for so little operational cost — and how durably. A file you encrypted with GPG in 2010 is a file you can decrypt in 2030 with no subscription, no vendor, no connection to the internet. That property is worth the command-line unfamiliarity for the documents that warrant it.