Created
June 8, 2017 08:52
-
-
Save phlbnks/94773378dce06336d05f35a88d88d9dd to your computer and use it in GitHub Desktop.
WP CLI based version of wp.sh (https://gist.github.com/emirpprime/37ef1f355ec5a7ecbb8f)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash -e | |
# | |
# Description: | |
# This will deploy WordPress in the current directory. | |
# Without modification it: | |
# - will configure basic security: | |
# - remove initial user created | |
# - deploy 6G firewall in .htaccess | |
# - attempt to prevent user enumeration in .htaccess | |
# - protect sensitive files and disallow executables in /wp-uploads | |
# - presumes a htpasswd file called wp-login is located in /etc/apache2/ | |
# - disallows theme/plugin editor in wp-admin | |
# - only allows core/plugin/theme updates in wp-admin when using a cookie set using &key=xxx | |
# - presumes it is a staging environment so sets 'discourage search engines' | |
# - deletes akismet and hello_dolly plugins | |
# - deletes the default page and post | |
# - creates a blank page called Home and sets it as the frontpage | |
# - sets permalinks to /%postaname%/ | |
# - optionally it: | |
# - bootstraps an _S theme | |
# - installs some plugins - advanced-custom-fields autoptimize better-wp-security breadcrumb-navxt broken-link-checker cms-tree-page-view custom-post-type-ui ewww-image-optimizer google-analytics-dashboard-for-wp google-captcha google-sitemap-generator gravity-forms-custom-post-types plugincheck query-monitor redirection re generate-thumbnails simple-local-avatars theme-check wp-fail2ban wp-pagenavi wp-super-cache | |
# - finally it will delete itself after it finishes. | |
clear | |
echo "============================================" | |
echo "WordPress Install Script" | |
echo "============================================" | |
echo "Do you need to setup new MySQL database? (y/n)" | |
read -e setupmysql | |
if [ "$setupmysql" == y ] ; then | |
echo "MySQL Admin User: " | |
read -e mysqluser | |
echo "MySQL Admin Password: " | |
read -s mysqlpass | |
echo "MySQL Host (Enter for default 'localhost'): " | |
read -e mysqlhost | |
mysqlhost=${mysqlhost:-localhost} | |
fi | |
echo "WP Database Name: " | |
read -e dbname | |
echo "WP Database User: " | |
read -e dbuser | |
echo "WP Database Password: " | |
read -s dbpass | |
echo "WP Database Table Prefix [numbers, letters, and underscores only] (Enter for default 'wp_'): " | |
read -e dbtable | |
dbtable=${dbtable:-wp_} | |
echo "Key for updating in wp-admin: " | |
read -e hardenkey | |
echo "Last chance - sure you want to run the install? (y/n)" | |
read -e run | |
if [ "$run" == y ] ; then | |
if [ "$setupmysql" == y ] ; then | |
echo "============================================" | |
echo "Setting up the database." | |
echo "============================================" | |
#login to MySQL, add database, add user and grant permissions | |
dbsetup="create database $dbname;GRANT ALL PRIVILEGES ON $dbname.* TO $dbuser@$mysqlhost IDENTIFIED BY '$dbpass';FLUSH PRIVILEGES;" | |
mysql -u $mysqluser -p$mysqlpass -e "$dbsetup" | |
if [ $? != "0" ]; then | |
echo "============================================" | |
echo "[Error]: Database creation failed. Aborting." | |
echo "============================================" | |
exit 1 | |
fi | |
fi | |
# configure wp cli to allow htaccess modification / re-write flushing. | |
cat > wp-cli.local.yml <<'EOL' | |
apache_modules: | |
- mod_rewrite | |
EOL | |
echo "============================================" | |
echo "Downloading WordPress for you." | |
echo "============================================" | |
#download wordpress | |
wp core download --locale=en_GB | |
echo "+++ Configuring..." | |
wp core config --dbname=$dbname --dbprefix=$dbtable --dbuser=$dbuser --dbpass=$dbpass --extra-php <<PHP | |
/** WP_DEBUG setup **/ | |
define( 'WP_DEBUG', false ); | |
if ( WP_DEBUG ) { | |
define( 'WP_DEBUG_LOG', true ); | |
define( 'SCRIPT_DEBUG', true ); | |
define( 'WP_DEBUG_DISPLAY', false ); | |
@ini_set( 'display_errors', 0 ); | |
} | |
/** Disallow theme and plugin editor in admin. Updates only with query var **/ | |
define( 'DISALLOW_FILE_EDIT', true ); | |
if ( $_REQUEST['key'] == "$hardenkey" ) { | |
setcookie( 'updatebypass', 1 ); | |
} elseif ( ! $_COOKIE['updatebypass'] ) { | |
define( 'DISALLOW_FILE_MODS', true ); | |
} | |
PHP | |
#create uploads folder and set permissions | |
mkdir -p wp-content/uploads | |
chmod 775 wp-content/uploads | |
#remove readme.html | |
rm readme.html | |
#create root .htaccess with some useful starters | |
cat > .htaccess <<'EOL' | |
# Protect this file | |
<Files ~ "^\.ht"> | |
Order allow,deny | |
Deny from all | |
</Files> | |
# Prevent directory listing | |
Options -Indexes | |
## BEGIN 6G Firewall from https://perishablepress.com/6g/ | |
# 6G:[QUERY STRINGS] | |
<IfModule mod_rewrite.c> | |
RewriteEngine On | |
RewriteCond %{QUERY_STRING} (eval\() [NC,OR] | |
RewriteCond %{QUERY_STRING} (127\.0\.0\.1) [NC,OR] | |
RewriteCond %{QUERY_STRING} ([a-z0-9]{2000}) [NC,OR] | |
RewriteCond %{QUERY_STRING} (javascript:)(.*)(;) [NC,OR] | |
RewriteCond %{QUERY_STRING} (base64_encode)(.*)(\() [NC,OR] | |
RewriteCond %{QUERY_STRING} (GLOBALS|REQUEST)(=|\[|%) [NC,OR] | |
RewriteCond %{QUERY_STRING} (<|%3C)(.*)script(.*)(>|%3) [NC,OR] | |
RewriteCond %{QUERY_STRING} (\\|\.\.\.|\.\./|~|`|<|>|\|) [NC,OR] | |
RewriteCond %{QUERY_STRING} (boot\.ini|etc/passwd|self/environ) [NC,OR] | |
RewriteCond %{QUERY_STRING} (thumbs?(_editor|open)?|tim(thumb)?)\.php [NC,OR] | |
RewriteCond %{QUERY_STRING} (\'|\")(.*)(drop|insert|md5|select|union) [NC] | |
RewriteRule .* - [F] | |
</IfModule> | |
# 6G:[REQUEST METHOD] | |
<IfModule mod_rewrite.c> | |
RewriteCond %{REQUEST_METHOD} ^(connect|debug|delete|move|put|trace|track) [NC] | |
RewriteRule .* - [F] | |
</IfModule> | |
# 6G:[REFERRERS] | |
<IfModule mod_rewrite.c> | |
RewriteCond %{HTTP_REFERER} ([a-z0-9]{2000}) [NC,OR] | |
RewriteCond %{HTTP_REFERER} (semalt.com|todaperfeita) [NC] | |
RewriteRule .* - [F] | |
</IfModule> | |
# 6G:[REQUEST STRINGS] | |
<IfModule mod_alias.c> | |
RedirectMatch 403 (?i)([a-z0-9]{2000}) | |
RedirectMatch 403 (?i)(https?|ftp|php):/ | |
RedirectMatch 403 (?i)(base64_encode)(.*)(\() | |
RedirectMatch 403 (?i)(=\\\'|=\\%27|/\\\'/?)\. | |
RedirectMatch 403 (?i)/(\$(\&)?|\*|\"|\.|,|&|&?)/?$ | |
RedirectMatch 403 (?i)(\{0\}|\(/\(|\.\.\.|\+\+\+|\\\"\\\") | |
RedirectMatch 403 (?i)(~|`|<|>|:|;|,|%|\\|\s|\{|\}|\[|\]|\|) | |
RedirectMatch 403 (?i)/(=|\$&|_mm|cgi-|etc/passwd|muieblack) | |
RedirectMatch 403 (?i)(&pws=0|_vti_|\(null\)|\{\$itemURL\}|echo(.*)kae|etc/passwd|eval\(|self/environ) | |
RedirectMatch 403 (?i)\.(aspx?|bash|bak?|cfg|cgi|dll|exe|git|hg|ini|jsp|log|mdb|out|sql|svn|swp|tar|rar|rdf)$ | |
RedirectMatch 403 (?i)/(^$|(wp-)?config|mobiquo|phpinfo|shell|sqlpatch|thumb|thumb_editor|thumbopen|timthumb|webshell)\.php | |
</IfModule> | |
# 6G:[USER AGENTS] | |
<IfModule mod_setenvif.c> | |
SetEnvIfNoCase User-Agent ([a-z0-9]{2000}) bad_bot | |
SetEnvIfNoCase User-Agent (archive.org|binlar|casper|checkpriv|choppy|clshttp|cmsworld|diavol|dotbot|extract|feedfinder|flicky|g00g1e|harvest|heritrix|httrack|kmccrew|loader|miner|nikto|nutch|planetwork|postrank|purebot|pycurl|python|seekerspider|siclab|skygrid|sqlmap|sucker|turnit|vikspider|winhttp|xxxyy|youda|zmeu|zune) bad_bot | |
<limit GET POST PUT> | |
Order Allow,Deny | |
Allow from All | |
Deny from env=bad_bot | |
</limit> | |
</IfModule> | |
# 6G:[BAD IPS] | |
<Limit GET HEAD OPTIONS POST PUT> | |
Order Allow,Deny | |
Allow from All | |
# uncomment/edit/repeat next line to block IPs | |
# Deny from 123.456.789 | |
</Limit> | |
## END 6G Firewall | |
## BEGIN htauth basic authentication | |
# STAGING | |
Require all denied | |
AuthType Basic | |
AuthUserFile /etc/apache2/wp-login | |
AuthName "Please Authenticate" | |
Require valid-user | |
# LIVE - prevent wp-login brute force attacks from causing load | |
#<FilesMatch "^(wp-login|xmlrpc)\.php$"> | |
# AuthType Basic | |
# AuthUserFile /etc/apache2/wp-login | |
# AuthName "Please Authenticate" | |
# Require valid-user | |
#</FilesMatch> | |
# Exclude the file upload and WP CRON scripts from authentication | |
<FilesMatch "(async-upload\.php|wp-cron\.php)$"> | |
Satisfy Any | |
Order allow,deny | |
Allow from all | |
Deny from none | |
</FilesMatch> | |
## END htauth | |
## BEGIN WP file protection | |
<Files wp-config.php> | |
order allow,deny | |
deny from all | |
</Files> | |
# WP includes directories | |
<IfModule mod_rewrite.c> | |
RewriteEngine On | |
RewriteBase / | |
RewriteRule ^wp-admin/includes/ - [F,L] | |
RewriteRule !^wp-includes/ - [S=3] | |
# note - comment out next line on multisite | |
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L] | |
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L] | |
RewriteRule ^wp-includes/theme-compat/ - [F,L] | |
</IfModule> | |
## END WP file protection | |
# Prevent author enumeration | |
RewriteCond %{REQUEST_URI} !^/wp-admin [NC] | |
RewriteCond %{QUERY_STRING} author=\d | |
RewriteRule ^ /? [L,R=301] | |
EOL | |
#create .htaccess to protect uploads directory | |
cat > wp-content/uploads/.htaccess <<'EOL' | |
# Protect this file | |
<Files .htaccess> | |
Order Deny,Allow | |
Deny from All | |
</Files> | |
# whitelist file extensions to prevent executables being | |
# accessed if they get uploaded | |
order deny,allow | |
deny from all | |
<Files ~ "(?i)\.(docx?|xlsx?|pptx?|txt|pdf|xml|css|jpe?g|png|gif)$"> | |
allow from all | |
</Files> | |
EOL | |
echo "Setup WordPress to a 'standard install'? (y/n)" | |
read -e setupwp | |
if [ "$setupwp" == y ] ; then | |
echo "=========================" | |
echo "Configuring WordPress." | |
echo "=========================" | |
# useful ref: https://indigotree.co.uk/automated-wordpress-installation-with-bash-wp-cli/ | |
echo "Site URL (no trailing slash): " | |
read -e siteurl | |
echo "Site name: " | |
read -e sitename | |
wp core install --url="${siteurl}/" --title="$sitename" --admin_user=admin --admin_password=admin [email protected] --skip-email | |
echo "Is this a sub-directory install? (y/n)" | |
read -e issubdir | |
if [ "$issubdir" == y ] ; then | |
read -e subdir | |
wp option update "${siteurl}/$issubdir" | |
fi | |
echo "+++ Setting up users..." | |
echo "Admin user name: " | |
read -e adminname | |
echo "Admin user email: " | |
read -e adminemail | |
wp user create $adminname $adminemail --role=administrator --send-email | |
echo "+++ Deleting dummy admin user..." | |
wp user delete admin | |
echo "+++ Discouraging search engines..." | |
wp option update blog_public 0 | |
echo "+++ Setting permalinks to /%postaname%/..." | |
wp rewrite structure '/%postname%/' --hard | |
wp rewrite flush --hard | |
echo "+++ Sample page and post deleted when users cleaned; now create empty 'Home' page..." | |
#echo "+++ Deleting sample page and post; create empty 'Home' page..." | |
#wp post delete $(wp post list --post_type=page,post --field=ID --format=ids) | |
wp post create --post_type=page --post_title=Home --post_status=publish | |
echo "+++ Set frontpage setting to show a page..." | |
wp option update show_on_front 'page' | |
echo "+++ Set 'Home' to be the frontpage..." | |
wp option update page_on_front $(wp post list --post_type=page --pagename=home --field=ID --format=ids) | |
echo "Install _s theme? (y/n)" | |
read -e underscores | |
if [ "$underscores" == y ] ; then | |
echo "Theme slug: " | |
read -e themeslug | |
echo "Theme name: " | |
read -e themename | |
echo "Author: " | |
read -s themeauthor | |
echo "Author URI: " | |
read -s themeuri | |
wp scaffold _s $themeslug --theme_name="$themename" --author="$author" --author_uri="$themeuri" --activate --sassify | |
fi | |
echo "Install default plugins? (y/n)" | |
read -e plugins | |
if [ "$plugins" == y ] ; then | |
echo "+++ Deleting Akismet and Hello Dolly..." | |
wp plugin delete akismet hello | |
echo "+++ Installing standard plugins..." | |
wp plugin install advanced-custom-fields autoptimize better-wp-security breadcrumb-navxt broken-link-checker cms-tree-page-view custom-post-type-ui ewww-image-optimizer google-analytics-dashboard-for-wp google-captcha google-sitemap-generator gravity-forms-custom-post-types plugincheck query-monitor redirection regenerate-thumbnails simple-local-avatars theme-check wp-fail2ban wp-pagenavi wp-super-cache | |
fi | |
fi | |
echo "Cleaning..." | |
#remove bash script if it exists in this dir | |
[[ -f "wp_cli.sh" ]] && rm "wp_cli.sh" | |
echo "=========================" | |
echo "[Success]: Installation is complete." | |
echo "=========================" | |
else | |
exit | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment