Configuration
Environment variables
There is no .env file to create. Everything below has a working default and is set inline in docker-compose.yml, where you can see it in context.
| Variable | Default | Description |
|---|---|---|
PORT | 3001 | Port the Express server listens on |
NODE_ENV | development | Set to production for production builds |
DB_PATH | data/homepage.db | Database location; the data directory is derived from it |
DOCKER_HOST | — | tcp://… address of a Docker socket proxy. Preferred over DOCKER_SOCKET — see Docker deployment |
DOCKER_SOCKET | /var/run/docker.sock | Direct socket path, used only when DOCKER_HOST is unset |
CORS_ORIGINS | empty | Extra origins allowed to call the API cross-origin, comma separated. Empty means same-origin only |
TRUST_PROXY | true | Read the client address from X-Forwarded-For. Set false only when there is no reverse proxy |
HOMEPAGE_SECRET_KEY_FILE | — | Path to a file holding the credential encryption key. See below |
HOMEPAGE_SECRET_KEY | — | The key itself, as 64 hex characters. See below |
Widget credentials are not environment variables
Every integration — Jellyfin, Weather, Umami, the rest — takes its credentials in the widget's own settings under Settings → Widgets, and the server stores them encrypted. There are no environment variables for them, and the old JELLYFIN_API_KEY / WEATHER_API_KEY fallbacks have been removed.
The credential encryption key
By default the key is generated into your data directory on first run and needs no configuration at all. Back it up with the database — losing it means re-entering every widget credential.
To keep it out of the data directory, the server checks these in order, and the first one it finds wins:
/run/secrets/homepage_secret_key— where Docker and Podman mount a secret of that name. Declared indocker-compose.yml, so no environment variable is involved.HOMEPAGE_SECRET_KEY_FILE— any other path. The variable holds a path rather than the secret, so it is safe to write into a committed compose file.HOMEPAGE_SECRET_KEY— the key itself, for setups that prefer it.- The generated
data/.encryption-key.
Separating the key buys one thing: it protects a database file that travels without the rest of the data directory — an old snapshot, a copy pulled out for debugging. Credentials are already kept out of API responses, backup exports and git regardless of where the key lives.
Application settings
These are stored in the database (data/homepage.db) and are editable through the Settings panel.
| Setting | Description |
|---|---|
| Homepage title | Browser tab title and displayed heading |
| Username | Displayed in the header greeting |
| Favicon | Custom favicon (upload via Settings → Preferences) |
| App logo | Custom logo displayed in the header next to the title (upload via Settings → Preferences) |
| Clock format | 12h or 24h |
| Temperature unit | C (Celsius) or F (Fahrenheit) |
| Theme | Active theme ID |
| Compact header | Reduces header height |
| Header widgets | Pin a widget (e.g. Search, Weather) to the left, centre, or right of the header |
| Bookmark category colour | primary, rainbow, or a fixed colour |
Database
The SQLite database is created at data/homepage.db on first run. It stores:
- Widget configurations and positions
- Bookmarks and categories
- Application settings
- Themes (built-in + custom)
- Keybindings
- Backup settings
Backup & restore
Go to Settings → Backup to:
- Create a manual backup (downloads a
.dbfile) - Configure automatic scheduled backups
- Restore from a previous backup
In Docker, mount the data/ directory as a volume so the database persists across container restarts:
volumes:
- ./data:/app/data