diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index f15a460..d7bc538 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -10,7 +10,7 @@ permissions: packages: write env: - IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/server-verwaltung + IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/fleetledger jobs: build: diff --git a/README.md b/README.md index b3be38b..dbecac2 100644 --- a/README.md +++ b/README.md @@ -1,64 +1,83 @@ # FleetLedger -Self-hosted Übersicht für gemietete Server (VPS, Dedizierte, Storage, Managed). Mehrnutzerfähig, Dark-Mode-first und PWA-ready. +Self-hosted overview for rented servers (VPS, dedicated, storage, managed). Multi-user, dark-mode first, PWA-ready. ## Features -- Server-CRUD pro Benutzer, Soft-Delete/Archiv -- Dashboard (Kosten, ablaufende Verträge) + Admin-Gesamtübersicht -- Map-Ansicht pro Nutzer auf Basis der Location-Namen (Leaflet) -- Optional verschlüsselte Speicherung von Management-Passwörtern (Fernet) -- Session-Auth mit CSRF-Schutz, Admin-Rolle -- PWA: Manifest, Service Worker, installierbar +- Server CRUD per user with soft delete/archiving +- Dashboard (costs, expiring contracts) and admin-wide overview +- Map view per user (Leaflet) based on location names +- Optional encrypted storage of management passwords (Fernet) +- Session auth with CSRF protection, admin role +- PWA: manifest, service worker, installable ## Stack - FastAPI, SQLModel, Jinja2 -- SQLite (Standard), Passlib (bcrypt), Cryptography (Fernet) -- Tailwind via CDN, Leaflet für Karte -- Uvicorn als ASGI-Server +- SQLite (default), Passlib (bcrypt), Cryptography (Fernet) +- Tailwind via CDN, Leaflet for maps +- Uvicorn as ASGI server -## Schnellstart mit Docker -1. Repository klonen - ```bash - git clone https://example.com/your/fleetledger.git - cd fleetledger - ``` -2. Umgebung setzen - ```bash - cp .env-example .env - # SESSION_SECRET in .env auf einen starken, einzigartigen Wert setzen - ``` -3. Starten - ```bash - docker-compose up --build - ``` - Die SQLite-DB liegt in `./data/` (Bind-Mount in den Container unter `/app/data/fleetledger.db`). +## Containers and Images +- Public repo: `https://github.com/nocci-sl/fleetledger`. +- Prebuilt image on GHCR: `ghcr.io/nocci-sl/fleetledger:latest` (plus commit-tagged `ghcr.io/nocci-sl/fleetledger:`). + - Pull directly with `docker pull ghcr.io/nocci-sl/fleetledger:latest`. -## Lokale Entwicklung (ohne Docker) -- Voraussetzungen: Python 3.12, virtualenv empfohlen. -- Setup: - ```bash - python -m venv .venv - source .venv/bin/activate - pip install -r requirements.txt - cp .env-example .env - export SESSION_SECRET="ein_langer_random_wert" - export SESSION_COOKIE_SECURE=0 # nur lokal ohne HTTPS - uvicorn app.main:app --reload --port 8000 - ``` +## Quickstart with Docker Compose (prebuilt image) +Use the published GHCR image; no local build needed. +```bash +cp .env-example .env +# set SESSION_SECRET in .env to a strong random value -## Umgebungsvariablen -- `SESSION_SECRET` (erforderlich): Langer, zufälliger String für die Session-Signierung. -- `SESSION_COOKIE_SECURE` (default `1`): Auf `0` nur für lokale HTTP-Tests setzen, sonst `1` (HTTPS). -- `DATABASE_PATH` (default `/app/data/fleetledger.db` im Docker-Image): Pfad zur SQLite-Datei. Lokal z. B. `./data/fleetledger.db`. -- `ENCRYPTION_KEY` (optional): Fernet-Key für verschlüsselte Management-Passwörter. Leer lassen, wenn keine Speicherung gewünscht ist. -- `ALLOW_SELF_REGISTRATION` (default `0`): `1` erlaubt neue Selbst-Registrierungen auch wenn schon ein Admin existiert; `0` = nur Admin darf weitere User anlegen. +cat > docker-compose.override.yml <<'EOF' +services: + fleetledger: + image: ghcr.io/nocci-sl/fleetledger:latest + environment: + SESSION_SECRET: ${SESSION_SECRET:?set in .env} + SESSION_COOKIE_SECURE: ${SESSION_COOKIE_SECURE:-1} + ENCRYPTION_KEY: ${ENCRYPTION_KEY:-} + ALLOW_SELF_REGISTRATION: ${ALLOW_SELF_REGISTRATION:-0} + volumes: + - ./data:/app/data +EOF -## Sicherheitshinweise -- Immer einen starken `SESSION_SECRET` verwenden; im Docker-Setup wird der Start verweigert, wenn ein Platzhalter genutzt wird. -- Produktiv hinter HTTPS betreiben (`SESSION_COOKIE_SECURE=1`). -- Management-Passwörter nur mit gesetztem `ENCRYPTION_KEY` speichern; ohne Key werden sie nicht persistiert. -- CSRF-Schutz ist aktiv für Form-POSTs; Browser-Service-Worker cached Assets versioniert. +docker-compose up -d +``` +SQLite will live on the host in `./data/fleetledger.db`. -## Datenhaltung -- SQLite speichert die Daten in einer Datei (`DATABASE_PATH`). In Docker wird `./data/` aus dem Host eingebunden. -- Backups: Einfach die SQLite-Datei in `./data/` sichern, während der Dienst gestoppt ist. +## Quickstart with Docker (build locally) +```bash +cp .env-example .env +# set SESSION_SECRET in .env +docker build -t fleetledger:local . +mkdir -p data +docker run --rm -p 8000:8000 --env-file .env -v $(pwd)/data:/app/data fleetledger:local +``` + +## Local development (without Docker) +Requirements: Python 3.12, virtualenv recommended. +```bash +python -m venv .venv +source .venv/bin/activate +pip install -r requirements.txt +cp .env-example .env +export SESSION_SECRET="long_random_value" +export SESSION_COOKIE_SECURE=0 # only for local HTTP +uvicorn app.main:app --reload --port 8000 +``` + +## Environment variables +- `SESSION_SECRET` (required): long random string for session signing. +- `SESSION_COOKIE_SECURE` (default `1`): set `0` only for local HTTP; keep `1` with HTTPS. +- `DATABASE_PATH` (default `/app/data/fleetledger.db`): SQLite file path; locally e.g. `./data/fleetledger.db`. +- `ENCRYPTION_KEY` (optional): Fernet key for encrypted management passwords. Leave empty to disable persistence of these passwords. +- `ALLOW_SELF_REGISTRATION` (default `0`): `1` allows new self-registrations even if an admin exists; `0` means only admin can create users. + +## Security notes +- Always use a strong `SESSION_SECRET`; the container refuses to start with a placeholder. +- Run behind HTTPS (`SESSION_COOKIE_SECURE=1`). +- Only store management passwords if `ENCRYPTION_KEY` is set. +- CSRF protection is enabled for form POSTs; service worker caches assets with versioning. + +## Data +- SQLite stores data in the file at `DATABASE_PATH`. In Docker, `./data/` on the host is mounted to `/app/data/` in the container. +- Backups: copy the SQLite file in `./data/` while the service is stopped.