| Crates.io | keyenv |
| lib.rs | keyenv |
| version | 1.2.0 |
| created_at | 2026-01-24 15:16:07.846389+00 |
| updated_at | 2026-01-24 15:16:07.846389+00 |
| description | Official Rust SDK for KeyEnv - Secrets management made simple |
| homepage | https://keyenv.dev |
| repository | https://github.com/keyenv/rust-sdk |
| max_upload_size | |
| id | 2066825 |
| size | 120,793 |
Official Rust SDK for KeyEnv - Secrets management made simple.
Add to your Cargo.toml:
[dependencies]
keyenv = "1.0"
tokio = { version = "1", features = ["full"] }
Or using cargo:
cargo add keyenv tokio --features tokio/full
use keyenv::KeyEnv;
use std::env;
#[tokio::main]
async fn main() -> Result<(), keyenv::Error> {
let client = KeyEnv::builder()
.token(env::var("KEYENV_TOKEN").expect("KEYENV_TOKEN not set"))
.build()?;
// Load secrets into environment
client.load_env("your-project-id", "production").await?;
println!("{}", env::var("DATABASE_URL").unwrap());
Ok(())
}
use keyenv::KeyEnv;
use std::time::Duration;
let client = KeyEnv::builder()
.token("your-service-token") // Required
.base_url("https://api.keyenv.dev") // Optional
.timeout(Duration::from_secs(30)) // Optional, default 30s
.cache_ttl(Duration::from_secs(300)) // Optional, 0 disables caching
.build()?;
The simplest way to use secrets in your application:
let count = client.load_env("project-id", "production").await?;
println!("Loaded {} secrets", count);
// Now use them
println!("{}", std::env::var("DATABASE_URL").unwrap());
Get secrets as a HashMap:
let secrets = client.export_secrets_as_map("project-id", "production").await?;
println!("{}", secrets.get("DATABASE_URL").unwrap());
Get secrets with full metadata:
let secrets = client.export_secrets("project-id", "production").await?;
for secret in secrets {
println!("{}={}", secret.key, secret.value);
}
let secret = client.get_secret("project-id", "production", "DATABASE_URL").await?;
println!("{}", secret.value);
Creates or updates a secret:
client.set_secret("project-id", "production", "API_KEY", "sk_live_...").await?;
// With description
client.set_secret_with_description(
"project-id",
"production",
"API_KEY",
"sk_live_...",
Some("Production API key")
).await?;
client.delete_secret("project-id", "production", "OLD_KEY").await?;
use keyenv::{SecretInput, BulkImportOptions};
let result = client.bulk_import(
"project-id",
"development",
vec![
SecretInput::new("DATABASE_URL", "postgres://localhost/mydb"),
SecretInput::new("REDIS_URL", "redis://localhost:6379"),
],
BulkImportOptions { overwrite: true },
).await?;
println!("Created: {}, Updated: {}", result.created, result.updated);
use std::fs;
let content = client.generate_env_file("project-id", "production").await?;
fs::write(".env", content)?;
let projects = client.list_projects().await?;
for project in projects {
println!("{} ({})", project.name, project.id);
}
let project = client.get_project("project-id").await?;
println!("Project: {}", project.name);
for env in project.environments {
println!(" - {}", env.name);
}
use keyenv::{KeyEnv, Error};
match client.get_secret("project-id", "production", "MISSING_KEY").await {
Ok(secret) => println!("{}", secret.value),
Err(Error::Api { status, message, .. }) => {
match status {
401 => eprintln!("Invalid or expired token"),
403 => eprintln!("Access denied"),
404 => eprintln!("Secret not found"),
_ => eprintln!("Error {}: {}", status, message),
}
}
Err(e) => eprintln!("Error: {}", e),
}
Enable caching for better performance:
let client = KeyEnv::builder()
.token(env::var("KEYENV_TOKEN")?)
.cache_ttl(Duration::from_secs(300)) // 5 minutes
.build()?;
// Cached for 5 minutes
let secrets = client.export_secrets("project-id", "production").await?;
// Clear cache manually
client.clear_cache(Some("project-id"), Some("production")).await;
// Or clear all cache
client.clear_all_cache().await;
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
token |
String |
Yes | - | Service token |
base_url |
String |
No | https://api.keyenv.dev |
API base URL |
timeout |
Duration |
No | 30s |
Request timeout |
cache_ttl |
Duration |
No | 0 |
Cache TTL (0 = disabled) |
| Method | Description |
|---|---|
get_current_user() |
Get current user/token info |
list_projects() |
List all accessible projects |
get_project(id) |
Get project with environments |
list_environments(project_id) |
List environments |
list_secrets(project_id, env) |
List secret keys (no values) |
export_secrets(project_id, env) |
Export secrets with values |
export_secrets_as_map(project_id, env) |
Export as HashMap |
get_secret(project_id, env, key) |
Get single secret |
set_secret(project_id, env, key, value) |
Create or update secret |
set_secret_with_description(...) |
Create/update with description |
delete_secret(project_id, env, key) |
Delete secret |
bulk_import(project_id, env, secrets, opts) |
Bulk import secrets |
load_env(project_id, env) |
Load secrets into env vars |
generate_env_file(project_id, env) |
Generate .env file content |
get_secret_history(project_id, env, key) |
Get secret version history |
list_permissions(project_id, env) |
List permissions |
set_permission(project_id, env, user_id, role) |
Set user permission |
delete_permission(project_id, env, user_id) |
Delete permission |
bulk_set_permissions(...) |
Bulk set permissions |
get_my_permissions(project_id) |
Get current user's permissions |
get_project_defaults(project_id) |
Get default permissions |
set_project_defaults(project_id, defaults) |
Set default permissions |
clear_cache(project_id, env) |
Clear cached secrets |
clear_all_cache() |
Clear all cached data |
use actix_web::{web, App, HttpServer, Responder};
use keyenv::KeyEnv;
use std::env;
async fn index() -> impl Responder {
"OK"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let client = KeyEnv::builder()
.token(env::var("KEYENV_TOKEN").unwrap())
.build()
.unwrap();
// Load secrets before starting server
client.load_env(
&env::var("KEYENV_PROJECT").unwrap(),
"production"
).await.unwrap();
HttpServer::new(|| {
App::new().route("/", web::get().to(index))
})
.bind(("0.0.0.0", 8080))?
.run()
.await
}
use keyenv::KeyEnv;
use lambda_runtime::{service_fn, LambdaEvent, Error};
use once_cell::sync::Lazy;
use std::env;
static CLIENT: Lazy<KeyEnv> = Lazy::new(|| {
KeyEnv::builder()
.token(env::var("KEYENV_TOKEN").unwrap())
.cache_ttl(std::time::Duration::from_secs(300))
.build()
.unwrap()
});
async fn handler(_event: LambdaEvent<()>) -> Result<String, Error> {
CLIENT.load_env(&env::var("KEYENV_PROJECT")?, "production").await?;
Ok(env::var("API_KEY")?)
}
#[tokio::main]
async fn main() -> Result<(), Error> {
lambda_runtime::run(service_fn(handler)).await
}
rustls - Use rustls for TLS (recommended for most platforms)native-tls - Use native TLS (OpenSSL on Linux, Secure Transport on macOS)[dependencies]
keyenv = { version = "1.0", features = ["rustls"] }
MIT License - see LICENSE for details.