Merge pull request #69 from WordOps/updating-configuration

Updating configuration
This commit is contained in:
VirtuBox
2019-05-02 20:40:51 +02:00
committed by GitHub
34 changed files with 964 additions and 1446 deletions

View File

@@ -51,8 +51,7 @@ script:
- sudo wo site create 1.com --html && sudo wo site create 2.com --php && sudo wo site create 3.com --mysql || sudo tail -n50 /var/log/wo/wordops.log
- sudo wo site update 1.com --wp && sudo wo site update 2.com --php73 && sudo wo site update 3.com --php73 && sudo wo site update 1.com --wpfc && sudo wo site update 1.com --wpsc && sudo wo site update 1.com --wpredis || sudo tail -n50 /var/log/wo/wordops.log
- sudo ls /var/www/
- sudo ls /var/www/22222/htdocs/
- sudo wp --allow-root --info
- sudo wo info || sudo tail -n50 /var/log/wo/wordops.log
- sudo tree -L 2 /etc/nginx
- sudo tree -L 3 /var/www/22222/htdocs/

View File

@@ -8,7 +8,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
---
### v3.9.5 - [Unreleased]
### v3.9.6 - [Unreleased]
### v3.9.5 - 2019-05-02
#### Added
@@ -28,13 +30,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- Support for Netdata on backend : https://server.hostname:22222/netdata/
- New Stacks : composer and netdata
- additional argument for letsencrypt : --hsts
- Theme for adminer
- Clean Theme for adminer
- Credits for tools shipped with WordOps
- Cache exception for Easy Digital Download
- Additional cache exception for Woocommerce
- Additional cache exceptions for Woocommerce
- MySQL monitoring with Netdata
- WordOps-dashboard on 22222
- Extplorer filemanager
- WordOps-dashboard on 22222, can be installed with `wo stack install`
- Extplorer filemanager in WordOps backend
- Enable OSCP Stapling with Let's Encrypt
- Compress database backup with pigz (faster than gzip) before updating sites
- Support for Ubuntu 19.04 (disco) - few php extensions missing
- Support for Raspbian 9 (stretch) - tested on Raspberry Pi 3b+
- backup letsencrypt certificate before upgrade
- directives emergency_restart_threshold & emergency_restart_interval to restart php-fpm in case of failure
- EasyEngine cronjob removal during install
- Kernel tweaks via systctl.conf
- open_basedir on php-fpm process to forbid access with php outside of /var/www & /run/nginx-cache
#### Changed
@@ -42,12 +53,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- letsencrypt validation with webroot folder
- hardened nginx ssl_ecdh_curve
- Update phpredisadmin
- Increase MySQL root password size to 16 characters
- Increase MySQL users password size to 16 characters
- Increase MySQL root password size to 24 characters
- Increase MySQL users password size to 24 characters
- Nginx locations template is the same for php7.2 & 7.3
- backend SSL configuration now stored in /var/www/22222/conf/nginx/ssl.conf
- Install Netdata with static pre-built binaries instead of having to compile it from source
- Nginx updated to new stable release (1.16.0)
- New packages (phpmyadmin, adminer, composer) are not download in /tmp anymore
#### Fixed
@@ -67,6 +79,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- phpredisadmin setup
- --hsts flag with basic html site
- hsts flag on site not secure with letsencrypt
- fix import of previous acme.sh certificate
- fix proxy webroot folder creation
### v3.9.4 - 2019-03-15

View File

@@ -11,10 +11,14 @@
</p>
<p align="center">
<a href="https://travis-ci.org/WordOps/WordOps"><img src="https://travis-ci.org/WordOps/WordOps.svg?branch=master" alt="build"></a>
<a href="https://travis-ci.org/WordOps/WordOps" target="_blank"><img src="https://travis-ci.org/WordOps/WordOps.svg?branch=master" alt="build"></a>
<img src="https://img.shields.io/github/license/wordops/wordops.svg" alt="MIT">
<img src="https://img.shields.io/github/last-commit/wordops/wordops.svg" alt="Commits">
<img alt="GitHub release" src="https://img.shields.io/github/release-pre/wordops/wordops.svg">
<img alt="GitHub release" src="https://img.shields.io/github/release/WordOps/WordOps.svg">
<br><a href="https://www.codacy.com/app/VirtuBox/WordOps?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=WordOps/WordOps&amp;utm_campaign=Badge_Grade"><img src="https://api.codacy.com/project/badge/Grade/fe9100fd2c634de7882ecec17f00a11a"/></a>
<a href="https://twitter.com/WordOps_" target="_blank"><img src="https://img.shields.io/badge/twitter-%40WordOps__-blue.svg?style=flat&logo=twitter" alt="Badge Twitter" /></a>
<a href="https://community.wordops.net/slack" target="_blank"><img src="https://img.shields.io/badge/slack-WordOps-4A154B.svg?style=flat&logo=slack" alt="Badge Slack" /></a>
</p>
<p align="center">
@@ -26,11 +30,9 @@
<a href="#license">License</a>
</p>
<p align="center">
<a href="https://wordops.net"> WordOps site</a> •
<a href="https://docs.wordops.net">Documentation</a> •
<a href="https://community.wordops.net">Community forum</a>
<a href="https://community.wordops.io/slack">Slack</a>
<a href="https://wordops.net" target="_blank"> WordOps.net</a> •
<a href="https://docs.wordops.net" target="_blank">Documentation</a> •
<a href="https://community.wordops.net" target="_blank">Community forum</a>
</p>
---
@@ -52,8 +54,10 @@
- Ubuntu 16.04 LTS (Xenial)
- Ubuntu 18.04 LTS (Bionic)
- Ubuntu 19.04 (Disco)
- Debian 8 (Jessie)
- Debian 9 (Stretch)
- Raspbian 9 (Stretch)
### Ports requirements

View File

@@ -74,7 +74,7 @@ _wo_complete()
# HANDLE EVERYTHING AFTER THE THIRD LEVEL NAMESPACE
"install" | "purge" | "remove" )
COMPREPLY=( $(compgen \
-W "--web --admin --nginx --php --php73 --mysql --wpcli --phpmyadmin --adminer --utils --all --redis --phpredisadmin --composer --netdata --fail2ban" \
-W "--web --admin --nginx --php --php73 --mysql --wpcli --phpmyadmin --adminer --utils --all --redis --phpredisadmin --composer --netdata --fail2ban --dashboard" \
-- $cur) )
;;
"upgrade" )

View File

@@ -5,7 +5,7 @@
.SH SYNOPSIS
wo [ --version | --help | info | stack | site | debug | update | clean | import_slow_log | log | secure | sync | maintenance]
.TP
wo stack [ install | remove | purge | migrate | upgrade] [ --web | --all | --nginx | --php | --php73 | --mysql | --admin | --adminer | --redis | --phpmyadmin | --phpredisadmin | --wpcli | --utils ]
wo stack [ install | remove | purge | migrate | upgrade] [ --web | --all | --nginx | --php | --php73 | --mysql | --admin | --adminer | --redis | --phpmyadmin | --phpredisadmin | --wpcli | --utils | --dashboard | --netdata ]
.TP
wo stack [ status | start | stop | reload | restart ] [--all | --nginx | --php | --php73 |--mysql | --web | --memcached | --redis]
.TP

169
install
View File

