Skip to content

Set up your lab

Start hereIntro⏱ ~25 min🧪 Lab 0 (auto-checked)

Every lab in this course runs against a real SpatiumDDI on your own machine: the release the videos were recorded on, with a BIND9 DNS server and a Kea DHCP server attached. One script starts it, and another grades your work. You set it up once here and use it until the end of Part 2.

The lab is a Docker Compose project in the course’s lab/ folder, pinned to SpatiumDDI 1.0.0-beta.3. Its docker-compose.yml is the release’s own Compose file, unchanged except for the project name, spatium-academy.

Container Role
frontend The web UI, on port 8077. It also passes /api/ to the API, so the REST API and its docs answer on 8077 too
api The REST API. Its own port, 8000, is published on 127.0.0.1 only
worker, beat Background jobs, and the scheduler that triggers them
postgres, redis The database that holds every setting and object, and the message broker. Neither is published
migrate Applies the database migrations, then exits
dns-bind9 BIND9 plus the SpatiumDDI agent, answering DNS on port 1053
dhcp-kea Kea plus the SpatiumDDI agent

The two agents register themselves with the control plane as they start, using the bootstrap keys in lab/.env. Nobody adds them by hand; module 1.4 shows how it works.

  • Docker. Docker Desktop on macOS or Windows. On Linux, Docker Engine with the Compose v2 plugin: the command is docker compose, not the older docker-compose. SpatiumDDI’s Docker guide asks for Docker Engine 25 or later and Compose 2.20 or later.
  • Memory. A freshly started lab uses about 1.4 GB of RAM: the worker about 0.7 GB, the API about 0.3 GB, and the rest little. The worker grows during its first hour. Give Docker at least 4 GB; in Docker Desktop, that’s one of the resource settings. SpatiumDDI’s sizing guide recommends 8 GB for a Docker Compose installation.
  • Download. The first start downloads about 500 MB of images, which take about 2 GB of disk.
  • A shell. The scripts are bash and use curl and openssl, which macOS and most Linux distributions include. On Windows, run them from a WSL 2 shell, with Docker Desktop’s WSL integration turned on for your distribution.
  • dig, from Lab 2 on. macOS includes it. On Debian or Ubuntu, WSL included, install the dnsutils package; on Fedora or RHEL, bind-utils. Lab 8 also uses python3.
  • Free ports: 8077, 8000, 1053, 6767 and 8001. Ports explains each one.

Apple Silicon Macs work as they are: the images are multi-architecture, and the course was recorded on an arm64 machine.

The lab kit is the course’s lab/ folder: the Compose file, the scripts that start and reset the lab, and the checker. Download spatiumddi-academy-lab.zip (about 50 KB) and unzip it, or do both from a terminal:

Terminal window
curl -LO https://academy.spatiumddi.com/downloads/spatiumddi-academy-lab.zip
unzip spatiumddi-academy-lab.zip
cd spatiumddi-academy

The spatiumddi-academy folder, with lab/ inside it, is your course folder: run every ./lab/… command in the course from there. If you’re using the offline course package, lab/ is already in it, and the course folder is the one you unzipped.

Hands-on lab 0 · about 20 min

Start SpatiumDDI with BIND9 and Kea

You will:

  • Start the pinned SpatiumDDI lab with its BIND9 and Kea servers
  • Confirm that both servers registered and that the web UI answers

Before you start: Docker is running with at least 4 GB of memory, and a terminal is open in the course folder (the folder that contains lab/).

  1. Check that Compose v2 is available: docker compose version should print a v2 version.

  2. Start the lab, keeping the default admin account for Lab 1:

    Terminal window
    ./lab/up.sh --first-login
  3. Wait for the summary that starts with “SpatiumDDI lab is up.” On the first run, the script creates lab/.env with fresh secrets, pulls the images, applies the database migrations, starts the stack and waits for the API. The summary lists the web UI and the REST API with its docs, all on port 8077.

  4. In a second terminal, change into lab/ and run docker compose ps. Every service should be running, and api should report healthy.

  5. Open http://localhost:8077. You should see the SpatiumDDI sign-in page. Don’t sign in yet: that’s Lab 1.

✅ Check your work from the course folder:./lab/check.sh 0

--first-login leaves the built-in admin account at admin / admin with its forced password change still pending, so that you can make the change yourself in Lab 1. If you started with plain ./lab/up.sh, run ./lab/reset-admin.sh before Lab 1.

The Lab 0 check confirms that the API is up, and that dns-bind9 and dhcp-kea are registered and active in their default server groups.

Once you’ve signed in during Lab 1, a healthy lab’s dashboard looks like this. The screenshot was taken at the end of the course, so your counts will be lower, and the environment banner only appears once you add it in Lab 1.

SpatiumDDI dashboard showing the environment banner, platform health all good and no agents needing attention.
A healthy lab: no agents needing attention, Platform Health all good, and the pinned release at the bottom of the sidebar. · SpatiumDDI 1.0.0-beta.3
  1. Environment banner: you are in the training lab, not production
  2. Agents needing attention: 0 means BIND9 and Kea are registered and healthy
  3. Platform Health: API, PostgreSQL, Redis, Celery workers and beat
  4. Release you are running (the course targets 1.0.0-beta.3)

A new lab also starts lean: Features & Integrations reads “16 of 57 enabled”, so the sidebar shows only what a new installation needs. Module 1.3 explains feature modules.

Run these from the course folder.

