ha-addon

Home Assistant Add-On Development

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "ha-addon" with this command: npx skills add nodnarbnitram/claude-code-extensions/nodnarbnitram-claude-code-extensions-ha-addon

Home Assistant Add-On Development

Expert guidance for building, configuring, and publishing Home Assistant add-ons with Docker, Supervisor integration, and multi-architecture support.

Before You Start

This skill prevents common Home Assistant add-on development errors:

Issue Symptom Solution

Permission errors Permission denied on supervisor API calls Use correct SUPERVISOR_TOKEN and API endpoints

Configuration validation Add-on won't load Validate config.yaml schema before publishing

Docker base image errors Missing dependencies in runtime Use official Home Assistant base images (ghcr.io/home-assistant)

Ingress misconfiguration Web UI not accessible through HA Configure nginx reverse proxy correctly

Multi-arch build failures Add-on only works on one architecture Set up build.yaml with architecture matrix

Quick Start: Create an Add-On from Scratch

Step 1: Create the Add-On Directory Structure

mkdir -p my-addon/{rootfs,rootfs/etc/s6-overlay/s6-rc.d/service-name} cd my-addon

Why this matters: Home Assistant expects specific directory layouts. The rootfs/ contains your actual application files that get packaged into the Docker image.

Step 2: Create config.yaml


name: My Custom Add-On description: My awesome Home Assistant add-on version: 1.0.0 slug: my-addon image: ghcr.io/home-assistant/{arch}-addon-my-addon arch:

  • amd64
  • armv7
  • aarch64 ports: 8080/tcp: null options: debug: false schema: debug: bool permissions:
  • homeassistant # Read/write Home Assistant core data

Why this matters: This is your add-on's manifest. The slug becomes the internal identifier and determines where configuration is stored.

Step 3: Create the Dockerfile

FROM ghcr.io/home-assistant/amd64-base:latest

Install dependencies

RUN apk add --no-cache python3 py3-pip

Copy application

COPY rootfs /

Set working directory

WORKDIR /app

Install Python packages if needed

RUN if [ -f requirements.txt ]; then pip install -r requirements.txt; fi

Run using S6 overlay

CMD ["/init"]

Why this matters: Using Home Assistant base images includes critical runtime components (S6 overlay, bashio helpers, supervisor integration).

Step 4: Create S6 Service Script

Create rootfs/etc/s6-overlay/s6-rc.d/service-name/run :

#!/command/execlineb -P foreground { echo "Starting my add-on..." } /app/my-service

Make it executable:

chmod +x rootfs/etc/s6-overlay/s6-rc.d/service-name/run

Why this matters: S6 overlay is Home Assistant's init system. It manages service startup, logging, and graceful shutdown.

Critical Rules

✅ Always Do

  • ✅ Use official Home Assistant base images (ghcr.io/home-assistant/{arch}-base)

  • ✅ Include all supported architectures in config.yaml (amd64, armv7, aarch64)

  • ✅ Use bashio helper functions for common operations (bashio::log::info, bashio::addon::option)

  • ✅ Validate config.yaml schema before releasing

  • ✅ Document configuration options in the schema section

  • ✅ Include addon_uuid in logs for debugging

❌ Never Do

  • ❌ Don't hardcode paths - use bashio to get configuration directory (/data/)

  • ❌ Don't run services as root unless absolutely necessary (set USER in Dockerfile)

  • ❌ Don't call supervisor API without SUPERVISOR_TOKEN

  • ❌ Don't ignore SIGTERM signals - implement graceful shutdown

  • ❌ Don't assume one architecture - use {arch} placeholder in image names

  • ❌ Don't store data outside /data/ - Home Assistant won't persist it

Common Mistakes

❌ Wrong: Hardcoded paths

#!/bin/bash CONFIG_PATH="/config/my-addon"

✅ Correct: Using bashio for configuration

#!/command/execlineb -P CONFIG_PATH=${"$(bashio::addon::config_path)"}

Why: bashio handles path resolution and ensures your add-on works in any Home Assistant installation.

Configuration Reference

config.yaml Structure


