Skip to content
rusthacks.dev
DevOps

Secrets Management for Rust Services in Production

Keep credentials out of images, repositories and logs. Compare environment variables, mounted files, systemd credentials and a secret manager, and plan for rotation.

3 min read
Summarize in AI
Flat illustration for the post “Secrets Management for Rust Services in Production”, composed around security.

Most credential leaks are not clever attacks. They are a .env committed in a hurry, a token in a Dockerfile ENV line, or a Debug print in a log aggregator. The defenses are boring and cheap if you decide them before the first deploy. This post compares four delivery methods and then lists the Rust-side habits that keep a secret from leaking after it arrives. It is the secrets step of shipping Rust to production, following configuration from the environment.

Rust 1.90.

Where secrets must not be

PlaceWhy not
Source repositoryhistory is permanent and widely cloned
Dockerfile ENV or ARGstored in image layers and visible in docker history
Compile-time env! or include_str!baked into the binary, readable with strings
Command line argumentsvisible in ps to other users
Logs and error messagescopied into aggregators with long retention

Four ways to deliver them

  1. Environment from the orchestrator. Kubernetes Secret as env, a systemd EnvironmentFile owned by root, Fly or Heroku config. Simple, widely supported. Visible in /proc/PID/environ to the same user and root.
  2. Mounted files. Docker secrets appear at /run/secrets/name; Kubernetes can mount a Secret as a file; systemd's LoadCredential= provides $CREDENTIALS_DIRECTORY/name. The application reads the file at startup. Permissions scope who can read it.
  3. Secret manager API. AWS Secrets Manager, GCP Secret Manager or Vault, fetched at startup with the instance's identity. Central audit and rotation, and an extra dependency and failure mode at boot.
  4. Encrypted in the repository. SOPS or age encrypted files committed, decrypted at deploy. Works for small teams without a manager; the decryption key is the secret that remains.

Pick the simplest one your platform already offers. Do not build your own.

Reading a file secret in Rust

rust
use std::{fs, io};

fn read_secret(name: &str) -> io::Result<String> {
    let dir = std::env::var("CREDENTIALS_DIRECTORY").unwrap_or_else(|_| "/run/secrets".into());
    Ok(fs::read_to_string(format!("{dir}/{name}"))?.trim().to_string())
}

Trim the trailing newline that editors add. Treat a missing file as a startup error, as in the validation in the configuration post.

Keep it from leaking after it arrives

  • Wrap values in a type with a redacting Debug, or use the secrecy crate, which also zeroes memory on drop. See handling secrets with zeroize and secrecy.
  • Do not log request headers wholesale; Authorization and Cookie carry credentials.
  • Do not include a secret in an error message, including connection strings with passwords.
  • Do not pass secrets as command line arguments to child processes.

Rotation

A secret that cannot be rotated without downtime will not be rotated. Support two active values at once where the protocol allows it: accept tokens signed with the old and new keys during a window, or re-read the file on SIGHUP. For database passwords, create the new user, switch, then delete the old one. Put rotation on a calendar and test the procedure; an untested rotation fails during an incident.

Catching mistakes early

Run a scanner such as gitleaks or trufflehog in CI and as a pre-commit hook. Set .gitignore for key files (git ignore for Rust projects). A leaked cloud key is abused within minutes by automated scanners, so assume exposure and rotate.

Limits

No delivery method protects against an attacker who has code execution as the service user; they can read what the service reads. The defenses reduce the chance of accidental disclosure and limit the blast radius. The OWASP Secrets Management Cheat Sheet is the primary reference.

Also inSecurity
Taggedsecrets
Share

Keep reading

Get new posts by email

We send one email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.