Secure storage vault for secrets in git repositories (SOPS alike)
Project description
XVault
XVault is a portable encrypted vault designed for developers to securely store secrets, tokens, certificates, and sensitive files while keeping encrypted vaults safe to store in Git repositories.
XVault is built around a simple idea:
Keep encrypted secrets versioned in Git while protecting the keys locally.
XVault supports modern cryptography, OS keyring integration, and flexible project configuration to make secret management safe and developer-friendly.
Single Source of Truth
XVault acts as a single source of truth for all sensitive configuration a project needs (secrets, tokens, passwords, certificates, and file blobs). From this encrypted vault, you can derive/export the exact formats your tooling expects (e.g., .env, JSON config, certificate files) without duplicating plaintext secrets across multiple files or repositories.
To minimize cognitive load, XVault keeps the workflow intentionally simple: one encrypted store, secure defaults, and straightforward commands—no servers to run, no KMS to configure, and no complex policy systems. It’s optimized for solo developers and small teams who want a local-first vault that integrates cleanly with Git.
Contents
- Motivation
- Features
- Security Model
- Installation
- Quick Start
- Import Secrets
- Export Secrets
- Project Configuration
- Roadmap
- License
Motivation
Many developers store secrets in .env files or private folders.
These files are frequently committed accidentally to Git repositories.
Tools such as Hashicorp Vault or Mozilla SOPS solve this problem
for infrastructure environments, but they often require external
key management systems.
XVault was created to provide a lightweight developer-focused vault that works locally, integrates with Git workflows, and requires no external infrastructure.
XVault focuses on a different niche than most secret-management tools:
- Local-first — works without external infrastructure
- Git-friendly — encrypted files are safe to version in repositories
- Developer-oriented — designed for development workflows
- Portable — no dependency on cloud KMS providers
The focus is developer ergonomics: fewer moving parts, fewer decisions, and a predictable workflow that works the same across projects.
Comparison with SOPS and git-crypt
XVault, SOPS (Secrets OPerationS), and git-crypt share a similar goal: storing encrypted secrets safely inside version-controlled files. They allow developers to keep encrypted configuration in Git while protecting the decryption keys locally. However, their design philosophies differ. SOPS focuses on infrastructure and DevOps workflows (Kubernetes, Terraform, cloud KMS integration), whereas XVault is designed primarily as a developer-centric vault, emphasizing simplicity, local password-based encryption, and flexible secret storage for development environments and personal projects.
| Feature | XVault | SOPS | git-crypt |
|---|---|---|---|
| Primary goal | Developer secret vault | Infrastructure secret management | Encrypt selected files in a Git repo |
| Encryption model | Password-derived key (Argon2id) | External key management (KMS, GPG, Age) | Key-based (GPG) / shared symmetric key for collaborators |
| Encryption algorithm | AES-256-GCM | AES-256-GCM | AES (transparent file encryption) |
| Key derivation | Argon2id | Not applicable (external keys) | Not a focus (GPG-managed keys) |
| Key storage | OS keyring (optional cache) | External key providers | GPG keychain |
| File format | XVault file | YAML / JSON / ENV | Original file formats (encrypted blobs in Git) |
| Git-friendly storage | Yes | Yes | Yes (encrypted blobs in Git) |
| CLI workflow | Developer-oriented | DevOps / infrastructure-oriented | Git workflow oriented |
| External dependencies | None required | Often requires KMS / GPG / Age | Requires GPG (for multi-user) |
| Secret import/export | dotenv, JSON | YAML/JSON editing | Not built-in |
| Typical use case | Developer secrets, local environments, personal vaults | Kubernetes, CI/CD, infrastructure configuration | Team repos where only some files should be readable to authorized users |
In short: XVault is a local-first, developer-oriented vault optimized for keeping a single source of truth and deriving/exporting the formats your projects need. SOPS is best when you want infrastructure-focused workflows and integration with KMS/GPG/Age key management. git-crypt is ideal when you want transparent encryption of specific files inside a Git repo, without a structured secrets store or import/export pipeline.
Example workflow
D:\Reps\myrepos> xvault create dev
Enter password: ********
Confirm password: ********
Store created: dev
Path: D:\Reps\myrepos\.secrets\xvault-dev.xvault
Status: unlocked
D:\Reps\myrepos> xvault set dev API_KEY
Enter secret value: ********
Confirm secret value: ********
API_KEY created
D:\Reps\myrepos> xvault get dev API_KEY
12345678
D:\Reps\myrepos> xvault export dev --format env
API_KEY=12345678
XVault includes an interactive editor (similar to SOPS) that decrypts values in-memory, opens an editor view, and re-encrypts on save.
Design Philosophy
XVault prioritizes developer ergonomics: a predictable workflow, minimal setup, and secure defaults (password → key → keyring → encrypt/decrypt).
This makes XVault particularly well-suited for:
- developer environments
- local secret management
- small teams encrypted vaults
- Git-friendly secret storage without external infrastructure
- personal encrypted vaults
Features
- AES-256-GCM authenticated encryption
- Argon2id password-based key derivation
- Cross-platform keyring integration
- Git-friendly
.xvaultfiles (JSON-based) - dotenv and JSON import/export
- Multiple vault stores per project
- Flexible vault location configuration
- Designed for automation and developer workflows
- Integrated interactive editor (SOPS-style) to edit vault contents safely
Security Model
XVault is designed to protect secrets stored in version-controlled repositories.
Threats mitigated
- accidental disclosure of secrets committed to Git
- unauthorized access to vault files without the password
- offline brute-force attacks through strong password-based key derivation
Cryptographic design
| Component | Algorithm |
|---|---|
| Key derivation | Argon2id |
| Encryption | AES-256-GCM |
| Nonce | 96-bit random nonce |
| Authentication | GCM tag |
Argon2id parameters:
time_cost = 5
memory_cost = 128 MB
parallelism = 4
These parameters significantly increase the cost of offline password brute-force attacks.
High-level encryption flow diagram
flowchart TD
U[User enters password] --> KDF[Argon2id<br/>password + salt -> 32-byte key]
KDF -->|optional| KR[Store derived key in OS keyring<br/>Windows DPAPI / macOS Keychain / Linux Secret Service]
KDF --> AES[AES-256-GCM encryption/decryption]
KR --> AES
AES --> ENC[Encrypt secret value<br/>random nonce + ciphertext + tag]
ENC --> FILE[Write to .xvault file<br/>value stored as enc:v1:...]
FILE --> DEC[Read encrypted value from .xvault file]
DEC --> AES
AES --> OUT[Decrypt -> plaintext value]
Limitations
XVault does not protect against:
- compromised host machines
- malicious code execution
- memory extraction attacks
- weak user passwords
Example Vault File
Vault files are JSON documents containing encrypted values.
{
"meta": {
"schema_version": 1,
"crypto_version": 1,
"salt": "0a24afe64ea0b73bee45f1ad31fcbd2e",
"check": "enc:v1:DtZmJqBmJbL+uvvojo4DmCs5+qhQUb80LiwV9mVqqy2VFfh5"
},
"secrets": {
"API_KEY": {
"type": "password",
"description": "API key for external service",
"meta": {},
"services": [],
"value": "enc:v1:..."
}
}
}
The vault file can safely be stored in Git because all secret values are encrypted.
Installation
Install from PyPI:
pip install xvault
Install from source (development)
Clone the repository:
# clone the repository:
git clone https://github.com/marcdp/xvault.git
# install dependencies:
pip install -r requirements.txt
# run the CLI:
python -m xvault
# or install as a command:
pip install .
Quick Start
Create a vault
xvault create dev
After creating a new vault, it is unlocked (key cached in the OS keyring)
List vaults
xvault list
Example output:
default 3 keys unlocked
dev 1 key locked
Store a secret
xvault set dev API_KEY
Retrieve a secret
xvault get dev API_KEY
Remove a secret
xvault remove dev API_KEY
Import Secrets
XVault can import from common formats.
Import .env
xvault import dev .env
Example .env:
DATABASE_URL=postgres://localhost/db
API_KEY=abcdef123
Import JSON
xvault import dev config.json
Example:
{
"API_KEY": "123456",
"SERVICE_TOKEN": "abcdef"
}
Export Secrets
Derive Project Secrets from the Vault
A common problem in real projects is secret sprawl: the same values end up duplicated across .env, CI variables, deployment scripts, and certificate files.
XVault avoids this by storing everything in one place and generating the rest on demand:
- Store secrets once in XVault
- Export to the format your project needs (
.env, JSON, etc.) - (Optional) export file entries (certs/keys) back to real files when needed
Export vault contents:
xvault export dev
Formats supported:
--format env
--format json
--format xvault
Vault Unlocking
XVault caches vault keys securely using the system keyring.
Unlock a store:
xvault unlock dev
Lock it again:
xvault lock dev
Supported keyring backends:
- Windows DPAPI
- macOS Keychain
- Linux Secret Service
Project Configuration
Vault location can be configured per Git repository.
Create a .xvault file in the project root:
file = ../dev/secrets/{project}-{name}.xvault
Variables:
| Variable | Meaning |
|---|---|
{project} |
Git repository name |
{name} |
vault store name |
Example resulting file:
../dev/secrets/myproject-dev.xvault
This allows multiple repositories to share a centralized secrets directory.
Roadmap
Planned improvements:
- rekey password:
xvault repassword MYSTORE - VSCode extension (to manage xvault contents as a virtual filesystem)
License
MIT License
See the LICENSE file for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file xvault-0.0.33.tar.gz.
File metadata
- Download URL: xvault-0.0.33.tar.gz
- Upload date:
- Size: 25.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
966bba0bd9a3eb3548568a624919036aab5b70bae92b9807f4402eff9331b9e7
|
|
| MD5 |
43ea8160a8a455bf271606e467a5f32a
|
|
| BLAKE2b-256 |
0950ca070609c914012a6ddb15c40ee868757c15e03a51ff763f96955399dd34
|
File details
Details for the file xvault-0.0.33-py3-none-any.whl.
File metadata
- Download URL: xvault-0.0.33-py3-none-any.whl
- Upload date:
- Size: 22.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4f380cd80853b76bf9565f28dc0e283299f7089c8eab188444ec61af3537ff5d
|
|
| MD5 |
9a8dd01657aae045dc97edb42ec1a263
|
|
| BLAKE2b-256 |
f94b1dc3d54502bb40a2eb50c9df2afda1373bc776b211349743eca4ced0a787
|