# The scanner cannot see MAC addresses until you move the backend onto the LAN

> Homelable draws and documents a homelab, scanning the network and importing Proxmox, Zigbee and Z-Wave devices, then health checking what it finds. The compose file is where the design shows: a bridge network that hides layer 2 data, admin credentials that ship as admin and admin, and a build time variable that decides your URL prefix.

**Pouzor/homelable** — Self-hosted homelab infrastructure visualizer — interactive network diagram with live status monitoring

- Repository: https://github.com/Pouzor/homelable
- Website: https://homelable.net
- Stars: 4,060 · Forks: 184
- Language: TypeScript
- License: MIT
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/pouzor-homelable

## Local auth ships as admin and admin, and the hash must stay quoted

The example environment file is unusually forthcoming about its own defaults. Three values matter before anything else:

```
AUTH_MODE=local
AUTH_USERNAME=admin
AUTH_PASSWORD_HASH='$2b$12$RtMbyw17l4N5UGzeXMNAWuzCaVV.XFBY7ZetWheQhxcBDcxahapkG'
```

The comment above them states the credentials in plain words, admin and admin, and carries a warning to change them before exposing the instance on a network. `AUTH_MODE=local` is described as the backward compatible default, and an OpenID Connect mode sits beside it as the alternative, with its own requirements: the callback has to be registered exactly at the identity provider, CORS origins must stay restricted to the browser origin because wildcard CORS is rejected in OIDC mode, and the secret key needs at least 32 bytes.

The quoting of the hash is the detail that will bite you first. The file explains that bcrypt hashes contain a backslash before the dollar signs, which Docker misinterprets unless the single quotes are kept, and that podman compose does not strip those quotes the way Docker Compose does, so the backend unwraps one matched pair itself and accepts either form.

## A bridge network cannot see MAC addresses, and the fix is host networking

The compose file carries the longest comment in the project, and it is about something the scanner cannot do by default. The backend is attached to a bridge network named homelable, and on that network the scanner can never see MAC addresses, because ARP is layer 2 and every host on your real network is one hop away behind the Docker gateway.

That has a concrete consequence. Without MAC collection, DHCP devices cannot be kept matched across an IP change, so a device that gets a new lease looks like a new device. The file's answer is to put the backend on the LAN by commenting out the networks key and uncommenting `network_mode: host`, with the restriction that this works on Linux hosts only.

So the choice is explicit and has a cost either way. Bridge networking keeps the container isolated and loses device identity across DHCP changes; host networking gets the identity and gives the backend the host's network position. Nothing in the file offers a third option.

Ping based status checks have their own requirement in the same file, the `NET_RAW` capability, added with `cap_add` and labelled as required.

## The URL prefix is compiled into the frontend bundle

Serving Homelable under a subpath instead of the root of the origin is a documented feature, and the way it works is the part to understand:

```
      args:
        # Serve Homelable under a subpath, e.g. VITE_BASE_PATH=/homelab/ in .env.
        # Defaults to the root — see docs/INSTALLATION.md.
        VITE_BASE_PATH: ${VITE_BASE_PATH:-/}
```

The comment in the example environment file is explicit that this is read by docker compose at build time, so `docker compose build frontend`, and that the prefix is baked into the frontend bundle. Changing the variable and restarting will not move your URLs; the frontend has to be rebuilt.

Four compose files sit at the root, `docker-compose.yml`, `.prebuilt.yml`, `.ci.yml` and `.standalone.yml`, alongside `Dockerfile.backend` and `Dockerfile.frontend` plus a separate build for the MCP service. So the variants are chosen by file rather than by profile, and picking the prebuilt one means the images come from GHCR instead of being built locally.

A `.hadolint.yaml` at the root lints those Dockerfiles, and there is a `VERSION` file next to the changelog.

## The public documentation view is a key in the URL, not a login

Documentation View shares your documentation space with anyone on your network, and it is worth reading exactly what that means. It exposes the tree, the pages and their version history. There is no login required. It is disabled by default, and it uses its own key, so enabling Live View does not turn it on.

Turning it on is three steps:

```
DOCS_VIEW_KEY=your-secret-key
```

generate a value with `python3 -c "import secrets; print(secrets.token_urlsafe(32))"`, restart the backend with `docker compose restart backend`, and read the space at `http://<your-homelab-ip>/docs?key=your-secret-key`.

Two properties follow from that URL shape. The key travels as a query parameter, so it lands in browser history, in any proxy log between the client and the server, and in referrer headers if the reader follows a link out of a page. And the scheme shown is plain http on a lab address, so the key crosses the network in clear text on exactly the segment where you might not trust it.

The feature is read only, which bounds the exposure. It is still a key in a URL on a network, so treat enabling it as publishing the documentation space to anyone who can reach the port.

## Documents are generated once and never rewritten behind you

The documentation model is the part of the project with the most opinion in it. Every device gets a document generated once from what the scan actually found, covering identity, hardware, one section per service, network, operations and troubleshooting, and it is never rewritten without you asking. Beside it sits a Library of pages you write yourself, from a template or blank: runbooks, incidents, decisions, a network overview.

The mechanics are specific. A device with no document gets one written from its facts. Saving is always explicit, and the `/` key inserts a freshly generated block, services, hardware, network or rack, from the device's current data. Pages cross link with `[[VLAN plan]]` and `[[device:nas-01]]`, and each document lists what links to it at the bottom. History keeps up to 50 versions per document, and a restore keeps the version it replaced.

