Restore Coolify storage safely after an incident.
Preview the change first. Apply it only with explicit confirmation.
coolrestore restores gzip-compressed tar archives created from Coolify storage and stored in S3-compatible storage such as RustFS. It supports local archive files and S3 objects, merge restores, replace restores, isolated staging, and atomic replace rollback.
The archive is validated and staged before anything is written to the target. By default, coolrestore only produces a plan.
Download the release binary for the target server:
coolrestore-linux-amd64
coolrestore-linux-arm64
Install it as coolrestore somewhere on the server's PATH:
install -m 0755 coolrestore-linux-amd64 /usr/local/bin/coolrestoreVerify the binary:
file /usr/local/bin/coolrestoreRelease binaries are statically built for Linux and macOS on amd64 and
arm64; Windows archives are also published.
Install the published cask from the Replworks tap:
brew tap replworks/tap
brew install --cask coolrestoreUpgrade it later with:
brew upgrade --cask coolrestoreThe cask provides prebuilt binaries for macOS and Linux on amd64 and
arm64. Homebrew downloads the binaries from the published GitHub Release.
The current macOS binary is not signed or notarized by Apple, so the cask uses
a macOS-only post-install hook to remove the download quarantine attribute.
This is a distribution workaround, not a replacement for code signing and
notarization; future releases should move to Apple Developer ID signing and
notarization and then remove the hook.
For development or local builds:
go install github.com/replworks/coolrestore/cmd/coolrestore@latestVerify the installed binary version:
coolrestore --versionShow the available commands and restore options:
coolrestore help
# or
coolrestore --helpS3-compatible access uses the AWS SDK environment variables:
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
export AWS_REGION=...
export AWS_ENDPOINT_URL=https://rustfs.example.com
export AWS_S3_FORCE_PATH_STYLE=trueIf these variables are not set, the AWS SDK default credential chain is used. Credentials are never accepted as command-line flags.
For package installations, an explicit environment file can be selected without depending on the install path:
cat > ./coolrestore.env <<'EOF'
AWS_ACCESS_KEY_ID=replace-me
AWS_SECRET_ACCESS_KEY=replace-me
AWS_REGION=us-east-1
AWS_ENDPOINT_URL=https://s3-compatible.example.com
AWS_S3_FORCE_PATH_STYLE=true
EOF
chmod 600 ./coolrestore.envUse it explicitly when running a restore:
coolrestore \
--env-file ./coolrestore.env \
--source 's3://bucket/object-key.tar.gz' \
--target /tmp/coolrestore-testThe file uses simple KEY=VALUE entries. Blank lines and full-line comments
are allowed; shell commands and export statements are not evaluated.
./coolrestore.env is never auto-discovered.
For repeated restores, keep coolrestore.env protected and pass it explicitly:
install -m 600 ./coolrestore.env /etc/coolrestore/env
coolrestore \
--env-file /etc/coolrestore/env \
--source 's3://bucket/object-key.tar.gz' \
--target /tmp/coolrestore-testFor a user-specific setup, use ~/.config/coolrestore/env and pass that path
with --env-file.
Diagnose an S3 source before restoring. This is read-only: it checks the environment configuration, credentials, endpoint, and object metadata without downloading the archive body or requiring a target directory:
coolrestore diagnose \
--env-file ./coolrestore.env \
--source 's3://coolify-bucket/data/coolify/backups/volumes/replworks-team-0/wjpmbrff7txw1hqtwu4jb4xb/directory-datawifinotestorage-1790266116.tar.gz'For a local archive, diagnosis checks that the path exists and is readable:
coolrestore diagnose \
--source /backups/coolify-storage.tar.gzPreview a local archive. Preview is the default and does not modify the target directory:
coolrestore \
--source /backups/coolify-storage.tar.gz \
--target /var/lib/coolify/storageUse an S3-compatible object as the source:
coolrestore \
--env-file ./coolrestore.env \
--source s3://coolify-backups/storage/2026-09-26.tar.gz \
--target /var/lib/coolify/storageApply a merge restore explicitly:
coolrestore \
--source s3://coolify-backups/storage/2026-09-26.tar.gz \
--target /var/lib/coolify/storage \
--mode merge \
--confirmReplace the target with the archive contents:
coolrestore \
--source s3://coolify-backups/storage/2026-09-26.tar.gz \
--target /var/lib/coolify/storage \
--mode replace \
--confirmUse a specific staging base when required:
coolrestore \
--source /backups/coolify-storage.tar.gz \
--target /var/lib/coolify/storage \
--staging /var/lib/coolify/restore-stagingOptional integrity override:
coolrestore \
--source /backups/coolify-storage.tar.gz \
--target /var/lib/coolify/storage \
--skip-checksum--mode replace requires --confirm. The target must be an absolute path and must not be a protected system directory or a final symbolic link.
Merge mode adds files that are missing from the target and overwrites files with the same path. Files that exist only in the target are preserved.
Replace mode makes the target contain exactly the archive's staged contents. The target and staging location must be on the same filesystem so the change can use atomic directory renames and rollback.
source: s3://coolify-backups/storage/2026-09-26.tar.gz
target: /var/lib/coolify/storage
mode: merge
outcome: planned
regular_files: 2
added:
uploads/avatar.png
overwritten:
config/app.php
source: s3://coolify-backups/storage/2026-09-26.tar.gz
target: /var/lib/coolify/storage
mode: merge
outcome: restored
regular_files: 2
source: s3://coolify-backups/storage/2026-09-26.tar.gz
target: /var/lib/coolify/storage
mode: merge
outcome: failed
step: change application
target_state: may contain partial changes
The process exits with 0 for a successful preview or restore and a non-zero status for failures.
coolrestore is designed for infrastructure recovery, not application-level validation.
- Archive paths are checked for traversal and absolute paths.
- Symlinks, hard links, and unsupported archive entry types are rejected.
- Archive contents are extracted into an isolated staging directory first.
- Staging and target paths may not overlap.
- A target lock prevents concurrent restores against the same directory.
- Merge failures clean temporary artifacts but may retain changes already applied.
- Replace failures restore the previous target directory through atomic rename rollback.
The backup archive produced by Coolify is treated as an input object. This tool does not create or require a SHA256 manifest for that archive. SHA256 files attached to GitHub Releases, when present, verify the downloaded coolrestore binary itself.
Verify:
AWS_ACCESS_KEY_IDandAWS_SECRET_ACCESS_KEYAWS_REGIONAWS_ENDPOINT_URLfor RustFS or another S3-compatible serviceAWS_S3_FORCE_PATH_STYLE=truewhen required by the endpoint- bucket and object-key permissions
If credentials cannot be loaded, coolrestore prints a short --env-file hint. It never prints credential values. Use a protected file such as /etc/coolrestore/env and pass it explicitly with --env-file.
Replace mode requires explicit authorization:
--mode replace --confirmIt also requires staging and target to be on the same filesystem.
This is expected. Omit --confirm to inspect a plan without changing the target. A missing target directory is not created during preview.
Check the failure report for the archive entry and reason. Unsafe archives are rejected before any content is applied to the target.
Run tests:
go test ./...Run static checks:
go vet ./...
git diff --checkBuild the local binary:
go build ./cmd/coolrestoreBuild release targets:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o coolrestore-linux-amd64 ./cmd/coolrestore
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o coolrestore-linux-arm64 ./cmd/coolrestoreSee the repository license before distributing the tool.
Built for safe Coolify storage recovery after an incident.