# Running docker-vuln-scan in Komodo Two ready-to-apply Resource Sync definitions are provided. Use **one** of them, not both (they declare the same resource names): | File | Use when | | --- | --- | | [`vuln-scan.toml`](vuln-scan.toml) | Komodo should clone this project from git and build the scanner itself. | | [`vuln-scan-files-on-host.toml`](vuln-scan-files-on-host.toml) | You copy this project to the Komodo server and want Komodo to use those files. | Both create: - a **Stack** named `vuln-scan` on the selected Komodo Server, and - a **Procedure** named `vuln-scan` that redeploys the stack every night, which rebuilds the scanner image and runs one scan. Alerts for HIGH/CRITICAL findings are sent **by the scanner directly through Apprise**. You do not need a Komodo Alerter for that part. ## Before you start - Komodo 2.x with a **Server** resource (Periphery) on the Docker host whose images you want to scan. - The project available to Komodo (git repo, or copied to the host). - A reachable Apprise target (Discord, Slack, email, Telegram, ...). ### 1. Create the APPRISE_URLS variable In Komodo: **Variables → New Variable** | Field | Value | | --- | --- | | Name | `APPRISE_URLS` | | Value | e.g. `discord://webhook_id/webhook_token` | | Secret | **on** | For several targets, separate them with a space: ```text mailto://user:app-password@gmail.com tgram://bot_token/chat_id ``` The stack reads this variable through an `[[APPRISE_URLS]]` interpolation in its `environment`, so do this before applying the sync. > If you prefer to keep everything in the TOML file, add a `[[variable]]` block > with `name = "APPRISE_URLS"`, `value = "..."` and `is_secret = true`. The > value will then live in your sync git repo, so only do this in a private repo. ### 2. Apply the resources #### Option A - git repo mode (recommended) 1. Push this project to a git repository Komodo can reach. 2. Edit `komodo/vuln-scan.toml`: - `server = "server-prod"` → your Komodo Server name. - `repo = "your-org/docker-vuln-scan"` → your repository. - `IMAGES = ...` → the images you want to scan. 3. In Komodo: **Syncs → New Resource Sync → Git Repo**, then set: - the repository and branch, - `resource_path = ["komodo/vuln-scan.toml"]`, - a git account if the repo is private. 4. Refresh the sync and review/apply the pending changes. 5. Open **Procedures → vuln-scan → Run** to start the first scan now. #### Option B - files on the host Komodo resolves files-on-host paths under the Periphery root directory (default `/etc/komodo`, mounted at the same path in the standard Komodo compose setup). The stack path is `/etc/komodo/stacks/`. 1. Copy the project to the Docker host: ```bash sudo mkdir -p /etc/komodo/stacks/vuln-scan sudo cp -r docker-vuln-scan/. /etc/komodo/stacks/vuln-scan/ ``` (If you changed `PERIPHERY_ROOT_DIRECTORY`, use that path instead.) 2. Edit `komodo/vuln-scan-files-on-host.toml` (`server`, `IMAGES`). 3. Apply the file. It still needs to be readable by **Core**, which does not mount `/etc/komodo` by default. Either keep the TOML in a git-based Resource Sync, or create the Stack and Procedure in the UI using the values from the file. 4. Run **Procedures → vuln-scan → Run**. ## What a run does ``` Procedure (cron) -> DeployStack -> docker compose build -> docker compose up -d | v scanner container runs and exits | +---------------+---------------+ v v Apprise alert (HIGH/CRITICAL) JSON report on disk ``` - `run_build = true` rebuilds the scanner image on the Komodo server. Layers are cached, so only changes to `scan.py`/`Dockerfile` rebuild. - `auto_pull = false` is required: the image is built locally and must not be pulled from a registry. - `ignore_services = ["vulnscan"]` tells Komodo that the exited one-shot container is expected in status checks. Because this stack contains only that one service, Komodo may still show the stack as stopped/down between runs. That is normal for a scheduled one-shot job. - `send_alerts = false` avoids daily status noise. Findings are reported by Apprise instead. `DeployStack` returns once `docker compose up -d` has started the container; it does not wait for the scan to finish. The Apprise notification is the result signal. The container exit code (`FAIL_ON`) is visible in the stack logs. ## Where the results are On the scan server: ``` /etc/komodo/stacks/vuln-scan/reports/.json ``` If your Periphery runs with a different root or the stack uses a `run_directory`, adjust the path accordingly. The Compose volume is `./reports:/reports` relative to the stack directory. Logs: - Komodo UI: **Stacks → vuln-scan → Logs** - Shell: `docker compose -p vuln-scan logs vulnscan` ## Customizing Edit the stack's `environment` (in the TOML or in Komodo) and re-apply the sync: | Setting | Meaning | | --- | --- | | `IMAGES` | Space separated images to scan. Leave empty to scan the images used by running containers. | | `DOCKER_SOCK` | Host path of the Docker socket (e.g. `/run/user/1000/docker.sock` for rootless Docker). | | `INCLUDE_SELF` | `true` to also scan the scanner's own image when auto-discovering. | | `APPRISE_URLS` | Notification target(s); usually kept in the secret variable. | | `NOTIFY_MIN_SEVERITY` | Lowest severity that sends an alert (default `HIGH`). | | `FAIL_ON` | Lowest severity that makes the container exit `1` (default `HIGH`). | | `IGNORE_UNFIXED` | `true` to ignore findings without a fix. | | `MAX_FINDINGS_IN_BODY` | Findings listed per notification. | Schedule fields are on the Procedure: ```toml [procedure.config] schedule_format = "Cron" schedule = "0 0 3 * * ?" # seconds minute hour day month weekday schedule_timezone = "UTC" ``` To scan every image on the server instead of just the images in use, write the list on the host and mount it: ```bash docker image ls --format '{{.Repository}}:{{.Tag}}' \ | grep -v '' > /etc/komodo/stacks/vuln-scan/images.txt ``` Then add `- ./images.txt:/images.txt:ro` to the `vulnscan` service volumes and set `IMAGES_FILE = /images.txt` in the stack environment. Private registries: add `TRIVY_USERNAME`, `TRIVY_PASSWORD` and optionally `TRIVY_INSECURE` to the stack environment. The Compose file already passes them through to the container. ## Troubleshooting | Symptom | Fix | | --- | --- | | Unresolved `[[APPRISE_URLS]]` / notification errors | Create the `APPRISE_URLS` variable (step 1) and re-apply. | | `docker-vuln-scan:latest` pull error | Keep `auto_pull = false`; the stack builds the image locally. | | Stack shows stopped/down between scans | Expected: the scanner is a one-shot container. Status alerts are disabled. | | No findings at all | Check the image reference is correct; Trivy pulls registry images, and the Docker socket covers local-only images. | | "No images configured ... nothing to scan" | The scanner cannot reach the Docker socket. With rootless Docker set `DOCKER_SOCK=/run/user//docker.sock`, or set `IMAGES` explicitly. | | Procedure success but no alert | Success only means the container started. Check stack logs and the Apprise target. | | Need Komodo to fail on findings | Not covered by `DeployStack`; use `FAIL_ON` in CI or trigger the scanner from a Komodo Action that runs `docker run --rm` and inspects the exit code. | ## Security note The scanner mounts `/var/run/docker.sock` and runs as root inside the container. That is effectively root on the scan host, so only deploy it to servers and Komodo users you trust.