Petru Paler 37300c00c6 chore: use ppetru as dev mode username
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 12:43:36 +00:00
2025-12-31 20:08:20 +00:00
2025-12-26 12:55:55 +00:00

AnimalTrack

Event-sourced animal tracking for poultry farm management. Built with FastHTML, MonsterUI, and SQLite.

Features

  • Egg Collection - Quick capture of daily egg counts by location
  • Feed Tracking - Record purchases and distribution with cost tracking
  • Animal Registry - Track cohorts, movements, and lifecycle events
  • Historical Queries - Point-in-time resolution using interval projections
  • Event Sourcing - Full audit trail with edit/delete support

Development Setup

Prerequisites

  • Nix with flakes enabled
  • direnv (optional but recommended)

Quick Start

# Clone the repo
git clone <repo-url>
cd animaltrack

# Enter dev environment
direnv allow  # or: nix develop

# Run the server
animaltrack serve

The server starts at http://localhost:3366 (3366 = EGG in leetspeak).

CLI Commands

# Run database migrations
animaltrack migrate

# Load seed data (users, locations, species, products, feed types)
animaltrack seed

# Start the web server
animaltrack serve [--port 3366] [--host 0.0.0.0]

# Create a new migration
animaltrack create-migration "add users table"

Running Tests

pytest tests/ -v

Deployment

Docker

Build the Docker image using Nix:

nix build .#dockerImage
docker load < result

Run the container:

docker run -d \
  -p 8080:3366 \
  -v /data/animaltrack:/var/lib/animaltrack \
  -e CSRF_SECRET="your-secret-here" \
  -e TRUSTED_PROXY_IPS="10.0.0.1,10.0.0.2" \
  gitea.v.paler.net/ppetru/animaltrack:latest

Environment Variables

Variable Required Default Description
CSRF_SECRET Yes - Secret for CSRF token generation
DB_PATH No animaltrack.db SQLite database path
PORT No 3366 Server port
AUTH_HEADER_NAME No X-Oidc-Username Header containing username from reverse proxy
TRUSTED_PROXY_IPS No (empty) Comma-separated IPs that can set auth headers
CSRF_COOKIE_NAME No csrf_token CSRF cookie name
SEED_ON_START No false Run seeds on startup
LOG_LEVEL No INFO Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
METRICS_ENABLED No true Enable Prometheus metrics at /metrics
DEV_MODE No false Bypasses auth, sets default user for development
BASE_PATH No / URL base path for reverse proxy setups

Reverse Proxy Configuration

AnimalTrack expects authentication to be handled by a reverse proxy (e.g., Authelia, Authentik, oauth2-proxy). The proxy should:

  1. Authenticate users via OIDC/OAuth2
  2. Forward the username in X-Oidc-Username header (configurable via AUTH_HEADER_NAME)
  3. Be listed in TRUSTED_PROXY_IPS to be trusted

Example Caddy configuration:

animaltrack.example.com {
    forward_auth authelia:9091 {
        uri /api/verify?rd=https://auth.example.com
        copy_headers Remote-User Remote-Groups Remote-Email
        header_up X-Oidc-Username {http.auth.resp.Remote-User}
    }
    reverse_proxy animaltrack:3366
}

Data Persistence

Mount a volume to /var/lib/animaltrack for the SQLite database:

-v /path/on/host:/var/lib/animaltrack

The database file will be created at $DB_PATH (default: /var/lib/animaltrack/animaltrack.db in Docker).

Health Check

  • GET /healthz - Returns 200 if database is writable, 503 otherwise
  • GET /metrics - Prometheus metrics (when METRICS_ENABLED=true)

Architecture

  • Event Sourcing - All state changes are events. Events are immutable.
  • Projections - Materialized views updated synchronously in transactions.
  • Interval Tables - Track animal locations, tags, and attributes over time.
  • ULID IDs - Time-ordered, sortable, unique identifiers.
  • Integer Timestamps - Milliseconds since Unix epoch for all timestamps.
  • Integer Money - All prices stored as cents for precision.

License

Proprietary - All rights reserved.

Description
No description provided
Readme 1.3 MiB
Languages
Python 99.3%
Nix 0.6%
JavaScript 0.1%