@@ -7,10 +7,10 @@
# Copyright (c) 2019 - WordOps
# This script is licensed under M.I.T
# -------------------------------------------------------------------------
# Version 3.9.5 - 2019-04-22
# Version 3.9.5 - 2019-05-02
# -------------------------------------------------------------------------
readonly wo_version_old="2.2.3"
readonly wo_version_new="3.9.4.6"
readonly wo_version_new="3.9.5"
# CONTENTS
# ---
# 1. VARIABLES AND DECLARATIONS
@@ -113,6 +113,7 @@ if [ -z "$wo_branch" ]; then
fi
readonly wo_log_dir=/var/log/wo/
readonly wo_backup_dir=/var/lib/wo-backup/
readonly wo_tmp_dir=/var/lib/wo/tmp
readonly wo_install_log=/var/log/wo/install.log
readonly wo_linux_distro=$(lsb_release -is)
readonly wo_distro_version=$(lsb_release -sc)
@@ -122,6 +123,7 @@ TIME=$(date +"$TIME_FORMAT")
NGINX_BACKUP_FILE="/var/lib/wo-backup/nginx-backup.$TIME.tar.gz"
EE_BACKUP_FILE="/var/lib/wo-backup/ee-backup.$TIME.tar.gz"
WO_BACKUP_FILE="/var/lib/wo-backup/wo-backup.$TIME.tar.gz"
WO_ARCH="$(uname -m)"
if [ -x /usr/local/bin/ee ]; then
ee_migration=1
@@ -133,15 +135,15 @@ fi
# 1 - Checking linux distro
###
if [ -z "$wo_force_install" ]; then
if [ "$wo_linux_distro" != "Ubuntu" ] && [ "$wo_linux_distro" != "Debian" ]; then
wo_lib_echo_fail "WordOps (wo) only supports Ubuntu and Debian at the moment."
if [ "$wo_linux_distro" != "Ubuntu" ] && [ "$wo_linux_distro" != "Debian" ] && [ "$wo_linux_distro" != "Raspbian" ]; then
wo_lib_echo_fail "WordOps (wo) only supports Ubuntu, Debian & Raspbian at the moment."
wo_lib_echo_fail "If you are feeling adventurous, you are free to fork WordOps to support"
wo_lib_echo_fail "other Linux distributions and perhaps even Unix deratives."
exit 100
else
check_wo_linux_distro=$(lsb_release -sc | grep -E "trusty|xenial|bionic|jessie|stretch")
check_wo_linux_distro=$(lsb_release -sc | grep -E "trusty|xenial|bionic|disco|jessie|stretch")
if [ -z "$check_wo_linux_distro" ]; then
wo_lib_echo_fail "WordOps (wo) only supports Ubuntu 14.04/16.04/18.04, Debian 8.x and Debian 9.x"
wo_lib_echo_fail "WordOps (wo) only supports Ubuntu 14.04/16.04/18.04/19.04 LTS, Debian 8.x, Debian 9.x and Raspbian 9.x"
exit 100
fi
fi
@@ -150,23 +152,15 @@ fi
###
# 1 - To prevent errors or unexpected behaviour, create the log and ACL it
###
if [ ! -d "$wo_log_dir" ]; then
if [ ! -d "$wo_log_dir" ] || [ ! -d "$wo_backup_dir" ] || [ ! -d "$wo_tmp_dir" ]; then
wo_lib_echo "Creating WordOps log directory, just a second..."
mkdir -p "$wo_log_dir" || wo_lib_error "Whoops - seems we are unable to create the log directory $wo_log_dir, exit status " $?
wo_lib_echo "Creating WordOps backup, tmp & log directory, just a second..."
mkdir -p "$wo_backup_dir" "$wo_log_dir" "$wo_tmp_dir" || wo_lib_error "Whoops - seems we are unable to create the log directory $wo_log_dir, exit status " $?
# create wordops log files
touch /var/log/wo/{wordops.log,install.log}
chmod -R 700 /var/log/wo || wo_lib_error "Whoops, there was an error setting the permissions on the WordOps log folder, exit status " $?
fi
if [ ! -d "$wo_backup_dir" ]; then
wo_lib_echo "Creating WordOps backup directory, just a second..."
mkdir -p "$wo_backup_dir" || wo_lib_error "Whoops - seems we are unable to create the backup directory $wo_backup_dir, exit status " $?
chmod -R 600 "$wo_backup_dir"
chmod -R 700 "$wo_log_dir" "$wo_backup_dir" "$wo_tmp_dir" || wo_lib_error "Whoops, there was an error setting the permissions on the WordOps log folder, exit status " $?
fi
###
@@ -178,7 +172,7 @@ wo_install_dep() {
if [ "$wo_linux_distro" == "Ubuntu" ]; then
DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confmiss" -o Dpkg::Options::="--force-confold" -y install build-essential curl gzip python3 python3-apt python3-setuptools python3-dev sqlite3 git tar software-properties-common pigz gnupg2 cron ccze rsync tree haveged ufw > /dev/null 2>&1
else
wget -qO /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg
[ -d /etc/apt/trusted.gpg.d ] && { wget -qO /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg; }
DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confmiss" -o Dpkg::Options::="--force-confold" -y install build-essential curl gzip dirmngr sudo python3 python3-apt python3-setuptools python3-dev ca-certificates sqlite3 git tar software-properties-common pigz apt-transport-https gnupg2 cron ccze rsync tree haveged ufw > /dev/null 2>&1
fi
@@ -216,9 +210,6 @@ wo_sync_db() {
# Copy the EasyEngine database
cp /var/lib/ee/ee.db /var/lib/wo/dbase-ee.db
# Set the migration variable for the closing text
migration=1
###
# Clean WO installation
###
@@ -327,9 +318,9 @@ wo_sync_db() {
secure_wo_db() {
# The owner is root
chown -R root:root /var/lib/wo/
chown -R root:root /var/lib/wo
# Only allow access by root, block others
chmod -R 600 /var/lib/wo/
chmod -R 600 /var/lib/wo
}
@@ -357,21 +348,17 @@ wo_update_wp_cli() {
wo_install_acme_sh() {
# check if acme.sh is already installed
if [ ! -d /opt/acme.sh ]; then
if [ ! -x /etc/letsencrypt/acme.sh ]; then
{
# clone the git repository
git clone https://github.com/Neilpang/acme.sh.git /opt/acme.sh -q
if [ -d /opt/acme.sh/.git ]; then
git -C /opt/acme.sh pull origin master
else
git clone https://github.com/Neilpang/acme.sh.git /opt/acme.sh -q
fi
cd /opt/acme.sh || exit 1
# create conf directories
[ ! -d /etc/letsencrypt/config ] && {
mkdir -p /etc/letsencrypt/config
}
[ ! -d /etc/letsencrypt/live ] && {
mkdir -p /etc/letsencrypt/live
}
[ ! -d /etc/letsencrypt/renewal ] && {
mkdir -p /etc/letsencrypt/renewal
}
mkdir -p /etc/letsencrypt/{config,live,renewal}
# install acme.sh
./acme.sh --install \
--home /etc/letsencrypt \
@@ -380,19 +367,13 @@ wo_install_acme_sh() {
# enable auto-upgrade
/etc/letsencrypt/acme.sh --config-home /etc/letsencrypt/config --upgrade --auto-upgrade
# Let's Encrypt .well-known folder setup
if [ ! -d /var/www/html/.well-known/acme-challenge ]; then
mkdir -p /var/www/html/.well-known/acme-challenge
chown -R www-data:www-data /var/www/html /var/www/html/.well-known
chmod 750 /var/www/html /var/www/html/.well-known
else
chmod 750 /var/www/html /var/www/html/.well-known
fi
} >> "$wo_install_log" 2>&1
fi
if [ -d "$HOME/.acme.sh" ]; then
if [ -x "$HOME/.acme.sh/acme.sh" ]; then
{
# backup acme.sh folder
/bin/tar -I pigz -cf /var/lib/wo-backup/acme.sh.tar.gz "$HOME/.acme.sh"
# rsync previous certificates to new acme.sh location
/usr/bin/rsync -rltgoDpz --exclude="account.conf" \
--exclude="acme.sh" \
--exclude="acme.sh.env" \
@@ -400,12 +381,24 @@ wo_install_acme_sh() {
--exclude="dnsapi" \
--exclude="http.header" \
--exclude="ca" \
--del \
"$HOME/.acme.sh/" \
/etc/letsencrypt/renewal/
# remove previous acme.sh folder
rm -rf "$HOME/.acme.sh"
# create acme.sh.env file inlcuded in .bashrc to avoid error when logging in
mkdir -p "$HOME/.acme.sh"
echo '' > "$HOME/.acme.sh/acme.sh.env"
} >> "$wo_install_log" 2>&1
fi
# Let's Encrypt .well-known folder setup
if [ ! -d /var/www/html/.well-known/acme-challenge ]; then
mkdir -p /var/www/html/.well-known/acme-challenge
chown -R www-data:www-data /var/www/html /var/www/html/.well-known
chmod 750 /var/www/html /var/www/html/.well-known
else
chmod 750 /var/www/html /var/www/html/.well-known
fi
}
# Clone Github repository if it doesn't exist
@@ -551,7 +544,7 @@ wo_update_latest() {
if [ -f /etc/ImageMagick/policy.xml ]; then
if [ ! -f /etc/ImageMagick/patch.txt ]; then
echo -e "\t<policy domain="coder" rights="none" pattern="EPHEMERAL" />\n\t<policy domain="coder" rights="none" pattern="URL" />\n\t<policy domain="coder" rights="none" pattern="HTTPS" />\n\t<policy domain="coder" rights="none" pattern="MVG" />\n\t<policy domain="coder" rights="none" pattern="MSL" />" >> /etc/ImageMagick/patch.txt
echo -e "\t<policy domain=\"coder\" rights=\"none\" pattern=\"EPHEMERAL\" />\n\t<policy domain=\"coder\" rights=\"none\" pattern=\"URL\" />\n\t<policy domain=\"coder\" rights=\"none\" pattern=\"HTTPS\" />\n\t<policy domain=\"coder\" rights=\"none\" pattern=\"MVG\" />\n\t<policy domain=\"coder\" rights=\"none\" pattern=\"MSL\" />" >> /etc/ImageMagick/patch.txt
sed -i '/<policymap>/r /etc/ImageMagick/patch.txt' /etc/ImageMagick/policy.xml
fi
fi
@@ -581,10 +574,10 @@ wo_update_latest() {
# Fix Redis-server security issue
# http://redis.io/topics/security
if [ -f /etc/redis/redis.conf ]; then
grep -0 -v "#" /etc/redis/redis.conf | grep 'bind' >> /dev/null 2>&1
CHECK_REDIS_BIND=$(grep -0 -v "#" /etc/redis/redis.conf | grep 'bind' >> /dev/null 2>&1)
if [ "$?" -ne 0 ]; then
sed -i '$ a bind 127.0.0.1' /etc/redis/redis.conf &
if [ -z "$CHECK_REDIS_BIND" ]; then
echo 'bind 127.0.0.1 ::1' >> /etc/redis/redis.conf
service redis-server restart > /dev/null 2>&1
@@ -598,9 +591,9 @@ wo_git_init() {
# Nginx under git version control
[ -d /etc/nginx ] && {
cd /etc/nginx || exit 1
if [ ! -d /etc/nginx/.git ]; then
[ ! -d /etc/nginx/.git ] && {
git init
fi
}
git add -A .
git commit -am "Updated Nginx"
} >> /var/log/wo/install.log 2>&1
@@ -616,36 +609,66 @@ wo_git_init() {
# PHP under git version control
[ -d /etc/php ] && {
cd /etc/php || exit 1
if [ ! -d /etc/php/.git ]; then
[ ! -d /etc/php/.git ] && {
git init
fi
}
git add -A .
git commit -am "Updated PHP"
} >> /var/log/wo/install.log 2>&1
}
wo_backup_ee() {
tar -I pigz -cf "$EE_BACKUP_FILE" /etc/nginx /usr/local/bin/ee /usr/lib/ee/templates /usr/local/lib/python3.6/dist-packages/ee-*.egg /etc/ee /var/lib/ee >> /var/log/wo/install.log 2>&1
/bin/tar -I pigz -cf "$EE_BACKUP_FILE" /etc/nginx /usr/local/bin/ee /usr/lib/ee/templates /usr/local/lib/python3.6/dist-packages/ee-*.egg /etc/ee /var/lib/ee /etc/letsencrypt >> /var/log/wo/install.log 2>&1
}
wo_backup_wo() {
tar -I pigz -cf "$WO_BACKUP_FILE" /etc/nginx/ /usr/local/lib/python3.6/dist-packages/wo-*.egg /etc/wo /var/lib/wo >> /var/log/wo/install.log 2>&1
/bin/tar -I pigz -cf "$WO_BACKUP_FILE" /etc/nginx /usr/local/lib/python3.6/dist-packages/wo-*.egg /etc/wo /var/lib/wo /etc/letsencrypt >> /var/log/wo/install.log 2>&1
}
wo_clean_ee() {
rm -f /usr/local/bin/ee /etc/bash_completion.d/ee_auto.rc /usr/lib/ee/templates /usr/local/lib/python3.6/dist-packages/ee-*.egg /etc/ee /var/lib/ee >> /var/log/wo/install.log 2>&1
}
wo_remove_ee_cron() {
crontab -l | sed '/ee site update --le=renew --all 2> \/dev\/null/d' | crontab -
}
wo_tweak_kernel() {
if [ ! -f /etc/sysctl.d/60-wo-tweaks.conf ]; then
if [ "$WO_ARCH" = "x86_64" ]; then
rm -f /etc/sysctl.d/60-ubuntu-nginx-web-server.conf
wget -qO /etc/sysctl.d/60-wo-tweaks.conf https://raw.githubusercontent.com/WordOps/WordOps/updating-configuration/wo/cli/templates/sysctl.mustache
if [ "$wo_distro_version" = "bionic" ] || [ "$wo_distro_version" = "disco" ]; then
modprobe tcp_bbr && echo 'tcp_bbr' >> /etc/modules-load.d/bbr.conf
echo -e '\nnet.ipv4.tcp_congestion_control = bbr\nnet.ipv4.tcp_notsent_lowat = 16384' >> /etc/sysctl.d/60-wo-tweaks.conf
else
modprobe tcp_htcp && echo 'tcp_htcp' >> /etc/modules-load.d/htcp.conf
echo 'net.ipv4.tcp_congestion_control = htcp' >> /etc/sysctl.d/60-wo-tweaks.conf
fi
fi
LIMIT_CHECK=$(grep "500000" /etc/security/limits.conf)
if [ -z "$LIMIT_CHECK" ]; then
echo -e "* hard nofile 500000\n* soft nofile 500000\nroot hard nofile 500000\nroot soft nofile 500000\n" >> /etc/security/limits.conf
fi
fi
}
###
# 4 - WO MAIN SETUP
###
# 1 - WO already installed
if [ -x /usr/local/bin/wo ]; then
wo -v 2>&1 | grep $wo_version_new
if [[ $? -ne 0 ]]; then
read -p "Update WordOps to $wo_version_new (y/n): " wo_ans
if [ "$wo_ans" = "y" ] || [ "$wo_ans" = "Y" ]; then
if ! {
wo -v 2>&1 | grep $wo_version_new
}; then
echo -e "Update WordOps to $wo_version_new (y/n): " && read -r WO_ANSWER
if [ "$WO_ANSWER" = "y" ] || [ "$WO_ANSWER" = "Y" ]; then
wo_lib_echo "Installing wo dependencies " | tee -ai $wo_install_log
wo_install_dep | tee -ai $wo_install_log
wo_lib_echo "Backing-up WO install" | tee -ai $wo_install_log
@@ -653,14 +676,20 @@ if [ -x /usr/local/bin/wo ]; then
wo_lib_echo "Syncing WO database" | tee -ai $wo_install_log
secure_wo_db | tee -ai $wo_install_log
wo_lib_echo "Installing WordOps " | tee -ai $wo_install_log
wo_install >> wo_install_log 2>&1
if [ -f "$HOME/.gitconfig" ]; then
wo_install >> wo_install_log 2>&1
else
wo_install | tee -ai $wo_install_log
fi
if [ -x "$(command -v nginx)" ]; then
wo_lib_echo "Upgrading Nginx" | tee -ai $wo_install_log
wo_upgrade_nginx | tee -ai $wo_install_log
fi
wo_update_latest | tee -ai $wo_install_log
wo_lib_echo "Installing acme.sh" | tee -ai $wo_install_log
wo_lib_echo "Updating acme.sh" | tee -ai $wo_install_log
wo_install_acme_sh | tee -ai $wo_install_log
wo_lib_echo "Applying Kernel tweaks" | tee -ai $wo_install_log
wo_tweak_kernel | tee -ai $wo_install_log
wo_lib_echo "Running post-install steps " | tee -ai $wo_install_log
wo_git_init | tee -ai $wo_install_log
wo_update_wp_cli | tee -ai $wo_install_log
@@ -673,17 +702,23 @@ if [ -x /usr/local/bin/wo ]; then
else
# 2 - Migration from EEv3
if [ -x /usr/local/bin/ee ]; then
read -p "Migrate from EasyEngine to WordOps (y/n): " wo_ans
if [ "$wo_ans" = "y" ] || [ "$wo_ans" = "Y" ]; then
echo -e "Migrate from EasyEngine to WordOps (y/n): " && read -r WO_ANSWER
if [ "$WO_ANSWER" = "y" ] || [ "$WO_ANSWER" = "Y" ]; then
wo_lib_echo "Installing wo dependencies " | tee -ai $wo_install_log
wo_install_dep | tee -ai $wo_install_log
wo_lib_echo "Backing-up EE install" | tee -ai $wo_install_log
wo_backup_ee | tee -ai $wo_install_log
wo_lib_echo "Removing EasyEngine cronjob" | tee -ai $wo_install_log
wo_remove_ee_cron | tee -ai $wo_install_log
wo_lib_echo "Syncing WO database" | tee -ai $wo_install_log
wo_sync_db | tee -ai $wo_install_log
secure_wo_db | tee -ai $wo_install_log
wo_lib_echo "Installing WordOps " | tee -ai $wo_install_log
wo_install >> wo_install_log 2>&1
if [ -f "$HOME/.gitconfig" ]; then
wo_install >> wo_install_log 2>&1
else
wo_install | tee -ai $wo_install_log
fi
if [ -x "$(command -v nginx)" ]; then
wo_lib_echo "Upgrading Nginx" | tee -ai $wo_install_log
wo_upgrade_nginx | tee -ai $wo_install_log
@@ -691,6 +726,8 @@ else
wo_update_latest | tee -ai $wo_install_log
wo_lib_echo "Installing acme.sh" | tee -ai $wo_install_log
wo_install_acme_sh | tee -ai $wo_install_log
wo_lib_echo "Applying Kernel tweaks" | tee -ai $wo_install_log
wo_tweak_kernel | tee -ai $wo_install_log
wo_lib_echo "Running post-install steps " | tee -ai $wo_install_log
wo_git_init | tee -ai $wo_install_log
wo_update_wp_cli | tee -ai $wo_install_log
@@ -705,6 +742,8 @@ else
wo_install_dep | tee -ai $wo_install_log
wo_lib_echo "Installing WordOps " | tee -ai $wo_install_log
wo_install | tee -ai $wo_install_log
wo_lib_echo "Applying Kernel tweaks" | tee -ai $wo_install_log
wo_tweak_kernel | tee -ai $wo_install_log
wo_lib_echo "Installing acme.sh" | tee -ai $wo_install_log
wo_install_acme_sh | tee -ai $wo_install_log
wo_lib_echo "Running post-install steps " | tee -ai $wo_install_log

View File

@@ -38,7 +38,7 @@ except Exception as e:
print("Your informations will ONLY be stored locally")
wo_user = input("Enter your name: ")
while wo_user is "":
while wo_user == "":
print("Unfortunately, this can't be left blank")
wo_user = input("Enter your name: ")
@@ -57,7 +57,7 @@ if not os.path.isfile('/root/.gitconfig'):
shutil.copy2(os.path.expanduser("~")+'/.gitconfig', '/root/.gitconfig')
setup(name='wo',
version='3.9.4',
version='3.9.5',
description=long_description,
long_description=long_description,
classifiers=[],

File diff suppressed because it is too large Load Diff

View File

@@ -86,7 +86,8 @@ def main():
# if not root...kick out
if not os.geteuid() == 0:
print("\nNon-privileged users cant use WordOps. Switch to root or invoke sudo.\n")
print("\nNon-privileged users cant use WordOps. "
"Switch to root or invoke sudo.\n")
app.close(1)
# Setup the application
@@ -130,5 +131,6 @@ def get_test_app(**kw):
app = WOApp(**kw)
return app
if __name__ == '__main__':
main()

View File

@@ -191,22 +191,22 @@ class WODebugController(CementBaseController):
nc.savef('/etc/nginx/conf.d/upstream.conf')
# Enable xdebug
WOFileUtils.searchreplace(self, "/etc/{0}/mods-available/".format("php/7.2" if (WOVariables.wo_platform_distro == 'ubuntu') else "php/7.2") +
WOFileUtils.searchreplace(self, "/etc/{0}/"
"mods-available/".format("php/7.2") +
"xdebug.ini",
";zend_extension",
"zend_extension")
# Fix slow log is not enabled default in PHP5.6
config = configparser.ConfigParser()
config.read('/etc/{0}/fpm/pool.d/debug.conf'.format(
"php/7.2" if (WOVariables.wo_platform_distro == 'ubuntu') else "php5"))
config['debug']['slowlog'] = '/var/log/{0}/slow.log'.format("php/7.2" if (
WOVariables.wo_platform_distro == 'ubuntu') else "php5")
config.read('/etc/{0}/fpm/pool.d/debug.conf'.format("php/7.2"))
config['debug']['slowlog'] = '/var/log/{0}/slow.log'.format(
"php/7.2")
config['debug']['request_slowlog_timeout'] = '10s'
with open('/etc/{0}/fpm/pool.d/debug.conf'.format("php/7.2" if (WOVariables.wo_platform_distro == 'ubuntu') else "php5"),
with open('/etc/{0}/fpm/pool.d/debug.conf'.format("php/7.2"),
encoding='utf-8', mode='w') as confifile:
Log.debug(self, "Writting debug.conf configuration into "
"/etc/{0}/fpm/pool.d/debug.conf".format("php/7.2" if (WOVariables.wo_platform_distro == 'ubuntu') else "php5"))
"/etc/{0}/fpm/pool.d/debug.conf".format("php/7.2"))
config.write(confifile)
self.trigger_php = True
@@ -214,8 +214,7 @@ class WODebugController(CementBaseController):
else:
Log.info(self, "PHP debug is already enabled")
self.msg = self.msg + ['/var/log/{0}/slow.log'.format("php/7.2" if (
WOVariables.wo_platform_distro == 'ubuntu') else "php5")]
self.msg = self.msg + ['/var/log/{0}/slow.log'.format("php/7.2")]
# PHP global debug stop
elif (self.app.pargs.php == 'off' and not self.app.pargs.site_name):
@@ -231,7 +230,8 @@ class WODebugController(CementBaseController):
nc.savef('/etc/nginx/conf.d/upstream.conf')
# Disable xdebug
WOFileUtils.searchreplace(self, "/etc/{0}/mods-available/".format("php/7.2" if (WOVariables.wo_platform_distro == 'ubuntu') else "php5") +
WOFileUtils.searchreplace(self, "/etc/{0}/"
"mods-available/".format("php/7.2") +
"xdebug.ini",
"zend_extension",
";zend_extension")
@@ -247,43 +247,41 @@ class WODebugController(CementBaseController):
# PHP5-FPM start global debug
if (self.app.pargs.fpm == 'on' and not self.app.pargs.site_name):
if not WOShellExec.cmd_exec(self, "grep \"log_level = debug\" "
"/etc/{0}/fpm/php-fpm.conf".format("php/7.2" if (WOVariables.wo_platform_distro == 'ubuntu') else "php5")):
"/etc/{0}/"
"fpm/php-fpm.conf".format("php/7.2")):
Log.info(self, "Setting up PHP5-FPM log_level = debug")
config = configparser.ConfigParser()
config.read('/etc/{0}/fpm/php-fpm.conf'.format("php/7.2" if (
WOVariables.wo_platform_distro == 'ubuntu') else "php5"))
config.read('/etc/{0}/fpm/php-fpm.conf'.format("php/7.2"))
config.remove_option('global', 'include')
config['global']['log_level'] = 'debug'
config['global']['include'] = '/etc/{0}/fpm/pool.d/*.conf'.format("php/7.2" if (
WOVariables.wo_platform_distro == 'ubuntu') else "php5")
with open('/etc/{0}/fpm/php-fpm.conf'.format("php/7.2" if (WOVariables.wo_platform_distro == 'ubuntu') else "php5"),
config['global']['include'] = '/etc/{0}/fpm/pool.d/*.conf'.format(
"php/7.2")
with open('/etc/{0}/fpm/php-fpm.conf'.format("php/7.2"),
encoding='utf-8', mode='w') as configfile:
Log.debug(self, "Writting php5-FPM configuration into "
"/etc/{0}/fpm/php-fpm.conf".format("php/7.2" if (WOVariables.wo_platform_distro == 'ubuntu') else "php5"))
"/etc/{0}/fpm/php-fpm.conf".format("php/7.2"))
config.write(configfile)
self.trigger_php = True
else:
Log.info(self, "PHP5-FPM log_level = debug already setup")
self.msg = self.msg + ['/var/log/{0}/fpm.log'.format("php/7.2" if (
WOVariables.wo_platform_distro == 'ubuntu') else "php5")]
self.msg = self.msg + ['/var/log/{0}/fpm.log'.format("php/7.2")]
# PHP5-FPM stop global debug
elif (self.app.pargs.fpm == 'off' and not self.app.pargs.site_name):
if WOShellExec.cmd_exec(self, "grep \"log_level = debug\" "
"/etc/{0}/fpm/php-fpm.conf".format("php/7.2" if (WOVariables.wo_platform_distro == 'ubuntu') else "php5")):
"/etc/{0}/fpm/php-fpm.conf".format("php/7.2")):
Log.info(self, "Disabling PHP5-FPM log_level = debug")
config = configparser.ConfigParser()
config.read('/etc/{0}/fpm/php-fpm.conf'.format("php/7.2" if (
WOVariables.wo_platform_distro == 'ubuntu') else "php5"))
config.read('/etc/{0}/fpm/php-fpm.conf'.format("php/7.2"))
config.remove_option('global', 'include')
config['global']['log_level'] = 'notice'
config['global']['include'] = '/etc/{0}/fpm/pool.d/*.conf'.format("php/7.2" if (
WOVariables.wo_platform_distro == 'ubuntu') else "php5")
with open('/etc/{0}/fpm/php-fpm.conf'.format("php/7.2" if (WOVariables.wo_platform_distro == 'ubuntu') else "php5"),
config['global']['include'] = '/etc/{0}/fpm/pool.d/*.conf'.format(
"php/7.2")
with open('/etc/{0}/fpm/php-fpm.conf'.format("php/7.2"),
encoding='utf-8', mode='w') as configfile:
Log.debug(self, "writting php5 configuration into "
"/etc/{0}/fpm/php-fpm.conf".format("php/7.2" if (WOVariables.wo_platform_distro == 'ubuntu') else "php5"))
"/etc/{0}/fpm/php-fpm.conf".format("php/7.2"))
config.write(configfile)
self.trigger_php = True
@@ -335,7 +333,8 @@ class WODebugController(CementBaseController):
# PHP global debug stop
elif (self.app.pargs.php73 == 'off' and not self.app.pargs.site_name):
if WOShellExec.cmd_exec(self, " sed -n \"/upstream php72 {/,/}/p\" "
if WOShellExec.cmd_exec(self, " sed -n \"/upstream "
"php72 {/,/}/p\" "
"/etc/nginx/conf.d/upstream.conf "
"| grep 9172"):
Log.info(self, "Disabling PHP 7.2 debug")
@@ -399,7 +398,8 @@ class WODebugController(CementBaseController):
config.write(configfile)
self.trigger_php = True
else:
Log.info(self, "PHP7.3-FPM log_level = debug already disabled")
Log.info(self, "PHP7.3-FPM log_level "
"= debug already disabled")
@expose(hide=True)
def debug_mysql(self):
@@ -536,8 +536,8 @@ class WODebugController(CementBaseController):
self.msg = self.msg + ['/var/log/nginx/*.error.log']
# Stop Nginx rewrite debug globally
elif (self.app.pargs.rewrite == 'off'
and not self.app.pargs.site_name):
elif (self.app.pargs.rewrite == 'off' and
not self.app.pargs.site_name):
if WOShellExec.cmd_exec(self, "grep \"rewrite_log on;\" "
"/etc/nginx/nginx.conf"):
Log.info(self, "Disabling Nginx rewrite logs")
@@ -644,10 +644,10 @@ class WODebugController(CementBaseController):
(not self.app.pargs.fpm73) and (not self.app.pargs.mysql) and
(not self.app.pargs.wp) and (not self.app.pargs.rewrite) and
(not self.app.pargs.all) and (not self.app.pargs.site_name) and
(not self.app.pargs.import_slow_log)
and (not self.app.pargs.interval)):
(not self.app.pargs.import_slow_log) and
(not self.app.pargs.interval)):
if self.app.pargs.stop or self.app.pargs.start:
print("--start/stop option is deprecated since ee v3.0.5")
print("--start/stop option is deprecated since wo v3.0.5")
self.app.args.print_help()
else:
self.app.args.print_help()
@@ -778,8 +778,8 @@ class WODebugController(CementBaseController):
if len(self.msg) > 0:
if not self.app.pargs.interactive:
disp_msg = ' '.join(self.msg)
Log.info(self, "Use following command to check debug logs:\n"
+ Log.ENDC + "tail -f {0}".format(disp_msg))
Log.info(self, "Use following command to check debug logs:\n" +
Log.ENDC + "tail -f {0}".format(disp_msg))
else:
signal.signal(signal.SIGINT, self.signal_handler)
watch_list = []
@@ -797,18 +797,18 @@ class WODebugController(CementBaseController):
# Get Anemometer user name and password
Log.info(self, "Importing MySQL slow log to Anemometer")
host = os.popen("grep -e \"\'host\'\" {0}22222/htdocs/"
.format(WOVariables.wo_webroot)
+ "db/anemometer/conf/config.inc.php "
.format(WOVariables.wo_webroot) +
"db/anemometer/conf/config.inc.php "
"| head -1 | cut -d\\\' -f4 | "
"tr -d '\n'").read()
user = os.popen("grep -e \"\'user\'\" {0}22222/htdocs/"
.format(WOVariables.wo_webroot)
+ "db/anemometer/conf/config.inc.php "
.format(WOVariables.wo_webroot) +
"db/anemometer/conf/config.inc.php "
"| head -1 | cut -d\\\' -f4 | "
"tr -d '\n'").read()
password = os.popen("grep -e \"\'password\'\" {0}22222/"
.format(WOVariables.wo_webroot)
+ "htdocs/db/anemometer/conf"
.format(WOVariables.wo_webroot) +
"htdocs/db/anemometer/conf"
"/config.inc.php "
"| head -1 | cut -d\\\' -f4 | "
"tr -d '\n'").read()
@@ -836,9 +836,9 @@ class WODebugController(CementBaseController):
" so not imported slow logs")
else:
Log.error(self, "Anemometer is not installed." +
Log.ENDC + "\n Install Anemometer with:"
+ Log.BOLD + "\n `wo stack install --utils`"
+ Log.ENDC)
Log.ENDC + "\n Install Anemometer with:" +
Log.BOLD + "\n `wo stack install --utils`" +
Log.ENDC)
def load(app):

View File

@@ -41,7 +41,8 @@ class WOInfoController(CementBaseController):
@expose(hide=True)
def info_nginx(self):
"""Display Nginx information"""
version = os.popen("nginx -v 2>&1 | awk -F '/' '{print $2}' | "
version = os.popen("/usr/sbin/nginx -v 2>&1 | "
"awk -F '/' '{print $2}' | "
"awk -F ' ' '{print $1}' | tr '\n' ' '").read()
allow = os.popen("grep ^allow /etc/nginx/common/acl.conf | "
"cut -d' ' -f2 | cut -d';' -f1 | tr '\n' ' '").read()
@@ -66,7 +67,8 @@ class WOInfoController(CementBaseController):
@expose(hide=True)
def info_php(self):
"""Display PHP information"""
version = os.popen("php7.2 -v 2>/dev/null | head -n1 | cut -d' ' -f2 |"
version = os.popen("/usr/bin/php7.2 -v 2>/dev/null | "
"head -n1 | cut -d' ' -f2 |"
" cut -d'+' -f1 | tr -d '\n'").read
config = configparser.ConfigParser()
config.read('/etc/{0}/fpm/php.ini'.format("php/7.2"))
@@ -140,7 +142,8 @@ class WOInfoController(CementBaseController):
@expose(hide=True)
def info_php73(self):
"""Display PHP information"""
version = os.popen("php7.3 -v 2>/dev/null | head -n1 | cut -d' ' -f2 |"
version = os.popen("/usr/bin/php7.3 -v 2>/dev/null | "
"head -n1 | cut -d' ' -f2 |"
" cut -d'+' -f1 | tr -d '\n'").read
config = configparser.ConfigParser()
config.read('/etc/php/7.3/fpm/php.ini')
@@ -214,23 +217,29 @@ class WOInfoController(CementBaseController):
@expose(hide=True)
def info_mysql(self):
"""Display MySQL information"""
version = os.popen("mysql -V | awk '{print($5)}' | cut -d ',' "
version = os.popen("/usr/bin/mysql -V | awk '{print($5)}' | "
"cut -d ',' "
"-f1 | tr -d '\n'").read()
host = "localhost"
port = os.popen("mysql -e \"show variables\" | grep ^port | awk "
port = os.popen("/usr/bin/mysql -e \"show variables\" | "
"grep ^port | awk "
"'{print($2)}' | tr -d '\n'").read()
wait_timeout = os.popen("mysql -e \"show variables\" | grep "
wait_timeout = os.popen("/usr/bin/mysql -e \"show variables\" | grep "
"^wait_timeout | awk '{print($2)}' | "
"tr -d '\n'").read()
interactive_timeout = os.popen("mysql -e \"show variables\" | grep "
interactive_timeout = os.popen("/usr/bin/mysql -e "
"\"show variables\" | grep "
"^interactive_timeout | awk "
"'{print($2)}' | tr -d '\n'").read()
max_used_connections = os.popen("mysql -e \"show global status\" | "
max_used_connections = os.popen("/usr/bin/mysql -e "
"\"show global status\" | "
"grep Max_used_connections | awk "
"'{print($2)}' | tr -d '\n'").read()
datadir = os.popen("mysql -e \"show variables\" | grep datadir | awk"
datadir = os.popen("/usr/bin/mysql -e \"show variables\" | "
"grep datadir | awk"
" '{print($2)}' | tr -d '\n'").read()
socket = os.popen("mysql -e \"show variables\" | grep \"^socket\" | "
socket = os.popen("/usr/bin/mysql -e \"show variables\" | "
"grep \"^socket\" | "
"awk '{print($2)}' | tr -d '\n'").read()
data = dict(version=version, host=host, port=port,
wait_timeout=wait_timeout,

View File

@@ -444,7 +444,8 @@ class WOLogMailController(CementBaseController):
(['--nginx'],
dict(help='Mail Nginx Error logs file', action='store_true')),
(['--php'],
dict(help='Mail PHP 7.2 Error logs file', action='store_true')),
dict(help='Mail PHP 7.2 Error logs file',
action='store_true')),
(['--fpm'],
dict(help='Mail PHP 7.2-fpm slow logs file',
action='store_true')),

View File

@@ -147,10 +147,6 @@ class WOSiteController(CementBaseController):
wo_db_user = siteinfo.db_user
wo_db_pass = siteinfo.db_password
wo_db_host = siteinfo.db_host
if sitetype == "proxy":
access_log = "/var/log/nginx/{0}.access.log".format(wo_domain)
error_log = "/var/log/nginx/{0}.error.log".format(wo_domain)
wo_site_webroot = ''
php_version = siteinfo.php_version
@@ -408,12 +404,14 @@ class WOSiteCreateController(CementBaseController):
"{0} already exists".format(wo_domain))
if stype == 'proxy':
data['site_name'] = wo_domain
data['www_domain'] = wo_www_domain
data = dict(site_name=wo_domain, www_domain=wo_www_domain,
static=True, basic=False, php73=False, wp=False,
wpfc=False, wpsc=False, multisite=False,
wpsubdir=False, webroot=wo_site_webroot)
data['proxy'] = True
data['host'] = host
data['port'] = port
wo_site_webroot = WOVariables.wo_webroot + wo_domain
data['basic'] = True
if self.app.pargs.php73:
data = dict(site_name=wo_domain, www_domain=wo_www_domain,
@@ -587,10 +585,35 @@ class WOSiteCreateController(CementBaseController):
"and please try again")
# Setup WordPress if Wordpress site
if data['wp']:
if (data['wp'] and (not self.app.pargs.vhostonly)):
try:
wo_wp_creds = setupwordpress(self, data)
# Add database information for site into database
updateSiteInfo(self, wo_domain,
db_name=data['wo_db_name'],
db_user=data['wo_db_user'],
db_password=data['wo_db_pass'],
db_host=data['wo_db_host'])
except SiteError as e:
# call cleanup actions on failure
Log.debug(self, str(e))
Log.info(self, Log.FAIL +
"There was a serious error encountered...")
Log.info(self, Log.FAIL + "Cleaning up afterwards...")
doCleanupAction(self, domain=wo_domain,
webroot=data['webroot'],
dbname=data['wo_db_name'],
dbuser=data['wo_db_user'],
dbhost=data['wo_mysql_grant_host'])
deleteSiteInfo(self, wo_domain)
Log.error(self, "Check the log for details: "
"`tail /var/log/wo/wordops.log` "
"and please try again")
if (data['wp'] and (self.app.pargs.vhostonly)):
try:
data = setupdatabase(self, data)
# Add database information for site into database
updateSiteInfo(self, wo_domain, db_name=data['wo_db_name'],
db_user=data['wo_db_user'],
db_password=data['wo_db_pass'],
@@ -605,7 +628,37 @@ class WOSiteCreateController(CementBaseController):
webroot=data['webroot'],
dbname=data['wo_db_name'],
dbuser=data['wo_db_user'],
dbhost=data['wo_mysql_grant_host'])
dbhost=data['wo_db_host'])
deleteSiteInfo(self, wo_domain)
Log.error(self, "Check the log for details: "
"`tail /var/log/wo/wordops.log` "
"and please try again")
try:
wodbconfig = open("{0}/wo-config.php"
.format(wo_site_webroot),
encoding='utf-8', mode='w')
wodbconfig.write("<?php \ndefine('DB_NAME', '{0}');"
"\ndefine('DB_USER', '{1}'); "
"\ndefine('DB_PASSWORD', '{2}');"
"\ndefine('DB_HOST', '{3}');\n?>"
.format(data['wo_db_name'],
data['wo_db_user'],
data['wo_db_pass'],
data['wo_db_host']))
wodbconfig.close()
except IOError as e:
Log.debug(self, str(e))
Log.debug(self, "Error occured while generating "
"wo-config.php")
Log.info(self, Log.FAIL +
"There was a serious error encountered...")
Log.info(self, Log.FAIL + "Cleaning up afterwards...")
doCleanupAction(self, domain=wo_domain,
webroot=data['webroot'],
dbname=data['wo_db_name'],
dbuser=data['wo_db_user'],
dbhost=data['wo_db_host'])
deleteSiteInfo(self, wo_domain)
Log.error(self, "Check the log for details: "
"`tail /var/log/wo/wordops.log` "
@@ -658,7 +711,7 @@ class WOSiteCreateController(CementBaseController):
for msg in wo_auth:
Log.info(self, Log.ENDC + msg, log=False)
if data['wp']:
if data['wp'] and (not self.app.pargs.vhostonly):
Log.info(self, Log.ENDC + "WordPress admin user :"
" {0}".format(wo_wp_creds['wp_user']), log=False)
Log.info(self, Log.ENDC + "WordPress admin user password : {0}"

View File

@@ -49,8 +49,7 @@ def pre_run_checks(self):
def check_domain_exists(self, domain):
if getSiteInfo(self, domain):
return True
else:
return False
return False
def setupdomain(self, data):
@@ -60,7 +59,7 @@ def setupdomain(self, data):
# print (key, value)
wo_domain_name = data['site_name']
wo_site_webroot = data['webroot'] if 'webroot' in data.keys() else ''
wo_site_webroot = data['webroot']
# Check if nginx configuration already exists
# if os.path.isfile('/etc/nginx/sites-available/{0}'
@@ -313,10 +312,12 @@ def setupwordpress(self, data):
"--dbname=\'{0}\' --dbprefix=\'{1}\' "
"--dbuser=\'{2}\' --dbhost=\'{3}\' "
.format(data['wo_db_name'], wo_wp_prefix,
data['wo_db_user'], data['wo_db_host']
data['wo_db_user'],
data['wo_db_host']
) +
"--dbpass=\'{0}\' "
"--extra-php<<PHP \n {1} {redissalt}\nPHP\""
"--extra-php<<PHP \n"
"{1} {redissalt}\nPHP\""
.format(data['wo_db_pass'],
"\n\ndefine(\'WP_DEBUG\', false);",
redissalt="\n\ndefine( \'WP_CACHE_KEY_SALT\', \'{0}:\' );"
@@ -697,7 +698,9 @@ def sitebackup(self, data):
if data['wo_db_name']:
Log.info(self, 'Backing up database \t\t', end='')
try:
if not WOShellExec.cmd_exec(self, "mysqldump {0} > {1}/{0}.sql"
if not WOShellExec.cmd_exec(self, "mysqldump --single-transaction "
"{0} | pigz -9 -p\"$(nproc)\" "
"> {1}/{0}.gz"
.format(data['wo_db_name'],
backup_path)):
Log.info(self,
@@ -1147,7 +1150,7 @@ def detSitePar(opts):
def generate_random():
wo_random10 = (''.join(random.sample(string.ascii_uppercase +
string.ascii_lowercase +
string.digits, 16)))
string.digits, 24)))
return wo_random10
@@ -1200,9 +1203,8 @@ def deleteWebRoot(self, webroot):
Log.debug(self, "Removing {0}".format(webroot))
WOFileUtils.rm(self, webroot)
return True
else:
Log.debug(self, "{0} does not exist".format(webroot))
return False
Log.debug(self, "{0} does not exist".format(webroot))
return False
def removeNginxConf(self, domain):
@@ -1219,6 +1221,19 @@ def removeNginxConf(self, domain):
.format(domain))
def removeAcmeConf(self, domain):
if os.path.isdir('/etc/letsencrypt/renewal/{0}_ecc'
.format(domain)):
Log.debug(self, "Removing Acme configuration")
WOFileUtils.rm(self, '/etc/letsencrypt/renewal/{0}_ecc'
.format(domain))
WOFileUtils.rm(self, '/etc/letsencrypt/live/{0}'
.format(domain))
WOGit.add(self, ["/etc/letsencrypt"],
msg="Deleted {0} "
.format(domain))
def doCleanupAction(self, domain='', webroot='', dbname='', dbuser='',
dbhost=''):
"""
@@ -1230,6 +1245,10 @@ def doCleanupAction(self, domain='', webroot='', dbname='', dbuser='',
if os.path.isfile('/etc/nginx/sites-available/{0}'
.format(domain)):
removeNginxConf(self, domain)
if os.path.isdir('/etc/letsencrypt/renewal/{0}_ecc'
.format(domain)):
removeAcmeConf(self, domain)
if webroot:
deleteWebRoot(self, webroot)
@@ -1287,6 +1306,7 @@ def setupLetsEncrypt(self, wo_domain_name):
"--key-file {0}/{1}/key.pem "
"--fullchain-file "
"{0}/{1}/fullchain.pem "
"--ca-file {0}/{1}/ca.pem "
"--reloadcmd "
"\"service nginx restart\" "
.format(WOVariables.wo_ssl_live,
@@ -1300,9 +1320,10 @@ def setupLetsEncrypt(self, wo_domain_name):
encoding='utf-8', mode='w')
sslconf.write("listen 443 ssl http2;\n"
"listen [::]:443 ssl http2;\n"
"ssl on;\n"
"ssl_certificate {0}/{1}/fullchain.pem;\n"
"ssl_certificate_key {0}/{1}/key.pem;\n"
"ssl_trusted_certificate {0}/{1}/ca.pem;\n"
"ssl_stapling_verify on;\n"
.format(WOVariables.wo_ssl_live, wo_domain_name))
sslconf.close()
updateSiteInfo(self, wo_domain_name, ssl=True)
@@ -1368,6 +1389,7 @@ def setupLetsEncryptSubdomain(self, wo_domain_name):
"--key-file {0}/{1}/key.pem "
"--fullchain-file "
"{0}/{1}/fullchain.pem "
"--ca-file {0}/{1}/ca.pem "
"--reloadcmd "
"\"service nginx restart\" "
.format(WOVariables.wo_ssl_live,
@@ -1382,9 +1404,10 @@ def setupLetsEncryptSubdomain(self, wo_domain_name):
encoding='utf-8', mode='w')
sslconf.write("listen 443 ssl http2;\n"
"listen [::]:443 ssl http2;\n"
"ssl on;\n"
"ssl_certificate {0}/{1}/fullchain.pem;\n"
"ssl_certificate_key {0}/{1}/key.pem;\n"
"ssl_trusted_certificate {0}/{1}/ca.pem;\n"
"ssl_stapling_verify on;\n"
.format(WOVariables.wo_ssl_live, wo_domain_name))
sslconf.close()
updateSiteInfo(self, wo_domain_name, ssl=True)
@@ -1548,6 +1571,7 @@ def archivedCertificateHandle(self, domain):
"--key-file {0}/{1}/key.pem "
"--fullchain-file "
"{0}/{1}/fullchain.pem "
"--ca-file {0}/{1}/ca.pem "
"--reloadcmd "
"\"service nginx restart\" "
.format(WOVariables.wo_ssl_live,
@@ -1567,10 +1591,11 @@ def archivedCertificateHandle(self, domain):
encoding='utf-8', mode='w')
sslconf.write("listen 443 ssl http2;\n"
"listen [::]:443 ssl http2;\n"
"ssl on;\n"
"ssl_certificate "
"{0}/{1}/fullchain.pem;\n"
"ssl_certificate_key {0}/{1}/key.pem;\n"
"ssl_trusted_certificate {0}/{1}/ca.pem;\n"
"ssl_stapling_verify on;\n"
.format(WOVariables.wo_ssl_live, domain))
sslconf.close()
@@ -1614,6 +1639,8 @@ def archivedCertificateHandle(self, domain):
"--key-file {0}/{1}/key.pem "
"--fullchain-file "
"{0}/{1}/fullchain.pem "
"ssl_trusted_certificate "
"{0}/{1}/ca.pem;\n"
"--reloadcmd "
"\"service nginx restart\" "
.format(WOVariables.wo_ssl_live, domain))
@@ -1634,4 +1661,4 @@ def archivedCertificateHandle(self, domain):
'/var/www/{0}/conf/nginx/ssl.conf.bak'
.format(domain))
return ssl
return ssl

View File

@@ -16,11 +16,9 @@ from wo.core.git import WOGit
from wo.core.checkfqdn import check_fqdn
from pynginxconfig import NginxConfig
from wo.core.services import WOService
from wo.core.variables import WOVariables
import random
import string
import configparser
import time
import shutil
import os
import pwd
@@ -72,6 +70,8 @@ class WOStackController(CementBaseController):
dict(help='Install WordOps dashboard', action='store_true')),
(['--adminer'],
dict(help='Install Adminer stack', action='store_true')),
(['--fail2ban'],
dict(help='Install Fail2ban stack', action='store_true')),
(['--utils'],
dict(help='Install Utils stack', action='store_true')),
(['--redis'],
@@ -91,50 +91,85 @@ class WOStackController(CementBaseController):
"""Pre settings to do before installation packages"""
if set(WOVariables.wo_mysql).issubset(set(apt_packages)):
Log.info(self, "Adding repository for MySQL, please wait...")
mysql_pref = ("Package: *\nPin: origin "
"sfo1.mirrors.digitalocean.com"
"\nPin-Priority: 1000\n")
with open('/etc/apt/preferences.d/'
'MariaDB.pref', 'w') as mysql_pref_file:
mysql_pref_file.write(mysql_pref)
WORepo.add(self, repo_url=WOVariables.wo_mysql_repo)
Log.debug(self, 'Adding key for {0}'
.format(WOVariables.wo_mysql_repo))
WORepo.add_key(self, '0xcbcb082a1bb943db',
keyserver="keyserver.ubuntu.com")
WORepo.add_key(self, '0xF1656F24C74CD1D8',
keyserver="keyserver.ubuntu.com")
chars = ''.join(random.sample(string.ascii_letters, 16))
Log.debug(self, "Pre-seeding MySQL")
Log.debug(self, "echo \"mariadb-server-10.3 "
"mysql-server/root_password "
"password \" | "
"debconf-set-selections")
try:
WOShellExec.cmd_exec(self, "echo \"mariadb-server-10.3 "
"mysql-server/root_password "
"password {chars}\" | "
"debconf-set-selections"
.format(chars=chars),
log=False)
except CommandExecutionError as e:
Log.error("Failed to initialize MySQL package")
# add mariadb repository excepted on raspbian and ubuntu 19.04
if ((not WOVariables.wo_platform_codename == 'disco') and
(not WOVariables.wo_platform_distro == 'raspbian')):
Log.info(self, "Adding repository for MySQL, please wait...")
mysql_pref = ("Package: *\nPin: origin "
"sfo1.mirrors.digitalocean.com"
"\nPin-Priority: 1000\n")
with open('/etc/apt/preferences.d/'
'MariaDB.pref', 'w') as mysql_pref_file:
mysql_pref_file.write(mysql_pref)
WORepo.add(self, repo_url=WOVariables.wo_mysql_repo)
Log.debug(self, 'Adding key for {0}'
.format(WOVariables.wo_mysql_repo))
WORepo.add_key(self, '0xcbcb082a1bb943db',
keyserver="keyserver.ubuntu.com")
WORepo.add_key(self, '0xF1656F24C74CD1D8',
keyserver="keyserver.ubuntu.com")
# generate random 24 characters root password
chars = ''.join(random.sample(string.ascii_letters, 24))
# configure MySQL non-interactive install
if (not WOVariables.wo_platform_distro == 'raspbian'):
Log.debug(self, "Pre-seeding MySQL")
Log.debug(self, "echo \"mariadb-server-10.3 "
"mysql-server/root_password "
"password \" | "
"debconf-set-selections")
try:
WOShellExec.cmd_exec(self, "echo \"mariadb-server-10.3 "
"mysql-server/root_password "
"password {chars}\" | "
"debconf-set-selections"
.format(chars=chars),
log=False)
except CommandExecutionError as e:
Log.error("Failed to initialize MySQL package")
Log.debug(self, "echo \"mariadb-server-10.3 "
"mysql-server/root_password_again "
"password \" | "
"debconf-set-selections")
try:
WOShellExec.cmd_exec(self, "echo \"mariadb-server-10.3 "
"mysql-server/root_password_again "
"password {chars}\" | "
"debconf-set-selections"
.format(chars=chars),
log=False)
except CommandExecutionError as e:
Log.error("Failed to initialize MySQL package")
Log.debug(self, "echo \"mariadb-server-10.3 "
"mysql-server/root_password_again "
"password \" | "
"debconf-set-selections")
try:
WOShellExec.cmd_exec(self, "echo \"mariadb-server-10.3 "
"mysql-server/root_password_again "
"password {chars}\" | "
"debconf-set-selections"
.format(chars=chars),
log=False)
except CommandExecutionError as e:
Log.error("Failed to initialize MySQL package")
else:
Log.debug(self, "Pre-seeding MySQL")
Log.debug(self, "echo \"mariadb-server-10.1 "
"mysql-server/root_password "
"password \" | "
"debconf-set-selections")
try:
WOShellExec.cmd_exec(self, "echo \"mariadb-server-10.1 "
"mysql-server/root_password "
"password {chars}\" | "
"debconf-set-selections"
.format(chars=chars),
log=False)
except CommandExecutionError as e:
Log.error("Failed to initialize MySQL package")
Log.debug(self, "echo \"mariadb-server-10.1 "
"mysql-server/root_password_again "
"password \" | "
"debconf-set-selections")
try:
WOShellExec.cmd_exec(self, "echo \"mariadb-server-10.1 "
"mysql-server/root_password_again "
"password {chars}\" | "
"debconf-set-selections"
.format(chars=chars),
log=False)
except CommandExecutionError as e:
Log.error("Failed to initialize MySQL package")
# generate my.cnf root credentials
mysql_config = """
[client]
user = root
@@ -151,12 +186,14 @@ class WOStackController(CementBaseController):
Log.debug(self, 'Setting my.cnf permission')
WOFileUtils.chmod(self, "/etc/mysql/conf.d/my.cnf", 0o600)
# add nginx repository
if set(WOVariables.wo_nginx).issubset(set(apt_packages)):
Log.info(self, "Adding repository for NGINX, please wait...")
WORepo.add(self, repo_url=WOVariables.wo_nginx_repo)
Log.debug(self, 'Adding repository for Nginx')
WORepo.add_key(self, WOVariables.wo_nginx_key)
# add php repository
if (set(WOVariables.wo_php73).issubset(set(apt_packages)) or
set(WOVariables.wo_php).issubset(set(apt_packages))):
if (WOVariables.wo_platform_distro == 'ubuntu'):
@@ -170,7 +207,7 @@ class WOStackController(CementBaseController):
WORepo.add(self, repo_url=WOVariables.wo_php_repo)
Log.debug(self, 'Adding deb.sury GPG key')
WORepo.add_key(self, WOVariables.wo_php_key)
# add redis repository
if set(WOVariables.wo_redis).issubset(set(apt_packages)):
Log.info(self, "Adding repository for Redis, please wait...")
if WOVariables.wo_platform_distro == 'ubuntu':
@@ -182,7 +219,7 @@ class WOStackController(CementBaseController):
@expose(hide=True)
def post_pref(self, apt_packages, packages):
"""Post activity after installation of packages"""
if len(apt_packages):
if (apt_packages):
if set(WOVariables.wo_nginx).issubset(set(apt_packages)):
if set(["nginx"]).issubset(set(apt_packages)):
@@ -377,10 +414,12 @@ class WOStackController(CementBaseController):
self.app.render((data), 'locations.mustache',
out=wo_nginx)
wo_nginx.close()
if not os.path.isfile("/etc/nginx/common/release"):
with open("/etc/nginx/common/release",
"a") as release_file:
release_file.write("v3.9.5")
release_file.write("v{0}"
.format(WOVariables.wo_version))
release_file.close()
# Nginx-Plus does not have nginx
@@ -640,7 +679,7 @@ class WOStackController(CementBaseController):
"/var/run/php/php73-fpm.sock;\n}\n"
"upstream debug73 {\nserver "
"127.0.0.1:9173;\n}\n")
# create nginx configuration for redis
if set(WOVariables.wo_redis).issubset(set(apt_packages)):
if (os.path.isfile("/etc/nginx/nginx.conf") and
not os.path.isfile("/etc/nginx/common/"
@@ -748,6 +787,12 @@ class WOStackController(CementBaseController):
"/etc/php/7.2/fpm/pool.d/www.conf")
config.write(configfile)
with open("/etc/php/7.2/fpm/pool.d/www.conf",
encoding='utf-8', mode='a') as myfile:
myfile.write("\nphp_admin_value[open_basedir] "
"= \"/var/www/:/usr/share/php/:"
"/tmp/:/var/run/nginx-cache/\"\n")
# Generate /etc/php/7.2/fpm/pool.d/www-two.conf
WOFileUtils.copyfile(self, "/etc/php/7.2/fpm/pool.d/www.conf",
"/etc/php/7.2/fpm/pool.d/www-two.conf")
@@ -903,6 +948,12 @@ class WOStackController(CementBaseController):
"/etc/php/7.3/fpm/pool.d/www.conf")
config.write(configfile)
with open("/etc/php/7.3/fpm/pool.d/www.conf",
encoding='utf-8', mode='a') as myfile:
myfile.write("\nphp_admin_value[open_basedir] "
"= \"/var/www/:/usr/share/php/:"
"/tmp/:/var/run/nginx-cache/\"\n")
# Generate /etc/php/7.3/fpm/pool.d/www-two.conf
WOFileUtils.copyfile(self, "/etc/php/7.3/fpm/pool.d/www.conf",
"/etc/php/7.3/fpm/pool.d/www-two.conf")
@@ -990,6 +1041,7 @@ class WOStackController(CementBaseController):
WOGit.add(self, ["/etc/php"], msg="Adding PHP into Git")
WOService.restart_service(self, 'php7.3-fpm')
# create mysql config if it doesn't exist
if set(WOVariables.wo_mysql).issubset(set(apt_packages)):
if not os.path.isfile("/etc/mysql/my.cnf"):
config = ("[mysqld]\nwait_timeout = 30\n"
@@ -1015,17 +1067,36 @@ class WOStackController(CementBaseController):
WOGit.add(self, ["/etc/mysql"], msg="Adding MySQL into Git")
WOService.reload_service(self, 'mysql')
if len(packages):
# create fail2ban configuration files
if set(WOVariables.wo_fail2ban).issubset(set(apt_packages)):
if not os.path.isfile("/etc/fail2ban/jail.d/custom.conf"):
data = dict()
Log.debug(self, "Setting up fail2ban jails configuration")
wo_fail2ban = open('/etc/fail2ban/jail.d/custom.conf',
encoding='utf-8', mode='w')
self.app.render((data), 'fail2ban.mustache',
out=wo_fail2ban)
wo_fail2ban.close()
Log.debug(self, "Setting up fail2ban wp filter")
wo_fail2ban = open('/etc/fail2ban/filter.d/wo-wordpress.conf',
encoding='utf-8', mode='w')
self.app.render((data), 'fail2ban-wp.mustache',
out=wo_fail2ban)
wo_fail2ban.close()
if (packages):
if any('/usr/local/bin/wp' == x[1] for x in packages):
Log.debug(self, "Setting Privileges"
" to /usr/local/bin/wp file ")
WOFileUtils.chmod(self, "/usr/local/bin/wp", 0o775)
if any('/tmp/pma.tar.gz' == x[1]
if any('/var/lib/wo/tmp/pma.tar.gz' == x[1]
for x in packages):
WOExtract.extract(self, '/tmp/pma.tar.gz', '/tmp/')
Log.debug(self, 'Extracting file /tmp/pma.tar.gz to '
'location /tmp/')
WOExtract.extract(
self, '/var/lib/wo/tmp/pma.tar.gz', '/var/lib/wo/tmp/')
Log.debug(self, 'Extracting file /var/lib/wo/tmp/pma.tar.gz to '
'location /var/lib/wo/tmp/')
if not os.path.exists('{0}22222/htdocs/db'
.format(WOVariables.wo_webroot)):
Log.debug(self, "Creating new directory "
@@ -1035,7 +1106,7 @@ class WOStackController(CementBaseController):
.format(WOVariables.wo_webroot))
if not os.path.exists('{0}22222/htdocs/db/pma/'
.format(WOVariables.wo_webroot)):
shutil.move('/tmp/phpmyadmin-STABLE/',
shutil.move('/var/lib/wo/tmp/phpmyadmin-STABLE/',
'{0}22222/htdocs/db/pma/'
.format(WOVariables.wo_webroot))
shutil.copyfile('{0}22222/htdocs/db/pma'
@@ -1079,12 +1150,12 @@ class WOStackController(CementBaseController):
recursive=True)
# composer install and phpmyadmin update
if any('/tmp/composer-install' == x[1]
if any('/var/lib/wo/tmp/composer-install' == x[1]
for x in packages):
Log.info(self, "Installing composer, please wait...")
WOShellExec.cmd_exec(self, "php -q /tmp/composer-install "
"--install-dir=/tmp/")
shutil.copyfile('/tmp/composer.phar',
WOShellExec.cmd_exec(self, "php -q /var/lib/wo/tmp/composer-install "
"--install-dir=/var/lib/wo/tmp/")
shutil.copyfile('/var/lib/wo/tmp/composer.phar',
'/usr/local/bin/composer')
WOFileUtils.chmod(self, "/usr/local/bin/composer", 0o775)
Log.info(self, "Updating phpMyAdmin, please wait...")
@@ -1092,12 +1163,12 @@ class WOStackController(CementBaseController):
"update -n --no-dev -d "
"/var/www/22222/htdocs/db/pma/")
# netdata install
if any('/tmp/kickstart.sh' == x[1]
if any('/var/lib/wo/tmp/kickstart.sh' == x[1]
for x in packages):
if ((not os.path.exists('/opt/netdata')) and
(not os.path.exists('/etc/netdata'))):
Log.info(self, "Installing Netdata, please wait...")
WOShellExec.cmd_exec(self, "bash /tmp/kickstart.sh "
WOShellExec.cmd_exec(self, "bash /var/lib/wo/tmp/kickstart.sh "
"--dont-wait")
# disable mail notifications
WOFileUtils.searchreplace(self, "/opt/netdata/usr/"
@@ -1125,21 +1196,21 @@ class WOStackController(CementBaseController):
WOService.restart_service(self, 'netdata')
# WordOps Dashboard
if any('/tmp/wo-dashboard.tar.gz' == x[1]
if any('/var/lib/wo/tmp/wo-dashboard.tar.gz' == x[1]
for x in packages):
if not os.path.isfile('{0}22222/htdocs/index.php'
.format(WOVariables.wo_webroot)):
Log.debug(self, "Extracting wo-dashboard.tar.gz "
"to location {0}22222/htdocs/"
.format(WOVariables.wo_webroot))
WOExtract.extract(self, '/tmp/wo-dashboard.tar.gz',
WOExtract.extract(self, '/var/lib/wo/tmp/wo-dashboard.tar.gz',
'{0}22222/htdocs'
.format(WOVariables.wo_webroot))
if WOVariables.wo_wan_interface != 'eth0':
if WOVariables.wo_wan != 'eth0':
WOFileUtils.searchreplace(self, "{0}22222/htdocs/index.php"
.format(WOVariables.wo_webroot),
"eth0",
"{0}".format(WOVariables.wo_wan_interface))
"{0}".format(WOVariables.wo_wan))
Log.debug(self, "Setting Privileges to "
"{0}22222/htdocs"
@@ -1151,16 +1222,16 @@ class WOStackController(CementBaseController):
recursive=True)
# Extplorer FileManager
if any('/tmp/extplorer.tar.gz' == x[1]
if any('/var/lib/wo/tmp/extplorer.tar.gz' == x[1]
for x in packages):
if not os.path.exists('{0}22222/htdocs/files'
.format(WOVariables.wo_webroot)):
Log.debug(self, "Extracting explorer.tar.gz "
"to location {0}22222/htdocs/files"
.format(WOVariables.wo_webroot))
WOExtract.extract(self, '/tmp/extplorer.tar.gz',
'/tmp/')
shutil.move('/tmp/extplorer-2.1.11/',
WOExtract.extract(self, '/var/lib/wo/tmp/extplorer.tar.gz',
'/var/lib/wo/tmp/')
shutil.move('/var/lib/wo/tmp/extplorer-2.1.11',
'{0}22222/htdocs/files'
.format(WOVariables.wo_webroot))
Log.debug(self, "Setting Privileges to "
@@ -1173,16 +1244,16 @@ class WOStackController(CementBaseController):
recursive=True)
# phpmemcachedadmin
if any('/tmp/memcached.tar.gz' == x[1]
if any('/var/lib/wo/tmp/memcached.tar.gz' == x[1]
for x in packages):
Log.debug(self, "Extracting memcached.tar.gz to location"
" {0}22222/htdocs/cache/memcached "
" {0}22222/htdocs/cache/memcache "
.format(WOVariables.wo_webroot))
WOExtract.extract(self, '/tmp/memcached.tar.gz',
'{0}22222/htdocs/cache/memcached'
WOExtract.extract(self, '/var/lib/wo/tmp/memcached.tar.gz',
'{0}22222/htdocs/cache/memcache'
.format(WOVariables.wo_webroot))
Log.debug(self, "Setting Privileges to "
"{0}22222/htdocs/cache/memcached file"
"{0}22222/htdocs/cache/memcache file"
.format(WOVariables.wo_webroot))
WOFileUtils.chown(self, '{0}22222'
.format(WOVariables.wo_webroot),
@@ -1190,11 +1261,12 @@ class WOStackController(CementBaseController):
WOVariables.wo_php_user,
recursive=True)
# webgrind
if any('/tmp/webgrind.tar.gz' == x[1]
if any('/var/lib/wo/tmp/webgrind.tar.gz' == x[1]
for x in packages):
Log.debug(self, "Extracting file webgrind.tar.gz to "
"location /tmp/ ")
WOExtract.extract(self, '/tmp/webgrind.tar.gz', '/tmp/')
"location /var/lib/wo/tmp/ ")
WOExtract.extract(
self, '/var/lib/wo/tmp/webgrind.tar.gz', '/var/lib/wo/tmp/')
if not os.path.exists('{0}22222/htdocs/php'
.format(WOVariables.wo_webroot)):
Log.debug(self, "Creating directroy "
@@ -1204,7 +1276,7 @@ class WOStackController(CementBaseController):
.format(WOVariables.wo_webroot))
if not os.path.exists('{0}22222/htdocs/php/webgrind'
.format(WOVariables.wo_webroot)):
shutil.move('/tmp/webgrind-master/',
shutil.move('/var/lib/wo/tmp/webgrind-master/',
'{0}22222/htdocs/php/webgrind'
.format(WOVariables.wo_webroot))
@@ -1232,11 +1304,12 @@ class WOStackController(CementBaseController):
WOVariables.wo_php_user,
recursive=True)
# anemometer
if any('/tmp/anemometer.tar.gz' == x[1]
if any('/var/lib/wo/tmp/anemometer.tar.gz' == x[1]
for x in packages):
Log.debug(self, "Extracting file anemometer.tar.gz to "
"location /tmp/ ")
WOExtract.extract(self, '/tmp/anemometer.tar.gz', '/tmp/')
"location /var/lib/wo/tmp/ ")
WOExtract.extract(
self, '/var/lib/wo/tmp/anemometer.tar.gz', '/var/lib/wo/tmp/')
if not os.path.exists('{0}22222/htdocs/db/'
.format(WOVariables.wo_webroot)):
Log.debug(self, "Creating directory")
@@ -1244,7 +1317,7 @@ class WOStackController(CementBaseController):
.format(WOVariables.wo_webroot))
if not os.path.exists('{0}22222/htdocs/db/anemometer'
.format(WOVariables.wo_webroot)):
shutil.move('/tmp/Anemometer-master',
shutil.move('/var/lib/wo/tmp/Anemometer-master',
'{0}22222/htdocs/db/anemometer'
.format(WOVariables.wo_webroot))
chars = ''.join(random.sample(string.ascii_letters, 8))
@@ -1288,8 +1361,8 @@ class WOStackController(CementBaseController):
if any('/usr/bin/pt-query-advisor' == x[1]
for x in packages):
WOFileUtils.chmod(self, "/usr/bin/pt-query-advisor", 0o775)
# ph
if any('/tmp/pra.tar.gz' == x[1]
# phpredisadmin
if any('/var/lib/wo/tmp/pra.tar.gz' == x[1]
for x in packages):
if not os.path.exists('{0}22222/htdocs/cache/redis'
.format(WOVariables.wo_webroot)):
@@ -1442,33 +1515,49 @@ class WOStackController(CementBaseController):
Log.debug(self, "WP-CLI is already installed")
Log.info(self, "WP-CLI is already installed")
# fail2ban
if self.app.pargs.fail2ban:
Log.debug(self, "Setting apt_packages variable for Fail2ban")
if not WOAptGet.is_installed(self, 'fail2ban'):
apt_packages = apt_packages + WOVariables.wo_fail2ban
else:
Log.debug(self, "Fail2ban already installed")
Log.info(self, "Fail2ban already installed")
# PHPMYADMIN
if self.app.pargs.phpmyadmin:
Log.debug(self, "Setting packages variable for phpMyAdmin ")
if (not self.app.pargs.composer):
packages = packages + [["https://github.com/phpmyadmin/"
"phpmyadmin/archive/STABLE.tar.gz",
"/tmp/pma.tar.gz", "phpMyAdmin"],
["https://getcomposer.org/installer",
"/tmp/composer-install", "Composer"]]
"/var/lib/wo/tmp/pma.tar.gz",
"phpMyAdmin"],
["https://getcomposer.org/"
"installer",
"/var/lib/wo/tmp/composer-install",
"Composer"]]
else:
packages = packages + [["https://github.com/phpmyadmin/"
"phpmyadmin/archive/STABLE.tar.gz",
"/tmp/pma.tar.gz", "phpMyAdmin"]]
"/var/lib/wo/tmp/pma.tar.gz",
"phpMyAdmin"]]
# Composer
if self.app.pargs.composer:
Log.debug(self, "Setting packages variable for Composer ")
packages = packages + [["https://getcomposer.org/installer",
"/tmp/composer-install", "Composer"]]
"/var/lib/wo/tmp/composer-install",
"Composer"]]
# PHPREDISADMIN
if self.app.pargs.phpredisadmin:
Log.debug(self, "Setting packages variable for phpRedisAdmin")
packages = packages + [["https://github.com/ErikDubbelboer/"
"phpRedisAdmin/archive/master.tar.gz",
"/tmp/pra.tar.gz", "phpRedisAdmin"],
"/var/lib/wo/tmp/pra.tar.gz",
"phpRedisAdmin"],
["https://github.com/nrk/predis/"
"archive/v1.1.1.tar.gz",
"/tmp/predis.tar.gz", "Predis"]]
"/var/lib/wo/tmp/predis.tar.gz",
"Predis"]]
# ADMINER
if self.app.pargs.adminer:
Log.debug(self, "Setting packages variable for Adminer ")
@@ -1493,7 +1582,7 @@ class WOStackController(CementBaseController):
if not os.path.exists('/opt/netdata'):
packages = packages + [['https://my-netdata.io/'
'kickstart-static64.sh',
'/tmp/kickstart.sh',
'/var/lib/wo/tmp/kickstart.sh',
'Netdata']]
# WordOps Dashboard
@@ -1503,11 +1592,11 @@ class WOStackController(CementBaseController):
[["https://github.com/WordOps/"
"wordops-dashboard/releases/"
"download/v1.0/wo-dashboard.tar.gz",
"/tmp/wo-dashboard.tar.gz",
"/var/lib/wo/tmp/wo-dashboard.tar.gz",
"WordOps Dashboard"],
["https://github.com/soerennb/"
"extplorer/archive/v2.1.11.tar.gz",
"/tmp/extplorer.tar.gz",
"/var/lib/wo/tmp/extplorer.tar.gz",
"eXtplorer"]]
# UTILS
@@ -1516,7 +1605,7 @@ class WOStackController(CementBaseController):
packages = packages + [["https://github.com/elijaa/"
"phpmemcachedadmin/archive/"
"1.3.0.tar.gz",
'/tmp/memcached.tar.gz',
'/var/lib/wo/tmp/memcached.tar.gz',
'phpMemcachedAdmin'],
["https://raw.githubusercontent.com"
"/rtCamp/eeadmin/master/cache/nginx/"
@@ -1546,7 +1635,8 @@ class WOStackController(CementBaseController):
"OCP.php"],
["https://github.com/jokkedk/webgrind/"
"archive/master.tar.gz",
'/tmp/webgrind.tar.gz', 'Webgrind'],
'/var/lib/wo/tmp/webgrind.tar.gz',
'Webgrind'],
["http://bazaar.launchpad.net/~"
"percona-toolkit-dev/percona-toolkit/"
"2.1/download/head:/ptquerydigest-"
@@ -1556,21 +1646,22 @@ class WOStackController(CementBaseController):
"pt-query-advisor"],
["https://github.com/box/Anemometer/"
"archive/master.tar.gz",
'/tmp/anemometer.tar.gz', 'Anemometer']
'/var/lib/wo/tmp/anemometer.tar.gz',
'Anemometer']
]
except Exception as e:
pass
if len(apt_packages) or len(packages):
if (apt_packages) or (packages):
Log.debug(self, "Calling pre_pref")
self.pre_pref(apt_packages)
if len(apt_packages):
if (apt_packages):
WOSwap.add(self)
Log.info(self, "Updating apt-cache, please wait...")
WOAptGet.update(self)
Log.info(self, "Installing packages, please wait...")
WOAptGet.install(self, apt_packages)
if len(packages):
if (packages):
Log.debug(self, "Downloading following: {0}".format(packages))
WODownload.download(self, packages)
Log.debug(self, "Calling post_pref")
@@ -1617,7 +1708,7 @@ class WOStackController(CementBaseController):
"/etc/redis/redis.conf")
WOService.restart_service(self, 'redis-server')
if disp_msg:
if len(self.msg):
if (self.msg):
for msg in self.msg:
Log.info(self, Log.ENDC + msg)
Log.info(self, "Successfully installed packages")
@@ -1729,13 +1820,13 @@ class WOStackController(CementBaseController):
.format(WOVariables.wo_webroot),
'{0}22222/htdocs/cache/nginx/'
'clean.php'.format(WOVariables.wo_webroot),
'{0}22222/htdocs/cache/memcached'
'{0}22222/htdocs/cache/memcache'
.format(WOVariables.wo_webroot),
'/usr/bin/pt-query-advisor',
'{0}22222/htdocs/db/anemometer'
.format(WOVariables.wo_webroot)]
if len(packages) or len(apt_packages):
if (packages) or (apt_packages):
wo_prompt = input('Are you sure you to want to'
' remove from server.'
'\nPackage configuration will remain'
@@ -1749,11 +1840,11 @@ class WOStackController(CementBaseController):
if (set(["nginx-custom"]).issubset(set(apt_packages))):
WOService.stop_service(self, 'nginx')
if len(packages):
if (packages):
WOFileUtils.remove(self, packages)
WOAptGet.auto_remove(self)
if len(apt_packages):
if (apt_packages):
Log.debug(self, "Removing apt_packages")
Log.info(self, "Removing packages, please wait...")
WOAptGet.remove(self, apt_packages)
@@ -1861,14 +1952,14 @@ class WOStackController(CementBaseController):
.format(WOVariables.wo_webroot),
'{0}22222/htdocs/cache/nginx/'
'clean.php'.format(WOVariables.wo_webroot),
'{0}22222/htdocs/cache/memcached'
'{0}22222/htdocs/cache/memcache'
.format(WOVariables.wo_webroot),
'/usr/bin/pt-query-advisor',
'{0}22222/htdocs/db/anemometer'
.format(WOVariables.wo_webroot)
]
if len(packages) or len(apt_packages):
if (packages) or (apt_packages):
wo_prompt = input('Are you sure you to want to purge '
'from server '
'along with their configuration'
@@ -1881,12 +1972,12 @@ class WOStackController(CementBaseController):
if (set(["nginx-custom"]).issubset(set(apt_packages))):
WOService.stop_service(self, 'nginx')
if len(apt_packages):
if (apt_packages):
Log.info(self, "Purging packages, please wait...")
WOAptGet.remove(self, apt_packages, purge=True)
WOAptGet.auto_remove(self)
if len(packages):
if (packages):
WOFileUtils.remove(self, packages)
WOAptGet.auto_remove(self)

View File

@@ -100,8 +100,8 @@ class WOStackMigrateController(CementBaseController):
Log.error(
self, "Remote MySQL server in use, skipping local install")
if WOShellExec.cmd_exec(self, "mysqladmin ping") and (not
WOAptGet.is_installed(self, 'mariadb-server')):
if (WOShellExec.cmd_exec(self, "mysqladmin ping") and
(not WOAptGet.is_installed(self, 'mariadb-server'))):
Log.info(self, "If your database size is big, "
"migration may take some time.")

View File

@@ -26,7 +26,9 @@ class WOStackStatusController(CementBaseController):
self.app.pargs.php73 or
self.app.pargs.mysql or
self.app.pargs.memcached or
self.app.pargs.redis):
self.app.pargs.redis or
self.app.pargs.fail2ban or
self.app.pargs.netdata):
self.app.pargs.nginx = True
self.app.pargs.php = True
self.app.pargs.mysql = True
@@ -78,6 +80,12 @@ class WOStackStatusController(CementBaseController):
else:
Log.info(self, "Redis server is not installed")
if self.app.pargs.fail2ban:
if WOAptGet.is_installed(self, 'fail2ban'):
services = services + ['fail2ban-client']
else:
Log.info(self, "fail2ban is not installed")
for service in services:
Log.debug(self, "Starting service: {0}".format(service))
WOService.start_service(self, service)
@@ -143,6 +151,12 @@ class WOStackStatusController(CementBaseController):
else:
Log.info(self, "Redis server is not installed")
if self.app.pargs.fail2ban:
if WOAptGet.is_installed(self, 'fail2ban'):
services = services + ['fail2ban-client']
else:
Log.info(self, "fail2ban is not installed")
for service in services:
Log.debug(self, "Stopping service: {0}".format(service))
WOService.stop_service(self, service)
@@ -155,7 +169,8 @@ class WOStackStatusController(CementBaseController):
self.app.pargs.php73 or
self.app.pargs.mysql or
self.app.pargs.memcached or
self.app.pargs.redis):
self.app.pargs.redis or
self.app.pargs.fail2ban):
self.app.pargs.nginx = True
self.app.pargs.php = True
self.app.pargs.mysql = True
@@ -209,6 +224,12 @@ class WOStackStatusController(CementBaseController):
else:
Log.info(self, "Redis server is not installed")
if self.app.pargs.fail2ban:
if WOAptGet.is_installed(self, 'fail2ban'):
services = services + ['fail2ban-client']
else:
Log.info(self, "fail2ban is not installed")
for service in services:
Log.debug(self, "Restarting service: {0}".format(service))
WOService.restart_service(self, service)
@@ -221,7 +242,8 @@ class WOStackStatusController(CementBaseController):
self.app.pargs.php73 or
self.app.pargs.mysql or
self.app.pargs.memcached or
self.app.pargs.redis):
self.app.pargs.redis or
self.app.pargs.fail2ban):
self.app.pargs.nginx = True
self.app.pargs.php = True
self.app.pargs.mysql = True
@@ -274,6 +296,12 @@ class WOStackStatusController(CementBaseController):
else:
Log.info(self, "Redis server is not installed")
if self.app.pargs.fail2ban:
if WOAptGet.is_installed(self, 'fail2ban'):
services = services + ['fail2ban-client']
else:
Log.info(self, "fail2ban is not installed")
for service in services:
if WOService.get_service_status(self, service):
Log.info(self, "{0:10}: {1}".format(service, "Running"))
@@ -286,7 +314,8 @@ class WOStackStatusController(CementBaseController):
self.app.pargs.php73 or
self.app.pargs.mysql or
self.app.pargs.memcached or
self.app.pargs.redis):
self.app.pargs.redis or
self.app.pargs.fail2ban):
self.app.pargs.nginx = True
self.app.pargs.php = True
self.app.pargs.mysql = True
@@ -340,6 +369,12 @@ class WOStackStatusController(CementBaseController):
else:
Log.info(self, "Redis server is not installed")
if self.app.pargs.fail2ban:
if WOAptGet.is_installed(self, 'fail2ban'):
services = services + ['fail2ban-client']
else:
Log.info(self, "fail2ban is not installed")
for service in services:
Log.debug(self, "Reloading service: {0}".format(service))
WOService.reload_service(self, service)

View File

@@ -107,7 +107,8 @@ class WOStackUpgradeController(CementBaseController):
if self.app.pargs.php:
if WOAptGet.is_installed(self, 'php7.2-fpm'):
if not WOAptGet.is_installed(self, 'php7.3-fpm'):
apt_packages = apt_packages + WOVariables.wo_php + WOVariables.wo_php_extra
apt_packages = apt_packages + WOVariables.wo_php + \
WOVariables.wo_php_extra
else:
apt_packages = apt_packages + WOVariables.wo_php
else:

View File

@@ -1,9 +1,10 @@
from cement.core.controller import CementBaseController, expose
import os
import time
from cement.core import handler, hook
from cement.core.controller import CementBaseController, expose
from wo.core.download import WODownload
from wo.core.logging import Log
import time
import os
def wo_update_hook(app):

View File

@@ -0,0 +1,4 @@
[Definition]
failregex = ^ \[error\] \d+#\d+: .* forbidden .*, client: <HOST>, .*$
ignoreregex =

View File

@@ -21,4 +21,4 @@ port = http,https
logpath = /var/log/nginx/*error*.log
findtime = 60
bantime = 6000
maxretry = 3
maxretry = 5

View File

@@ -1,4 +1,4 @@
# FastCGI cache settings - WO v3.9.5.1
# FastCGI cache settings
fastcgi_cache_path /var/run/nginx-cache levels=1:2 keys_zone=WORDPRESS:50m inactive=60m max_size=256M;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header updating http_500 http_503;
@@ -17,3 +17,5 @@ fastcgi_buffer_size 32k;
fastcgi_param SERVER_NAME $http_host;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
fastcgi_keep_conn on;
# only available with Nginx 1.15.6 and earlier
fastcgi_socket_keepalive on;

View File

@@ -2,4 +2,7 @@
pid = {{pid}}
error_log = {{error_log}}
log_level = notice
include = {{include}}
emergency_restart_threshold = 10
emergency_restart_interval = 1m
process_control_timeout = 10s
include = {{include}}

View File

@@ -0,0 +1,266 @@
# Kernel sysctl configuration file for Linux
#
# Version 1.16 - 2019-10-25
# Michiel Klaver - IT Professional
# Modified by VirtuBox
#
# Instructions available on https://github.com/VirtuBox/ubuntu-nginx-web-server
#
# Sources :
# https://klaver.it/linux/sysctl.conf
# https://easyengine.io/tutorials/linux/sysctl-conf/
#
#
# Credits:
#
# http://www.enigma.id.au/linux_tuning.txt
# http://www.securityfocus.com/infocus/1729
# http://fasterdata.es.net/TCP-tuning/linux.html
# http://fedorahosted.org/ktune/browser/sysctl.ktune
# http://www.cymru.com/Documents/ip-stack-tuning.html
# http://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
# http://www.frozentux.net/ipsysctl-tutorial/chunkyhtml/index.html
# http://knol.google.com/k/linux-performance-tuning-and-measurement
# http://www.cyberciti.biz/faq/linux-kernel-tuning-virtual-memory-subsystem/
# http://www.redbooks.ibm.com/abstracts/REDP4285.html
# http://www.speedguide.net/read_articles.php?id=121
# http://lartc.org/howto/lartc.kernel.obscure.html
# http://en.wikipedia.org/wiki/Sysctl
#
# Usage
# wget -O /etc/sysctl.d/60-ubuntu-nginx-web-server.conf https://virtubox.github.io/ubuntu-nginx-web-server/files/etc/sysctl.d/60-ubuntu-nginx-web-server.conf
#
# sysctl -e -p /etc/sysctl.d/60-ubuntu-nginx-web-server.conf
# For binary values, 0 is disabled, 1 is enabled. See sysctl(8) and sysctl.conf(5) for more details.
#
###
### GENERAL SYSTEM SECURITY OPTIONS ###
###
# Controls the System Request debugging functionality of the kernel
kernel.sysrq = 0
# Controls whether core dumps will append the PID to the core filename.
# Useful for debugging multi-threaded applications.
kernel.core_uses_pid = 1
#Allow for more PIDs
kernel.pid_max = 65535
# The contents of /proc/<pid>/maps and smaps files are only visible to
# readers that are allowed to ptrace() the process
kernel.maps_protect = 1
#Enable ExecShield protection
kernel.exec-shield = 1
kernel.randomize_va_space = 2
# Controls the maximum size of a message, in bytes
kernel.msgmnb = 65535
# Controls the default maxmimum size of a mesage queue
kernel.msgmax = 65535
# Restrict core dumps
fs.suid_dumpable = 0
# Hide exposed kernel pointers
kernel.kptr_restrict = 1
###
### IMPROVE SYSTEM MEMORY MANAGEMENT ###
###
# Increase size of file handles and inode cache
fs.file-max = 209708
# Do less swapping
vm.swappiness = 10
vm.dirty_ratio = 30
vm.dirty_background_ratio = 5
# specifies the minimum virtual address that a process is allowed to mmap
vm.mmap_min_addr = 4096
# 50% overcommitment of available memory
vm.overcommit_ratio = 50
# allow memory overcommit required for redis
vm.overcommit_memory = 1
# Set maximum amount of memory allocated to shm to 256MB
kernel.shmmax = 268435456
kernel.shmall = 268435456
# Keep at least 64MB of free RAM space available
vm.min_free_kbytes = 65535
###
### GENERAL NETWORK SECURITY OPTIONS ###
###
#Prevent SYN attack, enable SYNcookies (they will kick-in when the max_syn_backlog reached)
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_max_syn_backlog = 4096
# Disables IP source routing
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
# Enable IP spoofing protection, turn on source route verification
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# Disable ICMP Redirect Acceptance
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
# Enable Log Spoofed Packets, Source Routed Packets, Redirect Packets
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
# Decrease the time default value for tcp_fin_timeout connection
net.ipv4.tcp_fin_timeout = 7
# Decrease the time default value for connections to keep alive
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15
# Don't relay bootp
net.ipv4.conf.all.bootp_relay = 0
# Don't proxy arp for anyone
net.ipv4.conf.all.proxy_arp = 0
# Turn on the tcp_timestamps, accurate timestamp make TCP congestion control algorithms work better
net.ipv4.tcp_timestamps = 1
# Don't ignore directed pings
net.ipv4.icmp_echo_ignore_all = 0
# Enable ignoring broadcasts request
net.ipv4.icmp_echo_ignore_broadcasts = 1
# Enable bad error message Protection
net.ipv4.icmp_ignore_bogus_error_responses = 1
# Allowed local port range
net.ipv4.ip_local_port_range = 16384 65535
# Enable a fix for RFC1337 - time-wait assassination hazards in TCP
net.ipv4.tcp_rfc1337 = 1
# Do not auto-configure IPv6
net.ipv6.conf.all.autoconf=0
net.ipv6.conf.all.accept_ra=0
net.ipv6.conf.default.autoconf=0
net.ipv6.conf.default.accept_ra=0
net.ipv6.conf.all.accept_ra_defrtr = 0
net.ipv6.conf.default.accept_ra_defrtr = 0
net.ipv6.conf.all.accept_ra_pinfo = 0
net.ipv6.conf.default.accept_ra_pinfo = 0
###
### TUNING NETWORK PERFORMANCE ###
###
# For servers with tcp-heavy workloads, enable 'fq' queue management scheduler (kernel > 3.12)
net.core.default_qdisc = fq
# Turn on the tcp_window_scaling
net.ipv4.tcp_window_scaling = 1
# Increase the read-buffer space allocatable
net.ipv4.tcp_rmem = 8192 87380 16777216
net.ipv4.udp_rmem_min = 16384
net.core.rmem_default = 262144
net.core.rmem_max = 16777216
# Increase the write-buffer-space allocatable
net.ipv4.tcp_wmem = 8192 65536 16777216
net.ipv4.udp_wmem_min = 16384
net.core.wmem_default = 262144
net.core.wmem_max = 16777216
# Increase number of incoming connections
net.core.somaxconn = 32768
# Increase number of incoming connections backlog
net.core.netdev_max_backlog = 16384
net.core.dev_weight = 64
# Increase the maximum amount of option memory buffers
net.core.optmem_max = 65535
# Increase the tcp-time-wait buckets pool size to prevent simple DOS attacks
net.ipv4.tcp_max_tw_buckets = 1440000
# try to reuse time-wait connections, but don't recycle them (recycle can break clients behind NAT)
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 1
# Limit number of orphans, each orphan can eat up to 16M (max wmem) of unswappable memory
net.ipv4.tcp_max_orphans = 16384
net.ipv4.tcp_orphan_retries = 0
# Limit the maximum memory used to reassemble IP fragments (CVE-2018-5391)
net.ipv4.ipfrag_low_thresh = 196608
net.ipv6.ip6frag_low_thresh = 196608
net.ipv4.ipfrag_high_thresh = 262144
net.ipv6.ip6frag_high_thresh = 262144
# don't cache ssthresh from previous connection
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_moderate_rcvbuf = 1
# Increase size of RPC datagram queue length
net.unix.max_dgram_qlen = 50
# Don't allow the arp table to become bigger than this
net.ipv4.neigh.default.gc_thresh3 = 2048
# Tell the gc when to become aggressive with arp table cleaning.
# Adjust this based on size of the LAN. 1024 is suitable for most /24 networks
net.ipv4.neigh.default.gc_thresh2 = 1024
# Adjust where the gc will leave arp table alone - set to 32.
net.ipv4.neigh.default.gc_thresh1 = 32
# Adjust to arp table gc to clean-up more often
net.ipv4.neigh.default.gc_interval = 30
# Increase TCP queue length
net.ipv4.neigh.default.proxy_qlen = 96
net.ipv4.neigh.default.unres_qlen = 6
# Enable Explicit Congestion Notification (RFC 3168), disable it if it doesn't work for you
net.ipv4.tcp_ecn = 1
net.ipv4.tcp_reordering = 3
# How many times to retry killing an alive TCP connection
net.ipv4.tcp_retries2 = 15
net.ipv4.tcp_retries1 = 3
# Avoid falling back to slow start after a connection goes idle
# keeps our cwnd large with the keep alive connections (kernel > 3.6)
net.ipv4.tcp_slow_start_after_idle = 0
# Allow the TCP fastopen flag to be used, beware some firewalls do not like TFO! (kernel > 3.7)
net.ipv4.tcp_fastopen = 3
# This will enusre that immediatly subsequent connections use the new values
net.ipv4.route.flush = 1
net.ipv6.route.flush = 1

View File

@@ -23,8 +23,8 @@ class WORepo():
"""
if repo_url is not None:
repo_file_path = ("/etc/apt/sources.list.d/"
+ WOVariables().wo_repo_file)
repo_file_path = ("/etc/apt/sources.list.d/" +
WOVariables().wo_repo_file)
try:
if not os.path.isfile(repo_file_path):
with open(repo_file_path,
@@ -62,8 +62,8 @@ class WORepo():
"--remove '{ppa_name}'"
.format(ppa_name=ppa))
elif repo_url:
repo_file_path = ("/etc/apt/sources.list.d/"
+ WOVariables().wo_repo_file)
repo_file_path = ("/etc/apt/sources.list.d/" +
WOVariables().wo_repo_file)
try:
repofile = open(repo_file_path, "w+")
@@ -84,8 +84,8 @@ class WORepo():
"""
WOShellExec.cmd_exec(self, "gpg --keyserver {serv}"
.format(serv=(keyserver or
"hkp://keyserver.ubuntu.com"))
+ " --recv-keys {key}".format(key=keyids))
"hkp://keyserver.ubuntu.com")) +
" --recv-keys {key}".format(key=keyids))
WOShellExec.cmd_exec(self, "gpg -a --export --armor {0}"
.format(keyids)
+ " | apt-key add - ")
.format(keyids) +
" | apt-key add - ")

View File

@@ -36,7 +36,8 @@ class WOAptGet():
for single_error in error_list:
if "NO_PUBKEY" in single_error:
key = single_error.rsplit(None, 1)[-1]
WORepo.add_key(self, key, keyserver="hkp://pgp.mit.edu")
WORepo.add_key(
self, key, keyserver="hkp://pgp.mit.edu")
proc = subprocess.Popen('apt-get update',
shell=True,
@@ -47,9 +48,11 @@ class WOAptGet():
if proc.returncode == 0:
return True
else:
Log.info(self, Log.FAIL + "Whoops, something went wrong...")
Log.info(self, Log.FAIL +
"Whoops, something went wrong...")
Log.error(self, "Check the WordOps log for more details "
"`tail /var/log/wo/wordops.log` and please try again...")
"`tail /var/log/wo/wordops.log` "
"and please try again...")
except Exception as e:
Log.error(self, "apt-get update exited with error")
@@ -60,7 +63,7 @@ class WOAptGet():
"""
try:
check_update = subprocess.Popen(['apt-get upgrade -s | grep '
'\"^Inst\" | wc -l'],
'\"^Inst\" | wc -l'],
stdout=subprocess.PIPE,
shell=True).communicate()[0]
if check_update == b'0\n':
@@ -96,7 +99,8 @@ class WOAptGet():
Log.info(self, Log.FAIL + "Oops Something went "
"wrong!!")
Log.error(self, "Check the WordOps log for more details "
"`tail /var/log/wo/wordops.log` and please try again...")
"`tail /var/log/wo/wordops.log` "
"and please try again...")
except Exception as e:
Log.error(self, "Error while installing packages, "
"apt-get exited with error")
@@ -122,13 +126,15 @@ class WOAptGet():
Log.info(self, Log.FAIL + "Oops Something went "
"wrong!!")
Log.error(self, "Check the WordOps log for more details "
"`tail /var/log/wo/wordops.log` and please try again...")
"`tail /var/log/wo/wordops.log` "
"and please try again...")
except Exception as e:
Log.info(self, Log.FAIL + "Oops Something went "
"wrong!!")
Log.error(self, "Check the WordOps log for more details "
"`tail /var/log/wo/wordops.log` and please try again...")
"`tail /var/log/wo/wordops.log` "
"and please try again...")
def remove(self, packages, auto=False, purge=False):
all_packages = ' '.join(packages)
@@ -151,7 +157,8 @@ class WOAptGet():
Log.info(self, Log.FAIL + "Oops Something went "
"wrong!!")
Log.error(self, "Check the WordOps log for more details "
"`tail /var/log/wo/wordops.log` and please try again...")
"`tail /var/log/wo/wordops.log` "
"and please try again...")
except Exception as e:
Log.error(self, "Error while installing packages, "
@@ -184,19 +191,20 @@ class WOAptGet():
def is_installed(self, package_name):
"""
Checks if package is available in cache and is installed or not
Checks if package is available in cache "
"and is installed or not
returns True if installed otherwise returns False
"""
apt_cache = apt.cache.Cache()
apt_cache.open()
if (package_name.strip() in apt_cache and
apt_cache[package_name.strip()].is_installed):
apt_cache[package_name.strip()].is_installed):
# apt_cache.close()
return True
# apt_cache.close()
return False
def download_only(self,package_name,repo_url=None,repo_key=None):
def download_only(self, package_name, repo_url=None, repo_key=None):
"""
Similar to `apt-get install --download-only PACKAGE_NAME`
"""
@@ -207,7 +215,8 @@ class WOAptGet():
WORepo.add(self, repo_url=repo_url)
if repo_key is not None:
WORepo.add_key(self, repo_key)
proc = subprocess.Popen("apt-get update && DEBIAN_FRONTEND=noninteractive "
proc = subprocess.Popen("apt-get update && "
"DEBIAN_FRONTEND=noninteractive "
"apt-get install -o "
"Dpkg::Options::=\"--force-confdef\""
" -o "
@@ -221,11 +230,12 @@ class WOAptGet():
if proc.returncode == 0:
return True
else:
Log.error(self,"Error in fetching dpkg package.\nReverting changes ..",False)
Log.error(
self, "Error in fetching dpkg package.\n"
"Reverting changes ..", False)
if repo_url is not None:
WORepo.remove(self, repo_url=repo_url)
return False
except Exception as e:
Log.error(self, "Error while downloading packages, "
"apt-get exited with error")

View File

@@ -5,28 +5,30 @@ from wo.core.logging import Log
Set CRON on LINUX system.
"""
class WOCron():
def setcron_weekly(self,cmd,comment='Cron set by WordOps',user='root',min=0,hour=12):
if not WOShellExec.cmd_exec(self, "crontab -l | grep -q \'{0}\'".format(cmd)):
def setcron_weekly(self, cmd, comment='Cron set by WordOps', user='root',
min=0, hour=12):
if not WOShellExec.cmd_exec(self, "crontab -l "
"| grep -q \'{0}\'".format(cmd)):
WOShellExec.cmd_exec(self, "/bin/bash -c \"crontab -l "
"2> /dev/null | {{ cat; echo -e"
" \\\""
"\\n0 0 * * 0 "
"{0}".format(cmd) +
" # {0}".format(comment)+
"\\\"; } | crontab -\"")
"2> /dev/null | {{ cat; echo -e"
" \\\""
"\\n0 0 * * 0 "
"{0}".format(cmd) +
" # {0}".format(comment) +
"\\\"; } | crontab -\"")
Log.debug(self, "Cron set")
def remove_cron(self,cmd):
if WOShellExec.cmd_exec(self, "crontab -l | grep -q \'{0}\'".format(cmd)):
def remove_cron(self, cmd):
if WOShellExec.cmd_exec(self, "crontab -l "
"| grep -q \'{0}\'".format(cmd)):
if not WOShellExec.cmd_exec(self, "/bin/bash -c "
"\"crontab "
"-l | sed '/{0}/d'"
"| crontab -\""
.format(cmd)):
Log.error(self, "Failed to remove crontab entry",False)
"\"crontab "
"-l | sed '/{0}/d'"
"| crontab -\""
.format(cmd)):
Log.error(self, "Failed to remove crontab entry", False)
else:
Log.debug(self, "Cron not found")

View File

@@ -22,7 +22,8 @@ class WODownload():
if not os.path.exists(directory):
os.makedirs(directory)
Log.info(self, "Downloading {0:20}".format(pkg_name), end=' ')
req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'})
req = urllib.request.Request(
url, headers={'User-Agent': 'Mozilla/5.0'})
with urllib.request.urlopen(req) as response, open(filename, 'wb') as out_file:
out_file.write(response.read())
Log.info(self, "{0}".format("[" + Log.ENDC + "Done"

View File

@@ -3,6 +3,7 @@
class WOError(Exception):
"""Generic errors."""
def __init__(self, msg):
Exception.__init__(self)
self.msg = msg

View File

@@ -21,14 +21,14 @@ class WOFileUtils():
Log.info(self, "Removing {0:65}".format(file), end=' ')
os.remove(file)
Log.info(self, "{0}".format("[" + Log.ENDC + "Done" +
Log.OKBLUE + "]"))
Log.OKBLUE + "]"))
Log.debug(self, 'file Removed')
if os.path.isdir(file):
try:
Log.info(self, "Removing {0:65}".format(file), end=' ')
shutil.rmtree(file)
Log.info(self, "{0}".format("[" + Log.ENDC + "Done" +
Log.OKBLUE + "]"))
Log.OKBLUE + "]"))
except shutil.Error as e:
Log.debug(self, "{err}".format(err=str(e.reason)))
Log.error(self, 'Unable to Remove file ')

View File

@@ -28,10 +28,12 @@ class WOMysql():
"""Method for MySQL connection"""
def connect(self):
"""Makes connection with MySQL server"""
# Makes connection with MySQL server
try:
if os.path.exists('/etc/mysql/conf.d/my.cnf'):
connection = pymysql.connect(read_default_file='/etc/mysql/conf.d/my.cnf')
connection = \
pymysql.connect(read_default_file='/etc/mysql/'
'conf.d/my.cnf')
else:
connection = pymysql.connect(read_default_file='~/.my.cnf')
return connection
@@ -45,9 +47,11 @@ class WOMysql():
def dbConnection(self, db_name):
try:
if os.path.exists('/etc/mysql/conf.d/my.cnf'):
connection = pymysql.connect(db=db_name,read_default_file='/etc/mysql/conf.d/my.cnf')
connection = pymysql.connect(
db=db_name, read_default_file='/etc/mysql/conf.d/my.cnf')
else:
connection = pymysql.connect(db=db_name,read_default_file='~/.my.cnf')
connection = pymysql.connect(
db=db_name, read_default_file='~/.my.cnf')
return connection
except DatabaseError as e:
@@ -58,12 +62,13 @@ class WOMysql():
except pymysql.err.InternalError as e:
Log.debug(self, str(e))
raise MySQLConnectionError
except Exception as e :
except Exception as e:
Log.debug(self, "[Error]Setting up database: \'" + str(e) + "\'")
raise MySQLConnectionError
def execute(self, statement, errormsg='', log=True):
"""Get login details from /etc/mysql/conf.d/my.cnf & Execute MySQL query"""
# Get login details from /etc/mysql/conf.d/my.cnf
# & Execute MySQL query
connection = WOMysql.connect(self)
log and Log.debug(self, "Exceuting MySQL Statement : {0}"
.format(statement))
@@ -95,20 +100,22 @@ class WOMysql():
'/var/wo-mysqlbackup')
os.makedirs('/var/wo-mysqlbackup')
db = subprocess.check_output(["mysql -Bse \'show databases\'"],
db = subprocess.check_output(["/usr/bin/mysql "
"-Bse \'show databases\'"],
universal_newlines=True,
shell=True).split('\n')
for dbs in db:
if dbs == "":
continue
Log.info(self, "Backing up {0} database".format(dbs))
p1 = subprocess.Popen("mysqldump {0}"
p1 = subprocess.Popen("/usr/bin/mysqldump {0}"
" --max_allowed_packet=1024M"
" --single-transaction".format(dbs),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True)
p2 = subprocess.Popen("gzip -c > /var/wo-mysqlbackup/{0}{1}.s"
"ql.gz".format(dbs, WOVariables.wo_date),
p2 = subprocess.Popen("/usr/bin/pigz -c > "
"/var/wo-mysqlbackup/{0}{1}.sql.gz"
.format(dbs, WOVariables.wo_date),
stdin=p1.stdout,
shell=True)

View File

@@ -116,7 +116,8 @@ class WOService():
try:
is_exist = subprocess.getstatusoutput('which {0}'
.format(service_name))
if is_exist[0] == 0 or service_name in ['php7.2-fpm', 'php7.3-fpm']:
if is_exist[0] == 0 or service_name in ['php7.2-fpm',
'php7.3-fpm']:
retcode = subprocess.getstatusoutput('service {0} status'
.format(service_name))
if retcode[0] == 0:

View File

@@ -19,7 +19,8 @@ class SSL:
current_date = WOShellExec.cmd_exec_stdout(self, "date -d \"now\" +%s")
expiration_date = WOShellExec.cmd_exec_stdout(self, "date -d \""
"`openssl x509 -in "
"`/usr/bin/openssl "
"x509 -in "
"/etc/letsencrypt/live/"
"{0}/cert.pem"
" -text -noout|grep "
@@ -45,7 +46,8 @@ class SSL:
"`tail /var/log/wo/wordops.log` and please try again...")
expiration_date = WOShellExec.cmd_exec_stdout(self, "date -d "
"\"`openssl x509 -in "
"\"`/usr/bin/openssl "
"x509 -in "
"/etc/letsencrypt/live/"
"{0}/cert.pem"
" -text -noout|grep "

View File

@@ -3,7 +3,6 @@ import platform
import socket
import configparser
import os
import sys
import psutil
import datetime
@@ -12,9 +11,9 @@ class WOVariables():
"""Intialization of core variables"""
# WordOps version
wo_version = "3.9.4"
wo_version = "3.9.5"
# WordOps packages versions
wo_wp_cli = "2.1.0"
wo_wp_cli = "2.2.0"
wo_adminer = "4.7.1"
# Get WPCLI path
@@ -23,17 +22,18 @@ class WOVariables():
wo_wpcli_path = '/usr/local/bin/wp '
# get wan network interface name
wo_wan_interface = os.popen("ip -4 route get 8.8.8.8 | "
"grep -oP \"dev [^[:space:]]+ \" "
"| cut -d ' ' -f 2").read()
if wo_wan_interface == '':
wo_wan_interface = 'eth0'
wo_wan = os.popen("/sbin/ip -4 route get 8.8.8.8 | "
"grep -oP \"dev [^[:space:]]+ \" "
"| cut -d ' ' -f 2").read()
if wo_wan == '':
wo_wan = 'eth0'
# Current date and time of System
wo_date = datetime.datetime.now().strftime('%d%b%Y%H%M%S')
# WordOps core variables
wo_platform_distro = platform.linux_distribution()[0].lower()
wo_platform_distro = os.popen("lsb_release -si "
"| tr -d \'\\n\'").read().lower()
wo_platform_version = platform.linux_distribution()[1]
wo_platform_codename = os.popen("lsb_release -sc | tr -d \'\\n\'").read()
@@ -70,8 +70,9 @@ class WOVariables():
except Exception as e:
wo_user = input("Enter your name: ")
wo_email = input("Enter your email: ")
os.system("git config --global user.name {0}".format(wo_user))
os.system("git config --global user.email {0}".format(wo_email))
os.system("/usr/bin/git config --global user.name {0}".format(wo_user))
os.system(
"/usr/bin/git config --global user.email {0}".format(wo_email))
# Get System RAM and SWAP details
wo_ram = psutil.virtual_memory().total / (1024 * 1024)
@@ -94,21 +95,35 @@ class WOVariables():
# WordOps stack installation variables
# Nginx repo and packages
if wo_platform_codename == 'trusty':
if wo_platform_distro == 'ubuntu':
if wo_platform_codename == 'trusty':
wo_nginx_repo = ("deb http://download.opensuse.org"
"/repositories/home:"
"/virtubox:/WordOps/xUbuntu_14.04/ /")
elif wo_platform_codename == 'xenial':
wo_nginx_repo = ("deb http://download.opensuse.org"
"/repositories/home:"
"/virtubox:/WordOps/xUbuntu_16.04/ /")
elif wo_platform_codename == 'bionic':
wo_nginx_repo = ("deb http://download.opensuse.org"
"/repositories/home:"
"/virtubox:/WordOps/xUbuntu_18.04/ /")
else:
wo_nginx_repo = ("deb http://download.opensuse.org"
"/repositories/home:"
"/virtubox:/WordOps/xUbuntu_19.04/ /")
elif wo_platform_distro == 'debian':
if wo_platform_codename == 'jessie':
wo_nginx_repo = ("deb http://download.opensuse.org"
"/repositories/home:"
"/virtubox:/WordOps/Debian_8.0/ /")
elif wo_platform_codename == 'stretch':
wo_nginx_repo = ("deb http://download.opensuse.org"
"/repositories/home:"
"/virtubox:/WordOps/Debian_9.0/ /")
else:
wo_nginx_repo = ("deb http://download.opensuse.org/repositories/home:"
"/virtubox:/WordOps/xUbuntu_14.04/ /")
elif wo_platform_codename == 'xenial':
wo_nginx_repo = ("deb http://download.opensuse.org/repositories/home:"
"/virtubox:/WordOps/xUbuntu_16.04/ /")
elif wo_platform_codename == 'bionic':
wo_nginx_repo = ("deb http://download.opensuse.org/repositories/home:"
"/virtubox:/WordOps/xUbuntu_18.04/ /")
elif wo_platform_codename == 'jessie':
wo_nginx_repo = ("deb http://download.opensuse.org/repositories/home:"
"/virtubox:/WordOps/Debian_8.0/ /")
elif wo_platform_codename == 'stretch':
wo_nginx_repo = ("deb http://download.opensuse.org/repositories/home:"
"/virtubox:/WordOps/Debian_9.0/ /")
"/virtubox:/WordOps/Raspbian_9.0/ /")
wo_nginx = ["nginx-custom", "nginx-wo"]
wo_nginx_key = '188C9FB063F0247A'
@@ -129,7 +144,7 @@ class WOVariables():
wo_php_extra = ["php-memcached", "php-imagick", "memcached",
"graphviz", "php-xdebug", "php-msgpack", "php-redis"]
wo_php_key = ''
elif wo_platform_distro == 'debian':
else:
wo_php_repo = (
"deb https://packages.sury.org/php/ {codename} main"
.format(codename=wo_platform_codename))
@@ -145,19 +160,21 @@ class WOVariables():
"php7.3-zip", "php7.3-xml", "php7.3-soap"]
wo_php_extra = ["php-memcached", "php-imagick", "memcached",
"graphviz", "php-xdebug", "php-msgpack", "php-redis"]
wo_php_key = 'AC0E47584A7A714D'
# MySQL repo and packages
if wo_platform_distro == 'ubuntu':
wo_mysql_repo = ("deb [arch=amd64,ppc64el] http://sfo1.mirrors.digitalocean.com/mariadb/repo/"
wo_mysql_repo = ("deb [arch=amd64,ppc64el] "
"http://sfo1.mirrors.digitalocean.com/mariadb/repo/"
"10.3/ubuntu {codename} main"
.format(codename=wo_platform_codename))
elif wo_platform_distro == 'debian':
wo_mysql_repo = ("deb [arch=amd64,ppc64el] http://sfo1.mirrors.digitalocean.com/mariadb/repo/"
else:
wo_mysql_repo = ("deb [arch=amd64,ppc64el] "
"http://sfo1.mirrors.digitalocean.com/mariadb/repo/"
"10.3/debian {codename} main"
.format(codename=wo_platform_codename))
wo_mysql = ["mariadb-server", "percona-toolkit"]
wo_mysql = ["mariadb-server", "percona-toolkit", "python3-mysqldb"]
wo_fail2ban = "fail2ban"