Files
homeai/homeai-infra/PLAN.md
Aodhan Collins 38247d7cc4 Initial project structure and planning docs
Full project plan across 8 sub-projects (homeai-infra, homeai-llm,
homeai-voice, homeai-agent, homeai-character, homeai-esp32,
homeai-visual, homeai-images). Includes per-project PLAN.md files,
top-level PROJECT_PLAN.md, and master TODO.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 01:11:37 +00:00

5.6 KiB

P1: homeai-infra — Infrastructure & Foundation

Phase 1 | No hard dependencies | Must complete before all other projects


Goal

Get the Mac Mini running a stable, self-healing Docker stack accessible over Tailscale. All services should survive a reboot with no manual intervention.


Deliverables

1. Directory Layout

~/server/
├── docker/
│   ├── home-assistant/
│   │   └── docker-compose.yml
│   ├── open-webui/
│   │   └── docker-compose.yml
│   ├── portainer/
│   │   └── docker-compose.yml
│   ├── uptime-kuma/
│   │   └── docker-compose.yml
│   ├── gitea/
│   │   └── docker-compose.yml
│   ├── n8n/
│   │   └── docker-compose.yml
│   └── code-server/
│       └── docker-compose.yml
├── .env.services          ← shared service URLs, written by this project
├── .env.secrets           ← secrets, never committed
└── Makefile               ← up/down/restart/logs per service

2. Services to Deploy

Service Image Port Purpose
Home Assistant ghcr.io/home-assistant/home-assistant:stable 8123 Smart home platform
Portainer portainer/portainer-ce 9443 Docker management UI
Uptime Kuma louislam/uptime-kuma 3001 Service health monitoring
Gitea gitea/gitea 3000 (HTTP), 2222 (SSH) Self-hosted Git
code-server codercom/code-server 8080 Browser VS Code
n8n n8nio/n8n 5678 Workflow automation

Open WebUI deployed in P2 (depends on Ollama being up first).

3. Docker Configuration Standards

Each compose file follows this pattern:

services:
  <service>:
    image: <image>
    container_name: <service>
    restart: unless-stopped
    env_file:
      - ../../.env.secrets
    volumes:
      - ./<service>-data:/data
    networks:
      - homeai
    ports:
      - "<port>:<port>"

networks:
  homeai:
    external: true
  • Shared homeai Docker network created once: docker network create homeai
  • All data volumes stored in service subdirectory (e.g., home-assistant/ha-data/)
  • Never use network_mode: host unless required by service

4. .env.services — Interface Contract

Written by this project, sourced by all others:

HA_URL=http://localhost:8123
HA_TOKEN=<long-lived access token>
PORTAINER_URL=https://localhost:9443
GITEA_URL=http://localhost:3000
N8N_URL=http://localhost:5678
CODE_SERVER_URL=http://localhost:8080
UPTIME_KUMA_URL=http://localhost:3001

5. .env.secrets (template, not committed)

HA_TOKEN=
GITEA_ADMIN_PASSWORD=
CODE_SERVER_PASSWORD=
N8N_ENCRYPTION_KEY=

Committed as .env.secrets.example with blank values.

6. Tailscale Setup

  • Install Tailscale on Mac Mini: brew install tailscale
  • Run tailscale up --accept-routes
  • All service URLs are LAN-only; Tailscale provides remote access without port forwarding
  • No ports opened in router/firewall

7. Makefile Targets

up-ha:         # docker compose -f docker/home-assistant/docker-compose.yml up -d
down-ha:
logs-ha:
up-all:        # bring up all services in dependency order
down-all:
restart-all:
status:        # docker ps --format table

8. Gitea Initialisation

  • Admin user created, SSH key added
  • Repos created for all 8 sub-projects
  • SSH remote added to each local repo
  • .gitignore templates: exclude *.env.secrets, *-data/, __pycache__/

9. Uptime Kuma Monitors

One monitor per service:

  • Home Assistant HTTP check → http://localhost:8123
  • Portainer HTTPS check → https://localhost:9443
  • Gitea HTTP check → http://localhost:3000
  • n8n HTTP check → http://localhost:5678
  • Ollama HTTP check → http://localhost:11434 (set up after P2)
  • Wyoming STT TCP check → port 10300 (set up after P3)

Alerts: configure ntfy or Pushover for mobile notifications.

10. Reboot Survival

  • Docker Desktop for Mac: set to launch at login
  • Docker containers: restart: unless-stopped on all
  • Ollama: launchd plist (configured in P2)
  • Wyoming: launchd plist (configured in P3)
  • ComfyUI: launchd plist (configured in P8)

Home Assistant Setup

After container is running:

  1. Complete onboarding at http://localhost:8123
  2. Create a long-lived access token: Profile → Long-Lived Access Tokens
  3. Write token to .env.secrets as HA_TOKEN
  4. Install HACS (Home Assistant Community Store) — needed for custom integrations
  5. Enable advanced mode in user profile

Implementation Steps

  • Install Docker Desktop for Mac, enable at login
  • Create homeai Docker network
  • Create ~/server/ directory structure
  • Write compose files for all services
  • Write .env.secrets.example
  • Write Makefile with up/down/logs targets
  • make up-all — bring all services up
  • Home Assistant onboarding — generate HA_TOKEN
  • Write .env.services
  • Install Tailscale, connect all services accessible on Tailnet
  • Gitea: create admin account, initialise repos, push initial commits
  • Uptime Kuma: add all monitors, configure alerts
  • Verify all containers restart cleanly after docker restart test
  • Verify all containers survive a Mac Mini reboot

Success Criteria

  • docker ps shows all services running after a cold reboot
  • Home Assistant UI reachable at http://localhost:8123
  • Gitea accessible, SSH push/pull working
  • Uptime Kuma showing green for all services
  • All services reachable via Tailscale IP from a remote device
  • .env.services exists and all URLs are valid