Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Build and push the web application image (PHP + baked src + samplelogs) to GHCR.
# Tags: semver from git tag ( v* ), plus :latest .
name: Docker publish

on:
push:
tags:
- "v*"

permissions:
contents: read
packages: write

jobs:
push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- id: lc
name: GHCR image name (lowercase)
run: |
echo "image=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT"

- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- uses: docker/build-push-action@v6
with:
context: .
file: docker/Dockerfile
push: true
tags: |
${{ steps.lc.outputs.image }}:${{ github.ref_name }}
${{ steps.lc.outputs.image }}:latest
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/.env

src/config.php
*.bak
/vendor/
Expand Down
81 changes: 56 additions & 25 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,78 @@
# LogAnalyzer agent / contributor notes

## Docker development
## Docker stacks

From the repository root:
| Compose file | Use case |
|----------------|----------|
| [`docker/docker-compose.yml`](docker/docker-compose.yml) | **Default/local install.** Application code is baked into the image. By default (**`LOGANALYZER_SEED_SAMPLE_SOURCES=0`**) MySQL seed creates **schema + admin only** — no bundled disk sources unless you set **`LOGANALYZER_DISK_*`** (first seed) or add sources in Administration. Fixtures remain under **`/samplelogs`** in the image so you can still opt into demo sources. MySQL (`loganalyzer_mysql_data`) and `config.php` (`loganalyzer_config`) use volumes. **`LOGANALYZER_OVERWRITE_CONFIG=0`**. |
| [`docker/docker-compose.dev.yml`](docker/docker-compose.dev.yml) | **Development.** Bind-mount [`src`](src) and [`tests/fixtures/samplelogs`](tests/fixtures/samplelogs); `LOGANALYZER_OVERWRITE_CONFIG=1` regenerates `src/config.php` on each container start so editor + DB drift is minimized. Host **MySQL** port `3306` is exposed like before. Separate volume label `loganalyzer_dev_mysql_data`. |

Build context for images is **repository root**; see [`docker/Dockerfile`](docker/Dockerfile) (multi-stage: runtime + baked `src`; optional fixture tree at `/samplelogs`). Install walkthrough (**`.env`**, volumes, **`LOGANALYZER_DISK_*`**, reset): [`docker/README.md`](docker/README.md).

Credentials and bootstrap flags normally come **at runtime**, not **`docker build`**: copy [`docker/env.example`](docker/env.example) to **`.env` in the repository root** (same folder as `README.md`) and adjust `LOGANALYZER_ADMIN_*`, `MYSQL_*`, `LOGANALYZER_SEED_SAMPLE_SOURCES`, and optional **`LOGANALYZER_DISK_*`** before **`docker compose up`**. Compose injects `${VARIABLE:-defaults}` automatically; **`.gitignore` excludes `.env`**.

**Real disk sources at first seed:** set **`LOGANALYZER_DISK_SOURCE_PATHS`** (comma-separated file paths *inside the web container*) and/or **`LOGANALYZER_DISK_SOURCES`** (see comments in [`docker/env.example`](docker/env.example)). Bind-mount host directories on the **`web`** service (commented example in [`docker/docker-compose.yml`](docker/docker-compose.yml)). `docker/write-config.php` extends **`DiskAllowed`** from those paths plus **`LOGANALYZER_DISK_ALLOWED_EXTRA`**. After the first boot, updating disk paths in `.env` requires either **`LOGANALYZER_OVERWRITE_CONFIG=1`** once or wiping the **`loganalyzer_config`** volume so **`config.php`** regenerates with the new prefixes (and usually **`docker compose … down -v`** if you must re-run the seed for new rows).

```bash
docker compose -f docker/docker-compose.yml up --build
```

**Clean rebuild** (drops MySQL data and re-seeds; `src/config.php` is regenerated on web container start):
**Clean reset** (wipe DB + persisted config):

- Linux/macOS/Git Bash: `sh docker/rebuild-consumer.sh`
- Windows (cmd): `docker\rebuild-consumer.bat`

