# 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: ```yaml services: : image: container_name: restart: unless-stopped env_file: - ../../.env.secrets volumes: - ./-data:/data networks: - homeai ports: - ":" 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: ```dotenv HA_URL=http://localhost:8123 HA_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) ```dotenv 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 ```makefile 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