Self-hosted inventory, documentation and operations cockpit for model railway collections.
English · Deutsch · Documentation
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.
The handbook brings together complete user, operator, and developer guidance, with coverage tracked against the project sources in both English and German.
- Responsive operations dashboard with inventory, value, maintenance, data-quality and command-station status in one view
- Profile-based import and export for vehicles, accessories and exhibition lists, including previews, conflict resolution, persistent jobs, transfer history and local artifacts. Master data remains exclusively under Settings.
- Dedicated command-station workspace with configured stations, locomotive comparison, live status, diagnostics and preview-before-write synchronization
- Persistent exhibition operations with events, participants, multi-day vehicle assignments, readiness checks, conflict handling, images, function keys, printing and list locking
- 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 inventory with generated inventory numbers, sortable selection-first overview, quantity or individual tracking, storage-location stock, reservations, installations, documents and usage history
- Layout, module, setup and plan-revision foundation with version-conflict protection; the workspace remains temporarily hidden from the main navigation while it is refined
- Article data web search with configurable sources, barcode/EAN entry, ZXing-based camera scanning, typed track details, 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
- Reviewed ECoS locomotive exchange reads locomotive data, CV values, and static function keys, then writes name, address, and protocol only after preview and confirmation. It does not monitor speed, direction, active function states, or ECoS layout object managers. CS3 reads name, address, and protocol into the comparison workspace without writing. Z21 and Intellibox 3 remain connection and diagnostic adapters.
- 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
- 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 responsive operational workspaces instead of marketing pages. The screens below show the current English interface and focus on the newest workflows:
| Responsive overview | Profile-based import/export |
|---|---|
![]() |
![]() |
| Command stations | Exhibition operations |
![]() |
![]() |
Additional detailed workflows:
| Article Web Search | Spare Parts Search | Decoder Speed Curve |
|---|---|---|
![]() |
![]() |
![]() |
- Overview for inventory, value, maintenance, data quality and command-station status
- Inventory for vehicle search, filtering, read views, reports, editing, uploads, CVs and function keys
- Accessories for article-data and barcode search, sortable inventory data, stock, reservations, installations, documents and history
- Exhibition for persistent events, participants, operating days, readiness and conflicts
- Import/Export for reusable profiles and controlled vehicle, accessory and exhibition-list transfers
- Command stations for read, comparison, diagnostics, live monitoring and confirmed writes
- Settings for master data, appearance, backups, updates and authentication
Download the Windows x64 ZIP from a release, extract it completely and start:
start-railkeeper.bat
RailKeeper runs locally without additional software. By default, persistent data is stored outside
the replaceable program folder at %LOCALAPPDATA%\RailKeeper\data. The ZIP deliberately contains
no database, uploads, backups, or data directory. Replacing the extracted program folder therefore
does not replace the active user data.
On the first start after an older Portable or Standalone version, RailKeeper copies a legacy data
folder beside RailKeeper.exe into the safe location and retains the source unchanged. If both
locations contain different databases, startup stops on a local safety page and changes neither
copy. The active absolute path and the retained migration source are visible to administrators under
Settings. Set RAILKEEPER_DATA_DIR only when an explicit alternative is required. A path inside the
program folder or on removable media can still be lost when that location is deleted or replaced.
External backups remain necessary.
When Windows Standalone detects a newer release under Settings > General > Updates, the button names the available version and starts the matching GitHub ZIP download. RailKeeper does not extract, install, replace, or restart anything. Create a backup, close RailKeeper, extract the downloaded ZIP into a new program folder, and verify the displayed data path and inventory after starting it. If no trusted matching ZIP is available, use the linked GitHub release page instead.
git clone https://github.com/ichwars/RailKeeper.git
cd RailKeeper
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 railkeeper_data Docker volume.
To pin a specific release instead of latest, set this in .env:
RAILKEEPER_IMAGE=ghcr.io/ichwars/railkeeper:v0.1.20.4If 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.
Create a Windows Standalone package:
.\tools\build_windows_standalone.ps1The script builds the frontend, cross-compiles RailKeeper.exe for Windows x64, rejects any user-data
content in the staged tree and ZIP, and creates
dist\windows-standalone\RailKeeper-windows-x64-v<version>.zip.
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/RailKeeper/releases/latest
RAILKEEPER_TRUSTED_PROXY_CIDRS=Optional 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=starttlsPassword-reset emails are sent only when RAILKEEPER_PUBLIC_URL or the public URL stored in the
Admin UI is a valid HTTP(S) origin. RailKeeper never derives emailed reset links from the request
Host header.
If SMTP is not configured, password reset links are neither returned to the browser nor written to the server log. An administrator must configure SMTP before the reset flow can deliver a link.
RailKeeper reads text-based PDF spare-parts lists directly. For scanned PDFs without a text layer,
install either ocrmypdf or both pdftoppm and tesseract on the host and keep the tools available
in PATH. The OCR fallback is used only when the built-in PDF text extraction does not find usable
spare-parts text.
RAILKEEPER_PDF_OCR=on
RAILKEEPER_PDF_OCR_MAX_PAGES=4Set RAILKEEPER_PDF_OCR=off to disable the fallback explicitly.
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, digital centers, 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
- image dimension limits of 12,000 pixels per side and 40 megapixels before decoding
- 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 AGPL-3.0-only. See LICENSE.md.
RailKeeper is a local, self-hosted application. AGPL-3.0 keeps modifications open and requires an operator of a modified version offered over a network to provide its users access to the corresponding source code. This protects the project's long-term openness more effectively than the former permissive license. AGPL permits commercial use. Versions already published under the former license retain the terms under which they were released.
The software license does not grant rights to project identifiers or third-party trademarks, graphics, documentation, or protocol rights. See TRADEMARKS.md and THIRD_PARTY_NOTICES.md.
Voluntary tips help cover development and project-related costs. They do not provide paid features, support entitlements, response times, or special access.
Support channels and boundaries are documented in SUPPORT.md.







