├── .gitattributes ├── LICENSE ├── README.md ├── app ├── phpmyadmin │ ├── Dockerfile │ ├── script_init.sh │ └── script_run_aux.sh └── wordpress │ ├── Dockerfile │ ├── script_init.sh │ └── script_run_aux.sh ├── balancer ├── Dockerfile ├── script_init.sh ├── script_run.sh └── script_update.sh ├── docweb ├── install.sh ├── notes.txt ├── proxy ├── Dockerfile ├── base │ ├── Dockerfile │ └── script_init.sh ├── script_init.sh ├── script_run.sh └── script_update.sh └── web ├── apache ├── Dockerfile ├── script_init.sh └── script_run.sh ├── aspnet4 ├── Dockerfile ├── script_init.sh └── script_run.sh ├── aspnet5 ├── Dockerfile ├── script_init.sh └── script_run.sh ├── go └── Dockerfile ├── nginx ├── Dockerfile ├── script_init.sh ├── script_run.sh └── script_update.sh ├── nodejs ├── Dockerfile ├── project.sh ├── script_init.sh └── script_run.sh ├── php5apache ├── Dockerfile ├── script_init.sh └── script_run.sh ├── php7apache ├── Dockerfile ├── script_init.sh └── script_run.sh ├── php7nginx ├── Dockerfile ├── base │ ├── Dockerfile │ └── script_init.sh ├── script_init.sh ├── script_run.sh └── script_update.sh └── python3 ├── Dockerfile ├── script_init.sh └── script_run.sh /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | DockerWeb Public Source License 2 | 3 | The DockerWeb software (henceforth referred to simply as "DockerWeb") is dual-licensed - Copyright 2016-2017 Faraz Fallahi 4 | 5 | Cases that include commercialization of DockerWeb require a commercial, non-free license. Otherwise, DockerWeb can be used without charge under the terms set out below. 6 | 7 | 1. Definitions 8 | 9 | 1.1 “License” means this document. 10 | 1.2 “Contributor” means each individual or legal entity that creates, contributes to the creation of, or owns DockerWeb. 11 | 1.3 “DockerWeb Team” means DockerWeb’s core developers, an updated list of whom can be found within the CREDITS file. 12 | 13 | 2. Commercialization 14 | 15 | A commercial use is one intended for commercial advantage or monetary compensation. 16 | 17 | Example cases of commercialization are: 18 | 19 | - Using DockerWeb to provide commercial managed/Software-as-a-Service services. 20 | - Distributing DockerWeb as a commercial product or as part of one. 21 | - Using DockerWeb as a value added service/product. 22 | 23 | Example cases which do not require a commercial license, and thus fall under the terms set out below, include (but are not limited to): 24 | 25 | - Penetration testers (or penetration testing organizations) using DockerWeb as part of their assessment toolkit. 26 | - Penetration Testing Linux Distributions including but not limited to Kali Linux, SamuraiWTF, BackBox Linux. 27 | - Using DockerWeb to test your own systems. 28 | - Any non-commercial use of DockerWeb. 29 | 30 | If you need to purchase a commercial license or are unsure whether you need to purchase a commercial license contact us - team@DockerWeb.org. 31 | 32 | We may grant commercial licenses at no monetary cost at our own discretion if the commercial usage is deemed by the DockerWeb Team to significantly benefit DockerWeb. 33 | 34 | Free-use Terms and Conditions; 35 | 36 | 3. Redistribution 37 | 38 | Redistribution is permitted under the following conditions: 39 | 40 | - Unmodified License is provided with DockerWeb. 41 | - Unmodified Copyright notices are provided with DockerWeb. 42 | - Does not conflict with the commercialization clause. 43 | 44 | 4. Copying 45 | 46 | Copying is permitted so long as it does not conflict with the Redistribution clause. 47 | 48 | 5. Modification 49 | 50 | Modification is permitted so long as it does not conflict with the Redistribution clause. 51 | 52 | 6. Contributions 53 | 54 | Any Contributions assume the Contributor grants the DockerWeb Team the unlimited, non-exclusive right to reuse, modify and relicense the Contributor's content. 55 | 56 | 7. Support 57 | 58 | DockerWeb is provided under an AS-IS basis and without any support, updates or maintenance. Support, updates and maintenance may be given according to the sole discretion of the DockerWeb Team. 59 | 60 | 8. Disclaimer of Warranty 61 | 62 | DockerWeb is provided under this License on an “as is” basis, without warranty of any kind, either expressed, implied, or statutory, including, without limitation, warranties that the DockerWeb is free of defects, merchantable, fit for a particular purpose or non-infringing. 63 | 64 | 9. Limitation of Liability 65 | 66 | To the extent permitted under Law, DockerWeb is provided under an AS-IS basis. The DockerWeb Team shall never, and without any limit, be liable for any damage, cost, expense or any other payment incurred as a result of DockerWeb's actions, failure, bugs and/or any other interaction between DockerWeb and end-equipment, computers, other software or any 3rd party, end-equipment, computer or services. 67 | 68 | 10. Disclaimer 69 | 70 | Running DockerWeb against websites without prior mutual consent may be illegal in your country. The DockerWeb Team accept no liability and are not responsible for any misuse or damage caused by DockerWeb. 71 | 72 | 11. Trademark 73 | 74 | The "DockerWeb" term is a registered trademark. This License does not grant the use of the "DockerWeb" trademark or the use of the DockerWeb logo. 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DockerWeb 2 | 3 | A docker-powered bash script for shared web hosting management. The ultimate Docker LAMP/LEMP Stack. 4 | 5 | ## Requirements 6 | 7 | - A fresh installation of latest Ubuntu LTS x64 with the FQDN set. 8 | - DigitalOcean provides Cloud VPS Servers at affordable prices. You can sign up via [this referral link](https://m.do.co/c/fb7b38f12520) to get a free $100 bonus in credit. 9 | - At least 512MB of system memory. (1GB recommended) 10 | - A domain name pointed at the host's IP address. (Optional but highly recommended) 11 | 12 | ## Installing 13 | 14 | After you changed the default root password and ssh port, to install the latest stable release, you can run the following commands as root: 15 | 16 | ``` 17 | git clone https://github.com/fffaraz/dockerweb.git /opt/dockerweb 18 | export PATH=$PATH:/opt/dockerweb 19 | ``` 20 | 21 | To add `/opt/dockerweb` to your $PATH permanently run `echo 'export PATH=$PATH:/opt/dockerweb' >> ~/.profile` 22 | 23 | To create swap space on a regular file run `docweb install:swapfile SIZE_IN_MB` 24 | 25 | If you don't already have docker installed on your host run `docweb install:docker` 26 | 27 | To create the network bridge used by dockerweb containers run `docweb install:network` 28 | 29 | Finally to build dockerweb images run `docweb build:all` 30 | 31 | Optionally, to install some useful packages run `docweb install:extras` and `docweb install:aliases` 32 | 33 | ### Upgrading 34 | 35 | To upgrade you just need to run `docweb upgrade` first and then if necessary rebuild all the images with `docweb build:all` and re-run all the containers to use new images built. 36 | 37 | ## How to run services 38 | 39 | ### The DNS Server 40 | 41 | [MicroDNS](https://github.com/fffaraz/microdns) is a tiny DNS server that is used to (almost) always return your host's IP address for any query sent to it. Hence you will just need to set your domains' dns setting to point to your host's IP address and you don't have to also add them in a config file on the host any more. 42 | 43 | ``` 44 | docweb microdns:run [--ttl 3600] [--log] 45 | docweb microdns:log 46 | docweb stop microdns 47 | ``` 48 | 49 | ### The Reverse Proxy Server 50 | 51 | This is the main web server listening on ports 80 and 443 and proxying requests to the apps based on their domain names. 52 | It also provides TLS/SSL encryption using valid certificates signed by [Let's Encrypt](https://letsencrypt.org/) and is responsible for output gzip compression. 53 | You can add your apps to its config file at `/home/proxy/websites.conf`. 54 | You need to run the update command each time you edit the config file. 55 | Make sure all your apps are running before updating the proxy server. 56 | 57 | ``` 58 | docweb proxy:run [--debug] [SERVER_NAME] 59 | docweb stop proxy 60 | docweb proxy:update 61 | docweb proxy:status 62 | ``` 63 | 64 | Logs Directory: `/home/proxy/log/nginx/` 65 | 66 | Config File Format: `CONTAINER CATCHALL WILDCARD SSLCERT DOMAIN1 [DOMAINS...]` 67 | 68 | * `CONTAINER` : The name of App's container. 69 | * `CATCHALL` : Set to 1 for the default app. Proxies all unmatched domain names to that container. Optional. One app only. 70 | * `WILDCARD` : Whether to also proxy all subdomains of app's domain names to that container. 71 | * `SSLCERT` : Request for a valid TLS/SSL certificate from letsencrypt. 72 | * `HTTPSONLY` : Redirect all HTTP requests to HTTPS. 73 | * `DOMAIN1` : Primary domain name for the app. 74 | * `[DOMAINS...]` : Optional additional domain names. 75 | 76 | ### MySQL Server 77 | 78 | ``` 79 | docweb mysql:run [--debug] [--direct PORT] [--memory M] NAME MYSQL_ROOT_PASSWORD [mariadb|mysql|mysql/mysql-server] 80 | docweb mysql:stop NAME 81 | docweb mysql:client NAME 82 | docweb mysql:status NAME 83 | docweb mysql:optimize NAME 84 | docweb mysql:backup NAME [--gzip] [DATABASES...] 85 | docweb mysql:import NAME [--gzip] FILENAME [DATABASE] 86 | docweb mysql:createuser NAME USERNAME PASSWORD 87 | docweb mysql:createdb NAME DB 88 | docweb mysql:listusers NAME 89 | docweb mysql:listproc NAME 90 | docweb mysql:listdbs NAME 91 | docweb mysql:upgrade NAME 92 | docweb mysql:tuner NAME MYSQL_ROOT_PASSWORD 93 | ``` 94 | 95 | Default Image: `mariadb` 96 | 97 | MySQL Backup / Import Directory: `/home/NAME/backup` 98 | 99 | ### PostgreSQL Server 100 | 101 | ``` 102 | docweb postgres:run [--debug] NAME POSTGRES_PASSWORD 103 | docweb stop NAME 104 | ``` 105 | 106 | ### Redis Server 107 | 108 | ``` 109 | docweb redis:run [--debug] NAME 110 | docweb stop NAME 111 | ``` 112 | 113 | ### Mail Forwarder 114 | 115 | ``` 116 | docweb mailfwd:run 117 | ``` 118 | 119 | Based on [zixia/docker-simple-mail-forwarder](https://github.com/zixia/docker-simple-mail-forwarder). Config File: `/home/mailfwd/mail.conf` 120 | 121 | ### Web Apps 122 | 123 | ``` 124 | docweb run [--debug|--bash] [--direct PORT] IMAGE NAME [WEBUSER_PASSWORD SSH_PORT] 125 | docweb stop NAME 126 | docweb logs NAME 127 | docweb update NAME 128 | docweb exec [--root] NAME 129 | docweb clean NAME 130 | docweb backup NAME 131 | docweb ps NAME 132 | docweb status NAME 133 | docweb log:nginx NAME [--error] 134 | docweb log:php NAME [--error] 135 | ``` 136 | 137 | WWW (public_hmtl) root directory: `/home/NAME/www/public` 138 | 139 | Domains config file: `/home/NAME/domains.conf` 140 | 141 | Optional project init script: `/home/NAME/project.sh` 142 | 143 | List of availabe images: ` php7nginx php7apache php5apache python3 nodejs aspnet4 aspnet5 ` 144 | 145 | ### phpMyAdmin 146 | 147 | ``` 148 | docweb pma:run [--debug] [--direct PORT] MYSQLSERVER MYSQLROOTPASSWORD [pma status] [CaptchaPublic CaptchaPrivate] 149 | docweb stop MYSQLSERVER_pma 150 | ``` 151 | 152 | Then add the following line to your `/home/proxy/websites.conf` and then run `dockweb proxy:update`. 153 | 154 | ``` 155 | MYSQLSERVER_pma 0 0 0 0 pma.example.com 156 | ``` 157 | 158 | phpMyAdmin can be accessed from `http://pma.example.com/pma/` 159 | 160 | Status page `http://pma.example.com/status/` 161 | 162 | ### ClamAV 163 | 164 | ``` 165 | docweb clamav:run 166 | ``` 167 | 168 | ### Etc. 169 | 170 | * `docweb rm` To remove stopped containers, orphaned images and orphaned volumes. 171 | * `docweb rm:all` To remove all containers and volumes. 172 | * `docweb rm:img` To remove all images. 173 | * `docweb build NAME` To build an image. 174 | * `docweb stats` Prints host status. 175 | * `docweb volume:create NAME SIZE` 176 | 177 | ## Examples 178 | 179 | ### PHP 7.1 + NGINX + MySQL Stack 180 | 181 | To create a new PHP website with NGINX webserver and MariaDB database server and phpMyAdmin run the following commands: 182 | 183 | ``` 184 | docweb mysql:run db1 mysqlrootpassword 185 | docweb mysql:createuser db1 example.com db_password 186 | docweb pma:run db1 mysqlrootpassword 187 | docweb run php7nginx example.com 188 | docweb proxy:run 189 | ``` 190 | 191 | Then add the following lines to `/home/proxy/websites.conf` 192 | 193 | ``` 194 | db1_pma 0 0 0 0 pma.example.com 195 | example.com 0 0 0 0 example.com 196 | ``` 197 | 198 | Then update the proxy server with `docweb proxy:update` 199 | 200 | ## See Also 201 | 202 | * [docker-webserver](https://github.com/nazar-pc/docker-webserver) - WebServer (MariaDB, PHP-FPM, Nginx) composed from several separate containers linked together. 203 | * [shipping-docker](https://github.com/shipping-docker) 204 | 205 | 217 | -------------------------------------------------------------------------------- /app/phpmyadmin/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fffaraz/web/php7nginx:latest 2 | ADD script_*.sh / 3 | RUN chown root:root /script_*.sh && chmod 540 /script_*.sh && sync && /script_init.sh 4 | -------------------------------------------------------------------------------- /app/phpmyadmin/script_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | # Install phpMyAdmin 5 | # https://www.phpmyadmin.net/downloads/ 6 | # https://github.com/phpmyadmin/phpmyadmin/releases 7 | # https://github.com/phpmyadmin/phpmyadmin/archive/RELEASE_4_7_9.zip 8 | # https://github.com/phpmyadmin/docker 9 | 10 | PMA_VERSION=4.7.9 11 | cd /opt 12 | wget --no-verbose https://files.phpmyadmin.net/phpMyAdmin/$PMA_VERSION/phpMyAdmin-$PMA_VERSION-english.zip 13 | unzip -q phpMyAdmin-$PMA_VERSION-english.zip 14 | rm phpMyAdmin-$PMA_VERSION-english.zip 15 | mv phpMyAdmin-$PMA_VERSION-english phpMyAdmin 16 | 17 | # http://docs.phpmyadmin.net/en/latest/config.html 18 | # https://www.google.com/recaptcha/ 19 | 20 | # https://github.com/nazar-pc/docker-phpmyadmin/blob/master/config.inc.php 21 | 22 | cat > /opt/phpMyAdmin/config.inc.php <<'EOL' 23 | /opt/status/db.php <<'EOL' 77 | \nError connecting to MySQL server.\n"); 83 | 84 | EOL 85 | 86 | cat > /opt/status/index.php <<'EOL' 87 |

'; 95 | while ($row = mysqli_fetch_row($result)) 96 | { 97 | if ($row[0] != 'information_schema' && $row[0] != 'performance_schema' && $row[0] != 'mysql' && $row[0] != 'sys') 98 | { 99 | echo ''; 100 | echo ""; 101 | echo ""; 102 | $tables = mysqli_query($link, "SELECT TABLE_NAME,TABLE_ROWS,DATA_LENGTH,INDEX_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA LIKE '$row[0]'"); 103 | if (!$tables) die("Error: " . mysqli_error($link)); 104 | $total_rows = 0; 105 | $total_data = 0; 106 | $total_index = 0; 107 | while ($table = mysqli_fetch_row($tables)) 108 | { 109 | $table_mb = array(); 110 | $table_mb[2] = round($table[2] / (1024*1024), 2); 111 | $table_mb[3] = round($table[3] / (1024*1024), 2); 112 | echo ""; 113 | $total_rows += $table[1]; 114 | $total_data += $table[2]; 115 | $total_index += $table[3]; 116 | } 117 | $total_data_mb = round($total_data / (1024*1024), 2); 118 | $total_index_mb = round($total_index / (1024*1024), 2); 119 | echo ""; 120 | echo '
$row[0]
TABLE NAMETABLE ROWSDATA LENGTHINDEX LENGTH
$table[0]$table[1]$table_mb[2]$table_mb[3]
TOTAL$total_rows$total_data_mb$total_index_mb



'; 121 | } 122 | } 123 | 124 | echo ''; 125 | echo ''; 126 | echo ''; 127 | echo ''; 128 | echo ''; 129 | echo ''; 130 | echo '
server_info' . mysqli_get_server_info($link) . '
server_version' . mysqli_get_server_version($link) . '
client_info' . mysqli_get_client_info($link) . '
client_version' . mysqli_get_client_version($link) . '
stat' . mysqli_stat($link) . '



'; 131 | 132 | // https://mariadb.com/kb/en/mariadb/show-processlist/ 133 | $result = mysqli_query($link, 'SHOW FULL PROCESSLIST'); 134 | if (!$result) die("Error: " . mysqli_error($link)); 135 | 136 | echo ''; 137 | echo ''; 138 | while ($row = mysqli_fetch_row($result)) 139 | { 140 | echo ''; 141 | for($i = 0; $i < count($row); $i++) echo ''; 142 | echo ''; 143 | } 144 | echo '
IDUSERHOSTDBCOMMANDTIMESTATEINFOPROGRESS
' . $row[$i] . '



'; 145 | 146 | // https://mariadb.com/kb/en/mariadb/information-schema-processlist-table/ 147 | $result = mysqli_query($link, 'SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST'); 148 | if (!$result) die("Error: " . mysqli_error($link)); 149 | 150 | echo ''; 151 | echo ''; 152 | echo ''; 153 | echo ''; 154 | while ($row = mysqli_fetch_row($result)) 155 | { 156 | echo ''; 157 | for($i = 0; $i < count($row); $i++) echo ''; 158 | echo ''; 159 | } 160 | echo '
IDUSERHOSTDBCOMMANDTIMESTATEINFOTIME_MSSTAGEMAX_STAGEPROGRESSMEMORY_USEDEXAMINED_ROWSQUERY_IDINFO_BINARYTID
' . $row[$i] . '



'; 161 | 162 | echo ''; 163 | 164 | $result = mysqli_query($link, 'SHOW ENGINE INNODB STATUS'); 165 | if (!$result) die("Error: " . mysqli_error($link)); 166 | $row = mysqli_fetch_row($result); 167 | 168 | echo "
$row[2]

\r\n"; 169 | 170 | EOL 171 | 172 | cat > /opt/status/vars.php <<'EOL' 173 | '; 181 | while ($row = mysqli_fetch_row($result)) 182 | { 183 | echo ''; 184 | for($i = 0; $i < count($row); $i++) echo ''; 185 | echo ''; 186 | } 187 | echo '
' . $row[$i] . '

'; 188 | 189 | EOL 190 | 191 | cat > /opt/status/status.php <<'EOL' 192 | '; 200 | while ($row = mysqli_fetch_row($result)) 201 | { 202 | echo ''; 203 | for($i = 0; $i < count($row); $i++) echo ''; 204 | echo ''; 205 | } 206 | echo '
' . $row[$i] . '

'; 207 | 208 | EOL 209 | 210 | cat > /opt/status/table.php <<'EOL' 211 | '; 219 | echo 'NameEngineVersionRow_formatRowsAvg_row_lengthData_lengthMax_data_lengthIndex_lengthData_freeAuto_incrementCreate_timeUpdate_timeCheck_timeCollationChecksumCreate_optionsComment'; 220 | while ($row = mysqli_fetch_row($result)) 221 | { 222 | echo ''; 223 | for($i = 0; $i < count($row); $i++) echo '' . $row[$i] . ''; 224 | echo ''; 225 | } 226 | echo '
'; 227 | 228 | EOL 229 | 230 | # Clean up 231 | rm /script_init.sh 232 | exit 0 233 | -------------------------------------------------------------------------------- /app/phpmyadmin/script_run_aux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "

It works!

