WebThings Gateway: a self-hosted Web of Things gateway you run with Docker
WebThings Gateway - a self-hosted web application for monitoring and controlling a building over the web
At a glance
- What is it?
- WebThings Gateway is a TypeScript web application that turns a Raspberry Pi or small Linux box into a local hub for monitoring and controlling a building. The 2.0 line moved the recommended install path to Docker, and the documentation still assumes you are comfortable with ports, TLS and addons.
- Who is it for?
- Adopt WebThings Gateway if you want a local, MPL-2.0 licensed hub that speaks the W3C Web of Things model and you are willing to run a Node.js service behind your own TLS certificate. Skip it if you need a vendor support contract, a managed cloud, or an install path that does not involve a terminal.
- Can I use it commercially?
- Yes, with conditions. MPL-2.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 7 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What WebThings Gateway actually does for a building
The README describes the project in one line: a self-hosted web application for monitoring and controlling a building over the web. That sentence is doing more work than it looks like. The gateway is not a cloud service with a local agent. It is the server. You install it on a machine inside the building, it discovers devices on your network, and it exposes them through a browser interface that you reach on the local network or through a tunnel.
The project positions itself as a Web of Things gateway, following the W3C Web of Things model. In practice that means devices and their capabilities are represented as Things with properties, actions and events, and the gateway is the thing that holds those representations and translates between them and the underlying protocols. The README does not enumerate which protocols ship in the box, so the honest answer for any specific device is: check the addon list, not the README.
The audience is narrow and specific. You are the kind of person who already runs a home server, who is comfortable with Docker or a manual Node.js build, and who wants the device data to stay on hardware you control. The README's install instructions assume exactly that: apt packages, npm ci, firewall rules, and an openssl command line for generating a certificate.
The architecture visible in the repository layout
The top-level entries tell you most of what you need about how this is put together. There is a src directory of TypeScript, a config directory, a static directory for front-end assets, and a webpack.config.js at the root. The package.json build script confirms the pipeline: it copies src to build, deletes the .ts files, runs tsc, then runs webpack. So the shipped artifact is compiled JavaScript plus bundled front-end assets, and the entry point is build/app.js.
The runtime is Node.js. The Dockerfile pins node:20-bookworm-slim, and the README's manual build instructions show node --version and npm --version output of v20.19.6 and 10.8.2, with a note that these might differ from the LTS version installed locally. The .nvmrc file is what nvm reads to pick a version, which is why the README tells you to run nvm install and nvm use rather than naming a version by hand.
Two ports matter. The Dockerfile declares EXPOSE 8080 4443, and the README's firewall section opens 4443/tcp, 8080/tcp and 5353/udp. Port 8080 is the plain HTTP entry point used during setup, 4443 is HTTPS, and 5353/udp is mDNS, which is how discovery works on the local network. The docker-compose.yml uses network_mode: host and comments out the ports mapping, with a note that ports are ignored under host networking. That is a deliberate choice: mDNS and device discovery generally do not survive a bridged network namespace.
Addons run as separate processes. The requirements.txt pins gateway-addon-python at v1.1.0, and the Dockerfile installs it through pipx and cookiecutter. The deb and rpm directories, plus the snap directory, show that packaging is maintained for more than one distribution channel even though Docker is the recommended one.
Installing WebThings Gateway with Docker and reaching the setup page
The README states that as of the 2.0 release the recommended way to install is the Docker image. The repository ships a docker-compose.yml you can use directly. It binds the container to the host network, sets a timezone, and mounts a host directory as the persistent profile.
services:
webthings-gateway:
container_name: webthings-gateway
build: .
restart: unless-stopped
network_mode: host
environment:
- "TZ=America/Los_Angeles"
volumes:
- /opt/docker/webthings-gateway:/home/node/.webthingsThe volume line is the one to think about. Everything the gateway remembers lives under /home/node/.webthings in the container, so that host path is your backup target. The compose file also carries commented-out devices and privileged entries for USB dongles and Bluetooth, with a note that Bluetooth requires privileged mode.
Once the container is up, the README's manual instructions describe the same flow you get from the image: load http://localhost:8080 in a browser, or the server's IP address if you are connecting remotely, and follow the page to set up a domain and register. After that you use https://localhost:4443.
If you would rather not use the provided tunneling service, the README documents supplying your own certificate. The HTTPS server looks for privatekey.pem and certificate.pem in the ssl sub-directory of the userProfile directory, and the README gives this sequence for a self-signed pair:
WEBTHINGS_HOME="${WEBTHINGS_HOME:=${HOME}/.webthings}"
SSL_DIR="${WEBTHINGS_HOME}/ssl"
[ ! -d "${SSL_DIR}" ] && mkdir -p "${SSL_DIR}"
openssl genrsa -out "${SSL_DIR}/privatekey.pem" 2048
openssl req -new -sha256 -key "${SSL_DIR}/privatekey.pem" -out "${SSL_DIR}/csr.pem"
openssl x509 -req -in "${SSL_DIR}/csr.pem" -signkey "${SSL_DIR}/privatekey.pem" -out "${SSL_DIR}/certificate.pem"Because that is self-signed, the README notes you will need to add a security exception in the browser. There is also an experimental snap package, and the README points at the snapcraft listing for it. Building from source is documented too: clone the repository, run nvm install and nvm use, then npm ci, then npm start. The README's macOS section warns that DBus needs python symlinked to python3, and the Linux section includes setcap commands so node and python3 can use the Bluetooth adapter.
Where the gateway is the wrong tool
The install path is the first limitation and the README is candid about it in places without labelling it as such. The default Dockerfile runs mosquitto, avahi, ffmpeg and a Python addon runtime inside one container, and it modifies /etc/sudoers to grant passwordless sudo to the sudo group. That is a lot of surface area for a device hub, and it is a direct consequence of the gateway being the integration point rather than a thin agent.
The second limitation is TLS. The README gives you two options: the provided tunneling service for a _.webthings.io domain, or your own certificate placed at specific filenames in a specific directory. There is no documented path for terminating TLS at a reverse proxy in front of the gateway; the HTTPS server reads privatekey.pem and certificate.pem itself. If your existing setup already has a proxy with certificates, you are working against the documented design rather than with it.
The third is packaging maturity. The README calls the snap package experimental, and the recommended path is Docker. The latest release listed is 2.1.0-beta.2 from 2026-04-01, with 2.0.0 as the last stable release in 2025-12-18. If you need a stable, versioned release with a long support window, you are choosing between a 2.0.0 install and running a beta.
Finally, the README does not document rollback or downgrade procedures. If an upgrade breaks an addon, the documented material does not tell you how to go back. That is a real operational gap, not a stylistic one.
How it differs from Home Assistant and openHAB
The obvious alternatives are Home Assistant and openHAB, and the difference is not the feature list. It is the data model. WebThings Gateway is built around the W3C Web of Things Thing Description: a device is described by its properties, actions and events in a standardized JSON form, and addons implement that interface. Home Assistant's model is entity and integration based, with its own state machine and a much larger integration catalogue. openHAB uses items and channels with a rules engine on top.
That distinction has practical consequences. A WoT-style Thing Description is portable: the description of a device is meaningful outside the gateway that produced it. An entity in Home Assistant is meaningful inside Home Assistant. If your interest is interoperability with other WoT implementations, or you are building devices that should describe themselves in a standard format, the WebThings model is the reason to pick this project. If your interest is the widest possible device support today, the larger catalogues of Home Assistant and openHAB are the reason to pick those.
The second difference is scope. The README describes a gateway for a building. Home Assistant has grown well beyond that into dashboards, voice assistants and automation blueprints. WebThings Gateway's repository layout reflects a narrower product: src, config, static, and packaging directories for deb, rpm, snap and Docker. There is no separate automation engine directory, and the README does not describe one.
Licence, maintenance and what an upgrade costs you
The licence is MPL-2.0, declared in package.json and shown as a badge in the README. MPL-2.0 is file-level copyleft: modifications to files that are part of the covered source must be made available under the same licence, while larger works that combine the covered code with separate files can be distributed under other terms. For a self-hoster running the gateway on their own hardware, this is mostly a non-issue. For anyone planning to ship a product that embeds gateway code, the file-level boundary is the thing to have a lawyer read, not this article.
The repository is not archived, and the last push was on 2026-09-23. That is recent enough that calling it maintained is fair on the evidence available. The release history is more mixed: 2.0.0 landed on 2025-12-18, and the two 2.1.0 betas both landed on 2026-04-01. Between April and September 2026 there were commits but no listed release, so the practical choice for a production install is 2.0.0 unless you are willing to track the beta line.
Upgrade cost is concentrated in two places. First, Node.js: the Dockerfile pins node:20-bookworm-slim and the README's manual build expects Node 20, so a Node version bump means a rebuild of the image and a check of native modules. The Dockerfile already rebuilds sqlite3 from source with npm rebuild sqlite3 --build-from-source, which is a hint that native bindings are fragile enough to need explicit handling. Second, addons: gateway-addon-python is pinned to v1.1.0 in requirements.txt, and the Dockerfile installs it via pipx, so an addon that depends on a different Python version is a container-level problem rather than a config change.
Editorial conclusion
Adopt WebThings Gateway if you want a local, MPL-2.0 licensed hub that speaks the W3C Web of Things model and you are willing to run a Node.js service behind your own TLS certificate. Skip it if you need a vendor support contract, a managed cloud, or an install path that does not involve a terminal. Before committing, verify three things: that your addons run under the Node 20 container, that your certificate files land in the ssl directory under your WEBTHINGS_HOME, and that the ports your setup needs (8080, 4443, and 5353/udp for mDNS) are reachable on the host.
Frequently asked questions
How do I install WebThings Gateway?
The README states that as of the 2.0 release the recommended way is the Docker image published as webthingsio/gateway. The repository also ships a docker-compose.yml that runs the container with network_mode: host and mounts a host directory at /home/node/.webthings. There is also an experimental snap package, and a documented build-from-source path using nvm, npm ci and npm start.
How do I connect to WebThings Gateway?
The README says to load http://localhost:8080 in a browser, or the server's IP address when connecting remotely, and follow the page to set up a domain and register. After that, the HTTPS interface is on https://localhost:4443. If you use your own self-signed certificate, the browser will require a security exception.
What ports does WebThings Gateway use?
The Dockerfile declares EXPOSE 8080 4443, and the README's Fedora firewall instructions open 4443/tcp, 8080/tcp and 5353/udp. Port 8080 is used during setup over plain HTTP, 4443 serves HTTPS, and 5353/udp is mDNS for discovery on the local network.
Does WebThings Gateway support Bluetooth devices?
The README includes Linux instructions to grant Bluetooth capability to node and python3 with setcap, and the docker-compose.yml notes that the container needs privileged mode for Bluetooth. The README also lists libbluetooth-dev among the Ubuntu and Debian build dependencies.
What licence is WebThings Gateway released under?
The project is licensed under MPL-2.0, which is declared in package.json and shown as a badge in the README. MPL-2.0 is file-level copyleft, so modifications to covered files must stay under the same licence.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/webthingsio-gateway)