Claude
Skills
Sign in
Back

ubuntu-deployment

Included with Lifetime
$97 forever

Deploy and manage Home Assistant on Ubuntu servers with Docker, security hardening, and complementary services.

Cloud & DevOps

What this skill does


# Ubuntu Deployment Skill

Deploy and manage Home Assistant on Ubuntu servers with Docker, security hardening, and complementary services.

## Activation Triggers

Activate this skill when:
- Deploying Home Assistant on Ubuntu
- Setting up Docker Compose stacks
- Configuring server security
- Managing backups and updates
- Setting up monitoring

## System Requirements

| Component | Minimum | Recommended |
|-----------|---------|-------------|
| CPU | 2 cores | 4+ cores |
| RAM | 2GB | 8GB+ |
| Storage | 32GB SSD | 128GB+ NVMe |
| Network | 100Mbps | 1Gbps |
| Ubuntu | 22.04 LTS | 24.04 LTS |

## Quick Deploy Script

```bash
#!/bin/bash
# ha-quick-deploy.sh

set -e

INSTALL_DIR="${INSTALL_DIR:-/opt/homeassistant}"
TZ="${TZ:-America/New_York}"

echo "=== Home Assistant Quick Deploy ==="

# Update system
sudo apt update && sudo apt upgrade -y

# Install Docker
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER

# Install Docker Compose plugin
sudo apt install -y docker-compose-plugin

# Create directory structure
sudo mkdir -p $INSTALL_DIR/{homeassistant,mosquitto/{config,data,log},zigbee2mqtt,nodered,ollama}
sudo chown -R $USER:$USER $INSTALL_DIR

# Create docker-compose.yaml
cat > $INSTALL_DIR/docker-compose.yaml << 'COMPOSE'
version: '3.8'

services:
  homeassistant:
    container_name: homeassistant
    image: ghcr.io/home-assistant/home-assistant:stable
    restart: unless-stopped
    privileged: true
    network_mode: host
    volumes:
      - ./homeassistant:/config
      - /etc/localtime:/etc/localtime:ro
    environment:
      - TZ=${TZ}

  mosquitto:
    container_name: mosquitto
    image: eclipse-mosquitto:latest
    restart: unless-stopped
    ports:
      - "1883:1883"
    volumes:
      - ./mosquitto/config:/mosquitto/config
      - ./mosquitto/data:/mosquitto/data
      - ./mosquitto/log:/mosquitto/log

  ollama:
    container_name: ollama
    image: ollama/ollama:latest
    restart: unless-stopped
    ports:
      - "11434:11434"
    volumes:
      - ./ollama:/root/.ollama
COMPOSE

# Create Mosquitto config
cat > $INSTALL_DIR/mosquitto/config/mosquitto.conf << 'MQTT'
listener 1883
allow_anonymous true
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
MQTT

# Start services
cd $INSTALL_DIR
docker compose up -d

# Pull Ollama models
sleep 10
docker exec ollama ollama pull llama3.2:3b

echo ""
echo "=== Deployment Complete ==="
echo "Home Assistant: http://$(hostname -I | awk '{print $1}'):8123"
echo "Ollama API: http://$(hostname -I | awk '{print $1}'):11434"
```

## Full Stack Docker Compose

