Self-hosted inventory, documentation and operations cockpit for model railway collections.
RailKeeper is a complete self-hosted application for managing model railway vehicles, decoder data, images, documents, maintenance, exhibition lists and imports in one local-first workspace. It runs as a single Go service with an integrated React frontend and stores all operational data in SQLite.
The project is designed for private collections, clubs and small workshops that want a serious inventory system without a cloud dependency. RailKeeper keeps data, uploads and backups under your control while still offering modern workflows such as article web search, structured import review, ECoS readout and release update checks.
- Local-first inventory with SQLite, uploads and JSON backups
- Vehicle records with model data, technical fields, ownership details, images, attachments, QR codes and clean read-only detail views
- Article data web search with configurable sources, barcode/EAN entry, ZXing-based camera scanning and explicit field-by-field review
- PDF report dialog for inventory overview and detail lists with selectable vehicles, QR codes and images
- Responsive inventory workflow with mobile-optimized dialogs, filter controls and camera fallback for barcode entry
- ECoS live connection with locomotive/CV readout, import handoff into vehicle creation and external ID preparation
- Decoder function mapping from F0 to F31 with symbol library and stored SVG/PNG graphics
- Structured CV values, CV import/export, decoder profiles, NMRA CV8 manufacturer master data and ESU/LokProgrammer file metadata
- Maintenance, condition history and searchable documentation per vehicle
- Exhibition lists with lock state, dedicated Messe role and print-ready list views
- Local authentication with first-run setup including email, roles, sessions, password change, token-based password reset and audit log
- User-specific sidebar order and visibility for tailoring the main navigation per login
- Master data management for manufacturers, gauges, epochs, categories, subtypes, railway companies and symbols
- Docker Compose deployment with hardened runtime container and persistent
/datavolume - Built-in GitHub release update check with release notes and user-controlled installation flow
RailKeeper is built around operational views instead of marketing pages:
- Overview for inventory, value, maintenance and data quality
- Inventory for vehicle search, filtering, read views, reports, editing, uploads, CVs and function keys
- Exhibition List for fair/show operations
- Import/Export for CSV, TSV, XML and JSON imports, controlled updates and ECoS readout
- Settings for master data, appearance, backups, updates and authentication
git clone https://github.com/ichwars/RailKeeper2.git
cd RailKeeper2
docker compose pull
docker compose up -dOpen:
http://localhost:8080
On first start RailKeeper opens the setup screen. Create the first admin account there. No default credentials are shipped.
git pull
docker compose pull
docker compose up -dThe SQLite database, uploads and local files stay in the railkeeper2_data Docker volume.
To pin a specific release instead of latest, set this in .env:
RAILKEEPER_IMAGE=ghcr.io/ichwars/railkeeper2:v0.1.9If you intentionally want to build the checked-out source tree, use:
docker compose up -d --buildCopy .env.example to .env only when you want to override operational settings such as secure cookies, upload limits, printer configuration or the GitHub release endpoint.
Do not override these container paths in Docker Compose:
RAILKEEPER_DATA_DIR=/data
RAILKEEPER_MIGRATIONS_DIR=/app/migrations
RAILKEEPER_SEEDS_DIR=/app/seeds
RAILKEEPER_STATIC_DIR=/app/webBackend:
cd backend
go test ./...
go run ./cmd/railkeeperFrontend:
cd frontend
npm ci
npm run buildThe production runtime serves the built frontend from frontend/dist.
Useful local defaults:
RAILKEEPER_ADDR=:8080
RAILKEEPER_DATA_DIR=./data
RAILKEEPER_MIGRATIONS_DIR=./backend/migrations
RAILKEEPER_SEEDS_DIR=./backend/seeds
RAILKEEPER_STATIC_DIR=./frontend/dist
RAILKEEPER_COOKIE_SECURE=false
RAILKEEPER_UPDATE_CHECK_URL=https://api.github.com/repos/ichwars/RailKeeper2/releases/latestOptional SMTP settings for password reset emails can be configured in the Admin UI under
Einstellungen > Authentifizierung > SMTP für Passwort-Reset. The environment variables
below remain useful as deployment defaults:
RAILKEEPER_PUBLIC_URL=https://railkeeper.example.test
RAILKEEPER_SMTP_HOST=smtp.example.test
RAILKEEPER_SMTP_PORT=587
RAILKEEPER_SMTP_USER=railkeeper@example.test
RAILKEEPER_SMTP_PASSWORD=change-me
RAILKEEPER_SMTP_FROM=railkeeper@example.test
RAILKEEPER_SMTP_TLS=starttlsIf SMTP is not configured, password reset links are not returned to the browser. For local recovery only, the backend writes the link to the server log.
backend/
cmd/railkeeper/ Go entrypoint
internal/api/ HTTP routes, middleware and response mapping
internal/application/ use cases, validation, backup and transactions
internal/infrastructure/ SQLite, migrations and seed loading
migrations/ SQLite schema migrations
seeds/ master data seed JSON
frontend/
src/app/ shell, routing and global styles
src/features/ setup, auth, vehicles, exhibition, import/export, settings
src/shared/ API adapter, i18n and shared frontend types
openapi/
railkeeper.yaml API contract
deploy/
README.md deployment notes
docs/
architecture.md
production-runbook.md
roadmap.md
security.md
RailKeeper is intended for trusted self-hosted environments, but the default installation avoids the common mistakes:
- no default admin account
- Argon2id password hashing
- HTTP-only session cookies
- SameSite cookies and CSRF protection
- role checks for viewer, editor, admin and Messe workflows
- setup, login and session rate limiting
- password reset links are sent by email when SMTP is configured
- audit log for relevant security and data actions
- upload size limits and executable attachment blocking
- runtime data ignored by Git
For HTTPS deployments set:
RAILKEEPER_COOKIE_SECURE=trueThe README includes a GitHub release download badge. GitHub does not provide a reliable public README view counter or generic install counter for self-hosted Docker deployments. Those would require third-party tracking, package registry metrics or explicit opt-in telemetry, none of which is enabled by RailKeeper.
RailKeeper is released under the MIT Self-Hosting License. See LICENSE.md.
If RailKeeper saves you time, coffee is a perfectly acceptable bug fuel:

