Config File

A Config File is a method of storing secrets and configuration directly in configuration files. These files can be either plaintext or encrypted and are often used for local development or small projects.

✅ When is it appropriate

Config Files are suitable if most of the following apply:

  • the project runs only on a local developer machine and the config file never leaves that machine
  • the configuration contains no passwords, API keys, or tokens, only non-sensitive settings such as port numbers or feature flags
  • the project is a personal tool or throwaway prototype that will never be deployed to a shared server
  • the team needs to get a working application running quickly without setting up any external infrastructure
  • secrets are stored in a separate file that is excluded from version control and never shared with other developers

A config file is a plain text or structured file such as .env, config.yaml, or appsettings.json that the application reads on startup. It is a good fit for local development because the file stays on one machine, but it becomes a security risk as soon as it contains real secrets and is shared across machines or committed to a repository.

❌ When is it NOT appropriate

Config Files may not be ideal if:

  • the application is deployed to a production server where a stolen or leaked config file would expose database passwords or API keys to attackers
  • multiple developers or automated pipelines need access to secrets, because sharing a file by email or chat transmits credentials in the clear
  • the project requires a log of who accessed or changed each secret, and when that change happened
  • credentials must be rotated on a schedule or immediately after a suspected breach, which a static file cannot support without manual edits on every server
  • the application runs in multiple environments such as staging and production, because maintaining separate secret files for each environment creates duplication and increases the chance of an accidental mismatch

The most common way secrets in config files reach attackers is through version control. A developer adds a config file with a real database password, commits it, and pushes it to a repository. Even if the file is deleted in a later commit, the secret remains visible in the repository history. Anyone who clones the repository can read it.

👍 Advantages

  • no external service, daemon, or network connection is needed; the application just reads the file on startup
  • the entire configuration is visible in one file, making it easy to understand what the application needs to run
  • non-sensitive configuration such as port numbers, timeouts, and feature flags can be committed to version control alongside the code
  • any developer can get the application running locally in minutes without requesting access to external systems

👎 Disadvantages

  • a plaintext file containing a password is readable by anyone who gains access to the filesystem, a backup, or the repository
  • the file must be manually copied to every server that needs it, and keeping all copies in sync across environments is error-prone
  • there is no built-in way to track who read a secret or to replace all copies of a secret quickly when it needs to change
  • a secret accidentally committed to version control remains in the repository history even after the file is deleted
  • as the application grows, managing separate config files per environment leads to duplication and inevitable configuration drift between environments

🛠️ Typical use cases

  • local development with non-sensitive settings such as local database ports or debug flags
  • personal or single-developer projects with no shared repository
  • throwaway prototypes and MVPs where secrets will be replaced before any real deployment
  • CI/CD pipelines where secrets are injected into a temporary config file at build time and never persisted to disk

⚠️ Common mistakes (anti-patterns)

  • storing real passwords, API keys, or tokens in a plaintext file instead of using encrypted secrets or environment variables
  • committing a config file that contains secrets to a Git repository, because the secret remains in the repository history even if the file is deleted in a later commit
  • sharing a config file with secrets between developers by email, Slack, or any other channel
  • using config files in production for an application accessed by many users, where a single server compromise would expose all secrets at once

Committing a secret to Git is difficult to undo. Deleting the file in a later commit does not remove the secret from the repository history. Any developer or attacker who clones the repository can run git log and read the secret from an older commit. To truly remove a secret from Git history, you need a tool such as git filter-repo, which rewrites every commit in the repository.

💡 How to build on it wisely

Recommended approach:

  1. Add a .env or config.local.* file pattern to .gitignore before writing any secrets into those files. Check that the pattern is in .gitignore before the first commit.
  2. Never put a real password, API key, or token into a file that is committed to version control. Use a separate local-only file for secrets and commit only a .env.example that lists the required variable names with empty or placeholder values.
  3. If a secret is accidentally committed, treat it as compromised immediately. Rotate the credential in the external service first, then remove the secret from the repository history using git filter-repo.
  4. For any environment beyond a local developer machine, replace config files with environment variables injected by the deployment platform, or use a dedicated secrets manager such as HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault.
  5. If encrypted config files are necessary, use a tool such as SOPS or git-crypt so that the file in the repository is ciphertext and the decryption key is stored separately.

When the application is deployed to a shared server, when more than one developer needs access to secrets, or when credentials must be rotated without touching every server manually, these are concrete signals to move to environment variables injected by the platform or to a dedicated secrets manager such as HashiCorp Vault.

Feedback & Sharing

Give us your thoughts on this page, or share it with others who may find it useful.

Share with your network:

Feedback

Found this helpful? Let me know what you think or suggest improvements 👉 Contact me.