#!/bin/bash # Simplified rootless Docker installation for tinsnip # Eliminates complex systemd detection and environment management set -euo pipefail SERVICE_USER="${1:-}" log() { echo "[Docker Install] $*" } error() { log "ERROR: $*" >&2 exit 1 } usage() { echo "Usage: $0 " echo " service_user: User to install rootless Docker for (e.g., gateway-prod)" exit 1 } install_dependencies() { log "Installing rootless Docker dependencies..." sudo apt-get update -qq >/dev/null 2>&1 || error "Failed to update package lists" sudo apt-get install -y uidmap dbus-user-session fuse-overlayfs slirp4netns >/dev/null 2>&1 || error "Failed to install Docker dependencies" log "Dependencies installed" } install_rootless_docker() { local username="$1" log "Installing rootless Docker for user: $username" # Check if already installed if sudo -u "$username" -i bash -c "command -v docker &>/dev/null"; then log "Docker already installed for $username" return 0 fi # Install rootless Docker sudo -u "$username" -i bash << 'EOF' # Download and install rootless Docker curl -fsSL https://get.docker.com/rootless | sh # Add Docker to PATH in .bashrc (simple approach) if ! grep -q 'export PATH=$HOME/bin:$PATH' ~/.bashrc 2>/dev/null; then echo 'export PATH=$HOME/bin:$PATH' >> ~/.bashrc fi # Source the new PATH export PATH=$HOME/bin:$PATH # Test Docker installation if command -v docker >/dev/null 2>&1; then echo "Docker binary installed successfully" else echo "ERROR: Docker binary not found after installation" exit 1 fi EOF if [[ $? -ne 0 ]]; then error "Failed to install Docker for $username" fi log "Rootless Docker installation completed for $username" } setup_docker_environment() { local username="$1" log "Setting up Docker environment for $username" # Create Docker runtime directory sudo -u "$username" -i bash -c 'mkdir -p "$HOME/.docker/run"' # Create simple Docker configuration sudo -u "$username" tee "/home/$username/.docker/daemon.json" > /dev/null << 'EOF' { "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" }, "storage-driver": "overlay2" } EOF # Set up environment variables in service .env file local service_env_file="/mnt/$username/.env" if [[ -f "$service_env_file" ]]; then log "Adding Docker environment to service .env file" # Remove existing Docker variables sudo -u "$username" bash -c "grep -v '^XDG_RUNTIME_DIR=\|^DOCKER_HOST=\|^PATH=' '$service_env_file' > '${service_env_file}.tmp' 2>/dev/null || touch '${service_env_file}.tmp'" sudo -u "$username" bash -c "mv '${service_env_file}.tmp' '$service_env_file'" # Add Docker environment variables sudo -u "$username" bash -c "cat >> '$service_env_file' << 'DOCKER_EOF' # Docker rootless environment XDG_RUNTIME_DIR=/home/$username/.docker/run DOCKER_HOST=unix:///home/$username/.docker/run/docker.sock PATH=/home/$username/bin:\$PATH DOCKER_EOF" log "Docker environment added to $service_env_file" else log "WARNING: Service .env file not found at $service_env_file" fi } start_docker_daemon() { local username="$1" log "Starting Docker daemon for $username" sudo -u "$username" -i bash << 'EOF' # Set up environment export XDG_RUNTIME_DIR="$HOME/.docker/run" export DOCKER_HOST="unix://$XDG_RUNTIME_DIR/docker.sock" export PATH="$HOME/bin:$PATH" # Kill any existing dockerd processes pkill -f dockerd-rootless || true sleep 2 # Start Docker daemon nohup dockerd-rootless.sh > "$HOME/.docker/docker.log" 2>&1 & sleep 5 # Wait for socket for i in {1..10}; do if [[ -S "$XDG_RUNTIME_DIR/docker.sock" ]]; then echo "Docker socket created successfully" break fi echo "Waiting for Docker socket... ($i/10)" sleep 2 done # Test Docker if docker version >/dev/null 2>&1; then echo "Docker daemon started successfully" else echo "ERROR: Docker daemon failed to start properly" cat "$HOME/.docker/docker.log" 2>/dev/null || echo "No log file found" exit 1 fi EOF if [[ $? -ne 0 ]]; then error "Failed to start Docker daemon for $username" fi log "Docker daemon started successfully" } verify_installation() { local username="$1" log "Verifying Docker installation for $username..." local service_env_file="/mnt/$username/.env" if sudo -u "$username" bash -c "source '$service_env_file' 2>/dev/null && docker version >/dev/null 2>&1"; then log "Docker verification successful!" local docker_version docker_version=$(sudo -u "$username" bash -c "source '$service_env_file' 2>/dev/null && docker --version") log "Installed: $docker_version" else error "Docker verification failed for $username" fi } main() { # Validate parameters if [[ -z "$SERVICE_USER" ]]; then usage fi # Check if user exists if ! id "$SERVICE_USER" &>/dev/null; then error "User $SERVICE_USER does not exist. Create the user first." fi log "Installing rootless Docker for service user: $SERVICE_USER" # Install dependencies install_dependencies # Install rootless Docker install_rootless_docker "$SERVICE_USER" # Setup Docker environment setup_docker_environment "$SERVICE_USER" # Start Docker daemon start_docker_daemon "$SERVICE_USER" # Verify installation verify_installation "$SERVICE_USER" log "" log "Rootless Docker installation complete!" log "User: $SERVICE_USER" log "To test: sudo -u $SERVICE_USER bash -c 'source /mnt/$SERVICE_USER/.env && docker run hello-world'" } main "$@"