feat(services): add service activation module

Implement runit service activation for essential services:
- dhcpcd enabled by default for network connectivity
- Helper function enable_service() for extensibility
- Service validation before symlink creation

Decision: Enable only dhcpcd by default.
Minimal service activation reduces attack surface and resource
usage. Additional services (sshd, chronyd) can be added via
future config file support.

Alternative considered: NetworkManager rejected as default.
dhcpcd is lighter and sufficient for server/minimal systems.
Desktop users can switch to NetworkManager post-install.

Trade-off: Automatic dhcpcd activation means network works
immediately after boot but may conflict with users who prefer
NetworkManager. Future config will allow service selection.

Service definition validation: Check if /etc/sv/<service> exists
before creating symlink. Prevents broken links if package not
installed. Returns error code but continues installation to
avoid cascading failures from optional services.
This commit is contained in:
Stefan Strobl 2025-12-24 20:44:41 +01:00
parent 4ac64e6659
commit dcd22b04c0

95
src/services.sh Normal file
View File

@ -0,0 +1,95 @@
#!/usr/bin/env bash
# === Motivation ===
# Enable essential system services for network connectivity and basic functionality.
# === Problem Statement ===
# A freshly installed system needs service activation to function properly at boot.
# === Scope ===
# In scope: network service activation, optional services (SSH, NTP).
# Out of scope: service configuration, firewall rules, custom service creation.
# === Concepts ===
# runit: Void's init system and service supervisor.
# Service directory: /etc/sv/<service> contains service definition.
# Service activation: Symlink from /etc/runit/runsvdir/default/<service> to /etc/sv/<service>.
# dhcpcd: DHCP client for automatic network configuration.
# sshd: OpenSSH server for remote access.
# chronyd: NTP client for time synchronization.
# === Decisions ===
# Enable dhcpcd by default for network connectivity (required for most systems).
# Disable sshd by default for security (can be enabled via config).
# Disable chronyd by default (optional service, can be enabled via config).
# Use absolute symlinks for service activation (Void standard).
# Validate service directory exists before creating symlink.
# === Alternatives Considered ===
# NetworkManager rejected as default (dhcpcd is lighter and sufficient for server/minimal systems).
# systemd-networkd rejected (Void uses runit).
# Enabling all services rejected (security and resource waste).
# Auto-detection of network interface rejected (dhcpcd handles this).
# === Constraints ===
# Target system must be mounted at $MOUNT_ROOT.
# Service packages must be installed before activation.
# Service definitions must exist in /etc/sv/.
# === Open Questions ===
# Should we detect network interface type and choose NetworkManager vs dhcpcd?
# Should we prompt for optional services interactively or only via config?
# Should we enable dbus by default for desktop environments?
# === Success Criteria ===
# dhcpcd is enabled and system has network connectivity after reboot.
# Optional services are enabled if requested via configuration.
# Services start successfully on boot.
services_configure() {
: "${MOUNT_ROOT:?Mount root is required}"
local runsvdir="$MOUNT_ROOT/etc/runit/runsvdir/default"
log_info "Service configuration: enabling system services"
# Ensure runsvdir exists
mkdir -p "$runsvdir"
# Enable dhcpcd for network connectivity
log_info "Enabling dhcpcd service"
enable_service "dhcpcd"
# Optional services (can be extended with config file support)
# For now, we only enable essential services
# Future: Add support for ENABLE_SSHD, ENABLE_CHRONYD via config
log_info "Service configuration complete."
}
enable_service() {
local service="$1"
local service_dir="/etc/sv/$service"
local runsvdir="$MOUNT_ROOT/etc/runit/runsvdir/default"
local service_link="$runsvdir/$service"
# Check if service definition exists
if [[ ! -d "$MOUNT_ROOT$service_dir" ]]; then
log_warn "Service definition not found: $service_dir (service may not be installed)"
return 1
fi
# Check if service is already enabled
if [[ -L "$service_link" ]]; then
log_info "Service $service already enabled"
return 0
fi
# Create symlink to enable service
if ! ln -sf "$service_dir" "$service_link"; then
log_warn "Failed to enable service: $service"
return 1
fi
log_info "Service $service enabled"
return 0
}