A friendly command-line tool for managing a HashiCorp Nomad homelab cluster.
Project description
nd
A friendly command-line tool for managing a Nomad cluster.
nd wraps the Nomad HTTP API and the local nomad binary behind a small set of
task-focused commands. Instead of stitching together multiple nomad commands, you
get easy to remember commands that marry your on-disk job and volume files and the
live cluster. No more no more hunting for an allocation ID or task name, just use
your easy to remember job and volume names and the cli does the rest.
Features
- A one-screen cluster dashboard covering nodes, jobs, allocations, deployments, evaluations, and host volumes.
- Deploy and stop commands that watch the rollout or drain live and report a clear success or failure at the end.
- Job-file aware commands that discover and work with your local
.hcland.nomadspecs - Interactive shell and log streaming for any task, with a prompt to pick the job, allocation, and task when the choice is ambiguous.
- Dynamic host volume management: register, delete, and list host volumes across every eligible node.
- Standard
NOMAD_*environment variables work out of the box, with an optional config file for anything you would rather not retype.
Requirements
- Python 3.13 or 3.14.
- A reachable Nomad cluster.
- The
nomadbinary on yourPATH. Theplan,run,exec, andlogscommands shell out to it, because the HTTP API cannot parse HCL2 job files and does not own the interactive exec protocol. The other commands use the API only.
Installation
The tool is published to PyPI as nomadctl. The installed command is nd.
Install it as an isolated CLI with uv:
uv tool install nomadctl
Or with pipx:
pipx install nomadctl
Confirm the install:
nd --version
Configuration
nd reads the standard Nomad environment variables first, then overrides them with
an optional config file. If you already run nomad from your shell, nd targets
the same cluster with no extra setup.
Environment variables
| Variable | Purpose | Default |
|---|---|---|
NOMAD_ADDR |
Cluster API address | http://127.0.0.1:4646 |
NOMAD_TOKEN |
ACL token | none |
NOMAD_NAMESPACE |
Default namespace | none |
NOMAD_REGION |
Default region | none |
NOMAD_CACERT |
Path to a CA certificate | none |
NOMAD_CLIENT_CERT |
Path to a client certificate | none |
NOMAD_CLIENT_KEY |
Path to a client key | none |
NOMAD_TLS_SERVER_NAME |
TLS server name override | none |
NOMAD_UI_URL |
Base URL for web UI links | falls back to NOMAD_ADDR |
Config file
For settings you do not want to export every session, create
~/.config/nd/config.toml (or $XDG_CONFIG_HOME/nd/config.toml). Values here
override the environment.
[nomad]
address = "https://nomad.example.com:4646"
token = "your-acl-token"
ui_url = "https://nomad.example.com"
# Directories nd searches for .hcl and .nomad job files.
[jobs]
directories = ["~/homelab/jobs"]
# Directories nd searches for host volume spec files.
[volumes]
directories = ["~/homelab/volumes"]
The [jobs] and [volumes] directory lists power the file-aware commands. Without
them, list, plan, run, and the volume commands have nothing to discover.
Quick start
Point nd at your cluster, then look at it:
export NOMAD_ADDR="https://nomad.example.com:4646"
export NOMAD_TOKEN="your-acl-token"
nd
Add a job directory to your config file, then list your specs against the live cluster:
nd list
Deploy a job that is not yet running and watch it roll out:
nd run web
Tail its logs, then open a shell inside it:
nd logs web
nd exec web
Commands
Run nd --help, or nd <command> --help, for the full option list at any time.
| Command | What it does |
|---|---|
nd status |
Show an at-a-glance overview of the cluster. Also runs when you type nd alone. |
nd list |
List discovered job files and whether each is running, dead, or not deployed. |
nd plan [JOB] |
Preview the changes one or more job files would apply, including to running jobs. |
nd run [JOB] |
Deploy not-yet-running job files and watch the rollout. |
nd stop [JOB] |
Stop, and optionally purge, running jobs and watch them drain. |
nd logs [JOB] |
Stream, tail, or export a task's logs. |
nd exec [JOB] |
Open an interactive shell inside a running task. |
nd clean |
Force garbage collection and reconcile job summaries. |
nd volume register [NAME] |
Register host volumes on every eligible node. |
nd volume delete [NAME] |
Delete registered host volumes matching the selected specs. |
nd volume list [NAME] |
List host volume specs and where each is registered. |
Targeting jobs by name
Commands that take a JOB or NAME argument match by case-insensitive name prefix.
A single match runs straight away; several matches open a prompt. Omit the argument
to pick from a list of every candidate.
nd run web # runs the one job whose name starts with "web"
nd stop # prompts you to choose from all running jobs
Previewing before you act
Lifecycle commands accept --dry-run (-n) to report their targets without
touching the cluster:
nd run --dry-run
nd stop web --dry-run
nd volume register --dry-run
For nd run, a dry run still validates each job file locally, so it catches a
broken spec without registering anything.
Deploying jobs
nd run only offers jobs that are not already running. Each selected file is
validated and registered, then watched live until its deployment or allocations
settle. Use --detach to register and return without watching the rollout.
nd run # choose from every deployable job
nd run web # deploy the job whose name starts with "web"
nd run web --detach # register and return immediately
Working with logs
nd logs streams both stdout and stderr live until you press Ctrl-C. Narrow or
redirect the output with flags:
nd logs web # follow stdout and stderr
nd logs web --stderr # follow stderr only
nd logs web --tail 100 # print the last 100 lines, no follow
nd logs web --export run.log # write the current logs to a file
Stopping jobs
nd stop confirms before it acts unless you pass --force. Use --purge to
garbage-collect the job afterward, --detach to return without watching the drain,
and --no-shutdown-delay to skip the configured shutdown delays for an immediate
teardown.
nd stop web # confirm, stop, and watch it drain
nd stop web --purge --force # purge without a prompt
nd stop web --detach # request the stop and return immediately
Verbosity
Add -v for debug output or -vv to trace each API request with timings. The flag
works before or after the subcommand.
nd status -v
nd -vv run web
Development
The project uses uv for dependency management and duty as a task runner.
uv sync # install dependencies
uv run nd --help # run the CLI from source
uv run duty lint # run ruff, ty, typos, and prek
uv run duty test # run the test suite with coverage
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nomadctl-0.2.0.tar.gz.
File metadata
- Download URL: nomadctl-0.2.0.tar.gz
- Upload date:
- Size: 57.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea1af99b710f2dd29ccd57c039d0a9e42002f18fdc39a9143c5eb0f1004ef883
|
|
| MD5 |
ee31a9e6d7528107504516368acc5507
|
|
| BLAKE2b-256 |
0e82e541508392700f4d696b88b3e54d209b977a0b8224f08c83b3cfbca69074
|
File details
Details for the file nomadctl-0.2.0-py3-none-any.whl.
File metadata
- Download URL: nomadctl-0.2.0-py3-none-any.whl
- Upload date:
- Size: 82.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5dd638c552502c98fe218d2f721037ed0d74b598eae259908d7ecb702d6d029
|
|
| MD5 |
78aaefa4392838c35ae7dba3ceefd4f9
|
|
| BLAKE2b-256 |
94326dc5ae15f9de80585a5886a47deab536b772259546cf1620b2af2d48949c
|