sub-aligator/README.md
SW 6e24ce541a feat: rename to SUB-ALIGATOR, dark theme, pool deletion, header nav
- Rename app title to SUB-ALIGATOR (header, page titles, exports, README)
- Add dark amber-terminal theme with a header toggle, persisted in localStorage
- Add pool deletion (soft delete): allocations are kept in history and
  block the address space again when the same or an overlapping pool is
  re-added (re-enable on exact CIDR match, re-attach contained allocations)
- Reject new pools that overlap an enabled pool
- Move Home link into the page header, keep other links in the footer
- Load app.js globally via base template, add theme.js (CSP-safe, no inline JS)
2026-10-01 18:00:32 +02:00

173 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# SUB-ALIGATOR
A simple internal web application for tracking and automatically allocating IPv4 subnets.
## Purpose
This application is intended solely for internal tracking and automatic allocation of IPv4 subnets. It is not a general IPAM, monitoring tool, device inventory, VLAN manager, or network topology viewer.
It is designed to run only inside a LAN/VPN. **The application does not include authentication** and must be placed behind a firewall/reverse proxy in a trusted network.
## Features
- Manage one or more IP pools manually through the web UI.
- First-run setup wizard: create the first pool before allocating subnets.
- Automatic subnet allocation using a **first-fit** algorithm for prefixes /20 through /30.
- Atomic allocation writes using SQLite `BEGIN IMMEDIATE` transactions.
- Retro TUI/terminal-style web UI, server-side rendered with Askama.
- Dynamic preview of the next free subnet via HTMX.
- Allocation history with filtering, search, and pagination.
- Release subnets (status `released`) with a mandatory note, directly from the history table or detail page.
- Released subnets free up address space and can be reused by the first-fit algorithm.
- Delete pools without losing their allocations: the subnets stay in history and keep blocking the address range if the same or an overlapping pool is added again.
- Light and dark (amber terminal) theme, switchable in the page header and remembered per browser.
- Audit log of all operations.
- Markdown, CSV, and JSON exports.
- SQLite migrations run automatically on startup.
- Backup and restore scripts.
## Architecture
- **Rust** edition 2024
- **Axum** + **Tokio**
- **SQLx** with **SQLite**
- **Askama** for HTML templates
- **HTMX** from a local static file
- Custom CSS without external frameworks
- CIDR/IP calculations using `ipnet`
## Quick start
```bash
cd sub-aligator
cp .env.example .env
docker compose up -d --build
```
Open a browser at:
```
http://SERVER_IP:8080
```
On first launch you will be asked to create the first pool. The default port can be changed in `.env` via the `APP_PORT` variable.
## Persistent data
Docker Compose creates local directories:
- `./data` – SQLite database
- `./exports` – generated exports (Markdown, CSV, JSON)
- `./backups` – database backups
These directories are bind-mounted into the container, so data persists even if the container is removed.
## Backup and restore
### Backup
```bash
./scripts/backup.sh
```
The script creates a consistent database backup using `sqlite3 .backup` with a UTC timestamp in the filename. Backups are stored in `./backups`.
### Restore
```bash
./scripts/restore.sh ./backups/subnet-allocator.db.20240930T120000Z.backup
```
**Warning:** restore overwrites the current database. Stop the container and back up the current state before restoring.
### Automating backups
On the host you can use a systemd timer or cron. Example cron entry:
```cron
0 2 * * * /path/to/sub-aligator/scripts/backup.sh >> /var/log/subnet-allocator-backup.log 2>&1
```
## Exports
After every successful allocation or release, read-only exports are regenerated:
- `/app/exports/allocations.md`
- `/app/exports/allocations.csv`
- `/app/exports/allocations.json`
They are also available for download via endpoints:
- `GET /exports/allocations.md`
- `GET /exports/allocations.csv`
- `GET /exports/allocations.json`
The Markdown export contains a separate section for each pool with a table of active and reserved allocations. CSV and JSON include all allocations, including released ones.
## Security notes
- The application **has no authentication**. Use it only behind a VPN/LAN/firewall.
- CSRF tokens are required for POST forms.
- Security headers are set: `X-Content-Type-Options`, `X-Frame-Options`, `Referrer-Policy`, `Content-Security-Policy`.
- The application has no default Internet exposure; port binding is handled by Docker Compose.
- `/healthz` returns only `{"status":"ok"}`.
## Adding authentication later via Caddy + Authentik
The application is prepared for authentication through a trusted reverse proxy. The function `get_actor_from_request()` in `src/audit.rs` currently returns `local`, but can be updated to read a header such as `X-Authentik-Username`.
Example Caddy configuration with Authentik:
```caddy
subnet.example.com {
reverse_proxy /outpost.goauthentik.io/* http://authentik:9000
forward_auth http://authentik:9000 {
uri /outpost.goauthentik.io/auth/caddy
copy_headers X-Authentik-Username X-Authentik-Groups X-Authentik-Email
}
reverse_proxy subnet-allocator:8080
}
```
After updating `get_actor_from_request()`, the audit log will record the real user.
## First-fit allocation example
1. First request `/30` receives `10.91.0.0/30`.
2. Next request `/24` receives `10.91.1.0/24` (avoids the occupied `/30`).
3. Another request `/30` fills the gap and receives `10.91.0.4/30`.
The algorithm always respects CIDR alignment and finds the first free space large enough.
## Endpoints
- `GET /` – main page
- `GET /healthz` – healthcheck
- `GET /setup` – first-run pool setup
- `GET /pools` – pool management
- `POST /pools/new` – create a new pool
- `GET /partials/pools/{slug}/preview?prefix_length=24` – HTMX preview
- `POST /allocations` – create an allocation
- `GET /allocations/{id}` – allocation detail
- `POST /allocations/{id}/release` – release an allocation
- `GET /exports/allocations.{md,csv,json}` – exports
## Troubleshooting
### Container does not start
```bash
docker compose logs -f subnet-allocator
```
### Database is locked
If the process terminates unexpectedly, a `-wal` or `-shm` file may remain. Stop the container and check `./data`.
### Exports are not generated
Check the permissions of the `./exports` directory and the `APP_EXPORTS_DIR` variable.
## Licence
MIT. See the `LICENSE` file.