Skip to main content

Environment File Management

To configure the application for different environments, you must manage a .env file and set the ENVIRONMENT variable to control security enforcement and feature toggling.

The application uses the Settings class in backend/app/core/config.py to load and validate these configurations.

Configure the .env File Location

The application is configured to look for a .env file at the project root, which is one level above the backend directory.

Create a file named .env in your project root:

# Project Root
.
├── .env
└── backend/
└── app/
└── core/
└── config.py

The Settings class defines this location in its model_config:

# backend/app/core/config.py

class Settings(BaseSettings):
model_config = SettingsConfigDict(
# Use top level .env file (one level above ./backend/)
env_file="../.env",
env_ignore_empty=True,
extra="ignore",
)

Define Required Environment Variables

For the application to start, you must provide several required variables in your .env file. If these are missing, Pydantic will raise a validation error on startup.

# .env example
PROJECT_NAME="My FastAPI Project"
POSTGRES_SERVER=localhost
POSTGRES_USER=postgres
POSTGRES_PASSWORD=changethis
FIRST_SUPERUSER=admin@example.com
FIRST_SUPERUSER_PASSWORD=changethis

These correspond to the following fields in Settings:

# backend/app/core/config.py

PROJECT_NAME: str
POSTGRES_SERVER: str
POSTGRES_USER: str
FIRST_SUPERUSER: EmailStr
FIRST_SUPERUSER_PASSWORD: str

Handle Environment-Specific Overrides

The ENVIRONMENT variable determines how the application handles security and secrets. It accepts three values: local, staging, or production.

Local Development

In local mode (the default), using default secrets like "changethis" will only trigger a warning.

ENVIRONMENT=local
SECRET_KEY=changethis

Staging and Production

In staging or production, the application enforces strict security. If SECRET_KEY, POSTGRES_PASSWORD, or FIRST_SUPERUSER_PASSWORD are set to "changethis", the application will raise a ValueError and fail to start.

# backend/app/core/config.py

def _check_default_secret(self, var_name: str, value: str | None) -> None:
if value == "changethis":
message = (
f'The value of {var_name} is "changethis", '
"for security, please change it, at least for deployments."
)
if self.ENVIRONMENT == "local":
warnings.warn(message, stacklevel=1)
else:
raise ValueError(message)

Configure CORS Origins

You can manage allowed CORS origins via the BACKEND_CORS_ORIGINS variable. The parse_cors utility allows you to provide these as either a JSON-formatted list or a comma-separated string.

Using a Comma-Separated String

BACKEND_CORS_ORIGINS="http://localhost:3000,https://app.example.com"

Using a JSON List

BACKEND_CORS_ORIGINS='["http://localhost:3000", "https://app.example.com"]'

The Settings class automatically combines these with the FRONTEND_HOST to create the final list used by the FastAPI middleware:

# backend/app/core/config.py

@computed_field
@property
def all_cors_origins(self) -> list[str]:
return [str(origin).rstrip("/") for origin in self.BACKEND_CORS_ORIGINS] + [
self.FRONTEND_HOST
]

Troubleshooting

Application Fails to Start in Production

If you see a ValueError regarding "changethis", ensure you have updated your secrets in the .env file or environment variables:

ValueError: The value of SECRET_KEY is "changethis", for security, please change it, at least for deployments.

Solution: Update your .env file with secure values:

ENVIRONMENT=production
SECRET_KEY=your-actual-secure-random-secret-key
POSTGRES_PASSWORD=your-secure-db-password
FIRST_SUPERUSER_PASSWORD=your-secure-admin-password

Database Connection Issues

The SQLALCHEMY_DATABASE_URI is automatically constructed from individual POSTGRES_* variables. If the connection fails, verify these specific variables:

# backend/app/core/config.py

@computed_field
@property
def SQLALCHEMY_DATABASE_URI(self) -> PostgresDsn:
return PostgresDsn.build(
scheme="postgresql+psycopg",
username=self.POSTGRES_USER,
password=self.POSTGRES_PASSWORD,
host=self.POSTGRES_SERVER,
port=self.POSTGRES_PORT,
path=self.POSTGRES_DB,
)

Ensure POSTGRES_PORT is an integer (defaults to 5432) and POSTGRES_SERVER is a valid host.