#!/bin/bash set -euo pipefail log() { echo "[Boot Config] $*" } error() { log "ERROR: $*" >&2 exit 1 } get_nas_mount() { if [[ -f ${DYNAMICALSYSTEM_TEMP_DIR:-/tmp/dynamicalsystem}/nas_mount.env ]]; then source ${DYNAMICALSYSTEM_TEMP_DIR:-/tmp/dynamicalsystem}/nas_mount.env echo "${NAS_MOUNT_POINT}" else read -p "Enter NAS mount point: " mount_point echo "$mount_point" fi } create_env_loader_service() { local env_file="$1" local service_file="/etc/systemd/system/machine-env-loader.service" log "Creating systemd service for environment loader..." sudo tee "$service_file" > /dev/null << EOF [Unit] Description=Load machine environment variables After=network.target remote-fs.target Wants=network-online.target [Service] Type=oneshot RemainAfterExit=yes ExecStart=/bin/bash -c 'if [[ -f "$env_file" ]]; then source "$env_file" && export -p > /etc/environment.d/99-machine.conf; fi' StandardOutput=journal [Install] WantedBy=multi-user.target EOF sudo mkdir -p /etc/environment.d sudo systemctl daemon-reload sudo systemctl enable machine-env-loader.service log "Environment loader service created and enabled" } create_docker_user_service() { local user_service_dir="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user" log "Setting up Docker user service for auto-start..." mkdir -p "$user_service_dir" cat > "$user_service_dir/docker-rootless.service" << 'EOF' [Unit] Description=Docker Application Container Engine (Rootless) Documentation=https://docs.docker.com/go/rootless/ [Service] Environment="PATH=/usr/local/bin:/usr/bin:/bin" ExecStart=/usr/bin/dockerd-rootless.sh ExecReload=/bin/kill -s HUP $MAINPID TimeoutSec=0 RestartSec=2 Restart=always StartLimitBurst=3 StartLimitInterval=60s LimitNOFILE=infinity LimitNPROC=infinity LimitCORE=infinity TasksMax=infinity Delegate=yes Type=simple KillMode=mixed [Install] WantedBy=default.target EOF systemctl --user daemon-reload systemctl --user enable docker-rootless.service loginctl enable-linger "$(whoami)" log "Docker rootless service configured for auto-start" } configure_mount_verification() { local mount_point="$1" local service_file="/etc/systemd/system/verify-nas-mount.service" log "Creating NAS mount verification service..." sudo tee "$service_file" > /dev/null << EOF [Unit] Description=Verify NAS mount is available After=network-online.target remote-fs.target Wants=network-online.target Before=machine-env-loader.service [Service] Type=oneshot RemainAfterExit=yes ExecStart=/bin/bash -c 'for i in {1..30}; do if mountpoint -q "$mount_point"; then exit 0; fi; sleep 2; done; exit 1' Restart=on-failure RestartSec=10 StandardOutput=journal [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable verify-nas-mount.service log "NAS mount verification service created and enabled" } create_startup_script() { local startup_script="/usr/local/bin/machine-startup" log "Creating machine startup script..." sudo tee "$startup_script" > /dev/null << 'EOF' #!/bin/bash # Machine startup script # This script runs at boot to ensure all services are properly initialized logger -t machine-startup "Starting machine initialization..." # Wait for network for i in {1..30}; do if ping -c 1 -W 1 8.8.8.8 &> /dev/null; then logger -t machine-startup "Network is available" break fi sleep 1 done # Verify mounts if ! systemctl is-active --quiet remote-fs.target; then logger -t machine-startup "Waiting for remote filesystems..." systemctl start remote-fs.target fi # Start user services for user in $(loginctl list-users --no-legend | awk '{print $2}'); do if [[ -f "/home/$user/.config/systemd/user/docker-rootless.service" ]]; then logger -t machine-startup "Starting Docker for user $user" sudo -u "$user" XDG_RUNTIME_DIR="/run/user/$(id -u "$user")" systemctl --user start docker-rootless.service fi done logger -t machine-startup "Machine initialization completed" EOF sudo chmod +x "$startup_script" local service_file="/etc/systemd/system/machine-startup.service" sudo tee "$service_file" > /dev/null << EOF [Unit] Description=Machine startup initialization After=network-online.target remote-fs.target Wants=network-online.target [Service] Type=oneshot ExecStart=$startup_script RemainAfterExit=yes StandardOutput=journal [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable machine-startup.service log "Machine startup script created and enabled" } main() { log "Starting boot configuration..." nas_mount=$(get_nas_mount) if [[ ! -d "$nas_mount" ]]; then error "NAS mount point $nas_mount does not exist" fi env_file="$nas_mount/.env" create_env_loader_service "$env_file" create_docker_user_service configure_mount_verification "$nas_mount" create_startup_script log "Boot configuration completed!" log "Services will start automatically on next boot" echo log "Created services:" log " - machine-env-loader.service: Loads environment variables" log " - verify-nas-mount.service: Ensures NAS is mounted" log " - docker-rootless.service: Starts Docker in user context" log " - machine-startup.service: Handles boot initialization" } main "$@"