" > /home/webuser/www/public/index.html 4 | 5 | if [ -z "${PHPMYADMIN:+x}" ]; then 6 | if [ ! -L /home/webuser/www/public/pma ]; then 7 | ln -s /opt/phpMyAdmin /home/webuser/www/public/pma 8 | fi 9 | else 10 | if [ ! -L /home/webuser/www/public/$PHPMYADMIN ]; then 11 | ln -s /opt/phpMyAdmin /home/webuser/www/public/$PHPMYADMIN 12 | fi 13 | fi 14 | 15 | if [ -z "${PHPSTATUS:+x}" ]; then 16 | if [ ! -L /home/webuser/www/public/status ]; then 17 | ln -s /opt/status /home/webuser/www/public/status 18 | fi 19 | else 20 | if [ ! -L /home/webuser/www/public/$PHPSTATUS ]; then 21 | ln -s /opt/status /home/webuser/www/public/$PHPSTATUS 22 | fi 23 | fi 24 | 25 | echo $MYSQL_ROOT_PASSWORD > /opt/mysql_root_password.txt 26 | 27 | sed -i -e "s/__CaptchaPublic__/${CaptchaPublic}/" /opt/phpMyAdmin/config.inc.php 28 | sed -i -e "s/__CaptchaPrivate__/${CaptchaPrivate}/" /opt/phpMyAdmin/config.inc.php 29 | sed -i -e "s/__MYSQLSERVER__/${MYSQL_SERVER}/" /opt/phpMyAdmin/config.inc.php 30 | sed -i -e "s/__MYSQLSERVER__/${MYSQL_SERVER}/" /opt/status/db.php 31 | -------------------------------------------------------------------------------- /app/wordpress/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fffaraz/web/php7nginx:latest 2 | ADD script_*.sh / 3 | RUN chown root:root /script_*.sh && chmod 544 /script_*.sh && sync && /script_init.sh 4 | -------------------------------------------------------------------------------- /app/wordpress/script_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | wget https://wordpress.org/latest.tar.gz 5 | tar xf latest.tar.gz --strip-components=1 6 | rm latest.tar.gz 7 | 8 | mv wp-config-sample.php wp-config.php 9 | sed -i s/database_name_here/$WP_DB_NAME/ wp-config.php 10 | sed -i s/username_here/$WP_DB_USERNAME/ wp-config.php 11 | sed -i s/password_here/$WP_DB_PASSWORD/ wp-config.php 12 | echo "define('FS_METHOD', 'direct');" >> wp-config.php 13 | 14 | curl "http://$WP_DOMAIN/wp-admin/install.php?step=2" \ 15 | --data-urlencode "weblog_title=$WP_DOMAIN"\ 16 | --data-urlencode "user_name=$WP_ADMIN_USERNAME" \ 17 | --data-urlencode "admin_email=$WP_ADMIN_EMAIL" \ 18 | --data-urlencode "admin_password=$WP_ADMIN_PASSWORD" \ 19 | --data-urlencode "admin_password2=$WP_ADMIN_PASSWORD" \ 20 | --data-urlencode "pw_weak=1" 21 | 22 | echo "add_filter( 'allow_dev_auto_core_updates', '__return_false' );" >> wp-config.php 23 | echo "add_filter( 'allow_minor_auto_core_updates', '__return_true' );" >> wp-config.php 24 | echo "add_filter( 'allow_major_auto_core_updates', '__return_true' );" >> wp-config.php 25 | echo "add_filter( 'auto_update_plugin', '__return_true' );" >> wp-config.php 26 | echo "add_filter( 'auto_update_theme', '__return_true' );" >> wp-config.php 27 | 28 | echo "define('DISALLOW_FILE_EDIT', true);" >> wp-config.php 29 | 30 | sed -i "s/define('AUTH_KEY',\s*'put your unique phrase here');/define('AUTH_KEY', '`pwgen -1 -s 64`');/" wp-config.php 31 | sed -i "s/define('SECURE_AUTH_KEY',\s*'put your unique phrase here');/define('SECURE_AUTH_KEY', '`pwgen -1 -s 64`');/" wp-config.php 32 | sed -i "s/define('LOGGED_IN_KEY',\s*'put your unique phrase here');/define('LOGGED_IN_KEY', '`pwgen -1 -s 64`');/" wp-config.php 33 | sed -i "s/define('NONCE_KEY',\s*'put your unique phrase here');/define('NONCE_KEY', '`pwgen -1 -s 64`');/" wp-config.php 34 | sed -i "s/define('AUTH_SALT',\s*'put your unique phrase here');/define('AUTH_SALT', '`pwgen -1 -s 64`');/" wp-config.php 35 | sed -i "s/define('SECURE_AUTH_SALT',\s*'put your unique phrase here');/define('SECURE_AUTH_SALT', '`pwgen -1 -s 64`');/" wp-config.php 36 | sed -i "s/define('LOGGED_IN_SALT',\s*'put your unique phrase here');/define('LOGGED_IN_SALT', '`pwgen -1 -s 64`');/" wp-config.php 37 | sed -i "s/define('NONCE_SALT',\s*'put your unique phrase here');/define('NONCE_SALT', '`pwgen -1 -s 64`');/" wp-config.php 38 | 39 | rm $WP_PATH/public/readme* 40 | 41 | # https://github.com/wp-cli/wp-cli 42 | 43 | # Clean up 44 | rm /script_init.sh 45 | -------------------------------------------------------------------------------- /app/wordpress/script_run_aux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | -------------------------------------------------------------------------------- /balancer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:latest 2 | ENTRYPOINT ["/script_run.sh"] 3 | ADD script_*.sh / 4 | RUN chown root:root /script_*.sh && chmod 544 /script_*.sh && sync && /script_init.sh 5 | -------------------------------------------------------------------------------- /balancer/script_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | #export DEBIAN_FRONTEND=noninteractive 5 | #apt update 6 | #apt -y upgrade 7 | #apt -y install bash nano wget 8 | 9 | echo " 10 | resolver 127.0.0.11 valid=30s ipv6=off; 11 | resolver_timeout 5s; 12 | " > /etc/nginx/conf.d/resolver.conf 13 | 14 | echo " 15 | proxy_connect_timeout 600; 16 | proxy_send_timeout 600; 17 | proxy_read_timeout 600; 18 | send_timeout 600; 19 | " > /etc/nginx/conf.d/timeout.conf 20 | 21 | # Clean up 22 | rm -rf /var/lib/apt/lists/* 23 | rm /script_init.sh 24 | exit 0 25 | -------------------------------------------------------------------------------- /balancer/script_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | #echo " 5 | #LOAD BALANCER SERVER 6 | #" > /usr/share/nginx/html/index.html 7 | 8 | /script_update.sh --no-reload 9 | exec nginx -g "daemon off;" 10 | -------------------------------------------------------------------------------- /balancer/script_update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | RELOADNGNIX=1 5 | [ $# -gt 0 ] && [ "$1" == "--no-reload" ] && RELOADNGNIX=0 6 | [ $# -gt 0 ] && [ "$1" == "--debug" ] && set -x 7 | 8 | [ ! -f /home/webuser/upstreams.conf ] && echo "# DOMAIN UPSTREAM1 [UPSTREAMS...]" > /home/webuser/upstreams.conf 9 | 10 | find /etc/nginx/conf.d -type f ! -name 'default.conf' -delete 11 | #rm -f /etc/nginx/conf.d/*.conf 12 | 13 | # https://stackoverflow.com/questions/34741571/nginx-tcp-forwarding-based-on-hostname 14 | 15 | COUNTER=0 16 | 17 | while read -r -a line; do 18 | COUNTER=$((COUNTER+1)) 19 | DOMAIN=${line[0]} 20 | SERVERNAME="server_name $DOMAIN;" 21 | UPSTREAMS="" 22 | for (( i=1; i<${#line[@]}; i++ )); do 23 | UPSTREAMS=$UPSTREAMS"server ${line[$i]};\n\t" 24 | done 25 | echo -e " 26 | upstream upstream_$COUNTER { 27 | least_conn; 28 | $UPSTREAMS 29 | } 30 | 31 | server { 32 | listen 80; 33 | $SERVERNAME 34 | #port_in_redirect off; 35 | location / { 36 | proxy_pass http://upstream_$COUNTER; 37 | proxy_redirect off; 38 | proxy_http_version 1.1; 39 | proxy_set_header Host \$host; 40 | proxy_set_header X-Real-IP \$remote_addr; 41 | proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; 42 | proxy_set_header X-Forwarded-Host \$server_name; 43 | proxy_set_header X-Forwarded-Proto \$scheme; 44 | } 45 | } 46 | " > /etc/nginx/conf.d/line_$COUNTER.conf 47 | 48 | done < <(sed -e '/^#/d' -e '/^$/d' /home/webuser/upstreams.conf) 49 | 50 | nginx -t 51 | [ $RELOADNGNIX -eq 1 ] && nginx -s reload 52 | 53 | exit 0 54 | -------------------------------------------------------------------------------- /docweb: -------------------------------------------------------------------------------- 1 | #!/bin/bash -i 2 | 3 | # Copyright 2016-2020 Faraz Fallahi 4 | # docweb is not responsible for misuse or for any damage that you may cause! 5 | # You agree that you use this software at your own risk. 6 | 7 | if [ "$(id -u)" != "0" ]; then 8 | echo "This script must be run as root" 1>&2 9 | exit 1 10 | fi 11 | 12 | if [ $# -lt 1 ]; then 13 | echo "Usage: docweb COMMAND [ARGS]" 14 | exit 1 15 | fi 16 | 17 | if [ "$1" == "rm" ]; then 18 | # Remove stopped containers 19 | stopped_containers=$(docker ps -q -f status=exited) 20 | [ ! -z "$stopped_containers" ] && docker rm $stopped_containers 21 | 22 | # Remove orphaned images 23 | dangling_images=$(docker images -q -f dangling=true) 24 | [ ! -z "$dangling_images" ] && docker rmi $dangling_images 25 | 26 | # Remove orphaned volumes 27 | dangling_volumes=$(docker volume ls -q -f dangling=true) 28 | [ ! -z "$dangling_volumes" ] && docker volume rm $dangling_volumes 29 | 30 | exit 0 31 | fi 32 | 33 | if [ "$1" == "rm:all" ]; then 34 | $0 rm 35 | 36 | # Remove all containers and volumes 37 | containers=$(docker ps -a -q) 38 | [ ! -z "$containers" ] && docker stop $containers 39 | [ ! -z "$containers" ] && docker rm $containers 40 | 41 | volumes=$(docker volume ls -q) 42 | [ ! -z "$volumes" ] && docker volume rm $volumes 43 | 44 | $0 rm 45 | exit 0 46 | # TODO: docker system prune 47 | # https://github.com/RobLoach/docker-clean 48 | fi 49 | 50 | if [ "$1" == "rm:img" ]; then 51 | # Remove all images 52 | docker rmi $(docker images -q) 53 | exit 0 54 | fi 55 | 56 | if [ "$1" == "build" ]; then 57 | shift 58 | if [ $# -lt 1 ]; then 59 | echo "Usage: docweb build IMAGE" 60 | exit 1 61 | fi 62 | if [ ! -d /opt/dockerweb/$1 ]; then 63 | echo "Directory /opt/dockerweb/$1 doesn't exist" 64 | exit 1 65 | fi 66 | cd /opt/dockerweb/$1 67 | docker build --no-cache -t fffaraz/$1:latest --rm=true -f Dockerfile . 68 | cd ~- 69 | exit 0 70 | fi 71 | 72 | if [ "$1" == "build:all" ] || [ "$1" == "build:core" ]; then 73 | set -euxo pipefail 74 | 75 | $0 build proxy/base 76 | $0 build proxy 77 | $0 build balancer 78 | $0 build web/php7nginx/base 79 | $0 build web/php7nginx 80 | $0 build web/php7apache 81 | $0 build app/phpmyadmin 82 | 83 | echo DONE 84 | exit 0 85 | fi 86 | 87 | if [ "$1" == "stats" ]; then 88 | shift 89 | echo 90 | uname -a 91 | echo 92 | docweb hostname 93 | hostname --all-fqdns 94 | hostname --all-ip-addresses 95 | echo 96 | lsb_release -a 97 | echo 98 | /usr/lib/update-notifier/apt-check --human-readable 99 | echo 100 | apt list --upgradable 101 | echo 102 | uptime 103 | echo 104 | w -i 105 | echo 106 | free -h 107 | echo 108 | vmstat 109 | echo 110 | df -h | grep --color=never -e Filesystem -e '^/dev/' 111 | echo 112 | df -i | grep --color=never -e Filesystem -e '^/dev/' 113 | echo 114 | iostat 115 | echo 116 | ss -s 117 | #docker system df 118 | #smem -tw 119 | #smem -tu 120 | 121 | echo 122 | echo -------------------------------------------------------------------------------- 123 | echo 124 | 125 | docker stats --no-stream $(docker ps --format={{.Names}}) 126 | # alias ds='while true; do TEXT=$(docker stats --no-stream $(docker ps --format={{.Names}})); sleep 0.1; clear; echo "$TEXT"; done' 127 | # https://www.datadoghq.com/blog/how-to-collect-docker-metrics/ 128 | 129 | if [ "$1" == "-f" ]; then 130 | #cat /etc/lsb-release 131 | #cat /proc/cpuinfo 132 | #cat /proc/meminfo 133 | #cat /proc/mdstat 134 | #cat cat /etc/os-release 135 | #cat cat /etc/lsb-release 136 | #dmesg | grep Memory 137 | #lsof +D /home 138 | #dstat -tdD total 60 139 | 140 | echo 141 | echo -------------------------------------------------------------------------------- 142 | echo 143 | echo Disk Usage: 144 | echo 145 | #du -sm /home/* 146 | du -sh /home/* 147 | 148 | echo 149 | echo -------------------------------------------------------------------------------- 150 | echo 151 | echo Number of Files: 152 | echo 153 | for i in $(find /home/* -maxdepth 0 -type d); do 154 | echo -n $i" : " 155 | find $i -type f | wc -l 156 | done 157 | 158 | fi 159 | echo 160 | exit 0 161 | fi 162 | 163 | if [ "$1" == "ps" ]; then 164 | shift 165 | if [ $# -lt 1 ]; then 166 | docker ps -a -s --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Size}}" 167 | exit 0 168 | fi 169 | docker exec "$1" ps -o user,comm,pid,ppid,pgid,time,vsz,rss,args 170 | exit 0 171 | fi 172 | 173 | if [ "$1" == "status" ]; then 174 | shift 175 | if [ $# -lt 1 ]; then 176 | echo "Usage: docweb status NAME" 177 | exit 1 178 | fi 179 | # user,group,comm,pid,ppid,pgid,etime,nice,rgroup,ruser,time,tty,vsz,stat,rss,args 180 | RESULT=$(docker exec "$1" ps -axo user,comm,pid,ppid,pgid,time,vsz,rss,args | grep -v "ps -axo ") 181 | echo "$RESULT" | grep -v "php-fpm: pool webuser" 182 | echo "$RESULT" | grep "php-fpm: pool webuser" 183 | # killall -9 php 184 | exit 0 185 | fi 186 | 187 | if [ "$1" == "run" ]; then 188 | shift 189 | 190 | RUNARGS="-d --restart=always" 191 | if [ "$1" == "--debug" ]; then 192 | shift 193 | RUNARGS="-it --rm" 194 | fi 195 | if [ "$1" == "--bash" ]; then 196 | shift 197 | RUNARGS="-it --rm --entrypoint /bin/bash" 198 | fi 199 | 200 | HTTPPORT="" 201 | if [ "$1" == "--direct" ]; then 202 | shift 203 | HTTPPORT="-p $1:80" 204 | echo "Exposing HTTP Port $1" 205 | shift 206 | fi 207 | 208 | SSHPORT="" 209 | if [ $# -eq 4 ]; then 210 | SSHPORT="-e WEBUSER_PASSWORD=$3 -p $4:22" 211 | echo "Exposing SSH Port $4" 212 | fi 213 | 214 | if [ $# -lt 2 ]; then 215 | echo "Usage: docweb run [--debug|--bash] [--direct PORT] IMAGE NAME [WEBUSER_PASSWORD SSH_PORT]" 216 | exit 1 217 | fi 218 | 219 | if [[ "$(docker images -q fffaraz/web/$1:latest 2> /dev/null)" == "" ]]; then 220 | echo "Docker image fffaraz/web/$1:latest doesn't exist" 221 | exit 1 222 | fi 223 | 224 | if [ "$2" == "proxy" ]; then 225 | echo "The name 'proxy' is reserved for the reverse proxy server container" 226 | exit 1 227 | fi 228 | 229 | ISRUNNING=$(docker inspect --format={{.State.Running}} $2 2> /dev/null) 230 | if [ $? -eq 0 ]; then 231 | echo "Stopping the running instance ..." 232 | docker stop $2 233 | docker rm $2 234 | fi 235 | 236 | mkdir -p /home/$2 237 | 238 | docker run $RUNARGS \ 239 | --name=$2 \ 240 | --hostname=$2 \ 241 | --net=isolated_nw \ 242 | --volume=/home/$2:/home/webuser \ 243 | -w=/home/webuser \ 244 | --memory=512m \ 245 | $HTTPPORT \ 246 | $SSHPORT \ 247 | fffaraz/web/$1:latest 248 | # --ulimit =[:] 249 | # --ulimit nproc=64:64 250 | # --memory-swap=512m 251 | # --kernel-memory=8M 252 | # --cap-drop=all --cap-add=NET_BIND_SERVICE 253 | 254 | exit 0 255 | fi 256 | 257 | if [ "$1" == "log" ]; then 258 | shift 259 | if [ $# -lt 1 ]; then 260 | echo "Usage: docweb log NAME" 261 | exit 1 262 | fi 263 | docker logs -f $1 264 | exit 0 265 | fi 266 | 267 | if [ "$1" == "stop" ]; then 268 | shift 269 | if [ $# -lt 1 ]; then 270 | echo "Usage: docweb stop NAME" 271 | exit 1 272 | fi 273 | docker stop --time 86400 $1 274 | #docker kill $1 275 | #docker kill --signal TERM $1 276 | docker rm $1 277 | exit 0 278 | fi 279 | 280 | if [ "$1" == "exec" ]; then 281 | shift 282 | RUNASROOT=0 283 | if [ "$1" = "--root" ]; then 284 | shift 285 | RUNASROOT=1 286 | fi 287 | 288 | if [ $# -lt 1 ]; then 289 | echo "Usage: docweb exec [--root] NAME" 290 | exit 1 291 | fi 292 | 293 | if [ $RUNASROOT -eq 1 ]; then 294 | docker exec -it -e COLUMNS=$COLUMNS -e LINES=$LINES -e TERM=$TERM $1 /bin/bash -c 'cd /home/webuser/www; exec /bin/bash -i -l' 295 | else 296 | docker exec -it --user webuser -e COLUMNS=$COLUMNS -e LINES=$LINES -e TERM=$TERM $1 /bin/bash -c 'cd /home/webuser/www; exec /bin/bash -i -l' 297 | fi 298 | 299 | exit 0 300 | fi 301 | 302 | if [ "$1" == "clean" ]; then 303 | shift 304 | if [ $# -lt 1 ]; then 305 | echo "Usage: docweb clean NAME" 306 | exit 1 307 | fi 308 | if [ ! -d /home/$1 ]; then 309 | echo "Directory /home/$1 doesn't exist" 310 | exit 1 311 | fi 312 | rm -rf /home/$1/tmp 313 | rm -rf /home/$1/log 314 | exit 0 315 | fi 316 | 317 | if [ "$1" == "update" ]; then 318 | shift 319 | if [ $# -lt 1 ]; then 320 | echo "Usage: docweb update NAME [args]" 321 | exit 1 322 | fi 323 | docker exec -it $1 /script_update.sh $@ 324 | exit 0 325 | fi 326 | 327 | if [ "$1" == "backup" ]; then 328 | shift 329 | if [ $# -lt 1 ]; then 330 | echo "Usage: docweb backup NAME" 331 | exit 1 332 | fi 333 | if [ ! -d /home/$1 ]; then 334 | echo "Directory /home/$1 doesn't exist" 335 | exit 1 336 | fi 337 | if [ "$1" == "backup" ]; then 338 | echo "Can't backup the backup directory!" 339 | exit 1 340 | fi 341 | mkdir -p /home/backup 342 | FILEPATH=/home/backup/$1_$(date +%Y-%m-%d_%H-%M-%S).tar.gz 343 | # TODO: pigz 344 | tar --exclude=$1/backup --exclude=$1/log --exclude=$1/tmp --directory=/home -czf $FILEPATH $1 345 | ls -lh $FILEPATH 346 | #gzip -v -t $FILEPATH 347 | exit 0 348 | fi 349 | 350 | if [ "$1" == "log:nginx" ]; then 351 | shift 352 | if [ $# -lt 1 ]; then 353 | echo "Usage: docweb log:nginx NAME [--access | --error]" 354 | exit 1 355 | fi 356 | if [ ! -d /home/$1 ]; then 357 | echo "Directory /home/$1 doesn't exist" 358 | exit 1 359 | fi 360 | if [ $# -eq 2 ] && [ "$2" == "--access" ]; then 361 | tail -f /home/$1/log/nginx/access.log 362 | elif [ $# -eq 2 ] && [ "$2" == "--error" ]; then 363 | tail -f /home/$1/log/nginx/error.log 364 | else 365 | tail -f /home/$1/log/nginx/*.log 366 | fi 367 | exit 0 368 | fi 369 | 370 | if [ "$1" == "log:php" ]; then 371 | shift 372 | if [ $# -lt 1 ]; then 373 | echo "Usage: docweb log:php NAME [--access | --error | --mail]" 374 | exit 1 375 | fi 376 | if [ ! -d /home/$1 ]; then 377 | echo "Directory /home/$1 doesn't exist" 378 | exit 1 379 | fi 380 | if [ $# -eq 2 ] && [ "$2" == "--access" ]; then 381 | tail -f /home/$1/log/php/access.log 382 | elif [ $# -eq 2 ] && [ "$2" == "--error" ]; then 383 | tail -f /home/$1/log/php/error.log 384 | elif [ $# -eq 2 ] && [ "$2" == "--mail" ]; then 385 | tail -f /home/$1/log/php/mail.log 386 | else 387 | tail -f /home/$1/log/php/*.log 388 | fi 389 | exit 0 390 | fi 391 | 392 | if [ "$1" == "proxy:run" ]; then 393 | shift 394 | # docweb proxy:run [--debug] [SERVER_NAME] 395 | ISRUNNING=$(docker inspect --format={{.State.Running}} proxy 2> /dev/null) 396 | if [ $? -eq 0 ]; then 397 | echo "Stopping the running instance ..." 398 | docker stop proxy 399 | docker rm proxy 400 | fi 401 | 402 | RUNARG="-d --restart=always" 403 | if [ "$1" = "--debug" ]; then 404 | shift 405 | RUNARG="-it --rm" 406 | fi 407 | 408 | mkdir -p /home/proxy 409 | mkdir -p /home/proxy/ssl/etc 410 | mkdir -p /home/proxy/ssl/lib 411 | mkdir -p /home/proxy/ssl/log 412 | mkdir -p /home/proxy/ssl/default 413 | 414 | docker run $RUNARG \ 415 | --name=proxy \ 416 | --hostname=$(docweb hostname) \ 417 | --net=isolated_nw \ 418 | --memory=512m \ 419 | -p 80:80 -p 443:443 \ 420 | -v /home/proxy:/home/webuser \ 421 | -v /home/proxy/ssl/etc:/etc/letsencrypt \ 422 | -v /home/proxy/ssl/lib:/var/lib/letsencrypt \ 423 | -v /home/proxy/ssl/log:/var/log/letsencrypt \ 424 | -v /home/proxy/ssl/default:/opt/nginx/conf/cert \ 425 | -e CERTEMAIL="fffaraz@gmail.com" \ 426 | fffaraz/proxy:latest \ 427 | $@ 428 | 429 | exit 0 430 | fi 431 | 432 | if [ "$1" == "proxy:update" ]; then 433 | shift 434 | docker exec -i proxy /script_update.sh $@ 435 | exit 0 436 | fi 437 | 438 | if [ "$1" == "balancer:run" ]; then 439 | shift 440 | ISRUNNING=$(docker inspect --format={{.State.Running}} balancer 2> /dev/null) 441 | if [ $? -eq 0 ]; then 442 | echo "Stopping the running instance ..." 443 | docker stop balancer 444 | docker rm balancer 445 | fi 446 | 447 | RUNARG="-d --restart=always" 448 | if [ "$1" = "--debug" ]; then 449 | shift 450 | RUNARG="-it --rm" 451 | fi 452 | 453 | mkdir -p /home/balancer 454 | docker run $RUNARG \ 455 | --name=balancer \ 456 | --net=isolated_nw \ 457 | --memory=512m \ 458 | -v /home/balancer:/home/webuser \ 459 | fffaraz/balancer:latest 460 | 461 | exit 0 462 | fi 463 | 464 | if [ "$1" == "balancer:update" ]; then 465 | shift 466 | docker exec -i balancer /script_update.sh $@ 467 | exit 0 468 | fi 469 | 470 | if [ "$1" == "proxy:log" ]; then 471 | shift 472 | if [ $# -eq 1 ] && [ "$1" == "--trafic" ]; then 473 | tail -f /home/proxy/log/nginx/trafic.log 474 | elif [ $# -eq 1 ] && [ "$1" == "--error" ]; then 475 | tail -f /home/proxy/log/nginx/error.log 476 | else 477 | tail -f /home/proxy/log/nginx/*.log 478 | fi 479 | exit 0 480 | fi 481 | 482 | if [ "$1" == "proxy:status" ]; then 483 | shift 484 | # https://github.com/lebinh/ngxtop 485 | # https://github.com/allinurl/goaccess 486 | exit 0 487 | fi 488 | 489 | if [ "$1" == "hostname" ]; then 490 | shift 491 | H1=$(hostname --fqdn) 492 | H2=$(hostnamectl --static) 493 | [ ${#H1} -ge ${#H2} ] && echo $H1 || echo $H2 494 | exit 0 495 | fi 496 | 497 | if [ "$1" == "ip" ]; then 498 | shift 499 | IPV4=$(dig +short myip.opendns.com @208.67.222.222 a) || IPV4="" 500 | echo "Your IPv4 address is: $IPV4" 501 | IPV6=$(dig +short myip.opendns.com @2620:0:ccc::2 aaaa) || IPV6="" 502 | echo "Your IPv6 address is: $IPV6" 503 | exit 0 504 | fi 505 | 506 | if [ "$1" == "microdns:run" ]; then 507 | shift 508 | 509 | DNSTTL="-ttl 3600" 510 | if [ "$1" = "--ttl" ]; then 511 | shift 512 | DNSTTL="-ttl $1" 513 | shift 514 | fi 515 | 516 | DNSLOG="" 517 | if [ "$1" = "--log" ]; then 518 | shift 519 | DNSLOG="-log" 520 | fi 521 | 522 | #curl -s http://whatismyip.akamai.com/ 523 | IPV4=$(dig +short myip.opendns.com @208.67.222.222 a) || IPV4="" 524 | echo "Your IPv4 address is: $IPV4" 525 | IPV6=$(dig +short myip.opendns.com @2620:0:ccc::2 aaaa) || IPV6="" 526 | echo "Your IPv6 address is: $IPV6" 527 | 528 | [ ! -z "$IPV4" ] && IPV4="-ipv4 $IPV4" 529 | [ ! -z "$IPV6" ] && IPV6="-ipv6 $IPV6" 530 | 531 | ISRUNNING=$(docker inspect --format={{.State.Running}} microdns 2> /dev/null) 532 | [ $? -eq 0 ] && docker rm -f microdns 533 | 534 | mkdir -p /home/microdns 535 | [ ! -f /home/microdns/dns.conf ] && echo "# domain. IPv4 IPv6" > /home/microdns/dns.conf 536 | 537 | docker run -d --restart=always \ 538 | --name microdns -p 53:53 -p 53:53/udp \ 539 | --memory 16m \ 540 | -v /home/microdns:/home \ 541 | fffaraz/microdns:latest \ 542 | $IPV4 $IPV6 $DNSTTL $DNSLOG -conf /home/dns.conf 543 | 544 | exit 0 545 | fi 546 | 547 | if [ "$1" == "microdns:log" ]; then 548 | docker logs -f --tail 1000 microdns 549 | exit 0 550 | fi 551 | 552 | if [ "$1" == "bind:run" ]; then 553 | shift 554 | 555 | ISRUNNING=$(docker inspect --format={{.State.Running}} bind 2> /dev/null) 556 | [ $? -eq 0 ] && docker rm -f bind 557 | 558 | mkdir -p /home/bind 559 | 560 | docker run -d --restart=always \ 561 | --name bind --memory 64m \ 562 | --hostname=$(docweb hostname) \ 563 | -p 53:53 -p 53:53/udp \ 564 | -v /home/bind:/data \ 565 | fffaraz/bind 566 | 567 | exit 0 568 | fi 569 | 570 | if [ "$1" == "bind:webmin" ]; then 571 | shift 572 | 573 | if [ $# -lt 2 ]; then 574 | echo "Usage: docweb bind:webmin ROOT_PASSWORD WEBMIN_ENABLED" 575 | exit 1 576 | fi 577 | 578 | ISRUNNING=$(docker inspect --format={{.State.Running}} bindwebmin 2> /dev/null) 579 | [ $? -eq 0 ] && docker rm -f bindwebmin 580 | 581 | mkdir -p /home/bindwebmin 582 | 583 | docker run -d --restart=always \ 584 | --name bindwebmin --memory 128m \ 585 | --hostname=$(docweb hostname) \ 586 | -p 53:53 -p 53:53/udp -p 90:10000 \ 587 | -v /home/bindwebmin:/data \ 588 | -e ROOT_PASSWORD="$1" \ 589 | -e WEBMIN_ENABLED="$2" \ 590 | fffaraz/bindwebmin 591 | 592 | exit 0 593 | fi 594 | 595 | if [ "$1" == "coredns:run" ]; then 596 | shift 597 | # https://github.com/miekg/coredns 598 | exit 0 599 | fi 600 | 601 | if [ "$1" == "pma:run" ]; then 602 | shift 603 | 604 | RUNARG="-d --restart=always" 605 | if [ "$1" = "--debug" ]; then 606 | shift 607 | RUNARG="-it --rm" 608 | fi 609 | 610 | HTTPPORT="" 611 | if [ "$1" = "--direct" ]; then 612 | shift 613 | HTTPPORT="-p $1:80" 614 | echo "Exposing HTTP Port $1" 615 | shift 616 | fi 617 | 618 | if [ $# -lt 2 ]; then 619 | echo "Usage: docweb pma:run [--debug] [--direct PORT] MYSQLSERVER MYSQLROOTPASSWORD [pma status] [CaptchaPublic CaptchaPrivate]" 620 | # TODO: controluser controlpass pmadb 621 | exit 1 622 | fi 623 | 624 | ISRUNNING=$(docker inspect --format={{.State.Running}} ${1}_pma 2> /dev/null) 625 | [ $? -eq 0 ] && docker rm -f ${1}_pma 626 | 627 | PHPMYADMIN=pma 628 | PHPSTATUS=status 629 | if [ $# -eq 4 ]; then 630 | PHPMYADMIN=$3 631 | PHPSTATUS=$4 632 | fi 633 | 634 | CaptchaPublic= 635 | CaptchaPrivate= 636 | if [ $# -eq 6 ]; then 637 | CaptchaPublic=$5 638 | CaptchaPrivate=$6 639 | fi 640 | 641 | docker run $RUNARG \ 642 | --name=${1}_pma \ 643 | --net=isolated_nw \ 644 | --memory=512m \ 645 | $HTTPPORT \ 646 | -e MYSQL_SERVER="$1" \ 647 | -e MYSQL_ROOT_PASSWORD="$2" \ 648 | -e PHPMYADMIN="$PHPMYADMIN" \ 649 | -e PHPSTATUS="$PHPSTATUS" \ 650 | -e CaptchaPublic="$CaptchaPublic" \ 651 | -e CaptchaPrivate="$CaptchaPrivate" \ 652 | fffaraz/app/phpmyadmin:latest 653 | 654 | exit 0 655 | fi 656 | 657 | if [ "$1" == "glances:run" ]; then 658 | shift 659 | if [ $# -lt 1 ]; then 660 | echo "Usage: docweb glances:run HASH" 661 | exit 1 662 | fi 663 | 664 | killall glances 665 | #mkdir -p /etc/glances 666 | #echo -n $1 > /etc/glances/glances.pwd 667 | mkdir -p ~/.config/glances 668 | echo -n $1 > ~/.config/glances/glances.pwd 669 | 670 | if [ $# -gt 1 ]; then 671 | nohup glances -w -B 172.17.0.1 --disable-plugin $2 --password & 672 | else 673 | nohup glances -w -B 172.17.0.1 --password & 674 | fi 675 | exit 0 676 | fi 677 | 678 | if [ "$1" == "redis:run" ]; then 679 | shift 680 | 681 | RUNARGS="-d --restart=always" 682 | if [ "$1" == "--debug" ]; then 683 | shift 684 | RUNARGS="-it --rm" 685 | fi 686 | 687 | REDISPORT="" 688 | if [ "$1" = "--direct" ]; then 689 | shift 690 | REDISPORT="-p $1:6379" 691 | echo "Exposing Redis Port $1" 692 | shift 693 | fi 694 | 695 | if [ $# -lt 2 ]; then 696 | echo "Usage: docweb redis:run [--debug] [--direct PORT] NAME PASSWORD" 697 | exit 1 698 | fi 699 | 700 | ISRUNNING=$(docker inspect --format={{.State.Running}} $1 2> /dev/null) 701 | if [ $? -eq 0 ]; then 702 | echo "Stopping the running instance ..." 703 | docker stop $1 704 | docker rm $1 705 | fi 706 | 707 | mkdir -p /home/$1/data 708 | 709 | # /myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf 710 | 711 | docker run $RUNARGS \ 712 | --name="$1" \ 713 | --hostname="$1" \ 714 | --net=isolated_nw \ 715 | --memory=512m \ 716 | --volume=/home/$1/data:/data \ 717 | $REDISPORT \ 718 | redis:alpine redis-server --appendonly yes --requirepass "$2" 719 | 720 | exit 0 721 | fi 722 | 723 | if [ "$1" == "postgres:run" ]; then 724 | shift 725 | 726 | RUNARGS="-d --restart=always" 727 | if [ "$1" == "--debug" ]; then 728 | shift 729 | RUNARGS="-it --rm" 730 | fi 731 | 732 | if [ $# -lt 2 ]; then 733 | echo "Usage: docweb postgres:run [--debug] NAME POSTGRES_ROOT_PASSWORD" 734 | exit 1 735 | fi 736 | 737 | ISRUNNING=$(docker inspect --format={{.State.Running}} $1 2> /dev/null) 738 | if [ $? -eq 0 ]; then 739 | echo "Stopping the running instance ..." 740 | docker stop $1 741 | docker rm $1 742 | fi 743 | 744 | mkdir -p /home/$1/log 745 | mkdir -p /home/$1/data 746 | mkdir -p /home/$1/backup 747 | mkdir -p /home/$1/entrypoint 748 | 749 | docker run $RUNARGS \ 750 | --name="$1" \ 751 | --hostname="$1" \ 752 | --net=isolated_nw \ 753 | --memory=512m \ 754 | -v /home/$1/backup:/backup \ 755 | -v /home/$1/log:/var/log/postgresql \ 756 | -v /home/$1/data:/var/lib/postgresql/data \ 757 | -v /home/$1/entrypoint:/docker-entrypoint-initdb.d \ 758 | -e POSTGRES_PASSWORD="$2" \ 759 | postgres:10 #latest 760 | 761 | exit 0 762 | fi 763 | 764 | if [ "$1" == "postgres:listdbs" ] || [ "$1" == "postgres:listdb" ]; then 765 | shift 766 | if [ $# -lt 1 ]; then 767 | echo "Usage: docweb postgres:listdbs NAME" 768 | exit 1 769 | fi 770 | docker exec -it $1 sh -c 'export COLUMNS=100; psql -U postgres -l' 771 | exit 0 772 | fi 773 | 774 | if [ "$1" == "postgres:backup" ]; then 775 | shift 776 | if [ $# -lt 1 ]; then 777 | echo "Usage: docweb postgres:backup NAME [DATABASE]" 778 | exit 1 779 | fi 780 | 781 | PSQLSERVER=$1 782 | shift 783 | 784 | ISRUNNING=$(docker inspect --format={{.State.Running}} $PSQLSERVER 2> /dev/null) 785 | if [ $? -ne 0 ]; then 786 | echo "PostgreSQL instance $PSQLSERVER is not running." 787 | exit 1 788 | fi 789 | 790 | mkdir -p /home/$PSQLSERVER/backup 791 | if [ $# -lt 1 ]; then 792 | docker exec -u postgres $PSQLSERVER pg_dumpall -U postgres -c > /home/$PSQLSERVER/backup/dump_$(date +%Y-%m-%d_%H-%M-%S).sql 793 | else 794 | docker exec -u postgres $PSQLSERVER pg_dump -U postgres -c $1 > /home/$PSQLSERVER/backup/dump_$1_$(date +%Y-%m-%d_%H-%M-%S).sql 795 | fi 796 | exit 0 797 | fi 798 | 799 | if [ "$1" == "postgres:clean" ]; then 800 | shift 801 | if [ $# -lt 1 ]; then 802 | echo "Usage: docweb postgres:clean NAME [DATABASE]" 803 | exit 1 804 | fi 805 | 806 | PSQLSERVER=$1 807 | shift 808 | 809 | ISRUNNING=$(docker inspect --format={{.State.Running}} $PSQLSERVER 2> /dev/null) 810 | if [ $? -ne 0 ]; then 811 | echo "PostgreSQL instance $PSQLSERVER is not running." 812 | exit 1 813 | fi 814 | 815 | if [ $# -lt 1 ]; then 816 | echo "DROP SCHEMA public CASCADE; CREATE SCHEMA public;" | docker exec -i $PSQLSERVER psql -U postgres 817 | else 818 | echo "DROP SCHEMA public CASCADE; CREATE SCHEMA public;" | docker exec -i $PSQLSERVER psql -U postgres -d $1 819 | fi 820 | exit 0 821 | fi 822 | 823 | if [ "$1" == "postgres:restore" ]; then 824 | shift 825 | if [ $# -lt 2 ]; then 826 | echo "Usage: docweb postgres:restore NAME FILENAME [DATABASE]" 827 | exit 1 828 | fi 829 | 830 | PSQLSERVER=$1 831 | shift 832 | 833 | ISRUNNING=$(docker inspect --format={{.State.Running}} $PSQLSERVER 2> /dev/null) 834 | if [ $? -ne 0 ]; then 835 | echo "PostgreSQL instance $PSQLSERVER is not running." 836 | exit 1 837 | fi 838 | 839 | if [ $# -lt 2 ]; then 840 | cat /home/$PSQLSERVER/backup/$1 | docker exec -i $PSQLSERVER psql -U postgres 841 | else 842 | cat /home/$PSQLSERVER/backup/$1 | docker exec -i $PSQLSERVER psql -U postgres -d $2 843 | fi 844 | exit 0 845 | fi 846 | 847 | if [ "$1" == "mysql:run" ]; then 848 | shift 849 | 850 | RUNARGS="-d --restart=always" 851 | if [ "$1" == "--debug" ]; then 852 | shift 853 | RUNARGS="-it --rm" 854 | fi 855 | 856 | MYSQLPORT="" 857 | if [ "$1" = "--direct" ]; then 858 | shift 859 | MYSQLPORT="-p $1:3306" 860 | echo "Exposing MySQL Port $1" 861 | shift 862 | fi 863 | 864 | MEMORY=512 865 | if [ "$1" == "--memory" ]; then 866 | shift 867 | MEMORY=$1 868 | shift 869 | fi 870 | 871 | SKIPGRANT="" 872 | if [ "$1" == "--skip-grant" ]; then 873 | shift 874 | SKIPGRANT="mysqld_safe --skip-grant-tables" 875 | fi 876 | 877 | SKIPNET="" 878 | if [ "$1" == "--skip-net" ]; then 879 | shift 880 | SKIPNET="--skip-networking" 881 | fi 882 | 883 | if [ $# -lt 2 ]; then 884 | echo "Usage: docweb mysql:run [--debug] [--direct PORT] [--memory M] [--skip-grant] [--skip-net] NAME MYSQL_ROOT_PASSWORD [mysql|mariadb|mysql/mysql-server]" 885 | exit 1 886 | fi 887 | 888 | ISRUNNING=$(docker inspect --format={{.State.Running}} $1 2> /dev/null) 889 | if [ $? -eq 0 ]; then 890 | echo "Stopping the running instance ..." 891 | docker stop --time 86400 $1 892 | docker rm $1 893 | fi 894 | 895 | # https://hub.docker.com/_/mysql/ 896 | # https://hub.docker.com/_/mariadb/ 897 | # https://hub.docker.com/r/mysql/mysql-server/ 898 | # https://hub.docker.com/_/percona/ 899 | # https://hub.docker.com/r/percona/percona-server/ 900 | # https://github.com/mysql/mysql-sys 901 | 902 | DBSERVER="mariadb" 903 | [[ $# -eq 3 ]] && DBSERVER="$3" 904 | echo "DBSERVER: $DBSERVER" 905 | 906 | rm -rf /home/$1/conf.d 907 | rm -rf /home/$1/log 908 | mkdir -p /home/$1/backup 909 | mkdir -p /home/$1/conf.d 910 | mkdir -p /home/$1/datadir 911 | mkdir -p /home/$1/entrypoint 912 | mkdir -p /home/$1/log 913 | chown -R 999:999 /home/$1/log 914 | 915 | cat > /home/$1/conf.d/global.cnf <<'EOL' 916 | [mysqld] 917 | default_storage_engine=InnoDB 918 | skip_name_resolve=1 919 | general_log=0 920 | general_log_file=/var/log/mysql/general.log 921 | innodb_fast_shutdown=0 922 | innodb_file_per_table=1 923 | innodb_lock_wait_timeout=120 924 | local_infile=0 925 | log_error=/var/log/mysql/error.log 926 | log_warnings=2 927 | long_query_time=1 928 | max_allowed_packet=1G 929 | max_connect_errors=1000000 930 | max_connections=500 931 | open_files_limit=100000 932 | performance_schema=0 933 | skip_external_locking=1 934 | slow_query_log=1 935 | slow_query_log_file=/var/log/mysql/slow.log 936 | log_queries_not_using_indexes=0 937 | character_set_server=utf8 938 | character_set_filesystem=utf8 939 | collation_server=utf8_unicode_ci 940 | # symbolic-links=0 941 | # character_set_results=utf8 942 | # character_set_client_handshake=utf8 943 | # character_set_connection=utf8 944 | # collation_connection=utf8_unicode_ci 945 | # sql_mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" 946 | # skip-innodb_doublewrite 947 | # innodb_doublewrite = 0 948 | 949 | [client] 950 | default-character-set=utf8 951 | 952 | [mysqldump] 953 | quick 954 | max_allowed_packet=1G 955 | 956 | [mysql] 957 | default-character-set=utf8 958 | no-auto-rehash 959 | 960 | EOL 961 | 962 | echo " 963 | [mysqld] 964 | binlog_cache_size=4K 965 | binlog_stmt_cache_size=4K 966 | innodb_buffer_pool_instances=1 967 | innodb_buffer_pool_size=$((MEMORY/4))M 968 | # innodb_log_file_size * innodb_log_files_in_group should be equals to 1/4 of buffer pool size 969 | # innodb_log_file_size=8M 970 | innodb_ft_cache_size=4M 971 | innodb_ft_total_cache_size=32M 972 | innodb_sort_buffer_size=8M 973 | join_buffer_size=4M 974 | key_buffer_size=256K 975 | max_heap_table_size=32M 976 | query_cache_limit=512K 977 | query_cache_min_res_unit=2K 978 | query_cache_size=32M 979 | query_cache_type=1 980 | read_buffer_size=1M 981 | read_rnd_buffer_size=1M 982 | sort_buffer_size=4M 983 | table_definition_cache=1K 984 | table_open_cache=2K 985 | thread_cache_size=16 986 | tmp_table_size=32M 987 | 988 | " > /home/$1/conf.d/limits.cnf 989 | 990 | # echo " 991 | # [client] 992 | # user=root 993 | # password=$2 994 | # host=127.0.0.1 995 | # " > /home/$1/conf.d/credentials.cnf 996 | 997 | docker run $RUNARGS \ 998 | --name="$1" \ 999 | --hostname="$1" \ 1000 | --net=isolated_nw \ 1001 | --memory=${MEMORY}m \ 1002 | $MYSQLPORT \ 1003 | -v /home/$1/backup:/backup \ 1004 | -v /home/$1/conf.d:/etc/mysql/conf.d \ 1005 | -v /home/$1/datadir:/var/lib/mysql \ 1006 | -v /home/$1/entrypoint:/docker-entrypoint-initdb.d \ 1007 | -v /home/$1/log:/var/log/mysql \ 1008 | -e MYSQL_ROOT_PASSWORD="$2" \ 1009 | ${DBSERVER}:latest $SKIPGRANT $SKIPNET 1010 | 1011 | # docker exec -it $1 sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e "FLUSH PRIVILEGES; SET PASSWORD FOR root = PASSWORD(\"$1\");"' 1012 | 1013 | exit 0 1014 | fi 1015 | 1016 | if [ "$1" == "mysql:stop" ]; then 1017 | shift 1018 | if [ $# -lt 1 ]; then 1019 | echo "Usage: docweb mysql:stop NAME" 1020 | exit 1 1021 | fi 1022 | #docker exec -it $1 sh -c 'exec mysqladmin -uroot -p"$MYSQL_ROOT_PASSWORD" shutdown' 1023 | #docker exec -it $1 sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e "SET GLOBAL innodb_fast_shutdown = 0"' 1024 | #sleep 2 1025 | docker stop --time 86400 $1 1026 | #docker kill --signal TERM $1 1027 | docker rm $1 1028 | exit 0 1029 | fi 1030 | 1031 | if [ "$1" == "mysql:upgrade" ]; then 1032 | shift 1033 | if [ $# -lt 1 ]; then 1034 | echo "Usage: docweb mysql:stop NAME" 1035 | exit 1 1036 | fi 1037 | docker exec -it $1 sh -c 'exec mysql_upgrade -uroot -p"$MYSQL_ROOT_PASSWORD"' 1038 | exit 0 1039 | fi 1040 | 1041 | if [ "$1" == "mysql:client" ]; then 1042 | shift 1043 | if [ $# -lt 1 ]; then 1044 | echo "Usage: docweb mysql:client NAME [--bash]" 1045 | exit 1 1046 | fi 1047 | if [ "$2" == "--bash" ]; then 1048 | docker exec -it $1 bash 1049 | else 1050 | docker exec -it $1 sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD"' 1051 | fi 1052 | exit 0 1053 | fi 1054 | 1055 | if [ "$1" == "mysql:status" ]; then 1056 | shift 1057 | if [ $# -lt 1 ]; then 1058 | echo "Usage: docweb mysql:status NAME" 1059 | exit 1 1060 | fi 1061 | # SHOW ENGINE INNODB STATUSG 1062 | printf "$(docker exec -it $1 sh -c 'exec mysql -N -B -uroot -p"$MYSQL_ROOT_PASSWORD" -e "SHOW ENGINE INNODB STATUS"')" 1063 | exit 0 1064 | fi 1065 | 1066 | if [ "$1" == "mysql:report" ]; then 1067 | shift 1068 | if [ $# -lt 1 ]; then 1069 | echo "Usage: docweb mysql:report NAME" 1070 | exit 1 1071 | fi 1072 | docker exec -it $1 sh -c 'exec mysqlreport --user root --password "$MYSQL_ROOT_PASSWORD"' 1073 | exit 0 1074 | fi 1075 | 1076 | if [ "$1" == "mysql:optimize" ]; then 1077 | shift 1078 | if [ $# -lt 1 ]; then 1079 | echo "Usage: docweb mysql:optimize NAME" 1080 | exit 1 1081 | fi 1082 | docker exec -it $1 sh -c 'exec mysqlcheck -o --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' 1083 | exit 0 1084 | fi 1085 | 1086 | if [ "$1" == "mysql:createuser" ]; then 1087 | shift 1088 | if [ "$#" -ne 3 ]; then 1089 | echo "Usage: docweb mysql:createuser NAME USERNAME PASSWORD" 1090 | exit 1 1091 | fi 1092 | 1093 | # FLUSH PRIVILEGES; 1094 | # CREATE USER IF NOT EXISTS '$2'@'%' IDENTIFIED WITH mysql_native_password BY '$3'; 1095 | # docker exec < sql.tmp 1104 | 1105 | cat sql.tmp | docker exec -i $1 sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD"' 1106 | rm sql.tmp 1107 | exit 0 1108 | fi 1109 | 1110 | if [ "$1" == "mysql:createdb" ]; then 1111 | shift 1112 | if [ "$#" -lt 2 ]; then 1113 | echo "Usage: docweb mysql:createdb MYSQLSERVER DBNAME" 1114 | exit 1 1115 | fi 1116 | echo "CREATE DATABASE IF NOT EXISTS \`$2\` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;" | docker exec -i $1 sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD"' 1117 | exit 0 1118 | fi 1119 | 1120 | if [ "$1" == "mysql:backup" ]; then 1121 | shift 1122 | if [ $# -lt 1 ]; then 1123 | echo "Usage: docweb mysql:backup NAME [--gzip] [DATABASES...]" 1124 | exit 1 1125 | fi 1126 | MYSQLSERVER=$1 1127 | shift 1128 | ISRUNNING=$(docker inspect --format={{.State.Running}} $MYSQLSERVER 2> /dev/null) 1129 | if [ $? -ne 0 ]; then 1130 | echo "MySQL instance $MYSQLSERVER is not running." 1131 | exit 1 1132 | fi 1133 | #set -x 1134 | if [ "$1" == "--gzip" ]; then 1135 | shift 1136 | if [ $# -lt 1 ]; then 1137 | docker exec -it $MYSQLSERVER sh -c \ 1138 | 'mysql -N -B -uroot -p"$MYSQL_ROOT_PASSWORD" -e "SHOW DATABASES;" | grep -v -e ^information_schema$ -e ^performance_schema$ -e ^mysql$ -e ^sys$ | xargs mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" --skip-comments --default-character-set=utf8 --databases | gzip -5 > /backup/dump_$(date +%Y-%m-%d_%H-%M-%S).sql.gz' 1139 | else 1140 | docker exec -it $MYSQLSERVER sh -c \ 1141 | "mysqldump -uroot -p\"\$MYSQL_ROOT_PASSWORD\" --skip-comments --default-character-set=utf8 --databases $(IFS=$' ' ; echo "$*") | gzip -5 > /backup/dump_$(IFS=_ ; echo "$*")_\$(date +%Y-%m-%d_%H-%M-%S).sql.gz" 1142 | if [ $# -eq 1 ] && [ -d /home/$1 ]; then 1143 | mkdir -p /home/$1/backup/db 1144 | mv /home/$MYSQLSERVER/backup/dump_${1}_*.sql.gz /home/$1/backup/db/ 1145 | fi 1146 | fi 1147 | else 1148 | if [ $# -lt 1 ]; then 1149 | docker exec -it $MYSQLSERVER sh -c \ 1150 | 'mysql -N -B -uroot -p"$MYSQL_ROOT_PASSWORD" -e "SHOW DATABASES;" | grep -v -e ^information_schema$ -e ^performance_schema$ -e ^mysql$ -e ^sys$ | xargs mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" --skip-comments --default-character-set=utf8 --result-file /backup/dump_$(date +%Y-%m-%d_%H-%M-%S).sql --databases' 1151 | else 1152 | docker exec -it $MYSQLSERVER sh -c \ 1153 | "mysqldump -uroot -p\"\$MYSQL_ROOT_PASSWORD\" --skip-comments --default-character-set=utf8 --result-file /backup/dump_"$(IFS=_ ; echo "$*")"_\$(date +%Y-%m-%d_%H-%M-%S).sql --databases $(IFS=$' ' ; echo "$*")" 1154 | if [ $# -eq 1 ] && [ -d /home/$1 ]; then 1155 | mkdir -p /home/$1/backup/db 1156 | mv /home/$MYSQLSERVER/backup/dump_${1}_*.sql /home/$1/backup/db/ 1157 | fi 1158 | fi 1159 | fi 1160 | # https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html 1161 | # --default-character-set=utf8 1162 | # --add-locks 1163 | # --master-data 1164 | # --quick 1165 | # TODO: --single-transaction 1166 | exit 0 1167 | fi 1168 | 1169 | if [ "$1" == "mysql:import" ]; then 1170 | shift 1171 | if [ $# -lt 2 ]; then 1172 | echo "Usage: docweb mysql:import NAME [--gzip] FILENAME [DATABASE]" 1173 | exit 1 1174 | fi 1175 | MYSQLSERVER=$1 1176 | shift 1177 | ISRUNNING=$(docker inspect --format={{.State.Running}} $MYSQLSERVER 2> /dev/null) 1178 | if [ $? -ne 0 ]; then 1179 | echo "MySQL instance $MYSQLSERVER is not running." 1180 | exit 1 1181 | fi 1182 | if [ "$1" == "--gzip" ]; then 1183 | shift 1184 | if [ $# -lt 1 ]; then 1185 | echo "Usage: docweb mysql:import NAME [--gzip] FILENAME [DATABASE]" 1186 | exit 1 1187 | fi 1188 | docker exec -it $MYSQLSERVER sh -c "gunzip < /backup/$1 | mysql -uroot -p\"\$MYSQL_ROOT_PASSWORD\" $2" 1189 | else 1190 | if [ $# -lt 1 ]; then 1191 | echo "Usage: docweb mysql:import NAME [--gzip] FILENAME [DATABASE]" 1192 | exit 1 1193 | fi 1194 | docker exec -it $MYSQLSERVER sh -c "mysql -uroot -p\"\$MYSQL_ROOT_PASSWORD\" $2 < /backup/$1" 1195 | fi 1196 | exit 0 1197 | fi 1198 | 1199 | if [ "$1" == "mysql:backupusers" ]; then 1200 | shift 1201 | if [ $# -lt 1 ]; then 1202 | echo "Usage: docweb mysql:backupusers NAME" 1203 | exit 1 1204 | fi 1205 | MYSQLSERVER=$1 1206 | shift 1207 | ISRUNNING=$(docker inspect --format={{.State.Running}} $MYSQLSERVER 2> /dev/null) 1208 | if [ $? -ne 0 ]; then 1209 | echo "MySQL instance $MYSQLSERVER is not running." 1210 | exit 1 1211 | fi 1212 | # TODO: 1213 | # mysql.user 1214 | # mysql.db 1215 | # mysqldump -u root -p mysql user > user_table_dump.sql 1216 | exit 0 1217 | fi 1218 | 1219 | if [ "$1" == "mysql:listdbs" ] || [ "$1" == "mysql:listdb" ]; then 1220 | shift 1221 | if [ $# -lt 1 ]; then 1222 | echo "Usage: docweb mysql:listdbs NAME" 1223 | exit 1 1224 | fi 1225 | docker exec -it $1 sh -c 'mysql -t -uroot -p"$MYSQL_ROOT_PASSWORD" -e "SHOW DATABASES;" | grep -v -e "^| information_schema \+|$" -e "^| performance_schema \+|$" -e "^| mysql \+|$" -e "^| sys \+|$"' 1226 | exit 0 1227 | fi 1228 | 1229 | if [ "$1" == "mysql:listusers" ] || [ "$1" == "mysql:listuser" ]; then 1230 | shift 1231 | if [ $# -lt 1 ]; then 1232 | echo "Usage: docweb mysql:listusers NAME [--all]" 1233 | exit 1 1234 | fi 1235 | if [ "$2" == "--all" ]; then 1236 | docker exec -it $1 sh -c \ 1237 | 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e "SELECT * FROM mysql.user;"' 1238 | else 1239 | docker exec -it $1 sh -c \ 1240 | 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e "SELECT Host,User,max_questions,max_updates,max_connections,max_user_connections,password_expired FROM mysql.user;"' 1241 | # password_last_changed, password_lifetime, account_locked 1242 | fi 1243 | exit 0 1244 | fi 1245 | 1246 | if [ "$1" == "mysql:listproc" ]; then 1247 | shift 1248 | if [ $# -lt 1 ]; then 1249 | echo "Usage: docweb mysql:listproc NAME" 1250 | exit 1 1251 | fi 1252 | docker exec -it $1 sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e "SHOW PROCESSLIST"' 1253 | exit 0 1254 | fi 1255 | 1256 | if [ "$1" == "mysql:upgrade" ]; then 1257 | shift 1258 | if [ $# -lt 1 ]; then 1259 | echo "Usage: docweb mysql:upgrade NAME" 1260 | exit 1 1261 | fi 1262 | docker exec -it $1 sh -c 'exec mysql_upgrade -uroot -p"$MYSQL_ROOT_PASSWORD"' 1263 | exit 0 1264 | fi 1265 | 1266 | if [ "$1" == "mssql:run" ]; then 1267 | shift 1268 | 1269 | RUNARGS="-d --restart=always" 1270 | if [ "$1" == "--debug" ]; then 1271 | shift 1272 | RUNARGS="-it --rm" 1273 | fi 1274 | 1275 | if [ $# -lt 2 ]; then 1276 | echo "Usage: docweb mssql:run [--debug] NAME SA_PASSWORD" 1277 | exit 1 1278 | fi 1279 | 1280 | ISRUNNING=$(docker inspect --format={{.State.Running}} $1 2> /dev/null) 1281 | if [ $? -eq 0 ]; then 1282 | echo "Stopping the running instance ..." 1283 | docker stop $1 1284 | docker rm $1 1285 | fi 1286 | 1287 | mkdir -p /home/$1 1288 | 1289 | docker run $RUNARGS \ 1290 | --name="$1" \ 1291 | --hostname="$1" \ 1292 | --net=isolated_nw \ 1293 | --memory=512m \ 1294 | -v /home/$1:/var/opt/mssql \ 1295 | -e 'ACCEPT_EULA=Y' \ 1296 | -e SA_PASSWORD="$2" \ 1297 | microsoft/mssql-server-linux:latest 1298 | 1299 | exit 0 1300 | fi 1301 | 1302 | if [ "$1" == "memcache:run" ]; then 1303 | shift 1304 | # https://hub.docker.com/_/memcached/ 1305 | exit 0 1306 | fi 1307 | 1308 | if [ "$1" == "mailfwd:run" ]; then 1309 | shift 1310 | 1311 | ISRUNNING=$(docker inspect --format={{.State.Running}} mailfwd 2> /dev/null) 1312 | [ $? -eq 0 ] && docker rm -f mailfwd 1313 | 1314 | mkdir -p /home/mailfwd 1315 | [ ! -f /home/mailfwd/mail.conf ] && echo "@example.com:fffaraz@gmail.com" > /home/mailfwd/mail.conf 1316 | 1317 | docker run -d --restart=always \ 1318 | --name mailfwd -p 25:25 \ 1319 | --memory 64m \ 1320 | -e SMF_CONFIG="$(cat /home/mailfwd/mail.conf)" \ 1321 | zixia/simple-mail-forwarder:latest 1322 | 1323 | exit 0 1324 | fi 1325 | 1326 | if [ "$1" == "volume:create" ]; then 1327 | shift 1328 | if [ $# -lt 2 ]; then 1329 | echo "Usage: docweb volume:create NAME SIZE" 1330 | exit 1 1331 | fi 1332 | mkdir -p /home/img 1333 | truncate -s $2 /home/img/$1.img 1334 | mkfs.ext4 /home/img/$1.img 1335 | mkdir -p /home/$1 1336 | mount /home/img/$1.img /home/$1 1337 | # http://stackoverflow.com/questions/257844/quickly-create-a-large-file-on-a-linux-system 1338 | # https://docs.docker.com/engine/reference/commandline/run/#/set-storage-driver-options-per-container 1339 | # http://stackoverflow.com/questions/29029326/how-to-define-a-disk-quota-for-docker-containers 1340 | exit 0 1341 | fi 1342 | 1343 | if [ "$1" == "wpscan" ]; then 1344 | shift 1345 | if [ $# -lt 1 ]; then 1346 | echo "Usage: docweb wpscan URL" 1347 | exit 1 1348 | fi 1349 | docker run --rm -it wpscanteam/wpscan --url $1 1350 | exit 0 1351 | fi 1352 | 1353 | if [ "$1" == "ssh" ]; then 1354 | shift 1355 | # https://github.com/tg123/sshpiper 1356 | exit 0 1357 | fi 1358 | 1359 | if [ "$1" == "bootstrap" ]; then 1360 | set -euxo pipefail 1361 | export DEBIAN_FRONTEND=noninteractive 1362 | apt-get -yq update < /dev/null 1363 | apt-get -yq upgrade < /dev/null 1364 | apt-get -yq dist-upgrade < /dev/null 1365 | apt-get -yq install dnsutils sysstat < /dev/null 1366 | $0 install:extras 1367 | $0 install:docker 1368 | $0 install:network 1369 | $0 install:aliases 1370 | apt-get -yq autoremove < /dev/null 1371 | apt-get -yq autoclean < /dev/null 1372 | exit 0 1373 | fi 1374 | 1375 | if [ "$1" == "install:swapfile" ]; then 1376 | shift 1377 | if [ $# -lt 1 ] || [ $1 -lt 512 ]; then 1378 | echo "Usage: docweb install:swapfile SIZE_IN_MB" 1379 | exit 1 1380 | fi 1381 | set -euxo pipefail 1382 | dd if=/dev/zero of=/swapfile bs=32M count=$(( $1 / 32 )) 1383 | chown root:root /swapfile 1384 | chmod 0600 /swapfile 1385 | mkswap /swapfile 1386 | echo "/swapfile none swap sw 0 0" >> /etc/fstab 1387 | echo "vm.swappiness=10" >> /etc/sysctl.conf 1388 | echo "vm.vfs_cache_pressure=50" >> /etc/sysctl.conf 1389 | swapon /swapfile 1390 | sysctl vm.swappiness=10 1391 | sysctl vm.vfs_cache_pressure=50 1392 | exit 0 1393 | fi 1394 | 1395 | if [ "$1" == "install:extras" ]; then 1396 | apt-get -yq install apache2-utils curl dstat atop htop iftop iotop joe-jupp logtop lsof pv pwgen p7zip-full smem sysstat tree vnstat unzip ncdu wget whois < /dev/null 1397 | 1398 | wget -O- https://bit.ly/glances | /bin/bash 1399 | 1400 | wget -O speedtest-cli https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.py 1401 | chmod +x speedtest-cli 1402 | 1403 | wget -O /usr/local/bin/httpstat https://raw.githubusercontent.com/reorx/httpstat/master/httpstat.py 1404 | chmod +x /usr/local/bin/httpstat 1405 | 1406 | wget -O /usr/local/bin/ctop https://github.com/bcicen/ctop/releases/download/v0.6.1/ctop-0.6.1-linux-amd64 1407 | chmod +x /usr/local/bin/ctop 1408 | 1409 | curl -sSf https://moncho.github.io/dry/dryup.sh | sh 1410 | chmod 755 /usr/local/bin/dry 1411 | 1412 | exit 0 1413 | fi 1414 | 1415 | if [ "$1" == "install:docker" ]; then 1416 | set -euxo pipefail 1417 | apt-get -yq install apt-transport-https ca-certificates < /dev/null 1418 | apt-get -yq install linux-image-extra-$(uname -r) linux-image-extra-virtual < /dev/null 1419 | # TODO: zfs ? 1420 | 1421 | # wget -qO- https://raw.githubusercontent.com/docker/docker/master/contrib/check-config.sh | /bin/bash 1422 | wget -qO- https://get.docker.com/ | sh 1423 | 1424 | # https://docs.docker.com/compose/install/ 1425 | # https://github.com/docker/compose/releases 1426 | curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose 1427 | chmod +x /usr/local/bin/docker-compose 1428 | 1429 | #apt-key adv --keyserver hkp://ha.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D 1430 | #echo "deb https://apt.dockerproject.org/repo ubuntu-xenial main" > /etc/apt/sources.list.d/docker.list 1431 | #apt-get -yq update < /dev/null 1432 | #apt-get -yq install docker-engine < /dev/null 1433 | 1434 | exit 0 1435 | fi 1436 | 1437 | if [ "$1" == "install:youtube-dl" ]; then 1438 | set -x 1439 | apt-get -yq install ffmpeg < /dev/null 1440 | wget -q https://yt-dl.org/downloads/latest/youtube-dl -O /usr/local/bin/youtube-dl 1441 | chmod a+rx /usr/local/bin/youtube-dl 1442 | youtube-dl -U 1443 | exit 0 1444 | fi 1445 | 1446 | if [ "$1" == "install:network" ]; then 1447 | docker network create --driver bridge isolated_nw 1448 | exit 0 1449 | fi 1450 | 1451 | if [ "$1" == "install:aliases" ]; then 1452 | # https://gist.github.com/jverdeyen/741d29a8e8d7a8e5d4dd4346fd1bd788 1453 | # https://gist.github.com/f3l1x/4c3bb59397d976ac83f0 1454 | echo 'alias dps="docweb ps"' >> ~/.bash_aliases 1455 | echo 'alias dpsa="docker ps -a -s | less -S"' >> ~/.bash_aliases 1456 | echo 'alias gitcam="git commit -a -m"' >> ~/.bash_aliases 1457 | echo 'alias gits="git status"' >> ~/.bash_aliases 1458 | echo 'alias gitpp="git pull; git push;"' >> ~/.bash_aliases 1459 | echo 'alias cdh="cd /home"' >> ~/.bash_aliases 1460 | exit 0 1461 | fi 1462 | 1463 | if [ "$1" == "install:webmin" ]; then 1464 | echo "deb https://download.webmin.com/download/repository sarge contrib" > /etc/apt/sources.list.d/webmin.list 1465 | cd /root 1466 | wget -q http://www.webmin.com/jcameron-key.asc 1467 | apt-key add jcameron-key.asc 1468 | apt-get -yq update < /dev/null 1469 | apt-get -yq install apt-transport-https < /dev/null 1470 | apt-get -yq install webmin < /dev/null 1471 | cd ~- 1472 | exit 0 1473 | fi 1474 | 1475 | if [ "$1" == "upgrade" ] || [ "$1" == "pull" ]; then 1476 | cd /opt/dockerweb 1477 | git pull 1478 | cd ~- 1479 | exit 0 1480 | fi 1481 | 1482 | if [ "$1" == "upgrade:os" ]; then 1483 | export DEBIAN_FRONTEND=noninteractive 1484 | apt-get -yq update < /dev/null 1485 | apt-get -yq upgrade < /dev/null 1486 | apt-get -yq dist-upgrade < /dev/null 1487 | apt-get -yq autoremove < /dev/null 1488 | apt-get -yq autoclean < /dev/null 1489 | apt-get -yq clean < /dev/null 1490 | #do-release-upgrade 1491 | exit 0 1492 | fi 1493 | 1494 | if [ "$1" == "dockly" ]; then 1495 | docker run -it --rm --name dockly -v /var/run/docker.sock:/var/run/docker.sock lirantal/dockly 1496 | exit 0 1497 | fi 1498 | 1499 | if [ "$1" == "artisan" ]; then 1500 | ps aux | grep artisan 1501 | exit 0 1502 | fi 1503 | 1504 | if [ "$1" == "geekbench" ]; then 1505 | # https://github.com/davidsarkany/docker-geekbench 1506 | docker run --rm davidsarkany/geekbench 1507 | exit 0 1508 | fi 1509 | 1510 | echo "Unknown command '$1'" 1511 | exit 1 1512 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # wget -qO - https://raw.githubusercontent.com/fffaraz/dockerweb/master/install.sh | bash 4 | 5 | if [ "$(id -u)" != "0" ]; then 6 | echo "This script must be run as root" 1>&2 7 | exit 1 8 | fi 9 | 10 | set -euxo pipefail 11 | 12 | sed -i "s/Port 22/Port 7071/" /etc/ssh/sshd_config 13 | service ssh restart 14 | 15 | export DEBIAN_FRONTEND=noninteractive 16 | apt -yq update < /dev/null 17 | apt -yq upgrade < /dev/null 18 | apt -yq dist-upgrade < /dev/null 19 | apt -yq full-upgrade < /dev/null 20 | apt -yq --fix-broken install < /dev/null 21 | apt -yq install apt-transport-https ca-certificates git wget < /dev/null 22 | apt -yq autoremove < /dev/null 23 | 24 | mkdir -p /opt 25 | git clone https://github.com/fffaraz/dockerweb.git /opt/dockerweb 26 | 27 | echo 'export PATH=$PATH:/opt/dockerweb' >> ~/.profile 28 | 29 | #echo 'alias docweb="/opt/dockerweb/docweb"' >> ~/.bash_aliases 30 | #alias docweb="/opt/dockerweb/docweb" 31 | 32 | #cat /proc/meminfo | grep SwapTotal: 33 | #cat /proc/meminfo | grep MemTotal: 34 | #docweb install:swapfile 1024 35 | 36 | #docweb bootstrap 37 | 38 | # bash completion for the `docweb` command 39 | 40 | # _docweb_complete() { 41 | # local OLD_IFS="$IFS" 42 | # local cur=${COMP_WORDS[COMP_CWORD]} 43 | 44 | # IFS=$'\n'; # want to preserve spaces at the end 45 | # local opts="$(docweb cli completions --line="$COMP_LINE" --point="$COMP_POINT")" 46 | 47 | # if [[ "$opts" =~ \\s* ]] 48 | # then 49 | # COMPREPLY=( $(compgen -f -- $cur) ) 50 | # elif [[ $opts = "" ]] 51 | # then 52 | # COMPREPLY=( $(compgen -f -- $cur) ) 53 | # else 54 | # COMPREPLY=( ${opts[*]} ) 55 | # fi 56 | 57 | # IFS="$OLD_IFS" 58 | # return 0 59 | # } 60 | # complete -o nospace -F _docweb_complete docweb 61 | -------------------------------------------------------------------------------- /notes.txt: -------------------------------------------------------------------------------- 1 | ## TODO List 2 | 3 | - Add Memory usage limit as a parameter for `docweb run` 4 | - Add certbot email as a parameter for `docweb proxy:run` 5 | - Add gzip compression level as a parameter for `docweb proxy:run` 6 | - logrotate 7 | - phpMyAdmin auto latest version 8 | - Requests rate limit 9 | - Bash Auto-Completion 10 | - Auto latest node.js version detection for php7nginx image 11 | - Redirect www to non-www for subdomains. non-www to www for root domains 12 | - fail2ban 13 | - run.sh template 14 | - the easiest way to run things at startup is to add them to the file /etc/rc.local. 15 | 16 | --- 17 | https://nginxconfig.io/ 18 | https://github.com/phanan/htaccess 19 | --- 20 | https://github.com/containous/traefik 21 | --- 22 | https://github.com/mholt/caddy 23 | https://github.com/lucaslorentz/caddy-docker-proxy 24 | https://github.com/abiosoft/caddy-docker 25 | --- 26 | https://github.com/lando/lando 27 | --- 28 | https://buddy.works/guides/laravel-in-docker 29 | https://github.com/TrafeX/docker-wordpress 30 | https://github.com/thecodingmachine/docker-images-php 31 | --- 32 | https://github.com/0xboz/digitalocean_email_server 33 | --- 34 | Wildcard SSL Certificates 35 | https://blogs.msdn.microsoft.com/mihansen/2018/03/15/creating-wildcard-ssl-certificates-with-lets-encrypt/ 36 | 37 | docweb exec --root proxy 38 | 39 | /opt/certbot-auto certonly \ 40 | --server https://acme-v02.api.letsencrypt.org/directory \ 41 | --manual --preferred-challenges dns \ 42 | -d example.com -d *.example.com 43 | 44 | nslookup -type=TXT _acme-challenge.example.com 45 | 46 | cp /etc/letsencrypt/live/example.com/fullchain.pem /opt/nginx/conf/cert/fullchain.pem 47 | cp /etc/letsencrypt/live/example.com/privkey.pem /opt/nginx/conf/cert/privkey.pem 48 | cp /etc/letsencrypt/live/example.com/chain.pem /opt/nginx/conf/cert/chain.pem 49 | 50 | --- 51 | https://docs.docker.com/config/containers/logging/json-file/ 52 | 53 | /etc/docker/daemon.json 54 | 55 | { 56 | "log-driver": "json-file", 57 | "log-opts": { 58 | "max-size": "100m" 59 | } 60 | } 61 | 62 | --- 63 | TODO: Block ip 64 | https://www.abuseipdb.com/statistics 65 | /home/proxy/blocklists.conf 66 | https://github.com/violentlydave/mkhtaccess_red 67 | --- 68 | /etc/default/grub 69 | GRUB_CMDLINE_LINUX_DEFAULT="cgroup_enable=memory swapaccount=1" 70 | update-grub 71 | --- 72 | High-performance PHP application server, load-balancer and process manager written in Golang 73 | https://github.com/spiral/roadrunner 74 | --- 75 | https://github.com/cytopia/devilbox 76 | https://github.com/yandex/gixy 77 | https://github.com/giovtorres/kvm-install-vm 78 | https://github.com/spotify/docker-gc 79 | https://www.cyberciti.biz/tips/top-linux-monitoring-tools.html 80 | https://github.com/dylanaraps/pure-bash-bible 81 | 82 | docker run --init 83 | 84 | glances --disable-sensors -w -p 81 85 | docker run -it --rm --volume=/var/run/docker.sock:/var/run/docker.sock --publish=0.0.0.0:8000:80 gliderlabs/logspout 86 | 87 | netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n 88 | netstat -anp |grep 'tcp\|udp' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n 89 | netstat -n | grep :80 |wc -l 90 | iptables -A INPUT -s IPADRESS -j DROP 91 | 92 | zgrep sshd /var/log/auth.log* | grep rhost | sed -re 's/.*rhost=([^ ]+).*/\1/' | sort | uniq -c | sort -n 93 | /var/log/auth.log 94 | 95 | .bash_profile 96 | echo 'ALERT - Root Shell Access on:' `date` `who` | mail -s "Alert: Root Access from `who | awk '{print $6}'`" mail@something.com 97 | 98 | https://git.cloudron.io/cloudron/box/blob/master/baseimage/initializeBaseUbuntuImage.sh 99 | 100 | PPM is a process manager, supercharger and load balancer for modern PHP applications. 101 | https://github.com/php-pm/php-pm 102 | 103 | https://github.com/banianhost/images 104 | 105 | nginx server block 106 | autoindex on; 107 | 108 | Docker Utilities: 109 | https://github.com/v2tec/watchtower 110 | https://github.com/spotify/docker-gc 111 | https://github.com/docker-slim/docker-slim 112 | https://github.com/grammarly/rocker 113 | https://github.com/bcicen/ctop 114 | 115 | https://github.com/evertramos 116 | 117 | https://github.com/thecodingmachine/kickoff-docker-php 118 | 119 | TODO: https://github.com/OptimalBits/redbird 120 | --- 121 | NGiИX config generator generator on steroids 122 | https://github.com/valentinxxx/nginxconfig.io 123 | https://nginxconfig.io 124 | --- 125 | TODO: Bash Programmable Completion: 126 | http://www.tldp.org/LDP/abs/html/tabexpansion.html 127 | http://askubuntu.com/questions/68175/how-to-create-script-with-auto-complete 128 | /etc/bash_completion.d/* 129 | http://mywiki.wooledge.org/BashFAQ 130 | --- 131 | 132 | EMAIL: https://github.com/hardware/mailserver 133 | https://github.com/vedetta-com/caesonia 134 | 135 | https://github.com/zixia/docker-simple-mail-forwarder 136 | https://github.com/jbeda/docker-postfix-forwarder 137 | https://github.com/tomav/docker-mailserver 138 | https://github.com/mail-in-a-box/mailinabox 139 | https://github.com/andryyy/mailcow-dockerized 140 | https://github.com/lava/dockermail 141 | https://github.com/Mailu/Mailu 142 | https://github.com/ONLYOFFICE/Docker-CommunityServer 143 | https://github.com/modoboa/modoboa 144 | https://github.com/n-at/docker-ox-app-suite 145 | https://github.com/sb-minimal/docker-ubuntu-open-exchange 146 | http://www.iredmail.org/ 147 | https://www.zimbra.com/open-source-email-overview/ 148 | 149 | EMAIL CATCHER: 150 | https://github.com/mailhog/MailHog 151 | https://github.com/sj26/mailcatcher 152 | 153 | DNS: 154 | https://www.digitalocean.com/community/tutorials/how-to-configure-bind-as-an-authoritative-only-dns-server-on-ubuntu-14-04 155 | https://www.digitalocean.com/community/tutorials/how-to-setup-dnssec-on-an-authoritative-bind-dns-server--2 156 | https://github.com/obi12341/docker-pdns 157 | https://github.com/poweradmin/poweradmin 158 | https://github.com/yswery/PHP-DNS-SERVER 159 | https://github.com/jethrocarr/namedmanager 160 | 161 | TODO: 162 | https://github.com/docker-slim/docker-slim 163 | https://github.com/influxdata/influxdb 164 | https://github.com/nazar-pc/docker-webserver 165 | https://github.com/shellinabox/shellinabox 166 | https://github.com/cytopia/mysqldump-secure 167 | https://github.com/pixelb/ps_mem 168 | https://github.com/Yelp/dumb-init 169 | https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion 170 | 171 | PHP: 172 | https://github.com/virustotal/yara 173 | https://github.com/Maikuolan/phpMussel 174 | https://github.com/nbs-system/php-malware-finder 175 | https://github.com/planet-work/php-malware-scanner 176 | https://github.com/btoplak/Joomla-Anti-Malware-Scan-Script--JAMSS- 177 | https://github.com/nexylan/PHPAV 178 | https://github.com/evoforge/evomalware 179 | https://github.com/mikestowe/Malicious-Code-Scanner 180 | https://github.com/emposha/PHP-Shell-Detector 181 | https://github.com/Orbixx/Obfuscalp 182 | https://github.com/lucanos/Tripwire 183 | https://github.com/krismas/Malicious 184 | 185 | TODO APP LIST: 186 | adminer 187 | https://github.com/vrana/adminer 188 | wget http://www.adminer.org/latest.php -O /var/www/index.php 189 | wget https://raw.github.com/vrana/adminer/master/designs/hever/adminer.css -O /var/www/adminer.css 190 | https://www.adminer.org/#download 191 | ajenti 192 | https://github.com/ajenti/ajenti 193 | https://github.com/paimpozhil/WhatPanel 194 | apaxy 195 | https://github.com/AdamWhitcroft/Apaxy 196 | https://github.com/DirectoryLister/DirectoryLister 197 | https://github.com/marekrei/encode-explorer 198 | bolt 199 | https://github.com/bolt/bolt 200 | codeigniter 201 | https://github.com/bcit-ci/CodeIgniter 202 | django 203 | https://github.com/django/django 204 | https://github.com/rosarior/awesome-django 205 | drupal 206 | https://github.com/drupal/drupal 207 | https://github.com/docker-library/drupal 208 | gateone 209 | https://github.com/liftoff/GateOne/ 210 | https://github.com/glyptodon/ 211 | gitlab 212 | https://github.com/gitlabhq/gitlabhq 213 | gogs 214 | https://github.com/gogits/gogs 215 | gitea 216 | https://github.com/go-gitea/gitea 217 | h5ai 218 | https://github.com/lrsjng/h5ai 219 | joomla 220 | https://github.com/joomla/joomla-cms 221 | laravel 222 | https://github.com/laravel/laravel 223 | metabase 224 | docker run -d -p 3000:3000 --net=isolated_nw --name metabase metabase/metabase 225 | octobercms 226 | https://github.com/octobercms/october 227 | owncloud 228 | https://owncloud.org/ 229 | paperwork 230 | https://github.com/twostairs/paperwork 231 | piwik 232 | https://piwik.org/ 233 | polr 234 | https://github.com/Cydrobolt/polr 235 | pydio 236 | https://pydio.com/ 237 | https://github.com/pydio/pydio-core 238 | redash 239 | http://redash.io/ 240 | https://github.com/getredash/redash 241 | seafile 242 | https://www.seafile.com 243 | https://github.com/haiwen/seafile 244 | webmin 245 | wordpress 246 | https://github.com/jbfink/docker-wordpress 247 | https://fa.wordpress.org/ 248 | caddy 249 | https://github.com/mholt/caddy 250 | cherokee 251 | tengine 252 | https://github.com/alibaba/tengine 253 | 254 | 255 | https://github.com/vmware/harbor 256 | 257 | Analog 258 | Awstats 259 | Webalizer 260 | DKIM 261 | SPF 262 | Max hourly emails per domain 263 | Disk space usage warnings 264 | Disk quota usage warnings 265 | Include databases in disk usage calculations (Use INFORMATION_SCHEMA to acquire MySQL disk usage) 266 | Out of memory warnings 267 | Critical load threshold 268 | Bandwidth usage warning 269 | PHP max execution time 270 | PHP max POST size 271 | PHP max upload size 272 | ioncube 273 | sourceguardian 274 | zend 275 | Always redirect to SSL 276 | I/O priority level (bandwidth usage, stats logs, nightly backups, quota checks) 277 | Update Preferences 278 | Brute Force Protection 279 | ModSecurity (https://waf.comodo.com/) 280 | Fork Bomb Protection 281 | Log Rotation 282 | Backup Scheduling and Retention 283 | View Bandwidth Usage 284 | Email Delivery Reports 285 | Email Queue 286 | munin 287 | 288 | https://github.com/minio/minio 289 | https://github.com/ceph/ceph 290 | https://github.com/ceph/ceph-docker 291 | https://github.com/chrislusf/seaweedfs 292 | https://github.com/coreos/torus 293 | https://github.com/rook/rook 294 | https://github.com/s3git/s3git 295 | https://github.com/leo-project/leofs 296 | 297 | 298 | VBoxManage createvm --name "Ubuntu 16.04 Server" --register 299 | VBoxManage modifyvm "Ubuntu 16.04 Server" --memory 2048 --acpi on --boot1 dvd --nic1 bridged --bridgeadapter1 ens33 300 | VBoxManage createhd --filename /home/administrator/Ubuntu_16_04_Server.vdi --size 10000 301 | VBoxManage storagectl "Ubuntu 16.04 Server" --name "IDE Controller" --add ide 302 | VBoxManage storageattach "Ubuntu 16.04 Server" --storagectl "IDE Controller" --port 0 --device 0 --type hdd --medium /home/administrator/Ubuntu_16_04_Server.vdi 303 | VBoxManage storageattach "Ubuntu 16.04 Server" --storagectl "IDE Controller" --port 1 --device 0 --type dvddrive --medium /home/administrator/iso/ubuntu-16.04-server-amd64.iso 304 | VBoxManage modifyvm "Ubuntu 16.04 Server" --vrde on 305 | VBoxHeadless --startvm "Ubuntu 16.04 Server" 306 | VBoxManage controlvm "Ubuntu 16.04 Server" poweroff 307 | VBoxManage controlvm "Ubuntu 16.04 Server" reset 308 | -------------------------------------------------------------------------------- /proxy/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fffaraz/proxy/base:latest 2 | ENTRYPOINT ["/script_run.sh"] 3 | ADD script_*.sh / 4 | RUN chown root:root /script_*.sh && chmod 544 /script_*.sh && sync && /script_init.sh 5 | -------------------------------------------------------------------------------- /proxy/base/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:latest 2 | ADD script_*.sh / 3 | RUN chown root:root /script_*.sh && chmod 544 /script_*.sh && sync && /script_init.sh 4 | -------------------------------------------------------------------------------- /proxy/base/script_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | NGINX_VERSION=1.11.7 5 | NGINX_URL="https://nginx.org/en/download.html" 6 | NPROC=$(($(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1)+1)) 7 | 8 | # Requirements 9 | addgroup webuser 10 | adduser --home /home/webuser --shell /bin/bash --no-create-home --gecos "" --ingroup webuser --disabled-password webuser 11 | 12 | export DEBIAN_FRONTEND=noninteractive 13 | apt-get -yq update < /dev/null 14 | apt-get -yq upgrade < /dev/null 15 | apt-get -yq install bash curl logrotate nano wget unzip < /dev/null 16 | apt-get -yq install build-essential gcc g++ make < /dev/null 17 | apt-get -yq install libgeoip-dev libgoogle-perftools-dev libpcre3 libpcre3-dev libperl-dev libssl-dev libxml2-dev libxslt1-dev openssl zlib1g-dev < /dev/null 18 | # libgd-dev 19 | 20 | echo "/usr/local/lib" > /etc/ld.so.conf.d/usr-local-lib.conf 21 | ldconfig 22 | mkdir -p /opt 23 | cd /opt 24 | 25 | # GeoIP 26 | #mkdir /opt/nginx 27 | #wget -qO /opt/nginx/GeoIP.dat.gz http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz 28 | #gunzip /opt/nginx/GeoIP.dat.gz 29 | 30 | # Nginx virtual host traffic status module 31 | cd /opt 32 | wget -q https://github.com/vozlt/nginx-module-vts/archive/master.zip 33 | unzip master.zip 34 | rm master.zip 35 | 36 | # ngx_pagespeed 37 | #cd /opt 38 | #wget -q https://github.com/apache/incubator-pagespeed-ngx/archive/latest-stable.zip 39 | #unzip latest-stable.zip 40 | #rm latest-stable.zip 41 | #cd incubator-pagespeed-ngx-latest-stable/ 42 | #psol_url=$(scripts/format_binary_url.sh PSOL_BINARY_URL) 43 | #wget -q ${psol_url} 44 | #tar -xzf $(basename ${psol_url}) 45 | 46 | # NAXSI is an open-source, high performance, low rules maintenance WAF for NGINX 47 | # http://www.bluemind.org/linux-nginx-waf-reverse-proxy-for-wordpress-running-apache/ 48 | # https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-naxsi-on-ubuntu-14-04 49 | #cd /opt 50 | #wget -q https://github.com/nbs-system/naxsi/archive/master.zip 51 | #unzip master.zip 52 | #rm master.zip 53 | 54 | # Install NGINX 55 | # https://ngxpagespeed.com/install 56 | function version_sort() { 57 | sort -t '.' -k 1,1 -k 2,2 -k 3,3 -k 4,4 -g 58 | } 59 | function version_older_than() { 60 | local test_version="$1" 61 | local compare_to="$2" 62 | local older_version=$(echo $@ | tr ' ' '\n' | version_sort | head -n 1) 63 | test "$older_version" != "$compare_to" 64 | } 65 | 66 | cd /opt 67 | versions_available=$(curl -sS --fail "$NGINX_URL" | grep -o '/download/nginx-[0-9.]*[.]tar[.]gz' | sed -e 's~^/download/nginx-~~' -e 's~\.tar\.gz$~~') 68 | latest_version=$(echo "$versions_available" | version_sort | tail -n 1) 69 | if version_older_than "$latest_version" "$NGINX_VERSION"; then 70 | echo "Expected the latest version of nginx to be at least $NGINX_VERSION but found $latest_version" 71 | exit 1 72 | fi 73 | NGINX_VERSION=$latest_version 74 | 75 | wget -q http://nginx.org/download/nginx-$NGINX_VERSION.tar.gz 76 | tar -xzf nginx-$NGINX_VERSION.tar.gz 77 | rm nginx-$NGINX_VERSION.tar.gz 78 | cd nginx-$NGINX_VERSION 79 | 80 | # -i = in-place (i.e. save back to the original file) 81 | # -e script 82 | # s = the substitute command 83 | # g = global (i.e. replace all and not just the first occurrence) 84 | sed -i -e 's/"Server: nginx"/"Server: Faraz"/g' src/http/ngx_http_header_filter_module.c 85 | sed -i -e 's/"\\x84\\xaa\\x63\\x55\\xe7"/"\\x84\\xc2\\x3b\\x07\\xef"/g' src/http/v2/ngx_http_v2_filter_module.c 86 | 87 | ./configure \ 88 | --prefix=/opt/nginx \ 89 | --error-log-path=/home/webuser/log/nginx/error.log \ 90 | --http-log-path=/home/webuser/log/nginx/access.log \ 91 | --http-client-body-temp-path=/home/webuser/tmp/nginx/client \ 92 | --http-proxy-temp-path=/home/webuser/tmp/nginx/proxy \ 93 | --http-fastcgi-temp-path=/home/webuser/tmp/nginx/fastcgi \ 94 | --http-uwsgi-temp-path=/home/webuser/tmp/nginx/uwsgi \ 95 | --http-scgi-temp-path=/home/webuser/tmp/nginx/scgi \ 96 | --user=webuser \ 97 | --group=webuser \ 98 | --without-select_module \ 99 | --without-poll_module \ 100 | --with-threads \ 101 | --with-http_ssl_module \ 102 | --with-http_v2_module \ 103 | --with-http_realip_module \ 104 | --with-http_gunzip_module \ 105 | --with-http_gzip_static_module \ 106 | --with-http_stub_status_module \ 107 | --add-module=/opt/nginx-module-vts-master 108 | #--with-http_geoip_module \ 109 | #--add-module=/opt/ngx_pagespeed-latest-stable # FIXME 110 | #--add-module=/opt/naxsi-master/naxsi_src # put naxsi first in your ./configure 111 | #--with-ngx_http_status_module 112 | 113 | make -j${NPROC} 114 | make install 115 | cd /opt 116 | rm -rf nginx-$NGINX_VERSION 117 | rm -rf nginx-module-vts-master 118 | rm -rf ngx_pagespeed-latest-stable 119 | rm -rf naxsi-master 120 | 121 | # Install letsencrypt 122 | cd /opt 123 | wget -q https://dl.eff.org/certbot-auto 124 | chmod a+x certbot-auto 125 | /opt/certbot-auto --non-interactive || true 126 | 127 | # Clean up 128 | apt-get -yq autoremove < /dev/null 129 | apt-get -yq autoclean < /dev/null 130 | sync 131 | 132 | rm -rf /var/log/letsencrypt/* 133 | rm -rf /usr/share/doc 134 | rm -rf /usr/share/man 135 | 136 | rm -rf /var/lib/apt/lists/* 137 | rm -rf /var/lib/apt 138 | rm -rf /var/cache/apt 139 | 140 | rm -rf /home/webuser 141 | rm -rf /var/tmp/* 142 | rm -rf /tmp/* 143 | 144 | rm /script_init.sh 145 | exit 0 146 | -------------------------------------------------------------------------------- /proxy/script_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | # Configure nginx 5 | # https://github.com/h5bp/server-configs-nginx 6 | # https://support.cloudflare.com/hc/en-us/articles/200170706 7 | # https://github.com/cloudflare/ngx_brotli_module 8 | # https://github.com/google/ngx_brotli 9 | # https://github.com/google/zopfli 10 | # https://waf.comodo.com/ 11 | 12 | mkdir -p /opt/nginx/conf/conf.d 13 | 14 | echo ' 15 | daemon off; 16 | worker_processes auto; 17 | worker_rlimit_nofile 20000; 18 | #include /home/webuser/conf/nginx/core.d/*.conf; 19 | events { 20 | worker_connections 10000; 21 | multi_accept on; 22 | use epoll; 23 | #include /home/webuser/conf/nginx/events.d/*.conf; 24 | } 25 | http { 26 | include mime.types; 27 | include global_params; 28 | vhost_traffic_status_zone; 29 | #include /home/webuser/conf/nginx/http.d/*.conf; 30 | #server { 31 | # listen 80 default_server; 32 | # listen [::]:80 default_server; 33 | # server_name _; 34 | # if ($allowed_country = no) { return 444; } 35 | # if ($http_host ~* ^www\.(.*)$ ) { return 301 $scheme://$1$request_uri; } 36 | # location ^~ /.well-known/acme-challenge { 37 | # alias /var/lib/letsencrypt/.well-known/acme-challenge; 38 | # try_files $uri =404; 39 | # default_type "text/plain"; 40 | # } 41 | # location / { return 301 https://$host$request_uri; } 42 | #} 43 | include /opt/nginx/conf/conf.d/*.conf; 44 | } 45 | ' > /opt/nginx/conf/nginx.conf 46 | 47 | cat > /opt/nginx/conf/global_params <<'EOL' 48 | #aio threads; 49 | default_type application/octet-stream; 50 | 51 | #if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})") { 52 | # set $year $1; 53 | # set $month $2; 54 | # set $day $3; 55 | #} 56 | 57 | #log_format traffic "$time_iso8601,$server_name,$remote_addr,$bytes_sent,$request_length,$request_time,$status,$request_uri"; 58 | #access_log /home/webuser/log/nginx/traffic-$year-$month-$day.log traffic; 59 | 60 | log_format main $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for" $request_length $request_time "$upstream_response_length" "$upstream_response_time" "$host"; 61 | access_log /home/webuser/log/nginx/access.log main; 62 | 63 | client_body_buffer_size 64K; 64 | client_body_timeout 30; 65 | client_max_body_size 1G; 66 | 67 | gzip on; 68 | gzip_disable "msie6"; 69 | #gzip_disable "MSIE [1-6]\.(?!.*SV1)"; 70 | gzip_vary on; 71 | gzip_http_version 1.1; 72 | gzip_comp_level 2; #6 73 | gzip_buffers 16 8k; 74 | gzip_min_length 512; 75 | gzip_proxied any; #expired no-cache no-store private auth; 76 | gzip_types text/plain text/xml text/css text/javascript application/javascript application/x-javascript application/json application/xml application/xml+rss application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon; 77 | keepalive_timeout 65; 78 | large_client_header_buffers 4 16k; 79 | open_file_cache max=1000 inactive=20s; 80 | open_file_cache_valid 60s; 81 | open_file_cache_min_uses 5; 82 | open_file_cache_errors off; 83 | rewrite_log on; 84 | #send_timeout 10; 85 | sendfile on; 86 | tcp_nopush on; 87 | tcp_nodelay on; 88 | server_tokens off; 89 | 90 | map $http_upgrade $connection_upgrade { 91 | default upgrade; 92 | '' keep-alive; 93 | } 94 | 95 | #limit_req zone=one burst=10; 96 | #limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s; 97 | 98 | server_names_hash_max_size 2048; 99 | server_names_hash_bucket_size 64; 100 | 101 | #geoip_country /opt/nginx/GeoIP.dat; 102 | #map $geoip_country_code $allowed_country { 103 | # default yes; 104 | # CN no; 105 | # RU no; 106 | # VN no; 107 | # TW no; 108 | #} 109 | 110 | # CloudFlare proxy addresses 111 | set_real_ip_from 103.21.244.0/22; 112 | set_real_ip_from 103.22.200.0/22; 113 | set_real_ip_from 103.31.4.0/22; 114 | set_real_ip_from 104.16.0.0/12; 115 | set_real_ip_from 108.162.192.0/18; 116 | set_real_ip_from 131.0.72.0/22; 117 | set_real_ip_from 141.101.64.0/18; 118 | set_real_ip_from 162.158.0.0/15; 119 | set_real_ip_from 172.64.0.0/13; 120 | set_real_ip_from 173.245.48.0/20; 121 | set_real_ip_from 188.114.96.0/20; 122 | set_real_ip_from 190.93.240.0/20; 123 | set_real_ip_from 197.234.240.0/22; 124 | set_real_ip_from 198.41.128.0/17; 125 | set_real_ip_from 199.27.128.0/21; 126 | set_real_ip_from 2400:cb00::/32; 127 | set_real_ip_from 2405:8100::/32; 128 | set_real_ip_from 2405:b500::/32; 129 | set_real_ip_from 2606:4700::/32; 130 | set_real_ip_from 2803:f800::/32; 131 | set_real_ip_from 2c0f:f248::/32; 132 | set_real_ip_from 2a06:98c0::/29; 133 | real_ip_header X-Forwarded-For; # X-Real-IP 134 | #real_ip_recursive on; 135 | 136 | EOL 137 | 138 | # https://cipherli.st/ 139 | # https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html 140 | # https://www.ssllabs.com/ssltest/ 141 | # https://hstspreload.org/ 142 | 143 | echo ' 144 | ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; 145 | ssl_prefer_server_ciphers on; 146 | ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"; 147 | ssl_ecdh_curve secp384r1; 148 | ssl_session_cache shared:SSL:10m; 149 | ssl_session_timeout 10m; 150 | ssl_session_tickets off; 151 | ssl_dhparam /opt/nginx/conf/cert/dhparam.pem; 152 | #resolver 8.8.8.8 8.8.4.4 valid=300s; 153 | resolver 127.0.0.11 valid=30s ipv6=off; 154 | resolver_timeout 5s; 155 | #add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; 156 | #add_header X-Content-Type-Options nosniff; 157 | #add_header X-Frame-Options DENY; 158 | #add_header X-XSS-Protection "1; mode=block"; 159 | #add_header Public-Key-Pins 160 | #add_header Content-Security-Policy 161 | ' > /opt/nginx/conf/ssl_params 162 | 163 | echo ' 164 | proxy_http_version 1.1; 165 | #proxy_set_header Connection keep-alive; 166 | proxy_set_header Connection $connection_upgrade; 167 | proxy_set_header Upgrade $http_upgrade; 168 | proxy_set_header Host $host; # $http_host 169 | proxy_set_header X-Real-IP $remote_addr; 170 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 171 | proxy_set_header X-Forwarded-Proto $scheme; 172 | proxy_buffering on; 173 | proxy_buffer_size 16k; 174 | proxy_buffers 32 8k; 175 | proxy_busy_buffers_size 128k; 176 | proxy_max_temp_file_size 1024m; 177 | proxy_temp_file_write_size 64k; 178 | proxy_connect_timeout 10s; 179 | proxy_read_timeout 600s; 180 | proxy_send_timeout 30s; 181 | #proxy_intercept_errors on; 182 | #proxy_redirect default; #off; 183 | #proxy_cache_bypass $http_upgrade; 184 | ' > /opt/nginx/conf/proxy_params 185 | 186 | # pagespeed on; 187 | # pagespeed FileCachePath /var/cache/pagespeed; 188 | # location ~ "\.pagespeed\.([a-z]\.)?[a-z]{2}\.[^.]{10}\.[^.]+" { add_header "" ""; } 189 | # location ~ "^/ngx_pagespeed_static/" { } 190 | # location ~ "^/ngx_pagespeed_beacon$" { } 191 | # location /ngx_pagespeed_statistics { deny all; } 192 | # location /ngx_pagespeed_global_statistics { deny all; } 193 | # location /ngx_pagespeed_message { deny all; } 194 | # location /pagespeed_console { deny all; } 195 | 196 | echo ' 197 | listen 80; 198 | listen [::]:80; 199 | listen 443 http2 ssl; 200 | listen [::]:443 http2 ssl; 201 | ' > /opt/nginx/conf/listen_params 202 | 203 | echo ' 204 | listen 80; 205 | listen [::]:80; 206 | ' > /opt/nginx/conf/listen_params_http 207 | 208 | echo ' 209 | listen 443 http2 ssl; 210 | listen [::]:443 http2 ssl; 211 | ' > /opt/nginx/conf/listen_params_https 212 | 213 | echo ' 214 | listen 80 default_server; 215 | listen [::]:80 default_server; 216 | listen 443 ssl http2 default_server; 217 | listen [::]:443 ssl http2 default_server; 218 | ' > /opt/nginx/conf/listen_params_default 219 | 220 | echo ' 221 | root /home/webuser/www; 222 | index index.html index.default.html; 223 | location /basic_status { stub_status; } 224 | location /nginx_status { vhost_traffic_status_display; vhost_traffic_status_display_format html; } 225 | location ^~ /.well-known/acme-challenge { alias /var/lib/letsencrypt/.well-known/acme-challenge; } 226 | ssl_certificate /opt/nginx/conf/cert/fullchain.pem; 227 | ssl_certificate_key /opt/nginx/conf/cert/privkey.pem; 228 | ssl_trusted_certificate /opt/nginx/conf/cert/chain.pem; 229 | include ssl_params; 230 | ' > /opt/nginx/conf/default_server 231 | 232 | # Logrotate 233 | logrotate --version 234 | 235 | cat > /etc/logrotate.d/nginx <<'EOL' 236 | /home/webuser/log/nginx/*.log { 237 | daily 238 | dateext 239 | missingok 240 | rotate 7305 # 2 decades 241 | olddir /home/webuser/log/nginx/old 242 | compress 243 | delaycompress 244 | notifempty 245 | create 644 webuser webuser 246 | sharedscripts 247 | postrotate 248 | if [ -f /opt/nginx/logs/nginx.pid ]; then 249 | kill -USR1 `/opt/nginx/logs/nginx.pid` 250 | fi 251 | endscript 252 | } 253 | EOL 254 | 255 | # Clean up 256 | rm /script_init.sh 257 | exit 0 258 | -------------------------------------------------------------------------------- /proxy/script_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | export TERM=xterm 4 | 5 | rm -rf /home/webuser/tmp 6 | mkdir -p /home/webuser/tmp/nginx/client 7 | mkdir -p /home/webuser/tmp/nginx/proxy 8 | mkdir -p /home/webuser/tmp/nginx/fastcgi 9 | mkdir -p /home/webuser/tmp/nginx/uwsgi 10 | mkdir -p /home/webuser/tmp/nginx/scgi 11 | mkdir -p /home/webuser/log/nginx 12 | mkdir -p /home/webuser/www 13 | 14 | SERVER_NAME=$(hostname) 15 | [ $# -gt 0 ] && SERVER_NAME=$1 16 | 17 | set +x 18 | echo " 19 | 20 | 21 | 22 | 23 | $SERVER_NAME 24 | 34 | 35 | 36 |

