The ability to access ESPHome via HTTPS is an important consideration if you’re going to host ESPHome on your own Docker server. If you don’t have an encrypted connection, you can’t use USB flashing. Unfortunately the current Docker container does not include support for encrypted connections.
This brief post explains how I achieved this aim, and I hope it may help others.
I use docker-compose
so will provide these on a per-container basis to simplify the explanation.
Encryption Certificates
I am using the certificates generated via HA’s integrated LetsEncrypt addon. There are plenty of guides on this step, so I won’t duplicate them. But, put simply, you’ll need to set it up for wildcards (like *.mydomain.com), and then create an automation to copy the resulting PEMs to your Docker host. You’ll also need to rename the files, to allow the system to automatically pick them up:
privkey.pem -> mydomain.com.key
fullchain.pem -> mydomain.com.crt
Reverse Proxy
First you need nginx to act as a reverse proxy. It’ll accept encrypted connections from your browser, and then route the decrypted traffic to your target container. Here is a sample docker-compose.yaml
:
version: '2'
services:
nginx-proxy:
container_name: nginx
image: jwilder/nginx-proxy
ports:
- 80:80
- 443:443
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- /path/to/copied/certificates:/etc/nginx/certs
- /storage/path/to/vhosts.d:/etc/nginx/vhost.d
network_mode: host
environment:
- DEFAULT_HOST=<Docker fully-qualified Hostname>
You should be able to start nginx via docker-compose up -d which will create the container, and the nginx network.
ESPHome
The docker-compose.yaml
is as follows:
version: '3'
services:
esphome:
container_name: esphome
image: esphome/esphome
volumes:
- /path/to/esphome/config:/config
- /etc/localtime:/etc/localtime:ro
restart: always
privileged: true
networks:
- nginx_default
environment:
- VIRTUAL_HOST=esphome.mydomain.com #This needs to be set to a unique subdomain that will be your URL.
networks:
nginx_default:
name: nginx_default
Make sure you update your DNS (or hosts file) so that your custom URL is resolvable.
Now fire it up via docker-compose up -d and let it install. I found that nginx only seems to pickup new containers on startup so, just to be sure, stop both, start nginx and then ESPHome.
You now should be able to access esphome via the URL you set above. So point your browser at https://esphome.mydomain.com and you should find yourself connected to ESPHome via HTTPS. Awesome!
The plot twist
But there is an issue. All of your tiles will show that the nodes are offline. This is because ESPHome relies on mdns (which is a broadcast/multicast protocol to do name resolution).
Unfortunately this isn’t easily fixed in either container or Docker itself.
mdns Repeater
The easiest solution, requiring the least amount of tweaking of broader Docker, was to install an mdns repeater on the network ESPHome is connected to. First, we need to find the id of the nginx network. From the command prompt, issue a docker network ls and scan down for the nginx_default
network. It should look something like:
abcdefghijk nginx_default bridge local
Copy the ID to your clipboard, and then do an ifconfig | grep abcdefghijk
We’re looking for the interface name, which is probably just br-abcdefghijk, but it’s worth confirming. You then also need to find the interface name of your Ethernet adapter.
The docker-compose.yaml:
version: '3'
services:
mdns-repeater:
image: monstrenyatko/mdns-repeater
container_name: mdns-repeater
restart: unless-stopped
command: mdns-repeater-app -f <Ethernet Adapter Name> <nginx-adapter name> #eg mdns-repeater-app -f eth0 br-abcdefghijk
network_mode: "host"
Issue your final docker-compose up -d and you should find that your ESPHome tiles spring to life.
I hope this helps someone who wants to do the same!