homelab infrastructure services
1#!/bin/bash
2
3# Simplified rootless Docker installation for tinsnip
4# Eliminates complex systemd detection and environment management
5
6set -euo pipefail
7
8SERVICE_USER="${1:-}"
9
10log() {
11 echo "[Docker Install] $*"
12}
13
14error() {
15 log "ERROR: $*" >&2
16 exit 1
17}
18
19usage() {
20 echo "Usage: $0 <service_user>"
21 echo " service_user: User to install rootless Docker for (e.g., gateway-prod)"
22 exit 1
23}
24
25install_dependencies() {
26 log "Installing rootless Docker dependencies..."
27
28 sudo apt-get update -qq >/dev/null 2>&1 || error "Failed to update package lists"
29 sudo apt-get install -y uidmap dbus-user-session fuse-overlayfs slirp4netns >/dev/null 2>&1 || error "Failed to install Docker dependencies"
30
31 log "Dependencies installed"
32}
33
34install_rootless_docker() {
35 local username="$1"
36
37 log "Installing rootless Docker for user: $username"
38
39 # Check if already installed
40 if sudo -u "$username" -i bash -c "command -v docker &>/dev/null"; then
41 log "Docker already installed for $username"
42 return 0
43 fi
44
45 # Install rootless Docker
46 sudo -u "$username" -i bash << 'EOF'
47# Download and install rootless Docker
48curl -fsSL https://get.docker.com/rootless | sh
49
50# Add Docker to PATH in .bashrc (simple approach)
51if ! grep -q 'export PATH=$HOME/bin:$PATH' ~/.bashrc 2>/dev/null; then
52 echo 'export PATH=$HOME/bin:$PATH' >> ~/.bashrc
53fi
54
55# Source the new PATH
56export PATH=$HOME/bin:$PATH
57
58# Test Docker installation
59if command -v docker >/dev/null 2>&1; then
60 echo "Docker binary installed successfully"
61else
62 echo "ERROR: Docker binary not found after installation"
63 exit 1
64fi
65EOF
66
67 if [[ $? -ne 0 ]]; then
68 error "Failed to install Docker for $username"
69 fi
70
71 log "Rootless Docker installation completed for $username"
72}
73
74setup_docker_environment() {
75 local username="$1"
76
77 log "Setting up Docker environment for $username"
78
79 # Create Docker runtime directory
80 sudo -u "$username" -i bash -c 'mkdir -p "$HOME/.docker/run"'
81
82 # Create simple Docker configuration
83 sudo -u "$username" tee "/home/$username/.docker/daemon.json" > /dev/null << 'EOF'
84{
85 "log-driver": "json-file",
86 "log-opts": {
87 "max-size": "10m",
88 "max-file": "3"
89 },
90 "storage-driver": "overlay2"
91}
92EOF
93
94 # Set up environment variables in service .env file
95 local service_env_file="/mnt/$username/.env"
96
97 if [[ -f "$service_env_file" ]]; then
98 log "Adding Docker environment to service .env file"
99
100 # Remove existing Docker variables
101 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'"
102 sudo -u "$username" bash -c "mv '${service_env_file}.tmp' '$service_env_file'"
103
104 # Add Docker environment variables
105 sudo -u "$username" bash -c "cat >> '$service_env_file' << 'DOCKER_EOF'
106
107# Docker rootless environment
108XDG_RUNTIME_DIR=/home/$username/.docker/run
109DOCKER_HOST=unix:///home/$username/.docker/run/docker.sock
110PATH=/home/$username/bin:\$PATH
111DOCKER_EOF"
112
113 log "Docker environment added to $service_env_file"
114 else
115 log "WARNING: Service .env file not found at $service_env_file"
116 fi
117}
118
119start_docker_daemon() {
120 local username="$1"
121
122 log "Starting Docker daemon for $username"
123
124 sudo -u "$username" -i bash << 'EOF'
125# Set up environment
126export XDG_RUNTIME_DIR="$HOME/.docker/run"
127export DOCKER_HOST="unix://$XDG_RUNTIME_DIR/docker.sock"
128export PATH="$HOME/bin:$PATH"
129
130# Kill any existing dockerd processes
131pkill -f dockerd-rootless || true
132sleep 2
133
134# Start Docker daemon
135nohup dockerd-rootless.sh > "$HOME/.docker/docker.log" 2>&1 &
136sleep 5
137
138# Wait for socket
139for i in {1..10}; do
140 if [[ -S "$XDG_RUNTIME_DIR/docker.sock" ]]; then
141 echo "Docker socket created successfully"
142 break
143 fi
144 echo "Waiting for Docker socket... ($i/10)"
145 sleep 2
146done
147
148# Test Docker
149if docker version >/dev/null 2>&1; then
150 echo "Docker daemon started successfully"
151else
152 echo "ERROR: Docker daemon failed to start properly"
153 cat "$HOME/.docker/docker.log" 2>/dev/null || echo "No log file found"
154 exit 1
155fi
156EOF
157
158 if [[ $? -ne 0 ]]; then
159 error "Failed to start Docker daemon for $username"
160 fi
161
162 log "Docker daemon started successfully"
163}
164
165verify_installation() {
166 local username="$1"
167
168 log "Verifying Docker installation for $username..."
169
170 local service_env_file="/mnt/$username/.env"
171
172 if sudo -u "$username" bash -c "source '$service_env_file' 2>/dev/null && docker version >/dev/null 2>&1"; then
173 log "Docker verification successful!"
174 local docker_version
175 docker_version=$(sudo -u "$username" bash -c "source '$service_env_file' 2>/dev/null && docker --version")
176 log "Installed: $docker_version"
177 else
178 error "Docker verification failed for $username"
179 fi
180}
181
182main() {
183 # Validate parameters
184 if [[ -z "$SERVICE_USER" ]]; then
185 usage
186 fi
187
188 # Check if user exists
189 if ! id "$SERVICE_USER" &>/dev/null; then
190 error "User $SERVICE_USER does not exist. Create the user first."
191 fi
192
193 log "Installing rootless Docker for service user: $SERVICE_USER"
194
195 # Install dependencies
196 install_dependencies
197
198 # Install rootless Docker
199 install_rootless_docker "$SERVICE_USER"
200
201 # Setup Docker environment
202 setup_docker_environment "$SERVICE_USER"
203
204 # Start Docker daemon
205 start_docker_daemon "$SERVICE_USER"
206
207 # Verify installation
208 verify_installation "$SERVICE_USER"
209
210 log ""
211 log "Rootless Docker installation complete!"
212 log "User: $SERVICE_USER"
213 log "To test: sudo -u $SERVICE_USER bash -c 'source /mnt/$SERVICE_USER/.env && docker run hello-world'"
214}
215
216main "$@"