$SERVER_NAME

37 |

If you see this page, the web server is successfully installed and working. 38 | Further configuration is required.

39 | 40 | 41 | " > /home/webuser/www/index.default.html 42 | 43 | # TODO: robots.txt 44 | set -x 45 | 46 | # Default ssl cert 47 | mkdir -p /opt/nginx/conf/cert 48 | 49 | if [ ! -f /opt/nginx/conf/cert/fullchain.pem ]; then 50 | openssl req -x509 -nodes -sha256 -days 730 -newkey rsa:4096 \ 51 | -keyout /opt/nginx/conf/cert/privkey.pem -out /opt/nginx/conf/cert/fullchain.pem \ 52 | -subj "/" 53 | cp /opt/nginx/conf/cert/fullchain.pem /opt/nginx/conf/cert/chain.pem 54 | fi 55 | 56 | # -subj "/subjectAltName=DNS:yoursite.com,DNS:www.yoursite.com" 57 | # -subj "/CN=MyCertificate/subjectAltName=DNS.1=*.com,DNS.2=*.ir" 58 | # -subj "/C=US/ST=New York/L=New York City/O=Company/OU=Department/CN=MyCertificate/emailAddress=ssl@example.com/subjectAltName=DNS.1=*" 59 | 60 | [ ! -f /opt/nginx/conf/cert/dhparam.pem ] && openssl dhparam -out /opt/nginx/conf/cert/dhparam.pem 2048 # -5 4096 61 | 62 | #/usr/sbin/logrotate -v 63 | 64 | /script_update.sh --no-reload 65 | chown -R webuser:webuser /home/webuser 66 | exec /opt/nginx/sbin/nginx 67 | -------------------------------------------------------------------------------- /proxy/script_update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | RELOADNGNIX=1 5 | [ $# -gt 0 ] && [ "$1" == "--no-reload" ] && RELOADNGNIX=0 6 | [ $# -gt 0 ] && [ "$1" == "--debug" ] && set -x 7 | 8 | [ ! -f /home/webuser/websites.conf ] && echo "# CONTAINER CATCHALL WILDCARD SSLCERT HTTPSONLY DOMAIN1 [DOMAINS...]" > /home/webuser/websites.conf 9 | rm -f /opt/nginx/conf/conf.d/*.conf 10 | HASCATCHALL=0 11 | COUNTER=0 12 | 13 | while read -r -a line; do 14 | COUNTER=$((COUNTER+1)) 15 | CONTAINER=${line[0]} 16 | CATCHALL=${line[1]} 17 | WILDCARD=${line[2]} 18 | SSLCERT=${line[3]} 19 | HTTPSONLY=${line[4]} 20 | DOMAIN1=${line[5]} 21 | # TODO: input validation 22 | 23 | echo -e "\nAPP: $CONTAINER\n" 24 | DOMAINS="" 25 | SERVERNAME="server_name" 26 | for (( i=5; i<${#line[@]}; i++ )); do 27 | DOMAINS=$DOMAINS"${line[$i]},www.${line[$i]}," 28 | if [ $WILDCARD -eq 1 ]; then 29 | SERVERNAME=$SERVERNAME" ${line[$i]} *.${line[$i]}" 30 | else 31 | SERVERNAME=$SERVERNAME" ${line[$i]} www.${line[$i]}" 32 | fi 33 | done 34 | SERVERNAME=$SERVERNAME";" 35 | 36 | LISTENPARAM="include listen_params;" 37 | HTTPREDIRECT="" 38 | if [ $HTTPSONLY -eq 1 ]; then 39 | LISTENPARAM="include listen_params_https;" 40 | HTTPREDIRECT="server { include listen_params_http; $SERVERNAME location / { return 301 https://\$host\$request_uri; } }" 41 | fi 42 | 43 | if [ $CATCHALL -eq 1 ]; then 44 | HASCATCHALL=1 45 | SERVERNAME="server_name _;" 46 | LISTENPARAM="include listen_params_default;" 47 | fi 48 | 49 | if [ $SSLCERT -eq 1 ]; then 50 | # TODO: dnslookup ${DOMAINS::-1} skip if failed 51 | CERTPLUGIN="--standalone --preferred-challenges http" # tls-sni-01 52 | [ $RELOADNGNIX -eq 1 ] && CERTPLUGIN="--webroot --webroot-path /var/lib/letsencrypt/" 53 | ( set -x; 54 | /opt/certbot-auto certonly --non-interactive --agree-tos --no-self-upgrade --keep-until-expiring --expand \ 55 | --email fffaraz@gmail.com \ 56 | $CERTPLUGIN \ 57 | --domains ${DOMAINS::-1} ) 58 | fi 59 | 60 | SSLCRT="/opt/nginx/conf/cert/fullchain.pem" 61 | SSLKEY="/opt/nginx/conf/cert/privkey.pem" 62 | SSLCHAIN="/opt/nginx/conf/cert/chain.pem" 63 | SSLOCSP="off" # TODO: off only if self signed (chain.pem == fullchain.pem) 64 | if [ -d "/etc/letsencrypt/live/$DOMAIN1" ]; then 65 | SSLCRT="/etc/letsencrypt/live/$DOMAIN1/fullchain.pem" 66 | SSLKEY="/etc/letsencrypt/live/$DOMAIN1/privkey.pem" 67 | SSLCHAIN="/etc/letsencrypt/live/$DOMAIN1/chain.pem" 68 | SSLOCSP="on" 69 | fi 70 | if [[ $CONTAINER = *:* ]]; then 71 | # http://tldp.org/LDP/abs/html/string-manipulation.html 72 | # To replace the first match of $substring with $replacement: ${string/substring/replacement} 73 | # To replace all matches of $substring with $replacement: ${string//substring/replacement} 74 | CONTAINERARR=(${CONTAINER/:/ }) 75 | echo " 76 | $HTTPREDIRECT 77 | server 78 | { 79 | $LISTENPARAM 80 | $SERVERNAME 81 | #port_in_redirect off; 82 | location / { 83 | #proxy_pass http://$CONTAINER; 84 | set \$target_$COUNTER ${CONTAINERARR[0]}; 85 | proxy_pass http://\$target_$COUNTER:${CONTAINERARR[1]}; 86 | include proxy_params; 87 | } 88 | location ^~ /.well-known/acme-challenge { alias /var/lib/letsencrypt/.well-known/acme-challenge; } 89 | ssl_certificate $SSLCRT; 90 | ssl_certificate_key $SSLKEY; 91 | ssl_trusted_certificate $SSLCHAIN; 92 | ssl_stapling $SSLOCSP; 93 | ssl_stapling_verify $SSLOCSP; 94 | include ssl_params; 95 | } 96 | " > /opt/nginx/conf/conf.d/$COUNTER.conf 97 | else 98 | echo " 99 | $HTTPREDIRECT 100 | server 101 | { 102 | $LISTENPARAM 103 | $SERVERNAME 104 | #port_in_redirect off; 105 | location / { 106 | #proxy_pass http://$CONTAINER.isolated_nw:80; 107 | set \$target_$COUNTER $CONTAINER.isolated_nw; 108 | proxy_pass http://\$target_$COUNTER:80; 109 | include proxy_params; 110 | } 111 | location ^~ /.well-known/acme-challenge { alias /var/lib/letsencrypt/.well-known/acme-challenge; } 112 | ssl_certificate $SSLCRT; 113 | ssl_certificate_key $SSLKEY; 114 | ssl_trusted_certificate $SSLCHAIN; 115 | ssl_stapling $SSLOCSP; 116 | ssl_stapling_verify $SSLOCSP; 117 | include ssl_params; 118 | } 119 | " > /opt/nginx/conf/conf.d/$COUNTER.conf 120 | fi 121 | 122 | done < <(sed -e '/^#/d' -e '/^$/d' /home/webuser/websites.conf) 123 | 124 | if [ $HASCATCHALL -eq 0 ]; then 125 | echo ' 126 | server 127 | { 128 | server_name _ ""; 129 | include listen_params_default; 130 | include default_server; 131 | } 132 | ' > /opt/nginx/conf/conf.d/default_server.conf 133 | else 134 | echo ' 135 | server 136 | { 137 | server_name ""; 138 | include listen_params; 139 | include default_server; 140 | } 141 | ' > /opt/nginx/conf/conf.d/default_server.conf 142 | fi 143 | 144 | /opt/nginx/sbin/nginx -t 145 | 146 | [ $RELOADNGNIX -eq 1 ] && /opt/nginx/sbin/nginx -s reload 147 | 148 | #mv access.log access.log.0 149 | #kill -USR1 `cat master.nginx.pid` 150 | #sleep 1 151 | #gzip access.log.0 152 | 153 | exit 0 154 | -------------------------------------------------------------------------------- /web/apache/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM httpd:latest 2 | ENTRYPOINT ["/script_run.sh"] 3 | ADD script_*.sh / 4 | RUN chown root:root /script_*.sh && chmod 544 /script_*.sh && sync && /script_init.sh 5 | -------------------------------------------------------------------------------- /web/apache/script_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | groupadd -o -g 33 webuser 5 | useradd -o -u 33 -g webuser webuser 6 | 7 | apt-get update 8 | apt-get -yq install nano wget 9 | 10 | rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 11 | rm /script_init.sh 12 | -------------------------------------------------------------------------------- /web/apache/script_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mkdir -p /home/webuser/www/public 4 | 5 | rm -rf /var/www/html 6 | ln -s /home/webuser/www/public /usr/local/apache2/htdocs 7 | 8 | chown -R webuser:webuser /home/webuser 9 | 10 | cd /usr/local/apache2/htdocs 11 | exec httpd-foreground 12 | -------------------------------------------------------------------------------- /web/aspnet4/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:latest 2 | ENTRYPOINT ["/script_run.sh"] 3 | ADD script_*.sh / 4 | RUN chown root:root /script_*.sh && chmod 544 /script_*.sh && sync && /script_init.sh 5 | -------------------------------------------------------------------------------- /web/aspnet4/script_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -euxo pipefail 3 | 4 | # requirements 5 | addgroup webuser 6 | adduser --disabled-password --no-create-home --shell /bin/bash --gecos "" --home /home/webuser --ingroup webuser webuser 7 | 8 | # install mono 9 | 10 | apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF 11 | echo "deb http://download.mono-project.com/repo/debian wheezy main" | tee /etc/apt/sources.list.d/mono-xamarin.list 12 | #echo "deb http://download.mono-project.com/repo/debian wheezy-apache24-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list 13 | #echo "deb http://download.mono-project.com/repo/debian wheezy-libjpeg62-compat main" | tee -a /etc/apt/sources.list.d/mono-xamarin.list 14 | 15 | export DEBIAN_FRONTEND=noninteractive 16 | apt-get -yq update < /dev/null 17 | apt-get -yq upgrade < /dev/null 18 | 19 | apt-get install -yq wget 20 | apt-get install -yq mono-complete 21 | apt-get install -yq mono-xsp4 22 | #apt-get install -yq mono-devel 23 | #apt-get install -yq referenceassemblies-pcl 24 | #mozroots --import --sync 25 | 26 | mkdir -p /opt 27 | cd /opt 28 | wget https://github.com/NuGet/Home/releases/download/3.3/NuGet.exe 29 | 30 | # clean up 31 | rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 32 | rm /script_init.sh 33 | -------------------------------------------------------------------------------- /web/aspnet4/script_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mkdir -p /home/webuser/www 4 | mkdir -p /home/webuser/log 5 | cd /home/webuser/www 6 | 7 | [[ -f /home/webuser/project.sh ]] && source /home/webuser/project.sh 8 | chown -R webuser:webuser /home/webuser 9 | 10 | exec xsp4 --port=80 --logfile=/home/webuser/log/xsp4.log --verbose --printlog --loglevels=All 11 | 12 | # mono /opt/NuGet.exe restore project.sln 13 | # xbuild /t:Rebuild /p:WarningLevel=2 /p:Configuration=Release project.sln 14 | # exec mono /home/webuser/project/bin/Release/project.exe 15 | -------------------------------------------------------------------------------- /web/aspnet5/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM microsoft/dotnet:latest 2 | ENTRYPOINT ["/script_run.sh"] 3 | ADD script_*.sh / 4 | RUN chown root:root /script_*.sh && chmod 544 /script_*.sh && sync && /script_init.sh 5 | -------------------------------------------------------------------------------- /web/aspnet5/script_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # requirements 4 | addgroup webuser 5 | adduser --disabled-password --no-create-home --shell /bin/bash --gecos "" --home /home/webuser --ingroup webuser webuser 6 | 7 | # https://hub.docker.com/r/microsoft/dotnet/ 8 | # https://hub.docker.com/r/microsoft/aspnetcore/ 9 | # https://hub.docker.com/r/microsoft/aspnetcore-build/ 10 | 11 | # clean up 12 | rm /script_init.sh 13 | -------------------------------------------------------------------------------- /web/aspnet5/script_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mkdir -p /home/webuser/www 4 | [[ -f /home/webuser/project.sh ]] && source /home/webuser/project.sh 5 | [[ ! -f /home/webuser/www/project.json ]] && echo ' 6 | { 7 | "version": "1.0.0-*", 8 | "webroot": "wwwroot", 9 | "exclude": [ 10 | "wwwroot" 11 | ], 12 | "packExclude": [ 13 | "**.kproj", 14 | "**.user", 15 | "**.vspscc" 16 | ], 17 | "dependencies": { 18 | "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final", 19 | "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final", 20 | "Microsoft.AspNet.Diagnostics": "1.0.0-rc1-final", 21 | "Microsoft.AspNet.Hosting": "1.0.0-rc1-final", 22 | "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final", 23 | "Microsoft.Extensions.Logging.Console": "1.0.0-rc1-final" 24 | }, 25 | "commands": { 26 | "web": "Microsoft.AspNet.Server.Kestrel --server.urls http://*:80" 27 | }, 28 | "frameworks": { 29 | "dnx451": { }, 30 | "dnxcore50": { } 31 | } 32 | } 33 | ' > /home/webuser/www/project.json 34 | 35 | chown -R webuser:webuser /home/webuser 36 | 37 | cd /home/webuser/www 38 | dotnet restore 39 | dotnet build 40 | exec dotnet run -p project.json web --server.urls http://0.0.0.0:80 41 | 42 | #dotnet publish -c Release -o ./bin/Release/PublishOutput 43 | #dotnet ./bin/Release/PublishOutput/myapp.dll 44 | -------------------------------------------------------------------------------- /web/go/Dockerfile: -------------------------------------------------------------------------------- 1 | #TODO: https://gist.github.com/rrgarciach/0ea36f2ecb3e2211f42f75787ab9ec47 2 | -------------------------------------------------------------------------------- /web/nginx/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:latest 2 | ENTRYPOINT ["/script_run.sh"] 3 | ADD script_*.sh / 4 | RUN chown root:root /script_*.sh && chmod 544 /script_*.sh && sync && /script_init.sh 5 | -------------------------------------------------------------------------------- /web/nginx/script_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | # configure nginx 5 | echo ' 6 | daemon off; 7 | worker_processes 1; 8 | events { 9 | worker_connections 1024; 10 | use epoll; 11 | } 12 | http { 13 | include mime.types; 14 | default_type application/octet-stream; 15 | sendfile on; 16 | keepalive_timeout 65; 17 | client_max_body_size 1G; 18 | server_tokens off; 19 | rewrite_log on; 20 | server { 21 | server_name _; 22 | listen 80 default_server; 23 | root /home/webuser/www/public; 24 | include server_params; 25 | } 26 | include /home/webuser/conf/nginx/*.conf; 27 | } 28 | ' > /opt/nginx/conf/nginx.conf 29 | 30 | echo ' 31 | index index.html index.htm; 32 | try_files $uri $uri/; 33 | location ~* \.(?:ico|css|js|gif|jpe?g|png|JPG|svg|woff|woff2)$ { 34 | expires max; 35 | add_header Pragma public; 36 | add_header Cache-Control "public, must-revalidate, proxy-revalidate"; 37 | } 38 | location / { autoindex on; } 39 | location ~ /\. { access_log off; log_not_found off; deny all; } 40 | location = /robots.txt { access_log off; log_not_found off; } 41 | location = /favicon.ico { access_log off; log_not_found off; } 42 | ' > /opt/nginx/conf/server_params 43 | 44 | # clean up 45 | rm /script_init.sh 46 | -------------------------------------------------------------------------------- /web/nginx/script_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | mkdir -p /home/webuser/.ssh 5 | mkdir -p /home/webuser/log/nginx 6 | mkdir -p /home/webuser/conf/nginx 7 | mkdir -p /home/webuser/cache/nginx/tmp_client 8 | mkdir -p /home/webuser/cache/nginx/tmp_proxy 9 | mkdir -p /home/webuser/cache/nginx/tmp_fastcgi 10 | mkdir -p /home/webuser/cache/nginx/tmp_uwsgi 11 | mkdir -p /home/webuser/cache/nginx/tmp_scgi 12 | mkdir -p /home/webuser/www/public 13 | 14 | env > /home/webuser/.env 15 | echo 'It works!' > /home/webuser/www/public/index.htm 16 | 17 | chown -R webuser:webuser /home/webuser 18 | chmod -R 700 /home/webuser/.ssh 19 | 20 | [[ -f /script_run_aux.sh ]] && source /script_run_aux.sh 21 | 22 | if [ ! -z ${WEBUSER_PASSWORD:+x} ]; then 23 | echo "webuser:$WEBUSER_PASSWORD" | chpasswd 24 | /usr/sbin/sshd 25 | fi 26 | 27 | /script_update.sh --no-reload 28 | 29 | # tail -f /var/www/logs/*.log & 30 | 31 | exec /opt/nginx/sbin/nginx 32 | -------------------------------------------------------------------------------- /web/nginx/script_update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | NORELOAD=0 5 | [ $# -gt 0 ] && [ "$1" == "--no-reload" ] && NORELOAD=1 6 | [ $# -gt 0 ] && [ "$1" == "--debug" ] && set -x 7 | 8 | exit 0 9 | -------------------------------------------------------------------------------- /web/nodejs/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:latest 2 | ENTRYPOINT ["/script_run.sh"] 3 | ADD script_*.sh / 4 | RUN chown root:root /script_*.sh && chmod 544 /script_*.sh && sync && /script_init.sh 5 | -------------------------------------------------------------------------------- /web/nodejs/project.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mkdir -p /home/webuser/app 4 | 5 | cat > /home/webuser/app/package.json <<'EOL' 6 | { 7 | "name": "docker_web_app", 8 | "version": "1.0.0", 9 | "description": "Node.js on Docker", 10 | "author": "First Last ", 11 | "main": "server.js", 12 | "scripts": { 13 | "start": "node server.js" 14 | }, 15 | "dependencies": { 16 | "express": "^4.13.3" 17 | } 18 | } 19 | 20 | EOL 21 | 22 | cat > /home/webuser/app/server.js <<'EOL' 23 | 'use strict;' 24 | 25 | const express = require('express'); 26 | 27 | // Constants 28 | const PORT = 80; 29 | 30 | // App 31 | const app = express(); 32 | app.get('/', function (req, res) { 33 | res.send('Hello world\n'); 34 | }); 35 | 36 | app.listen(PORT); 37 | console.log('Running on http://localhost:' + PORT); 38 | 39 | EOL 40 | -------------------------------------------------------------------------------- /web/nodejs/script_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Requirements 4 | addgroup webuser 5 | adduser --disabled-password --no-create-home --shell /bin/bash --gecos "" --home /home/webuser --ingroup webuser webuser 6 | 7 | npm i -g yarn 8 | npm i -g pm2 9 | 10 | # Clean up 11 | rm /script_init.sh 12 | -------------------------------------------------------------------------------- /web/nodejs/script_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mkdir -p /home/webuser/app 4 | [[ -f /home/webuser/project.sh ]] && source /home/webuser/project.sh 5 | chown -R webuser:webuser /home/webuser 6 | cd /home/webuser/app 7 | 8 | npm install 9 | 10 | exec npm start 11 | #exec yarn start 12 | -------------------------------------------------------------------------------- /web/php5apache/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:5-apache 2 | ENTRYPOINT ["/script_run.sh"] 3 | ADD script_*.sh / 4 | RUN chown root:root /script_*.sh && chmod 544 /script_*.sh && sync && /script_init.sh 5 | -------------------------------------------------------------------------------- /web/php5apache/script_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | apt-get -yq update 5 | apt-get -yq install git nano zip unzip libfreetype6-dev libicu-dev libpq-dev libjpeg62-turbo-dev libmcrypt-dev libpng-dev 6 | 7 | # PHP Core Extensions 8 | docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ 9 | docker-php-ext-configure pdo_mysql --with-pdo-mysql=mysqlnd 10 | docker-php-ext-install -j$(nproc) iconv mcrypt zip gd intl mbstring pcntl pdo_mysql pdo_pgsql pgsql 11 | 12 | a2enmod rewrite 13 | 14 | # Composer 15 | cd /tmp 16 | php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" 17 | php composer-setup.php 18 | php -r "unlink('composer-setup.php');" 19 | mv composer.phar /usr/local/bin/composer 20 | composer global require "laravel/installer" 21 | 22 | cat > /etc/profile.d/aliases.sh <<'EOL' 23 | alias ll="ls -alh" 24 | EOL 25 | 26 | cat > /etc/profile.d/envvars.sh <<'EOL' 27 | export TERM=xterm 28 | export TEMP=/home/webuser/tmp/tmp 29 | export COMPOSER_HOME=/home/webuser/.composer 30 | export PS1='\u@\H:\w\$ ' 31 | EOL 32 | 33 | cat > /etc/profile.d/path.sh <<'EOL' 34 | export PATH=$PATH:/home/webuser/.composer/vendor/bin 35 | export PATH=$PATH:/home/webuser/.npm-global/bin 36 | export PATH=$PATH:/home/webuser/spark-installer 37 | EOL 38 | source /etc/profile.d/path.sh 39 | 40 | # Site 41 | cat > /etc/apache2/sites-available/000-laravel.conf <<'EOL' 42 | #ServerName localhost 43 | 44 | ServerAdmin webmaster@localhost 45 | DocumentRoot /home/webuser/www/public 46 | 47 | Options FollowSymLinks 48 | AllowOverride All 49 | 50 | 51 | Options Indexes FollowSymLinks MultiViews 52 | AllowOverride All 53 | Order allow,deny 54 | Allow from all 55 | 56 | LogLevel warn 57 | ErrorLog /home/webuser/log/apache/error.log 58 | CustomLog /home/webuser/log/apache/access.log combined 59 | 60 | EOL 61 | 62 | cat >> /etc/apache2/conf-available/docker-php.conf <<'EOL' 63 | 64 | #Options -Indexes 65 | AllowOverride All 66 | Options Indexes FollowSymLinks 67 | #AllowOverride None 68 | Require all granted 69 | 70 | EOL 71 | 72 | /usr/sbin/a2dissite '*' 73 | /usr/sbin/a2ensite 000-laravel 74 | 75 | rm -rf /var/www/html 76 | ln -s /home/webuser/www/public /var/www/html 77 | 78 | # Clean up 79 | rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 80 | rm /script_init.sh 81 | -------------------------------------------------------------------------------- /web/php5apache/script_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | mkdir -p /home/webuser/log/apache 5 | mkdir -p /home/webuser/www/public 6 | chown -R www-data:www-data /home/webuser 7 | 8 | exec apache2-foreground 9 | -------------------------------------------------------------------------------- /web/php7apache/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:apache 2 | ENTRYPOINT ["/script_run.sh"] 3 | ADD script_*.sh / 4 | RUN chown root:root /script_*.sh && chmod 540 /script_*.sh && sync && /script_init.sh 5 | -------------------------------------------------------------------------------- /web/php7apache/script_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | #sed -ri -e 's!/var/www/html!/home/webuser/www/public!g' /etc/apache2/sites-available/*.conf 5 | #sed -ri -e 's!/var/www!/home/webuser/www!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf 6 | 7 | apt-get -yq update 8 | apt-get -yq install git nano zip unzip wget libfreetype6-dev libjpeg62-turbo-dev libpng-dev zip unzip 9 | apt-get -yq install libicu-dev mysql-client libpq-dev libmcrypt-dev libssl-dev libsqlite3-dev 10 | #apt-get -yq install postgresql-client 11 | 12 | docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ 13 | docker-php-ext-configure pdo_mysql --with-pdo-mysql=mysqlnd 14 | 15 | #docker-php-ext-install -j$(nproc) mcrypt 16 | docker-php-ext-install -j$(nproc) mysqli tokenizer gd intl iconv mbstring pcntl pdo pdo_mysql pdo_pgsql pdo_sqlite pgsql zip opcache 17 | 18 | a2enmod rewrite 19 | 20 | rm -rf /var/www/html 21 | ln -s /home/webuser/www/public /var/www/html 22 | 23 | useradd --no-create-home --home-dir /home/webuser --shell /bin/bash --gid $(id -g www-data) --non-unique --uid $(id -u www-data) webuser 24 | 25 | # Composer 26 | curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer 27 | 28 | # Laravel 29 | composer global require "laravel/installer" 30 | 31 | # Site 32 | cat > /etc/apache2/sites-available/000-laravel.conf <<'EOL' 33 | #ServerName localhost 34 | 35 | ServerAdmin webmaster@localhost 36 | DocumentRoot /home/webuser/www/public 37 | 38 | Options FollowSymLinks 39 | AllowOverride All 40 | 41 | 42 | Options Indexes FollowSymLinks MultiViews 43 | AllowOverride All 44 | Order allow,deny 45 | Allow from all 46 | 47 | LogLevel warn 48 | ErrorLog /home/webuser/log/apache/error.log 49 | CustomLog /home/webuser/log/apache/access.log combined 50 | 51 | EOL 52 | 53 | cat >> /etc/apache2/conf-available/docker-php.conf <<'EOL' 54 | 55 | #Options -Indexes 56 | AllowOverride All 57 | Options Indexes FollowSymLinks 58 | #AllowOverride None 59 | Require all granted 60 | 61 | EOL 62 | 63 | cp $PHP_INI_DIR/php.ini-development $PHP_INI_DIR/php.ini 64 | echo "memory_limit=-1" > $PHP_INI_DIR/conf.d/memory-limit.ini 65 | echo "max_execution_time=0" > $PHP_INI_DIR/conf.d/max-execution-time.ini 66 | echo "upload_max_filesize=1024M" > $PHP_INI_DIR/conf.d/upload.ini 67 | echo "post_max_size=1024M" >> $PHP_INI_DIR/conf.d/upload.ini 68 | 69 | /usr/sbin/a2dissite '*' 70 | /usr/sbin/a2ensite 000-laravel 71 | 72 | cat > /etc/profile.d/aliases.sh <<'EOL' 73 | alias ll="ls -alh" 74 | EOL 75 | 76 | cat > /etc/profile.d/envvars.sh <<'EOL' 77 | export TERM=xterm 78 | export TEMP=/home/webuser/tmp/temp 79 | export COMPOSER_HOME=/home/webuser/.composer 80 | export PS1='\u@\H:\w\$ ' 81 | EOL 82 | 83 | cat > /etc/profile.d/path.sh <<'EOL' 84 | export PATH=$PATH:/home/webuser/.composer/vendor/bin 85 | export PATH=$PATH:/home/webuser/.npm-global/bin 86 | export PATH=$PATH:/home/webuser/spark-installer 87 | EOL 88 | source /etc/profile.d/path.sh 89 | 90 | rm -rf /var/www/html 91 | ln -s /home/webuser/www/public /var/www/html 92 | 93 | # Clean up 94 | rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 95 | rm /script_init.sh 96 | -------------------------------------------------------------------------------- /web/php7apache/script_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | mkdir -p /home/webuser/log/apache 5 | mkdir -p /home/webuser/www/public 6 | mkdir -p /home/webuser/tmp/temp 7 | chown -R www-data:www-data /home/webuser 8 | 9 | NEWUSER=$(hostname | tr -d "_.-") 10 | if [ ! -d /home/$NEWUSER ]; then 11 | useradd --no-create-home --home-dir /home/$NEWUSER --shell /bin/bash --gid $(id -g www-data) --non-unique --uid $(id -u www-data) $NEWUSER 12 | ln -s /home/webuser /home/$NEWUSER 13 | fi 14 | 15 | export APACHE_LOG_DIR=/home/webuser/log/apache 16 | exec apache2-foreground 17 | -------------------------------------------------------------------------------- /web/php7nginx/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fffaraz/web/php7nginx/base:latest 2 | ENTRYPOINT ["/script_run.sh"] 3 | ADD script_*.sh / 4 | RUN chown root:root /script_*.sh && chmod 540 /script_*.sh && sync && /script_init.sh 5 | -------------------------------------------------------------------------------- /web/php7nginx/base/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:latest 2 | #FROM phusion/baseimage:latest 3 | #FROM blitznote/debootstrap-amd64:16.10 4 | ADD script_*.sh / 5 | RUN chown root:root /script_*.sh && chmod 540 /script_*.sh && sync && /script_init.sh 6 | -------------------------------------------------------------------------------- /web/php7nginx/base/script_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | NGINX_VERSION=1.11.7 5 | PHP_VERSION=7.1.0 6 | 7 | NGINX_URL="https://nginx.org/en/download.html" 8 | #RUNTIME_DEPS="libpcre3" 9 | BUILD_DEPS="build-essential gcc g++ make" 10 | NPROC=$(($(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1)+1)) 11 | 12 | # Requirements 13 | addgroup webuser 14 | adduser --home /home/webuser --shell /bin/bash --no-create-home --gecos "" --ingroup webuser --disabled-password webuser 15 | 16 | export DEBIAN_FRONTEND=noninteractive 17 | apt-get -yq update < /dev/null 18 | apt-get -yq upgrade < /dev/null 19 | apt-get -yq install bash ca-certificates curl dnsutils git iputils-ping mysql-client nano ncdu tree wget whois zip unzip xz-utils < /dev/null # perl python nodejs logrotate 20 | apt-get -yq install openssl openssh-client openssh-sftp-server dropbear # openssh 21 | apt-get -yq install $BUILD_DEPS libzip-dev zlib1g-dev libpcre3-dev libssl-dev libxslt1-dev libgd-dev libperl-dev libbz2-dev libfreetype6-dev libjpeg-turbo8-dev libpng-dev libxml2-dev libcurl4-gnutls-dev < /dev/null 22 | # TODO: dig, nslookup, whois 23 | 24 | # libmysqlclient-dev bison libcurl4-openssl-dev libjpeg-dev libpspell-dev librecode-dev 25 | #apt-get -yq build-dep nginx php7 < /dev/null 26 | #pear install pear/PHP_Archive 27 | 28 | echo "/usr/local/lib" > /etc/ld.so.conf.d/usr-local-lib.conf 29 | ldconfig 30 | mkdir -p /opt 31 | cd /opt 32 | 33 | # Install SSH 34 | #ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa 35 | #ssh-keygen -f /etc/ssh/ssh_host_dsa_key -N '' -t dsa 36 | #ssh-keygen -f /etc/ssh/ssh_host_ecdsa_key -N '' -t ecdsa 37 | #ssh-keygen -f /etc/ssh/ssh_host_ed25519_key -N '' -t ed25519 38 | #mkdir -p /etc/dropbear 39 | #dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key 40 | #dropbearkey -t dss -f /etc/dropbear/dropbear_dss_host_key 41 | #dropbearkey -t ecdsa -f /etc/dropbear/dropbear_ecdsa_host_key 42 | 43 | # Install NGINX 44 | # https://ngxpagespeed.com/install 45 | function version_sort() { 46 | sort -t '.' -k 1,1 -k 2,2 -k 3,3 -k 4,4 -g 47 | } 48 | function version_older_than() { 49 | local test_version="$1" 50 | local compare_to="$2" 51 | local older_version=$(echo $@ | tr ' ' '\n' | version_sort | head -n 1) 52 | test "$older_version" != "$compare_to" 53 | } 54 | 55 | cd /opt 56 | versions_available=$(curl -sS --fail "$NGINX_URL" | grep -o '/download/nginx-[0-9.]*[.]tar[.]gz' | sed -e 's~^/download/nginx-~~' -e 's~\.tar\.gz$~~') 57 | latest_version=$(echo "$versions_available" | version_sort | tail -n 1) 58 | if version_older_than "$latest_version" "$NGINX_VERSION"; then 59 | echo "Expected the latest version of nginx to be at least $NGINX_VERSION but found $latest_version" 60 | exit 1 61 | fi 62 | NGINX_VERSION=$latest_version 63 | 64 | wget -q http://nginx.org/download/nginx-$NGINX_VERSION.tar.gz 65 | tar -xzf nginx-$NGINX_VERSION.tar.gz 66 | rm nginx-$NGINX_VERSION.tar.gz 67 | cd nginx-$NGINX_VERSION 68 | ./configure \ 69 | --prefix=/opt/nginx \ 70 | --error-log-path=/home/webuser/log/nginx/error.log \ 71 | --http-log-path=/home/webuser/log/nginx/access.log \ 72 | --http-client-body-temp-path=/home/webuser/tmp/nginx/client \ 73 | --http-proxy-temp-path=/home/webuser/tmp/nginx/proxy \ 74 | --http-fastcgi-temp-path=/home/webuser/tmp/nginx/fastcgi \ 75 | --http-uwsgi-temp-path=/home/webuser/tmp/nginx/uwsgi \ 76 | --http-scgi-temp-path=/home/webuser/tmp/nginx/scgi \ 77 | --user=webuser \ 78 | --group=webuser \ 79 | --without-select_module \ 80 | --without-poll_module \ 81 | --without-http_gzip_module \ 82 | --without-http_proxy_module \ 83 | --with-http_realip_module 84 | 85 | make -j${NPROC} 86 | make install 87 | cd /opt 88 | rm -rf nginx-$NGINX_VERSION 89 | 90 | # TODO: https://github.com/pagespeed/ngx_pagespeed 91 | # https://developers.google.com/speed/pagespeed/module/configuration 92 | # https://developers.google.com/speed/pagespeed/module/build_ngx_pagespeed_from_source 93 | # https://www.digitalocean.com/community/tutorials/how-to-add-ngx_pagespeed-to-nginx-on-ubuntu-14-04 94 | 95 | # Install PHP7 96 | 97 | latest_version=$(curl -sS --fail "http://php.net/releases/index.php?json&version=7&max=1" | grep -o 'php-[0-9.]*[.]tar[.]gz' | sed -e 's~^php-~~' -e 's~\.tar\.gz$~~') 98 | if version_older_than "$latest_version" "$PHP_VERSION"; then 99 | echo "Expected the latest version of php to be at least $PHP_VERSION but found $latest_version" 100 | exit 1 101 | fi 102 | PHP_VERSION=$latest_version 103 | 104 | cd /opt 105 | wget -qO php-$PHP_VERSION.tar.xz http://php.net/get/php-$PHP_VERSION.tar.xz/from/this/mirror 106 | tar -Jxf php-$PHP_VERSION.tar.xz 107 | rm php-$PHP_VERSION.tar.xz 108 | cd php-$PHP_VERSION 109 | # --enable-compile-warnings=no 110 | ./configure \ 111 | --prefix=/opt/php \ 112 | --with-config-file-path=/opt/php/conf \ 113 | --with-config-file-scan-dir=/opt/php/conf/php.ini.d \ 114 | --enable-bcmath \ 115 | --enable-calendar \ 116 | --enable-dba \ 117 | --enable-exif \ 118 | --enable-fpm \ 119 | --enable-ftp \ 120 | --enable-gd-jis-conv \ 121 | --enable-gd-native-ttf \ 122 | --enable-mbstring \ 123 | --enable-mysqlnd \ 124 | --enable-opcache \ 125 | --enable-pcntl \ 126 | --enable-shmop \ 127 | --enable-soap \ 128 | --enable-sockets \ 129 | --enable-sysvmsg \ 130 | --enable-sysvsem \ 131 | --enable-sysvshm \ 132 | --enable-wddx \ 133 | --enable-zip \ 134 | --disable-cgi \ 135 | --disable-debug \ 136 | --disable-phpdbg \ 137 | --with-bz2 \ 138 | --with-curl \ 139 | --with-fpm-group=webuser \ 140 | --with-fpm-user=webuser \ 141 | --with-gd \ 142 | --with-freetype-dir=/usr/include/ \ 143 | --with-png-dir=/usr/include/ \ 144 | --with-jpeg-dir=/usr/include/ \ 145 | --with-mhash \ 146 | --with-mysqli=mysqlnd \ 147 | --with-openssl \ 148 | --with-pdo-mysql=mysqlnd \ 149 | --with-zlib 150 | make -j${NPROC} 151 | make install 152 | make clean 153 | cd /opt 154 | rm -rf php-$PHP_VERSION 155 | rm -rf /opt/php/include 156 | rm -rf /opt/php/php 157 | 158 | # Clean up 159 | apt-get purge -yq --auto-remove $BUILD_DEPS 160 | apt-get -yq autoremove < /dev/null 161 | apt-get -yq autoclean < /dev/null 162 | sync 163 | 164 | rm -rf /var/lib/apt/lists/* 165 | rm -rf /var/lib/apt 166 | rm -rf /var/cache/apt 167 | 168 | rm -rf /home/webuser 169 | rm -rf /var/tmp/* 170 | rm -rf /tmp/* 171 | 172 | rm /script_init.sh 173 | exit 0 174 | -------------------------------------------------------------------------------- /web/php7nginx/script_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | # Configure openssh 5 | 6 | mkdir -p /etc/security 7 | echo ' 8 | webuser hard nproc 256 9 | ' > /etc/security/limits.conf 10 | 11 | echo ' 12 | Banner /etc/issue 13 | LoginGraceTime 1m 14 | PermitRootLogin no 15 | MaxAuthTries 3 16 | MaxSessions 1 17 | PasswordAuthentication yes 18 | PermitEmptyPasswords no 19 | AllowAgentForwarding no 20 | AllowTcpForwarding no 21 | X11Forwarding no 22 | UseDNS no 23 | MaxStartups 2:30:10 24 | Subsystem sftp /usr/lib/ssh/sftp-server 25 | #Subsystem sftp internal-sftp 26 | 27 | #Match User webuser 28 | #ForceCommand internal-sftp 29 | #PasswordAuthentication yes 30 | #ChrootDirectory /home/webuser 31 | #PermitTunnel no 32 | #AllowAgentForwarding no 33 | #AllowTcpForwarding no 34 | #X11Forwarding no 35 | 36 | ' > /etc/ssh/sshd_config 37 | 38 | # Display SSH Warning Message BEFORE the Login 39 | # https://www.cyberciti.biz/faq/howto-change-login-message/ 40 | # Ubuntu 16.04.1 LTS \n \l 41 | echo ' 42 | WARNING : Unauthorized access to this system is forbidden and will be 43 | prosecuted by law. By accessing this system, you agree that your actions 44 | may be monitored if unauthorized usage is suspected. 45 | Disconnect IMMEDIATELY if you are not an authorized user! 46 | 47 | ' > /etc/issue 48 | 49 | # Display SSH Welcome Message AFTER the Login 50 | # ALERT! That is a secured area. Your IP is logged. Administrator has been notified 51 | echo ' 52 | Welcome 53 | ' > /etc/motd 54 | 55 | # Configure nginx 56 | # https://codex.wordpress.org/Nginx 57 | # http://nginx.org/en/docs/http/ngx_http_log_module.html 58 | 59 | mkdir -p /opt/nginx/conf/conf.d 60 | 61 | echo ' 62 | daemon off; 63 | worker_processes 1; 64 | error_log /home/webuser/log/nginx/error.log info; 65 | events { 66 | worker_connections 1024; 67 | multi_accept on; 68 | use epoll; 69 | } 70 | http { 71 | include mime.types; 72 | charset utf-8; 73 | default_type application/octet-stream; 74 | sendfile on; 75 | tcp_nopush on; 76 | tcp_nodelay on; 77 | keepalive_timeout 65; 78 | client_body_buffer_size 64K; 79 | client_max_body_size 1G; 80 | server_tokens off; 81 | rewrite_log on; 82 | open_file_cache max=1000 inactive=20s; 83 | open_file_cache_valid 60s; 84 | open_file_cache_min_uses 5; 85 | open_file_cache_errors off; 86 | #log_format main $http_x_forwarded_for - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"; 87 | access_log /home/webuser/log/nginx/access.log combined; 88 | index index.html index.htm index.php index.default.html; 89 | autoindex on; 90 | #set_real_ip_from 0.0.0.0/0; 91 | #real_ip_header X-Forwarded-For; # X-Real-IP 92 | map $http_x_forwarded_proto $fe_https { 93 | default off; 94 | https on; 95 | } 96 | server { 97 | server_name _; 98 | listen 80 default_server; 99 | listen [::]:80 default_server; 100 | root /home/webuser/www/public; 101 | include server_params; 102 | include /home/webuser/conf/nginx/default.conf*; 103 | } 104 | include /opt/nginx/conf/conf.d/*.conf; 105 | include /home/webuser/conf/nginx/conf.d/*.conf; 106 | } 107 | ' > /opt/nginx/conf/nginx.conf 108 | 109 | echo ' 110 | try_files $uri $uri/ /index.php$is_args$args; 111 | location ~ [^/]\.php(/|$) { 112 | #try_files $uri =404; 113 | fastcgi_split_path_info ^(.+?\.php)(/.*)$; 114 | if (!-f $document_root$fastcgi_script_name) { return 404; } 115 | include fastcgi_params; 116 | } 117 | location ~ ^/(fpm_status)$ { 118 | #allow 1.2.3.4; 119 | #deny all; 120 | include fastcgi_params; 121 | } 122 | location ~* \.(?:ico|css|js|gif|jpe?g|png|JPG|svg|woff|woff2|xml)$ { 123 | expires max; 124 | access_log off; 125 | #log_not_found off; 126 | add_header Pragma public; 127 | add_header Cache-Control "public, must-revalidate, proxy-revalidate"; 128 | } 129 | location ~ /\. { access_log off; log_not_found off; deny all; } 130 | location = /favicon.ico { access_log off; log_not_found off; } 131 | #location = /robots.txt { access_log off; log_not_found off; } 132 | #location ~* /(?:uploads|files)/.*\.php$ { deny all; } 133 | ' > /opt/nginx/conf/server_params 134 | 135 | # https://www.digitalocean.com/community/tutorials/understanding-and-implementing-fastcgi-proxying-in-nginx 136 | echo ' 137 | fastcgi_param CONTENT_LENGTH $content_length; 138 | fastcgi_param CONTENT_TYPE $content_type; 139 | fastcgi_param DOCUMENT_ROOT $document_root; 140 | fastcgi_param DOCUMENT_URI $document_uri; 141 | fastcgi_param GATEWAY_INTERFACE CGI/1.1; 142 | fastcgi_param HTTPS $fe_https; # $https if_not_empty; 143 | fastcgi_param HTTP_PROXY ""; 144 | fastcgi_param PATH_INFO $fastcgi_path_info; 145 | fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; 146 | fastcgi_param QUERY_STRING $query_string; 147 | fastcgi_param REDIRECT_STATUS 200; 148 | fastcgi_param REMOTE_ADDR $http_x_real_ip; # $remote_addr; 149 | fastcgi_param REMOTE_PORT $remote_port; 150 | fastcgi_param REQUEST_METHOD $request_method; 151 | fastcgi_param REQUEST_SCHEME $scheme; 152 | fastcgi_param REQUEST_URI $request_uri; 153 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 154 | fastcgi_param SCRIPT_NAME $fastcgi_script_name; 155 | fastcgi_param SERVER_ADDR $hostname; # $server_addr; 156 | fastcgi_param SERVER_NAME $host; # $server_name; $hostname; 157 | fastcgi_param SERVER_PORT $server_port; 158 | fastcgi_param SERVER_PROTOCOL $server_protocol; 159 | fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; 160 | fastcgi_buffer_size 128k; 161 | fastcgi_buffers 256 16k; 162 | fastcgi_busy_buffers_size 256k; 163 | fastcgi_index index.php; 164 | fastcgi_pass unix:/opt/php/var/run/webuser.sock; 165 | fastcgi_read_timeout 600; 166 | fastcgi_temp_file_write_size 256k; 167 | #fastcgi_ignore_client_abort on 168 | #fastcgi_intercept_errors on; 169 | ' > /opt/nginx/conf/fastcgi_params 170 | 171 | # Configure bash 172 | 173 | cat > /etc/profile.d/aliases.sh <<'EOL' 174 | alias ll="ls -alh" 175 | EOL 176 | 177 | cat > /etc/profile.d/envvars.sh <<'EOL' 178 | export TERM=xterm 179 | export TEMP=/home/webuser/tmp/tmp 180 | export COMPOSER_HOME=/home/webuser/.composer 181 | export PS1='\u@\H:\w\$ ' 182 | EOL 183 | 184 | cat > /etc/profile.d/path.sh <<'EOL' 185 | export PATH=$PATH:/opt/php/bin:/opt/bin:/opt/node/bin 186 | export PATH=$PATH:/opt/.composer/vendor/bin:/home/webuser/.composer/vendor/bin 187 | export PATH=$PATH:/home/webuser/.npm-global/bin 188 | export PATH=$PATH:/home/webuser/spark-installer 189 | EOL 190 | source /etc/profile.d/path.sh 191 | 192 | # Configure php 193 | 194 | mkdir -p /opt/php/conf/conf.d 195 | echo ' 196 | [PHP] 197 | cgi.fix_pathinfo=1 198 | #enable_dl=off 199 | #allow_url_fopen=off 200 | #allow_url_include=off 201 | #disable_functions=show_source,system,shell_exec,passthru,exec,popen,proc_open,curl_exec,curl_multi_exec,parse_ini_file # ini_set 202 | #open_basedir=/home/webuser/ 203 | display_errors=1 204 | error_reporting=E_ALL 205 | log_errors=1 206 | error_log=/home/webuser/log/php/error.log 207 | expose_php=off 208 | max_execution_time=600 209 | max_input_time=600 210 | memory_limit=512M 211 | post_max_size=1G 212 | upload_tmp_dir=/home/webuser/tmp/php/upload 213 | upload_max_filesize=1G 214 | session.gc_maxlifetime=36000 215 | session.save_path=/home/webuser/tmp/php/session 216 | mail.add_x_header=1 217 | mail.log=/home/webuser/log/php/mail.log 218 | sys_temp_dir=/home/webuser/tmp/php/systemp 219 | 220 | # realpath_cache_size=1M 221 | # realpath_cache_ttl=120 222 | # cgi.check_shebang_line=0 223 | 224 | # http://php.net/manual/en/opcache.configuration.php 225 | zend_extension=opcache.so 226 | opcache.consistency_checks=0 227 | opcache.enable=1 228 | opcache.enable_cli=1 229 | opcache.fast_shutdown=1 230 | opcache.file_cache=/home/webuser/tmp/php/opcache 231 | opcache.file_cache_consistency_checks=1 232 | opcache.file_cache_only=1 233 | opcache.interned_strings_buffer=8 234 | opcache.load_comments=0 235 | opcache.max_accelerated_files=4000 236 | opcache.max_file_size=0 237 | opcache.max_wasted_percentage=5 238 | opcache.memory_consumption=64 239 | opcache.revalidate_freq=60 240 | opcache.revalidate_path=0 241 | opcache.save_comments=0 242 | opcache.use_cwd=1 243 | opcache.validate_timestamps=1 244 | 245 | [mail function] 246 | sendmail_path=/opt/bin/phpsendmail 247 | 248 | [Date] 249 | date.timezone=UTC 250 | ' > /opt/php/conf/php.ini 251 | 252 | echo ' 253 | [global] 254 | log_level = notice 255 | error_log = /home/webuser/log/php/php-fpm.log 256 | emergency_restart_threshold = 10 257 | emergency_restart_interval = 1m 258 | process_control_timeout = 10s 259 | events.mechanism = epoll 260 | 261 | [webuser] 262 | ;prefix = /home/webuser 263 | user = webuser 264 | group = webuser 265 | listen = /opt/php/var/run/webuser.sock 266 | listen.owner = webuser 267 | listen.group = webuser 268 | listen.mode = 0660 269 | clear_env = no 270 | catch_workers_output = yes 271 | request_terminate_timeout = 600s 272 | request_slowlog_timeout = 2s 273 | access.log = /home/webuser/log/php/access.log 274 | access.format = "%{HTTP_X_FORWARDED_FOR}e - %R - %u %t \"%m %l %r%Q%q\" %s %f %{mili}dms %{kilo}Mkb %C%%" 275 | ;access.format = "%{HTTP_X_FORWARDED_FOR}e - [%t] \"%m %r%Q%q\" %s %l - %P %p %{seconds}d %{bytes}M %{user}C%% %{system}C%% \"%{REQUEST_URI}e\"" 276 | slowlog = /home/webuser/log/php/slow.log 277 | security.limit_extensions = .php 278 | php_flag[display_errors] = on 279 | php_admin_flag[log_errors] = on 280 | php_admin_value[memory_limit] = 512M 281 | php_admin_value[cgi.fix_pathinfo] = 1 282 | php_admin_value[error_log] = /home/webuser/log/php/error.log 283 | php_value[mail.log] = /home/webuser/log/php/mail.log 284 | ;php_admin_value[sendmail_path] = 285 | 286 | ;php_value[doc_root] = /home/webuser/www/public 287 | ;php_value[upload_tmp_dir] = /home/webuser/tmp/php/upload 288 | ;php_value[session.save_path] = /home/webuser/tmp/php/session 289 | 290 | ;env[PATH] = /opt/php/bin:/sbin:/usr/sbin:/bin:/usr/bin 291 | ;env[TMPDIR] = /home/webuser/tmp/tmp 292 | ;env[TEMP] = /home/webuser/tmp/tmp 293 | ;env[TMP] = /home/webuser/tmp/tmp 294 | 295 | pm=dynamic 296 | pm.start_servers=1 297 | pm.max_children=10 298 | pm.min_spare_servers=1 299 | pm.max_spare_servers=2 300 | pm.max_requests=1000 301 | ;pm.process_idle_timeout=60s 302 | 303 | pm.status_path=/fpm_status 304 | 305 | ' > /opt/php/etc/php-fpm.conf 306 | mkdir -p /home/webuser/tmp/php/opcache 307 | mkdir -p /home/webuser/tmp/php/systemp 308 | php -v 309 | 310 | # Install composer 311 | cd /opt 312 | mkdir -p /opt/bin 313 | #wget -qO /opt/bin/composer-setup.php https://getcomposer.org/installer 314 | #php /opt/bin/composer-setup.php --install-dir=/opt/bin --filename=composer 315 | #rm /opt/bin/composer-setup.php 316 | 317 | wget -qO /opt/bin/composer https://getcomposer.org/download/1.6.3/composer.phar 318 | chmod +x /opt/bin/composer 319 | mkdir -p /opt/.composer 320 | export COMPOSER_HOME=/opt/.composer 321 | php /opt/bin/composer -V 322 | 323 | # Install laravel 324 | composer global require laravel/installer 325 | #composer global require laravel/lumen-installer 326 | laravel --version 327 | 328 | # Install drush 329 | #wget -qO /opt/bin/drush https://s3.amazonaws.com/files.drush.org/drush.phar 330 | #chmod +x /opt/bin/drush 331 | 332 | # Install phan 333 | # https://github.com/etsy/phan 334 | #composer global require --dev etsy/phan:dev-master 335 | #composer global install 336 | 337 | # Install node.js & npm 338 | #NODE_VERSION=8.9.4 339 | #cd /opt 340 | #wget -q https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.xz 341 | #tar -xJf node-v${NODE_VERSION}-linux-x64.tar.xz 342 | #rm node-v${NODE_VERSION}-linux-x64.tar.xz 343 | #mv node-v${NODE_VERSION}-linux-x64 node 344 | 345 | # Install gulp 346 | #npm install --global gulp-cli 347 | 348 | # bower, yo, grunt, yarn 349 | # sass, compass 350 | # imagemagic, ffmpeg 351 | 352 | # Install sendmail 353 | cat > /opt/bin/phpsendmail <<'EOL' 354 | #!/opt/php/bin/php 355 | 362 | */ 363 | 364 | $sendmail_bin = '/usr/sbin/sendmail'; 365 | $logfile = '/home/webuser/log/php/phpsendmail.log'; 366 | 367 | // Get the email content 368 | $logline = ''; 369 | $pointer = fopen('php://stdin', 'r'); 370 | 371 | $mail = ''; 372 | while ($line = fgets($pointer)) { 373 | if(preg_match('/^to:/i', $line) || preg_match('/^from:/i', $line)) $logline .= trim($line) . ' '; 374 | $mail .= $line; 375 | } 376 | 377 | // compose the sendmail command 378 | $command = 'echo ' . escapeshellarg($mail) . ' | ' . $sendmail_bin . ' -t -i '; 379 | for ($i = 1; $i < $_SERVER['argc']; $i++) $command .= escapeshellarg($_SERVER['argv'][$i]) . ' '; 380 | 381 | // Write the log 382 | file_put_contents($logfile, date('Y-m-d H:i:s') . ' ' . $_ENV['PWD'] . ' ' . $logline . "\n", FILE_APPEND | LOCK_EX); 383 | // Execute the command 384 | return shell_exec($command); 385 | 386 | EOL 387 | chmod +x /opt/bin/phpsendmail 388 | 389 | # Clean up 390 | sync 391 | rm -rf /home/webuser 392 | rm /script_init.sh 393 | exit 0 394 | -------------------------------------------------------------------------------- /web/php7nginx/script_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | rm -rf /home/webuser/tmp 5 | mkdir -p /home/webuser/.ssh 6 | mkdir -p /home/webuser/backup 7 | mkdir -p /home/webuser/log/php 8 | mkdir -p /home/webuser/log/nginx 9 | mkdir -p /home/webuser/conf/nginx 10 | mkdir -p /home/webuser/conf/nginx/conf.d 11 | mkdir -p /home/webuser/tmp/tmp 12 | mkdir -p /home/webuser/tmp/php/opcache 13 | mkdir -p /home/webuser/tmp/php/upload 14 | mkdir -p /home/webuser/tmp/php/session 15 | mkdir -p /home/webuser/tmp/php/systemp 16 | mkdir -p /home/webuser/tmp/nginx/client 17 | mkdir -p /home/webuser/tmp/nginx/proxy 18 | mkdir -p /home/webuser/tmp/nginx/fastcgi 19 | mkdir -p /home/webuser/tmp/nginx/uwsgi 20 | mkdir -p /home/webuser/tmp/nginx/scgi 21 | mkdir -p /home/webuser/www/public 22 | 23 | rm -rf /tmp 24 | ln -s /home/webuser/tmp/tmp /tmp 25 | chmod 1777 /tmp 26 | chmod -R 700 /home/webuser/.ssh 27 | 28 | #find /home/webuser/www -type d -exec chmod 0755 {} \; 29 | #find /home/webuser/www -type f -exec chmod 0644 {} \; 30 | 31 | NEWUSER=$(hostname | tr -d "_.-") 32 | if [ ! -d /home/$NEWUSER ]; then 33 | useradd --no-create-home --home-dir /home/$NEWUSER --shell /bin/bash --gid $(id -g webuser) --non-unique --uid $(id -u webuser) $NEWUSER 34 | ln -s /home/webuser /home/$NEWUSER 35 | fi 36 | 37 | # /var/tmp 38 | # /etc/shells 39 | 40 | PS1='$ ' 41 | 42 | set +u 43 | source /etc/profile 44 | set -u 45 | 46 | env > /home/webuser/tmp/envvars 47 | set +x 48 | echo ' /home/webuser/www/public/_info_.php 49 | echo " 50 | 51 | 52 | 53 | 54 | $(hostname) 55 | 65 | 66 | 67 |

