Installation
tagbackup ships as a single compiled binary for Linux, macOS, and Windows. Download the archive for your OS from GitHub Releases. The current version is v0.0.9.
| Platform | Asset name |
|---|---|
| Linux x86_64 | tagbackup_0.0.9_linux_amd64.tar.gz |
| Linux ARM64 | tagbackup_0.0.9_linux_arm64.tar.gz |
| macOS Intel | tagbackup_0.0.9_darwin_amd64.tar.gz |
| macOS Apple Silicon | tagbackup_0.0.9_darwin_arm64.tar.gz |
| Windows x86_64 | tagbackup_0.0.9_windows_amd64.zip |
| Windows ARM64 | tagbackup_0.0.9_windows_arm64.zip |
Linux
curl -sfL https://tagbackup.com/install.sh | sh
Or manually: download the archive, extract, and move the binary into your PATH:
ARCH=$(uname -m); case "${ARCH}" in x86_64|amd64) ARCH=amd64 ;; aarch64|arm64) ARCH=arm64 ;; esac
tar -xzf tagbackup_0.0.9_linux_${ARCH}.tar.gz
chmod +x tagbackup
sudo mv tagbackup /usr/local/bin/
macOS
curl -sfL https://tagbackup.com/install.sh | sh
Or manually:
ARCH=$(uname -m); case "${ARCH}" in x86_64|amd64) ARCH=amd64 ;; aarch64|arm64) ARCH=arm64 ;; esac
tar -xzf tagbackup_0.0.9_darwin_${ARCH}.tar.gz
chmod +x tagbackup
sudo mv tagbackup /usr/local/bin/
# If macOS quarantines the binary after a browser download:
xattr -d com.apple.quarantine /usr/local/bin/tagbackup
Windows
Extract the .zip, locate tagbackup.exe, and either run it from that folder or add the folder to your user PATH (Settings → System → About → Advanced system settings → Environment Variables → Path).
Verify checksum (optional)
Each release includes a tagbackup_0.0.9_checksums.txt. On Linux/macOS:
sha256sum -c --ignore-missing <(grep "tagbackup_0.0.9_linux_amd64.tar.gz" tagbackup_0.0.9_checksums.txt)
Quick start
After installing, add a bucket and start pushing files.
# 1. Add a bucket interactively
tagbackup bucket add
# 2. Push a file with tags
tagbackup push dump.sql --bucket=dbbackup --tag=nightly,prod
# 3. List files by tag
tagbackup files --bucket=dbbackup --tag=prod
# 4. Pull the latest matching file
tagbackup pull --bucket=dbbackup --tag=nightly+prod --latest
tagbackup --help or tagbackup <command> --help for the exact flag list for any command.Concepts
Tags
Tags are alphanumeric labels ([a-zA-Z0-9], minimum one character) you assign when pushing a file. They're stored directly in the S3 object key — no separate index, no database.
On push you supply a comma-separated list: --tag=nightly,prod,mydb. Tags are sorted before being written to the key, so a,b and b,a are identical.
Object keys
Keys follow the pattern <prefix><timestamp-ms>-<tags-csv>-<filename>. Example:
nightly/1776831788343-nightly,prod-dump.sql
tagbackup only considers objects matching this pattern — other keys in the bucket are silently ignored.
Bucket aliases
A bucket alias is a short name ([a-zA-Z0-9_]+) you choose that maps to a full S3 connection. You pass it with --bucket=ALIAS on every file command.
tagbackup bucket add
Adds a new bucket alias to your config. By default this is fully interactive — tagbackup will prompt you for each setting.
Prompted settings: alias, S3 bucket name, endpoint URL, region, optional prefix, path-style addressing, TLS options, and credential type (static, profile, or iam).
For unattended provisioning (Ansible, Terraform, Dockerfiles), pass everything as flags:
tagbackup bucket add \
--alias=dbbackup \
--bucket=my-company-db-backups \
--endpoint=https://s3.eu-west-1.amazonaws.com \
--region=eu-west-1 \
--credential-type=static \
--access-key-id=AKIAEXAMPLE \
--secret-access-key=wJalr...
After a successful save, bucket verify runs automatically. Pass --no-test to skip it.
tagbackup bucket verify
Checks connectivity and permissions against a bucket. Verifies list, write, read, and delete independently, using a small probe object that is cleaned up afterwards.
tagbackup bucket verify
# or target a specific alias:
tagbackup bucket verify --bucket=dbbackup
Example output:
Connecting to bucket ✓
Listing files in bucket ✓
Writing file to bucket ✓
Reading file from bucket ✓
Deleting file from bucket ✓
bucket list / edit / delete
| Command | What it does |
|---|---|
| bucket list | Print all configured aliases, one per line, sorted |
| bucket edit | Interactively pick and edit a bucket's settings (including alias). Prevents alias collisions. |
| bucket delete | Interactively remove a bucket alias from the local config. Does not touch the remote bucket. |
Config file
tagbackup stores all configuration in a single YAML file per user:
- Linux / macOS:
$XDG_CONFIG_HOME/tagbackup/config.yaml(falls back to~/.config/tagbackup/config.yaml) - Windows:
%AppData%\tagbackup\config.yaml
The file is created with mode 0600 on first write. Writes are atomic — a partial write never leaves a corrupt config.
version: 1
buckets:
dbbackup:
bucket: my-company-db-backups
endpoint: https://s3.eu-west-1.amazonaws.com
region: eu-west-1
prefix: nightly/
credential_type: static
access_key_id: AKIAEXAMPLE
secret_access_key: wJalrXUtnFEMI/K7MDENG/...
Credentials
For each invocation, credentials are resolved in this order. First match wins:
- Environment variables —
TAGBACKUP_BUCKET_<ALIAS>_ACCESS_KEY_IDandTAGBACKUP_BUCKET_<ALIAS>_SECRET_ACCESS_KEY(alias is uppercased) - AWS shared-credentials profile — when
credential_type: profileis set - Inline in config.yaml — when
credential_type: staticwith keys present - AWS SDK default chain — instance roles (EC2), task roles (ECS), IRSA (EKS), etc. Used when
credential_type: iam
tagbackup push
tagbackup push <path> --bucket=ALIAS --tag=TAG1,TAG2
Uploads one file. Tags are comma-separated; order doesn't matter (they're sorted before storage).
To push from stdin, use - as the path and supply --filename=NAME:
pg_dump mydb | tagbackup push - --bucket=db --tag=maindb --filename=dump.sql
Limits: original filename ≤ 255 bytes; full S3 key ≤ 1024 bytes.
tagbackup pull
tagbackup pull --bucket=ALIAS --tag=EXPRESSION [flags]
| Flag | Purpose |
|---|---|
| --latest | Download the single newest matching object. Without this flag, an interactive chooser is shown. |
| --output=PATH | Destination path. Omit to use the current directory. Pass - to write to stdout (progress goes to stderr). |
Pipe directly into a tool:
tagbackup pull --bucket=db --tag=maindb --latest --output=- | psql mydb
No match → exit code 5. In scripts always combine --latest with --non-interactive.
Without --latest, an interactive chooser lists matches (paged, 20 at a time) with column headers above the prompt:
TIMESTAMP SIZE FILENAME TAGS
? Choose a file
2026-06-13 22:34:01Z 1.2 MiB dump.sql [maindb]
> 2026-06-08 22:34:01Z 1.1 MiB dump.sql [maindb]
tagbackup files
tagbackup files --bucket=ALIAS --tag=EXPRESSION [--json]
Lists all objects matching the expression. Non-interactive. Without --json, output includes a header row and one line per match (newest first):
TIMESTAMP SIZE FILENAME TAGS
2026-06-13 22:34:01Z 1.2 MiB dump.sql [maindb]
2026-06-08 22:34:01Z 1.1 MiB dump.sql [maindb]
With --json, emits one JSON object per line to stdout — no header row — suitable for piping to jq:
tagbackup files --bucket=dbbackup --tag=prod --json | jq -r .key
JSON fields: key, tags (array), size (bytes), timestamp (epoch ms from the key).
tagbackup tags
tagbackup tags --bucket=ALIAS
Lists every tag that appears in at least one object in the bucket — with file count and the date range (oldest / newest) for each tag. Sorted alphabetically. Non-interactive.
TAG FILES OLDEST NEWEST
bpmapi 6 2026-06-08 22:34:01Z 2026-06-13 22:34:01Z
joncombeapi 8 2026-06-07 08:19:23Z 2026-06-13 22:33:01Z
tagbackup delete
tagbackup delete --bucket=ALIAS --tag=EXPRESSION [options]
| Flag | Purpose |
|---|---|
| --force | Delete all matches without confirmation |
| --dry-run | Show what would be deleted without deleting |
| --json | Machine-readable output (same shape as files --json) |
| --older-than=DUR | Only objects strictly older than DUR (e.g. 30d, 2w, 12h) |
| --newer-than=DUR | Only objects strictly newer than DUR. Mutually exclusive with --older-than. |
Typical retention pattern in a cron script:
tagbackup delete --bucket=dbbackup --tag=nightly+prod --older-than=30d --force
tagbackup serve
tagbackup serve [--port=PORT] [--no-open]
Starts a local web server and opens your browser. Use it when you want to browse, upload, download, or delete files visually rather than at the command line. The web UI is embedded in the binary — there is nothing extra to install. Stop the server with Ctrl+C.
- Browse all configured buckets (one tab per alias; no
--bucketflag) - Filter files by tag
- Upload files with tags (drag-and-drop or file picker)
- Download individual files (download button per row; saved under the original filename)
- Delete selected files
127.0.0.1 only — it is never exposed on your network. It uses your existing config.yaml and credentials. Bucket configuration is still managed via the CLI (tagbackup bucket add / edit) or by editing the config file directly.Each file row has a download button that saves that object under its original filename. There is no tag filter or "latest" picker — you download the specific file shown in the row. For tag-based or scripted downloads, use tagbackup pull instead.
| Flag | Purpose |
|---|---|
| --port=PORT | Port to listen on (default 3000) |
| --no-open | Print the URL without opening a browser |
tagbackup serve
tagbackup serve --port 8080
tagbackup serve --no-open
Global flags
| Flag | Short | Purpose |
|---|---|---|
| --config=PATH | Use a specific config file | |
| --verbose | -v | Enable debug output (credential path, SDK retries, skipped keys) |
| --quiet | -q | Suppress info messages; errors still print. Mutually exclusive with --verbose. |
| --non-interactive | Exit with a usage error instead of prompting. Required in scripts. | |
| --no-color | Disable colour output | |
| --version | Print version and exit | |
| --help | -h | Help for the current command |
Tag expressions
Used with pull, files, and delete for the --tag flag. No spaces allowed. Tag characters are [a-zA-Z0-9] only.
| Token | Meaning |
|---|---|
| a|b | OR — either tag |
| a+b | AND — must have all tags |
| -a | NOT — must not have this tag |
| ( … ) | Grouping — evaluated first |
Precedence (highest to lowest): () → - → + → |
Examples:
prod # files tagged prod
db+prod # files with both db and prod
a|b # files with a or b
(-scratch)+release # has release and does not have scratch
(-a+-b)|c # (not a and not b) or c
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Unexpected error (I/O error, push file not found, etc.) |
| 2 | Usage error — bad flags, malformed tag expression, missing required parameter |
| 3 | Config error — file missing, unreadable, or unknown bucket alias |
| 4 | S3 / network / auth error |
| 5 | No matching objects found |
| 130 / 143 | Process interrupted (SIGINT / SIGTERM) |
All errors are formatted as tagbackup: <command>: <message> on stderr, optionally followed by a Hint: line with remediation advice.