A lightweight CLI tool that provides comprehensive Terraform state file protection through automated backup, encryption, versioning, and restoration capabilities. Never lose your Terraform state again!
- Automated Backups: Automatic state backups before and after Terraform operations
- Multiple Storage Backends: Local filesystem and AWS S3 support
- Encryption: AES-256-GCM and AWS KMS encryption options
- Terraform Integration: Drop-in replacement for terraform commands
- Flexible Configuration: Project-level and global configuration support
- Cross-Platform: Single binary for Linux, macOS, and Windows
- Retention Policies: Configurable backup retention with automatic cleanup
- State Restoration: Easy restoration of any previous state version
brew install tf-safecurl -fsSL https://packages.tf-safe.dev/gpg | sudo apt-key add -
echo "deb https://packages.tf-safe.dev/apt stable main" | sudo tee /etc/apt/sources.list.d/tf-safe.list
sudo apt update && sudo apt install tf-safechoco install tf-safecurl -fsSL https://raw.githubusercontent.com/BIRhrt/tf-safe/main/scripts/install.sh | bashFor detailed installation instructions, see INSTALL.md.
-
Initialize tf-safe in your Terraform project:
cd /path/to/terraform/project tf-safe init -
Configure your storage backend (edit
.tf-safe.yaml):local: enabled: true retention_count: 10 remote: provider: s3 bucket: my-terraform-backups region: us-west-2 enabled: true encryption: provider: aes
-
Replace terraform commands with tf-safe:
# Instead of: terraform apply tf-safe apply # Instead of: terraform plan tf-safe plan # Instead of: terraform destroy tf-safe destroy
-
View and restore backups:
# List all backups tf-safe list # Restore a specific backup tf-safe restore 2024-01-15T10:30:00Z
Initialize tf-safe configuration in the current directory.
tf-safe init [flags]
Flags:
--global Create global configuration instead of project-level
--storage string Storage backend (local, s3) (default "local")
--encrypt Enable encryption (default true)Create a manual backup of the current Terraform state.
tf-safe backup [flags]
Flags:
--message string Optional backup message/description
--force Force backup even if no changes detectedList all available backups.
tf-safe list [flags]
Flags:
--storage string Filter by storage backend (local, s3, all) (default "all")
--limit int Limit number of results (default 20)
--format string Output format (table, json, yaml) (default "table")Restore a previous state backup.
tf-safe restore <backup-id> [flags]
Flags:
--dry-run Show what would be restored without making changes
--force Skip confirmation prompt
--backup-current Create backup of current state before restore (default true)tf-safe provides drop-in replacements for common Terraform commands:
# Terraform apply with automatic backups
tf-safe apply [terraform-flags]
# Terraform plan with pre-operation backup
tf-safe plan [terraform-flags]
# Terraform destroy with pre-operation backup
tf-safe destroy [terraform-flags]All Terraform flags and arguments are passed through unchanged.
tf-safe uses a hierarchical configuration system:
- Command-line flags (highest priority)
- Project-level
.tf-safe.yaml - Global
~/.tf-safe/config.yaml - Built-in defaults (lowest priority)
# Local storage configuration
local:
enabled: true # Enable local backups
path: ".tfstate_snapshots" # Local backup directory
retention_count: 10 # Number of local backups to keep
# Remote storage configuration
remote:
provider: "s3" # Storage provider (s3)
bucket: "my-terraform-backups" # S3 bucket name
region: "us-west-2" # AWS region
prefix: "project-name/" # S3 key prefix
enabled: true # Enable remote backups
# Encryption configuration
encryption:
provider: "aes" # Encryption provider (aes, kms, none)
kms_key_id: "" # AWS KMS key ID (for KMS provider)
# Retention policies
retention:
local_count: 10 # Local backup retention count
remote_count: 50 # Remote backup retention count
max_age_days: 90 # Maximum backup age in days
# Logging configuration
logging:
level: "info" # Log level (debug, info, warn, error)
format: "text" # Log format (text, json)For complete configuration reference, see Configuration Reference.
tf-safe can store backups to multiple backends simultaneously:
local:
enabled: true
retention_count: 5
remote:
provider: s3
bucket: team-terraform-backups
enabled: trueencryption:
provider: aes
# Key will be generated and stored locallyencryption:
provider: kms
kms_key_id: "arn:aws:kms:us-west-2:123456789012:key/12345678-1234-1234-1234-123456789012"encryption:
provider: nonename: Terraform with tf-safe
on: [push, pull_request]
jobs:
terraform:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install tf-safe
run: |
curl -fsSL https://raw.githubusercontent.com/BIRhrt/tf-safe/main/scripts/install.sh | bash
- name: Configure tf-safe
run: |
tf-safe init --storage s3
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: Terraform Plan
run: tf-safe plan
- name: Terraform Apply
if: github.ref == 'refs/heads/main'
run: tf-safe apply -auto-approveterraform:
image: hashicorp/terraform:latest
before_script:
- curl -fsSL https://raw.githubusercontent.com/BIRhrt/tf-safe/main/scripts/install.sh | bash
- tf-safe init --storage s3
script:
- tf-safe plan
- tf-safe apply -auto-approve
only:
- main- Go 1.23 or later
- Git
# Clone the repository
git clone https://github.com/BIRhrt/tf-safe.git
cd tf-safe
# Build for your platform
make build
# Build for all platforms
make build-all
# Install locally
make install
# Run tests
make test| Option | Type | Default | Description |
|---|---|---|---|
enabled |
bool | true |
Enable local backup storage |
path |
string | .tfstate_snapshots |
Directory for local backups |
retention_count |
int | 10 |
Number of local backups to retain |
| Option | Type | Default | Description |
|---|---|---|---|
provider |
string | s3 |
Storage provider (currently only s3) |
bucket |
string | "" |
S3 bucket name |
region |
string | us-west-2 |
AWS region |
prefix |
string | "" |
S3 key prefix |
enabled |
bool | false |
Enable remote backup storage |
| Option | Type | Default | Description |
|---|---|---|---|
provider |
string | aes |
Encryption provider (aes, kms, none) |
kms_key_id |
string | "" |
AWS KMS key ID (required for kms provider) |
| Option | Type | Default | Description |
|---|---|---|---|
local_count |
int | 10 |
Number of local backups to retain |
remote_count |
int | 50 |
Number of remote backups to retain |
max_age_days |
int | 90 |
Maximum backup age in days |
| Option | Type | Default | Description |
|---|---|---|---|
level |
string | info |
Log level (debug, info, warn, error) |
format |
string | text |
Log format (text, json) |
tf-safe looks for terraform.tfstate in the current directory. Make sure you're running tf-safe from your Terraform project root.
Ensure tf-safe has write permissions to the backup directory:
chmod 755 .tfstate_snapshotsVerify your AWS credentials are configured:
aws configure list
# or
export AWS_ACCESS_KEY_ID=your-key
export AWS_SECRET_ACCESS_KEY=your-secretIf a backup fails integrity checks:
# List all backups to find a good one
tf-safe list
# Restore from a known good backup
tf-safe restore <backup-id>Enable debug logging for troubleshooting:
tf-safe --log-level debug <command>Or in configuration:
logging:
level: debug- Documentation: GitHub Repository
- Issues: GitHub Issues
- Discussions: GitHub Discussions
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
This project is licensed under the MIT License - see the LICENSE file for details.
- HashiCorp Terraform for the amazing infrastructure as code tool
- Cobra for the CLI framework
- Viper for configuration management