Skip to main content

esphome-deployment

A CLI Tool for managing compilation and deployment of ESPHome Device configurations.

Programming Language Latest Release License

Features

  • 🚀 Batch Deployment: Deploy to multiple devices with a single command.
  • 📦 Smart Caching: Avoids redundant compiles by tracking configuration hashes.
  • 🕵️ Change Detection: Only uploads binaries if the resulting build actually changed.
  • 🔄 VCS State Tracking: Store deployment metadata in Git to sync state across CI/CD or multiple machines.
  • 📋 Detailed Logging: Automatic per-device log capture for easy debugging.

Setup

Prerequisites

  1. ESPHome CLI must be installed in your PATH.
  2. A Git repository for your ESPHome device configurations.

Reproducible Builds

For the caching mechanism of esphome-deployment to work across machines, the firmware images produced by ESPHome need to be made reproducible. This means that given the same input, the build process should always produce the exact same output binary, bit for bit. Unfortunately, ESPHome does not currently guarantee reproducible builds out of the box, but there are a couple of options we can add to our configuration YAML to remedy this:

esphome: Section

packages/esphome.yaml

esphome:
  platformio_options:
    build_flags:
      # 1. Prevent warnings for redefining built-in macros
      - -Wno-builtin-macro-redefined
      # 2. Force a static date and time
      - '-D__DATE__="\"Dec 29 2025\""'
      - '-D__TIME__="\"23:00:00\""'

See: https://esphome.io/components/esphome/

esp32: Section

packages/chip/esp32-esp-idf.yaml

esp32:
  framework:
    type: esp-idf
    sdkconfig_options:
      # options to ensure reproducible builds (exact binary match)
      CONFIG_APP_REPRODUCIBLE_BUILD: y
      CONFIG_APP_COMPILE_TIME_DATE: n
      CONFIG_APP_EXCLUDE_PROJECT_VER_VAR: y
      CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR: y

See: https://esphome.io/components/esp32/

Docker

If you prefer to use Docker, you can use the published image ghcr.io/markusressel/esphome-deployment from ghcr. Just ensure you mount your ESPHome configurations path into it, and run the CLI commands as shown in the usage section below.

docker run --rm -it \
  -v ~/esphome-configs:/config \
  -u $(id -u):$(id -g) \
  -e ESPHOME_DEPLOYMENT_DEPLOYMENT_COORDINATOR_MAX_WORKERS=1 \ 
  ghcr.io/markusressel/esphome-deployment:latest \
  esphome-deployment --help

Usage

Usage: esphome-deployment [OPTIONS] COMMAND [ARGS]...

Options:
  --version   Show the version and exit.
  -h, --help  Show this message and exit.

Commands:
  clean    Clean
  compile  Compile the given deployment(s)
  config   Print the current configuration
  deploy   Deploy (compile + upload) the given deployment(s)
  upload   Upload the given deployment(s)

Configuration

Main configuration

The main configuration for esphome-deployment can be specified in a file named .esphome_deployment.yaml located next to your ESPHome configurations (within your working directory). See .esphome_deployment.yaml for all available options.

Per-Device configuration

Each ESPHome configuration can optionally contain a .esphome_deployment: section (note the leading dot) to adjust the deployment behavior for that specific device. Example:

.esphome_deployment:
  deploy: true
  tags:
    - bluetooth_proxy

packages:
  esphome: !include packages/esphome.yaml
  chip: !include packages/chip/esp32-esp-idf.yaml

... rest of your esp home config ...

Repository layout, state files and logs

Recommended layout for a repository using esphome-deployment to deploy multiple ESPHome configurations:

<repo-root>/
├── packages/                 # reusable package files (recommended)
│   ├── esphome.yaml
│   └── chip/...
├── .deployment-state/        # (generated) per-deployment JSON state files, commit this to VCS to share state across machines
├── .deployment-logs/         # (generated) CLI logs for compile/upload runs
├── .esphome_deployment.yaml  # global config for esphome-deployment
├── secrets.yaml
├── your-device-1.yaml        # individual deployment yamls (put in repo root)
└── your-device-2.yaml

Add this to your .gitignore:

# Ignore generated log files from esphome-deployment, but keep the deployment state files for VCS tracking
.deployment-logs/

Deployment State

esphome-deployment remembers the compilation and upload state for each deployment configuration in a JSON file within .deployment-state/.

  • What they are: For every esphome invocation the CLI writes a log into .deployment-logs/ in the same directory as your device YAMLs. Filenames are like <deployment>_<command>_YYYYMMDD_HHMMSS.log and contain merged stdout/stderr from the esphome CLI. These logs are invaluable for debugging compile/upload issues.

Logs

esphome-deployment captures the output of each esphome CLI invocation and saves it to a log file in .deployment-logs/ for later inspection. This includes both stdout and stderr, merged together with timestamps for easier debugging.

# list recent logs
ls -lt .deployment-logs/

# view a specific log
less .deployment-logs/<filename>.log

# follow a log in real time
tail -f .deployment-logs/<filename>.log

Contributing

Contributions to esphome-deployment are very welcome! If you have an idea for a new feature, found a bug or want to help out with documentation, please open an issue or submit a pull request.

Local Development

### Installation

1. Clone this repository as a git submodule next to your ESPHome configurations
    * e.g. `git submodule add https://github.com/markusressel/esphome-deployment`
2. Ensure your configurations utilize the reproducible build options as shown above
    * e.g. via packages for both ESPHome and ESP32 devices containing the options above
3. Use `poetry` (or any other method of your choice) to run esphome-deployment (see below)

```bash
python3 -m venv venv
. venv/bin/activate && pip install --upgrade pip poetry
poetry install -P ./esphome-deployment

License

esphome-deployment is licensed under the AGPLv3 License. By using or contributing to this project, you agree to comply with the terms of this license. Please review the LICENSE file for more details.

Metadata

Release files for esphome-deployment 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for esphome-deployment 0.1.0
File Size Uploaded
esphome_deployment-0.1.0.tar.gz 33.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for esphome-deployment 0.1.0
File Interpreter ABI Platform
esphome_deployment-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 69.6 kB

Release files / esphome_deployment-0.1.0.tar.gz

Download URL esphome_deployment-0.1.0.tar.gz
Size 33.4 kB
Tags Source
SHA-256 checksum
How to use checksums
3e7e350700e06b7ee791322773fbf08c17e841b5ed74fe95b97db32f76537b76
BLAKE2b-256 checksum
How to use checksums
cfd11b2764a552b040a881d66d61267fad915f023c37ac7aa4e58fd5db5925b8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 25, 2026.

Transparency log

Release files / esphome_deployment-0.1.0-py3-none-any.whl

Download URL esphome_deployment-0.1.0-py3-none-any.whl
Size 36.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
00090d8bcecca8060e8f84e0901a1de7c853d32c0f958cdffbcb934643a9dbc7
BLAKE2b-256 checksum
How to use checksums
7c8d704b0bf47bdfd902b434268f0a9cf13787c8eb0bfc5799626b6f1ddd0763
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page