Command What it does
./lab/up.sh --first-login Starts or resumes the lab and leaves admin / admin with its forced password change, for Lab 1
./lab/up.sh Starts or resumes the lab. If admin still has the default password, sets it to LAB_ADMIN_PASSWORD
./lab/up.sh --seed Also loads the upstream demo data (a Corporate space, corp.example.com and more), for exploring only
./lab/down.sh Stops the lab and keeps its data. ./lab/up.sh resumes it
./lab/destroy.sh Stops the lab and deletes all of its data. The next start is a factory-fresh SpatiumDDI
./lab/reset-admin.sh Puts admin back to admin / admin, with a forced change at the next sign-in, and clears its password history so that you can reuse LAB_ADMIN_PASSWORD. The lab must be running
./lab/check.sh <n> Grades lab n. Use all for every lab, or a list such as 2,5
Host port Service Set in
8077/tcp Web UI, plus the REST API and its docs under /api/ HTTP_PORT in lab/.env
8000/tcp, on 127.0.0.1 only The API directly. ./lab/up.sh checks it; the course uses 8077 API_PORT in lab/.env
1053/udp and 1053/tcp BIND9 (port 53 inside the container) lab/docker-compose.yml
6767/udp Kea (port 67 inside the container) lab/docker-compose.yml
8001/tcp Kea’s high-availability peer port, unused in the course lab/docker-compose.yml
  • PostgreSQL and Redis aren’t published at all.
  • DNS and DHCP sit on high port numbers so they can’t clash with a resolver or another service already using 53 or 67 on your machine. That’s why every dig in the course says @127.0.0.1 -p 1053.
  • The lab has no real DHCP clients: Docker’s port mapping doesn’t carry DHCP broadcasts from your network. Leases stay empty, so the DHCP labs check configuration, not leases.
  • Docker publishes the web UI, DNS and DHCP ports on all of your machine’s network interfaces, and the API’s port on 127.0.0.1 only, as SpatiumDDI’s own Compose file does. The lab’s admin password is printed in this course, so run the lab on a network you trust, and never expose it to the internet.

On its first run, ./lab/up.sh creates lab/.env from lab/.env.example and fills every secret with a fresh random value. You’ll read two values from it; leave the rest alone.

Setting Default What it’s for
SPATIUMDDI_VERSION 1.0.0-beta.3 The release the course targets. Keep it
COMPOSE_PROFILES dns-bind9,dhcp Starts the BIND9 and Kea agents with the control plane
HTTP_PORT, API_PORT 8077, 8000 Host ports for the web UI and the API
LAB_ADMIN_PASSWORD Ridgeline-Lab-2026! The password the scripts expect admin to have after Lab 1
POSTGRES_PASSWORD, SECRET_KEY, the agent keys Random Generated on the first run
  • lab/.env holds your lab’s real secrets. Keep it out of chats, screenshots and version control.
  • ./lab/destroy.sh keeps lab/.env. Don’t delete the file while the lab still has data: a new file brings new secrets that no longer match the existing database. To start completely fresh, run ./lab/destroy.sh first.

./lab/up.sh stops with a Docker error saying that a port is already allocated or in use. On macOS or Linux, find what holds it with lsof -nP -iTCP:8077 for a TCP port, or lsof -nP -iUDP:1053 for a UDP port.

  • 8077 or 8000. Stop the other program, or change HTTP_PORT or API_PORT in lab/.env, which exists after the first attempt, and run ./lab/up.sh again. Your secrets are kept. If you change a port, use yours wherever the course says 8077 or 8000.
  • 1053, 6767 or 8001. Free the port. These are fixed in lab/docker-compose.yml, and the course’s commands assume 1053.

The script seems stuck at “pulling images”

Section titled “The script seems stuck at “pulling images””

The first run downloads about 500 MB without showing progress, so on a slow connection it can sit there for a while. If the pull fails, check that your network, VPN or proxy lets you reach ghcr.io, where the SpatiumDDI images are published, and Docker Hub, which serves the PostgreSQL and Redis images.

The script waits a few minutes for the API. If it gives up, it stops with API did not become healthy within 180s. From inside lab/, see which service isn’t running and read its log:

Terminal window
docker compose ps
docker compose logs api

Also check that Docker has at least 4 GB of memory.

Lab 0’s check says a server isn’t registered

Section titled “Lab 0’s check says a server isn’t registered”

The agents register within seconds of starting, but a busy machine can take longer. Wait a minute and run ./lab/check.sh 0 again. If a check still fails, read that agent’s log from inside lab/: docker compose logs dns-bind9 or docker compose logs dhcp-kea. If the checker says “The lab isn’t running”, start it with ./lab/up.sh.

SpatiumDDI signs out a console that has been idle for 60 minutes and returns it to the sign-in page. Sign in again: everything you saved is still there. Module 1.2 shows where the timeout is set.

“Could not sign in as admin with the lab password or admin/admin”

Section titled ““Could not sign in as admin with the lab password or admin/admin””

./lab/up.sh prints this when admin has a password the script doesn’t know, usually because you chose something other than LAB_ADMIN_PASSWORD in Lab 1. The lab is running anyway. Run ./lab/reset-admin.sh, then ./lab/up.sh, which sets the password to LAB_ADMIN_PASSWORD for you.

Run the scripts from a WSL 2 shell, not from PowerShell or Command Prompt, and turn on Docker Desktop’s WSL integration for your distribution. If a script reports “Permission denied”, run it through bash instead, for example bash lab/up.sh --first-login.

Nothing to change. The images run natively on arm64, and the course was recorded on an arm64 machine.

./lab/destroy.sh, then ./lab/up.sh --first-login, gives you a factory-fresh SpatiumDDI. You lose everything you built, so redo the labs in order.

With Lab 0 passing, start Part 1 with 1.1 DDI in one control plane.