Skip to content

svandragt/itool

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 

Repository files navigation

itool — local internal tools runner

itool.sh is a small CLI for running many independent internal tools on a single machine in a predictable, conflict-free way using Docker.

The design is intentionally conservative: machine-local facts live in a registry, application facts stay inside projects, and itool only glues the two together.


What’s in this repository

.
├── itool.sh      # the CLI (symlink this into your PATH)
└── README.md     # this document

After cloning, install it like this:

ln -s $(pwd)/itool.sh ~/.local/bin/itool

Goals

  • Run many independent internal tools on one machine
  • Zero port collisions
  • Stable URLs per machine
  • No guessing or duplication of app configuration
  • Minimal, human-editable registry
  • Docker-based, but not tied to Traefik, Avahi subdomains, or shared proxies
  • Clear separation between machine concerns and project concerns

Core invariants

  1. The registry owns machine-local facts only

    • Project path
    • Host port (unique per machine)
  2. Projects own application facts

    • Container port (PORT in .env)
    • How the server is started
    • Docker image and runtime config
  3. itool never guesses

    • If the project doesn’t declare its container port, startup fails
    • No “smart defaults” for app internals
  4. Ports are assigned once and stay stable

    • Auto-assigned at registration
    • Persisted in the registry
    • Reboots do not change them

File layout (outside this repo)

itool keeps all machine-local state under ~/.config/itools:

~/.config/itools/
  registry.ini

Each internal tool is a normal project directory:

project/
  docker-compose.yml
  docker-compose.override.yml   # generated, machine-local (DO NOT COMMIT)
  .env
  Dockerfile

Registry format (one file for all tools)

The registry lives at:

~/.config/itools/registry.ini

Each tool is a section containing only its path and host port.

Example

[taskpe]
path = /home/username/dev/python/task-progress-estimator
port = 8611

[search]
path = /home/username/dev/internal/search-service
port = 8612

That is the entire registry contract.


Port management

  • itool register automatically allocates a host port from a reserved range (default: 8600–8999)

  • The chosen port must:

    • not already be assigned in the registry
    • not currently be in use on the host
  • An explicit port can be requested with --port

  • Once registered, a tool’s port does not change unless you edit the registry


Project requirements

Every project must define its container port itself.

.env

PORT=8501

This is the port the application listens on inside the container.

docker-compose.yml

The base compose file must not hardcode host ports:

services:
  app:
    build: .
    env_file: .env
    restart: unless-stopped

Machine-local wiring (generated)

itool generates a compose override per project:

docker-compose.override.yml

# Generated by itool (machine-local). DO NOT COMMIT.
services:
  app:
    ports:
      - "8611:${PORT}"

This file is:

  • machine-specific
  • regenerated automatically
  • the only place where host ↔ container ports are connected

Commands

itool register <name> <path> [--port N]

  • Registers a project
  • Auto-assigns a unique host port
  • Writes the registry entry
  • Generates docker-compose.override.yml

itool edit-registry

  • Opens registry.ini in $EDITOR
  • Validates all entries on save
  • Regenerates all overrides

itool list

  • Lists registered tools with name, port, and path

itool info <name>

  • Shows details for one tool

itool <name> up

  • Starts the tool with Docker Compose
  • Fails fast if .env or PORT is missing
  • Prints and opens the tool URL

Other lifecycle helpers

itool <name> down
itool <name> restart
itool <name> logs
itool <name> ps
itool <name> build
itool <name> path

URLs and networking

Each tool is reachable at:

http://<name>.local:<host_port>

Name resolution is intentionally outside the registry:

  • via /etc/hosts automation or wildcard DNS (e.g. dnsmasq)
  • no Traefik reuse
  • no Avahi subdomain management
  • no shared reverse proxy required

Example: taskpe (a webapp)

Project defines:

PORT=8501

Registry assigns:

port = 8611

Resulting URL:

http://taskpe.local:8611

The webapp still runs on 8501 internally; only the host port is machine-specific.


Behavior on reboot

  • Docker restarts containers (restart: unless-stopped)
  • Registry and overrides persist
  • URLs remain stable
  • No manual action required

What itool intentionally does not do

  • Guess container ports
  • Infer application types
  • Modify .env contents
  • Share ports or proxies with unrelated systems
  • Hide configuration errors

Mental model

  • Registry = machine facts
  • Project = application facts
  • Compose override = glue
  • itool = invariant enforcer

If something is wrong, it fails loudly and early.


Running itool on a home-server setup

This section explains how to run itool on an always-on home server (NUC, mini-PC, NAS, or spare machine) so tools are reachable from your LAN and survive reboots without manual intervention.


Assumptions

  • The machine runs Linux with systemd
  • Docker and Docker Compose v2 are installed
  • The machine has a stable hostname (e.g. homeserver)
  • Tools are internal / trusted (no public internet exposure by default)

Networking model (recommended)

  • Each tool:

    • runs in its own container
    • listens on its container port (PORT in .env)
    • is mapped to a unique host port (from the registry)
  • Containers bind to 0.0.0.0 so they’re reachable from the LAN

  • No reverse proxy required

Resulting URLs from other devices on your network:

http://homeserver:8611
http://homeserver:8612

This is the simplest, most robust setup for a home server.


Project configuration for LAN access

In each project’s .env:

PORT=8501
HOST=0.0.0.0

Ensure the app actually listens on 0.0.0.0:

  • Streamlit: --server.address=0.0.0.0
  • ASGI servers: --host 0.0.0.0

If the app only binds to 127.0.0.1, it will not be reachable from other machines.


Docker restart behavior

All tools should include in docker-compose.yml:

restart: unless-stopped

This ensures:

  • Containers start automatically after a reboot
  • Tools come back online without running itool up again

Verify Docker itself is enabled:

sudo systemctl enable docker

Firewall considerations

If a firewall is enabled (e.g. ufw), allow the itool port range:

sudo ufw allow 8600:8999/tcp

Or selectively allow only ports in use:

sudo ufw allow 8611/tcp
sudo ufw allow 8612/tcp

Name resolution on the LAN

Option 1: Use the hostname (simplest)

Most home networks already support this:

http://homeserver:8611

No additional configuration required.

Option 2: Local DNS (optional)

If you run a local DNS (router, Pi-hole, dnsmasq):

  • Create DNS entries pointing to the server IP:

    taskpe.homelab → 192.168.1.10
    
  • Access as:

    http://taskpe.homelab:8611
    

This is purely cosmetic and not required for itool.


Managing tools remotely

From the server itself:

itool list
itool taskpe restart
itool search logs

From another machine:

  • Use SSH for control:

    ssh homeserver
    itool taskpe restart
  • Access the UI via browser over LAN


Backups and persistence

Machine-local state to back up:

  • ~/.config/itools/registry.ini

Project data:

  • Project directories themselves
  • Any Docker volumes defined by tools

Containers can always be recreated; the registry is what preserves stable ports.


Security notes

  • This setup assumes a trusted LAN

  • Tools are not authenticated by default

  • Do not forward these ports to the public internet without:

    • authentication
    • TLS
    • and ideally a reverse proxy

If you later need remote access, put a proxy (Caddy, Nginx) in front of selected tools explicitly—itool stays unchanged.


Summary for home-server usage

  • Use fixed host ports from the registry
  • Bind apps to 0.0.0.0
  • Rely on Docker’s restart policy for persistence
  • Access tools via hostname:port
  • Keep itool focused on orchestration, not networking policy

This keeps the home-server setup simple, resilient, and easy to reason about.

About

local internal docker tools runner

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages