Port occupancy map for homelabs

Every port. One glance. Zero guesswork.

Port-Light turns your host's listen tables, Docker, and Compose files into one traffic-light grid โ€” so you always know which port is taken, by what, and which are free.

Star on GitHub
4.4K Docker pulls v0.7.0

45 in use ยท 4 configured

live demo ยท simulated data

How it works

Three local sources. One honest map.

No agents to install, nothing leaves the machine. Port-Light reads what is already true on your host and merges it into a single grid.

Host listen tables ยท /proc, ss

TCP/UDP ports actually bound right now.

Docker API

Container names, status, images, published mappings.

Compose files

Ports that are declared โ€” even when the stack is stopped.

In use โ€” something is listening Configured โ€” declared, but quiet Free โ€” offered when you search

Features

Built for people who run too many stacks.

Search that suggests

Type a port number; if it's taken, nearby free ones light up.

Conflict radar

Two Compose projects claiming the same host port get flagged before they collide.

Multi-host, one screen

Pull occupancy maps from other Port-Light instances over LAN or Tailscale.

Live, not stale

SSE pushes a refresh the moment occupancy changes; local history records every transition.

Hooks & metrics

Optional webhooks on new listeners and conflicts; Prometheus aggregates when you want them.

Agent-friendly API

GET /api/ports/suggest hands your coding agent a genuinely free port โ€” with leases.

Speaks your theme

Fifteen palettes from Gruvbox to Kanagawa; four UI languages.

Stays on your machine

No telemetry, no accounts, no cloud. Your port map never leaves the host.

For coding agents

Your agent picks ports. They stick.

Coding agents guess ports and collide with your stacks. Port-Light exposes a tiny API โ€” and an MCP stdio server โ€” that hands out genuinely free ports, optionally reserving them with an expiring lease.

$ curl -s "http://127.0.0.1:2100/api/ports/suggest?count=2&reserve=true&ttl=3600&label=preview"

{
  "ports": [8081, 8082],
  "reserved": [8081, 8082],
  "range": { "start": 1, "end": 9999 }
}

Appearance

Fifteen palettes. Pick yours.

Click one โ€” the whole site re-skins, just like the app.

Quick start

Up in one minute.

services:
  port-light:
    image: stepaniah/port-light:v0.7.0
    container_name: port-light
    restart: unless-stopped
    ports:
      - "2100:2100"
    volumes:
      - /path/to/your/compose-stacks:/compose:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /proc:/host/proc:ro
      - ./data:/data
    environment:
      COMPOSE_SCAN_DIR: /compose
mkdir -p data
docker compose up -d

โ†’ http://localhost:2100

Images for linux/amd64 and arm64, also on GHCR. Prefer version tags over latest.

A port occupancy map โ€” not a container manager.

Port-Light doesn't start or stop containers, tail logs, or replace Portainer. It's a LAN tool: set Basic Auth or keep it behind a reverse proxy, and never expose port 2100.