Detach DB queries from HTTP request context so HTMX polling doesn't cancel in-flight queries when the browser aborts previous XHRs. Add indexes on login_attempts and sessions to speed up frequent dashboard queries. Bump version to 0.17.1. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Oubliette
An SSH honeypot that logs login attempts, presents fake shells to "successful" logins, and tries to detect when a real human is poking around.
Named after the medieval dungeon - a place you throw people into and forget about them.
Status
Early development. See PLAN.md for the roadmap.
Usage
Build
# With Nix
nix build
# With Go
nix develop -c go build ./cmd/oubliette
Configure
Copy and edit the example config:
cp oubliette.toml.example oubliette.toml
Key settings:
ssh.listen_addr— listen address (default:2222)ssh.host_key_path— Ed25519 host key, auto-generated if missingauth.accept_after— accept login after N failures per IP (default10)auth.credential_ttl— how long to remember accepted credentials (default24h)auth.static_credentials— always-accepted username/password pairs (optionalshellfield routes to a specific shell)- Available shells:
bash(fake Linux shell),fridge(Samsung Smart Fridge OS),banking(80s-style bank terminal TUI),adventure(Zork-style text adventure dungeon),cisco(Cisco IOS CLI with mode state machine and command abbreviation),psql(PostgreSQL psql interactive terminal),roomba(iRobot Roomba vacuum robot),tetris(Tetris game TUI) shell.username_routes— map usernames to specific shells (e.g.postgres = "psql"); credential-specific shell overrides take prioritystorage.db_path— SQLite database path (defaultoubliette.db)storage.retention_days— auto-prune records older than N days (default90)storage.retention_interval— how often to run retention (default1h)shell.hostname— hostname shown in shell prompts (defaultubuntu-server)shell.banner— banner displayed on connectionshell.fake_user— override username in prompt; empty uses the authenticated userweb.enabled— enable the web dashboard (defaultfalse)web.listen_addr— web dashboard listen address (default:8080)- Dashboard includes Chart.js charts (attempts over time, hourly pattern), an SVG world map choropleth colored by attack origin, and filter controls for date range / IP / country / username
- Session detail pages at
/sessions/{id}include terminal replay via xterm.js
web.metrics_enabled— expose Prometheus metrics at/metrics(defaulttrue)web.metrics_token— bearer token to protect/metrics; empty means no auth (default empty)detection.enabled— enable human detection scoring (defaultfalse)detection.threshold— score threshold (0.0–1.0) for flagging sessions (default0.6)detection.update_interval— how often to recompute scores (default5s)notify.webhooks— list of webhook endpoints for notifications (see example config)
GeoIP
Country-level GeoIP lookups are embedded in the binary using the DB-IP Lite database (CC-BY-4.0). The dashboard shows country alongside IPs and includes a "Top Countries" table.
For local development, run scripts/fetch-geoip.sh to download the MMDB file. The Nix build fetches it automatically.
Run
./oubliette -config oubliette.toml
Test with:
ssh -o StrictHostKeyChecking=no -p 2222 root@localhost
SSH exec commands (ssh user@host <command>) are also captured and stored on the session record.
NixOS Module
Add the flake as an input and enable the service:
{
services.oubliette = {
enable = true;
package = inputs.oubliette.packages.${system}.default;
settings = {
ssh.listen_addr = ":2222";
auth.accept_after = 10;
auth.static_credentials = [
{ username = "root"; password = "toor"; }
];
};
};
}
Alternatively, use configFile to pass a pre-written TOML file instead of settings.
Docker
Build a Docker image via nix:
nix build .#dockerImage
docker load < result
docker run -v /path/to/data:/data -p 2222:2222 -p 8080:8080 oubliette:0.8.0
Place your oubliette.toml in the data volume. The container exposes ports 2222 (SSH) and 8080 (web/metrics).