-
-
Notifications
You must be signed in to change notification settings - Fork 136
/
Copy path10-init-unit.sh
194 lines (164 loc) · 7.46 KB
/
10-init-unit.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
#!/bin/sh
###################################################
# Usage: 10-init-unit.sh
###################################################
# This script processes the environment variables used in the Unit configuration template files.
# Once the templates are processed, the script will enable the configurations and start Unit.
# This script is executed at container initialization.
set -e
script_name="init-unit"
WAITLOOPS=5
SLEEPSEC=1
UNIT_CONFIG_DIRECTORY=${UNIT_CONFIG_DIRECTORY:-"/etc/unit/config.d"}
UNIT_CONFIG_FILE=${UNIT_CONFIG_FILE:-"$UNIT_CONFIG_DIRECTORY/config.json"}
UNIT_SOCKET_LOCATION=${UNIT_SOCKET_LOCATION:-"/var/run/unit/control.unit.sock"}
##########
# Functions
##########
set_debug_output() {
if [ "$LOG_OUTPUT_LEVEL" = "debug" ]; then
echo "👉 $script_name: Output of $*:" >&2
echo
eval "$@" || { echo "Command $* failed" >&2; return 1; }
echo
fi
}
process_template() {
template_file=$1
output_file=$2
if [ -f "$output_file" ]; then
echo "$script_name (ℹ️ NOTICE): $output_file already exists, so we'll use the existing file."
return 0
fi
if [ ! -f "$template_file" ]; then
echo "🛑 ERROR ($script_name): Unable to initialize container. $output_file doesn't exist and we're unable to find a template for $template_file."
return 1
fi
# Get all environment variables starting with 'NGINX_', 'SSL_', `LOG_`, and 'APACHE_'
subst_vars=$(env | grep -E '^(UNIT_|SSL_|LOG_)' | cut -d= -f1 | awk '{printf "${%s},",$1}' | sed 's/,$//')
# Validate that all required variables are set
for var_name in $(echo "$subst_vars" | tr ',' ' '); do
eval "value=\$$var_name" # Use eval to get the value of var_name
if [ -z "$value" ]; then
echo "🛑 ERROR ($script_name): Environment variable $var_name is not set."
return 1
fi
done
echo "$script_name: Processing $template_file → $output_file..."
envsubst "$subst_vars" < "$template_file" > "$output_file"
set_debug_output "cat $output_file"
}
curl_put() {
curl_option="$1"
curl_value="$2"
api_location="$3"
if [ $curl_option = "--data-binary" ]; then
curl_value="@$curl_value"
fi
curl_return=$(/usr/bin/curl -s -w '\n%{http_code}' -X PUT "$curl_option" "$curl_value" --unix-socket "$UNIT_SOCKET_LOCATION" "http://localhost/$api_location")
return_status=$(echo "$curl_return" | tail -n1)
return_body=$(echo "$curl_return" | head -n -1)
if [ "$return_status" -ne "200" ]; then
if echo "$return_body" | grep "Certificate already exists."; then
echo "ℹ️ NOTICE: Certificate already exists. Ignoring this error..."
echo "$return_body"
return 0 # Ignore errors of certicate already existing
else
echo "🛑 ERROR: HTTP response status code is '$return_status'"
echo "$return_body"
return 1 # Return error for all other errors
fi
else
echo "✅ OK: HTTP response status code is '$return_status'"
echo "$return_body"
fi
return 0
}
configure_unit() {
echo "$script_name: Launching Unit daemon to perform initial configuration..."
/usr/sbin/$DOCKER_CMD --control unix:"$UNIT_SOCKET_LOCATION"
for i in $(/usr/bin/seq $WAITLOOPS); do
if [ ! -S "$UNIT_SOCKET_LOCATION" ]; then
echo "$script_name: Waiting for control socket to be created..."
/bin/sleep $SLEEPSEC
else
break
fi
done
# even when the control socket exists, it does not mean unit has finished initialisation
# this curl call will get a reply once unit is fully launched
/usr/bin/curl -s -X GET --unix-socket "$UNIT_SOCKET_LOCATION" http://localhost/
echo "$script_name: Looking for certificate bundles in $UNIT_CONFIG_DIRECTORY..."
for f in $(/usr/bin/find "$UNIT_CONFIG_DIRECTORY" -type f -name "*.pem"); do
echo "$script_name: Uploading certificates bundle: $f"
curl_put "--data-binary" "$f" "certificates/$(basename $f .pem)"
done
set_debug_output "/usr/bin/find $UNIT_CONFIG_DIRECTORY -type f -name \"*.pem\""
echo "$script_name: Looking for JavaScript modules in $UNIT_CONFIG_DIRECTORY..."
for f in $(/usr/bin/find $UNIT_CONFIG_DIRECTORY -type f -name "*.js"); do
echo "$script_name: Uploading JavaScript module: $f"
curl_put "--data-binary" "$f" "js_modules/$(basename $f .js)"
done
echo "$script_name: Looking for configuration snippets in $UNIT_CONFIG_DIRECTORY..."
for f in $(/usr/bin/find "$UNIT_CONFIG_DIRECTORY" -type f -name "*.json"); do
echo "$script_name: Applying configuration $f";
curl_put "--data-binary" "$f" "config"
done
# warn on filetypes we don't know what to do with
for f in $(/usr/bin/find "$UNIT_CONFIG_DIRECTORY" -type f -not -name "*.sh" -not -name "*.template" -not -name "*.json" -not -name "*.pem" -not -name "*.js"); do
echo "$script_name: Ignoring $f";
done
echo "$script_name: Setting access log to STDOUT..."
curl_put "-d" '"/dev/stdout"' "config/access_log"
echo "$script_name: Stopping Unit daemon after initial configuration..."
kill -TERM "$(/bin/cat /var/run/unit/unit.pid)"
for i in $(/usr/bin/seq $WAITLOOPS); do
if [ -S "$UNIT_SOCKET_LOCATION" ]; then
echo "$script_name: Waiting for control socket to be removed..."
/bin/sleep $SLEEPSEC
else
break
fi
done
if [ -S "$UNIT_SOCKET_LOCATION" ]; then
kill -KILL "$(/bin/cat /var/run/unit/unit.pid)"
rm -f "$UNIT_SOCKET_LOCATION"
fi
echo
echo "$script_name: Unit initial configuration complete; ready for start up..."
echo
}
validate_ssl(){
available_ssl_bundles=$(/usr/bin/find "$UNIT_CONFIG_DIRECTORY" -type f -name "*.pem")
if [ -n "$available_ssl_bundles" ]; then
echo "ℹ️ NOTICE ($script_name): SSL Certbundle already exists, so we'll use the existing files."
return 0
fi
echo "$script_name: 🔐 SSL Certbundle not found. Generating self-signed SSL bundle..."
mkdir -p /etc/ssl/private/
openssl req -x509 -subj "/C=US/ST=Wisconsin/L=Milwaukee/O=IT/CN=default.test" -nodes -newkey rsa:2048 -keyout "/etc/ssl/private/$UNIT_CERTIFICATE_NAME.key" -out "/etc/ssl/private/$UNIT_CERTIFICATE_NAME.crt" -days 365 >/dev/null 2>&1
cat "/etc/ssl/private/$UNIT_CERTIFICATE_NAME.key" "/etc/ssl/private/$UNIT_CERTIFICATE_NAME.crt" > "$UNIT_CONFIG_DIRECTORY/$UNIT_CERTIFICATE_NAME.pem"
}
##########
# Main
##########
DOCKER_CMD=$1
if [ "$DISABLE_DEFAULT_CONFIG" = false ]; then
# Configure Unit only if the command is "unitd" or "unitd-debug"
if [ "$DOCKER_CMD" = "unitd" ] || [ "$DOCKER_CMD" = "unitd-debug" ]; then
ssl_mode=$(echo "$SSL_MODE" | tr '[:upper:]' '[:lower:]')
process_template "$UNIT_CONFIG_DIRECTORY/ssl-$ssl_mode.json.template" "$UNIT_CONFIG_DIRECTORY/config.json"
if [ "$ssl_mode" != "off" ]; then
validate_ssl
fi
configure_unit
else
if [ "$LOG_OUTPUT_LEVEL" = "debug" ]; then
echo "👉 $script_name: DISABLE_DEFAULT_CONFIG does not equal \"false\", so no initialization will be performed."
fi
fi
# If debug is set, write replace "unitd" with "unitd-debug" and save this file in the docker_cmd_override file for execution by the entrypoint script
if [ "$LOG_OUTPUT_LEVEL" = "debug" ]; then
echo "$@" | sed 's/unitd/unitd-debug/' > /tmp/docker_cmd_override
fi
fi