-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.sh
More file actions
executable file
·184 lines (169 loc) · 7.56 KB
/
Copy pathserver.sh
File metadata and controls
executable file
·184 lines (169 loc) · 7.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#!/usr/bin/env bash
# Headless server (Ubuntu Server LTS) profile: apt + snap, no GUI packages.
# Shares the Linux install spine (linux_main) with the apt desktop — the
# apt/Tailscale/Docker hooks live in lib/core.sh. This module only carries the
# server tier composition and the server-only "step two" infra: SSH/Tailscale
# services, Docker dashboard stacks, cockpit, AdGuard.
# (The Raspberry Pi — Debian proper, no snapd — is a future target; docs/TODO.md.)
platform_bootstrap() {
apt_bootstrap
}
# Pre-clone the antidote plugins now while the network is provably up; otherwise
# the first interactive login does the GitHub clones lazily.
server_preclone_antidote() {
printf '\n==> Pre-cloning antidote plugins...\n'
run zsh -c 'source /usr/share/zsh-antidote/antidote.zsh && antidote bundle <"$HOME/.zsh_plugins.txt" >/dev/null' \
|| printf 'warning: antidote pre-clone failed; plugins will clone on first login\n' >&2
}
server_ups_step() {
pkg_selected nut || return 0
local ups_dir="$CONFIG_SRC_DIR/ups"
printf '\n==> Configuring NUT UPS monitoring...\n'
if [[ -f "$ups_dir/.env" ]]; then
run sudo bash "$ups_dir/setup.sh"
else
printf ' NUT is installed but not configured. Run:\n'
printf ' cp %s/.env.example %s/.env\n' "$ups_dir" "$ups_dir"
printf ' sudo bash %s/setup.sh\n' "$ups_dir"
fi
}
# Server-only "step two": the headless service + dashboard layer that runs after
# the shared base install (packages, shell, dotfiles, Tailscale, Docker engine).
server_extras() {
# ── Cockpit ─────────────────────────────────────────────────────────────────
printf '\n'
if systemctl is-active --quiet cockpit.socket 2>/dev/null; then
printf '==> Cockpit already running\n'
else
printf '==> Enabling cockpit...\n'
run sudo systemctl enable --now cockpit.socket
fi
# ── Tailscale web service ───────────────────────────────────────────────────
printf '\n'
local service_dst="$HOME/.config/systemd/user/tailscale-web.service"
if [[ ! -f "$service_dst" ]] || ! diff -q "$CONFIG_SRC_DIR/tailscale-web.service" "$service_dst" &>/dev/null; then
printf '==> Installing Tailscale web service...\n'
run mkdir -p "$HOME/.config/systemd/user"
run cp "$CONFIG_SRC_DIR/tailscale-web.service" "$service_dst"
run systemctl --user daemon-reload
run systemctl --user enable --now tailscale-web
else
printf '==> Tailscale web service already installed\n'
fi
run loginctl enable-linger "$USER"
# ── AdGuard: free port 53 ───────────────────────────────────────────────────
printf '\n'
local resolved_conf="/etc/systemd/resolved.conf"
if ! grep -q "^DNSStubListener=no" "$resolved_conf" 2>/dev/null; then
printf '==> Freeing port 53 for AdGuard...\n'
run sudo sed -i 's/#DNSStubListener=yes/DNSStubListener=no/' "$resolved_conf"
run sudo systemctl restart systemd-resolved
else
printf '==> Port 53 already free for AdGuard\n'
fi
# ── Docker .env files ───────────────────────────────────────────────────────
printf '\n'
printf '==> Setting up Docker service .env files...\n'
local svc
for svc in homepage speedtest-tracker filebrowser tailscale-proxy qbittorrent; do
if [[ -f "$CONFIG_SRC_DIR/$svc/.env.example" && ! -f "$CONFIG_SRC_DIR/$svc/.env" ]]; then
run cp "$CONFIG_SRC_DIR/$svc/.env.example" "$CONFIG_SRC_DIR/$svc/.env"
printf ' created %s/.env\n' "$svc"
else
printf ' ✓ %s/.env\n' "$svc"
fi
done
# Fill derivable values into homepage/.env (replace placeholders or append if missing)
local homepage_env="$CONFIG_SRC_DIR/homepage/.env"
if [[ -f "$homepage_env" ]]; then
_fill_env() {
local key="$1" val="$2"
if [[ "$DRY_RUN" == true ]]; then
printf ' [dry-run] %s → %s\n' "$key" "$val"
return
fi
if grep -q "^$key=" "$homepage_env"; then
sed -i "s|^$key=.*|$key=$val|" "$homepage_env"
else
echo "$key=$val" >> "$homepage_env"
fi
printf ' %s → %s\n' "$key" "$val"
}
_fill_env HOSTNAME "$(hostname)"
_fill_env SERVER_IP "$(hostname -I | awk '{print $1}')"
if command -v tailscale &>/dev/null; then
local ts_hostname
ts_hostname=$(tailscale status --json 2>/dev/null | jq -r '.Self.DNSName // empty' | sed 's/\.$//')
if [[ -n "$ts_hostname" ]]; then
_fill_env TAILSCALE_HOSTNAME "$ts_hostname"
else
printf " TAILSCALE_HOSTNAME → (skipped — run 'tailscale up' then re-run setup.sh)\n"
fi
fi
fi
# Auto-generate APP_KEY for speedtest-tracker
if [[ -f "$CONFIG_SRC_DIR/speedtest-tracker/.env" ]]; then
if ! grep -qE "^APP_KEY=base64:.+" "$CONFIG_SRC_DIR/speedtest-tracker/.env" 2>/dev/null; then
if [[ "$DRY_RUN" == true ]]; then
printf ' [dry-run] generate APP_KEY in speedtest-tracker/.env\n'
else
local app_key
app_key="base64:$(openssl rand -base64 32)"
sed -i "s|^APP_KEY=.*|APP_KEY=$app_key|" "$CONFIG_SRC_DIR/speedtest-tracker/.env"
printf ' auto-generated APP_KEY for speedtest-tracker\n'
fi
fi
fi
# ── Docker services ─────────────────────────────────────────────────────────
printf '\n'
printf '==> Starting Docker services...\n'
local svc_dir
for svc in homepage portainer glances speedtest-tracker filebrowser watchtower \
uptime-kuma nginx-proxy-manager ntfy syncthing adguard tailscale-proxy \
qbittorrent; do
svc_dir="$CONFIG_SRC_DIR/$svc"
if [[ -d "$svc_dir" && -f "$svc_dir/docker-compose.yml" ]]; then
printf ' %s...\n' "$svc"
if ! run sudo docker compose -f "$svc_dir/docker-compose.yml" up -d; then
printf ' Warning: %s failed to start\n' "$svc"
fi
fi
done
}
server_footer() {
printf '\n'
if [[ "$DRY_RUN" == true ]]; then
printf 'Dry run complete — nothing was installed.\n'
return 0
fi
printf '================================================================\n'
printf ' Done. A few manual steps remain:\n'
printf '================================================================\n'
printf '\n'
printf " 1. Log out and back in — activates zsh and 'docker' without sudo\n"
printf '\n'
printf ' 2. Authenticate Tailscale:\n'
printf ' sudo tailscale up\n'
printf ' sudo tailscale set --operator=$USER\n'
printf '\n'
printf ' 3. SSH / GPG keys:\n'
printf ' bash SSH_and_GPG/create_ssh_key.sh\n'
printf ' bash SSH_and_GPG/create_gpg_key.sh\n'
printf '\n'
printf ' 4. Authenticate Tailscale, then re-run setup.sh to auto-fill TAILSCALE_HOSTNAME:\n'
printf ' sudo tailscale up\n'
printf ' bash setup.sh --profile server\n'
printf ' Then fill in any remaining values in linux-server/homepage/.env and restart:\n'
printf ' cd linux-server/homepage && docker compose restart\n'
printf '\n'
printf '================================================================\n'
printf '\n'
if command -v bat &>/dev/null; then
bat "$CONFIG_SRC_DIR/post-install.md"
else
cat "$CONFIG_SRC_DIR/post-install.md"
fi
}
platform_main() {
linux_main
}