bootstrap.sh
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env bash
#
# bootstrap.sh - Prepare system for OnRamp (installs Docker and dependencies)
#
# This script is called automatically by `make install` on fresh systems,
# or can be run directly: ./bootstrap.sh
#
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Ensure we're in the onramp directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
log_info "OnRamp Bootstrap Script"
log_info "======================="
# Check if running as root (we need sudo, not root)
if [[ $EUID -eq 0 ]]; then
log_error "Do not run this script as root. Run as a regular user with sudo access."
exit 1
fi
# Check for sudo access
if ! sudo -v; then
log_error "This script requires sudo access."
exit 1
fi
# Keep sudo alive for the duration of the script
while true; do sudo -n true; sleep 60; kill -0 "$$" || exit; done 2>/dev/null &
# Ubuntu 25+ ships sudo-rs by default, which produces a different password prompt
# format that Ansible's sudo become plugin can't parse (ansible/ansible#85837).
# If sudo-rs is the active provider and sudo.ws (traditional sudo) is available,
# tell Ansible to use it instead.
if sudo-rs --version >/dev/null 2>&1 && command -v sudo.ws >/dev/null 2>&1; then
log_warn "Detected sudo-rs. Configuring Ansible to use sudo.ws for compatibility."
export ANSIBLE_BECOME_EXE=sudo.ws
fi
export DEBIAN_FRONTEND=noninteractive
# ============================================================================
# Step 1: System packages
# ============================================================================
log_info "Step 1: Installing system packages..."
# Update apt cache first
sudo apt update
# Detect Ubuntu using /etc/os-release (lsb_release may not exist on minimal installs)
IS_UBUNTU=false
if [[ -f /etc/os-release ]]; then
# shellcheck source=/dev/null
. /etc/os-release
[[ "$ID" == "ubuntu" ]] && IS_UBUNTU=true
fi
# On Ubuntu, add Ansible PPA for latest version (requires software-properties-common)
if [[ "$IS_UBUNTU" == "true" ]]; then
if ! apt-cache policy | grep -q "ansible/ansible"; then
log_info "Adding Ansible PPA (requires software-properties-common)..."
sudo apt install -y software-properties-common
sudo apt-add-repository ppa:ansible/ansible -y
sudo apt update
fi
fi
PACKAGES=(
git
nano
jq
python3-pip
yamllint
python3-pathspec
ansible
curl
software-properties-common
)
# Check which packages are missing
MISSING_PACKAGES=()
for pkg in "${PACKAGES[@]}"; do
if ! dpkg -s "$pkg" >/dev/null 2>&1; then
MISSING_PACKAGES+=("$pkg")
fi
done
if [[ ${#MISSING_PACKAGES[@]} -gt 0 ]]; then
log_info "Installing missing packages: ${MISSING_PACKAGES[*]}"
sudo apt install -y "${MISSING_PACKAGES[@]}"
else
log_info "All system packages already installed."
fi
# ============================================================================
# Step 2: Git configuration
# ============================================================================
log_info "Step 2: Configuring git hooks..."
if [[ ! -f .gitconfig ]]; then
git config -f .gitconfig core.hooksPath .githooks
fi
git config --local include.path "$(pwd)/.gitconfig"
log_info "Git hooks configured."
# ============================================================================
# Step 3: Ansible roles
# ============================================================================
log_info "Step 3: Installing Ansible Galaxy roles..."
mkdir -p ./ansible/roles
# Silence Ansible warnings
export ANSIBLE_LOCALHOST_WARNING=False
export ANSIBLE_INVENTORY_UNPARSED_WARNING=False
# Install roles if not already present
ROLES=(
"geerlingguy.docker"
"geerlingguy.node_exporter"
)
for role in "${ROLES[@]}"; do
role_dir="./ansible/roles/${role##*.}"
if [[ ! -d "$role_dir" ]] && [[ ! -d "./ansible/roles/$role" ]]; then
log_info "Installing Ansible role: $role"
ansible-galaxy install "$role" -p ./ansible/roles
else
log_info "Ansible role already installed: $role"
fi
done
# ============================================================================
# Step 4: Docker installation
# ============================================================================
log_info "Step 4: Installing Docker..."
DOCKER_JUST_INSTALLED=false
if command -v docker >/dev/null 2>&1; then
if docker ps >/dev/null 2>&1; then
log_info "Docker is already installed and accessible."
elif id -nG | grep -qw docker; then
# User is in docker group but can't access - likely needs re-login
log_warn "Docker is installed and you're in the docker group,"
log_warn "but the current shell session doesn't have access yet."
log_warn "Run 'newgrp docker' or log out and back in, then run 'make install' again."
exit 0
else
# Docker installed but user not in group - run ansible to add them
log_info "Docker is installed but user not in docker group. Running setup..."
ansible-playbook ansible/install-docker.yml
DOCKER_JUST_INSTALLED=true
fi
else
log_info "Installing Docker via Ansible..."
ansible-playbook ansible/install-docker.yml
DOCKER_JUST_INSTALLED=true
fi
# ============================================================================
# Step 5: Basic environment setup (without Sietch)
# ============================================================================
log_info "Step 5: Setting up basic environment..."
mkdir -p services-enabled
mkdir -p external-enabled
mkdir -p etc
mkdir -p media
mkdir -p backups
# Create services-enabled/.env from template if it doesn't exist
if [[ ! -f services-enabled/.env ]]; then
if [[ -f services-scaffold/onramp/.env.template ]]; then
log_info "Creating services-enabled/.env from template..."
cp services-scaffold/onramp/.env.template services-enabled/.env
else
log_warn "No .env template found. Creating minimal .env..."
touch services-enabled/.env
fi
fi
# Create other env files from templates if missing
for env_file in .env.nfs .env.external; do
if [[ ! -f "services-enabled/$env_file" ]] && [[ -f "services-scaffold/onramp/${env_file}.template" ]]; then
log_info "Creating services-enabled/$env_file from template..."
cp "services-scaffold/onramp/${env_file}.template" "services-enabled/$env_file"
fi
done
# Copy default traefik middleware
if [[ ! -f external-enabled/middleware.yml ]] && [[ -f external-available/middleware.yml ]]; then
log_info "Initializing external-enabled/middleware.yml..."
cp external-available/middleware.yml external-enabled/middleware.yml
fi
# ============================================================================
# Done!
# ============================================================================
echo ""
log_info "=========================================="
log_info "Bootstrap complete!"
log_info "=========================================="
# Check if we need to handle docker group membership
if [[ "$DOCKER_JUST_INSTALLED" == "true" ]]; then
if ! docker ps >/dev/null 2>&1; then
echo ""
log_warn "Docker was just installed. You need to refresh your shell session"
log_warn "for docker group membership to take effect."
echo ""
# Detect VSCode remote environment
if [[ -n "${VSCODE_IPC_HOOK_CLI:-}" ]] || [[ -n "${VSCODE_GIT_ASKPASS_NODE:-}" ]]; then
echo "VSCode Remote detected. To refresh your session:"
echo ""
echo " 1. Run: make kill-code"
echo " 2. Reconnect to this machine in VSCode"
echo " 3. Run: make continue-install"
echo ""
else
echo "Please run ONE of the following:"
echo " 1. newgrp docker # Refresh group in current shell, then: make continue-install"
echo " 2. Log out and log back in, then: make continue-install"
echo ""
fi
exit 0
fi
fi