#!/bin/bash # Prepare this machine to serve as the Omarchy repository host. # # The host receives uploads, promotes packages into the published tree, and # syncs that tree to the mirror. Everything Arch-specific — makepkg, repo-add, # package signing — happens inside containers, so the host itself needs very # little and does not need to be Arch. The production host is Ubuntu. # # Run this on the host itself: # ssh root@ 'cd /root/omarchy-pkgs && bin/setup' # # It is idempotent — run it again after adding a dependency. set -e BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..") source "$BUILD_ROOT/helpers/message-helpers.sh" CHECK_ONLY=false SKIP_TIMERS=false STATE_DIR="${OMARCHY_STATE_DIR:-/root/.state}" CREDENTIALS="/root/.omarchy/build-credentials" print_header "Omarchy Repository Host Setup" while [[ $# -gt 0 ]]; do case $1 in --check) CHECK_ONLY=true shift ;; --skip-timers) SKIP_TIMERS=true shift ;; -h | --help) echo "Usage: $0 [OPTIONS]" echo "" echo "Install and enable everything the repository host needs." echo "Works on Debian/Ubuntu (apt) and Arch (pacman)." echo "" echo "Options:" echo " --check Report what is missing, change nothing" echo " --skip-timers Do not install or enable the release timers" echo " -h, --help Show this help message" exit 0 ;; *) print_error "Unknown option: $1" exit 1 ;; esac done # --- distribution ------------------------------------------------------------ # Package names differ where it matters: bsdtar is libarchive-tools on Debian # and libarchive on Arch, and Docker is docker.io rather than docker. if command -v apt-get >/dev/null 2>&1; then DISTRO="debian" PKG_BSDTAR="libarchive-tools" PKG_DOCKER="docker.io" elif command -v pacman >/dev/null 2>&1; then DISTRO="arch" PKG_BSDTAR="libarchive" PKG_DOCKER="docker" else print_error "Unsupported distribution — need apt-get or pacman" exit 1 fi print_info "Distribution: $DISTRO" if [[ "$CHECK_ONLY" != true && $EUID -ne 0 ]]; then print_error "Run as root (installing packages and systemd units)" exit 1 fi # Docker and the release timers are both systemd units. Say so plainly rather # than failing later on a missing command — a container is the usual way to end # up here, and it cannot be a repository host. if [[ "$CHECK_ONLY" != true ]] && ! command -v systemctl >/dev/null 2>&1; then print_error "systemctl not found — the repository host must run systemd" echo "" echo "Docker and the release timers are systemd units. This looks like a" echo "container; run setup on the host itself." exit 1 fi install_packages() { case "$DISTRO" in debian) apt-get update -qq DEBIAN_FRONTEND=noninteractive apt-get install -y "$@" ;; arch) pacman -S --needed --noconfirm "$@" ;; esac } # --- dependencies ------------------------------------------------------------ # Only what the host runs directly. Signing and repo-add happen in containers, # so gnupg and the Arch build tools are deliberately absent from this list. REQUIREMENTS=( "bsdtar:$PKG_BSDTAR" # reads repo databases and .PKGINFO out of packages "git:git" # pulls this repository "jq:jq" # package metadata in .omarchy/package.json "rsync:rsync" # receives uploads from bin/repo push "rclone:rclone" # publishes to the mirror ) print_info "Checking dependencies..." MISSING_PACKAGES=() for requirement in "${REQUIREMENTS[@]}"; do cmd="${requirement%%:*}" pkg="${requirement#*:}" if command -v "$cmd" >/dev/null 2>&1; then print_step "$cmd" else print_warning "$cmd missing (provided by $pkg)" MISSING_PACKAGES+=("$pkg") fi done echo "" if [[ ${#MISSING_PACKAGES[@]} -gt 0 ]]; then if [[ "$CHECK_ONLY" == true ]]; then print_warning "Would install: ${MISSING_PACKAGES[*]}" else print_info "Installing: ${MISSING_PACKAGES[*]}" install_packages "${MISSING_PACKAGES[@]}" print_success "Dependencies installed" fi else print_success "All dependencies present" fi echo "" # --- docker ------------------------------------------------------------------ # Docker is left alone when it already works. A host may well be running a # version from Docker's own repository rather than the distribution's, and # replacing that underneath a working builder would be a poor trade for # tidiness. print_info "Checking Docker..." if command -v docker >/dev/null 2>&1; then print_step "docker present: $(docker --version 2>/dev/null | head -1)" if docker info >/dev/null 2>&1; then print_success "Docker is installed and running — leaving it alone" elif [[ "$CHECK_ONLY" == true ]]; then print_warning "Docker is installed but not running; would start it" else print_info "Docker is installed but not running — starting it" systemctl enable --now docker.service if docker info >/dev/null 2>&1; then print_success "Docker started" else print_error "Docker is installed but still not responding" echo " Check 'systemctl status docker' — builds cannot run without it." exit 1 fi fi elif [[ "$CHECK_ONLY" == true ]]; then print_warning "Would install $PKG_DOCKER and enable it" else print_info "Installing $PKG_DOCKER..." install_packages "$PKG_DOCKER" systemctl enable --now docker.service if docker info >/dev/null 2>&1; then print_success "Docker installed and running" else print_error "Docker installed but not responding" echo " Check 'systemctl status docker' — builds cannot run without it." exit 1 fi fi echo "" # --- state directory --------------------------------------------------------- if [[ -d "$STATE_DIR" ]]; then print_success "State directory present: $STATE_DIR" elif [[ "$CHECK_ONLY" == true ]]; then print_warning "Would create $STATE_DIR" else mkdir -p "$STATE_DIR" print_success "Created $STATE_DIR" fi echo "" # --- release timers ---------------------------------------------------------- TIMERS=(omarchy-check-versions omarchy-auto-release-edge omarchy-auto-release-stable) if [[ "$SKIP_TIMERS" == true ]]; then print_info "Skipping release timers (--skip-timers)" elif [[ "$CHECK_ONLY" == true ]]; then for timer in "${TIMERS[@]}"; do if systemctl is-enabled "$timer.timer" >/dev/null 2>&1; then print_success "$timer.timer is enabled" else print_warning "$timer.timer would be enabled" fi done else print_info "Installing release timers..." cp "$BUILD_ROOT"/systemd/*.service "$BUILD_ROOT"/systemd/*.timer /etc/systemd/system/ systemctl daemon-reload for timer in "${TIMERS[@]}"; do systemctl enable --now "$timer.timer" print_step "$timer.timer" done print_success "Release timers enabled" fi echo "" # --- credentials ------------------------------------------------------------- # These hold secrets, so setup reports on them rather than creating them. print_info "Checking credentials..." if [[ -f "$CREDENTIALS" ]]; then print_success "Signing credentials present: $CREDENTIALS" else print_warning "Missing $CREDENTIALS" echo " Must export GPG_PRIVATE_KEY and GPG_PASSPHRASE; the release" echo " services source it before signing." fi if rclone listremotes 2>/dev/null | grep -q '^pkgs.omarchy.org:'; then print_success "rclone remote 'pkgs.omarchy.org' configured" else print_warning "rclone remote 'pkgs.omarchy.org' not configured" echo " bin/repo sync publishes there; configure it with 'rclone config'." fi echo "" if [[ "$CHECK_ONLY" == true ]]; then print_info "Check complete — nothing was changed" else print_success "Repository host ready" fi