Skip to main content

Functional Specification: Secrets Management with Infisical

1. Introduction & Goal

Problem: The project currently relies on multiple .env files across different services (/backend/.env, /python-services/.env, etc.). This approach is insecure, difficult to manage, and prone to errors. Secrets are not centrally stored or audited.

Goal: To implement a centralized, secure, and scalable secrets management solution by deploying a self-hosted Infisical instance. This will replace the use of .env files for storing sensitive information.

2. Current State

  • Secrets like database URLs, API keys, and JWT secrets are stored in plaintext .env files within service directories.
  • There is no central source of truth for secrets, making rotation and access control difficult.
  • .env.example files are used for documentation, but they can easily fall out of sync with actual required variables.
  • Sharing secrets among team members is an insecure manual process.

3. Proposed Solution

We will deploy a self-hosted Infisical instance using Docker on Hetzner. All services will be updated to fetch their configuration and secrets from Infisical at runtime using the Infisical SDK.

This provides:

  • Centralized Management: A single dashboard to manage all secrets for all environments (development, production, etc.).
  • Enhanced Security: Secrets are encrypted at rest and in transit. Access can be controlled via role-based access control (RBAC).
  • Audit Trails: All access and changes to secrets are logged.
  • Developer Experience: A simple CLI (infisical run) and SDKs streamline development and eliminate the need to manage local .env files.

4. Scope of Work (Implementation Steps)

  1. Deploy Infisical:

    • Deploy the infisical/infisical:latest Docker image on the Hetzner server, potentially managed via Dokploy.
    • Configure persistent volume for Infisical data.
  2. Configure Infisical Project:

    • Create a new project named chainalign.
    • Set up environments within the project (e.g., development, production).
  3. Migrate Secrets:

    • Identify all secrets from existing .env files in backend, python-services, and any other service.
    • Add these secrets to the chainalign project in Infisical, assigning them to the appropriate environments.
  4. Integrate Infisical SDK:

    • For each service (e.g., graphql-server, python-service), add the appropriate Infisical SDK (@infisical/sdk for Node.js).
    • Create a configuration loader (e.g., config.js) in each service that:
      • Initializes the Infisical client using INFISICAL_CLIENT_ID and INFISICAL_CLIENT_SECRET.
      • Fetches all secrets for the current NODE_ENV.
      • Exports the secrets for the application to use.
  5. Update Environment Configuration:

    • The only environment variables required by the services will be INFISICAL_CLIENT_ID, INFISICAL_CLIENT_SECRET, and NODE_ENV.
    • These will be stored in a single, git-ignored .env.local file for local development.
    • In production (Hetzner/Dokploy), these variables will be injected securely by the deployment system.
  6. Cleanup:

    • Delete all old .env files from the project repository.
    • Ensure .env.local and similar files are listed in .gitignore.
    • Update README.md and other developer documentation to reflect the new setup process.

5. Out of Scope

  • This FSD does not cover the migration of the user authentication system from Firebase to SuperTokens. That is detailed in a separate document.
  • This FSD does not cover the setup of advanced Infisical features like secret rotation or signed JWTs, which can be considered in a future phase.

6. Success Criteria

  • All services successfully start and run by fetching secrets from the central Infisical instance.
  • No sensitive information (API keys, database URLs, etc.) exists in any .env file within the git repository.
  • Local development is simplified via the infisical run --env=development -- npm run dev command.
  • Production deployments automatically receive secrets without any .env files on the server.