Gladys Assistant is a privacy-first smart home alternative to Apple Home and Google Home, running local scenes, Zigbee devices, and cameras via Docker.
Gladys Assistant is an open-source home automation hub that executes smart home workflows on local hardware. Its guided configuration pairs low-overhead Docker containers with a clean web interface, avoiding the YAML files common in self-hosted home automation. Sensor states, device schedules, and telemetry stay on the host machine, keeping connected peripherals operational without cloud subscriptions.
Apple Home promises local execution and privacy, but it imposes a steep hardware tax to enter the ecosystem. Running Apple Home requires a dedicated Apple TV 4K or HomePod hub, alongside iOS devices for system management. Retaining security camera history incurs recurring costs through iCloud+ storage tiers. Closed vendor certification historically restricted device choices to expensive HomeKit-approved hardware, inflating the cost of equipping every room with sensors and switches.
Gladys Assistant removes that entry barrier by running in Docker on existing homelab hardware, from a Raspberry Pi to a home server. It talks directly to standard Zigbee dongles, Matter devices, and open MQTT endpoints, letting users deploy affordable commodity sensors instead of premium accessories. RTSP camera feeds stream locally without cloud video subscriptions. The trade-off is maintenance: while Apple updates hub firmware silently, a Gladys administrator manages container updates, local backups, and remote access.
How does Gladys Assistant compare to Apple Home on overall cost? Gladys Assistant avoids dedicated Apple TV or HomePod hub purchases and works with inexpensive Zigbee and MQTT peripherals. Unlike Apple Home, camera recording and history do not require an ongoing iCloud+ storage subscription.
Can Gladys Assistant run completely offline without internet connectivity? Yes. All automation scenes, device communications, and dashboard controls execute entirely on the local network without connecting to external cloud servers.
Does Gladys Assistant support voice control? Gladys includes an internal chat assistant and local voice interfaces, but connecting external Google Assistant or Amazon Alexa endpoints requires either the paid Gladys Plus relay or custom webhooks.
Gladys Assistant is a practical choice for homelab operators who want local automation and camera monitoring without paying hub hardware premiums or cloud fees, provided their devices match its Zigbee and Matter ecosystem. Active maintenance with recent updates in August 2026 and an Apache-2.0 license give self-hosters full freedom to modify the code or deploy custom integration containers on their own infrastructure.
We started this exact setup from scratch in a clean Linux machine on Nov 3, 2026 and checked it through Gladys Assistant's own API: every check passed. Recipes are re-checked regularly and removed if they stop working.
mkdir -p gladys-assistant && cd gladys-assistant
curl -fsSL https://open-source.store/tools/gladys-assistant/compose.yml -o compose.ymlcat > .env <<EOF
JWT_SECRET=$(openssl rand -hex 32)
GLADYS_ADMIN_PASSWORD=$(openssl rand -hex 12)
EOFJWT_SECRET — Random 64-character secret key used to sign and verify JSON Web Tokens (JWT) for user sessions. Generated above; keep it secret.GLADYS_ADMIN_PASSWORD — Password set during automated smoke steps to create the initial admin account. Generated above; keep it secret.docker compose up -dservices:
gladys:
image: gladysassistant/gladys:v5.3.1
ports:
- "80:80"
environment:
NODE_ENV: production
SERVER_PORT: 80
TZ: UTC
SQLITE_FILE_PATH: /var/lib/gladysassistant/gladys-production.db
JWT_SECRET: ${JWT_SECRET}
volumes:
- gladys-data:/var/lib/gladysassistant
restart: always
volumes:
gladys-data:
Go, gRPC and Protobuf done right, LLM agents in production, and the hard parts of shipping a first product.
Show that Gladys Assistant is listed as an open-source alternative. Paste into your README:
Ubuntu 24.04 · Apple container, Docker 29.1.3, Compose 2.40.3+ds1-0ubuntu1~24.04.1. Images pulled in 103 s: gladysassistant/gladys:v5.3.1.
Based on the upstream setup. Official compose. Pinned image to v5.3.1; dropped watchtower, host networking, privileged mode, docker.sock and host device mounts (/dev, /run/udev, /run/dbus) required only for hardware dongles and Bluetooth; persistent data stored in a named volume.
gladys-1 | 2026-11-03T08:16:50.969761924Z at trim_prefix (/src/server/node_modules/express/lib/router/index.js:328:13)
gladys-1 | 2026-11-03T08:16:50.969762424Z at /src/server/node_modules/express/lib/router/index.js:286:9
gladys-1 | 2026-11-03T08:16:50.969762924Z at router.process_params (/src/server/node_modules/express/lib/router/index.js:346:12)
gladys-1 | 2026-11-03T08:16:50.969763424Z at next (/src/server/node_modules/express/lib/router/index.js:280:10)
gladys-1 | 2026-11-03T08:16:50.969771216Z at router.handle (/src/server/node_modules/express/lib/router/index.js:175:3)
gladys-1 | 2026-11-03T08:16:50.969771799Z at router (/src/server/node_modules/express/lib/router/index.js:47:12)
gladys-1 | 2026-11-03T08:16:50.969772299Z at Layer.handle [as handle_request] (/src/server/node_modules/express/lib/router/layer.js:95:5)
gladys-1 | 2026-11-03T08:16:50.969772799Z at trim_prefix (/src/server/node_modules/express/lib/router/index.js:328:13)
gladys-1 | 2026-11-03T08:16:50.969773341Z at /src/server/node_modules/express/lib/router/index.js:286:9
gladys-1 | 2026-11-03T08:16:50.969773799Z at router.process_params (/src/server/node_modules/express/lib/router/index.js:346:12)
gladys-1 | 2026-11-03T08:16:50.969774299Z at next (/src/server/node_modules/express/lib/router/index.js:280:10)
gladys-1 | 2026-11-03T08:16:50.969774758Z at SendStream.error (/src/server/node_modules/serve-static/index.js:121:7)
gladys-1 | 2026-11-03T08:16:50.969775258Z at SendStream.emit (node:events:514:28)
gladys-1 | 2026-11-03T08:16:50.969775758Z at SendStream.error (/src/server/node_modules/send/index.js:270:17)
gladys-1 | 2026-11-03T08:16:50.969776633Z at SendStream.pipe (/src/server/node_modules/send/index.js:515:10)
gladys-1 | 2026-11-03T08:16:50.969777133Z at serveStatic (/src/server/node_modules/serve-static/index.js:125:12)
gladys-1 | 2026-11-03T08:16:50.969777591Z at Layer.handle [as handle_request] (/src/server/node_modules/express/lib/router/layer.js:95:5)
gladys-1 | 2026-11-03T08:16:50.969778133Z at trim_prefix (/src/server/node_modules/express/lib/router/index.js:328:13)
gladys-1 | 2026-11-03T08:16:50.969778591Z at /src/server/node_modules/express/lib/router/index.js:286:9
gladys-1 | 2026-11-03T08:16:50.969779091Z at router.process_params (/src/server/node_modules/express/lib/router/index.js:346:12)
gladys-1 | 2026-11-03T08:16:50.969779591Z at next (/src/server/node_modules/express/lib/router/index.js:280:10)
gladys-1 | 2026-11-03T08:16:50.969780133Z at jsonParser (/src/server/node_modules/body-parser/lib/types/json.js:117:7)
gladys-1 | 2026-11-03T08:16:50.969780633Z at jsonBodyMiddleware (/src/server/api/middlewares/jsonBodyMiddleware.js:57:10)
gladys-1 | 2026-11-03T08:16:50.969781091Z at Layer.handle [as handle_request] (/src/server/node_modules/express/lib/router/layer.js:95:5)
gladys-1 | 2026-11-03T08:16:50.969781591Z at trim_prefix (/src/server/node_modules/express/lib/router/index.js:328:13)
gladys-1 | 2026-11-03T08:16:50.969782091Z at /src/server/node_modules/express/lib/router/index.js:286:9
gladys-1 | 2026-11-03T08:16:50.969782549Z at router.process_params (/src/server/node_modules/express/lib/router/index.js:346:12)
gladys-1 | 2026-11-03T08:16:50.969783049Z at next (/src/server/node_modules/express/lib/router/index.js:280:10)
gladys-1 | 2026-11-03T08:16:50.969783549Z at compression (/src/server/node_modules/compression/index.js:265:5)
gladys-1 | 2026-11-03T08:16:50.969784049Z at Layer.handle [as handle_request] (/src/server/node_modules/express/lib/router/layer.js:95:5)
gladys-1 | 2026-11-03T08:16:50.969953758Z at trim_prefix (/src/server/node_modules/express/lib/router/index.js:328:13)
gladys-1 | 2026-11-03T08:16:50.969956549Z at /src/server/node_modules/express/lib/router/index.js:286:9
gladys-1 | 2026-11-03T08:16:50.969957133Z at router.process_params (/src/server/node_modules/express/lib/router/index.js:346:12)
gladys-1 | 2026-11-03T08:16:50.969957674Z at next (/src/server/node_modules/express/lib/router/index.js:280:10)
gladys-1 | 2026-11-03T08:16:50.969958216Z at expressInit (/src/server/node_modules/express/lib/middleware/init.js:40:5)
gladys-1 | 2026-11-03T08:16:50.969958716Z at Layer.handle [as handle_request] (/src/server/node_modules/express/lib/router/layer.js:95:5)
gladys-1 | 2026-11-03T08:16:50.969959258Z at trim_prefix (/src/server/node_modules/express/lib/router/index.js:328:13)
gladys-1 | 2026-11-03T08:16:50.969959841Z at /src/server/node_modules/express/lib/router/index.js:286:9
gladys-1 | 2026-11-03T08:16:50.969960341Z at router.process_params (/src/server/node_modules/express/lib/router/index.js:346:12)
gladys-1 | 2026-11-03T08:16:50.969961299Z at next (/src/server/node_modules/express/lib/router/index.js:280:10)
gladys-1 | 2026-11-03T08:16:50.969961799Z at query (/src/server/node_modules/express/lib/middleware/query.js:45:5)
gladys-1 | 2026-11-03T08:16:50.969962299Z at Layer.handle [as handle_request] (/src/server/node_modules/express/lib/router/layer.js:95:5)
gladys-1 | 2026-11-03T08:16:50.969962841Z at trim_prefix (/src/server/node_modules/express/lib/router/index.js:328:13)
gladys-1 | 2026-11-03T08:16:50.969963383Z at /src/server/node_modules/express/lib/router/index.js:286:9
gladys-1 | 2026-11-03T08:16:50.969963841Z at router.process_params (/src/server/node_modules/express/lib/router/index.js:346:12)
gladys-1 | 2026-11-03T08:16:50.969964383Z at next (/src/server/node_modules/express/lib/router/index.js:280:10)
gladys-1 | 2026-11-03T08:16:50.969964924Z at router.handle (/src/server/node_modules/express/lib/router/index.js:175:3)
gladys-1 | 2026-11-03T08:16:50.969965424Z at app.handle (/src/server/node_modules/express/lib/application.js:181:10)
gladys-1 | 2026-11-03T08:16:50.969965924Z at Server.app (/src/server/node_modules/express/lib/express.js:39:9)
gladys-1 | 2026-11-03T08:16:50.969966424Z at Server.emit (node:events:514:28)
gladys-1 | 2026-11-03T08:16:50.969966924Z at parserOnIncoming (node:_http_server:1293:12)
gladys-1 | 2026-11-03T08:16:50.969967466Z at HTTPParser.parserOnHeadersComplete (node:_http_common:125:17) {
gladys-1 | 2026-11-03T08:16:50.969967966Z statusCode: 400,
gladys-1 | 2026-11-03T08:16:50.969968466Z status: 400
gladys-1 | 2026-11-03T08:16:50.969968966Z }
gladys-1 | 2026-11-03T08:16:50.976771633Z 2026-11-03T08:16:50+0000 <warn> errorMiddleware.js:83 (errorMiddleware) URIError: Failed to decode param '/theme/META-INF/prototype%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%af..%c0%afwindows/win.ini'
gladys-1 | 2026-11-03T08:16:50.976781674Z at decodeURIComponent (<anonymous>)
gladys-1 | 2026-11-03T08:16:50.976782633Z at decode_param (/src/server/node_modules/express/lib/router/layer.js:172:12)
gladys-1 | 2026-11-03T08:16:50.976783383Z at Layer.match (/src/server/node_modules/express/lib/router/layer.js:123:27)
gladys-1 | 2026-11-03T08:16:50.976783924Z at matchLayer (/src/server/node_modules/express/lib/router/index.js:585:18)
gladys-1 | 2026-11-03T08:16:50.976791424Z at next (/src/server/node_modules/express/lib/router/index.js:226:15)
gladys-1 | 2026-11-03T08:16:50.976792216Z at /src/server/node_modules/express/lib/router/index.js:646:15
gladys-1 | 2026-11-03T08:16:50.976792883Z at next (/src/server/node_modules/express/lib/router/index.js:265:14)
gladys-1 | 2026-11-03T08:16:50.976793716Z at CorsMiddleware (/src/server/api/middlewares/corsMiddleware.js:8:5)
gladys-1 | 2026-11-03T08:16:50.976794424Z at Layer.handle [as handle_request] (/src/server/node_modules/express/lib/router/layer.js:95:5)
gladys-1 | 2026-11-03T08:16:50.976795133Z at trim_prefix (/src/server/node_modules/express/lib/router/index.js:328:13)
gladys-1 | 2026-11-03T08:16:50.976795841Z at /src/server/node_modules/express/lib/router/index.js:286:9
gladys-1 | 2026-11-03T08:16:50.976796508Z at router.process_params (/src/server/node_modules/express/lib/router/index.js:346:12)
gladys-1 | 2026-11-03T08:16:50.976797216Z at next (/src/server/node_modules/express/lib/router/index.js:280:10)
gladys-1 | 2026-11-03T08:16:50.976797883Z at router.handle (/src/server/node_modules/express/lib/router/index.js:175:3)
gladys-1 | 2026-11-03T08:16:50.976798549Z at router (/src/server/node_modules/express/lib/router/index.js:47:12)
gladys-1 | 2026-11-03T08:16:50.976799216Z at Layer.handle [as handle_request] (/src/server/node_modules/express/lib/router/layer.js:95:5)
gladys-1 | 2026-11-03T08:16:50.976799966Z at trim_prefix (/src/server/node_modules/express/lib/router/index.js:328:13)
gladys-1 | 2026-11-03T08:16:50.976800633Z at /src/server/node_modules/express/lib/router/index.js:286:9
gladys-1 | 2026-11-03T08:16:50.976801299Z at router.process_params (/src/server/node_modules/express/lib/router/index.js:346:12)
gladys-1 | 2026-11-03T08:16:50.976801966Z at next (/src/server/node_modules/express/lib/router/index.js:280:10)
gladys-1 | 2026-11-03T08:16:50.976802633Z at SendStream.error (/src/server/node_modules/serve-static/index.js:121:7)
gladys-1 | 2026-11-03T08:16:50.976803341Z at SendStream.emit (node:events:514:28)
gladys-1 | 2026-11-03T08:16:50.976803966Z at SendStream.error (/src/server/node_modules/send/index.js:270:17)
gladys-1 | 2026-11-03T08:16:50.976805008Z at SendStream.pipe (/src/server/node_modules/send/index.js:515:10)
gladys-1 | 2026-11-03T08:16:50.976805674Z at serveStatic (/src/server/node_modules/serve-static/index.js:125:12)
gladys-1 | 2026-11-03T08:16:50.976806341Z at Layer.handle [as handle_request] (/src/server/node_modules/express/lib/router/layer.js:95:5)
gladys-1 | 2026-11-03T08:16:50.976807091Z at trim_prefix (/src/server/node_modules/express/lib/router/index.js:328:13)
gladys-1 | 2026-11-03T08:16:50.976807758Z at /src/server/node_modules/express/lib/router/index.js:286:9
gladys-1 | 2026-11-03T08:16:50.976808466Z at router.process_params (/src/server/node_modules/express/lib/router/index.js:346:12)
gladys-1 | 2026-11-03T08:16:50.976809133Z at next (/src/server/node_modules/express/lib/router/index.js:280:10)
gladys-1 | 2026-11-03T08:16:50.976809799Z at jsonParser (/src/server/node_modules/body-parser/lib/types/json.js:117:7)
gladys-1 | 2026-11-03T08:16:50.976811383Z at jsonBodyMiddleware (/src/server/api/middlewares/jsonBodyMiddleware.js:57:10)
gladys-1 | 2026-11-03T08:16:50.976812091Z at Layer.handle [as handle_request] (/src/server/node_modules/express/lib/router/layer.js:95:5)
gladys-1 | 2026-11-03T08:16:50.976812758Z at trim_prefix (/src/server/node_modules/express/lib/router/index.js:328:13)
gladys-1 | 2026-11-03T08:16:50.976813299Z at /src/server/node_modules/express/lib/router/index.js:286:9
gladys-1 | 2026-11-03T08:16:50.976813841Z at router.process_params (/src/server/node_modules/express/lib/router/index.js:346:12)
gladys-1 | 2026-11-03T08:16:50.976814383Z at next (/src/server/node_modules/express/lib/router/index.js:280:10)
gladys-1 | 2026-11-03T08:16:50.976815049Z at compression (/src/server/node_modules/compression/index.js:265:5)
gladys-1 | 2026-11-03T08:16:50.976815591Z at Layer.handle [as handle_request] (/src/server/node_modules/express/lib/router/layer.js:95:5)
gladys-1 | 2026-11-03T08:16:50.976816133Z at trim_prefix (/src/server/node_modules/express/lib/router/index.js:328:13)
gladys-1 | 2026-11-03T08:16:50.976816674Z at /src/server/node_modules/express/lib/router/index.js:286:9
gladys-1 | 2026-11-03T08:16:50.976817216Z at router.process_params (/src/server/node_modules/express/lib/router/index.js:346:12)
gladys-1 | 2026-11-03T08:16:50.976817758Z at next (/src/server/node_modules/express/lib/router/index.js:280:10)
gladys-1 | 2026-11-03T08:16:50.976818299Z at expressInit (/src/server/node_modules/express/lib/middleware/init.js:40:5)
gladys-1 | 2026-11-03T08:16:50.976818841Z at Layer.handle [as handle_request] (/src/server/node_modules/express/lib/router/layer.js:95:5)
gladys-1 | 2026-11-03T08:16:50.976819383Z at trim_prefix (/src/server/node_modules/express/lib/router/index.js:328:13)
gladys-1 | 2026-11-03T08:16:50.976819883Z at /src/server/node_modules/express/lib/router/index.js:286:9
gladys-1 | 2026-11-03T08:16:50.976820424Z at router.process_params (/src/server/node_modules/express/lib/router/index.js:346:12)
gladys-1 | 2026-11-03T08:16:50.976821049Z at next (/src/server/node_modules/express/lib/router/index.js:280:10)
gladys-1 | 2026-11-03T08:16:50.976821591Z at query (/src/server/node_modules/express/lib/middleware/query.js:45:5)
gladys-1 | 2026-11-03T08:16:50.976822133Z at Layer.handle [as handle_request] (/src/server/node_modules/express/lib/router/layer.js:95:5)
gladys-1 | 2026-11-03T08:16:50.976822674Z at trim_prefix (/src/server/node_modules/express/lib/router/index.js:328:13)
gladys-1 | 2026-11-03T08:16:50.976823216Z at /src/server/node_modules/express/lib/router/index.js:286:9
gladys-1 | 2026-11-03T08:16:50.976823716Z at router.process_params (/src/server/node_modules/express/lib/router/index.js:346:12)
gladys-1 | 2026-11-03T08:16:50.976824258Z at next (/src/server/node_modules/express/lib/router/index.js:280:10)
gladys-1 | 2026-11-03T08:16:50.976824799Z at router.handle (/src/server/node_modules/express/lib/router/index.js:175:3)
gladys-1 | 2026-11-03T08:16:50.976825341Z at app.handle (/src/server/node_modules/express/lib/application.js:181:10)
gladys-1 | 2026-11-03T08:16:50.976825883Z at Server.app (/src/server/node_modules/express/lib/express.js:39:9)
gladys-1 | 2026-11-03T08:16:50.976841966Z at Server.emit (node:events:514:28)
gladys-1 | 2026-11-03T08:16:50.976843091Z at parserOnIncoming (node:_http_server:1293:12)
gladys-1 | 2026-11-03T08:16:50.976843674Z at HTTPParser.parserOnHeadersComplete (node:_http_common:125:17) {
gladys-1 | 2026-11-03T08:16:50.976844258Z statusCode: 400,
gladys-1 | 2026-11-03T08:16:50.976844799Z status: 400
gladys-1 | 2026-11-03T08:16:50.976845424Z }