READMESource: main@318b744e
dsh-port-map
Port, service and Caddy route map for DeepSeek Harness.
dsh-port-map answers the questions a busy server keeps asking: what is on
9094? which unit owns this port? is every Caddy route still pointing at
something alive? what is exposed to the internet?
Every tool is read-only. Nothing is opened, closed or reconfigured.
Tools
| Tool | Kind | What it does |
|---|---|---|
listening_ports |
read-only | TCP listening sockets: port, bound address, reachability scope (public / localhost / interface), process, and the systemd unit or docker container that owns it. Filters: scope, port. |
service_map |
read-only | The reverse view: every unit/container with the ports it listens on, plus the ports nothing claims. |
caddy_routes |
read-only | Parses the Caddyfile into site → path → reverse_proxy upstream, then checks each upstream against the listening sockets. |
url_check |
read-only | HTTP status, latency and content type for an allow-listed host. A redirect is reported, not followed. |
Example output
Listening TCP sockets (39):
port address scope owner
8790 127.0.0.1 localhost dsh-web.service
1933 127.0.0.1 localhost docker:openviking
9090 0.0.0.0 public map-service.service
Bound to all interfaces: 22, 443, 8642, 8799, 9090, 9091, 9094, 11434
Caddy routes (11) from /etc/caddy/Caddyfile:
example.org /panel → 127.0.0.1:8788 · up (vps-panel.service)
example.org /gone → 127.0.0.1:9999 · DOWN
Install
dsh plugin --profile web add dsh-port-map
systemctl restart dsh-web # or restart your DSH process
- id: port-map
config:
caddyfile: /etc/caddy/Caddyfile
urlCheck:
hosts:
- 127.0.0.1
- localhost
- example.org
timeoutMs: 10000
docker: true
safety:
timeoutMs: 15000
maxOutputBytes: 65536
Configuration
| Key | Default | Meaning |
|---|---|---|
caddyfile |
/etc/caddy/Caddyfile |
File parsed by caddy_routes. |
urlCheck.hosts |
["127.0.0.1", "localhost"] |
Hosts url_check may request; everything else is refused. |
urlCheck.timeoutMs |
10000 |
Per-request timeout. |
docker |
true |
Resolve container names for published ports. |
safety.timeoutMs |
15000 |
Default command timeout. |
safety.maxOutputBytes |
65536 |
Output cap per call. |
How the owner is resolved
ss -tlnpHgives the socket, its bound address and the owning PID.- The PID's cgroup gives the systemd unit (
/proc/<pid>/cgroup). - A
docker-proxysocket is matched to its container through the published port (docker ps --format '{{.Names}}\t{{.Ports}}'), so the map showsdocker:openvikingrather thandocker.service.
Nothing is guessed: an unclaimed socket is reported as unowned:<process>.
Honest limits
- Read-only: it reports, it does not fix. No firewall changes, no restarts.
- The Caddyfile parser understands site blocks,
handle/handle_pathandreverse_proxy(with or without an options block).!!jsexpressions, imported snippets orphp_fastcgi-style directives are not modelled and are simply not reported. - Docker name resolution needs
docker psto work for the current user; without it the socket is still listed with itsdocker:<id>marker. url_checknever follows a redirect, so a redirect chain is reported as one hop, not resolved to the final page.
Requirements
- DSH
>= 0.2.1-rc.4(Node^22.19.0 || >=24.0.0). ss(iproute2) for the socket tools;dockeroptional; the Caddyfile optional.
Development
npm run link-peers
node --test
License
MIT
No comments yet. Be the first to write one.