How to Keep Secrets in Python Without Pushing Them to GitHub
In Python application development it’s common to work with API keys, access tokens, or database credentials. Accidentally publishing these values in a public repository can compromise your project’s security and generate unexpected costs. Below is a practical, straightforward method to keep your secrets out of the code and prevent them from ending up on GitHub.
1. Understanding the Risk of Storing Secrets in the Repository
Git records every change permanently. Even if you delete a secret in a later commit, the value remains in the history and anyone who clones the repository can retrieve it. This situation is described in the best‑practice guide for secret management in development teams, which recommends preventing sensitive values from entering the source tree from the start【3】. Moreover, public repositories are indexed by search engines and can be automatically scanned by bots looking for exposed keys.
2. Using .env Files and the python‑dotenv Library
The simplest and most widely adopted solution is to store the values in a plain‑text file called .env. Each line contains an environment variable in the form NAME=value. For example:
API_KEY=12345abcde DB_PASSWORD=mi_contraseña_secreta The file is never committed to the repository; it lives locally or in the deployment environment. When your application starts, the python‑dotenv library reads the .env file and loads those variables into the process environment, so you can access them with os.getenv():
import os from dotenv import load_dotenv load_dotenv() # Load .env into the environment api_key = os.getenv("API_KEY") db_pass = os.getenv("DB_PASSWORD") This practice is outlined in the guide on secret and API‑key management in Python, which advises keeping secrets out of the code and loading them only when needed【1】.
3. Protecting the .env File with .gitignore and Best Practices
To make sure the file never gets included in commits, add it to the project’s .gitignore:
# .gitignore .env It’s good practice to create a .env.example file that contains only the variable names without values. This way, any collaborator knows which variables need to be defined without exposing real data.
# .env.example API_KEY= DB_PASSWORD= When the project is initialized, each developer copies this file to .env and fills in the local values. If you accidentally commit the file, you can purge it from history with tools like git filter-branch or git filter-repo, although preventing the inclusion in the first place is the ideal approach【3】.
4. Advanced Alternatives for Production Environments
4.1 GitHub Secrets
GitHub provides a mechanism called Secrets that allows you to store encrypted values at the repository or organization level. These secrets can be consumed by GitHub Actions during CI/CD pipelines without appearing in logs. The official GitHub documentation explains how to create and use these secrets securely【2】.
In a workflow, a secret is accessed with the syntax ${{ secrets.NAME }} and passed to the container or script that runs the application. This option is ideal when deployment is performed entirely on GitHub’s infrastructure.
4.2 External Secret Managers
For more complex projects, you can integrate specialized services such as HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault. These systems offer automatic credential rotation, auditing, and policy‑based access control. Although their setup is more involved, they provide an additional security layer that goes beyond a simple .env file.
5. Quick Checklist to Avoid Exposing Secrets
| Action | ✅ Yes | ❌ No |
|---|---|---|
Add .env to .gitignore | ||
Keep a .env.example without values | ||
Review history with git log --stat before publishing | ||
Use python-dotenv to load variables | ||
| Configure GitHub Secrets for CI/CD | ||
| Avoid printing sensitive variables in logs | ||
| Rotate credentials regularly |
Following this checklist on every new project significantly reduces the risk of leaks.
Conclusion
Keeping secrets out of source code is an essential practice for any Python developer publishing to GitHub. By using a .env file together with python-dotenv, protecting it with .gitignore, and supplementing with GitHub Secrets or external managers, you can ensure that your keys and passwords remain confidential in both development and production.
Ready to secure your next project?
Create a .env.example file right now, add .env to your .gitignore, and test variable loading with python-dotenv. If you use GitHub Actions, configure at least one secret and watch your pipeline run without revealing sensitive information. Protect your code and sleep easy!
