homelab infrastructure services
1#!/bin/bash
2
3# Deploy a tinsnip service
4
5set -euo pipefail
6
7SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8SERVICE_DIR="$(dirname "$SCRIPT_DIR")/service"
9
10# Use namespace from environment (defaults to dynamicalsystem if not set)
11TIN_NAMESPACE="${TIN_NAMESPACE:-dynamicalsystem}"
12
13log() {
14 echo "[Deploy] $*"
15}
16
17error() {
18 log "ERROR: $*" >&2
19 exit 1
20}
21
22deploy_service() {
23 local service_name="$1"
24 local service_dir="$SERVICE_DIR/$service_name"
25
26 if [[ ! -d "$service_dir" ]]; then
27 error "Service directory not found: $service_dir"
28 fi
29
30 log "Deploying service: $service_name"
31
32 # Copy service files to tinsnip user's home
33 local target_dir="/home/tinsnip/service/$service_name"
34 sudo -u tinsnip mkdir -p "$target_dir"
35
36 # Copy all files
37 sudo cp -r "$service_dir"/* "$target_dir/"
38 sudo chown -R tinsnip:tinsnip "$target_dir"
39
40 # Make scripts executable
41 sudo find "$target_dir" -name "*.sh" -exec chmod +x {} \;
42
43 # For LLDAP, we let it run as root to handle initial setup, then it switches to its internal user
44
45 # Generate secrets for lldap and update docker-compose.yml
46 if [[ "$service_name" == "lldap" ]]; then
47 # Check if secrets are already configured
48 if grep -q "changeme-jwt-secret-32-chars-min" "$target_dir/docker-compose.yml"; then
49 log "Generating LLDAP secrets..."
50 local jwt_secret
51 local key_seed
52 local admin_pass
53
54 jwt_secret=$(openssl rand -base64 32)
55 key_seed=$(openssl rand -base64 32)
56
57 read -s -p "Enter LLDAP admin password: " admin_pass
58 echo
59
60 # Update docker-compose.yml with actual secrets (using | as delimiter to avoid issues with / in base64)
61 sudo sed -i "s|changeme-jwt-secret-32-chars-min|$jwt_secret|" "$target_dir/docker-compose.yml"
62 sudo sed -i "s|changeme-key-seed-32-chars-minimum|$key_seed|" "$target_dir/docker-compose.yml"
63 sudo sed -i "s|changeme-admin-password|$admin_pass|" "$target_dir/docker-compose.yml"
64
65 log "LLDAP secrets configured"
66 else
67 log "LLDAP secrets already configured, skipping generation"
68 fi
69 fi
70
71 # Run service-specific setup if it exists
72 if [[ -f "$target_dir/setup.sh" ]]; then
73 log "Running $service_name setup..."
74 sudo -u tinsnip -i bash -c "cd ~/service/$service_name && ./setup.sh"
75 else
76 # Generic docker-compose deployment
77 log "Starting $service_name with docker-compose..."
78 sudo -u tinsnip -i bash -c "cd ~/service/$service_name && docker compose up -d"
79 fi
80
81 # Create systemd service for auto-start
82 create_systemd_service "$service_name"
83}
84
85create_systemd_service() {
86 local service_name="$1"
87 local systemd_file="/etc/systemd/system/tinsnip-${service_name}.service"
88
89 log "Creating systemd service for $service_name..."
90
91 sudo tee "$systemd_file" > /dev/null << EOF
92[Unit]
93Description=tinsnip $service_name service
94After=network-online.target
95Wants=network-online.target
96Requires=user@1010.service
97
98[Service]
99Type=simple
100User=tinsnip
101WorkingDirectory=/home/tinsnip/service/$service_name
102ExecStart=/usr/bin/sudo -u tinsnip docker compose up
103ExecStop=/usr/bin/sudo -u tinsnip docker compose down
104Restart=on-failure
105RestartSec=10
106
107[Install]
108WantedBy=multi-user.target
109EOF
110
111 sudo systemctl daemon-reload
112 sudo systemctl enable "tinsnip-${service_name}.service"
113 log "Systemd service created and enabled: tinsnip-${service_name}.service"
114}
115
116main() {
117 if [[ $# -lt 1 ]]; then
118 error "Usage: $0 <service-name>"
119 fi
120
121 local service_name="$1"
122
123 # Check if tinsnip user exists
124 if ! id "tinsnip" &>/dev/null; then
125 error "tinsnip user does not exist. Run setup.sh first."
126 fi
127
128 deploy_service "$service_name"
129
130 log ""
131 log "Service $service_name deployed successfully!"
132 log "To check status: sudo -u tinsnip docker compose -f /home/tinsnip/service/$service_name/docker-compose.yml ps"
133 log "To view logs: sudo -u tinsnip docker compose -f /home/tinsnip/service/$service_name/docker-compose.yml logs"
134}
135
136main "$@"