$(hostname)

68 |

If you see this page, the web server is successfully installed and working. 69 | Further configuration is required.

70 | 71 | 72 | " > /home/webuser/www/public/index.default.html 73 | set -x 74 | 75 | [[ -f /script_run_aux.sh ]] && source /script_run_aux.sh 76 | chown -R webuser:webuser /home/webuser 77 | [[ -f /home/webuser/project.sh ]] && su webuser -c '/bin/bash /home/webuser/project.sh' 78 | /script_update.sh --no-reload 79 | 80 | if [ -f /home/webuser/www/composer.json ]; then 81 | echo "Found 'composer.json', installing dependencies ..." 82 | #composer install --no-interaction --no-ansi --optimize-autoloader 83 | fi 84 | 85 | if [ ! -z "${WEBUSER_PASSWORD:+x}" ]; then 86 | echo "webuser:${WEBUSER_PASSWORD}" | chpasswd 87 | echo "${NEWUSER}:${WEBUSER_PASSWORD}" | chpasswd 88 | #/usr/sbin/sshd 89 | dropbear -Ewgjk -b /etc/issue -p 22 -K 120 -I 1200 90 | # svr-runopts.c 91 | # -b bannerfile 92 | # -d dsskey 93 | # -r rsakey 94 | # -R Create hostkeys as required 95 | # -F Don't fork into background 96 | # -E Log to stderr rather than syslog 97 | # -m Don't display the motd on login 98 | # -w Disallow root logins 99 | # -s Disable password logins 100 | # -g Disable password logins for root 101 | # -j Disable local port forwarding 102 | # -k Disable remote port forwarding 103 | # -p [address:]port 104 | # -i Service program mode 105 | # -P pidfile 106 | # -a Allow remote hosts to connect to forwarded ports 107 | # -W windowsize 108 | # -K timeout_seconds 109 | # -I idle_timeout 110 | # no-port-forwarding 111 | # no-agent-forwarding 112 | # no-X11-forwarding 113 | # no-pty 114 | # command="forced_command" 115 | fi 116 | 117 | /opt/php/sbin/php-fpm 118 | chmod 644 /home/webuser/log/php/*.log 119 | exec /opt/nginx/sbin/nginx 120 | -------------------------------------------------------------------------------- /web/php7nginx/script_update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | NORELOAD=0 5 | [ $# -gt 0 ] && [ "$1" == "--no-reload" ] && NORELOAD=1 6 | [ $# -gt 0 ] && [ "$1" == "--debug" ] && set -x 7 | 8 | if [ ! -f /home/webuser/domains.conf ]; then 9 | echo "# DIRECTORY DOMAIN1 [DOMAINS...]" > /home/webuser/domains.conf 10 | chown webuser:webuser /home/webuser/domains.conf 11 | fi 12 | 13 | rm -f /opt/nginx/conf/conf.d/*.conf 14 | 15 | sed -e '/^#/d' -e '/^$/d' /home/webuser/domains.conf | while read -r -a line; do 16 | DIRECTORY=${line[0]} 17 | SERVERNAME="server_name" 18 | for (( i = 1; i < ${#line[@]}; i++ )); do 19 | SERVERNAME=$SERVERNAME" ${line[$i]} www.${line[$i]}" 20 | done 21 | echo " 22 | server 23 | { 24 | $SERVERNAME; 25 | listen 80; 26 | root /home/webuser/$DIRECTORY/public; 27 | include server_params; 28 | include /home/webuser/conf/nginx/$DIRECTORY.conf*; 29 | } 30 | " > /opt/nginx/conf/conf.d/$DIRECTORY.conf 31 | mkdir -p /home/webuser/$DIRECTORY/public 32 | chown webuser:webuser /home/webuser/$DIRECTORY 33 | chown webuser:webuser /home/webuser/$DIRECTORY/public 34 | done 35 | 36 | [ $NORELOAD -eq 0 ] && /opt/nginx/sbin/nginx -s reload 37 | 38 | exit 0 39 | -------------------------------------------------------------------------------- /web/python3/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:latest 2 | ENTRYPOINT ["/script_run.sh"] 3 | ADD script_*.sh / 4 | RUN chown root:root /script_*.sh && chmod 540 /script_*.sh && sync && /script_init.sh 5 | -------------------------------------------------------------------------------- /web/python3/script_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | groupadd webuser 5 | useradd --no-create-home --shell /bin/bash --gid webuser webuser 6 | 7 | apt-get update 8 | apt-get -yq install ca-certificates nano nginx tree wget 9 | pip install django gunicorn psycopg2 uwsgi Flask 10 | 11 | echo ' 12 | uwsgi_param QUERY_STRING $query_string; 13 | uwsgi_param REQUEST_METHOD $request_method; 14 | uwsgi_param CONTENT_TYPE $content_type; 15 | uwsgi_param CONTENT_LENGTH $content_length; 16 | 17 | uwsgi_param REQUEST_URI $request_uri; 18 | uwsgi_param PATH_INFO $document_uri; 19 | uwsgi_param DOCUMENT_ROOT $document_root; 20 | uwsgi_param SERVER_PROTOCOL $server_protocol; 21 | uwsgi_param REQUEST_SCHEME $scheme; 22 | uwsgi_param HTTPS $https if_not_empty; 23 | 24 | uwsgi_param REMOTE_ADDR $remote_addr; 25 | uwsgi_param REMOTE_PORT $remote_port; 26 | uwsgi_param SERVER_PORT $server_port; 27 | uwsgi_param SERVER_NAME $server_name; 28 | ' > /etc/nginx/uwsgi_params 29 | 30 | echo ' 31 | daemon off; 32 | user webuser; 33 | worker_processes 1; 34 | pid /run/nginx.pid; 35 | error_log /home/webuser/log/nginx/error.log; 36 | events { 37 | worker_connections 1024; 38 | multi_accept on; 39 | } 40 | http { 41 | sendfile on; 42 | tcp_nopush on; 43 | tcp_nodelay on; 44 | keepalive_timeout 65; 45 | charset utf-8; 46 | client_max_body_size 128M; 47 | types_hash_max_size 2048; 48 | include /etc/nginx/mime.types; 49 | default_type application/octet-stream; 50 | access_log /home/webuser/log/nginx/access.log; 51 | server { 52 | listen 80 default_server; 53 | location /media { 54 | alias /home/webuser/www/media; 55 | } 56 | location /static { 57 | alias /home/webuser/www/static; 58 | } 59 | location = /favico.ico { alias /home/webuser/www/favico.ico; } 60 | location / { 61 | proxy_pass http://127.0.0.1:8000; 62 | proxy_set_header Host $host; 63 | proxy_set_header X-Real-IP $remote_addr; 64 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 65 | proxy_set_header X-Forwarded-Host $server_name; 66 | 67 | #include uwsgi_params; 68 | #uwsgi_pass 127.0.0.1:8000; 69 | #proxy_redirect off; 70 | } 71 | } 72 | } 73 | ' > /etc/nginx/nginx.conf 74 | 75 | rm -rf /var/lib/apt/lists/* 76 | rm /script_init.sh 77 | -------------------------------------------------------------------------------- /web/python3/script_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | mkdir -p /home/webuser/.ssh 5 | mkdir -p /home/webuser/log/nginx 6 | mkdir -p /home/webuser/tmp 7 | mkdir -p /home/webuser/www 8 | 9 | chmod -R 700 /home/webuser/.ssh 10 | 11 | [ ! -f /home/webuser/www/wsgi.py ] && cat > /home/webuser/www/wsgi.py <<'EOL' 12 | def application(environ, start_response): 13 | start_response('200 OK', [('Content-Type', 'text/html')]) 14 | return [b"

Hello There!

"] 15 | EOL 16 | 17 | chown -R webuser:webuser /home/webuser 18 | 19 | [ -f /home/webuser/www/requirements.txt ] && pip install -r /home/webuser/www/requirements.txt 20 | 21 | cd /home/webuser/www 22 | 23 | uwsgi --uid webuser --gid webuser --socket 127.0.0.1:8000 --protocol=http --wsgi-file wsgi.py & 24 | exec /usr/sbin/nginx 25 | 26 | #exec uwsgi --ini myapp.ini 27 | #exec uwsgi --json myapp.json 28 | #exec gunicorn --bind 127.0.0.1:8000 myproject.wsgi:application 29 | #exec python manage.py runserver 127.0.0.1:8000 30 | 31 | #python manage.py collectstatic --noinput 32 | #/usr/local/bin/gunicorn config.wsgi -w 4 -b 127.0.0.1:8000 --chdir=/app --log-level=DEBUG --timeout 600 33 | --------------------------------------------------------------------------------