feat: complete CLI, Docker & deployment docs (Step 10.3)
- Add comprehensive CLI tests for seed and serve commands - Create README.md with development setup, deployment guide, and environment variable reference - Mark Step 10.3 as complete in PLAN.md This completes the final implementation step. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
143
README.md
Normal file
143
README.md
Normal file
@@ -0,0 +1,143 @@
|
||||
# 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](https://nixos.org/download.html) with flakes enabled
|
||||
- [direnv](https://direnv.net/) (optional but recommended)
|
||||
|
||||
### Quick Start
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
pytest tests/ -v
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
### Docker
|
||||
|
||||
Build the Docker image using Nix:
|
||||
|
||||
```bash
|
||||
nix build .#dockerImage
|
||||
docker load < result
|
||||
```
|
||||
|
||||
Run the container:
|
||||
|
||||
```bash
|
||||
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:
|
||||
|
||||
```bash
|
||||
-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.
|
||||
Reference in New Issue
Block a user