OpSOPS is a wrapper around SOPS (Secrets OPerationS) that uses 1Password for key management, making it easier to handle encrypted files and secrets in your projects.
OpSOPS simplifies the process of encrypting, decrypting, and managing secrets by leveraging SOPS with 1Password integration. It handles key management automatically, allowing teams to securely share encrypted configuration without manual key distribution.
# Nix
# todo
# Or using homebrew
brew tap frostplexx/tap
brew install opsops
- SOPS installed on your system
- 1Password CLI installed and configured
opsops <COMMAND>
list-config
- Parse and display the.sops.yaml
for this projectgenerate-age-key
- Generate an age key pairedit
- Edit a file using sops with a key from 1passwordencrypt
- Encrypt a file using sopsdecrypt
- Decrypt a file using sopsinit
- Initialize opsopshelp
- Print this message or the help of the given subcommand(s)
See [[#Configuration]] on how to create a .sops.yaml. The 1Password item will be chosen in the next step
opsops generate-age-key
This will generate a new age key pair and store the private key securely in your 1Password vault. Afterwards you have to add the public key manually to the .sops.yaml you created in the previous step
opsops init
This command will:
- Set up 1Password integration
- Guide you through selecting the correct 1Password item
opsops encrypt config.json
opsops decrypt config.enc.json
opsops edit config.enc.json
This will decrypt the file, open it in your default editor, and re-encrypt it when you save and exit.
OpsOps uses the standard .sops.yaml
configuration file format with additional options for 1Password integration.
Example .sops.yaml
:
creation_rules:
- path_regex: .*.ya?ml
age: age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
encrypted_suffix: _secret
- path_regex: .*.json
age: age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
encrypted_regex: "^(data|stringData)$"
# OpsOps specific configuration
onepassworditem: op://Personal/test/Private Key
OpsOps simplifies key management for teams by storing encryption keys in 1Password, which can be shared securely with team members through 1Password vaults.
To add a new team member:
- Add them to the appropriate 1Password vault
- They can now encrypt/decrypt files using OpsOps without additional configuration
OPSOPS_OP_VAULT
- Override the 1Password vault nameOPSOPS_OP_ITEM
- Override the 1Password item nameOPSOPS_AGE_KEY_FIELD
- Override the field name for the age key in 1PasswordEDITOR
- The editor to use when editing files (defaults to system default)
OpSOPS provides a simplified interface to SOPS while handling all the key management through 1Password:
- When encrypting/decrypting, OpsOps retrieves the appropriate keys from 1Password
- It temporarily makes the keys available to SOPS
- SOPS performs the encryption/decryption operation
- The keys are set as environment variables and never stored on disk
- "1Password CLI not found" - Install the 1Password CLI and make sure it's in your PATH
- "Unable to access 1Password vault" - Ensure you're signed in to 1Password CLI (
op signin
) - "Key not found in 1Password" - Check your configuration and make sure the key exists in the specified vault/item
Run OpSOPS with debug logging:
RUST_LOG=debug opsops <command>
# Clone the repository
git clone https://github.com/username/opsops.git
cd opsops
# If you have direnv installed
direnv allow
# Or manually activate the development environment
nix develop
# Clone the repository
git clone https://github.com/username/opsops.git
cd opsops
# Build the project
cargo build
# Run the tests
cargo test
The project includes a Justfile with common development tasks:
# List available commands
just
# Build the project (uses Nix if available, otherwise Cargo)
just build
# Run tests
just test
# Format code
just fmt
Contributions are welcome! Please feel free to submit a Pull Request.
OpsOps is designed with security in mind:
- No keys are stored on disk in plaintext
- All key material is fetched from 1Password just-in-time
- Automatically check if public age key in sops file matches the one in the 1password item
- If age keys don't offer to update
- Add more options like specifying a key file or manually specifying a 1password item in-line
- init should offer to generate a blank .sops.yaml if it doesn't exist.
- Add autocomplete
- Add set key command:
- ^(String|STRING)