Those scripts invoke **`docker/init-env-interactive.sh`** (POSIX path requires **bash** on `PATH`; if none, they fall back to copying **`docker/env.example`**) or **`docker/init-env-interactive.ps1`** (called from **`.bat`**) whenever **`.env`** is absent. Each **`KEY=value`** line from **`docker/env.example`** is prompted with **Enter = default**. **`*PASSWORD*`** prompts are masked in Bash and PowerShell **`7.1+`**, echoed in **`5.x`** / **7.0**). Afterwards: **`docker compose down -v`** then **`up --build`** for [`docker-compose.yml`](docker/docker-compose.yml).

### Developer stack

```bash
docker compose -f docker/docker-compose.dev.yml up --build
```

**Clean rebuild** (`src/config.php` + MySQL wiped for this stack):

- Linux/macOS/Git Bash: `sh docker/rebuild-dev.sh`
- Windows (cmd): `docker\rebuild-dev.bat`

**E2E clean run** (fresh E2E DB + Playwright):
### E2E clean run (Playwright)

- `sh docker/rebuild-e2e.sh` or `docker\rebuild-e2e.bat`

- **Web UI:** http://localhost:8080/
- **MySQL:** `localhost:3306`, database `loganalyzer`, user `loganalyzer` / `loganalyzer`, root password `loganalyzer_root`
- **Admin login:** `admin` / `pass` (seeded once per fresh MySQL volume)
- **Sample logs** are mounted read-only at `/samplelogs` from [tests/fixtures/samplelogs](https://github.com/rsyslog/loganalyzer/tree/master/tests/fixtures/samplelogs). The default seeded source reads `sampledata_syslog.log`.
Operational details mirror the handbook: **`http://localhost:8080/`**, **fresh admin** defaults to **`LOGANALYZER_ADMIN_*`** from Compose or `.env` (compose defaults **`admin`** / **`loganalyzer`** if unset).

Developer stack exposes **MySQL** on **`localhost:3306`**.

The default consumer compose sets **`LOGANALYZER_SEED_SAMPLE_SOURCES=0`**, giving a **clean first install**: schema + views + admin only (add sources manually). Fixtures still exist under **`/samplelogs`** if you bump that env var to **`1`**. Contributor/E2E stacks omit it or pin **`1`**, restoring the seeded demo disk sources Playwright relies on.

Reset the developer stack volumes: `docker compose -f docker/docker-compose.dev.yml down -v`.

### Publish image (maintainers)

Pushing tag **`v*`** triggers [`.github/workflows/docker-publish.yml`](.github/workflows/docker-publish.yml): image **`ghcr.io/<owner>/<repo>`** tagged with **`v…`** and **`latest`**.

Reset the database and config: `docker compose -f docker/docker-compose.yml down -v` then `up --build` again.
To pull from GHCR, point **`web.image`** at **`ghcr.io/<owner>/<repo>:<tag>`** (matching the publish workflow outputs) alongside appropriate env/`LOGANALYZER_CONFIG_PATH` settings, instead of **`build`**.

### Environment variables (web container)

| Variable | Default | Purpose |
|----------|---------|---------|
| `LOGANALYZER_DB_HOST` | `db` | MySQL host |
| `LOGANALYZER_DB_PORT` | `3306` | MySQL port |
| `LOGANALYZER_DB_NAME` | `loganalyzer` | Database name |
| `LOGANALYZER_DB_USER` | `loganalyzer` | App DB user |
| `LOGANALYZER_DB_PASSWORD` | `loganalyzer` | App DB password |
| `MYSQL_ROOT_PASSWORD` | `loganalyzer_root` | Root (used by seed script only) |
| `LOGANALYZER_TABLE_PREFIX` | `logcon_` | Table prefix |
| `LOGANALYZER_ADMIN_USER` | `admin` | First admin username |
| `LOGANALYZER_ADMIN_PASSWORD` | `pass` | First admin password |
| `LOGANALYZER_LOGIN_REQUIRED` | `0` | Set `1` to force login on all pages |
| `LOGANALYZER_SAMPLE_LOG` | `/samplelogs/sampledata_syslog.log` | First seeded disk source (syslog) |
| `LOGANALYZER_SAMPLE_EVENTREPORTER` | `/samplelogs/EventReporter.log` | Second seeded disk source (Windows EventReporter / EvntSLog) |
| `LOGANALYZER_SKIP_SEED` | unset | Set `1` to skip MySQL seed |
| `LOGANALYZER_OVERWRITE_CONFIG` | `1` | Overwrite `src/config.php` on each start in dev |
| Variable | Typical default stack | Typical dev stack | Purpose |
|------------------|----------------|-------------------|---------|
| `LOGANALYZER_DB_HOST` | `db` | `db` | MySQL host |
| `LOGANALYZER_DB_PORT` | `3306` | `3306` | MySQL port |
| `(MySQL service)` `MYSQL_DATABASE`, `MYSQL_USER`, `MYSQL_PASSWORD` | `loganalyzer`/… compose defaults (`${…:-…}` pulls from repo-root **`.env`**) | same | Passed to **`db`** bootstrap + surfaced as **`LOGANALYZER_DB_*`** inside **`web`** |
| `MYSQL_ROOT_PASSWORD` | `loganalyzer_root` | `loganalyzer_root` | Seed script credential; keep synced with Compose healthchecks (`CMD-SHELL` uses **`$$MYSQL_ROOT_PASSWORD`**) |
| `LOGANALYZER_TABLE_PREFIX` | `logcon_` | `logcon_` | Table prefix |
| `LOGANALYZER_ADMIN_USER` | compose default `admin`; override `.env` | compose default `.env`/Compose | First admin username |
| `LOGANALYZER_ADMIN_PASSWORD` | compose default `loganalyzer`; override `.env` | same | First admin password (**customise before sharing host**) |
| `LOGANALYZER_LOGIN_REQUIRED` | `0` | `0` | Set `1` to force login on all pages |
| `LOGANALYZER_SAMPLE_LOG` / `LOGANALYZER_SAMPLE_EVENTREPORTER` | paths only when demo seeding | same | Used when **`LOGANALYZER_SEED_SAMPLE_SOURCES` enables demo disk sources |
| `LOGANALYZER_SEED_SAMPLE_SOURCES` | `0` (compose default, clean install) | unset / `1` | `0`/`false`/`no`/`off` skips demo sources; anything else seeds fixtures |
| `LOGANALYZER_SKIP_SEED` | unset | unset | Set `1` to skip MySQL seed |
| `LOGANALYZER_OVERWRITE_CONFIG` | `0` | `1` | Regenerate `config.php` on start when `1`; default stack persists config on the `/persist` volume |
| `LOGANALYZER_DISK_SOURCE_PATHS` | `.env`/unset | `.env`/unset | Comma-separated container paths → syslog disk sources seeded on first DB init (`basename` → display name) |
| `LOGANALYZER_DISK_SOURCES` | `.env`/unset | `.env`/unset | Records separated by `;;`, fields separated by `|` (see `docker/env.example`): name, path, kind `syslog` or `event`, optional description (description may contain `|` — only the first three delimiters split fields); deduped with `PATHS` by path |
| `LOGANALYZER_DISK_ALLOWED_EXTRA` | `.env`/unset | `.env`/unset | Extra `DiskAllowed` directory prefixes (comma-separated); auto-includes dirs of env disk paths plus `/var/log/` and `/samplelogs/` |
| `LOGANALYZER_CONFIG_PATH` | `/persist/config.php` | unset | When set (and not equal to `LOGANALYZER_DOCROOT/config.php`), config is stored there and symlinked into the docroot |

## PHPUnit

Expand Down
21 changes: 15 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,36 @@

## Documentation

- **Handbook** (Docker & CI, **LogAnalyzer user guide**, third-party components): [rsyslog.github.io/loganalyzer](https://rsyslog.github.io/loganalyzer/)
- **[`AGENTS.md`](https://github.com/rsyslog/loganalyzer/blob/master/AGENTS.md)** — Docker development, environment variables, PHPUnit, Playwright E2E; start here for a working local stack
- **Handbook** (Docker install & development, **LogAnalyzer user guide**, third-party components): [rsyslog.github.io/loganalyzer](https://rsyslog.github.io/loganalyzer/)
- **[`docker/README.md`](docker/README.md)** — install walkthrough (`docker compose` from repo root, `.env`), file map (`Dockerfile`, compose files, scripts), handbook links
- **[`AGENTS.md`](https://github.com/rsyslog/loganalyzer/blob/master/AGENTS.md)** — contributor notes: developer Docker stack (`docker-compose.dev.yml`), environment variables, PHPUnit, Playwright E2E
- **User guide chapters** (imported into the handbook) are maintained as HTML under [`doc/`](https://github.com/rsyslog/loganalyzer/tree/master/doc/)

## Quick start (Docker)
## Quick start (Docker — default stack)

From the repository root:
Step-by-step install: **[`docker/README.md`](docker/README.md)** · handbook: **[Docker install & development](https://rsyslog.github.io/loganalyzer/docker/)**.

[`docker/docker-compose.yml`](https://github.com/rsyslog/loganalyzer/blob/master/docker/docker-compose.yml) ships a **fresh install** by default: the database bootstrap creates schema, default views, and the **admin user** — **no** auto-added sample log sources. Fixture files remain available under **`/samplelogs`** in the image if you set **`LOGANALYZER_SEED_SAMPLE_SOURCES=1`**. MySQL data and **`config.php`** persist in **named Compose volumes**.

From the repository root, optionally copy [`docker/env.example`](https://github.com/rsyslog/loganalyzer/blob/master/docker/env.example) → **`.env`** to customise **`LOGANALYZER_ADMIN_*`**, **`MYSQL_*`**, **`LOGANALYZER_DISK_*`**, and demo seeding — or use the handbook section **[Docker helper scripts](doc-site/docs/docker.md#docker-helper-scripts)** (`init-env-interactive`, `rebuild-consumer`, etc.).

```bash
docker compose -f docker/docker-compose.yml up --build
```

Open **http://localhost:8080/**. Default dev credentials and MySQL settings are documented in [`AGENTS.md`](https://github.com/rsyslog/loganalyzer/blob/master/AGENTS.md).
Open **http://localhost:8080/**.

- **Credentials / DB defaults:** see [`doc-site/docs/docker.md`](https://github.com/rsyslog/loganalyzer/blob/master/doc-site/docs/docker.md) (handbook section). Dev-only stack with a bind-mounted repo `src/` uses [`docker/docker-compose.dev.yml`](https://github.com/rsyslog/loganalyzer/blob/master/docker/docker-compose.dev.yml).

**Clean reset everything** (drops MySQL and generated config volumes): `sh docker/rebuild-consumer.sh` or `docker\rebuild-consumer.bat`.

## Tests and CI

| Area | Where |
|------|--------|
| PHPUnit | `composer install` then `composer test` |
| Playwright E2E | [`e2e/README.md`](https://github.com/rsyslog/loganalyzer/blob/master/e2e/README.md), `docker/docker-compose.e2e.yml` |
| Workflows | [`.github/workflows/`](https://github.com/rsyslog/loganalyzer/tree/master/.github/workflows/) (PHP CI, Playwright E2E, GitHub Pages) |
| Workflows | [`.github/workflows/`](https://github.com/rsyslog/loganalyzer/tree/master/.github/workflows/) (PHP CI, Docker publish on tag `v*`, Playwright E2E, GitHub Pages) |

On GitHub, the Playwright workflow can open an issue when E2E fails (same repository only); see [`AGENTS.md`](https://github.com/rsyslog/loganalyzer/blob/master/AGENTS.md) and [`e2e.yml`](https://github.com/rsyslog/loganalyzer/blob/master/.github/workflows/e2e.yml).

Expand Down
Loading
Loading