homelab infrastructure services
1#!/bin/bash
2
3set -euo pipefail
4
5log() {
6 echo "[Boot Config] $*"
7}
8
9error() {
10 log "ERROR: $*" >&2
11 exit 1
12}
13
14get_nas_mount() {
15 if [[ -f ${DYNAMICALSYSTEM_TEMP_DIR:-/tmp/dynamicalsystem}/nas_mount.env ]]; then
16 source ${DYNAMICALSYSTEM_TEMP_DIR:-/tmp/dynamicalsystem}/nas_mount.env
17 echo "${NAS_MOUNT_POINT}"
18 else
19 read -p "Enter NAS mount point: " mount_point
20 echo "$mount_point"
21 fi
22}
23
24create_env_loader_service() {
25 local env_file="$1"
26 local service_file="/etc/systemd/system/machine-env-loader.service"
27
28 log "Creating systemd service for environment loader..."
29
30 sudo tee "$service_file" > /dev/null << EOF
31[Unit]
32Description=Load machine environment variables
33After=network.target remote-fs.target
34Wants=network-online.target
35
36[Service]
37Type=oneshot
38RemainAfterExit=yes
39ExecStart=/bin/bash -c 'if [[ -f "$env_file" ]]; then source "$env_file" && export -p > /etc/environment.d/99-machine.conf; fi'
40StandardOutput=journal
41
42[Install]
43WantedBy=multi-user.target
44EOF
45
46 sudo mkdir -p /etc/environment.d
47 sudo systemctl daemon-reload
48 sudo systemctl enable machine-env-loader.service
49
50 log "Environment loader service created and enabled"
51}
52
53create_docker_user_service() {
54 local user_service_dir="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user"
55
56 log "Setting up Docker user service for auto-start..."
57
58 mkdir -p "$user_service_dir"
59
60 cat > "$user_service_dir/docker-rootless.service" << 'EOF'
61[Unit]
62Description=Docker Application Container Engine (Rootless)
63Documentation=https://docs.docker.com/go/rootless/
64
65[Service]
66Environment="PATH=/usr/local/bin:/usr/bin:/bin"
67ExecStart=/usr/bin/dockerd-rootless.sh
68ExecReload=/bin/kill -s HUP $MAINPID
69TimeoutSec=0
70RestartSec=2
71Restart=always
72StartLimitBurst=3
73StartLimitInterval=60s
74LimitNOFILE=infinity
75LimitNPROC=infinity
76LimitCORE=infinity
77TasksMax=infinity
78Delegate=yes
79Type=simple
80KillMode=mixed
81
82[Install]
83WantedBy=default.target
84EOF
85
86 systemctl --user daemon-reload
87 systemctl --user enable docker-rootless.service
88
89 loginctl enable-linger "$(whoami)"
90
91 log "Docker rootless service configured for auto-start"
92}
93
94configure_mount_verification() {
95 local mount_point="$1"
96 local service_file="/etc/systemd/system/verify-nas-mount.service"
97
98 log "Creating NAS mount verification service..."
99
100 sudo tee "$service_file" > /dev/null << EOF
101[Unit]
102Description=Verify NAS mount is available
103After=network-online.target remote-fs.target
104Wants=network-online.target
105Before=machine-env-loader.service
106
107[Service]
108Type=oneshot
109RemainAfterExit=yes
110ExecStart=/bin/bash -c 'for i in {1..30}; do if mountpoint -q "$mount_point"; then exit 0; fi; sleep 2; done; exit 1'
111Restart=on-failure
112RestartSec=10
113StandardOutput=journal
114
115[Install]
116WantedBy=multi-user.target
117EOF
118
119 sudo systemctl daemon-reload
120 sudo systemctl enable verify-nas-mount.service
121
122 log "NAS mount verification service created and enabled"
123}
124
125create_startup_script() {
126 local startup_script="/usr/local/bin/machine-startup"
127
128 log "Creating machine startup script..."
129
130 sudo tee "$startup_script" > /dev/null << 'EOF'
131#!/bin/bash
132# Machine startup script
133# This script runs at boot to ensure all services are properly initialized
134
135logger -t machine-startup "Starting machine initialization..."
136
137# Wait for network
138for i in {1..30}; do
139 if ping -c 1 -W 1 8.8.8.8 &> /dev/null; then
140 logger -t machine-startup "Network is available"
141 break
142 fi
143 sleep 1
144done
145
146# Verify mounts
147if ! systemctl is-active --quiet remote-fs.target; then
148 logger -t machine-startup "Waiting for remote filesystems..."
149 systemctl start remote-fs.target
150fi
151
152# Start user services
153for user in $(loginctl list-users --no-legend | awk '{print $2}'); do
154 if [[ -f "/home/$user/.config/systemd/user/docker-rootless.service" ]]; then
155 logger -t machine-startup "Starting Docker for user $user"
156 sudo -u "$user" XDG_RUNTIME_DIR="/run/user/$(id -u "$user")" systemctl --user start docker-rootless.service
157 fi
158done
159
160logger -t machine-startup "Machine initialization completed"
161EOF
162
163 sudo chmod +x "$startup_script"
164
165 local service_file="/etc/systemd/system/machine-startup.service"
166 sudo tee "$service_file" > /dev/null << EOF
167[Unit]
168Description=Machine startup initialization
169After=network-online.target remote-fs.target
170Wants=network-online.target
171
172[Service]
173Type=oneshot
174ExecStart=$startup_script
175RemainAfterExit=yes
176StandardOutput=journal
177
178[Install]
179WantedBy=multi-user.target
180EOF
181
182 sudo systemctl daemon-reload
183 sudo systemctl enable machine-startup.service
184
185 log "Machine startup script created and enabled"
186}
187
188main() {
189 log "Starting boot configuration..."
190
191 nas_mount=$(get_nas_mount)
192
193 if [[ ! -d "$nas_mount" ]]; then
194 error "NAS mount point $nas_mount does not exist"
195 fi
196
197 env_file="$nas_mount/.env"
198
199 create_env_loader_service "$env_file"
200 create_docker_user_service
201 configure_mount_verification "$nas_mount"
202 create_startup_script
203
204 log "Boot configuration completed!"
205 log "Services will start automatically on next boot"
206
207 echo
208 log "Created services:"
209 log " - machine-env-loader.service: Loads environment variables"
210 log " - verify-nas-mount.service: Ensures NAS is mounted"
211 log " - docker-rootless.service: Starts Docker in user context"
212 log " - machine-startup.service: Handles boot initialization"
213}
214
215main "$@"