-
Notifications
You must be signed in to change notification settings - Fork 27
/
Copy pathinstall.sh
executable file
·356 lines (298 loc) · 10.8 KB
/
install.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
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
#!/usr/bin/env bash
# Enable strict mode for safer bash scripting
set -euo pipefail
# Trap errors and display line number
trap 'echo "Error on line $LINENO"; exit 1' ERR
#######################################
# Required environment variables
#######################################
: "${APP_DOCROOT:?APP_DOCROOT is not set}"
: "${WORDPRESS_DB_NAME:?WORDPRESS_DB_NAME is not set}"
: "${WORDPRESS_DB_USER:?WORDPRESS_DB_USER is not set}"
: "${WORDPRESS_DB_PASSWORD:?WORDPRESS_DB_PASSWORD is not set}"
: "${WORDPRESS_DB_HOST:?WORDPRESS_DB_HOST is not set}"
: "${NGINX_SERVER_NAME:?NGINX_SERVER_NAME is not set}"
: "${WORDPRESS_ADMIN:?WORDPRESS_ADMIN is not set}"
: "${WORDPRESS_ADMIN_PASSWORD:?WORDPRESS_ADMIN_PASSWORD is not set}"
: "${WORDPRESS_ADMIN_EMAIL:?WORDPRESS_ADMIN_EMAIL is not set}"
# Optional: Specify a version (or leave empty for latest)
WORDPRESS_VERSION="${WORDPRESS_VERSION:-}"
# INSTALL_METHOD can be "wp" or "curl". Defaults to "wp" (with fallback to curl)
INSTALL_METHOD="${INSTALL_METHOD:-wp}"
# OPcache settings with defaults
OPCACHE_PRELOAD_ENABLE="${OPCACHE_PRELOAD_ENABLE:-0}"
OPCACHE_PRELOAD_PATH="${OPCACHE_PRELOAD_PATH:-${APP_DOCROOT}/001-preload.php}"
# Redis settings with defaults
REDIS_UPSTREAM_HOST="${REDIS_UPSTREAM_HOST:-127.0.0.1}"
REDIS_UPSTREAM_PORT="${REDIS_UPSTREAM_PORT:-6379}"
#######################################
# Logging function
#######################################
log() {
echo "[$(date +"%Y-%m-%d %H:%M:%S")] $*"
}
#######################################
# Dependency check function
#######################################
check_dependency() {
command -v "$1" >/dev/null 2>&1 || { log "$1 is required but not installed. Aborting."; exit 1; }
}
# Check required commands
check_dependency curl
check_dependency unzip
check_dependency openssl
# If INSTALL_METHOD is not set to 'curl', verify WP-CLI is available
if [[ "$INSTALL_METHOD" != "curl" ]]; then
if ! command -v wp >/dev/null 2>&1; then
log "WP-CLI not found. Falling back to curl installation."
INSTALL_METHOD="curl"
fi
fi
#######################################
# Generates fallback salts if the API fails
#######################################
generate_fallback_salts() {
local keys=("AUTH" "SECURE_AUTH" "LOGGED_IN" "NONCE")
local salts=""
for key in "${keys[@]}"; do
local auth_key
auth_key=$(openssl rand -base64 48)
local auth_salt
auth_salt=$(openssl rand -base64 48)
salts+="define('${key}_KEY', '${auth_key}');\n"
salts+="define('${key}_SALT', '${auth_salt}');\n"
done
echo -e "$salts"
}
#######################################
# Downloads WordPress using wp-cli
#######################################
wordpress_install_wp_cli() {
log "Installing WordPress via WP-CLI method..."
mkdir -p "${APP_DOCROOT}"
cd "${APP_DOCROOT}" || exit
# Attempt to download the core files with wp-cli
if ! wp --allow-root core download ${WORDPRESS_VERSION:+--version="$WORDPRESS_VERSION"} --path="${APP_DOCROOT}"; then
log "WP-CLI download failed. Falling back to curl method..."
wordpress_install_curl
return
fi
chown -R www-data:www-data "${APP_DOCROOT}"
}
#######################################
# Downloads WordPress using curl (fallback method)
#######################################
wordpress_install_curl() {
log "Installing WordPress via curl method..."
mkdir -p "${APP_DOCROOT}"
cd "${APP_DOCROOT}" || exit
local wp_zip="wordpress.zip"
local download_url="https://wordpress.org/latest.zip"
if [ -n "$WORDPRESS_VERSION" ]; then
download_url="https://wordpress.org/wordpress-${WORDPRESS_VERSION}.zip"
fi
log "Downloading WordPress from ${download_url}..."
curl -fSL "${download_url}" -o "${wp_zip}"
log "Download complete; unzipping..."
# Create a temporary directory for extraction
local tmp_dir
tmp_dir=$(mktemp -d)
unzip -q "${wp_zip}" -d "${tmp_dir}"
# Move files from the extracted "wordpress" folder to the document root
cp -r "${tmp_dir}/wordpress/"* ./
# Cleanup temporary directory and zip file
rm -rf "${tmp_dir}" "${wp_zip}"
chown -R www-data:www-data "${APP_DOCROOT}"
}
#######################################
# Configures WordPress and installs plugins
#######################################
wordpress_config() {
log "Configuring WordPress..."
local MAX_RETRIES=3
local RETRY_DELAY=5
local SALT_URL="https://api.wordpress.org/secret-key/1.1/salt/"
local retries=0
local success=false
local wp_salts=""
log "Fetching WordPress salts..."
while [ $retries -lt $MAX_RETRIES ] && [ "$success" = false ]; do
wp_salts=$(curl -s -f "$SALT_URL") && success=true || {
retries=$((retries + 1))
if [ $retries -lt $MAX_RETRIES ]; then
log "Attempt $retries failed. Retrying in $RETRY_DELAY seconds..."
sleep $RETRY_DELAY
else
log "Failed to fetch salts after $MAX_RETRIES attempts; generating fallback salts..."
wp_salts=$(generate_fallback_salts)
success=true
fi
}
done
cd "${APP_DOCROOT}" || exit
if [[ "${OPCACHE_PRELOAD_ENABLE}" == "1" ]]; then
log "Generating OPcache preload script at ${OPCACHE_PRELOAD_PATH}..."
# Create the preload script
cat <<'EOF' > "${OPCACHE_PRELOAD_PATH}"
<?php
/**
* OPcache Preload File for WordPress
*
* This script precompiles a curated list of WordPress core files into OPcache.
* It's meant to be used with PHP 7.4+ with opcache.preload enabled.
*/
if (!function_exists('opcache_compile_file')) {
return;
}
// Define an array of core files to preload.
$preload_files = [
__DIR__ . '/wp-includes/load.php',
__DIR__ . '/wp-includes/functions.php',
__DIR__ . '/wp-includes/class-wp-hook.php',
__DIR__ . '/wp-includes/post.php',
__DIR__ . '/wp-includes/formatting.php',
__DIR__ . '/wp-includes/query.php',
__DIR__ . '/wp-includes/class-wpdb.php',
__DIR__ . '/wp-includes/cache.php',
__DIR__ . '/wp-includes/option.php',
__DIR__ . '/wp-includes/template.php',
__DIR__ . '/wp-includes/class-wp-query.php',
__DIR__ . '/wp-includes/class-wp.php',
__DIR__ . '/wp-includes/theme.php',
__DIR__ . '/wp-settings.php',
];
foreach ($preload_files as $file) {
if (file_exists($file)) {
opcache_compile_file($file);
}
}
EOF
fi # Close the if OPCACHE_PRELOAD_ENABLE condition
# Create the wp-config.php file
cat <<EOF > wp-config.php
<?php
define('DB_NAME', '${WORDPRESS_DB_NAME}');
define('DB_USER', '${WORDPRESS_DB_USER}');
define('DB_PASSWORD', '${WORDPRESS_DB_PASSWORD}');
define('DB_HOST', '${WORDPRESS_DB_HOST}');
define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');
// Salts
$wp_salts
\$table_prefix = '${WORDPRESS_TABLE_PREFIX:-wp_}';
define('WP_DEBUG', ${WORDPRESS_DEBUG:-false});
// Improved HTTPS detection
\$is_https = false;
if (isset(\$_SERVER['HTTP_X_FORWARDED_PROTO']) && \$_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
\$is_https = true;
} elseif (isset(\$_SERVER['HTTP_X_FORWARDED_SSL']) && \$_SERVER['HTTP_X_FORWARDED_SSL'] === 'on') {
\$is_https = true;
} elseif (isset(\$_SERVER['HTTPS']) && \$_SERVER['HTTPS'] === 'on') {
\$is_https = true;
}
\$_SERVER['HTTPS'] = \$is_https ? 'on' : 'off';
// Redis Configuration (if using Redis caching)
define('WP_REDIS_HOST', '${REDIS_UPSTREAM_HOST}');
define('WP_REDIS_PORT', ${REDIS_UPSTREAM_PORT});
define('WP_REDIS_DATABASE', 1);
define('WP_REDIS_PREFIX', 'wp_cache:');
define('WP_REDIS_MAXTTL', 86400);
define('WP_REDIS_TIMEOUT', 1);
define('WP_REDIS_READ_TIMEOUT', 1);
define('WP_REDIS_RETRY_INTERVAL', 100);
define('WP_REDIS_COMPRESSION', true);
define('WP_REDIS_COMPRESSION_LEVEL', 6);
define('WP_REDIS_SELECTIVE_FLUSH', true);
define('WP_REDIS_GRACEFUL', true);
define('WP_REDIS_PERSISTENT', true);
define('WP_REDIS_SERIALIZER', 'msgpack');
// Global groups for Redis (optional)
define('WP_REDIS_GLOBAL_GROUPS', [
'blog-details',
'blog-id-cache',
'blog-lookup',
'global-posts',
'networks',
'sites',
'site-details',
'site-lookup',
'site-options',
'site-transient',
'users',
'useremail',
'userlogins',
'usermeta',
'user_meta',
'userslugs',
]);
define('WP_REDIS_IGNORED_GROUPS', ['counts', 'plugins']);
define('FORCE_SSL_ADMIN', true);
define('DISALLOW_FILE_EDIT', false);
define('FS_METHOD', 'direct');
define('WP_CACHE', true);
if (!defined('ABSPATH')) {
define('ABSPATH', dirname(__FILE__) . '/');
}
require_once(ABSPATH . 'wp-settings.php');
EOF
log "Running WordPress core install..."
wp --allow-root --path="${APP_DOCROOT}" core install \
--url="https://${NGINX_SERVER_NAME}" \
--title="${NGINX_SERVER_NAME}" \
--admin_user="${WORDPRESS_ADMIN}" \
--admin_password="${WORDPRESS_ADMIN_PASSWORD}" \
--admin_email="${WORDPRESS_ADMIN_EMAIL}"
log "Updating admin user password..."
wp --allow-root --path="${APP_DOCROOT}" user update "${WORDPRESS_ADMIN}" \
--user_pass="${WORDPRESS_ADMIN_PASSWORD}" --allow-root
log "Deleting default plugins (akismet, hello)..."
wp --allow-root --path="${APP_DOCROOT}" plugin delete akismet hello
log "Setting permalink structure..."
wp --allow-root --path="${APP_DOCROOT}" rewrite structure '/%postname%/' --hard
log "Installing and activating additional plugins..."
wp --allow-root --path="${APP_DOCROOT}" plugin install amp antispam-bee nginx-helper wp-mail-smtp --activate
log "WordPress configuration complete."
log "Username: ${WORDPRESS_ADMIN} | Password: ${WORDPRESS_ADMIN_PASSWORD}"
echo "Username: ${WORDPRESS_ADMIN} | Password: ${WORDPRESS_ADMIN_PASSWORD}" > /home/creds.txt
chmod 600 /home/creds.txt
}
#######################################
# Sets appropriate file and directory permissions
#######################################
cleanup() {
log "Setting file permissions..."
# Change ownership for files and directories not owned by www-data
find "${APP_DOCROOT}" ! -user www-data -exec chown www-data:www-data {} +
# Set directory permissions to 755
find "${APP_DOCROOT}" -type d ! -perm 755 -exec chmod 755 {} +
# Set file permissions to 644
find "${APP_DOCROOT}" -type f ! -perm 644 -exec chmod 644 {} +
}
#######################################
# Main installation function
#######################################
run() {
if [[ ! -f "${APP_DOCROOT}/wp-config.php" ]]; then
# Choose installation method based on INSTALL_METHOD or wp-cli availability
if [[ "$INSTALL_METHOD" == "curl" ]]; then
wordpress_install_curl
else
if command -v wp >/dev/null 2>&1; then
wordpress_install_wp_cli
else
log "WP-CLI not found; falling back to curl method..."
wordpress_install_curl
fi
fi
# Add this snippet to copy your object cache file into wp-content
log "Copying object cache file..."
cp "/usr/src/plugins/${NGINX_APP_PLUGIN}/object-cache.php" "${APP_DOCROOT}/wp-content/object-cache.php"
wordpress_config
cleanup
else
log "WordPress appears to be already installed."
fi
}
# Execute the main function
run
exit 0