This pulls together every piece of the NicTool DNS management stack -- the legacy Perl v2, the Node.js v3 API and web UI, shared libraries, and research notes -- so you can run them side by side from a single docker compose up.
The idea is straightforward: v2 running next to v3, sharing the same MariaDB, on the same machine. Compare behavior, contribute to v3, run end-to-end tests across both generations.
| Path | What it is | Upstream |
|---|---|---|
api/ |
v3 REST API (Hapi, MySQL2) | NicTool/api |
server/ |
v3 Web UI + configurator | NicTool/server |
NicTool/ |
Legacy Perl v2 (Apache + mod_perl) | NicTool/NicTool |
libs/validate/ |
Joi-based DNS object validation | NicTool/validate |
libs/dns-zone/ |
Zone import/export (BIND, tinydns, maradns, JSON) | NicTool/dns-zone |
libs/dns-nameserver/ |
Nameserver management | NicTool/dns-nameserver |
libs/dns-resource-record/ |
Resource record handling | NicTool/dns-resource-record |
research/ |
LLM-generated audits, gap analyses, design notes | NicTool/research |
Every path is a git submodule pointing to the NicTool org upstream. If you want to contribute from your own fork, make fork sets that up automatically (see below).
A handful of things on a fresh macOS machine. Everything else (Node 22, MariaDB 11, Perl) runs inside Docker containers.
Homebrew, if you don't already have it:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"Then install the rest:
brew install colima docker docker-compose git
colima startWe use Colima as the container runtime -- it's free, lightweight, and doesn't require a Docker Desktop license. Colima needs to be running before any docker compose or make up-* commands work. After a reboot, just colima start again.
Podman also works if you prefer it, but the Makefile and compose file are written for the Docker CLI.
No Perl setup needed on your host -- the legacy v2 stack runs entirely inside Docker.
Clone, initialize, generate credentials, and bring up the stack:
git clone https://github.com/NicTool/monorepo.git
cd monorepo
make init
make env
make upmake init checks out all submodules recursively. Node.js dependencies are installed inside the Docker containers during make up, so nothing is installed on your host.
SSH clone errors? Some upstream submodules (notably
api/.releaseandlibs/validate/.release) reference a dependency via SSH (git@github.com:...). If you don't have SSH keys configured for GitHub,make initwill fail with "Permission denied (publickey)." Fix it by telling git to use HTTPS instead:git config --global url."https://github.com/".insteadOf "git@github.com:"Then re-run
make init.
make env creates docker/.env with randomly generated passwords via openssl rand -- it won't overwrite an existing file, so it's safe to run more than once. Edit docker/.env directly to customize ports or credentials (see docker/.env.example for the full list).
Pick whichever slice of the stack you need:
make up # v3 core (MariaDB + API)
make up-ui # v3 full stack (MariaDB + API + Web UI)
make up-legacy # Legacy Perl v2 (MariaDB + NicTool v2)
make up-all # Everything at onceThe first run builds all Docker images, which takes a few minutes. After that, layer caching keeps it fast.
Once the containers are healthy:
| Service | URL | What you should see |
|---|---|---|
| v3 API | http://localhost:3000/documentation | Swagger/Hapi docs page |
| v3 Web UI | http://localhost:8080 | NicTool v3 login page |
| v2 Legacy (HTTP) | http://localhost:8082 | Classic NicTool login page |
| v2 Legacy (HTTPS) | https://localhost:8443 | Same, with self-signed cert |
| MariaDB | localhost:3307 |
Connect with any MySQL client |
All ports are configurable in docker/.env.
| Profile | Services started |
|---|---|
| (default) | db + api |
ui |
db + api + server |
legacy |
db + nictool-legacy |
e2e |
db + api + server |
all |
All four services |
All tests run inside containers -- nothing is installed on your host.
make test # API + library tests (requires make up)
make test-api # just the API tests
make test-server # just the server tests (requires make up-ui)
make test-libs # just the four libraries (no running services needed)make test-api and make test-server exec into the running containers. make test-libs spins up ephemeral node:22 containers for each library. The API integration tests need a running database, so run make up first.
The v2 container has its own Perl test suites. These run inside the container against the shared MariaDB:
make test-v2 # runs everything below in sequence
make test-v2-xt # just the extended tests (see below)make test-v2 runs three things in order: the server unit tests, the client unit tests, and then the extended ("xt") integration tests. The xt tests exercise cross-group permissions, zone delegation, and other multi-object interactions that require a running database with seeded data. make test-v2-xt runs only that last step, which is useful when you're iterating on permission or delegation logic and don't want to wait for the full suite.
The compose file bind-mounts source directories into each container, so code changes on your host are reflected immediately without rebuilding. Just restart the affected service:
docker compose --env-file docker/.env --profile all restart # restart all
docker compose --env-file docker/.env restart api # restart oneYou only need --build when you change a Dockerfile or dependencies (package.json, Makefile.PL).
Tear down when you're done:
make clean # stops everything and deletes volumesmake help # list all targets
make logs # tail logs from all services
make down # stop everything (keeps data)
make clean # stop everything and delete volumes (fresh start)
make sync # update all submodules to latest from their tracked branch
make test # run v3 API + library tests (requires make up)
make test-api # run v3 API tests only
make test-server # run v3 server tests only (requires make up-ui)
make test-libs # run library tests (no running services needed)
make test-v2 # run all v2 Perl tests (server, client, and extended; requires up-legacy)
make test-v2-xt # run only v2 extended integration tests (permissions, delegation)The submodules point to the NicTool org by default. To fork everything into your own GitHub account and repoint the submodules:
make forkThis uses gh to fork each upstream repo, then sets origin to your fork and upstream to NicTool. You'll need gh auth login first.
To pull in the latest from upstream at any point:
make syncmonorepo/
docker/
.env.example # reference for environment variables
.env # generated credentials (gitignored)
generate-env.sh # creates .env with random passwords
docker-compose.yml # all services, all profiles
Makefile # task runner
pnpm-workspace.yaml # Node.js workspace config
package.json # monorepo root (test + lint scripts)
api/ # [submodule] v3 REST API
server/ # [submodule] v3 Web UI
NicTool/ # [submodule] Legacy Perl v2
research/ # [submodule] audits, gap analyses, design notes
libs/
validate/ # [submodule] DNS validation
dns-zone/ # [submodule] zone import/export
dns-nameserver/ # [submodule] nameserver management
dns-resource-record/ # [submodule] resource record handling
/swagger.jsonreturns a 500 due to a Joi version mismatch between the API and the swagger plugin. The API itself works fine -- it's just the generated schema that breaks.- The legacy v2 entrypoint generates a test user (
nictest@test_group) with a random password stored at/usr/local/nictool/server/t/test.cfginside the container.