#!/usr/bin/env bash # install.sh — one-time setup for a fresh Raspberry Pi. # # Run this once after cloning the repo: # cd ~/Hostityourself && ./infra/install.sh # # What it does: # 1. Installs system packages (podman, aardvark-dns, sqlite3, git, uidmap) # 2. Installs podman-compose (via pip, into ~/.local/bin) # 3. Installs rclone (for off-site backups — optional) # 4. Creates .env from the template and prompts for required values # 5. Runs infra/start.sh to build and launch the stack # # Safe to re-run — all steps are idempotent. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" log() { echo; echo "▶ $*"; } info() { echo " $*"; } ok() { echo " ✓ $*"; } echo "╔══════════════════════════════════════════╗" echo "║ HostItYourself — installer ║" echo "╚══════════════════════════════════════════╝" # ── 1. System packages ───────────────────────────────────────────────────────── log "Installing system packages…" sudo apt-get update -qq sudo apt-get install -y \ podman \ aardvark-dns \ sqlite3 \ git \ uidmap \ python3-pip \ python3-venv \ curl ok "System packages installed." # ── 2. podman-compose ────────────────────────────────────────────────────────── log "Checking podman-compose…" if command -v podman-compose &>/dev/null; then ok "podman-compose already installed ($(podman-compose --version 2>&1 | head -1))." else info "Installing podman-compose via pip…" pip3 install --user podman-compose ok "podman-compose installed to ~/.local/bin" fi # Ensure ~/.local/bin is in PATH for this session and future logins. if ! echo "$PATH" | grep -q "$HOME/.local/bin"; then export PATH="$HOME/.local/bin:$PATH" fi PROFILE="$HOME/.bashrc" if ! grep -q '\.local/bin' "$PROFILE" 2>/dev/null; then echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$PROFILE" info "Added ~/.local/bin to PATH in $PROFILE" fi # ── 3. rclone (optional) ─────────────────────────────────────────────────────── log "rclone (used for off-site backups)…" if command -v rclone &>/dev/null; then ok "rclone already installed ($(rclone --version 2>&1 | head -1))." else read -r -p " Install rclone? [y/N] " _RCLONE if [[ "${_RCLONE,,}" == "y" ]]; then curl -fsSL https://rclone.org/install.sh | sudo bash ok "rclone installed." info "Configure a remote later with: rclone config" info "Then set HIY_BACKUP_REMOTE in .env" else info "Skipped. Install later with: curl https://rclone.org/install.sh | sudo bash" fi fi # ── 4. .env setup ────────────────────────────────────────────────────────────── log "Setting up .env…" ENV_FILE="$REPO_ROOT/.env" ENV_EXAMPLE="$SCRIPT_DIR/.env.example" if [ -f "$ENV_FILE" ]; then ok ".env already exists — skipping (edit manually if needed)." else cp "$ENV_EXAMPLE" "$ENV_FILE" info "Created .env from template. Filling in required values…" echo # Helper: prompt for a value and write it into .env. set_env() { local key="$1" prompt="$2" default="$3" secret="${4:-}" local current current=$(grep "^${key}=" "$ENV_FILE" | cut -d= -f2- || echo "") if [ -z "$current" ] || [ "$current" = "changeme" ] || [ "$current" = "" ]; then if [ -n "$secret" ]; then read -r -s -p " ${prompt} [${default}]: " _VAL; echo else read -r -p " ${prompt} [${default}]: " _VAL fi _VAL="${_VAL:-$default}" # Replace the line in .env (works on both macOS and Linux). sed -i "s|^${key}=.*|${key}=${_VAL}|" "$ENV_FILE" fi } set_env "DOMAIN_SUFFIX" "Your domain (e.g. example.com)" "yourdomain.com" set_env "ACME_EMAIL" "Email for Let's Encrypt notices" "" set_env "HIY_ADMIN_USER" "Dashboard admin username" "admin" set_env "HIY_ADMIN_PASS" "Dashboard admin password" "$(openssl rand -hex 12)" "secret" set_env "POSTGRES_PASSWORD" "Postgres admin password" "$(openssl rand -hex 16)" "secret" set_env "FORGEJO_DB_PASSWORD" "Forgejo DB password" "$(openssl rand -hex 16)" "secret" set_env "FORGEJO_DOMAIN" "Forgejo domain (e.g. git.example.com)" "git.yourdomain.com" echo ok ".env written to $ENV_FILE" info "Review it with: cat $ENV_FILE" fi # ── 5. Git remote check ──────────────────────────────────────────────────────── log "Checking git remote…" cd "$REPO_ROOT" REMOTE_URL=$(git remote get-url origin 2>/dev/null || echo "") if [ -n "$REMOTE_URL" ]; then ok "Git remote: $REMOTE_URL" else info "No git remote configured — auto-update will not work." info "Set one with: git remote add origin " fi # Ensure the tracking branch is set so auto-update.sh can compare commits. BRANCH=$(git rev-parse --abbrev-ref HEAD) if ! git rev-parse --abbrev-ref --symbolic-full-name '@{u}' &>/dev/null; then info "Setting upstream tracking branch…" git branch --set-upstream-to="origin/$BRANCH" "$BRANCH" 2>/dev/null || true fi # ── 6. Launch the stack ──────────────────────────────────────────────────────── log "Running start.sh to build and launch the stack…" echo exec "$SCRIPT_DIR/start.sh"