name: String # Display name description: String # Short description version: String # Semantic version (1.0.0) slug: String # URL-safe identifier image: String # Docker image URL with {arch} placeholder arch:

  • amd64|armv7|aarch64|armhf|i386 # Supported architectures ports: 8080/tcp: null # TCP port (null=internal only, number=external) 53/udp: 53 # UDP with external port mapping devices:
  • /dev/ttyACM0 # Device access services:
  • mysql # Depends on other service options: debug: false # User configuration options log_level: info schema: debug: bool # Configuration validation schema log_level:
    • debug
    • info
    • warning
    • error permissions:
  • homeassistant # Read/write HA config
  • hassio # Full supervisor API access
  • admin # Broad system access
  • backup # Backup/restore operations environment: NODE_ENV: production webui: http://[HOST]:[PORT:8080] # Web UI URL pattern ingress: true # Enable ingress proxy ingress_port: 8080 # Internal port for ingress ingress_entry: / # URL path for ingress entry

Key settings:

  • slug : Used internally and in supervisor API calls

  • arch : List all supported architectures or builds fail

  • image : Must use {arch} placeholder for dynamic builds

  • options : User-configurable settings

  • permissions : Controls supervisor API access level

  • ingress : Enables reverse proxy for web UIs

Common Patterns

Using bashio for Logging

#!/command/execlineb -P foreground { bashio::log::info "Add-on started" } foreground { bashio::log::warning "Low disk space" } foreground { bashio::log::error "Failed to connect" }

Accessing Configuration Options

#!/command/execlineb -P define DEBUG "$(bashio::addon::option 'debug')" define LOG_LEVEL "$(bashio::addon::option 'log_level')" if { test "${DEBUG}" = "true" } bashio::log::debug "Debug mode enabled"

Supervisor API Communication

#!/bin/bash

Get addon info

curl -X GET
-H "Authorization: Bearer $SUPERVISOR_TOKEN"
http://supervisor/addons/self/info | jq .

Send notification

curl -X POST
-H "Authorization: Bearer $SUPERVISOR_TOKEN"
-H "Content-Type: application/json"
-d '{"message":"Warning message"}'
http://supervisor/notifications/create

Multi-Arch Docker Build

Create build.yaml :

build_from: amd64: ghcr.io/home-assistant/amd64-base:latest armv7: ghcr.io/home-assistant/armv7-base:latest aarch64: ghcr.io/home-assistant/aarch64-base:latest armhf: ghcr.io/home-assistant/armhf-base:latest codenotary: your-notary-id # Optional code signing

Ingress Configuration for Web UIs

ingress: true ingress_port: 8080 ingress_entry: /

Optional ingress_stream for streaming endpoints

Inside your app, use correct reverse proxy headers:

nginx configuration in your app

location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $host; proxy_pass http://localhost:8080; }

Known Issues Prevention

Issue Root Cause Solution

Add-on fails to start Missing S6 service files Create /etc/s6-overlay/s6-rc.d/service-name/ with run executable

Supervisor API returns 401 Invalid SUPERVISOR_TOKEN Verify token is set by Home Assistant (check logs with addon_uuid )

Configuration not persisting Saving outside /data/ Always use bashio::addon::config_path or /data/ for persistence

Port already in use Multiple services on same port Check configuration - each service needs unique port

Architecture mismatch {arch} placeholder not used Use exact placeholder in image field: ghcr.io/home-assistant/{arch}-base

Build fails with "Unknown architecture" config.yaml lists unsupported arch Use only: amd64, armv7, aarch64, armhf, i386

Supervisor API Endpoints

Authentication: Pass SUPERVISOR_TOKEN header

Base URL: http://supervisor

GET /addons/self/info # Get current add-on details POST /addons/self/restart # Restart this add-on GET /addons/installed # List installed add-ons GET /info # System information POST /notifications/create # Send notification to user GET /config/homeassistant # Read Home Assistant config

Example with bashio

bashio::addon::self_info # Helper function for self info

Dependencies

Required

Package Version Purpose

Home Assistant 2024.1+ Add-on platform and supervisor

Docker Latest Container runtime

S6 Overlay 3.x Init system (included in base images)

Optional

Package Version Purpose

bashio Latest Helper functions (included in base images)