The staleness model is a field rather than a convention: `review_every: 6m` on a document that rots, after which it is badged as due. When a device changes after its document was written, a banner says the device data changed and Regenerate rebuilds the document from scratch. All of this is full mode only, since documents need the backend to store, index and search them.

## Racks come in 19 inch and 10 inch, and widths share a U

The Rack Canvas draws the physical side of the lab next to the network diagram, and it is a separate kind of canvas created through the canvas switcher with New Canvas, then Kind, then Rack.

Adding a rack drops a frame; double clicking it sets the U height, the width as either 19 inch or 10 inch, the numbering direction and the colours. Devices are mounted from the sidebar, either an entry from your Device Inventory, a new device which joins that inventory as a side effect, or an accessory such as a blank, a shelf or a cable manager. A faceplate is then chosen from a visual catalog covering servers, switches, routers, patch panels, UPS and PDUs, desktop NAS towers, shelves and blanks.

Cabling is a mode rather than a tool: click Patch, then drag from one port to another, across racks when the run goes that far, and click a cable and press Delete to unplug it. Save Rack is explicit, and the file's own wording is that nothing is written behind your back.

The geometry has one rule worth knowing: gear occupies a U range and part of a 12 column width grid, so half width and third width machines share a U, and a drop snaps to the nearest free slot. A mount can follow the status check of its matching diagram node, and Import links derives the patch cables from links you have already drawn on the diagrams.

## The backend health check polls its own API every ten seconds

The compose file declares the backend's own health check explicitly:

```
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/api/v1/health"]
      interval: 10s
      timeout: 5s
      retries: 6
      start_period: 15s
```

Ten second interval, five second timeout, six retries, and a fifteen second start period so the container is not judged during boot. The endpoint is the same versioned API path the rest of the project uses, so the check exercises the real HTTP surface rather than a process probe.

This is the application's health check, separate from the health check system the project offers for your own devices. That one is described as working through multiple methods, ping and TCP as well as a /health API, and it exists to give a global online or offline overview of services.

So there are two health checks in this project with the same word in their name: one that keeps the container honest and one that draws your infrastructure. The `NET_RAW` capability added elsewhere in the file belongs to the second, since ping needs it.

## A frontend only mode, a Home Assistant build, and an empty screenshot block

Three smaller arrangements are worth knowing before you commit to a deployment. If you like the design but not the scanning, you can run only the frontend and export your diagram as a PNG, which makes the project usable as a drawing tool. If you run Home Assistant, there is a separate HACS distribution in its own repository, homelable-hacs, rather than an integration inside this one.

The project's own documentation is split across three places at the root: `FEATURES.md` for every feature with how to turn it on, `INSTALLATION.md` for Docker images, Proxmox LXC, bare metal, building from source and configuration, and a `docs/` directory holding the longer pages such as the rack canvas and documentation references. The readme is a summary that points at them rather than a manual.

There is also a Screenshots section in the readme that contains an empty centred paragraph and nothing else.

For the state of the project: MIT licensed, TypeScript, with releases v3.4.2 on 2026-09-13, v3.5.0 on 2026-09-20 and v3.5.1 on 2026-09-24, and the default branch last pushed on 2026-10-02.

## Conclusion

Homelable is aimed at someone whose homelab has outgrown a spreadsheet and a wiki in another tool, since it keeps the diagram, the rack drawing and the documentation in one place and derives device documents from what a scan actually found. Four things to settle before you expose it. Change the default admin credentials, because the example environment file ships them and says so. Decide whether the public documentation view is something you want on your network at all, since it is a key in a URL with no login. Read the bridge network comment before you rely on device identity, because MAC collection needs host networking on Linux. And if you serve under a subpath, set it before the first build rather than after, because the prefix is compiled into the frontend bundle.

## FAQ

### How do I use Homelable?

Scan the network, import devices from Proxmox, Zigbee or Z-Wave, draw your diagrams and rack canvases, and let the health checks report what is online. Each device also gets a document written from what the scan found, beside a library of pages you write yourself.

### What are the default Homelable credentials?

Local authentication ships with the username admin and the password admin, and the example environment file carries a warning to change them before exposing the instance on a network. The stored value is a bcrypt hash and the file insists the single quotes around it be kept.

### How do I install Homelable without Docker?

The bare metal path runs sudo bash scripts/install-baremetal.sh on a Debian or Ubuntu host, which sets up a systemd unit plus nginx. Pre-built GHCR images, a Proxmox LXC and building from source are the other routes described in INSTALLATION.md.

### Can the Homelable scanner collect MAC addresses?

Not on the default Docker bridge network, because ARP is layer 2 and the hosts sit behind the Docker gateway. The compose file documents switching the backend to network_mode: host on Linux, which is also what keeps DHCP devices matched across an IP change.

### What is the Homelable MCP server for?

It is an optional integration for AI assistants. The compose file builds it from the mcp directory, publishes port 8001 and points it at the backend over the compose network rather than at your LAN.

## Sources

- [License: MIT](https://github.com/Pouzor/homelable/blob/main/LICENSE)
- [Pouzor/homelable on GitHub](https://github.com/Pouzor/homelable)
- [Project website](https://homelable.net)
- [README](https://github.com/Pouzor/homelable/blob/main/README.md)
- [Releases](https://github.com/Pouzor/homelable/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pouzor-homelable
