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.
docker-compose so will provide these on a per-container basis to simplify the explanation.
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
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
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.
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.
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.
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!