Redenv Python SDK
The official, zero-knowledge Python client for Redenv. Securely fetch, cache, and manage your environment variables at runtime.
Features
- 🔒 Zero-Knowledge: End-to-End Encryption. Secrets are decrypted locally using your Project Encryption Key (PEK).
- ⚡ High Performance: In-memory
LRUCachewithStale-While-Revalidatestrategy for zero-latency reads. - 🔄 Universal: Native Async (
asyncio) and Synchronous clients included. - 🛠️ Developer Experience:
- Smart Casting:
secrets.get("PORT", cast=int) - Scoping:
secrets.scope("STRIPE_")for namespaced configs. - Validation:
secrets.require("API_KEY")fail-fast checks. - Time Travel: Fetch historical versions of secrets.
- Smart Casting:
- 🛡️ Secure by Default: Secrets are masked (
********) in logs to prevent accidental leaks.
Installation
pip install redenv
Quick Start
Async Client (FastAPI / Modern Apps)
import asyncio
import os
from redenv import Redenv
async def main():
client = Redenv({
"project": os.getenv("REDENV_PROJECT"),
"token_id": os.getenv("REDENV_TOKEN_ID"),
"token": os.getenv("REDENV_TOKEN_KEY"),
"upstash": {
"url": os.getenv("UPSTASH_REDIS_URL"),
"token": os.getenv("UPSTASH_REDIS_TOKEN")
}
})
# 1. Load Secrets (Populates os.environ by default)
secrets = await client.load()
# 2. Access Secrets
print(f"Database URL: {secrets['DATABASE_URL']}")
# 3. Smart Casting
port = secrets.get("PORT", cast=int)
debug = secrets.get("DEBUG", cast=bool)
# 4. Safe Access (Returns None if missing)
missing = secrets["MISSING_KEY"] # None
# 5. Fallback Values
timeout = secrets.get("TIMEOUT", default=30, cast=int)
if __name__ == "__main__":
asyncio.run(main())
Synchronous Client (Flask / Scripts / Legacy)
Perfect for scripts or frameworks where async/await is not available at the top level.
from redenv import RedenvSync
client = RedenvSync({ ... }) # Same config as above
# Blocks until secrets are fetched
secrets = client.load()
print(secrets["API_KEY"])
Advanced Usage
1. Secret Expansion (Reference other keys)
Redenv supports referencing other secrets using the ${VAR_NAME} syntax. This helps avoid duplication.
Example Configuration:
BASE_URL:https://api.example.comAUTH_URL:${BASE_URL}/auth
Usage:
secrets = await client.load()
print(secrets["AUTH_URL"])
# Output: https://api.example.com/auth
2. Raw Values
You can access the unexpanded, raw value of a secret using the .raw property. This is useful for debugging or editing.
print(secrets["AUTH_URL"]) # https://api.example.com/auth
print(secrets.raw["AUTH_URL"]) # ${BASE_URL}/auth
3. Scoping & Validation
Organize large configurations and ensure critical keys exist.
secrets = await client.load()
# Fail if these keys are missing
secrets.require("STRIPE_KEY", "STRIPE_WEBHOOK")
# Create a subset of keys (e.g., keys starting with "STRIPE_")
# The prefix is automatically stripped.
stripe_config = secrets.scope("STRIPE_")
print(stripe_config["KEY"]) # Maps to STRIPE_KEY
print(stripe_config["WEBHOOK"]) # Maps to STRIPE_WEBHOOK
4. Time Travel (Version History)
Redenv stores a history of every secret change. You can access older versions for rollbacks or auditing.
# Get the absolute version 5
v5 = await client.get_version("API_KEY", 5)
# Get the previous version (1 version older than latest)
# Mode="index": 0=Latest, 1=Previous, -1=Oldest
prev = await client.get_version("API_KEY", 1, mode="index")
# Get the oldest version ever created
first = await client.get_version("API_KEY", -1)
3. Writing Secrets
You can update secrets programmatically. This automatically encrypts the value, increments the version, and updates the history.
await client.set("FEATURE_FLAG", "true")
4. Configuration Options
| Option | Type | Description | Default |
|---|---|---|---|
project |
str | Your Project ID | Required |
token_id |
str | Service Token Public ID | Required |
token |
str | Service Token Secret Key | Required |
upstash |
dict | { url: ..., token: ... } |
Required |
environment |
str | Target environment (dev, prod) | development |
log |
str | Log level (none, low, high) |
low |
cache |
dict | { ttl: 300, swr: 86400 } (seconds) |
5min / 24h |
env.override |
bool | Overwrite existing os.environ keys |
True |
client = Redenv({
# ...
"env": {
"override": False # Protects local env vars from being overwritten
}
})
Security
- Masking: If you accidentally print the
secretsobject, values are hidden:Secrets({'API_KEY': '********'}). - Zero-Knowledge: The server (Upstash) never sees the plaintext. Decryption happens only in your application's memory.
License
MIT
Release files for redenv 0.4.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| redenv-0.4.1.tar.gz | 18.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| redenv-0.4.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 37.3 kB
Release files / redenv-0.4.1.tar.gz
| Download URL | redenv-0.4.1.tar.gz |
|---|---|
| Size | 18.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4c51aa5053a876be7451fda118f088970f02697b9dfb2f9ca909d684c7f2b041
|
|
BLAKE2b-256 checksum How to use checksums |
aafd49cf4b0018b398eb6f5e09f6f683090ebd4b914e08aa76a057e9f36a4c1a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.0
|
Release files / redenv-0.4.1-py3-none-any.whl
| Download URL | redenv-0.4.1-py3-none-any.whl |
|---|---|
| Size | 18.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ce3360fb4d6902c5bbb06b3e75ec0b0e4817f42c3e5a8488218fff0453305b23
|
|
BLAKE2b-256 checksum How to use checksums |
e08b52942ccdb262296ec0fc0c6a205df742d8f7a98c52d766573283ba88c8b1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.0
|