Appearance
Docker Deployment
Nikto Platform runs as a set of Docker Compose services: the database, the API, the console, and (for Headless Browser crawls) Chromium.
This page covers installing, running, and removing a deployment. You install with the launcher (nikto-launcher): one program, downloaded from the release page, that writes the compose files into its install folder, pulls the images, and starts the stack. It is the only supported way to install.
System requirements
Docker
| Requirement | Minimum | Check with |
|---|---|---|
| Docker Engine (or Docker Desktop) | 28.0 | docker version (Server → Version) |
| Docker Compose | v2 (2.17 or later) | docker compose version |
The launcher checks these before starting and stops with a message naming the version it found. Compose v1 (docker-compose 1.x) cannot read these files.
Why 28.0: the internal networks that keep the database and the headless browser off your host use a Docker network option older engines do not have. On Engine 27 and earlier, startup fails with unknown gateway mode isolated.
Docker Desktop (macOS, Windows)
Any current Docker Desktop includes Engine 28+ and Compose v2. Update it if docker version reports an older engine.
Windows
Install Docker Desktop and start it before running the launcher. Docker Desktop's own requirement is the WSL 2 backend (wsl --install) or Hyper-V — see Docker's install guide. Run the launcher from PowerShell. The Windows launchers are not signed yet, so SmartScreen warns on first run (More info → Run anyway).
Colima (macOS)
Colima works as an alternative to Docker Desktop on macOS (tested with the launcher on Apple silicon). It runs its own virtual machine, so give it enough memory for the stack (see Memory below):
bash
brew install colima
colima start --cpu 4 --memory 8
docker context use colimaIf Docker Desktop is installed you already have the docker CLI and Compose. Without it, also install them (brew install docker docker-compose) and make sure docker compose version works.
The launcher uses whichever Docker context is active. To go back to Docker Desktop, run docker context use desktop-linux. Containers and data in Colima are separate from Docker Desktop's; colima delete removes the virtual machine and everything in it, including the database.
Colima is also a way to try a release on a Mac that already runs another copy of Nikto Platform (for example a development checkout): the two installs share container and volume names, so on the same Docker engine they collide.
Linux
The Docker packaged by your distribution may be too old, and it often leaves Compose out:
| Distribution | Distro packages | Works? | Install |
|---|---|---|---|
| Kali (2026.3, desktop) | docker.io 28.5, docker-compose 2.40 | Yes | sudo apt install docker.io docker-compose |
| Ubuntu 24.04 / 26.04 | docker.io 29.x; Compose is a separate package | Yes | sudo apt install docker.io docker-compose-v2 |
| Amazon Linux 2023 | docker 25 | No: Engine too old | Docker's own repository (below) |
| Ubuntu 22.04 and older | docker.io predates Engine 28 | No: Engine too old (untested) | Docker's own repository (below) |
| Debian 13 | docker.io 26.1 | No: Engine too old | Docker's own repository (below) |
| Debian 12 | docker.io 20.10, docker-compose 1.29 | No: both too old | Docker's own repository (below) |
On Ubuntu, installing docker.io alone gives you the Engine but no Compose — the launcher then stops with "Docker Compose v2 is required". Install docker-compose-v2 as well (the plain docker-compose package is the old v1 and does not work). Without Compose, docker compose also fails with the confusing unknown shorthand flag: 'f' in -f.
Any other distribution, or when in doubt: install Docker Engine and the Compose plugin from Docker's own repository, following docs.docker.com/engine/install. That gives you docker-ce and docker-compose-plugin, which are always current. Two recipes we have run:
- Amazon Linux 2023 — Docker's repo has no
amzn2023build, so use the CentOS repo pinned to EL9:bashsudo dnf remove -y docker containerd runc # distro Docker is 25, too old sudo dnf install -y dnf-plugins-core sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo sed -i 's/\$releasever/9/g' /etc/yum.repos.d/docker-ce.repo sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin sudo systemctl enable --now docker - Debian / Kali cloud images — use Docker's Debian (
bookworm) repo. On Ubuntu, the same recipe works with.../linux/ubuntuand your own release codename in place of.../linux/debianandbookworm. A Kali cloud image can ship only adockerCLI with no daemon (sodocker versionshows a Client butdocker.serviceis missing); installingdocker-cefrom Docker's repo provides the daemon:bash(sudo install -m0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable" | sudo tee /etc/apt/sources.list.d/docker.list sudo apt-get update && sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin sudo systemctl enable --now dockergnupgandcurlmust be installed first.)
Run Docker as a non-root user: sudo usermod -aG docker "$USER", then log out and back in (a fresh login session — newgrp alone may not apply the group to processes the launcher starts). Otherwise run the launcher as root.
Cloud VMs
The console binds to loopback only (see Remote Access), so on a headless cloud VM you reach it with an SSH tunnel from your own machine, not by opening a port:
bash
ssh -L 3001:localhost:3001 user@vm-host # then open http://localhost:3001 locallyOpen only SSH (22) in the cloud firewall / security group — never the console port. A few provider-specific snags we have hit:
- Low-memory droplets (≤ 2 GB): add swap or Headless Browser crawls will be OOM-killed —
sudo fallocate -l 2G /swapfile && sudo chmod 600 /swapfile && sudo mkswap /swapfile && sudo swapon /swapfile(persist it in/etc/fstab). Everything else runs on 2 GB. - AWS Kali AMI: ships with SSH disabled, and EC2 Instance Connect is not supported on it. Launch with user data
#!/bin/bash+systemctl enable --now ssh, then log in askali. - Azure Windows 11: client (desktop) Windows images need a Visual Studio subscription or Enterprise Agreement; on pay-as-you-go they fail at validation with "Unable to retrieve prices and legal terms". Use a real Windows 11 machine/VM, or Windows Server 2022 for a launcher smoke test.
Image access
The product images are private. You need a GitHub account that has been granted access to them, and a personal access token (classic) with the read:packages scope. The launcher logs in to ghcr.io with these before it pulls.
Platforms
| Component | Available for |
|---|---|
| API and console images | linux/amd64, linux/arm64 |
| Launcher | macOS Apple silicon (nikto-launcher-macos-arm64), macOS Intel (nikto-launcher-macos-amd64), Linux x86-64 (nikto-launcher-linux-amd64), Linux arm64 (nikto-launcher-linux-arm64), Windows x86-64 (nikto-launcher-windows-amd64.exe), Windows arm64 (nikto-launcher-windows-arm64.exe) |
Memory
The compose file caps each container's memory:
| Service | Memory cap |
|---|---|
| db (PostgreSQL) | 2 GB |
| api | 4 GB |
| ui | No cap |
| chromium | 2 GB (CHROMIUM_MEM_LIMIT) |
| chromium-relay | 128 MB |
These are ceilings, not measured usage. Size Docker's memory so every container can reach its cap:
| Memory available to Docker | |
|---|---|
| Minimum (no Headless Browser crawls) | 6 GB |
| Recommended (with Headless Browser crawls) | 8 GB or more |
Docker Desktop runs containers in a virtual machine with its own memory limit; on macOS it is under Settings → Resources. The machine itself needs more than that for the operating system and your browser. Recommendation: 16 GB of RAM on the host.
The launcher checks this for you: on up and update it warns when Docker has less than 6 GB (8 GB if the headless browser is enabled in .env). It is a warning, not an error, and it names how to raise the limit.
The db and api containers are each capped at 2 CPUs. Recommendation: 4 CPU cores or more.
Disk
The PostgreSQL volume (nikto-platform_pgdata) grows with use. It holds projects, scans, findings, the activity log of every request sent to a target, and stored responses. Large crawls and long-running projects are what make it grow. The images need space as well.
Recommendation: start with at least 20 GB free for Docker, and watch the volume as your scan history builds. This is a starting point, not a measured size.
The launcher warns on up and update when its install folder has less than 10 GB free (backups are written there). It cannot see inside Docker's own storage, and the check is skipped on Windows.
Linux: Headless Browser crawls
Chromium runs with its sandbox on, which needs unprivileged user namespaces enabled on the host. If your distribution disables them, the headless services fail to start. Docker Desktop on macOS and Windows is not affected.
On hosts that use AppArmor (Kali, Debian, Ubuntu), Docker's default AppArmor profile blocks the user namespace Chrome's sandbox needs. The chromium container therefore runs without an AppArmor profile; you do not need to change any host setting. Chrome's own sandbox, a restrictive seccomp profile, a non-root user, no Linux capabilities and a read-only filesystem still apply to it. No other container is affected.
Install with the launcher
Download the launcher for your platform from the release page.
On macOS and Linux, make it executable:
bashchmod +x nikto-launcher-*The macOS launchers are signed and notarized by Apple. The Windows launchers are not yet signed: SmartScreen warns on first run, so choose More info, then Run anyway.
Start the stack:
bash./nikto-launcher-macos-arm64 up --ghcr-user <github-user> --ghcr-token <token>Use the file name for your platform. The token is saved to the launcher's
.env, so later runs need onlyup.
On first run the launcher creates its install folder, generates a random database user and password, pulls the images, starts the stack, and opens the console in your browser.
Launcher commands
In the examples on this page, replace nikto-launcher with the file name you downloaded (for example ./nikto-launcher-linux-amd64).
| Command | What it does |
|---|---|
up | Log in, pull the pinned images, start the stack, open the console. --no-browser skips opening the browser. |
update | Pull the pinned images for this launcher version, back up the database, and recreate changed containers. --no-backup skips the backup. |
backup | Write a checked database backup to the backups folder. See Backups. |
restore <file> | Replace all current data with a backup. Asks first; --yes skips the question. See Backups. |
status | Show the containers and the console address. |
logs [service] | Follow logs for all services, or one (for example logs api). |
down | Stop and remove the containers. --volumes also deletes the database. |
reset-db-password | Re-sync the database password with .env. --random rotates it; --password <value> sets one. |
license | Print the license terms. |
version | Print the launcher version, and whether a newer launcher has been released. |
Full reference for every host command: Host Commands.
Launcher install folder
The launcher keeps its compose file, .env, and support files in a nikto-platform folder under your user configuration directory:
| OS | Folder |
|---|---|
| macOS | ~/Library/Application Support/nikto-platform |
| Linux | $XDG_CONFIG_HOME/nikto-platform, or ~/.config/nikto-platform when that is unset |
| Windows | %AppData%\nikto-platform |
The launcher rewrites the compose file and support files on every command that runs Docker Compose, so edits to them do not last. It creates .env once and never overwrites it.
Putting the install folder somewhere else
Pass --home PATH, or set NIKTO_HOME=PATH, to move the whole deployment — .env, the database secret, the installed license, the compose files, and the database volume path — to a directory you choose:
bash
nikto-launcher --home /srv/nikto upRules:
- The path must be absolute. A relative
NIKTO_HOMEis refused rather than resolved against whatever directory you happen to be in — the fixed folder exists to remove that ambiguity.~is expanded. - Use the same
--home(or keepNIKTO_HOMEexported) for every command. Without it the launcher uses the default folder above, which is a different, empty deployment — not an error you want to discover during a restore. - Unset means today's path, unchanged. An
.envleft in some other directory was always ignored; this is the supported way to relocate.
The database password lives in .env (POSTGRES_PASSWORD). On each of those commands the launcher copies it into secrets/db_password, which Docker mounts into the database and API containers as a file, so the password does not appear in docker inspect or docker compose config. Do not edit secrets/db_password: the launcher overwrites it from .env every time. It is readable by the containers' own users, and the install folder around it is readable only by you.
Newer-launcher check
After a successful up or update, and on version, the launcher asks ghcr.io — the registry it already pulls the images from, using the GHCR_USER/GHCR_TOKEN in .env — for the newest release tag. If a newer launcher exists it prints one line saying so and where to download it. The check takes at most 5 seconds and never stops the command; if it cannot reach ghcr.io it prints one Could not check for a newer launcher: ... line.
On an air-gapped or egress-filtered host, turn it off with --no-update-check or by setting NIKTO_NO_UPDATE_CHECK=1 in the environment. Details: Host Commands.
Advanced: docker compose
The launcher writes a normal docker-compose.yml and .env into its install folder. If you are comfortable with Docker Compose, you can run docker compose commands from that folder, for example:
bash
docker compose -f docker-compose.yml --env-file .env psThe Compose project name is nikto-platform. Containers need secrets/db_password, which any launcher command writes from .env; run nikto-launcher status first if you changed .env or the file is missing. Use the launcher for updates and backups: nikto-launcher update checks the images are pinned and backs up the database first, which a plain docker compose pull does not.
Console address
The console listens on port 3001 (UI_PORT in .env). It is published on 127.0.0.1 only, so it is reachable from the machine that runs Docker and not from other machines on the network. To use it from another computer, see Remote Access.
Headless browser
The Headless Browser crawl engine needs Chromium. The Standard engine does not, and neither do Nikto, LFIC, or Bustah.
The shipped .env turns Chromium on with this line:
bash
COMPOSE_PROFILES=headlessTo run without Chromium, remove that line from .env in the install folder, then stop the browser services. Stop both together, from that folder:
bash
docker compose -f docker-compose.yml --env-file .env stop chromium chromium-relayWhen Chromium is not running, the console disables only the Headless Browser engine. Standard crawls still launch.
The browser has no direct internet access and no route to the host machine. It sends traffic through the scanner's logged proxy, which applies the same address-tier rules as other tools.
Browser hardening
- The Chromium sandbox stays on. A Headless Browser crawl is refused unless the sandbox is confirmed when the crawl starts.
- The shipped configuration lets 2 Headless Browser crawls use the browser at the same time.
- The browser debug port is not published to the host.
CHROMIUM_MEM_LIMIT(default2g) andCHROMIUM_SHM_SIZE(default1g) in.envchange the browser's memory. The shared-memory size counts against the memory cap, so raiseCHROMIUM_MEM_LIMITrather than loweringCHROMIUM_SHM_SIZE.
License file
Install a license in Global Settings → License. See License.
If no license is installed, new work is blocked.
Environment
These .env settings take effect in the shipped compose file:
| Variable | Default | Purpose |
|---|---|---|
GHCR_USER / GHCR_TOKEN | (empty) | Credentials used to pull the images |
UI_PORT | 3001 | Host port for the console (bound to 127.0.0.1) |
AUTH | on | Require operator login for the console. Set off only on a single-user machine — see Operator Login |
POSTGRES_DB | nplatform | Database name |
POSTGRES_USER / POSTGRES_PASSWORD | Generated on first start | Database credentials. Do not edit them; see below |
COMPOSE_PROFILES | headless | Starts Chromium for Headless Browser crawls |
CHROMIUM_MEM_LIMIT | 2g | Chromium memory cap |
CHROMIUM_SHM_SIZE | 1g | Chromium shared memory |
The database keeps the credentials it was created with. Editing POSTGRES_USER or POSTGRES_PASSWORD in .env afterward locks the API out. The API reads the password from secrets/db_password, which the launcher writes from .env (see install folder).
If the password in .env and the database no longer match, run nikto-launcher reset-db-password. It sets the database password to the one in .env. Add --random to rotate to a new password instead. It does not change the user name.
What is running
| Service | Role |
|---|---|
| db-init | Runs once at start to set ownership of the database volume, then exits. |
| db | PostgreSQL. Not published to the host; only the API connects. |
| api | The application and background workers. Not published to the host. |
| ui | The console. |
| chromium + chromium-relay | Headless browser, only with the headless profile. |
The API talks to the database on an internal network and sends scan traffic on a separate outbound network. The browser network has no route to the internet or the host.
Uninstall
Uninstalling deletes all scan data
Uninstall deletes the database volume nikto-platform_pgdata: every project, scan, finding, log, and installed license. It also deletes the install folder, including your backups in it. It cannot be undone.
Run:
bash
./nikto-launcher uninstallIt shows exactly what it will delete and asks you to confirm, then offers a final backup in your Downloads folder (outside the install folder) and verifies it before deleting anything. It then removes the containers, the database volume, the install folder, and the images. At the end it prints where the backup is and how to restore it, the path of the launcher binary to delete by hand, and how to clear the saved ghcr.io login (docker logout ghcr.io). Options, the exact prompts, and unattended use: Host Commands → Uninstall.
To stop the platform but keep the data for later, run ./nikto-launcher down instead and keep the install folder: the database accepts only the user and password recorded in its .env, so a fresh install cannot open the old database.
Next steps
- Getting Started — first project and scan
- Backups — what each update saves, and how to restore
- Remote Access — use the console from another computer
- License — install and manage licenses
- Scan Scope & Address Tiers — what a scan may follow
- Web Crawler — Standard vs Headless Browser