Home Assistant Container has no app store. You run the same app as its own container next to Home Assistant, from a ready image; the ESPHome tools are in it. On Home Assistant OS you don't need this page: install the app instead.
Which route is yours
| Your setup | What to follow |
|---|---|
Linux host, Home Assistant with network_mode: host (the standard Home Assistant Container setup) | Install, then Open Tessera |
Windows or macOS with Docker Desktop, or Home Assistant published with ports: | Install steps 1 and 2, then Home Assistant on a bridge network |
| Synology NAS (Container Manager) | Synology NAS |
What you need
- Home Assistant Container, and Docker with Compose on the same machine (amd64 or aarch64).
- Nothing to build: Compose pulls a ready image from GitHub (
ghcr.io/maxgramser/homeassistant_espscreen, for amd64 and arm64), the same app the Home Assistant app store offers. You don't needgit, so it also works on a Synology NAS. - The ESPHome integration in Home Assistant. Tessera adds the screens to it by itself.
- A Home Assistant account with administrator rights, to create an access token.
Install
Create a folder, for example
esp-screens, and save compose.yaml in it.Create an access token. In Home Assistant, open your profile, go to the Security tab, and under Long-lived access tokens choose Create token. Paste only the token into a new file named
ha_token, next tocompose.yaml. On Linux, make it readable for you only:shchmod 600 ha_tokenOn Docker Desktop, continue with Home Assistant on a bridge network now.
Check two lines in
compose.yaml:HA_API: http://127.0.0.1:8123/apiis right when Home Assistant runs on the same machine on port 8123. Keep/apiat the end../esphome:/configkeeps the screens' ESPHome files in a newesphomefolder. If you already use ESPHome Device Builder, put its folder here instead, so both see the same files.
Start the container from the folder:
shdocker compose up -dThe first start downloads the image, which is based on the official ESPHome image. This takes a few minutes.
Check that it runs:
shdocker compose logs -fWhat you'll see: the line
Home Assistant connectedonce the token works. Press Ctrl+C to stop following the log. After about a minute,docker psshows(healthy)next toesp-screens.
Open Tessera
The page has no login of its own, so it only listens on 127.0.0.1:8099 of the Docker host and answers nothing else. Don't make port 8099 reachable from your network.
In the Home Assistant sidebar (recommended)
Install hass_ingress from HACS.
Add this to
configuration.yaml:yamlingress: tessera: title: Tessera icon: mdi:view-grid require_admin: true url: http://127.0.0.1:8099Restart Home Assistant.
What you'll see: Tessera in the sidebar. Home Assistant handles the login, just like the app panel on Home Assistant OS.
Through an SSH tunnel
From your own computer:
ssh -L 8099:127.0.0.1:8099 you@docker-hostThen open http://localhost:8099. A screen's card offers Open Devices & services when Tessera can't add the screen to Home Assistant by itself. That button only works in the sidebar panel; here, open Home Assistant yourself.
Home Assistant on a bridge network
Use this when Home Assistant does not use network_mode: host but publishes its ports under ports:. That is the usual setup with Docker Desktop on Windows and macOS, where "host" means Docker's own Linux VM and not your computer.
Without these steps the sidebar panel shows 502: Bad Gateway: inside the Home Assistant container, 127.0.0.1 is Home Assistant itself, not Tessera. The fix is to let Tessera share the network of the Home Assistant container, so 127.0.0.1 means the same in both.
Move the
esp-screensservice from the downloadedcompose.yamlinto the compose file that already holds Home Assistant. Copy thesecrets:block at the bottom along with it, and putha_tokennext to that file.Change the two services like this. Put the service name of Home Assistant after
service::yamlservices: homeassistant: # ... your existing settings ... ports: # ... your existing ports ... - 8098:8098 # camera images for the screens esp-screens: # ... image, restart, init, secrets, volumes and healthcheck stay as they are ... network_mode: "service:homeassistant" # replaces network_mode: host depends_on: - homeassistant environment: SCREEN_DEV: "1" HA_API: http://127.0.0.1:8123/api # Home Assistant in the shared network, see the https note below HA_TOKEN_FILE: /run/secrets/ha_token ESPHOME_CONFIG: /config SCREEN_DATA: /data SCREEN_CAMERA_URL: http://192.168.1.20:8098 # your computer's address on the home networkHome Assistant on https only? Then
http://127.0.0.1:8123doesn't answer, andhttps://127.0.0.1:8123fails the certificate check. PointHA_APIat an http address that reaches Home Assistant, such as a reverse proxy in front of it. On Docker Desktop,http://host.docker.internal:<port>/apireaches a port your computer publishes.Start both:
shdocker compose up -dCheck that Home Assistant reaches the app. Replace
homeassistantwith the name of your Home Assistant container (docker psshows it):shdocker exec homeassistant curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8099/What you'll see:
200means the panel works.000means the two containers don't share a network yet.Set up the sidebar panel as in Open Tessera. The configuration stays the same.
Good to know:
- Updating Home Assistant recreates its container and takes the shared network away. Run
docker compose up -dagain afterwards, so the Tessera container is recreated too. - Camera images: your computer's firewall has to let the screens in on port 8098 (Windows Firewall on Windows).
- USB: Docker Desktop passes no USB ports to containers. Plug the screen into your computer and install it from the browser, as in Installing screens.
Opening the panel this way is confirmed on Docker Desktop for Windows with WSL 2. Camera images and updates over Wi-Fi have not been tested on Docker Desktop yet. If you try them, please report back in an issue.
Synology NAS
The ready image is what makes a Synology NAS work: Container Manager has no git and doesn't need to build anything.
- In File Station, create a folder for the app, for example
docker/esp-screens. - Put
compose.yamland yourha_tokenfile in it, as in Install steps 1 to 3. - In Container Manager, open Project, choose Create, pick that folder and use its existing
compose.yaml. - Start the project. Container Manager pulls the image and starts the app.
Then open the panel as in Open Tessera. A Synology usually can't pass a USB port to the container, so install your screens from your own computer, as in Installing screens.
Running Synology Container Manager with the ready image is new. Please report how it goes.
Prefer to build the image yourself? compose.yaml has the build: lines ready, in a comment above image:. That needs git on the host.
Installing screens
From here it works like the app on Home Assistant OS: New screen installs a screen, Tessera adds it to Home Assistant by itself once it is on your Wi-Fi, and then you choose the tiles. Add a screen walks through it.
Tessera knows a screen's key from its file in the folder mounted at /config. A screen whose file lives somewhere else, such as an ESPHome Device Builder folder you didn't mount here, is added to Home Assistant by hand.
How to get the first firmware onto a screen:
| Your host | How |
|---|---|
| Linux, screen plugged into the Docker host | Connect the screen, uncomment devices: in compose.yaml with its port (/dev/ttyUSB0 or /dev/ttyACM0), and run docker compose up -d. Then choose that port under Install via. |
| Docker Desktop, Synology, or a server out of reach | Plug the screen into the computer you are using. Under Install via, in Plugged into this computer, choose Install from this browser (Chrome or Edge) and click Connect & install. The container builds the firmware and the page writes it to the screen. This needs Tessera opened over https, or on localhost (such as through the SSH tunnel). Otherwise choose Download the file and flash it yourself and put the file on the screen with ESPHome Web. |
After the first install, every update goes over Wi-Fi and needs nothing extra.
Camera images: every screen except the CYD, the Waveshare 3.5-inch and the Hosyond 4-inch shows camera pictures and album covers. The screens load them from port 8098 of the Docker host, so keep that port open to them. By default the app gives the screens Home Assistant's own network address. If the screens reach the Docker host under another address, set SCREEN_CAMERA_URL. More in Cameras and pictures.
Claude: the Install for Claude Code button is meant for the Claude Code app on Home Assistant OS. Use Download for claude.ai instead.
Updating
Update the app first, then update each screen.
To update the app, run this in the folder with compose.yaml:
docker compose pull
docker compose up -dThis pulls the latest image, the same version the Home Assistant app store offers. On a Synology, stop the project in Container Manager, pull the new image and start the project again. Afterwards, Tessera shows for each screen whether newer firmware is available.
To stay on one version, replace latest in the image: line of compose.yaml with a version number:
image: ghcr.io/maxgramser/homeassistant_espscreen:0.3.25Set up before app 0.3.22? Your compose.yaml still builds from GitHub with build:. Download the current compose.yaml and keep your own HA_API and folders.
Backups
Home Assistant backups don't include this container. Keep a copy of:
data/screens.jsonanddata/updates.json: your layouts and update settings.- The ESPHome folder (
esphomeby default): the screens' files and Wi-Fi secrets.
data/build, data/esphome, data/idf and data/platformio are caches and can be left out.
Settings in compose.yaml
| Setting | What it does |
|---|---|
SCREEN_DEV: "1" | Runs the app without Home Assistant's Supervisor: it reads the token from HA_TOKEN_FILE, and the page listens on 127.0.0.1 only. Camera images for the screens stay on port 8098 on every address. |
HA_API | Home Assistant's address, ending in /api |
HA_TOKEN_FILE | The token file inside the container (the ha_token secret) |
ESPHOME_CONFIG | The ESPHome folder inside the container. Keep it /config: /esphome holds the ESPHome tools themselves. |
SCREEN_DATA | Layouts, update settings and build caches |
SCREEN_CAMERA_URL | Optional: where screens load camera images, such as http://192.168.1.20:8098. By default Home Assistant's own network address. |
SCREEN_CAMERA_PORT | Optional: another port for camera images instead of 8098 |
If something doesn't work
| What you see | What to do |
|---|---|
An error that git can't be found | Your compose.yaml is from before app 0.3.22 and still builds from GitHub. Use the current one, which pulls the ready image (see Updating). |
No Home Assistant connected in the log | Check that ha_token holds only the token, and that HA_API ends in /api and reaches Home Assistant from inside the container. |
| 502: Bad Gateway in the sidebar panel | Home Assistant is on a bridge network. Follow Home Assistant on a bridge network. |
| The page asks you to open it through Home Assistant | You opened port 8099 from another address. Use the sidebar panel or the SSH tunnel. |
| Camera tiles stay empty | Open port 8098 on the Docker host to the screens, and set SCREEN_CAMERA_URL if the screens reach the host under another address. |
Still stuck? Please open an issue.