Skip to content

Quick start

A working install in about ten minutes

Edit this page
On this page

A working Loomscope — control plane, database, worker and one scanning daemon — in about ten minutes. You need Docker and Docker Compose, and a network you are authorised to scan.

For a production install read Docker Compose and Configuration instead; this page takes the shortest honest path, and says where it cuts a corner.

1. Get the repository

bash
git clone https://github.com/bendaamerahmed/loomscope.git
cd loomscope
cp .env.example .env

2. Generate the secrets

Four values in .env are marked REQUIRED. The compose file references them with the ${VAR:?} form, so compose aborts rather than starting with a blank value — deliberately, because that is what stops a half-configured install from coming up looking healthy.

bash
openssl rand -hex 32     # BETTER_AUTH_SECRET — signs sessions
openssl rand -base64 32  # LOOMSCOPE_KMS_KEY  — encrypts stored credentials
openssl rand -hex 24     # POSTGRES_PASSWORD  — database password

Use -hex for POSTGRES_PASSWORD, not -base64. That value ends up inside DATABASE_URL, and base64 output contains / and + about half the time, which makes the connection string an invalid URL that the driver refuses outright.

LOOMSCOPE_KMS_KEY is the one to guard. It encrypts every credential Loomscope stores. Lose it and those are unrecoverable; leak it and treat them all as compromised. Keep a copy somewhere that is not the server.

The fourth, LOOMSCOPE_DAEMON_API_KEY, does not exist yet — you mint it in step 4.

3. Start the database and control plane

bash
docker compose -f infra/docker-compose.yml up -d postgres server

Migrations are never applied automatically, in any environment. With more than one control-plane replica, automatic migration means every replica racing to alter the same schema at boot. Apply them yourself:

bash
docker compose -f infra/docker-compose.yml run --rm server node --experimental-strip-types apps/server/server/db/migrate.ts

The runner records each file in a __migrations table and skips what is already applied, so re-running it is safe.

4. Create the organisation and enrol a daemon

Open http://localhost:3000. A deployment with no organisation sends you to Set up Loomscope, which creates the organisation and its first account, then closes itself — the page cannot be reached again once an organisation exists, so it is not a standing door into a running deployment.

Sign in, then go to Settings → Daemons and enrol one. The key is shown once, like an invitation link: only its hash is stored, so a lost key is replaced rather than recovered.

Copy it into .env:

bash
LOOMSCOPE_DAEMON_API_KEY=lsk_...
LOOMSCOPE_DAEMON_NAME=default

Then start the scanner and the job worker:

bash
docker compose -f infra/docker-compose.yml up -d daemon worker

5. Add a network

Nothing is scanned until a network exists — Loomscope never probes a range you have not declared. Go to Networks → Add network and enter a CIDR, IPv4 or IPv6. Start with one small range.

A /24 completes a cold scan in under 30 seconds on a normal network. Open Hosts; results appear as they arrive and the page updates live over SSE.

If nothing appears

Two causes account for almost all of it.

The daemon cannot send an ICMP echo. Check for the fallback warning:

bash
docker logs loomscope-daemon | grep "falling back to TCP"

Without that one privileged operation the sweep degrades to TCP probes on 80, 443 and 22 — which finds web servers and misses printers, cameras and anything else that is up but serving nothing. Deploying daemons explains both supported ways to grant it.

A firewall is dropping the probes, or the daemon has no layer-2 reachability to the range. A host that answers nothing at all will not be discovered by active scanning; that is what SNMP, ARP-table collection and flow data are for.

What this quick start skipped

SkippedWhy it mattersWhere it is covered
TLS terminationPort 3000 is cleartext. Fine on a laptop, wrong for anything elseTLS and reverse proxy
Resource limitsThe compose file sets none, so a runaway scan can consume the hostScaling
BackupsThe database and the encryption key have to survive togetherBackup and restore
Single sign-onLocal accounts suit one team, not a directory that owns the user listSingle sign-on
An offline CVE mirrorWithout one, vulnerability matching needs internet accessAir-gapped installation