Backend connection
Pre-filled with this page's own address — nginx forwards
/api to the backend internally, so this works
whether you're on the LAN over http:// or behind
an HTTPS reverse proxy. Leave it as-is unless you're
intentionally pointing at a different host. Stored only in
this browser's local storage. The key matches the
ADMIN_API_KEY you set in the backend's
.env.
GUI login password
Change the password that gates this web GUI (separate from the admin API key above). Requires the admin API key to be set and connected.
Door defaults
Pre-filled unlock time when adding a new door.
Scheduling
Timezone group/user access schedules are evaluated in — not
necessarily this server's own timezone. Pick a country to
narrow the list, or type an IANA name directly (e.g.
America/Chicago) if yours isn't in the list below.
Build firmware
Every controller runs the same image — set these once and every
(re)build bakes them in. No editing config.h by hand.
The backend/MQTT host is whatever LAN IP or hostname a device on
your WiFi can reach this homelab at — the same value goes to
both BACKEND_HOST and MQTT_HOST. MQTT
credentials and the provisioning key are pulled from the
backend's own .env automatically.
Flash a controller
Chrome or Edge only. This page must be served over HTTPS, or opened as http://localhost — a plain http://<lan-ip> address won't be allowed to access the device's serial port.
- Plug the ESP32 in via USB.
- Click Install firmware below and pick its serial port when Chrome asks.
- Once flashed, it reboots and joins your WiFi automatically — the credentials are baked into this firmware image, nothing to type in.
- Open the Controllers tab — the device appears under "Unclaimed devices" within a few seconds of joining WiFi. Assign it to a door there.
Flashes whatever Save & build firmware above most
recently produced. Prefer the CLI instead? See
firmware/build_web_flash.sh and
firmware/src/config.h.example for the manual path.
Doors
| Name | Slug | Location | Unlock (s) | Remote | |
|---|---|---|---|---|---|
| — |
Unclaimed devices
Flash a device with the generic firmware and plug it in — it appears here within a few seconds once it joins WiFi.
| MAC address | Last seen | Firmware | Relays | Assign to door(s) |
|---|
Claimed controllers
| MAC | Relays → Doors | Firmware | Last seen |
|---|
Groups
| Name |
|---|
Users
| Name | Credentials | Add credential | Active | Groups | Schedule |
|---|
A user can hold several credentials — a badge, a replacement
badge, a keypad PIN, etc. — any of them grants the same access.
A bare number (e.g. 4821) matches leniently —
card number only, ignoring facility code, for cards with
unknown/inconsistent facility codes. Include a facility code
(e.g. 12-4821) for an exact, strict match; PINs
always use this form under keypad facility code 99 (e.g.
99-4821), since that code is fixed and known.
Once a lenient credential has been seen on a real swipe, its
true facility code shows next to it as a small "fc:" hint —
useful once you're ready to switch it to strict. Assign groups
from the Groups tab.
Facility code updates
These badges currently match leniently (card number only, real facility code unknown/inconsistent) and have now been seen on a real swipe. Approving switches that one badge to strict matching using the facility code it was actually seen with; dismissing just clears the observation without changing anything.
| User | Current | Proposed |
|---|