ojster

Ojster – GitOps-safe one-way encrypted secrets

Problem: I can manage my entire Docker Compose stack with Git, except secrets.

Solution: Encrypt your secrets using Ojster and safely store them in Git — even inside a public repository. Values can only be decrypted by the server holding the private key.

Ojster Logo

Docker Compose workflows commonly rely on environment variables. Even when encrypted with tools like Ansible Vault, Dotenvx, or env-vault, decrypted values often end up embedded in container specs, visible in management UIs (Docker Desktop, Portainer), or leaked via docker inspect, logs, or image metadata.

Ojster closes this gap. It is a companion to Dotenvx that enables zero-trust, ephemeral secrets for Docker Compose, ideal for self-hosting prebuilt images in a GitOps workflow. Decryption happens just in time during container startup and remains exclusively in memory under strict least-privilege constraints.

Benefits

Get ready to BYOB and safely store encrypted secrets in Git.

🚧 Project status: early stages

Ojster is in an early-stage, pre-release phase. Expect breaking changes as the design evolves, security hardening improves, and real-world feedback shapes the API and integration model. The core concepts are stable, but details may change between versions. Review release notes before upgrading.

Quick start

On the server that hosts your Docker containers:

git clone https://github.com/ojster/ojster
cd ojster

# Add some env vars
echo EXAMPLE1=1234 > .env
echo EXAMPLE2=HelloWorld >> .env

# Encrypt env vars with the dotenvx CLI in a locked-down container
docker run -it --rm -v $(pwd):/app --workdir=/app --pull=always \
  -u=64646:64646 --cap-drop=ALL --network=none \
  --security-opt=no-new-privileges=true dotenv/dotenvx encrypt

# Verify encrypted and safe to store in Git
cat .env

# Build Your Own Binary
docker bake

# Bring up example stack
docker compose up -d
# See that the app has access to decrypted env vars
docker logs -f ojster_example_client
# Cleanup
docker compose down

Integrating existing stacks

Add the 4-line snippet (marked OJSTER INTEGRATION in compose.yaml) to any service you want to integrate. Ojster acts as a lightweight docker-init replacement and injects decrypted values at process start — no need to modify entrypoints, commands, or rebuild images.

Comparison

Bitnami Sealed Secrets

If you’re familiar with Kubernetes, Ojster is the closest conceptual match to Bitnami Sealed Secrets — but for Docker Compose.

Shared principles:

Sealed Secrets uses a Kubernetes controller. Ojster applies the same pattern to Docker Compose using a lightweight client and a hardened decryption server.

Dotenvx and Docker secrets

Ojster encryption is currently “powered by” Dotenvx, but the projects are not officially affiliated. See Dotenvx docs for usage instructions. The table below compares Ojster to plain Dotenvx and Docker secrets.

Feature Ojster dotenvx run
outside container
dotenvx run
inside container
Docker secrets
Secure secrets in Git
Encrypted env vars
in container spec
⚠️
Unmodified
container image
Native Docker Compose
Air-gapped
private key access
N/A
0 third-party runtime
dependencies (client side)
Image size increase N/A N/A ~50 MB N/A

Interpretation

Secret platforms

Ojster does not provide the feature set of a full secrets platform. If that’s what you need, consider:

Technical design and workings

Design goals

High-level flow

  1. Client selection: scan environment for values matching OJSTER_REGEX (configurable).
  2. HTTP over Unix socket: client posts key → encrypted value map to the Ojster server over the Unix domain socket.
  3. Server workdir: create a tmpfs directory, write .env, symlink .env.keys.
  4. Subprocess: run dotenvx get -o (configurable) to decrypt in memory.
  5. Validation: ensure subprocess returns only requested keys.
  6. Return: send decrypted map back to client.
  7. Exec: client merges values and execs the real entrypoint.

Key implementation details

Security considerations

Securely provision the private key on the Ojster server host. Only the Ojster server should ever have access to the private key. Access to the ojster volume (which contains the IPC socket file) is equivalent to the ability to request decryptions: any process that can open the socket can talk HTTP to the server and obtain decrypted values. Treat the socket like a sensitive IPC endpoint.

Recommendations

Contributing and license

Contributing

Testing

export BUILDKIT_PROGRESS=plain
docker bake test # logs in ./log/test.log

License

Apache License 2.0.

Why Ojster?

Ojster (pronounced “oyster”) is a metaphor for a protective shell that keeps something valuable sealed away until the moment it’s needed. The J gives the name a distinctive, memorable twist while subtly nodding to its creator. Its nautical undertone fits naturally within the Docker ecosystem.