Skip to main content

GPG Encryption for Server Files and Backup Archives

Security · 29.09.2026

Why encrypt files and server backups with GPG?

Encrypting files and backups protects data if the storage medium or transfer channel is compromised: a VDS disk gets stolen, a backup archive is copied from a third-party S3 bucket, or traffic is intercepted while uploading to a remote server. GPG (GnuPG, an OpenPGP implementation) encrypts files without a key server or database — a gpg binary and a key file are enough. On ZevsHost.net VDS/VPS instances and dedicated servers in Germany, the USA, and France, encrypting backups with GPG is mandatory whenever an archive leaves the server: to external S3, to an off-site backup FTP, or to another data center.

GPG supports two modes: symmetric encryption with a single password (gpg -c) for one-off file protection, and asymmetric encryption with a key pair — public and private — for automated backups without human involvement. Both schemes are covered below.

How to quickly encrypt a file symmetrically: gpg -c and passphrase?

Symmetric encryption fits a one-off task: sending a single archive to a colleague, mailing a config with secrets, or encrypting a database snapshot before copying it to a USB drive.

gpg -c --cipher-algo AES256 backup.sql
# asks for the passphrase twice, creates backup.sql.gpg
gpg -o backup.sql -d backup.sql.gpg
# asks for the passphrase to decrypt

The --cipher-algo AES256 flag pins the algorithm explicitly: without it, older GPG builds fall back to CAST5, which is weaker than AES256. The password is entered interactively here, so a cron script needs a password file with 600 permissions instead, or any local user could read it — see the article on Linux file permissions for details.

How to generate a GPG key pair and encrypt a backup asymmetrically?

The asymmetric scheme is for automated backups: the script encrypts the archive with the public key, and only whoever holds the private key and its password can decrypt it. The private key does not need to live on the production server at all — the public key is enough there.

gpg --full-generate-key
# choose RSA and RSA, key size 4096
gpg --list-keys
gpg --export -a "backup@zevshost-client.example" > pubkey.asc
gpg --import pubkey.asc

The key pair is stored by default in ~/.gnupg (for root — in /root/.gnupg). Encrypting a backup for the recipient's key:

gpg --encrypt --recipient "backup@zevshost-client.example" backup.tar.gz
# creates backup.tar.gz.gpg
gpg --output backup.tar.gz -d backup.tar.gz.gpg

The private key is the only way to get the data back, so it must be moved off the server: onto an offline medium or into a secure secrets store, as described in the article on storing secrets in Vault. If the private key is lost or its password is forgotten, decrypting the archives is physically impossible — GPG has no recovery service.

How to automate GPG in cron without typing a password?

A backup cron script cannot wait for an interactive password prompt, so there are working ways to automate it. For symmetric encryption — a password file plus the --batch flags:

umask 077
echo 'my-long-password' > /root/.backup_pass
chmod 600 /root/.backup_pass

gpg --batch --yes --passphrase-file /root/.backup_pass     -c --cipher-algo AES256 -o backup.tar.gz.gpg backup.tar.gz

For asymmetric encryption, no password is needed at archiving time: encrypting with a public key happens without a passphrase, and gpg-agent is only needed for private-key operations (decryption, signing).

MethodWhere the secret livesFits cronRisk if the server is compromised
gpg -c interactivelytyped in manuallynolow
--passphrase-file (600)a file on diskyesmedium
gpg-agent + cacheagent memoryyes, with caveatsmedium
public-key encryptionprivate key off the serveryeslow

A crontab -e line for root:

0 3 * * * tar czf - /var/www | gpg --encrypt --recipient "backup@zevshost-client.example"   -o /backups/site-$(date +\%F).tar.gz.gpg &&   find /backups -name '*.gpg' -mtime +14 -delete

How to verify backup integrity: signing and verify?

Encryption alone does not guarantee a file was not swapped or corrupted while being transferred to S3. For that, GPG can sign files separately from encrypting them:

gpg --detach-sign --armor backup.tar.gz.gpg
# creates backup.tar.gz.gpg.asc — the signature file

gpg --verify backup.tar.gz.gpg.asc backup.tar.gz.gpg
# gpg: Good signature from "..." — the file is intact
# gpg: BAD signature — the file was altered or corrupted

In an automated verification script it is convenient to combine encryption and signing in one --encrypt --sign command, and to run the check as a separate step before uploading to S3. On a BAD signature response, the upload should be stopped and alerted on, not overwritten onto the old backup with a new broken archive. The general approach to hardening the server that runs such a script is covered in the article on SSH hardening.

Checklist: common mistakes when working with GPG on a server

  • Losing the private key without a backup — decrypting old backups becomes impossible forever.
  • The password file for --passphrase-file has 644 permissions instead of 600 and is readable by any user on the server.
  • Encrypting without --cipher-algo AES256 on older GPG builds — a weaker default algorithm gets used instead.
  • The private key is stored on the same server that encrypts the backups — a server breach wipes out the whole protection.
  • No separate gpg --verify check after uploading to S3 — a corrupted archive is only discovered at restore time.

For comparison: filesystem-level encryption via LUKS protects the whole disk but does not protect a specific file once it leaves the server — see the article on LUKS disk encryption for that approach. GPG and LUKS cover different scenarios and are usually used together: LUKS for the entire server disk, GPG for specific files and backups that leave the server.

← Back to Knowledge Base Ask Support