Infisical: Open Source Secrets and Env Var Manager
Infisical is quickly becoming the go‑to open‑source solution for managing secrets and environment variables across development, staging, and production. It blends the simplicity of a .env file with the security and auditability of a vault, all while staying completely self‑hosted or cloud‑hosted on your terms. In this post we’ll explore how Infisical works under the hood, walk through a real‑world integration with Node.js and Python, and share some pro tips to keep your secret‑management workflow smooth and secure.
What makes Infisical different?
At first glance Infisical looks like another secret manager, but three design decisions set it apart. First, it stores secrets in an encrypted SQLite database by default, meaning you can spin up a fully functional instance with a single Docker command—no external services required. Second, it offers a native CLI that mirrors the familiar dotenv workflow, letting you replace dotenv with a single line in your startup script. Third, Infisical embraces role‑based access control (RBAC) and audit logs, features usually reserved for enterprise‑grade vaults.
Because it’s open source, you can audit the code, extend the API, or even contribute back. The community has already built integrations for popular CI/CD platforms, Kubernetes operators, and serverless runtimes, making Infisical a flexible backbone for any stack.
Core features at a glance
- End‑to‑end encryption: Secrets are encrypted client‑side before they ever touch the server.
- Environment segregation: Define multiple environments (dev, test, prod) and switch between them with a single flag.
- RBAC & audit trails: Granular permissions per project and detailed logs of who accessed or modified a secret.
- CLI & SDKs: A powerful command‑line interface and language‑specific SDKs for Node.js, Python, Go, and more.
- Self‑hosted or SaaS: Run it on your own infrastructure or use the managed cloud offering.
Getting started: Installation and initial setup
Infisical can be launched in seconds with Docker. The official image bundles the API server, web UI, and PostgreSQL (or SQLite) in one container. Below is the minimal command to get a local dev instance up and running.
docker run -d \
-p 8080:8080 \
-e INFISICAL_ADMIN_EMAIL=admin@example.com \
-e INFISICAL_ADMIN_PASSWORD=SuperSecret123 \
--name infisical \
infisical/infisical:latest
After the container starts, visit http://localhost:8080 to complete the web‑based onboarding. You’ll create your first organization, add a project, and generate an API key that the CLI will use for authentication.
CLI installation
The CLI is a single binary you can download via Homebrew, npm, or a direct curl command. Here’s the Homebrew approach for macOS and Linux:
brew tap infisical/infisical
brew install infisical
Verify the installation:
infisical --version
Authenticating the CLI
Export your API key as an environment variable or store it in the CLI’s config file. The most secure method is to use the infisical login command, which stores the token encrypted on disk.
infisical login --api-key YOUR_GENERATED_API_KEY
Now the CLI can fetch, create, and update secrets without you having to type the token each time.
Using Infisicular with Node.js
Node.js developers love the simplicity of dotenv. Infisical’s SDK mimics that pattern while adding encryption and remote fetching. Install the package:
npm install @infisical/sdk
Below is a minimal example that loads secrets for the development environment and starts an Express server.
const express = require('express');
const { InfisicalClient } = require('@infisical/sdk');
// Initialize the client – it reads INFISICAL_TOKEN from process.env
const client = new InfisicalClient({
// The project ID you created in the web UI
projectId: 'proj_1234567890abcdef',
// Optional: override the API base URL if you self‑host
apiUrl: 'http://localhost:8080/api',
});
// Load all secrets for the "development" env
async function loadSecrets() {
const secrets = await client.getAllSecrets({ environment: 'development' });
// Populate process.env so the rest of your app can use them normally
Object.entries(secrets).forEach(([key, value]) => {
process.env[key] = value;
});
}
loadSecrets()
.then(() => {
const app = express();
app.get('/', (req, res) => {
// Example: using a secret stored in Infisical
res.send(`API key is ${process.env.MY_API_KEY}`);
});
app.listen(3000, () => console.log('Server running on :3000'));
})
.catch(err => {
console.error('Failed to load secrets:', err);
process.exit(1);
});
This pattern keeps your codebase clean—no hard‑coded keys, no .env files checked into Git, and a single source of truth for all environments.
Environment switching in CI pipelines
When you run tests in a CI environment, you can tell Infisical which environment to fetch by setting the INFISICAL_ENV variable. Here’s a GitHub Actions snippet that pulls the staging secrets before running Jest tests.
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Infisical CLI
run: brew install infisical/infisical/infisical
- name: Authenticate
run: infisical login --api-key ${{ secrets.INFISICAL_API_KEY }}
- name: Pull secrets
run: infisical pull --environment staging
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
Using Infisical with Python
Python developers can leverage the infisical-python SDK, which integrates seamlessly with os.getenv patterns. Install it via pip:
pip install infisical
Below is a Flask application that pulls secrets at startup, then uses them to configure a database connection.
import os
from flask import Flask
from infisical import InfisicalClient
# Initialise the client – token read from INFISICAL_TOKEN env var
client = InfisicalClient(
project_id="proj_abcdef1234567890",
api_url="http://localhost:8080/api"
)
def load_secrets(env: str = "development"):
# Returns a dict of key/value pairs
secrets = client.get_all_secrets(environment=env)
for key, value in secrets.items():
os.environ[key] = value
# Load secrets before creating the Flask app
load_secrets(env=os.getenv("INFISICAL_ENV", "development"))
app = Flask(__name__)
# Example: using a secret to configure SQLAlchemy
app.config["SQLALCHEMY_DATABASE_URI"] = os.getenv("DATABASE_URL")
@app.route("/")
def index():
# Access a secret directly from the environment
return f"Redis password is {os.getenv('REDIS_PASSWORD')}"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
The same code works locally, in Docker, or on a Kubernetes pod—as long as the appropriate INFISICAL_ENV and INFISICAL_TOKEN are supplied.
Dockerfile example for Python
Embedding the secret‑fetch step into a Docker build keeps your container immutable while still pulling fresh secrets at runtime.
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
# Install Infisical CLI for runtime secret pulling
RUN apt-get update && apt-get install -y curl && \
curl -L https://github.com/Infisical/infisical-cli/releases/download/v0.9.0/infisical-linux-amd64 -o /usr/local/bin/infisical && \
chmod +x /usr/local/bin/infisical
COPY . .
ENV INFISICAL_ENV=production
ENV INFISICAL_TOKEN=${INFISICAL_TOKEN} # passed at container start
# Pull secrets before the app starts
CMD ["sh", "-c", "infisical pull && python app.py"]
Advanced use cases
Beyond simple secret injection, Infisical shines in complex workflows where multiple services need coordinated access.
1. Centralized secrets for a microservices architecture
Imagine a set of microservices—auth, payments, notifications—each running in its own Docker container. Instead of maintaining separate .env files, you create a single Infisical project with multiple environments. Each service pulls only the keys it needs, reducing surface area and simplifying rotation.
- Auth service:
JWT_SECRET,OAUTH_CLIENT_ID - Payments service:
STRIPE_API_KEY,PAYPAL_CLIENT_SECRET - Notifications service:
SENDGRID_API_KEY,SLACK_WEBHOOK_URL
When a key expires, you update it once in the Infisical UI; all services automatically receive the new value on their next pull or via the long‑polling webhook.
2. Secret rotation with zero downtime
Infisical supports versioned secrets. You can create a new version of DB_PASSWORD while the old one remains active. Services that read the secret at startup will continue using the old version until they restart, while new deployments pick up the fresh version. This enables a “rotate‑and‑watch” strategy without immediate service disruption.
Pro tip: Pair Infisical’s versioning with a Kubernetes InitContainer that fetches the latest secrets before the main container starts. This guarantees every pod launches with the newest values while still allowing in‑flight rotation.
3. Auditing and compliance
Every secret read, write, or delete is logged with user ID, timestamp, and IP address. Exporting these logs to a SIEM (Security Information and Event Management) system satisfies many compliance frameworks like PCI‑DSS or GDPR. The UI also offers a “who accessed what” report that can be scheduled as a PDF.
Pro tips and best practices
1. Keep the token out of source control. Store INFISICAL_TOKEN in your CI secret store, not in a .env file that gets committed.
2. Use short‑lived tokens for CI pipelines. Infisical can generate tokens that expire after a set period (e.g., 24 hours). Rotate them regularly to reduce the blast radius of a leak.
3. Leverage secret groups. Group related secrets (e.g., all database credentials) and assign them to a role. This way, adding a new microservice only requires assigning the appropriate group, not individual keys.
4. Enable webhook notifications. Configure a webhook that fires on secret changes; your deployment system can then trigger a rolling restart automatically.
Performance considerations
Infisical’s API is lightweight, but fetching secrets on every request can add latency. The recommended pattern is to cache secrets in memory after the first fetch and refresh them on a configurable interval (e.g., every 5 minutes) or when a webhook signals a change. Most SDKs expose a watch method that abstracts this for you.
For high‑throughput services, consider running a local sidecar that maintains a hot cache of secrets and serves them over a Unix socket. This reduces network hops and keeps your main application focused on business logic.
Troubleshooting common pitfalls
- Invalid token errors: Ensure the token you passed to
infisical loginhas access to the target project and environment. Tokens are scoped; a token for “project A” won’t work on “project B”. - Environment mismatch: If you see empty values, double‑check the
INFISICAL_ENVvariable. By default the CLI assumes “development”. - Network timeouts: When self‑hosting behind a corporate proxy, set
HTTPS_PROXYandNO_PROXYso the CLI can reach the API endpoint. - Permission denied on write: RBAC policies are enforced at the project level. Grant the “write” role to the user or service account that needs to create or update secrets.
Future roadmap (what’s next for Infisical?)
The maintainers have an open roadmap that includes native support for secret‑as‑a‑service (SaaS) integrations (e.g., AWS Secrets Manager, Azure Key Vault), a Terraform provider for IaC pipelines, and an advanced policy engine similar to Open Policy Agent. Keeping an eye on the GitHub milestones will help you plan migrations before major features become stable.
Conclusion
Infisical bridges the gap between the simplicity of .env files and the robustness of enterprise vaults, all while staying fully open source. By integrating its CLI or SDK into your Node.js or Python applications, you gain encrypted, versioned, and auditable secret management without sacrificing developer ergonomics. Whether you’re running a single monolith or a sprawling microservices fleet, Infisical’s environment segregation, RBAC, and webhook capabilities provide the flexibility needed for modern DevOps pipelines. Adopt the pro tips above, automate secret rotation, and let Infisical handle the heavy lifting so you can focus on building great software.