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>
5.6 KiB
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
homeaiDocker network created once:docker network create homeai - All data volumes stored in service subdirectory (e.g.,
home-assistant/ha-data/) - Never use
network_mode: hostunless 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
.gitignoretemplates: 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-stoppedon 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:
- Complete onboarding at
http://localhost:8123 - Create a long-lived access token: Profile → Long-Lived Access Tokens
- Write token to
.env.secretsasHA_TOKEN - Install HACS (Home Assistant Community Store) — needed for custom integrations
- Enable advanced mode in user profile
Implementation Steps
- Install Docker Desktop for Mac, enable at login
- Create
homeaiDocker network - Create
~/server/directory structure - Write compose files for all services
- Write
.env.secrets.example - Write
Makefilewith 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 restarttest - Verify all containers survive a Mac Mini reboot
Success Criteria
docker psshows 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.servicesexists and all URLs are valid