Variables de entorno y archivos .env en Flask
Cómo sacar claves secretas, contraseñas y configuración fuera de tu código Flask usando un archivo .env. La forma correcta de manejar credenciales sin filtrarlas en GitHub.
Si tu app Flask tiene la clave secreta, la contraseña de la base de datos o un token de API escritos directamente en el código, tienes un problema esperando a pasar: el día que subas eso a GitHub, esas credenciales quedan expuestas. La solución estándar es sacar toda la configuración sensible a un archivo .env. Aquí cómo hacerlo bien.
El problema que resuelve
Mira este código, muy común al empezar:
app.secret_key = "mi-clave-super-secreta"
DATABASE_URL = "postgresql://usuario:password123@localhost/midb"
Todo eso está a la vista. Si subes el proyecto a un repositorio, cualquiera que lo vea tiene tus credenciales. Y aunque el repo sea privado, mezclar secretos con código es una mala práctica: no puedes tener valores distintos para desarrollo y producción sin editar el código.
La idea de las variables de entorno es separar la configuración (que cambia según el entorno) del código (que es igual en todos lados).
Instalar python-dotenv
La librería que carga el archivo .env es python-dotenv:
pip install python-dotenv
Crear el archivo .env
En la raíz de tu proyecto, crea un archivo llamado exactamente .env (con el punto al inicio, sin nombre antes). Dentro, una variable por línea, con formato CLAVE=valor:
SECRET_KEY=una-clave-larga-y-aleatoria-de-verdad
DATABASE_URL=postgresql://usuario:password123@localhost/midb
API_TOKEN=tok_abc123xyz
Sin comillas, sin espacios alrededor del =. Ese es todo el formato.
Cargar las variables en Flask
Al inicio de tu app, cargas el .env y luego lees los valores con os.environ:
import os
from dotenv import load_dotenv
from flask import Flask
load_dotenv() # lee el archivo .env y carga sus variables
app = Flask(__name__)
app.secret_key = os.environ.get("SECRET_KEY")
DATABASE_URL = os.environ.get("DATABASE_URL")
El load_dotenv() debe ir antes de que uses cualquier variable. Lee el archivo .env y mete sus valores en el entorno, de donde os.environ.get() los recupera.
Un detalle sobre os.environ.get() frente a os.environ[...]: el .get() devuelve None si la variable no existe, mientras que los corchetes lanzan un error. Para valores obligatorios, a veces conviene que falle ruidosamente:
# Falla al arrancar si falta la clave — útil para lo imprescindible
app.secret_key = os.environ["SECRET_KEY"]
Así te enteras de inmediato si olvidaste configurar algo, en vez de que la app arranque rota.
El paso crítico: ignorar .env en Git
Aquí está lo más importante, y lo que la gente olvida. El archivo .env nunca debe subirse al repositorio — si lo subes, no resolviste nada, solo moviste el problema de sitio. Agrégalo a tu .gitignore:
.env
Con esa línea, Git ignora el archivo y jamás lo sube. Tus secretos se quedan solo en tu máquina.
Cómo comparten la configuración otros desarrolladores
Si .env no se sube, ¿cómo sabe otra persona (o tú en otra máquina) qué variables hacen falta? La convención es crear un archivo de ejemplo, .env.example, sí versionado, con las claves pero sin los valores reales:
SECRET_KEY=
DATABASE_URL=
API_TOKEN=
Ese archivo sirve de plantilla: quien clone el proyecto copia .env.example a .env y rellena sus propios valores. Documenta qué se necesita sin filtrar nada.
En producción
En un servidor real (como los que vimos en desplegar Flask gratis), normalmente no subes un archivo .env, sino que defines las variables de entorno directamente en el panel de la plataforma. Tu código no cambia: sigue leyendo con os.environ.get(), y da igual si el valor viene de un .env local o de la configuración del servidor. Ese es justo el punto de las variables de entorno: el mismo código funciona en todos lados, con la configuración de cada sitio.
Resumen
- Secretos y configuración van en un archivo
.env, fuera del código. - Se cargan con
load_dotenv()y se leen conos.environ.get(). .envva siempre en.gitignore— nunca al repositorio.- Un
.env.exampleversionado documenta las claves necesarias sin los valores.
Con esto, tu código queda limpio de credenciales y listo para compartirse sin regalar tus llaves. Es una de esas prácticas que separan un proyecto de juguete de uno hecho con criterio.
¿Quieres manejar configuraciones distintas para desarrollo y producción, o validar que no falte ninguna variable al arrancar? Escríbeme desde contacto y lo cubrimos.