```yaml
version: '3.8'

services:
  # Home Assistant
  homeassistant:
    container_name: homeassistant
    image: ghcr.io/home-assistant/home-assistant:stable
    restart: unless-stopped
    privileged: true
    network_mode: host
    volumes:
      - ./homeassistant:/config
      - /etc/localtime:/etc/localtime:ro
      - /run/dbus:/run/dbus:ro
    environment:
      - TZ=America/New_York
    depends_on:
      - mosquitto
      - mariadb

  # Database
  mariadb:
    container_name: mariadb
    image: mariadb:latest
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: homeassistant
      MYSQL_USER: homeassistant
      MYSQL_PASSWORD: ${DB_PASSWORD}
    volumes:
      - ./mariadb:/var/lib/mysql
    ports:
      - "3306:3306"

  # MQTT Broker
  mosquitto:
    container_name: mosquitto
    image: eclipse-mosquitto:latest
    restart: unless-stopped
    ports:
      - "1883:1883"
      - "9001:9001"
    volumes:
      - ./mosquitto/config:/mosquitto/config
      - ./mosquitto/data:/mosquitto/data
      - ./mosquitto/log:/mosquitto/log

  # Zigbee2MQTT
  zigbee2mqtt:
    container_name: zigbee2mqtt
    image: koenkk/zigbee2mqtt:latest
    restart: unless-stopped
    volumes:
      - ./zigbee2mqtt:/app/data
      - /run/udev:/run/udev:ro
    ports:
      - "8080:8080"
    environment:
      - TZ=America/New_York
    devices:
      - /dev/ttyUSB0:/dev/ttyUSB0
    depends_on:
      - mosquitto

  # Z-Wave JS UI
  zwavejs:
    container_name: zwavejs
    image: zwavejs/zwave-js-ui:latest
    restart: unless-stopped
    environment:
      - TZ=America/New_York
    devices:
      - /dev/ttyACM0:/dev/ttyACM0
    volumes:
      - ./zwavejs:/usr/src/app/store
    ports:
      - "8091:8091"
      - "3000:3000"

  # Node-RED
  nodered:
    container_name: nodered
    image: nodered/node-red:latest
    restart: unless-stopped
    ports:
      - "1880:1880"
    volumes:
      - ./nodered:/data
    environment:
      - TZ=America/New_York

  # InfluxDB
  influxdb:
    container_name: influxdb
    image: influxdb:2.7
    restart: unless-stopped
    ports:
      - "8086:8086"
    volumes:
      - ./influxdb/data:/var/lib/influxdb2
      - ./influxdb/config:/etc/influxdb2
    environment:
      - DOCKER_INFLUXDB_INIT_MODE=setup
      - DOCKER_INFLUXDB_INIT_USERNAME=admin
      - DOCKER_INFLUXDB_INIT_PASSWORD=${INFLUX_PASSWORD}
      - DOCKER_INFLUXDB_INIT_ORG=home
      - DOCKER_INFLUXDB_INIT_BUCKET=homeassistant

  # Grafana
  grafana:
    container_name: grafana
    image: grafana/grafana:latest
    restart: unless-stopped
    ports:
      - "3001:3000"
    volumes:
      - ./grafana:/var/lib/grafana
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
    depends_on:
      - influxdb

  # Caddy Reverse Proxy
  caddy:
    container_name: caddy
    image: caddy:latest
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./caddy/Caddyfile:/etc/caddy/Caddyfile
      - ./caddy/data:/data
      - ./caddy/config:/config

  # Ollama LLM
  ollama:
    container_name: ollama
    image: ollama/ollama:latest
    restart: unless-stopped
    ports:
      - "11434:11434"
    volumes:
      - ./ollama:/root/.ollama
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]

networks:
  default:
    name: homeassistant
```

## Security Hardening

```bash
#!/bin/bash
# ha-security.sh

# UFW Firewall
sudo apt install -y ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enable

# Fail2ban
sudo apt install -y fail2ban
cat | sudo tee /etc/fail2ban/jail.local << 'EOF'
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5

[sshd]
enabled = true
EOF
sudo systemctl enable fail2ban
sudo systemctl restart fail2ban

# SSH Hardening
sudo sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sudo systemctl restart sshd

# Automatic Updates
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

echo "Security hardening complete"
```

## Backup Script

```bash
#!/bin/bash
# ha-backup.sh

INSTALL_DIR="/opt/homeassistant"
BACKUP_DIR="/opt/backups"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="ha_backup_$DATE.tar.gz"

mkdir -p $BACKUP_DIR

# Stop HA for consistent backup
docker compose -f $INSTALL_DIR/docker-compose.yaml stop homeassistant

# Create backup
tar -czvf $BACKUP_DIR/$BACKUP_NAME \
    -C $INSTALL_DIR \
    homeassistant \
    mosquitto/config \
    zigbee2mqtt \
    nodered

# Restart HA
docker compose -f $INSTALL_DIR/docker-compose.yaml start homeassistant

# Keep last 7 backups
ls -t $BACKUP_DIR/*.tar.gz | tail -n +8 | xargs -r rm

echo "Backup complete: $BACKUP_DIR/$BACKUP_NAME"
```

## Systemd Service

```ini
# /etc/systemd/system/homeassistant.service
[Unit]
Description=Home Assistant Docker Stack
Requires=docker.service
After=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/homeassistant
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0

[Install]
WantedBy=multi-user.target
```

```bash
# Ena

Related in Cloud & DevOps