Port occupancy map for homelabs

Know which ports are taken, and which are free.

Port-Light merges your host's listen tables, Docker, and Compose files into a single traffic-light grid, so you can tell taken ports from free ones without reaching for ss.

View on GitHub
8.6K Docker pulls v0.7.8

Interactive demo: type a port number in the search box, or click any card to copy its port.

41 in use · 5 configured

22sshd 53adguardhome 80caddy 111rpcbind 443caddy 1900plex 3000grafana 3001uptime-kuma 3002jellystat 3003logto 3004logto 3020gitea 3030homepage 3210lobe-server 3306mysql 4533navidrome 5003dify-plugin 5230memos 5432postgres 5800makemkv 6379redis 6767bazarr 6881qbittorrent 6969whisparr 7878radarr 8015mcp-fs-web2org 8080qbittorrent 8081adguardhome 8082calibre-web 8083freshrss 8096jellyfin 8111dify-nginx 8123python3 8384syncthing 8412gatus 8443dify-nginx 8888my_ml_notebook 8920emby 8989sonarr 9000portainer 9001lobe-minio 9080health-export 9090prometheus 9100node-exporter 9208mdc 9443portainer

live demo · simulated data

How it works

Three sources, one grid.

Nothing to install elsewhere, nothing leaves the machine. Port-Light reads what is already true on your host and merges it into one view.

In use — something is listening Configured — declared, but quiet Free — offered when you search

Features

For hosts running more than a few stacks.

For coding agents

A port API your agent can rely on

Coding agents pick ports by guessing until one collides with your stacks. Port-Light exposes a small HTTP API that returns ports which are free right now and can hold them with an expiring lease. An agent skill and an MCP server wrap the same endpoints; AGENT_TOKEN requires an auth header.

$ export PORT_LIGHT_URL=http://127.0.0.1:2100

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

{
  "ports": [8081, 8082],
  "reserved": [8081, 8082],
  "reservations": [
    { "port": 8081, "expires_at": "2026-09-03T13:04:11Z" },
    { "port": 8082, "expires_at": "2026-09-03T13:04:11Z" }
  ]
}

Result of the call above — 8081 and 8082 are now reserved:

Reserved ports appear as configured (amber) on every map until the lease expires.

Appearance

Ten palette families, straight from the app.

Click one and the whole page re-skins, mirroring the app's theme system. Your pick persists.

Quick start

One compose file.

services:
  port-light:
    image: stepaniah/port-light:v0.7.8
    container_name: port-light
    restart: unless-stopped
    ports:
      - "${PORT_LIGHT_PORT:-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:${PORT_LIGHT_PORT:-2100}

The public port follows PORT_LIGHT_PORT; it defaults to 2100.

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

FAQ

Common questions, quick answers.

docker.sock: permission denied?

The Compose file mounts /var/run/docker.sock read-only. If the container logs permission errors, verify the socket path on your host and that the container user can read it — no privileged mode is needed.

My Compose stacks don't show up.

Point COMPOSE_SCAN_DIR at the folder that holds your stacks (up to 4 levels deep, at most 400 files). Declared ports count even when a stack is stopped — they show as configured.

Is it safe to expose Port-Light to the internet?

No. It serves one read-only page on your LAN — keep it behind Basic Auth or a reverse proxy and off the public internet. The security checklist has the hardening notes.

How does an agent reserve a free port?

GET /api/ports/suggest?reserve=true returns ports that are free right now and holds them with an expiring lease. The agent skill and MCP server wrap the same endpoints.

A port occupancy map — not a container manager.

Port-Light doesn't start or stop containers, tail logs, or replace Portainer. It serves one read-only page on your LAN — keep it behind Basic Auth or a reverse proxy and off the public internet. The security checklist collects the hardening notes.