Google killed Google Trips. TripIt wants your credit card. And shared Google Sheets "trip planners" are just organized suffering. If you've been self-hosting everything else — photos, documents, notes — it never made sense to hand your travel data to someone else. TREK fixes that.
What It Is
TREK is a self-hosted trip planner that runs as a single Docker container. It handles day-by-day itineraries with drag-and-drop, interactive maps, flight and hotel reservations, expense tracking with split calculations, packing lists, weather forecasts, and real-time sync so travel partners see changes the moment you make them. The backend is SQLite — no separate database to manage.
Previously shipped as NOMAD, it was renamed to TREK earlier this year. The project has been moving fast.
Why It's Worth Your Time
Most "self-hosted alternatives" in this space are hobbyist projects that handle the basics and call it done. TREK went further.
The real-time collaboration works over WebSockets. Not polling, not a refresh button — someone adds a restaurant to Day 2 in Tokyo and it appears on your screen immediately.
Maps support both Leaflet with OpenStreetMap (no API key, no cost) and Mapbox GL with 3D buildings and terrain. You can import Google Maps saved lists, KML files, and GPX routes directly. Weather forecasts pull from Open-Meteo — free, no key required.
What actually surprised me: the expense tracker does multi-currency conversion and Splitwise-style settle-up calculations. The "Journey" feature is a proper travel journal with entries, photos, maps, and moods. The "Atlas" view tracks countries you've visited on a world map with stats and streaks.
It installs as a PWA on iOS and Android straight from the browser. No App Store, no TestFlight, no APK sideloading. Open the URL, tap "Add to Home Screen," and it launches fullscreen like a native app.
SSO support is real: Google, Apple, Authentik, Keycloak, or any OIDC provider. 2FA with TOTP and passkeys (WebAuthn). If you've got an existing auth stack, TREK slots in without friction.
Hands On
The fastest way to kick the tires:
ENCRYPTION_KEY=$(openssl rand -hex 32) docker run -d -p 3000:3000 \
-e ENCRYPTION_KEY=$ENCRYPTION_KEY \
-v ./data:/app/data -v ./uploads:/app/uploads \
--name trek --restart unless-stopped \
mauriceboe/trek
Open http://localhost:3000. On first boot, TREK seeds an admin account — set ADMIN_EMAIL and ADMIN_PASSWORD as env vars to choose your credentials, or they'll be printed to the container log (docker logs trek).
For production, the repo includes a Docker Compose setup with hardened security defaults — read-only filesystem, dropped capabilities, tmpfs for /tmp. Here's the important part of it:
services:
app:
image: mauriceboe/trek:latest
container_name: trek
read_only: true
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- CHOWN
- SETUID
- SETGID
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- ENCRYPTION_KEY=${ENCRYPTION_KEY}
- APP_URL=https://trek.yourdomain.com
volumes:
- ./data:/app/data
- ./uploads:/app/uploads
restart: unless-stopped
One thing worth knowing about volumes: only mount ./data and ./uploads. Never mount a volume at /app — it hides the application code shipped in the image and the container won't start. The README is explicit about this, but it's the kind of thing you'd only know to look for after it bites you.
For OIDC/SSO, add these environment variables:
OIDC_ISSUER=https://auth.example.com
OIDC_CLIENT_ID=trek
OIDC_CLIENT_SECRET=supersecret
APP_URL=https://trek.yourdomain.com
APP_URL is required for OIDC to work — it's used as the base for callback URLs. Skip it and the whole auth flow breaks silently.
For the reverse proxy, TREK uses WebSockets for real-time sync. The proxy must handle WebSocket upgrades on /ws. With Nginx that means a separate location block:
location /ws {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 86400;
}
With Caddy, reverse_proxy localhost:3000 handles WebSockets automatically — no extra config needed.
Updates are clean. Your data lives in the mounted volumes and is never touched during a pull:
docker compose pull && docker compose up -d
Honest Verdict
For a project this young, the feature coverage is remarkable. SQLite keeps the operational footprint low — no Postgres to manage, backups are just file copies. The security defaults in the Compose example are better than most mature projects bother to include (read-only filesystem, dropped capabilities — that's not standard for a hobby project).
The rough edges are real. This is still a one-developer project — check the open issues on GitHub before deploying this for a group trip. Some configuration, like OIDC discovery URL overrides, assumes you already know your auth provider well. And at version 3.x, there's no migration path guarantee if a data schema changes under you.
But if you're the kind of person who already self-hosts Immich for photos and Actual Budget for finances, TREK is the obvious next piece. The "why are you still using Google Sheets for this" feeling hits fast.
Go Try It
Start with the one-liner Docker run to kick the tires. Once you decide it's worth keeping, migrate to the full Compose setup with an .env file for your encryption key.
Source: github.com/mauriceboe/TREK