python3 3.9+ Python-based add-ons

nodejs 18+ Node.js-based add-ons

Official Documentation

  • Home Assistant Add-On Development

  • Add-On Configuration Reference

  • Supervisor Development

  • bashio Helper Functions

  • S6 Overlay Documentation

Troubleshooting

Add-on Won't Start

Symptoms: Add-on shows as "Not running" or "Unknown"

Solution:

Check logs

docker logs addon_name_latest # Or use HA UI: Settings > System > Logs

Common causes:

1. Invalid config.yaml syntax

2. Missing S6 service files

3. Dockerfile can't find base image

4. Permission denied on rootfs files

Supervisor API Returns 401

Symptoms: API calls fail with "Unauthorized"

Solution:

Verify SUPERVISOR_TOKEN is set

echo $SUPERVISOR_TOKEN

Check add-on logs for token errors

Token is automatically injected by Home Assistant

Verify permissions in config.yaml

If calling hassio endpoints, add: permissions: [hassio]

Configuration Not Saving

Symptoms: Options are lost after restart

Solution:

Always save to /data/ or use bashio

CONFIG_PATH="$(bashio::addon::config_path)" # Returns /data/ echo "my_value=123" > "${CONFIG_PATH}/settings.json"

Verify /data/ exists and is writable

ls -la /data/

Ingress Web UI Not Accessible

Symptoms: Ingress URL returns 502 or blank page

Solution:

1. Verify service is listening on correct port

netstat -tlnp | grep 8080

2. Check reverse proxy headers in app config

X-Forwarded-For, X-Forwarded-Proto must be set

3. Verify ingress settings in config.yaml

ingress: true ingress_port: 8080 ingress_entry: /

Build Fails with Architecture Error

Symptoms: "Unknown architecture" or "Image not found"

Solution:

Check config.yaml has valid arch values

arch:

  • amd64 # x86 64-bit
  • armv7 # 32-bit ARM (Pi 2/3)
  • aarch64 # 64-bit ARM (Pi 4+)
  • armhf # 32-bit ARM (older devices)
  • i386 # 32-bit x86 (rare)

Dockerfile must use {arch} placeholder

FROM ghcr.io/home-assistant/{arch}-base:latest

Setup Checklist

Before publishing your add-on, verify:

  • config.yaml has valid YAML syntax (use online YAML validator)

  • All listed architectures are supported (amd64, armv7, aarch64, armhf, i386)

  • Dockerfile uses official Home Assistant base image

  • S6 service files exist and are executable (chmod +x)

  • All configuration options are documented in schema

  • No hardcoded paths (use bashio helpers)

  • Permissions field lists required supervisor API access

  • Tested on at least amd64 and ARM architecture

  • Logs use bashio::log functions

  • Graceful shutdown on SIGTERM implemented

  • /data/ used for all persistent data

  • Ingress working if web UI is provided

  • README includes installation and usage instructions

Creating a Repository

To publish multiple add-ons:

  1. Create Repository Structure

mkdir my-addon-repo cd my-addon-repo

  1. Create repository.yaml

name: My Add-On Repository url: https://github.com/username/my-addon-repo maintainer: Your Name <email@example.com>

  1. Add Add-Ons

my-addon-repo/ ├── repository.yaml ├── my-addon-1/ │ ├── config.yaml │ ├── Dockerfile │ └── rootfs/ └── my-addon-2/ ├── config.yaml ├── Dockerfile └── rootfs/

  1. Push to GitHub

Add the repository URL to Home Assistant to make add-ons discoverable.

Advanced: Publishing to GitHub Container Registry

For private repositories or multi-architecture builds:

Build and push for all architectures

docker buildx build
--platform linux/amd64,linux/arm/v7,linux/arm64/v8
-t ghcr.io/username/my-addon:1.0.0
--push .

Related Skills

  • docker-configs

  • Docker fundamentals and best practices

  • esphome-config-helper

  • Related IoT device integration patterns

  • home-assistant-automation

  • Home Assistant automation and scripting

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

tauri-v2

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

ha-automation

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

kubernetes-operations

No summary provided by upstream source.

Repository SourceNeeds Review