For testing/evaluation purposes or as a guideline for application developers that want to run the Matter.js Server, we provide an official Docker container image. Make sure that the underlying operating system on which you intend to run the Docker container matches the requirements needed for Matter and Thread.
Note
Attention Home Assistant users: The Docker image is provided as-is and without official support (due to all the complex requirements to the underlying host/OS). Use it at your own risk if you know what you're doing.
We strongly recommend using Home Assistant OS along with the official Matter Server add-on to use Matter with Home Assistant. The Matter integration automatically installs the Matter Server as an add-on. Please refer to the Home Assistant documentation.
Home Assistant OS has been tested and tuned to be used with Matter and Thread, which makes this combination the best tested and largely worry-free environment.
If you still prefer a self-managed container installation, you might experience communication issues with Matter devices, especially Thread-based devices. This is mostly because the container installation uses host networking, and relies on the networking managed by your operating system.
| Tag | Description |
|---|---|
stable |
Latest stable release |
latest |
Same as stable |
dev |
Latest development/nightly (pre-release) version |
X.Y.Z |
Specific version (e.g., 1.0.0) |
X.Y |
Latest patch of minor version (e.g., 1.0) |
X |
Latest version of major release (e.g., 1) |
A Docker Compose file is provided in the repository at docker/matterjs-server/docker-compose.yml:
To use it:
# Navigate to the docker compose directory or copy the file
cd docker/matterjs-server
# Start the server
docker compose up -d
# View logs
docker compose logs -f
# Stop the server
docker compose downWith the following command you can run the Matter.js Server in a container using Docker. The Matter network data (fabric information) are stored in a newly created directory data in the current directory. Adjust the command to choose another location instead.
mkdir data
docker run -d \
--name matterjs-server \
--restart=unless-stopped \
-v $(pwd)/data:/data \
--network=host \
ghcr.io/matter-js/matterjs-server:stableNote
The container uses environment variables for configuration by default (STORAGE_PATH=/data). You can override any setting using environment variables or CLI arguments.
Warning
Security: The server binds to all network interfaces by default. You are responsible for
securing access according to your requirements and use-case — for example by setting
LISTEN_ADDRESS=127.0.0.1 to restrict the WebSocket port to localhost, setting
PRIMARY_INTERFACE=eth0 to control which interface Matter uses, or placing a firewall or
authenticating reverse proxy in front of the server.
You can also pass CLI arguments directly (these override environment variables):
docker run -d \
--name matterjs-server \
--restart=unless-stopped \
-v $(pwd)/data:/data \
--network=host \
ghcr.io/matter-js/matterjs-server:stable \
--storage-path /data \
--primary-interface eth0Common options:
--storage-path <path>: Path to store Matter fabric data (default:/data)--port <port>: WebSocket server port (default:5580)--primary-interface <interface>: Primary network interface for mDNS and Matter communication
For all available options, see the CLI documentation.
All CLI options can be configured via environment variables, making it easy to configure the server without passing command-line arguments.
| Variable | Description | Default | Values / Notes |
|---|---|---|---|
STORAGE_PATH |
Path to store Matter fabric data | /data |
Any valid path |
PORT |
WebSocket server port | 5580 |
Any valid port number |
LISTEN_ADDRESS |
IP address(es) to bind WebSocket server | (all interfaces) | Set a specific IP address to bind to a single address. Using ifname expands to all IPs on that interface (v4/v6). |
LOG_LEVEL |
Server logging verbosity | info |
critical, error, warning, info, debug, verbose |
LOG_FILE |
Log file path (must include filename, not just dir) | (none) | e.g. /data/logs/matter-server.log |
PRIMARY_INTERFACE |
Primary network interface for mDNS | (auto-detect) | e.g., eth0, en0 |
ENABLE_TEST_NET_DCL |
Enable test-net DCL certificates | false |
true/false, 1/0, yes/no, on/off |
BLUETOOTH_ADAPTER |
Bluetooth adapter HCI ID | (none) | e.g., 0 for hci0, but see this workaround |
DISABLE_OTA |
Disable OTA update functionality | false |
true/false, 1/0, yes/no, on/off |
OTA_PROVIDER_DIR |
Directory for OTA Provider files | (none) | Any valid directory path |
DISABLE_DASHBOARD |
Disable the web dashboard | false |
true/false, 1/0, yes/no, on/off |
PRODUCTION_MODE |
Force dashboard production mode (reverse proxy) | false |
true/false, 1/0, yes/no, on/off |
VENDOR_ID |
Vendor ID for the Fabric | 0xfff1 |
Any valid vendor ID |
FABRIC_ID |
Fabric ID for the Fabric | 1 |
Any valid fabric ID |
Note
LOG_FILE must be a full file path including the filename, not a directory. The log is rotated
every 24 hours, and on each startup: backups are shifted (.6→.7, …, .1→.2, current→.1),
keeping up to seven daily backup files (≈ 7 days of history). No further cleanup is performed.
Note
The LISTEN_ADDRESS environment variable only supports a single address. Use the CLI --listen-address option (repeatable) to bind to multiple addresses.
The value can either be an ip address or the network interface name (i.e. 192.168.1.10 or eth0)
For advanced matter.js library configuration via MATTER_* environment variables (e.g.
MATTER_DCL_PRODUCTION_URL for a self-hosted DCL node), see
Advanced matter.js Configuration in the CLI docs.
Example with environment variables:
docker run -d \
--name matterjs-server \
--restart=unless-stopped \
-v $(pwd)/data:/data \
--network=host \
-e LOG_LEVEL=debug \
-e PRIMARY_INTERFACE=eth0 \
ghcr.io/matter-js/matterjs-server:stableIf you want to build the Docker image yourself:
cd docker/matterjs-server
# Build with a specific version from npm
docker build \
--build-arg MATTERJS_SERVER_VERSION=1.0.0 \
-t matterjs-server:local \
.
# Run the locally built image
docker run -d \
--name matterjs-server \
--restart=unless-stopped \
-v $(pwd)/data:/data \
--network=host \
matterjs-server:localFor development, use Dockerfile.dev which builds from the local source code instead of npm:
# From the repository root
docker build \
-f docker/matterjs-server/Dockerfile.dev \
-t matterjs-server:dev \
.
# Run the development image
docker run -d \
--name matterjs-server-dev \
--restart=unless-stopped \
-v $(pwd)/data:/data \
--network=host \
matterjs-server:devThis builds the entire monorepo from source, which is useful for:
- Testing local changes in a container environment
- Debugging container-specific issues
- Verifying the build process works in a clean environment
Once running, the Matter.js Server exposes:
- WebSocket API:
ws://localhost:5580/ws- Python Matter Server compatible API - Web Dashboard:
http://localhost:5580/- Browser-based management interface
The container includes a built-in health check that verifies the server is responding. You can check the container health status with:
docker inspect --format='{{.State.Health.Status}}' matterjs-serverIf devices are not being discovered, ensure:
- Host networking is enabled (
--network=host) - mDNS is working on the host system
- The correct network interface is specified with
--primary-interfaceif needed
If you encounter permission issues with the data volume:
# Ensure the data directory is writable
chmod 755 data# Docker
docker logs -f matterjs-server
# Docker Compose
docker compose logs -fFor security reasons, by default the matter.js server is run as an unprivileged user in Docker. Unfortunately, up to now we didn't find a way to grant access to a specific HCI device to unprivileged users.
If you need to discover Matter devices via the hosts BLE, you can use this workaround:
- Stop the docker container
- Use
chown -R 0:0 /path-to-data-volume - Run docker with the root user
docker run --user=0:0 …(for compose:user: 0:0)
However, be aware this workaround effectively disables container isolation. For this reason, using other means of device commissioning (e.g. via the Home Assistant app) are preferred to applying this workaround.
When pinging a Matter device (e.g. via the Home Assistant UI) the matter.js server uses the system ping or ping6 command to send an ICMP echo request to the device and listen for its response.
To allow this, modern Linux distributions use a sysctl net.ipv4.ping_group_range with a value of 0 2147483647, meaning all user groups may send echo requests and responses (but not any other ICMP packet, see below).
If your host still has the old value of 1 0 (no pings allowed for anyone), it is recommended to either
- update the value to include group id 1000, or to
- grant the kernel capability
CAP_NET_RAWinstead:docker run --cap-add NET_RAW(for compose:cap_add: NET_RAW)
Note that the latter is a broader permission: it could be exploited to craft malicious network packets of any form.