@@ -0,0 +1,245 @@
|
|||||||
|
# Jakach Logging
|
||||||
|
|
||||||
|
A self-hosted log analysis and alerting system. Ingests logs from files, TCP/UDP syslog, and HTTP, evaluates them against configurable rules, notifies via Telegram, and provides a Bootstrap web UI for management.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||||
|
│ Log Files │ │ TCP/UDP │ │ HTTP POST │
|
||||||
|
│ (tail -f) │ │ syslog │ │ /ingest │
|
||||||
|
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
|
||||||
|
│ │ │
|
||||||
|
└─────────────────┼──────────────────┘
|
||||||
|
│
|
||||||
|
┌──────────▼──────────┐
|
||||||
|
│ Worker (PHP-CLI) │
|
||||||
|
│ FileWatcher │
|
||||||
|
│ SocketListener │
|
||||||
|
└──────────┬──────────┘
|
||||||
|
│
|
||||||
|
┌──────────▼──────────┐
|
||||||
|
│ Rule Engine │
|
||||||
|
│ preg_match rules │
|
||||||
|
│ Rate Limiter │
|
||||||
|
└──────────┬──────────┘
|
||||||
|
│
|
||||||
|
┌──────────▼──────────┐
|
||||||
|
│ TelegramNotifier │
|
||||||
|
└──────────┬──────────┘
|
||||||
|
│
|
||||||
|
┌──────────▼──────────┐
|
||||||
|
│ SQLite Database │
|
||||||
|
│ (FTS5 full-text) │
|
||||||
|
└──────────┬──────────┘
|
||||||
|
│
|
||||||
|
┌──────────▼──────────┐
|
||||||
|
│ API (PHP-FPM) │
|
||||||
|
│ REST + Auth │
|
||||||
|
└──────────┬──────────┘
|
||||||
|
│
|
||||||
|
┌──────────▼──────────┐
|
||||||
|
│ Web UI (Bootstrap)│
|
||||||
|
│ nginx :8080 │
|
||||||
|
└─────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clone and start
|
||||||
|
git clone <repo> jakach-logging
|
||||||
|
cd jakach-logging
|
||||||
|
docker compose build --no-cache && docker compose up -d
|
||||||
|
|
||||||
|
# Seed default rules and syslog sources
|
||||||
|
docker compose exec api php bin/seed
|
||||||
|
|
||||||
|
# Open the UI
|
||||||
|
open http://localhost:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
The first user to log in via Jakach Auth is automatically added as admin.
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
Uses [Jakach Login](https://github.com/jakani24/jakach-login) for authentication. Users authenticate via `auth.jakach.ch`. The first user is automatically authorized; subsequent users must have their `user_token` added in Settings > Security.
|
||||||
|
|
||||||
|
## Log Sources (Ingestion)
|
||||||
|
|
||||||
|
### File sources
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8080/sources \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d '{"name":"nginx-access","type":"file","address":"/var/log/nginx/access.log"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
Supports glob patterns: `"/collect/*.log"`
|
||||||
|
|
||||||
|
### TCP/UDP syslog
|
||||||
|
The worker already listens on `:9514` (TCP and UDP). Add the source via UI or:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8080/sources \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d '{"name":"syslog","type":"tcp","address":"tcp://0.0.0.0:9514"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
Other containers can send logs via Docker syslog driver:
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
my-app:
|
||||||
|
logging:
|
||||||
|
driver: syslog
|
||||||
|
options:
|
||||||
|
syslog-address: "tcp://<host>:9514"
|
||||||
|
tag: "my-app"
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTTP POST
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8080/ingest \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d '{"line":"2024-01-01 ERROR: something broke","source":"my-app"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Shared volume
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
my-app:
|
||||||
|
volumes:
|
||||||
|
- jakach-logging_log_collect:/collect
|
||||||
|
```
|
||||||
|
|
||||||
|
Files written to `/collect/*.log` are automatically picked up by the worker.
|
||||||
|
|
||||||
|
## Alert Rules
|
||||||
|
|
||||||
|
Default rules (created by `bin/seed`):
|
||||||
|
|
||||||
|
| Rule | Pattern | Severity |
|
||||||
|
|------|---------|----------|
|
||||||
|
| PHP Fatal Error | `/PHP Fatal/i` | critical_high |
|
||||||
|
| PHP Exception | `/Uncaught (Exception\|Error)/` | critical |
|
||||||
|
| PHP Warning | `/PHP (Warning\|Notice)/i` | warning |
|
||||||
|
| HTTP 5xx | `/" (50[0-9]) /` | critical |
|
||||||
|
| HTTP 4xx | `/" (4[0-9]{2}) /` | warning_low |
|
||||||
|
| Failed Login | `/Failed (login\|password\|authentication)/i` | critical_low |
|
||||||
|
| Out of Memory | `/out of memory\|OutOfMemory/i` | emergency |
|
||||||
|
| Connection Refused | `/Connection (refused\|reset\|timed? out)/i` | warning_high |
|
||||||
|
| Disk Space | `/disk (full\|space\|usage\|low)/i` | critical_low |
|
||||||
|
| Service Started | `/service started\|daemon started\|ready to serve/i` | notice |
|
||||||
|
| Slow Query | `/slow (query\|request\|response)/i` | warning_high |
|
||||||
|
|
||||||
|
Rules use PHP regex. Add custom rules via UI or API:
|
||||||
|
```bash
|
||||||
|
curl -X POST http://localhost:8080/rules \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d '{"name":"SSH Login","pattern":"/sshd.*Accepted/i","severity":"notice"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
Each rule can have a `rate_limit_seconds` to prevent alert storms.
|
||||||
|
|
||||||
|
## Severity Levels
|
||||||
|
|
||||||
|
`debug` → `info` → `notice` → `warning_low` → `warning` → `warning_high` → `error` → `critical_low` → `critical` → `critical_high` → `emergency`
|
||||||
|
|
||||||
|
## Telegram Notifications
|
||||||
|
|
||||||
|
Configure in Settings > Telegram Notifications:
|
||||||
|
1. Create a bot via [@BotFather](https://t.me/BotFather) on Telegram
|
||||||
|
2. Get your chat ID (send a message to your bot, visit `https://api.telegram.org/bot<token>/getUpdates`)
|
||||||
|
3. Enter bot token and chat ID in settings, click Save, then Test
|
||||||
|
|
||||||
|
## Alerts Workflow
|
||||||
|
|
||||||
|
- **Open** — newly triggered, shown on dashboard
|
||||||
|
- **Acknowledged** — someone has seen it
|
||||||
|
- **Resolved** — closed, hidden from dashboard counts
|
||||||
|
|
||||||
|
Quick actions in the table: ✓ (acknowledge), ✓✓ (resolve). Click any row for full detail.
|
||||||
|
|
||||||
|
## API Endpoints
|
||||||
|
|
||||||
|
| Method | Path | Auth | Description |
|
||||||
|
|--------|------|------|-------------|
|
||||||
|
| GET | `/health` | No | Health check |
|
||||||
|
| POST | `/ingest` | No | Ingest a log line |
|
||||||
|
| GET | `/auth/me` | No | Current session user |
|
||||||
|
| POST | `/auth/logout` | No | Destroy session |
|
||||||
|
| GET | `/sources` | Yes | List sources |
|
||||||
|
| POST | `/sources` | Yes | Create source |
|
||||||
|
| PUT | `/sources/{id}` | Yes | Update source |
|
||||||
|
| DELETE | `/sources/{id}` | Yes | Delete source |
|
||||||
|
| GET | `/rules` | Yes | List rules |
|
||||||
|
| POST | `/rules` | Yes | Create rule |
|
||||||
|
| PUT | `/rules/{id}` | Yes | Update rule |
|
||||||
|
| DELETE | `/rules/{id}` | Yes | Delete rule |
|
||||||
|
| GET | `/alerts` | Yes | List alerts (query: `severity`, `status`, `limit`) |
|
||||||
|
| GET | `/alerts/search?q=` | Yes | Full-text search alerts |
|
||||||
|
| GET | `/alerts/counts` | Yes | Alert counts by status/severity |
|
||||||
|
| POST | `/alerts/{id}/status` | Yes | Update alert status |
|
||||||
|
| GET | `/logs/search?q=` | Yes | Search raw log entries |
|
||||||
|
| GET | `/config/allowed_tokens` | Yes | Get allowed user tokens |
|
||||||
|
| PUT | `/config/allowed_tokens` | Yes | Set allowed user tokens |
|
||||||
|
| GET | `/config/telegram` | Yes | Get Telegram config |
|
||||||
|
| PUT | `/config/telegram` | Yes | Set Telegram config |
|
||||||
|
|
||||||
|
## Log Search
|
||||||
|
|
||||||
|
In the Logs tab, search through all ingested log lines. Use `*` as wildcard:
|
||||||
|
- `error` — matches any line containing "error"
|
||||||
|
- `error 500` — matches lines containing both "error" AND "500"
|
||||||
|
- `*` — shows all logs
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install PHP deps locally
|
||||||
|
composer install
|
||||||
|
|
||||||
|
# Run PHP built-in server (no Docker)
|
||||||
|
composer serve
|
||||||
|
```
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
├── bin/
|
||||||
|
│ ├── consume # Worker entrypoint
|
||||||
|
│ └── seed # Seed default data
|
||||||
|
├── config/
|
||||||
|
│ └── default.php # Default rules config
|
||||||
|
├── docker/
|
||||||
|
│ ├── Dockerfile.api # PHP-FPM image
|
||||||
|
│ ├── Dockerfile.php # PHP-CLI image
|
||||||
|
│ ├── entrypoint-api.sh
|
||||||
|
│ └── nginx.conf
|
||||||
|
├── docker-compose.yml
|
||||||
|
├── public/
|
||||||
|
│ ├── index.html # SPA frontend
|
||||||
|
│ ├── index.php # API entrypoint
|
||||||
|
│ └── oauth.php # Auth callback
|
||||||
|
└── src/
|
||||||
|
├── Api/
|
||||||
|
│ ├── AuthMiddleware.php
|
||||||
|
│ └── Router.php
|
||||||
|
├── Model/
|
||||||
|
│ ├── Alert.php
|
||||||
|
│ ├── AlertSeverity.php
|
||||||
|
│ ├── AlertStatus.php
|
||||||
|
│ ├── LogSource.php
|
||||||
|
│ ├── LogSourceType.php
|
||||||
|
│ └── Rule.php
|
||||||
|
├── Notifier/
|
||||||
|
│ └── TelegramNotifier.php
|
||||||
|
├── RuleEngine/
|
||||||
|
│ └── Engine.php
|
||||||
|
├── Storage/
|
||||||
|
│ ├── Database.php
|
||||||
|
│ └── Repository.php
|
||||||
|
└── Worker/
|
||||||
|
├── FileWatcher.php
|
||||||
|
├── Orchestrator.php
|
||||||
|
└── SocketListener.php
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user