SecretShift

SecretShift is a CLI tool for migrating and syncing secrets and environment variables between providers. Move secrets from GitHub, GitLab, HashiCorp Vault, etcd, Kubernetes, or local files to any of those destinations.
See CONTEXT.md for domain terminology and conventions.
Features
- 7 provider types: GitHub, GitLab, Vault, etcd, Kubernetes, local file (source + destination)
- Flexible processing: Filter by name regex or type, add prefixes/suffixes to secret names
- Multiple run modes: One-shot, periodic interval, cron-scheduled, or long-running server
- Server mode: HTTP health endpoints (
/healthz, /readyz, /status) for Kubernetes deployments
- Dry-run support: Preview changes without writing to the destination
- Encrypted file I/O: Optional AES-256-GCM encryption for file sources and destinations
- Conflict handling: Replace, skip, or report existing secrets at the destination
- Per-step environment variables: Separate
SECRET_SHIFT_SRC_* and SECRET_SHIFT_DST_* for source and destination credentials
- Helm chart: Deploy to Kubernetes as a Deployment (periodic/server) or CronJob (one-shot)
Installation
Homebrew (macOS & Linux)
brew tap PapaDanielVi/tap
brew install secret-shift
Go Install
go install github.com/PapaDanielVi/secret-shift@latest
From Source
go build -o secret-shift .
From Release
Download the binary for your platform from the releases page.
Installation Scripts
For automated installation and updates, use the provided scripts:
Linux (Auto-detects package manager):
curl -Lo install-linux.sh https://raw.githubusercontent.com/PapaDanielVi/secret-shift/main/scripts/install-linux.sh
chmod +x install-linux.sh
sudo ./install-linux.sh
The script detects and uses:
dnf/yum/zypper: RPM packages
apt-get: DEB packages
apk: APK packages (Alpine)
pacman: Arch packages
- Falls back to tarball if no package manager is found
Windows (PowerShell):
curl -Uri https://raw.githubusercontent.com/PapaDanielVi/secret-shift/main/scripts/install-windows.ps1 -OutFile install-windows.ps1
.\install-windows.ps1
Both scripts:
- Fetch and install the latest release automatically
- Remove existing installations before upgrading
- Install to standard system locations
- Add the binary to PATH (Windows only)
Quick Start
Config File
Create a secret-shift.json:
{
"source": {
"type": "github",
"repo": "owner/repo",
"token": "ghp_xxx"
},
"process": {
"add_prefix": "PROD_",
"include_regex": "^DB_"
},
"destination": {
"type": "vault",
"vault_address": "https://vault.example.com",
"vault_path": "myapp/config",
"token": "hvs_xxx"
}
}
Run the sync:
secret-shift sync
Environment Variables
All config keys can be set via environment variables. Source fields use the SECRET_SHIFT_SRC_ prefix and destination fields use SECRET_SHIFT_DST_:
SECRET_SHIFT_SRC_TYPE=github \
SECRET_SHIFT_SRC_GITHUB_TOKEN=ghp_xxx \
SECRET_SHIFT_DST_TYPE=file \
SECRET_SHIFT_DST_PATH=./secrets.json \
secret-shift sync
This per-step convention means you can use different credentials for source and destination, e.g. SECRET_SHIFT_SRC_GITHUB_TOKEN and SECRET_SHIFT_DST_GITHUB_TOKEN.
Commands
secret-shift sync
Execute a sync pipeline.
| Flag |
Default |
Description |
-c, --config |
./secret-shift.json |
Path to config file |
--periodically |
false |
Run in a loop |
--frequency |
5m |
Interval between syncs (e.g. 1m, 1h) |
--cron |
|
Cron expression (e.g. */5 * * * *) |
--dry-run |
false |
Simulate sync without writing to destination |
--server |
false |
Start HTTP server with health endpoints + periodic sync |
--health-port |
8080 |
Port for health HTTP server |
secret-shift version
Print the current version.
Sources
| Source |
What it reads |
| github |
GitHub Actions secrets + environment variables |
| gitlab |
GitLab project-level CI/CD variables |
| vault |
HashiCorp Vault KV v2 secrets |
| etcd |
etcd key-value pairs under a prefix |
| kubernetes |
K8s Secrets + ConfigMaps (by name, label, or namespace) |
| file |
Local JSON or YAML key-value file (optionally encrypted) |
Destinations
| Destination |
What it writes |
Notes |
| file |
Local JSON or YAML file |
Optional AES-256-GCM encryption |
| github |
GitHub Actions secrets + environment variables |
RSA-OAEP encrypted |
| gitlab |
GitLab project-level CI/CD variables |
|
| vault |
HashiCorp Vault KV v2 |
Single KV entry |
| etcd |
etcd key-value store |
One key per secret |
| kubernetes |
K8s Secrets + ConfigMaps |
Routes by secret type |
Server Mode
When running with --server, secret-shift starts an HTTP server that exposes:
| Endpoint |
Description |
GET /healthz |
Liveness probe — always returns {"status":"ok"} |
GET /readyz |
Readiness probe — returns ready after first successful sync, not_ready if no sync has completed or the last sync failed |
GET /status |
Detailed status including sync count, error count, last sync time |
In server mode, syncs run periodically in the background (default every 5 minutes).
Enterprise and Self-Hosted Providers
GitHub Enterprise
Set the url field to your GitHub Enterprise API endpoint:
{
"source": {
"type": "github",
"repo": "owner/repo",
"url": "https://git.mycompany.com/api/v3",
"token": "ghp_xxx"
}
}
GitLab Self-Hosted
Set the url field to your GitLab instance:
{
"source": {
"type": "gitlab",
"project_id": "123",
"url": "https://gitlab.mycompany.com",
"token": "glpat-xxx"
}
}
Processing
The processor runs between source and destination:
- Type filtering:
include_types / exclude_types filter by "env" or "secret"
- Name filtering:
include_regex / exclude_regex filter by secret name
- Name transformation:
add_prefix and add_suffix modify secret names
Conflict Strategies
For destinations that support it (GitHub, GitLab):
| Strategy |
Behavior |
replace |
Overwrite existing secrets (default) |
skip |
Silently skip existing secrets |
report |
Print conflict info and skip |
Environment Variable Reference
Per-Step Variables
The config system supports separate environment variables for source and destination:
| Variable Pattern |
Example |
SECRET_SHIFT_SRC_TYPE |
Source provider type |
SECRET_SHIFT_SRC_GITHUB_TOKEN |
GitHub token for source |
SECRET_SHIFT_SRC_GITLAB_TOKEN |
GitLab token for source |
SECRET_SHIFT_SRC_VAULT_TOKEN |
Vault token for source |
SECRET_SHIFT_SRC_PATH |
File path for file source |
SECRET_SHIFT_SRC_KUBE_NAMESPACE |
K8s namespace for source |
SECRET_SHIFT_DST_TYPE |
Destination provider type |
SECRET_SHIFT_DST_GITHUB_TOKEN |
GitHub token for destination |
SECRET_SHIFT_DST_GITLAB_TOKEN |
GitLab token for destination |
SECRET_SHIFT_DST_VAULT_TOKEN |
Vault token for destination |
SECRET_SHIFT_DST_PATH |
File path for file destination |
SECRET_SHIFT_DST_KUBE_NAMESPACE |
K8s namespace for destination |
SECRET_SHIFT_DRY_RUN |
Enable dry-run mode |
Token resolution order: direct config value → token_env field → SECRET_SHIFT_SRC/DST_<PROVIDER>_TOKEN env var.
Examples
See the examples/ directory for ready-to-use configurations for every source→destination combination (49 total), each with a config.json and README.md.
Helm Chart
A Helm chart is available at charts/secret-shift/. It supports three modes:
| Mode |
Description |
Kubernetes Resource |
server |
HTTP health endpoints + periodic sync |
Deployment |
periodic |
Periodic sync loop |
Deployment |
one-shot |
Single sync run on a schedule |
CronJob |
helm install secret-shift charts/secret-shift/ --set mode=server
Project Structure
secret-shift/
cmd/ # CLI commands (root, sync, version)
internal/
config/ # Config loading, validation, env resolution
pipeline/ # Sync pipeline (source → process → destination)
provider/ # Provider interfaces + registry
github/ # GitHub source + destination
gitlab/ # GitLab source + destination
vault/ # HashiCorp Vault source + destination
etcd/ # etcd source + destination
kubernetes/ # Kubernetes source + destination
file/ # File source + destination (JSON/YAML, encrypted)
server/ # HTTP health server (/healthz, /readyz, /status)
charts/secret-shift/ # Helm chart for Kubernetes deployment
examples/ # 49 src→dst example configurations
Dependencies
- CLI: Cobra + Viper
- APIs: go-github, GitLab client, Vault API, etcd client, Kubernetes client-go
- Scheduling: cron
- HTTP Server: Standard library
net/http
License
MIT