-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinit.sh
315 lines (259 loc) · 11.1 KB
/
init.sh
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
#!/bin/bash
g_env_file="/etc/environment"
g_docker_user="dockeruser"
g_docker_network="docker_network"
g_reboot_required=false
# Function to read input with regex validation
read_with_regex() {
local prompt="$1"
local regex="$2"
local default="$3"
local input
while true; do
# Read user input
if [[ -n $default ]]; then
read -p "$prompt (default: $default): " input
# Use default if input is empty
input="${input:-$default}"
else
read -p "$prompt: " input
fi
# Trim spaces and new lines
input=$(echo "$input" | xargs | tr -d '\n')
# Check if the input is valid
if [[ $input =~ $regex ]]; then
# Return valid input
echo "$input"
return
else
echo "Invalid input. Please try again." >&2
fi
done
}
# Function to set environment variable
set_environment_variable() {
local var_name="$1"
local var_value="$2"
local env_file="$g_env_file"
# Check if the variable is already in file
if grep -Eq "^[^#]*\b${var_name}=" "$env_file"; then
# Update the value if it's different
if [ "$(sudo grep -E "^[^#]*\b${var_name}=" "$env_file" | cut -d'=' -f2-)" != "$var_value" ]; then
sudo sed -i "s#^${var_name}=.*#${var_name}=${var_value}#" "$env_file"
echo "Updated $var_name in $env_file"
else
return
fi
else
# Append the new variable
echo "${var_name}=${var_value}" | sudo tee -a "$env_file" > /dev/null
echo "Added $var_name to $env_file"
fi
# Export for parent session
export "${var_name}=${var_value}"
g_reboot_required=true
}
# Function to set environment variable with command
set_environment_variable_with_command() {
local var_name="$1"
local command="$2"
local var_value
# Check if the variable is already set
if [ -z "${!var_name}" ]; then
var_value="${command}"
set_environment_variable "$var_name" "$var_value"
fi
}
# Function to set environment variable with prompt and regex
set_environment_variable_with_prompt_and_regex() {
local var_name="$1"
local prompt="$2"
local regex="$3"
local default="$4"
local var_value
# Check if the variable is already set
if [ -z "${!var_name}" ]; then
var_value=$(read_with_regex "$prompt" "$regex" "$default")
set_environment_variable "$var_name" "$var_value"
fi
}
# Function to set Docker secret
set_docker_secret() {
local secret_name="$1"
local secret_value="$2"
# Create the Docker secret
printf "$secret_value" | sudo docker secret create "$secret_name" - || {
echo -e "\033[0;35m✗\033[0m \033[1;31mFailed to create Docker secret '$secret_name'.\033[0m"
exit 1
}
echo "Docker secret '$secret_name' created."
}
# Function to set Docker secret with prompt and regex
set_docker_secret_with_prompt_and_regex() {
local secret_name="$1"
local prompt="$2"
local regex="$3"
local default="$4"
local secret_value
# Check if the secret is already set
if ! sudo docker secret ls | grep -w "$secret_name" > /dev/null 2>&1; then
secret_value=$(read_with_regex "$prompt" "$regex" "$default")
set_docker_secret "$secret_name" "$secret_value"
fi
}
# Function to check permissions
check_permissions() {
echo -e "\033[0;36m①\033[0m \033[1;36mPermissions\033[0m"
# Check for permissions
if ! sudo -v; then
echo -e "\033[0;35m✗\033[0m \033[1;31mYou need sudo privileges to run Docker commands. Please ensure you have proper permissions.\033[0m"
exit 1
fi
echo -e "\033[0;35m✓\033[0m \033[1;32mTask completed successfully.\033[0m"
}
# Function to install Docker
install_docker() {
echo -e "\033[0;36m②\033[0m \033[1;36mDocker setup\033[0m"
# Check if Docker is installed
if ! command -v docker > /dev/null 2>&1; then
# Install Docker
echo "Docker is not installed. Installing Docker..."
if ! curl -fsSL https://get.docker.com | sudo sh; then
echo -e "\033[0;35m✗\033[0m \033[1;31mFailed to install Docker. Please check your system's configuration.\033[0m"
exit 1
fi
echo "Docker has been installed."
# Start Docker service
if ! sudo systemctl is-active --quiet docker; then
echo "Docker service is not running. Starting Docker..."
sudo systemctl start docker || {
echo -e "\033[0;35m✗\033[0m \033[1;31mFailed to start Docker service.\033[0m"
exit 1
}
fi
echo "Docker service is running."
fi
echo -e "\033[0;35m✓\033[0m \033[1;32mTask completed successfully.\033[0m"
}
# Function to initialize Docker Swarm
initialize_docker_swarm() {
echo -e "\033[0;36m③\033[0m \033[1;36mDocker Swarm setup\033[0m"
local default_addr_pool
local advertise_addr
# Check if Docker Swarm is initialized
if sudo docker info 2>/dev/null | grep -iq "Swarm: inactive"; then
echo "Docker Swarm is not initialized. Initializing Docker Swarm..."
# Read the default address pool and advertise address for Docker Swarm
default_addr_pool=$(read_with_regex "Enter the default address pool" "^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]{1,2}\$" "172.18.0.0/16")
advertise_addr=$(read_with_regex "Enter the advertise address" "^([0-9]{1,3}\.){3}[0-9]{1,3}\$" "10.0.0.252")
# Initialize Docker Swarm
sudo docker swarm init --default-addr-pool $default_addr_pool --advertise-addr $advertise_addr || {
echo -e "\033[0;35m✗\033[0m \033[1;31mFailed to initialize Docker Swarm.\033[0m"
exit 1
}
echo "Docker Swarm initialized."
fi
echo -e "\033[0;35m✓\033[0m \033[1;32mTask completed successfully.\033[0m"
}
# Function to create a system user for Docker
create_docker_user() {
echo -e "\033[0;36m④\033[0m \033[1;36mDocker service user setup\033[0m"
local docker_user="$g_docker_user"
# Check if the system user exists
if ! id -u $docker_user > /dev/null 2>&1; then
# Create a new user
echo "Creating system user '$docker_user'..."
sudo useradd -r -M -N -s /bin/bash $docker_user || {
echo -e "\033[0;35m✗\033[0m \033[1;31mFailed to create user '$docker_user'.\033[0m"
exit 1
}
echo "User '$docker_user' created."
# Set a password for the user
echo "Set a password for '$docker_user':"
sudo passwd $docker_user
# Set the 'DOCKER_PUID' environment variable
echo "Updating DOCKER_PUID environment variable..."
set_environment_variable_with_command "DOCKER_PUID" "$(id -u dockeruser)"
fi
# Check if the user belongs to the 'docker' group
if ! groups $docker_user | grep -q "\bdocker\b"; then
# Add the user to the 'docker' group
echo "User '$docker_user' is not in the 'docker' group. Adding user to the 'docker' group..."
sudo usermod -aG docker $docker_user
echo "User '$docker_user' added to the 'docker' group."
# Set the 'DOCKER_PGID' environment variable
echo "Updating DOCKER_PGID environment variable..."
set_environment_variable_with_command "DOCKER_PGID" "$(getent group docker | cut -d: -f3)"
fi
echo -e "\033[0;35m✓\033[0m \033[1;32mTask completed successfully.\033[0m"
}
# Function to create the Docker network
create_docker_network() {
echo -e "\033[0;36m⑤\033[0m \033[1;36mDocker network setup\033[0m"
local docker_network="$g_docker_network"
# Check if the Docker network exists
if ! sudo docker network inspect $docker_network > /dev/null 2>&1; then
# Create the Docker network
echo "Creating $docker_network network..."
sudo docker network create --driver overlay --attachable $docker_network || {
echo -e "\033[0;35m✗\033[0m \033[1;31mFailed to create Docker network '$docker_network'.\033[0m"
exit 1
}
echo "$docker_network network created."
# Set the 'DOCKER_NETWORK' environment variable
echo "Updating DOCKER_NETWORK environment variable..."
set_environment_variable "DOCKER_NETWORK" "$docker_network"
fi
echo -e "\033[0;35m✓\033[0m \033[1;32mTask completed successfully.\033[0m"
}
# Function to configure Docker apps
configure_docker_apps() {
echo -e "\033[0;36m⑥\033[0m \033[1;36mDocker secrets setup\033[0m"
local username
local password
local wireguard_password_hash
local basicauth_password_hash
set_docker_secret_with_prompt_and_regex "duckdns_token" "Enter the Duck DNS token" "[a-zA-Z0-9-]+"
if ! sudo docker secret ls | grep -w "username" > /dev/null 2>&1; then
username=$(read_with_regex "Enter the username" "^[a-zA-Z0-9]{4,}\$")
set_docker_secret "username" "$username"
set_environment_variable "BASICAUTH_USERNAME" "$username"
fi
if ! sudo docker secret ls | grep -w "password" > /dev/null 2>&1; then
password=$(read_with_regex "Enter the password" "^[A-Za-z0-9@\$!%*?&]{6,}\$")
wireguard_password_hash=$(docker run --rm -it ghcr.io/wg-easy/wg-easy wgpw "$password" | grep -oP "PASSWORD_HASH='.*'" | sed "s/PASSWORD_HASH='//;s/'$//")
basicauth_password_hash=$(docker run --rm --name apache httpd:alpine htpasswd -nb admin $password | cut -d: -f2)
set_docker_secret "password" "$password"
set_environment_variable "WIREGUARD_PASSWORD_HASH" "$wireguard_password_hash"
set_environment_variable "BASICAUTH_PASSWORD_HASH" "$basicauth_password_hash"
fi
echo -e "\033[0;36m⑥\033[0m \033[1;36mDocker environment variables setup\033[0m"
set_environment_variable_with_command "DOCKER_TZ" "$(cat /etc/timezone 2>/dev/null || timedatectl | grep "Time zone" | awk '{print $3}')"
set_environment_variable_with_prompt_and_regex "WIREGUARD_DOMAIN_NAME" "Enter the domain name used for WireGuard VPN" "^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\$"
set_environment_variable_with_prompt_and_regex "TRAEFIK_DOMAIN_NAME" "Enter the domain name used for Traefik reverse-proxy" "^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\$"
set_environment_variable_with_prompt_and_regex "DUCKDNS_EMAIL" "Enter the Duck DNS email address" "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\$"
echo -e "\033[0;35m✓\033[0m \033[1;32mTask completed successfully.\033[0m"
}
# Function to ask the user to reboot the system if required
reboot_system_if_needed() {
if [ "$g_reboot_required" = true ]; then
echo -e "\033[0;33mYou need to restart the system to apply the changes.\033[0m"
answer=$(read_with_regex "Do you want to reboot now? [Y/n]" "^[yYnN]$" "Y")
if [[ $answer =~ ^[yY]$ ]]; then
sudo reboot
exit 0
fi
echo -e "\033[0;35m✗\033[0m \033[1;33mPlease reboot your system before restarting the installation process.\033[0m"
exit 1
fi
}
# Main script execution
check_permissions
install_docker
initialize_docker_swarm
create_docker_user
configure_docker_apps
initialize_docker_secrets
set_docker_environment_variables
create_docker_network
reboot_system_if_needed