Spec for packaging the Alexa Media Player HACS component declaratively on jupiter (HA -> Echo: TTS/announce, media, sensors). Requires bumping alexapy 1.29.22 -> 1.29.25 and packaging dictor 0.1.12 (absent from nixpkgs) to satisfy the manifest's exact requirement pins. Alexa -> HA voice control is explicitly deferred. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RCn8YgGQMGpauatdeTdQYf
6.7 KiB
Amazon Alexa integration for Home Assistant (jupiter) — design
Date: 2026-07-29 Machine: jupiter Status: approved, ready for implementation plan
Goal
Let Home Assistant control and read the household Amazon Echo devices via the
unofficial alexa_media_player
integration: text-to-speech / announcements, media control, and per-device
sensors (last-called device, next alarm/timer, DND state, etc.).
This uses the user's Amazon account through an unofficial API. It is a config-flow integration: after the rebuild it is added through the HA UI, not via YAML.
Non-goals (deferred)
Alexa → HA voice control ("Alexa, turn on the light") is out of scope. It
would need either emulated_hue bound to port 80 on the LAN, or a public HTTPS
endpoint plus the AWS-Lambda Smart Home Skill. The user chose to decide on that
later. Nothing in this change touches the firewall, port 80, systemd unit
capabilities, or network exposure.
Approach
Package the integration declaratively, following the existing ha-sourdough
pattern in modules/environments/home-assistant/default.nix (a
buildHomeAssistantComponent entry in services.home-assistant.customComponents).
No HACS runtime.
Unlike sourdough, alexa_media_player has real Python dependencies. Its
manifest.json (v5.15.7) declares:
alexapy==1.29.25
packaging>=20.3
wrapt>=1.14.0
dictor>=0.1.12,<0.2
buildHomeAssistantComponent runs manifestCheckPhase at build time
(check_manifest.py): every requirement must resolve to an installed
distribution whose version satisfies the specifier, or the build fails.
Home Assistant repeats this check at runtime. Therefore each requirement must be
satisfied exactly — the exact ==1.29.25 pin in particular.
Dependency status in the pinned nixpkgs (nixos-25.11):
| Requirement | nixpkgs today | Action |
|---|---|---|
alexapy==1.29.25 |
1.29.22 | Bump to 1.29.25 via override |
dictor>=0.1.12,<0.2 |
absent | Package dictor 0.1.12 (new) |
wrapt>=1.14.0 |
1.17.2 | none — already satisfied |
packaging>=20.3 |
26.1 | none — already satisfied |
authcaptureproxy (in nixpkgs at 1.3.7) is a transitive dependency of
alexapy, not listed in the manifest, so it needs no direct handling.
Components
All changes live in modules/environments/home-assistant/default.nix (plus the
hashes below). Three small pieces, wired together in the module's let block:
1. dictor package (new)
Not in nixpkgs. Pure-Python, no runtime dependencies (requires_dist: null),
ships a setup.py. A minimal pkgs.python3Packages.buildPythonPackage:
- pname
dictor, version0.1.12 src = fetchPypi { pname = "dictor"; version = "0.1.12"; hash = "sha256-bbSDda4eU9ye2EToWzj04/v79qTmC+yjd1Fa0URTuRs="; }- setuptools format (legacy
setup.py);build-system = [ setuptools ] doCheck = false(no meaningful test suite);pythonImportsCheck = [ "dictor" ]
Build against the HA Python set so the version lands in HA's venv — i.e. use
config.services.home-assistant.package.python.pkgs (the same interpreter the
component check and HA runtime use), not the top-level pkgs.python3Packages.
2. alexapy 1.29.25 (override)
nixpkgs alexapy is fetched from GitLab (keatontaylor/alexapy, tag
v<version>), not PyPI. Override just the version + src via
overridePythonAttrs, reusing the existing build-system and dependency list:
version = "1.29.25"src = fetchFromGitLab { owner = "keatontaylor"; repo = "alexapy"; tag = "v1.29.25"; hash = "sha256-P/hvgqZVaBJF5dbmHrDjQMC+pwV3EEhKyFIS5KmhgD4="; }
This is a patch bump (1.29.22 → 1.29.25); the dependency set is expected to be
unchanged. Override the HA-Python-set alexapy so it shares the interpreter
with dictor and the component.
3. alexa_media_player component (new customComponents entry)
buildHomeAssistantComponent {
owner = "Alandtse";
domain = "alexa_media";
version = "5.15.7";
src = fetchFromGitHub {
owner = "Alandtse";
repo = "alexa_media_player";
rev = "v5.15.7";
hash = "sha256-1rcZVSX1xA1Lc4qSu39MOitVEciZFhoPQy2y5+PpoAI=";
};
dependencies = [ alexapy' dictor' wrapt packaging ]; # HA-python-set packages
}
dependencies must make every manifest requirement importable at the required
version for manifestCheckPhase to pass. Include all four (the two custom ones
plus wrapt and packaging from the HA Python set) to be explicit.
Data flow
nixos-rebuild switchbuilds the component;manifestCheckPhasevalidates the four requirements against the provideddependencies.- HA starts; the custom component is present but not configured.
- User adds Alexa Media Player in Settings → Devices & Services, signs in with the Amazon account (email/password; 2FA or app-password handled in the UI flow at runtime).
- HA creates media_player entities and per-device sensors; TTS/announce services become available for automations.
Error handling / risks
- Version-pin drift. If a future
alexa_media_playerbump changes thealexapy==pin,alexapymust be re-bumped in lockstep, or the build fails loudly atmanifestCheckPhase(fail-safe, not silent). - Amazon login fragility. The unofficial API can break on Amazon's side (captcha/2FA changes). This is a runtime concern, independent of packaging; not addressed here.
dictorupper bound<0.2. 0.1.12 is the current release and satisfies it. If nixpkgs later gains adictor≥ 0.2, prefer our pinned 0.1.12 for this component.
Verification
nix build '.#nixosConfigurations.jupiter.config.system.build.toplevel'succeeds — this exercises the build-time manifest-requirements check for all three new/overridden derivations.nixfmt-rfc-styleclean on the edited module.- Post-deploy (manual, by the user): the integration appears under Add Integration, and a TTS/announce call reaches an Echo.
Pinned artifacts
| Artifact | Source | Ref / version | Hash |
|---|---|---|---|
| alexa_media_player | GitHub | v5.15.7 | sha256-1rcZVSX1xA1Lc4qSu39MOitVEciZFhoPQy2y5+PpoAI= |
| alexapy | GitLab | v1.29.25 | sha256-P/hvgqZVaBJF5dbmHrDjQMC+pwV3EEhKyFIS5KmhgD4= |
| dictor | PyPI sdist | 0.1.12 | sha256-bbSDda4eU9ye2EToWzj04/v79qTmC+yjd1Fa0URTuRs= |