Skip to content

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 ​

RequirementMinimumCheck with
Docker Engine (or Docker Desktop)28.0docker version (Server → Version)
Docker Composev2 (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 colima

If 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:

DistributionDistro packagesWorks?Install
Kali (2026.3, desktop)docker.io 28.5, docker-compose 2.40Yessudo apt install docker.io docker-compose
Ubuntu 24.04 / 26.04docker.io 29.x; Compose is a separate packageYessudo apt install docker.io docker-compose-v2
Amazon Linux 2023docker 25No: Engine too oldDocker's own repository (below)
Ubuntu 22.04 and olderdocker.io predates Engine 28No: Engine too old (untested)Docker's own repository (below)
Debian 13docker.io 26.1No: Engine too oldDocker's own repository (below)
Debian 12docker.io 20.10, docker-compose 1.29No: both too oldDocker'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 amzn2023 build, so use the CentOS repo pinned to EL9:
    bash
    sudo 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/ubuntu and your own release codename in place of .../linux/debian and bookworm. A Kali cloud image can ship only a docker CLI with no daemon (so docker version shows a Client but docker.service is missing); installing docker-ce from 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 docker
    (gnupg and curl must 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 locally

Open 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 as kali.
  • 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 ​

ComponentAvailable for
API and console imageslinux/amd64, linux/arm64
LaunchermacOS 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:

ServiceMemory cap
db (PostgreSQL)2 GB
api4 GB
uiNo cap
chromium2 GB (CHROMIUM_MEM_LIMIT)
chromium-relay128 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 ​

  1. Download the launcher for your platform from the release page.

  2. On macOS and Linux, make it executable:

    bash
    chmod +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.

  3. 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 only up.

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).

CommandWhat it does
upLog in, pull the pinned images, start the stack, open the console. --no-browser skips opening the browser.
updatePull the pinned images for this launcher version, back up the database, and recreate changed containers. --no-backup skips the backup.
backupWrite 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.
statusShow the containers and the console address.
logs [service]Follow logs for all services, or one (for example logs api).
downStop and remove the containers. --volumes also deletes the database.
reset-db-passwordRe-sync the database password with .env. --random rotates it; --password <value> sets one.
licensePrint the license terms.
versionPrint 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:

OSFolder
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 up

Rules:

  • The path must be absolute. A relative NIKTO_HOME is 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 keep NIKTO_HOME exported) 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 .env left 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 ps

The 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=headless

To 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-relay

When 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 (default 2g) and CHROMIUM_SHM_SIZE (default 1g) in .env change the browser's memory. The shared-memory size counts against the memory cap, so raise CHROMIUM_MEM_LIMIT rather than lowering CHROMIUM_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:

VariableDefaultPurpose
GHCR_USER / GHCR_TOKEN(empty)Credentials used to pull the images
UI_PORT3001Host port for the console (bound to 127.0.0.1)
AUTHonRequire operator login for the console. Set off only on a single-user machine — see Operator Login
POSTGRES_DBnplatformDatabase name
POSTGRES_USER / POSTGRES_PASSWORDGenerated on first startDatabase credentials. Do not edit them; see below
COMPOSE_PROFILESheadlessStarts Chromium for Headless Browser crawls
CHROMIUM_MEM_LIMIT2gChromium memory cap
CHROMIUM_SHM_SIZE1gChromium 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 ​

ServiceRole
db-initRuns once at start to set ownership of the database volume, then exits.
dbPostgreSQL. Not published to the host; only the API connects.
apiThe application and background workers. Not published to the host.
uiThe console.
chromium + chromium-relayHeadless 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 uninstall

It 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 ​

Proprietary software. Licensed for use under the End User License Agreement.