diff --git a/.env.dist b/.env.dist index 54fee77a..d204228e 100644 --- a/.env.dist +++ b/.env.dist @@ -71,10 +71,6 @@ SSH_PASSWORDLESS=false # Your RSA Public key. RSA_PUB_KEY="copy your ssh public rsa key here" -# Hash length (bits), supported value 2048 | 4096 (take longer times) -# length of bits used for generating RSA key / Diffie-Helman params. -KEY_HASH_LENGTH=2048 - [nginx] INSTALL_NGINX=true @@ -144,12 +140,16 @@ LUA_RESTY_LRUCACHE_VERSION="v0.11" NGX_HTTP_PASSENGER=false NGX_HTTP_REDIS2=false NGX_HTTP_SUBS_FILTER=true -NGX_HTTP_UPSTREAM_FAIR=true +NGX_HTTP_UPSTREAM_FAIR=false NGX_HTTP_VTS=true NGX_HTTP_XSLT_FILTER=true NGX_MAIL=true NGX_NCHAN=false + +# For Nginx latest v1.23 or greater, try using NPS v1.14.33.1-RC1 or master +NGX_PAGESPEED_VERSION="v1.13.35.2-stable" NGX_PAGESPEED=false + NGX_RTMP=false NGX_STREAM=true @@ -279,9 +279,12 @@ FTP_SERVER_VERSION="latest" # Enable FTP over TLS. FTP_SSL_ENABLE=true +# Enable passv mode. +FTP_PASV_MODE=true + # Range of passv ports. FTP_MIN_PORT=45000 -FTP_MAX_PORT=45999 +FTP_MAX_PORT=45099 [dns] # TODO: Install DNS server. @@ -296,9 +299,16 @@ INSTALL_SPFDKIM=true SENDER_DOMAIN="" [certbot] +# Install Let's Encrypt SSL certificate is mandatory. INSTALL_CERTBOT=true + +# Path to live certificate for production server. HOSTNAME_CERT_PATH="" +# Hash length (bits), supported value 2048 | 4096 (take longer times) +# length of bits used for generating RSA key / Diffie-Helman params. +KEY_HASH_LENGTH=2048 + [firewall] INSTALL_FW=true @@ -312,4 +322,4 @@ INSTALL_FAIL2BAN=true # Available installer: repo | source. FAIL2BAN_INSTALLER="source" -FAIL2BAN_VERSION="0.11.2" +FAIL2BAN_VERSION="1.0.2" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5c3dd91c..a6c5c93b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -61,9 +61,8 @@ jobs: shellcheck -s bash -x remove.sh shellcheck -s bash -x bin/lemper-*.sh shellcheck -s bash -x lib/lemper-*.sh - shellcheck -s bash -x scripts/helper.sh - shellcheck -s bash -x scripts/cleanup_server.sh - shellcheck -s bash -x scripts/secure_server.sh + shellcheck -s bash -x scripts/utils.sh + shellcheck -s bash -x scripts/server_*.sh shellcheck -s bash -x scripts/install_*.sh shellcheck -s bash -x scripts/remove_*.sh # Simple Unit Tests @@ -72,6 +71,6 @@ jobs: TERM: xterm-256color run: | set -ex - sudo bash scripts/cleanup_server.sh + sudo bash scripts/server_cleanup.sh sudo bash scripts/install_dependencies.sh sudo bash shunit2/run_test.sh diff --git a/.gitignore b/.gitignore index c8900cc6..ee1dcaa7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ .env.bak .env.save .travis.yml +dev-notes.md install.log lemper.log lemper_install.log diff --git a/etc/nginx/fastcgi_cache b/etc/nginx/fastcgi_cache index cdf6b19f..d4ebdf46 100644 --- a/etc/nginx/fastcgi_cache +++ b/etc/nginx/fastcgi_cache @@ -18,8 +18,8 @@ log_format cache '$remote_addr - $upstream_cache_status [$time_local] ' # Purge cache for request method. map $request_method $purge_method { - PURGE 1; default 0; + PURGE 1; } # Skip caching for request method. diff --git a/etc/nginx/fastcgi_https_map b/etc/nginx/fastcgi_https_map index 5b21ef93..9075f03a 100644 --- a/etc/nginx/fastcgi_https_map +++ b/etc/nginx/fastcgi_https_map @@ -5,3 +5,8 @@ map $scheme $server_https { default off; https on; } + +map $http_x_forwarded_proto $proto_https { + default $scheme; + https https; +} diff --git a/etc/nginx/fastcgi_params b/etc/nginx/fastcgi_params index c1c5bb33..e78e2ad2 100644 --- a/etc/nginx/fastcgi_params +++ b/etc/nginx/fastcgi_params @@ -3,7 +3,8 @@ # Comment out HTTPS line for PHP behind SSL https. #fastcgi_param HTTPS on; # old pre .03 method -#fastcgi_param HTTPS $server_https; # new .04+ map method +fastcgi_param HTTPS $server_https; # new .04+ map method +fastcgi_param HTTP_X_FORWARDED_PROTO $proto_https; # Comment out PATH_TRANSLATED line if /etc/php5/fpm/php.ini sets following: # cgi.fix_pathinfo=0 diff --git a/etc/nginx/http_proxy_ips b/etc/nginx/http_proxy_ips index f2fe4970..0dced640 100644 --- a/etc/nginx/http_proxy_ips +++ b/etc/nginx/http_proxy_ips @@ -1,6 +1,6 @@ ## Designed to be included to /etc/nginx/nginx.conf http{} or server{} block -# Varnish HTTP Accelerator +# HTTP Accelerator or Load Balancer. set_real_ip_from 127.0.0.1/32; # Header diff --git a/etc/nginx/includes/compression_brotli.conf b/etc/nginx/includes/compression_brotli.conf index 92b0ee0f..8b4b8531 100644 --- a/etc/nginx/includes/compression_brotli.conf +++ b/etc/nginx/includes/compression_brotli.conf @@ -66,9 +66,9 @@ brotli_buffers 16 8k; brotli_window 512k; # Up the minimum length a little to account for gzip overhead -# this means anything smaller than 1024 bytes won't be compressed. +# this means anything smaller than 256 bytes won't be compressed. # The default is 20 bytes, which is sooo tiny it's a waste to compress. -brotli_min_length 1024; +brotli_min_length 256; # Custom header. add_header X-Powered-By "LEMPer/Brotli"; diff --git a/etc/nginx/includes/compression_gzip.conf b/etc/nginx/includes/compression_gzip.conf index f3086214..c58ca38d 100644 --- a/etc/nginx/includes/compression_gzip.conf +++ b/etc/nginx/includes/compression_gzip.conf @@ -79,9 +79,9 @@ gzip_vary on; gzip_buffers 16 8k; # Up the minimum length a little to account for gzip overhead -# this means anything smaller than 1024 bytes won't be compressed. +# this means anything smaller than 256 bytes won't be compressed. # The default is 20 bytes, which is sooo tiny it's a waste to compress. -gzip_min_length 1024; +gzip_min_length 256; # Custom header. add_header X-Powered-By "LEMPer/Gzip"; diff --git a/etc/nginx/includes/fastcgi_cache.conf b/etc/nginx/includes/fastcgi_cache.conf index 708ec4f2..f28004e3 100644 --- a/etc/nginx/includes/fastcgi_cache.conf +++ b/etc/nginx/includes/fastcgi_cache.conf @@ -16,8 +16,8 @@ fastcgi_no_cache $http_pragma $http_authorization; fastcgi_cache_purge $purge_method; -# Ignore header -fastcgi_ignore_headers Cache-Control Expires Set-Cookie; +# Ignore header (Added Pragma, crosscheck first) +fastcgi_ignore_headers Cache-Control Expires Pragma Set-Cookie; # Header status add_header X-FastCGI-Cache $upstream_cache_status; diff --git a/etc/nginx/includes/ssl.conf b/etc/nginx/includes/ssl.conf index a1f34285..ffefe3f8 100644 --- a/etc/nginx/includes/ssl.conf +++ b/etc/nginx/includes/ssl.conf @@ -1,8 +1,10 @@ # Enables SSL (deprecated on http2). #ssl on; +# --- Common definitions for HTTPS content --- # + # Optimize SSL by caching session parameters for 10 minutes. This cuts down on the number of expensive SSL handshakes. -ssl_session_cache shared:LEMPer_SSL:10m; # a 1mb cache can hold about 4000 sessions +ssl_session_cache shared:LEMPer_SSL:50m; # a 1mb cache can hold about 4000 sessions ssl_session_timeout 1d; # SSL buffer size was added in 1.5.9 @@ -14,25 +16,33 @@ ssl_session_tickets off; # Diffie-Hellman parameter for DHE ciphersuites, minimum recommendation 2048 bits. ssl_dhparam /etc/nginx/ssl/dhparam-2048.pem; -# If you need to support older browsers (IE6) you may need to add -# SSLv2 SSLv3 TLSv1 TLSv1.1 to the list of protocols below. -ssl_protocols TLSv1.2 TLSv1.3; +# --- Protocols & Ciphers [start] --- # -# Enables server-side protection from BEAST attacks. -# http://blog.ivanristic.com/2013/09/is-beast-still-a-threat.html +# Maximum client support [enabled by default] +# Supports Firefox 1, Android 2.3, Chrome 1, Edge 12, IE8 on Windows XP, Java 6, OpenSSL 0.9.8, Opera 5 & Safari 1 +ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; +ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA; ssl_prefer_server_ciphers on; -# Ciphers set to best allow protection from Beast, while providing forwarding secrecy, -# as defined by Mozilla (Intermediate Set) - https://wiki.mozilla.org/Security/Server_Side_TLS#Nginx -ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; +# Intermediate client support [disabled by default] +# Supports Firefox 27, Android 4.4.2, Chrome 31, Edge, IE 11 on Windows 7, Java 8u31, OpenSSL 1.0.1, Opera 20 & Safari 9 +#ssl_protocols TLSv1.2 TLSv1.3; +#ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; +#ssl_prefer_server_ciphers off; + +# Modern client support [disabled by default] +# Supports Firefox 63, Android 10.0, Chrome 70, Edge 75, Java 11, OpenSSL 1.1.1, Opera 57 & Safari 12.1 +#ssl_protocols TLSv1.3; +#ssl_ciphers TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 +#ssl_prefer_server_ciphers off; # Specifies a curve for ECDHE ciphers, default is auto. ssl_ecdh_curve prime256v1:secp384r1; # Enable OCSP stapling (mechanism by which a site can convey certificate revocation information to visitors in a privacy-preserving, scalable manner) # http://blog.mozilla.org/security/2013/07/29/ocsp-stapling-in-firefox/ -ssl_stapling on; -ssl_stapling_verify on; +#ssl_stapling on; +#ssl_stapling_verify on; # Reduce SSL buffer size. ssl_buffer_size 4k; # Default = 16k @@ -55,4 +65,4 @@ resolver_timeout 5s; # This header tells browsers to cache the certificate for a year and to connect exclusively via HTTPS. #add_header Strict-Transport-Security "max-age=31536000;" always; # This version tells browsers to treat all subdomains the same as this site and to load exclusively over HTTPS -add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload;"; \ No newline at end of file +add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload;"; diff --git a/etc/nginx/nginx.conf b/etc/nginx/nginx.conf index 879fbb24..3870d261 100644 --- a/etc/nginx/nginx.conf +++ b/etc/nginx/nginx.conf @@ -60,6 +60,8 @@ http { # Optimization settings. aio threads; sendfile on; + # Limit the amount of data transferred in a single sendfile() call to 1MB. + sendfile_max_chunk 1m; tcp_nopush on; tcp_nodelay on; client_body_buffer_size 128k; @@ -80,8 +82,8 @@ http { # Enable Compression. # gzip (default) or brotli (requires Nginx installed with brotli module). - # TODO: Move to per site config. - #include /etc/nginx/comp_gzip; + # Moved to per site config. + ##include /etc/nginx/compression_gzip; # Uncomment to enable FastCGI cache. If disabled, do not use the cached vhost setting. include /etc/nginx/fastcgi_cache; @@ -91,7 +93,7 @@ http { # Upstream, ex: for Node.JS application server. # TODO: Move to per site config. - #include /etc/nginx/upstream; + ##include /etc/nginx/upstream; # SSL map. include /etc/nginx/fastcgi_https_map; diff --git a/etc/nginx/sites-available/default b/etc/nginx/sites-available/default index 6dec3964..e48fdcbc 100644 --- a/etc/nginx/sites-available/default +++ b/etc/nginx/sites-available/default @@ -11,8 +11,8 @@ server { #ssl_certificate_key /etc/letsencrypt/live/localhost.localdomain/privkey.pem; #ssl_trusted_certificate /etc/letsencrypt/live/localhost.localdomain/fullchain.pem; - access_log /var/log/nginx/localhost.access.log; - error_log /var/log/nginx/localhost.error.log; + access_log /var/log/nginx/localhost.access.log combined buffer=32k; + error_log /var/log/nginx/localhost.error.log error; root /usr/share/nginx/html; index index.php index.html index.htm; @@ -24,15 +24,28 @@ server { include /etc/nginx/vhost/site_default.conf; - location ~ ^/(status|ping)$ { + # Nginx basic status monitoring. + location = /nginx_status { + stub_status; + allow all; + auth_basic "Denied"; + auth_basic_user_file /srv/.htpasswd; + access_log off; + log_not_found off; + } + + # PHP-FPM status monitoring. + location ~ ^/php-fpm_(status|ping)$ { include /etc/nginx/fastcgi_params; - fastcgi_pass unix:/run/php/php7.4-fpm.sock; + fastcgi_pass unix:/run/php/php8.0-fpm.sock; fastcgi_param SCRIPT_FILENAME $fastcgi_script_name; allow all; auth_basic "Denied"; auth_basic_user_file /srv/.htpasswd; + access_log off; + log_not_found off; } location ~ \.php81$ { @@ -46,7 +59,7 @@ server { fastcgi_pass unix:/run/php/php8.1-fpm.sock; } - location ~ \.php80$ { + location ~ \.(php|php80)$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_index index.php; @@ -56,7 +69,7 @@ server { fastcgi_pass unix:/run/php/php8.0-fpm.sock; } - location ~ \.(php|php74)$ { + location ~ \.php74$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_index index.php; @@ -132,8 +145,8 @@ server { index index.php index.html index.htm; # Log Settings. - access_log /var/log/nginx/localhost.access.log; - error_log /var/log/nginx/localhost.error.log; + access_log /var/log/nginx/localhost.access.log combined buffer=32k; + error_log /var/log/nginx/localhost.error.log error; location /lcp { try_files $uri $uri/ /index.php?$args; @@ -161,7 +174,7 @@ server { # Uncomment to Enable PHP FastCGI cache. #include /etc/nginx/includes/fastcgi_cache.conf; - fastcgi_pass unix:/run/php/php7.4-fpm.sock; + fastcgi_pass unix:/run/php/php8.0-fpm.sock; } } @@ -175,7 +188,7 @@ server { fastcgi_pass unix:/run/php/php8.1-fpm.sock; } - location ~ \.php80$ { + location ~ \.(php|php80)$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_index index.php; @@ -185,7 +198,7 @@ server { fastcgi_pass unix:/run/php/php8.0-fpm.sock; } - location ~ \.(php|php74)$ { + location ~ \.php74$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_index index.php; diff --git a/etc/openssl/ca.conf b/etc/openssl/ca.conf new file mode 100644 index 00000000..da3c2832 --- /dev/null +++ b/etc/openssl/ca.conf @@ -0,0 +1,20 @@ +[ca] +default_ca = CA_default # The default ca section + +[CA_default] +default_days = 36500 # How long to certify for + +[req] +default_bits = 2048 +default_md = sha256 +distinguished_name = ca_dn +prompt = no + +[ca_dn] +C = ID +ST = Jakarta +L = Jakarta +O = LEMPer +OU = LEMPer Stack +CN = demo.lemper.cloud +emailAddress = cert@lemper.cloud diff --git a/etc/openssl/cert.conf b/etc/openssl/cert.conf new file mode 100644 index 00000000..8fa9e596 --- /dev/null +++ b/etc/openssl/cert.conf @@ -0,0 +1,7 @@ +authorityKeyIdentifier=keyid,issuer +basicConstraints=CA:FALSE +keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment +subjectAltName = @alt_names + +[alt_names] +DNS.1 = demo.lemper.cloud diff --git a/etc/openssl/csr.conf b/etc/openssl/csr.conf new file mode 100644 index 00000000..6de7c714 --- /dev/null +++ b/etc/openssl/csr.conf @@ -0,0 +1,23 @@ +[req] +default_bits = 2048 +default_md = sha256 +distinguished_name = dn +prompt = no +req_extensions = req_ext + +[dn] +C = ID +ST = Jakarta +L = Jakarta +O = LEMPer +OU = LEMPer Stack +CN = demo.lemper.cloud + +[req_ext] +subjectAltName = @alt_names + +[alt_names] +DNS.1 = demo.lemper.cloud +DNS.2 = www.demo.lemper.cloud +IP.1 = 192.168.1.1 +IP.2 = 192.168.1.1 diff --git a/etc/php/5.6/fpm/pool.d/lemper.conf b/etc/php/5.6/fpm/pool.d/lemper.conf index c3ec932c..ccde45e0 100644 --- a/etc/php/5.6/fpm/pool.d/lemper.conf +++ b/etc/php/5.6/fpm/pool.d/lemper.conf @@ -18,8 +18,8 @@ pm.max_spare_servers = 20 pm.process_idle_timeout = 30s pm.max_requests = 500 -pm.status_path = /status -ping.path = /ping +pm.status_path = /php-fpm_status +ping.path = /php-fpm_ping slowlog = /home/lemper/logs/php/php5.6-fpm_slow.log request_slowlog_timeout = 10s diff --git a/etc/php/5.6/fpm/pool.d/www.conf b/etc/php/5.6/fpm/pool.d/www.conf index a89d675e..b59e3674 100644 --- a/etc/php/5.6/fpm/pool.d/www.conf +++ b/etc/php/5.6/fpm/pool.d/www.conf @@ -201,7 +201,7 @@ pm.max_requests = 500 ; may conflict with a real PHP file. ; Default Value: not set ;pm.status_path = /fpm_status -pm.status_path = /status +pm.status_path = /php-fpm_status ; The ping URI to call the monitoring page of FPM. If this value is not set, no ; URI will be recognized as a ping page. This could be used to test from outside @@ -214,7 +214,7 @@ pm.status_path = /status ; may conflict with a real PHP file. ; Default Value: not set ;ping.path = /ping -ping.path = /ping +ping.path = /php-fpm_ping ; This directive may be used to customize the response of a ping request. The ; response is formatted as text/plain with a 200 response code. diff --git a/etc/php/7.0/fpm/pool.d/lemper.conf b/etc/php/7.0/fpm/pool.d/lemper.conf index efc6e804..2bb33792 100644 --- a/etc/php/7.0/fpm/pool.d/lemper.conf +++ b/etc/php/7.0/fpm/pool.d/lemper.conf @@ -18,8 +18,8 @@ pm.max_spare_servers = 20 pm.process_idle_timeout = 30s pm.max_requests = 500 -pm.status_path = /status -ping.path = /ping +pm.status_path = /php-fpm_status +ping.path = /php-fpm_ping slowlog = /home/lemper/logs/php/php7.0-fpm_slow.log request_slowlog_timeout = 10s diff --git a/etc/php/7.0/fpm/pool.d/www.conf b/etc/php/7.0/fpm/pool.d/www.conf index 42026405..6264c25f 100644 --- a/etc/php/7.0/fpm/pool.d/www.conf +++ b/etc/php/7.0/fpm/pool.d/www.conf @@ -230,7 +230,7 @@ pm.max_spare_servers = 3 ; may conflict with a real PHP file. ; Default Value: not set ;pm.status_path = /status -pm.status_path = /status +pm.status_path = /php-fpm_status ; The ping URI to call the monitoring page of FPM. If this value is not set, no ; URI will be recognized as a ping page. This could be used to test from outside @@ -243,7 +243,7 @@ pm.status_path = /status ; may conflict with a real PHP file. ; Default Value: not set ;ping.path = /ping -ping.path = /ping +ping.path = /php-fpm_ping ; This directive may be used to customize the response of a ping request. The ; response is formatted as text/plain with a 200 response code. diff --git a/etc/php/7.1/fpm/pool.d/lemper.conf b/etc/php/7.1/fpm/pool.d/lemper.conf index 39f3ef05..aa9be1e4 100644 --- a/etc/php/7.1/fpm/pool.d/lemper.conf +++ b/etc/php/7.1/fpm/pool.d/lemper.conf @@ -18,8 +18,8 @@ pm.max_spare_servers = 20 pm.process_idle_timeout = 30s pm.max_requests = 500 -pm.status_path = /status -ping.path = /ping +pm.status_path = /php-fpm_status +ping.path = /php-fpm_ping slowlog = /home/lemper/logs/php/php7.1-fpm_slow.log request_slowlog_timeout = 10s diff --git a/etc/php/7.1/fpm/pool.d/www.conf b/etc/php/7.1/fpm/pool.d/www.conf index 604a35eb..2de7c27f 100644 --- a/etc/php/7.1/fpm/pool.d/www.conf +++ b/etc/php/7.1/fpm/pool.d/www.conf @@ -230,7 +230,7 @@ pm.max_spare_servers = 3 ; may conflict with a real PHP file. ; Default Value: not set ;pm.status_path = /status -pm.status_path = /status +pm.status_path = /php-fpm_status ; The ping URI to call the monitoring page of FPM. If this value is not set, no ; URI will be recognized as a ping page. This could be used to test from outside @@ -243,7 +243,7 @@ pm.status_path = /status ; may conflict with a real PHP file. ; Default Value: not set ;ping.path = /ping -ping.path = /ping +ping.path = /php-fpm_ping ; This directive may be used to customize the response of a ping request. The ; response is formatted as text/plain with a 200 response code. diff --git a/etc/php/7.2/fpm/pool.d/lemper.conf b/etc/php/7.2/fpm/pool.d/lemper.conf index 4bc564d2..d5be5108 100644 --- a/etc/php/7.2/fpm/pool.d/lemper.conf +++ b/etc/php/7.2/fpm/pool.d/lemper.conf @@ -18,8 +18,8 @@ pm.max_spare_servers = 20 pm.process_idle_timeout = 30s pm.max_requests = 500 -pm.status_path = /status -ping.path = /ping +pm.status_path = /php-fpm_status +ping.path = /php-fpm_ping slowlog = /home/lemper/logs/php/php7.2-fpm_slow.log request_slowlog_timeout = 10s diff --git a/etc/php/7.2/fpm/pool.d/www.conf b/etc/php/7.2/fpm/pool.d/www.conf index 956350f0..1bde0dbc 100644 --- a/etc/php/7.2/fpm/pool.d/www.conf +++ b/etc/php/7.2/fpm/pool.d/www.conf @@ -230,7 +230,7 @@ pm.max_spare_servers = 3 ; may conflict with a real PHP file. ; Default Value: not set ;pm.status_path = /status -pm.status_path = /status +pm.status_path = /php-fpm_status ; The ping URI to call the monitoring page of FPM. If this value is not set, no ; URI will be recognized as a ping page. This could be used to test from outside @@ -243,7 +243,7 @@ pm.status_path = /status ; may conflict with a real PHP file. ; Default Value: not set ;ping.path = /ping -ping.path = /ping +ping.path = /php-fpm_ping ; This directive may be used to customize the response of a ping request. The ; response is formatted as text/plain with a 200 response code. diff --git a/etc/php/7.3/fpm/pool.d/lemper.conf b/etc/php/7.3/fpm/pool.d/lemper.conf index 5064c21c..7d7dad0f 100644 --- a/etc/php/7.3/fpm/pool.d/lemper.conf +++ b/etc/php/7.3/fpm/pool.d/lemper.conf @@ -18,8 +18,8 @@ pm.max_spare_servers = 20 pm.process_idle_timeout = 30s pm.max_requests = 500 -pm.status_path = /status -ping.path = /ping +pm.status_path = /php-fpm_status +ping.path = /php-fpm_ping slowlog = /home/lemper/logs/php/php7.3-fpm_slow.log request_slowlog_timeout = 10s diff --git a/etc/php/7.3/fpm/pool.d/www.conf b/etc/php/7.3/fpm/pool.d/www.conf index c119cce7..800bedf2 100644 --- a/etc/php/7.3/fpm/pool.d/www.conf +++ b/etc/php/7.3/fpm/pool.d/www.conf @@ -236,7 +236,7 @@ pm.max_spare_servers = 3 ; may conflict with a real PHP file. ; Default Value: not set ;pm.status_path = /status -pm.status_path = /status +pm.status_path = /php-fpm_status ; The ping URI to call the monitoring page of FPM. If this value is not set, no ; URI will be recognized as a ping page. This could be used to test from outside @@ -249,7 +249,7 @@ pm.status_path = /status ; may conflict with a real PHP file. ; Default Value: not set ;ping.path = /ping -ping.path = /ping +ping.path = /php-fpm_ping ; This directive may be used to customize the response of a ping request. The ; response is formatted as text/plain with a 200 response code. diff --git a/etc/php/7.4/fpm/pool.d/lemper.conf b/etc/php/7.4/fpm/pool.d/lemper.conf index 2d490ffb..d69a2bdb 100644 --- a/etc/php/7.4/fpm/pool.d/lemper.conf +++ b/etc/php/7.4/fpm/pool.d/lemper.conf @@ -18,8 +18,8 @@ pm.max_spare_servers = 20 pm.process_idle_timeout = 30s pm.max_requests = 500 -pm.status_path = /status -ping.path = /ping +pm.status_path = /php-fpm_status +ping.path = /php-fpm_ping slowlog = /home/lemper/logs/php/php7.4-fpm_slow.log request_slowlog_timeout = 10s diff --git a/etc/php/7.4/fpm/pool.d/www.conf b/etc/php/7.4/fpm/pool.d/www.conf index 80a85d76..699f9ffe 100644 --- a/etc/php/7.4/fpm/pool.d/www.conf +++ b/etc/php/7.4/fpm/pool.d/www.conf @@ -236,7 +236,7 @@ pm.max_spare_servers = 3 ; may conflict with a real PHP file. ; Default Value: not set ;pm.status_path = /status -pm.status_path = /status +pm.status_path = /php-fpm_status ; The ping URI to call the monitoring page of FPM. If this value is not set, no ; URI will be recognized as a ping page. This could be used to test from outside @@ -249,7 +249,7 @@ pm.status_path = /status ; may conflict with a real PHP file. ; Default Value: not set ;ping.path = /ping -ping.path = /ping +ping.path = /php-fpm_ping ; This directive may be used to customize the response of a ping request. The ; response is formatted as text/plain with a 200 response code. diff --git a/etc/php/8.0/fpm/php-fpm.conf b/etc/php/8.0/fpm/php-fpm.conf index c501100b..18e81ee6 100644 --- a/etc/php/8.0/fpm/php-fpm.conf +++ b/etc/php/8.0/fpm/php-fpm.conf @@ -21,7 +21,7 @@ pid = /run/php/php8.0-fpm.pid ; into a local file. ; Note: the default prefix is /var ; Default Value: log/php-fpm.log -error_log = /var/log/php/php8.0-fpm.log +error_log = /var/log/php/php8.0-fpm_error.log ; syslog_facility is used to specify what type of program is logging the ; message. This lets syslogd specify that messages from different facilities diff --git a/etc/php/8.0/fpm/pool.d/lemper.conf b/etc/php/8.0/fpm/pool.d/lemper.conf index 181ffd45..032358ce 100644 --- a/etc/php/8.0/fpm/pool.d/lemper.conf +++ b/etc/php/8.0/fpm/pool.d/lemper.conf @@ -15,11 +15,12 @@ pm.max_children = 30 pm.start_servers = 5 pm.min_spare_servers = 5 pm.max_spare_servers = 20 -pm.process_idle_timeout = 30s +; Note: Used only when pm is set to 'ondemand' +;pm.process_idle_timeout = 30s pm.max_requests = 500 -pm.status_path = /status -ping.path = /ping +pm.status_path = /php-fpm_status +ping.path = /php-fpm_ping slowlog = /home/lemper/logs/php/php8.0-fpm_slow.log request_slowlog_timeout = 10s @@ -37,17 +38,16 @@ php_admin_value[open_basedir] = /home/lemper ;php_admin_value[disable_functions] = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,exec,passthru,popen,proc_open,shell_exec,system ;php_admin_value[disable_classes] = php_admin_flag[log_errors] = on -php_admin_value[error_log] = /home/lemper/logs/php/php8.0-fpm.log +php_admin_value[error_log] = /home/lemper/logs/php/php8.0-fpm_error.log php_admin_value[sys_temp_dir] = /home/lemper/.lemper/tmp php_admin_value[upload_tmp_dir] = /home/lemper/.lemper/tmp ;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com -php_admin_value[opcache.file_cache] = /home/lemper/.lemper/tmp/php_opcache ; Configuration below can be overwritten from PHP call 'ini_set'. php_flag[short_open_tag] = off php_value[max_execution_time] = 300 php_value[max_input_time] = 60 -php_value[memory_limit] = 128M +php_value[memory_limit] = 256M php_value[post_max_size] = 50M php_flag[file_uploads] = on php_value[upload_max_filesize] = 50M @@ -57,4 +57,8 @@ php_value[error_reporting] = E_ALL & ~E_DEPRECATED & ~E_STRICT php_flag[display_errors] = on php_flag[cgi.fix_pathinfo] = 1 php_value[date.timezone] = UTC -php_value[session.save_path] = /home/lemper/.lemper/tmp/php_sessions +php_value[session.save_handler] = files +php_value[session.save_path] = /home/lemper/.lemper/php/sessions +php_value[soap.wsdl_cache_dir] = /home/lemper/.lemper/php/wsdlcache +php_value[opcache.file_cache] = /home/lemper/.lemper/php/opcache +php_value[opcache.error_log] = /home/lemper/logs/php/php8.0-opcache_error.log diff --git a/etc/php/8.0/fpm/pool.d/www.conf b/etc/php/8.0/fpm/pool.d/www.conf index d25d3494..cdb2bb32 100644 --- a/etc/php/8.0/fpm/pool.d/www.conf +++ b/etc/php/8.0/fpm/pool.d/www.conf @@ -33,7 +33,7 @@ group = www-data ; (IPv6 and IPv4-mapped) on a specific port; ; '/path/to/unix/socket' - to listen on a unix socket. ; Note: This value is mandatory. -listen = /run/php/php8.0-fpm.sock +listen = /run/php/php8.0-fpm.$pool.sock ; Set listen(2) backlog. ; Default Value: 511 (-1 on FreeBSD and OpenBSD) @@ -47,6 +47,7 @@ listen = /run/php/php8.0-fpm.sock listen.owner = www-data listen.group = www-data ;listen.mode = 0660 + ; When POSIX Access Control Lists are supported you can set them using ; these options, value is a comma separated list of user/group names. ; When set, listen.owner and listen.group are ignored @@ -236,7 +237,7 @@ pm.max_spare_servers = 3 ; may conflict with a real PHP file. ; Default Value: not set ;pm.status_path = /status -pm.status_path = /status +pm.status_path = /php-fpm_status ; The ping URI to call the monitoring page of FPM. If this value is not set, no ; URI will be recognized as a ping page. This could be used to test from outside @@ -249,7 +250,7 @@ pm.status_path = /status ; may conflict with a real PHP file. ; Default Value: not set ;ping.path = /ping -ping.path = /ping +ping.path = /php-fpm_ping ; This directive may be used to customize the response of a ping request. The ; response is formatted as text/plain with a 200 response code. @@ -435,11 +436,10 @@ php_admin_value[open_basedir] = /usr/share/nginx/html ;php_admin_value[disable_functions] = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,exec,passthru,popen,proc_open,shell_exec,system ;php_admin_value[disable_classes] = php_admin_flag[log_errors] = on -php_admin_value[error_log] = /var/log/php/php8.0-fpm.$pool.log +php_admin_value[error_log] = /var/log/php/php8.0-fpm.$pool_error.log php_admin_value[sys_temp_dir] = /usr/share/nginx/html/.lemper/tmp php_admin_value[upload_tmp_dir] = /usr/share/nginx/html/.lemper/tmp ;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com -php_admin_value[opcache.file_cache] = /usr/share/nginx/html/.lemper/tmp/php_opcache ; Configuration below can be overwritten from PHP call 'ini_set'. php_flag[short_open_tag] = off @@ -455,4 +455,7 @@ php_value[error_reporting] = E_ALL & ~E_DEPRECATED & ~E_STRICT php_flag[display_errors] = on php_flag[cgi.fix_pathinfo] = 1 php_value[date.timezone] = UTC -php_value[session.save_path] = /usr/share/nginx/html/.lemper/tmp/php_sessions +php_value[session.save_handler] = files +php_value[session.save_path] = /usr/share/nginx/html/.lemper/php/sessions +php_value[soap.wsdl_cache_dir] = /usr/share/nginx/html/.lemper/php/wsdlcache +php_value[opcache.file_cache] = /usr/share/nginx/html/.lemper/php/opcache diff --git a/etc/php/8.1/fpm/pool.d/lemper.conf b/etc/php/8.1/fpm/pool.d/lemper.conf index f5bd373a..2f2bf762 100644 --- a/etc/php/8.1/fpm/pool.d/lemper.conf +++ b/etc/php/8.1/fpm/pool.d/lemper.conf @@ -18,8 +18,8 @@ pm.max_spare_servers = 20 pm.process_idle_timeout = 30s pm.max_requests = 500 -pm.status_path = /status -ping.path = /ping +pm.status_path = /php-fpm_status +ping.path = /php-fpm_ping slowlog = /home/lemper/logs/php/php8.1-fpm_slow.log request_slowlog_timeout = 10s diff --git a/etc/php/8.1/fpm/pool.d/www.conf b/etc/php/8.1/fpm/pool.d/www.conf index 8240fb83..d77e62fd 100644 --- a/etc/php/8.1/fpm/pool.d/www.conf +++ b/etc/php/8.1/fpm/pool.d/www.conf @@ -46,7 +46,8 @@ listen = /run/php/php8.1-fpm.sock ; mode is set to 0660 listen.owner = www-data listen.group = www-data -;listen.mode = 0660 +listen.mode = 0660 + ; When POSIX Access Control Lists are supported you can set them using ; these options, value is a comma separated list of user/group names. ; When set, listen.owner and listen.group are ignored @@ -236,7 +237,7 @@ pm.max_spare_servers = 3 ; may conflict with a real PHP file. ; Default Value: not set ;pm.status_path = /status -pm.status_path = /status +pm.status_path = /php-fpm_status ; The ping URI to call the monitoring page of FPM. If this value is not set, no ; URI will be recognized as a ping page. This could be used to test from outside @@ -249,7 +250,7 @@ pm.status_path = /status ; may conflict with a real PHP file. ; Default Value: not set ;ping.path = /ping -ping.path = /ping +ping.path = /php-fpm_ping ; This directive may be used to customize the response of a ping request. The ; response is formatted as text/plain with a 200 response code. @@ -435,11 +436,10 @@ php_admin_value[open_basedir] = /usr/share/nginx/html ;php_admin_value[disable_functions] = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,exec,passthru,popen,proc_open,shell_exec,system ;php_admin_value[disable_classes] = php_admin_flag[log_errors] = on -php_admin_value[error_log] = /var/log/php/php8.1-fpm.$pool.log +php_admin_value[error_log] = /var/log/php/php8.0-fpm.$pool_error.log php_admin_value[sys_temp_dir] = /usr/share/nginx/html/.lemper/tmp php_admin_value[upload_tmp_dir] = /usr/share/nginx/html/.lemper/tmp ;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com -php_admin_value[opcache.file_cache] = /usr/share/nginx/html/.lemper/tmp/php_opcache ; Configuration below can be overwritten from PHP call 'ini_set'. php_flag[short_open_tag] = off @@ -455,4 +455,7 @@ php_value[error_reporting] = E_ALL & ~E_DEPRECATED & ~E_STRICT php_flag[display_errors] = on php_flag[cgi.fix_pathinfo] = 1 php_value[date.timezone] = UTC -php_value[session.save_path] = /usr/share/nginx/html/.lemper/tmp/php_sessions +php_value[session.save_handler] = files +php_value[session.save_path] = /usr/share/nginx/html/.lemper/php/sessions +php_value[soap.wsdl_cache_dir] = /usr/share/nginx/html/.lemper/php/wsdlcache +php_value[opcache.file_cache] = /usr/share/nginx/html/.lemper/php/opcache diff --git a/etc/php/8.2/fpm/php-fpm.conf b/etc/php/8.2/fpm/php-fpm.conf new file mode 100644 index 00000000..e5cfcc5f --- /dev/null +++ b/etc/php/8.2/fpm/php-fpm.conf @@ -0,0 +1,146 @@ +;;;;;;;;;;;;;;;;;;;;; +; FPM Configuration ; +;;;;;;;;;;;;;;;;;;;;; + +; All relative paths in this configuration file are relative to PHP's install +; prefix (/usr). This prefix can be dynamically changed by using the +; '-p' argument from the command line. + +;;;;;;;;;;;;;;;;;; +; Global Options ; +;;;;;;;;;;;;;;;;;; + +[global] +; Pid file +; Note: the default prefix is /var +; Default Value: none +pid = /run/php/php8.2-fpm.pid + +; Error log file +; If it's set to "syslog", log is sent to syslogd instead of being written +; into a local file. +; Note: the default prefix is /var +; Default Value: log/php-fpm.log +error_log = /var/log/php/php8.2-fpm.log + +; syslog_facility is used to specify what type of program is logging the +; message. This lets syslogd specify that messages from different facilities +; will be handled differently. +; See syslog(3) for possible values (ex daemon equiv LOG_DAEMON) +; Default Value: daemon +;syslog.facility = daemon + +; syslog_ident is prepended to every message. If you have multiple FPM +; instances running on the same server, you can change the default value +; which must suit common needs. +; Default Value: php-fpm +;syslog.ident = php-fpm + +; Log level +; Possible Values: alert, error, warning, notice, debug +; Default Value: notice +;log_level = notice + +; Log limit on number of characters in the single line (log entry). If the +; line is over the limit, it is wrapped on multiple lines. The limit is for +; all logged characters including message prefix and suffix if present. However +; the new line character does not count into it as it is present only when +; logging to a file descriptor. It means the new line character is not present +; when logging to syslog. +; Default Value: 1024 +;log_limit = 4096 + +; Log buffering specifies if the log line is buffered which means that the +; line is written in a single write operation. If the value is false, then the +; data is written directly into the file descriptor. It is an experimental +; option that can potentionaly improve logging performance and memory usage +; for some heavy logging scenarios. This option is ignored if logging to syslog +; as it has to be always buffered. +; Default value: yes +;log_buffering = no + +; If this number of child processes exit with SIGSEGV or SIGBUS within the time +; interval set by emergency_restart_interval then FPM will restart. A value +; of '0' means 'Off'. +; Default Value: 0 +;emergency_restart_threshold = 0 +emergency_restart_threshold = 10 + +; Interval of time used by emergency_restart_interval to determine when +; a graceful restart will be initiated. This can be useful to work around +; accidental corruptions in an accelerator's shared memory. +; Available Units: s(econds), m(inutes), h(ours), or d(ays) +; Default Unit: seconds +; Default Value: 0 +;emergency_restart_interval = 0 +emergency_restart_interval = 60 + +; Time limit for child processes to wait for a reaction on signals from master. +; Available units: s(econds), m(inutes), h(ours), or d(ays) +; Default Unit: seconds +; Default Value: 0 +;process_control_timeout = 0 +process_control_timeout = 10 + +; The maximum number of processes FPM will fork. This has been designed to control +; the global number of processes when using dynamic PM within a lot of pools. +; Use it with caution. +; Note: A value of 0 indicates no limit +; Default Value: 0 +; process.max = 128 + +; Specify the nice(2) priority to apply to the master process (only if set) +; The value can vary from -19 (highest priority) to 20 (lowest priority) +; Note: - It will only work if the FPM master process is launched as root +; - The pool process will inherit the master process priority +; unless specified otherwise +; Default Value: no set +; process.priority = -19 + +; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging. +; Default Value: yes +;daemonize = yes + +; Set open file descriptor rlimit for the master process. +; Default Value: system defined value +;rlimit_files = 1024 + +; Set max core size rlimit for the master process. +; Possible Values: 'unlimited' or an integer greater or equal to 0 +; Default Value: system defined value +;rlimit_core = 0 + +; Specify the event mechanism FPM will use. The following is available: +; - select (any POSIX os) +; - poll (any POSIX os) +; - epoll (linux >= 2.5.44) +; - kqueue (FreeBSD >= 4.1, OpenBSD >= 2.9, NetBSD >= 2.0) +; - /dev/poll (Solaris >= 7) +; - port (Solaris >= 10) +; Default Value: not set (auto detection) +;events.mechanism = epoll + +; When FPM is built with systemd integration, specify the interval, +; in seconds, between health report notification to systemd. +; Set to 0 to disable. +; Available Units: s(econds), m(inutes), h(ours) +; Default Unit: seconds +; Default value: 10 +;systemd_interval = 10 + +;;;;;;;;;;;;;;;;;;;; +; Pool Definitions ; +;;;;;;;;;;;;;;;;;;;; + +; Multiple pools of child processes may be started with different listening +; ports and different management options. The name of the pool will be +; used in logs and stats. There is no limitation on the number of pools which +; FPM can handle. Your system will tell you anyway :) + +; Include one or more files. If glob(3) exists, it is used to include a bunch of +; files from a glob(3) pattern. This directive can be used everywhere in the +; file. +; Relative path can also be used. They will be prefixed by: +; - the global prefix if it's been set (-p argument) +; - /usr otherwise +include=/etc/php/8.2/fpm/pool.d/*.conf diff --git a/etc/php/8.2/fpm/php.ini b/etc/php/8.2/fpm/php.ini new file mode 100644 index 00000000..6420ae6e --- /dev/null +++ b/etc/php/8.2/fpm/php.ini @@ -0,0 +1,1936 @@ +[PHP] + +;;;;;;;;;;;;;;;;;;; +; About php.ini ; +;;;;;;;;;;;;;;;;;;; +; PHP's initialization file, generally called php.ini, is responsible for +; configuring many of the aspects of PHP's behavior. + +; PHP attempts to find and load this configuration from a number of locations. +; The following is a summary of its search order: +; 1. SAPI module specific location. +; 2. The PHPRC environment variable. (As of PHP 5.2.0) +; 3. A number of predefined registry keys on Windows (As of PHP 5.2.0) +; 4. Current working directory (except CLI) +; 5. The web server's directory (for SAPI modules), or directory of PHP +; (otherwise in Windows) +; 6. The directory from the --with-config-file-path compile time option, or the +; Windows directory (usually C:\windows) +; See the PHP docs for more specific information. +; http://php.net/configuration.file + +; The syntax of the file is extremely simple. Whitespace and lines +; beginning with a semicolon are silently ignored (as you probably guessed). +; Section headers (e.g. [Foo]) are also silently ignored, even though +; they might mean something in the future. + +; Directives following the section heading [PATH=/www/mysite] only +; apply to PHP files in the /www/mysite directory. Directives +; following the section heading [HOST=www.example.com] only apply to +; PHP files served from www.example.com. Directives set in these +; special sections cannot be overridden by user-defined INI files or +; at runtime. Currently, [PATH=] and [HOST=] sections only work under +; CGI/FastCGI. +; http://php.net/ini.sections + +; Directives are specified using the following syntax: +; directive = value +; Directive names are *case sensitive* - foo=bar is different from FOO=bar. +; Directives are variables used to configure PHP or PHP extensions. +; There is no name validation. If PHP can't find an expected +; directive because it is not set or is mistyped, a default value will be used. + +; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one +; of the INI constants (On, Off, True, False, Yes, No and None) or an expression +; (e.g. E_ALL & ~E_NOTICE), a quoted string ("bar"), or a reference to a +; previously set variable or directive (e.g. ${foo}) + +; Expressions in the INI file are limited to bitwise operators and parentheses: +; | bitwise OR +; ^ bitwise XOR +; & bitwise AND +; ~ bitwise NOT +; ! boolean NOT + +; Boolean flags can be turned on using the values 1, On, True or Yes. +; They can be turned off using the values 0, Off, False or No. + +; An empty string can be denoted by simply not writing anything after the equal +; sign, or by using the None keyword: + +; foo = ; sets foo to an empty string +; foo = None ; sets foo to an empty string +; foo = "None" ; sets foo to the string 'None' + +; If you use constants in your value, and these constants belong to a +; dynamically loaded extension (either a PHP extension or a Zend extension), +; you may only use these constants *after* the line that loads the extension. + +;;;;;;;;;;;;;;;;;;; +; About this file ; +;;;;;;;;;;;;;;;;;;; +; PHP comes packaged with two INI files. One that is recommended to be used +; in production environments and one that is recommended to be used in +; development environments. + +; php.ini-production contains settings which hold security, performance and +; best practices at its core. But please be aware, these settings may break +; compatibility with older or less security conscience applications. We +; recommending using the production ini in production and testing environments. + +; php.ini-development is very similar to its production variant, except it is +; much more verbose when it comes to errors. We recommend using the +; development version only in development environments, as errors shown to +; application users can inadvertently leak otherwise secure information. + +; This is the php.ini-production INI file. + +;;;;;;;;;;;;;;;;;;; +; Quick Reference ; +;;;;;;;;;;;;;;;;;;; +; The following are all the settings which are different in either the production +; or development versions of the INIs with respect to PHP's default behavior. +; Please see the actual settings later in the document for more details as to why +; we recommend these changes in PHP's behavior. + +; display_errors +; Default Value: On +; Development Value: On +; Production Value: Off + +; display_startup_errors +; Default Value: Off +; Development Value: On +; Production Value: Off + +; error_reporting +; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED +; Development Value: E_ALL +; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT + +; log_errors +; Default Value: Off +; Development Value: On +; Production Value: On + +; max_input_time +; Default Value: -1 (Unlimited) +; Development Value: 60 (60 seconds) +; Production Value: 60 (60 seconds) + +; output_buffering +; Default Value: Off +; Development Value: 4096 +; Production Value: 4096 + +; register_argc_argv +; Default Value: On +; Development Value: Off +; Production Value: Off + +; request_order +; Default Value: None +; Development Value: "GP" +; Production Value: "GP" + +; session.gc_divisor +; Default Value: 100 +; Development Value: 1000 +; Production Value: 1000 + +; session.sid_bits_per_character +; Default Value: 4 +; Development Value: 5 +; Production Value: 5 + +; short_open_tag +; Default Value: On +; Development Value: Off +; Production Value: Off + +; track_errors +; Default Value: Off +; Development Value: On +; Production Value: Off + +; variables_order +; Default Value: "EGPCS" +; Development Value: "GPCS" +; Production Value: "GPCS" + +;;;;;;;;;;;;;;;;;;;; +; php.ini Options ; +;;;;;;;;;;;;;;;;;;;; +; Name for user-defined php.ini (.htaccess) files. Default is ".user.ini" +;user_ini.filename = ".user.ini" + +; To disable this feature set this option to an empty value +;user_ini.filename = + +; TTL for user-defined php.ini files (time-to-live) in seconds. Default is 300 seconds (5 minutes) +;user_ini.cache_ttl = 300 + +;;;;;;;;;;;;;;;;;;;; +; Language Options ; +;;;;;;;;;;;;;;;;;;;; + +; Enable the PHP scripting language engine under Apache. +; http://php.net/engine +engine = On + +; This directive determines whether or not PHP will recognize code between +; tags as PHP source which should be processed as such. It is +; generally recommended that should be used and that this feature +; should be disabled, as enabling it may result in issues when generating XML +; documents, however this remains supported for backward compatibility reasons. +; Note that this directive does not control the would work. +; http://php.net/syntax-highlighting +;highlight.string = #DD0000 +;highlight.comment = #FF9900 +;highlight.keyword = #007700 +;highlight.default = #0000BB +;highlight.html = #000000 + +; If enabled, the request will be allowed to complete even if the user aborts +; the request. Consider enabling it if executing long requests, which may end up +; being interrupted by the user or a browser timing out. PHP's default behavior +; is to disable this feature. +; http://php.net/ignore-user-abort +;ignore_user_abort = On + +; Determines the size of the realpath cache to be used by PHP. This value should +; be increased on systems where PHP opens many files to reflect the quantity of +; the file operations performed. +; Note: if open_basedir is set, the cache is disabled +; http://php.net/realpath-cache-size +;realpath_cache_size = 4096k + +; Duration of time, in seconds for which to cache realpath information for a given +; file or directory. For systems with rarely changing files, consider increasing this +; value. +; http://php.net/realpath-cache-ttl +;realpath_cache_ttl = 120 + +; Enables or disables the circular reference collector. +; http://php.net/zend.enable-gc +zend.enable_gc = On + +; If enabled, scripts may be written in encodings that are incompatible with +; the scanner. CP936, Big5, CP949 and Shift_JIS are the examples of such +; encodings. To use this feature, mbstring extension must be enabled. +; Default: Off +;zend.multibyte = Off + +; Allows to set the default encoding for the scripts. This value will be used +; unless "declare(encoding=...)" directive appears at the top of the script. +; Only affects if zend.multibyte is set. +; Default: "" +;zend.script_encoding = + +; Allows to include or exclude arguments from stack traces generated for exceptions +; Default: Off +; In production, it is recommended to turn this setting on to prohibit the output +; of sensitive information in stack traces +zend.exception_ignore_args = On + +;;;;;;;;;;;;;;;;; +; Miscellaneous ; +;;;;;;;;;;;;;;;;; + +; Decides whether PHP may expose the fact that it is installed on the server +; (e.g. by adding its signature to the Web server header). It is no security +; threat in any way, but it makes it possible to determine whether you use PHP +; on your server or not. +; http://php.net/expose-php +expose_php = Off + +;;;;;;;;;;;;;;;;;;; +; Resource Limits ; +;;;;;;;;;;;;;;;;;;; + +; Maximum execution time of each script, in seconds +; http://php.net/max-execution-time +; Note: This directive is hardcoded to 0 for the CLI SAPI +max_execution_time = 30 + +; Maximum amount of time each script may spend parsing request data. It's a good +; idea to limit this time on productions servers in order to eliminate unexpectedly +; long running scripts. +; Note: This directive is hardcoded to -1 for the CLI SAPI +; Default Value: -1 (Unlimited) +; Development Value: 60 (60 seconds) +; Production Value: 60 (60 seconds) +; http://php.net/max-input-time +max_input_time = 60 + +; Maximum input variable nesting level +; http://php.net/max-input-nesting-level +;max_input_nesting_level = 64 + +; How many GET/POST/COOKIE input variables may be accepted +;max_input_vars = 1000 + +; Maximum amount of memory a script may consume (128MB) +; http://php.net/memory-limit +memory_limit = 128M + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Error handling and logging ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; This directive informs PHP of which errors, warnings and notices you would like +; it to take action for. The recommended way of setting values for this +; directive is through the use of the error level constants and bitwise +; operators. The error level constants are below here for convenience as well as +; some common settings and their meanings. +; By default, PHP is set to take action on all errors, notices and warnings EXCEPT +; those related to E_NOTICE and E_STRICT, which together cover best practices and +; recommended coding standards in PHP. For performance reasons, this is the +; recommend error reporting setting. Your production server shouldn't be wasting +; resources complaining about best practices and coding standards. That's what +; development servers and development settings are for. +; Note: The php.ini-development file has this setting as E_ALL. This +; means it pretty much reports everything which is exactly what you want during +; development and early testing. +; +; Error Level Constants: +; E_ALL - All errors and warnings (includes E_STRICT as of PHP 5.4.0) +; E_ERROR - fatal run-time errors +; E_RECOVERABLE_ERROR - almost fatal run-time errors +; E_WARNING - run-time warnings (non-fatal errors) +; E_PARSE - compile-time parse errors +; E_NOTICE - run-time notices (these are warnings which often result +; from a bug in your code, but it's possible that it was +; intentional (e.g., using an uninitialized variable and +; relying on the fact it is automatically initialized to an +; empty string) +; E_STRICT - run-time notices, enable to have PHP suggest changes +; to your code which will ensure the best interoperability +; and forward compatibility of your code +; E_CORE_ERROR - fatal errors that occur during PHP's initial startup +; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's +; initial startup +; E_COMPILE_ERROR - fatal compile-time errors +; E_COMPILE_WARNING - compile-time warnings (non-fatal errors) +; E_USER_ERROR - user-generated error message +; E_USER_WARNING - user-generated warning message +; E_USER_NOTICE - user-generated notice message +; E_DEPRECATED - warn about code that will not work in future versions +; of PHP +; E_USER_DEPRECATED - user-generated deprecation warnings +; +; Common Values: +; E_ALL (Show all errors, warnings and notices including coding standards.) +; E_ALL & ~E_NOTICE (Show all errors, except for notices) +; E_ALL & ~E_NOTICE & ~E_STRICT (Show all errors, except for notices and coding standards warnings.) +; E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR (Show only errors) +; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED +; Development Value: E_ALL +; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT +; http://php.net/error-reporting +error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT + +; This directive controls whether or not and where PHP will output errors, +; notices and warnings too. Error output is very useful during development, but +; it could be very dangerous in production environments. Depending on the code +; which is triggering the error, sensitive information could potentially leak +; out of your application such as database usernames and passwords or worse. +; For production environments, we recommend logging errors rather than +; sending them to STDOUT. +; Possible Values: +; Off = Do not display any errors +; stderr = Display errors to STDERR (affects only CGI/CLI binaries!) +; On or stdout = Display errors to STDOUT +; Default Value: On +; Development Value: On +; Production Value: Off +; http://php.net/display-errors +display_errors = Off + +; The display of errors which occur during PHP's startup sequence are handled +; separately from display_errors. PHP's default behavior is to suppress those +; errors from clients. Turning the display of startup errors on can be useful in +; debugging configuration problems. We strongly recommend you +; set this to 'off' for production servers. +; Default Value: Off +; Development Value: On +; Production Value: Off +; http://php.net/display-startup-errors +display_startup_errors = Off + +; Besides displaying errors, PHP can also log errors to locations such as a +; server-specific log, STDERR, or a location specified by the error_log +; directive found below. While errors should not be displayed on productions +; servers they should still be monitored and logging is a great way to do that. +; Default Value: Off +; Development Value: On +; Production Value: On +; http://php.net/log-errors +log_errors = On + +; Set maximum length of log_errors. In error_log information about the source is +; added. The default is 1024 and 0 allows to not apply any maximum length at all. +; http://php.net/log-errors-max-len +log_errors_max_len = 1024 + +; Do not log repeated messages. Repeated errors must occur in same file on same +; line unless ignore_repeated_source is set true. +; http://php.net/ignore-repeated-errors +ignore_repeated_errors = Off + +; Ignore source of message when ignoring repeated messages. When this setting +; is On you will not log errors with repeated messages from different files or +; source lines. +; http://php.net/ignore-repeated-source +ignore_repeated_source = Off + +; If this parameter is set to Off, then memory leaks will not be shown (on +; stdout or in the log). This is only effective in a debug compile, and if +; error reporting includes E_WARNING in the allowed list +; http://php.net/report-memleaks +report_memleaks = On + +; This setting is on by default. +;report_zend_debug = 0 + +; Store the last error/warning message in $php_errormsg (boolean). Setting this value +; to On can assist in debugging and is appropriate for development servers. It should +; however be disabled on production servers. +; This directive is DEPRECATED. +; Default Value: Off +; Development Value: Off +; Production Value: Off +; http://php.net/track-errors +;track_errors = Off + +; Turn off normal error reporting and emit XML-RPC error XML +; http://php.net/xmlrpc-errors +;xmlrpc_errors = 0 + +; An XML-RPC faultCode +;xmlrpc_error_number = 0 + +; When PHP displays or logs an error, it has the capability of formatting the +; error message as HTML for easier reading. This directive controls whether +; the error message is formatted as HTML or not. +; Note: This directive is hardcoded to Off for the CLI SAPI +; http://php.net/html-errors +;html_errors = On + +; If html_errors is set to On *and* docref_root is not empty, then PHP +; produces clickable error messages that direct to a page describing the error +; or function causing the error in detail. +; You can download a copy of the PHP manual from http://php.net/docs +; and change docref_root to the base URL of your local copy including the +; leading '/'. You must also specify the file extension being used including +; the dot. PHP's default behavior is to leave these settings empty, in which +; case no links to documentation are generated. +; Note: Never use this feature for production boxes. +; http://php.net/docref-root +; Examples +;docref_root = "/phpmanual/" + +; http://php.net/docref-ext +;docref_ext = .html + +; String to output before an error message. PHP's default behavior is to leave +; this setting blank. +; http://php.net/error-prepend-string +; Example: +;error_prepend_string = "" + +; String to output after an error message. PHP's default behavior is to leave +; this setting blank. +; http://php.net/error-append-string +; Example: +;error_append_string = "" + +; Log errors to specified file. PHP's default behavior is to leave this value +; empty. +; http://php.net/error-log +; Example: +;error_log = php_errors.log +; Log errors to syslog (Event Log on Windows). +;error_log = syslog + +; The syslog ident is a string which is prepended to every message logged +; to syslog. Only used when error_log is set to syslog. +;syslog.ident = php + +; The syslog facility is used to specify what type of program is logging +; the message. Only used when error_log is set to syslog. +;syslog.facility = user + +; Set this to disable filtering control characters (the default). +; Some loggers only accept NVT-ASCII, others accept anything that's not +; control characters. If your logger accepts everything, then no filtering +; is needed at all. +; Allowed values are: +; ascii (all printable ASCII characters and NL) +; no-ctrl (all characters except control characters) +; all (all characters) +; raw (like "all", but messages are not split at newlines) +; http://php.net/syslog.filter +;syslog.filter = ascii + +;windows.show_crt_warning +; Default value: 0 +; Development value: 0 +; Production value: 0 + +;;;;;;;;;;;;;;;;; +; Data Handling ; +;;;;;;;;;;;;;;;;; + +; The separator used in PHP generated URLs to separate arguments. +; PHP's default setting is "&". +; http://php.net/arg-separator.output +; Example: +;arg_separator.output = "&" + +; List of separator(s) used by PHP to parse input URLs into variables. +; PHP's default setting is "&". +; NOTE: Every character in this directive is considered as separator! +; http://php.net/arg-separator.input +; Example: +;arg_separator.input = ";&" + +; This directive determines which super global arrays are registered when PHP +; starts up. G,P,C,E & S are abbreviations for the following respective super +; globals: GET, POST, COOKIE, ENV and SERVER. There is a performance penalty +; paid for the registration of these arrays and because ENV is not as commonly +; used as the others, ENV is not recommended on productions servers. You +; can still get access to the environment variables through getenv() should you +; need to. +; Default Value: "EGPCS" +; Development Value: "GPCS" +; Production Value: "GPCS"; +; http://php.net/variables-order +variables_order = "GPCS" + +; This directive determines which super global data (G,P & C) should be +; registered into the super global array REQUEST. If so, it also determines +; the order in which that data is registered. The values for this directive +; are specified in the same manner as the variables_order directive, +; EXCEPT one. Leaving this value empty will cause PHP to use the value set +; in the variables_order directive. It does not mean it will leave the super +; globals array REQUEST empty. +; Default Value: None +; Development Value: "GP" +; Production Value: "GP" +; http://php.net/request-order +request_order = "GP" + +; This directive determines whether PHP registers $argv & $argc each time it +; runs. $argv contains an array of all the arguments passed to PHP when a script +; is invoked. $argc contains an integer representing the number of arguments +; that were passed when the script was invoked. These arrays are extremely +; useful when running scripts from the command line. When this directive is +; enabled, registering these variables consumes CPU cycles and memory each time +; a script is executed. For performance reasons, this feature should be disabled +; on production servers. +; Note: This directive is hardcoded to On for the CLI SAPI +; Default Value: On +; Development Value: Off +; Production Value: Off +; http://php.net/register-argc-argv +register_argc_argv = Off + +; When enabled, the ENV, REQUEST and SERVER variables are created when they're +; first used (Just In Time) instead of when the script starts. If these +; variables are not used within a script, having this directive on will result +; in a performance gain. The PHP directive register_argc_argv must be disabled +; for this directive to have any effect. +; http://php.net/auto-globals-jit +auto_globals_jit = On + +; Whether PHP will read the POST data. +; This option is enabled by default. +; Most likely, you won't want to disable this option globally. It causes $_POST +; and $_FILES to always be empty; the only way you will be able to read the +; POST data will be through the php://input stream wrapper. This can be useful +; to proxy requests or to process the POST data in a memory efficient fashion. +; http://php.net/enable-post-data-reading +;enable_post_data_reading = Off + +; Maximum size of POST data that PHP will accept. +; Its value may be 0 to disable the limit. It is ignored if POST data reading +; is disabled through enable_post_data_reading. +; http://php.net/post-max-size +post_max_size = 10M + +; Automatically add files before PHP document. +; http://php.net/auto-prepend-file +auto_prepend_file = + +; Automatically add files after PHP document. +; http://php.net/auto-append-file +auto_append_file = + +; By default, PHP will output a media type using the Content-Type header. To +; disable this, simply set it to be empty. +; +; PHP's built-in default media type is set to text/html. +; http://php.net/default-mimetype +default_mimetype = "text/html" + +; PHP's default character set is set to UTF-8. +; http://php.net/default-charset +default_charset = "UTF-8" + +; PHP internal character encoding is set to empty. +; If empty, default_charset is used. +; http://php.net/internal-encoding +;internal_encoding = + +; PHP input character encoding is set to empty. +; If empty, default_charset is used. +; http://php.net/input-encoding +;input_encoding = + +; PHP output character encoding is set to empty. +; If empty, default_charset is used. +; See also output_buffer. +; http://php.net/output-encoding +;output_encoding = + +;;;;;;;;;;;;;;;;;;;;;;;;; +; Paths and Directories ; +;;;;;;;;;;;;;;;;;;;;;;;;; + +; UNIX: "/path1:/path2" +;include_path = ".:/usr/share/php" +; +; Windows: "\path1;\path2" +;include_path = ".;c:\php\includes" +; +; PHP's default setting for include_path is ".;/path/to/php/pear" +; http://php.net/include-path + +; The root of the PHP pages, used only if nonempty. +; if PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root +; if you are running php as a CGI under any web server (other than IIS) +; see documentation for security issues. The alternate is to use the +; cgi.force_redirect configuration below +; http://php.net/doc-root +doc_root = + +; The directory under which PHP opens the script using /~username used only +; if nonempty. +; http://php.net/user-dir +user_dir = + +; Directory in which the loadable extensions (modules) reside. +; http://php.net/extension-dir +;extension_dir = "./" +; On windows: +;extension_dir = "ext" + +; Directory where the temporary files should be placed. +; Defaults to the system default (see sys_get_temp_dir) +;sys_temp_dir = "/tmp" + +; Whether or not to enable the dl() function. The dl() function does NOT work +; properly in multithreaded servers, such as IIS or Zeus, and is automatically +; disabled on them. +; http://php.net/enable-dl +enable_dl = Off + +; cgi.force_redirect is necessary to provide security running PHP as a CGI under +; most web servers. Left undefined, PHP turns this on by default. You can +; turn it off here AT YOUR OWN RISK +; **You CAN safely turn this off for IIS, in fact, you MUST.** +; http://php.net/cgi.force-redirect +;cgi.force_redirect = 1 + +; if cgi.nph is enabled it will force cgi to always sent Status: 200 with +; every request. PHP's default behavior is to disable this feature. +;cgi.nph = 1 + +; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape +; (iPlanet) web servers, you MAY need to set an environment variable name that PHP +; will look for to know it is OK to continue execution. Setting this variable MAY +; cause security issues, KNOW WHAT YOU ARE DOING FIRST. +; http://php.net/cgi.redirect-status-env +;cgi.redirect_status_env = + +; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's +; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok +; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting +; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting +; of zero causes PHP to behave as before. Default is 1. You should fix your scripts +; to use SCRIPT_FILENAME rather than PATH_TRANSLATED. +; http://php.net/cgi.fix-pathinfo +;cgi.fix_pathinfo=1 + +; if cgi.discard_path is enabled, the PHP CGI binary can safely be placed outside +; of the web tree and people will not be able to circumvent .htaccess security. +;cgi.discard_path=1 + +; FastCGI under IIS supports the ability to impersonate +; security tokens of the calling client. This allows IIS to define the +; security context that the request runs under. mod_fastcgi under Apache +; does not currently support this feature (03/17/2002) +; Set to 1 if running under IIS. Default is zero. +; http://php.net/fastcgi.impersonate +;fastcgi.impersonate = 1 + +; Disable logging through FastCGI connection. PHP's default behavior is to enable +; this feature. +;fastcgi.logging = 0 + +; cgi.rfc2616_headers configuration option tells PHP what type of headers to +; use when sending HTTP response code. If set to 0, PHP sends Status: header that +; is supported by Apache. When this option is set to 1, PHP will send +; RFC2616 compliant header. +; Default is zero. +; http://php.net/cgi.rfc2616-headers +;cgi.rfc2616_headers = 0 + +; cgi.check_shebang_line controls whether CGI PHP checks for line starting with #! +; (shebang) at the top of the running script. This line might be needed if the +; script support running both as stand-alone script and via PHP CGI<. PHP in CGI +; mode skips this line and ignores its content if this directive is turned on. +; http://php.net/cgi.check-shebang-line +;cgi.check_shebang_line=1 + +;;;;;;;;;;;;;;;; +; File Uploads ; +;;;;;;;;;;;;;;;; + +; Whether to allow HTTP file uploads. +; http://php.net/file-uploads +file_uploads = On + +; Temporary directory for HTTP uploaded files (will use system default if not +; specified). +; http://php.net/upload-tmp-dir +;upload_tmp_dir = + +; Maximum allowed size for uploaded files. +; http://php.net/upload-max-filesize +upload_max_filesize = 10M + +; Maximum number of files that can be uploaded via a single request +max_file_uploads = 20 + +;;;;;;;;;;;;;;;;;; +; Fopen wrappers ; +;;;;;;;;;;;;;;;;;; + +; Whether to allow the treatment of URLs (like http:// or ftp://) as files. +; http://php.net/allow-url-fopen +allow_url_fopen = On + +; Whether to allow include/require to open URLs (like http:// or ftp://) as files. +; http://php.net/allow-url-include +allow_url_include = Off + +; Define the anonymous ftp password (your email address). PHP's default setting +; for this is empty. +; http://php.net/from +;from="john@doe.com" + +; Define the User-Agent string. PHP's default setting for this is empty. +; http://php.net/user-agent +;user_agent="PHP" + +; Default timeout for socket based streams (seconds) +; http://php.net/default-socket-timeout +default_socket_timeout = 60 + +; If your scripts have to deal with files from Macintosh systems, +; or you are running on a Mac and need to deal with files from +; unix or win32 systems, setting this flag will cause PHP to +; automatically detect the EOL character in those files so that +; fgets() and file() will work regardless of the source of the file. +; http://php.net/auto-detect-line-endings +;auto_detect_line_endings = Off + +;;;;;;;;;;;;;;;;;;;;;; +; Dynamic Extensions ; +;;;;;;;;;;;;;;;;;;;;;; + +; If you wish to have an extension loaded automatically, use the following +; syntax: +; +; extension=modulename +; +; For example: +; +; extension=mysqli +; +; When the extension library to load is not located in the default extension +; directory, You may specify an absolute path to the library file: +; +; extension=/path/to/extension/mysqli.so +; +; Note : The syntax used in previous PHP versions ('extension=.so' and +; 'extension='php_.dll') is supported for legacy reasons and may be +; deprecated in a future PHP major version. So, when it is possible, please +; move to the new ('extension=) syntax. +; +; Notes for Windows environments : +; +; - Many DLL files are located in the extensions/ (PHP 4) or ext/ (PHP 5+) +; extension folders as well as the separate PECL DLL download (PHP 5+). +; Be sure to appropriately set the extension_dir directive. +; +;extension=bz2 +;extension=curl +;extension=fileinfo +;extension=gd2 +;extension=gettext +;extension=gmp +;extension=intl +;extension=imap +;extension=ldap +;extension=mbstring +;extension=exif ; Must be after mbstring as it depends on it +;extension=mysqli +;extension=oci8_12c ; Use with Oracle Database 12c Instant Client +;extension=odbc +;extension=openssl +;extension=pdo_firebird +;extension=pdo_mysql +;extension=pdo_oci +;extension=pdo_odbc +;extension=pdo_pgsql +;extension=pdo_sqlite +;extension=pgsql +;extension=shmop + +; The MIBS data available in the PHP distribution must be installed. +; See http://www.php.net/manual/en/snmp.installation.php +;extension=snmp + +;extension=soap +;extension=sockets +;extension=sodium +;extension=sqlite3 +;extension=tidy +;extension=xmlrpc +;extension=xsl + +;;;;;;;;;;;;;;;;;;; +; Module Settings ; +;;;;;;;;;;;;;;;;;;; + +[CLI Server] +; Whether the CLI web server uses ANSI color coding in its terminal output. +cli_server.color = On + +[Date] +; Defines the default timezone used by the date functions +; http://php.net/date.timezone +;date.timezone = + +; http://php.net/date.default-latitude +;date.default_latitude = 31.7667 + +; http://php.net/date.default-longitude +;date.default_longitude = 35.2333 + +; http://php.net/date.sunrise-zenith +;date.sunrise_zenith = 90.583333 + +; http://php.net/date.sunset-zenith +;date.sunset_zenith = 90.583333 + +[filter] +; http://php.net/filter.default +;filter.default = unsafe_raw + +; http://php.net/filter.default-flags +;filter.default_flags = + +[iconv] +; Use of this INI entry is deprecated, use global input_encoding instead. +; If empty, default_charset or input_encoding or iconv.input_encoding is used. +; The precedence is: default_charset < input_encoding < iconv.input_encoding +;iconv.input_encoding = + +; Use of this INI entry is deprecated, use global internal_encoding instead. +; If empty, default_charset or internal_encoding or iconv.internal_encoding is used. +; The precedence is: default_charset < internal_encoding < iconv.internal_encoding +;iconv.internal_encoding = + +; Use of this INI entry is deprecated, use global output_encoding instead. +; If empty, default_charset or output_encoding or iconv.output_encoding is used. +; The precedence is: default_charset < output_encoding < iconv.output_encoding +; To use an output encoding conversion, iconv's output handler must be set +; otherwise output encoding conversion cannot be performed. +;iconv.output_encoding = + +[imap] +; rsh/ssh logins are disabled by default. Use this INI entry if you want to +; enable them. Note that the IMAP library does not filter mailbox names before +; passing them to rsh/ssh command, thus passing untrusted data to this function +; with rsh/ssh enabled is insecure. +;imap.enable_insecure_rsh=0 + +[intl] +;intl.default_locale = +; This directive allows you to produce PHP errors when some error +; happens within intl functions. The value is the level of the error produced. +; Default is 0, which does not produce any errors. +;intl.error_level = E_WARNING +;intl.use_exceptions = 0 + +[sqlite3] +; Directory pointing to SQLite3 extensions +; http://php.net/sqlite3.extension-dir +;sqlite3.extension_dir = + +; SQLite defensive mode flag (only available from SQLite 3.26+) +; When the defensive flag is enabled, language features that allow ordinary +; SQL to deliberately corrupt the database file are disabled. This forbids +; writing directly to the schema, shadow tables (eg. FTS data tables), or +; the sqlite_dbpage virtual table. +; https://www.sqlite.org/c3ref/c_dbconfig_defensive.html +; (for older SQLite versions, this flag has no use) +;sqlite3.defensive = 1 + +[Pcre] +; PCRE library backtracking limit. +; http://php.net/pcre.backtrack-limit +;pcre.backtrack_limit=100000 + +; PCRE library recursion limit. +; Please note that if you set this value to a high number you may consume all +; the available process stack and eventually crash PHP (due to reaching the +; stack size limit imposed by the Operating System). +; http://php.net/pcre.recursion-limit +;pcre.recursion_limit=100000 + +; Enables or disables JIT compilation of patterns. This requires the PCRE +; library to be compiled with JIT support. +;pcre.jit=1 + +[Pdo] +; Whether to pool ODBC connections. Can be one of "strict", "relaxed" or "off" +; http://php.net/pdo-odbc.connection-pooling +;pdo_odbc.connection_pooling=strict + +;pdo_odbc.db2_instance_name + +[Pdo_mysql] +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +pdo_mysql.default_socket= + +[Phar] +; http://php.net/phar.readonly +;phar.readonly = On + +; http://php.net/phar.require-hash +;phar.require_hash = On + +;phar.cache_list = + +[mail function] +; For Win32 only. +; http://php.net/smtp +SMTP = localhost +; http://php.net/smtp-port +smtp_port = 25 + +; For Win32 only. +; http://php.net/sendmail-from +;sendmail_from = me@example.com + +; For Unix only. You may supply arguments as well (default: "sendmail -t -i"). +; http://php.net/sendmail-path +;sendmail_path = + +; Force the addition of the specified parameters to be passed as extra parameters +; to the sendmail binary. These parameters will always replace the value of +; the 5th parameter to mail(). +;mail.force_extra_parameters = + +; Add X-PHP-Originating-Script: that will include uid of the script followed by the filename +mail.add_x_header = Off + +; The path to a log file that will log all mail() calls. Log entries include +; the full path of the script, line number, To address and headers. +;mail.log = +; Log mail to syslog (Event Log on Windows). +;mail.log = syslog + +[ODBC] +; http://php.net/odbc.default-db +;odbc.default_db = Not yet implemented + +; http://php.net/odbc.default-user +;odbc.default_user = Not yet implemented + +; http://php.net/odbc.default-pw +;odbc.default_pw = Not yet implemented + +; Controls the ODBC cursor model. +; Default: SQL_CURSOR_STATIC (default). +;odbc.default_cursortype + +; Allow or prevent persistent links. +; http://php.net/odbc.allow-persistent +odbc.allow_persistent = On + +; Check that a connection is still valid before reuse. +; http://php.net/odbc.check-persistent +odbc.check_persistent = On + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/odbc.max-persistent +odbc.max_persistent = -1 + +; Maximum number of links (persistent + non-persistent). -1 means no limit. +; http://php.net/odbc.max-links +odbc.max_links = -1 + +; Handling of LONG fields. Returns number of bytes to variables. 0 means +; passthru. +; http://php.net/odbc.defaultlrl +odbc.defaultlrl = 4096 + +; Handling of binary data. 0 means passthru, 1 return as is, 2 convert to char. +; See the documentation on odbc_binmode and odbc_longreadlen for an explanation +; of odbc.defaultlrl and odbc.defaultbinmode +; http://php.net/odbc.defaultbinmode +odbc.defaultbinmode = 1 + +[MySQLi] + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/mysqli.max-persistent +mysqli.max_persistent = -1 + +; Allow accessing, from PHP's perspective, local files with LOAD DATA statements +; http://php.net/mysqli.allow_local_infile +;mysqli.allow_local_infile = On + +; Allow or prevent persistent links. +; http://php.net/mysqli.allow-persistent +mysqli.allow_persistent = On + +; Maximum number of links. -1 means no limit. +; http://php.net/mysqli.max-links +mysqli.max_links = -1 + +; Default port number for mysqli_connect(). If unset, mysqli_connect() will use +; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the +; compile-time value defined MYSQL_PORT (in that order). Win32 will only look +; at MYSQL_PORT. +; http://php.net/mysqli.default-port +mysqli.default_port = 3306 + +; Default socket name for local MySQL connects. If empty, uses the built-in +; MySQL defaults. +; http://php.net/mysqli.default-socket +mysqli.default_socket = + +; Default host for mysqli_connect() (doesn't apply in safe mode). +; http://php.net/mysqli.default-host +mysqli.default_host = + +; Default user for mysqli_connect() (doesn't apply in safe mode). +; http://php.net/mysqli.default-user +mysqli.default_user = + +; Default password for mysqli_connect() (doesn't apply in safe mode). +; Note that this is generally a *bad* idea to store passwords in this file. +; *Any* user with PHP access can run 'echo get_cfg_var("mysqli.default_pw") +; and reveal this password! And of course, any users with read access to this +; file will be able to reveal the password as well. +; http://php.net/mysqli.default-pw +mysqli.default_pw = + +; Allow or prevent reconnect +mysqli.reconnect = Off + +[mysqlnd] +; Enable / Disable collection of general statistics by mysqlnd which can be +; used to tune and monitor MySQL operations. +mysqlnd.collect_statistics = On + +; Enable / Disable collection of memory usage statistics by mysqlnd which can be +; used to tune and monitor MySQL operations. +mysqlnd.collect_memory_statistics = Off + +; Records communication from all extensions using mysqlnd to the specified log +; file. +; http://php.net/mysqlnd.debug +;mysqlnd.debug = + +; Defines which queries will be logged. +;mysqlnd.log_mask = 0 + +; Default size of the mysqlnd memory pool, which is used by result sets. +;mysqlnd.mempool_default_size = 16000 + +; Size of a pre-allocated buffer used when sending commands to MySQL in bytes. +;mysqlnd.net_cmd_buffer_size = 2048 + +; Size of a pre-allocated buffer used for reading data sent by the server in +; bytes. +;mysqlnd.net_read_buffer_size = 32768 + +; Timeout for network requests in seconds. +;mysqlnd.net_read_timeout = 31536000 + +; SHA-256 Authentication Plugin related. File with the MySQL server public RSA +; key. +;mysqlnd.sha256_server_public_key = + +[OCI8] + +; Connection: Enables privileged connections using external +; credentials (OCI_SYSOPER, OCI_SYSDBA) +; http://php.net/oci8.privileged-connect +;oci8.privileged_connect = Off + +; Connection: The maximum number of persistent OCI8 connections per +; process. Using -1 means no limit. +; http://php.net/oci8.max-persistent +;oci8.max_persistent = -1 + +; Connection: The maximum number of seconds a process is allowed to +; maintain an idle persistent connection. Using -1 means idle +; persistent connections will be maintained forever. +; http://php.net/oci8.persistent-timeout +;oci8.persistent_timeout = -1 + +; Connection: The number of seconds that must pass before issuing a +; ping during oci_pconnect() to check the connection validity. When +; set to 0, each oci_pconnect() will cause a ping. Using -1 disables +; pings completely. +; http://php.net/oci8.ping-interval +;oci8.ping_interval = 60 + +; Connection: Set this to a user chosen connection class to be used +; for all pooled server requests with Oracle 11g Database Resident +; Connection Pooling (DRCP). To use DRCP, this value should be set to +; the same string for all web servers running the same application, +; the database pool must be configured, and the connection string must +; specify to use a pooled server. +;oci8.connection_class = + +; High Availability: Using On lets PHP receive Fast Application +; Notification (FAN) events generated when a database node fails. The +; database must also be configured to post FAN events. +;oci8.events = Off + +; Tuning: This option enables statement caching, and specifies how +; many statements to cache. Using 0 disables statement caching. +; http://php.net/oci8.statement-cache-size +;oci8.statement_cache_size = 20 + +; Tuning: Enables statement prefetching and sets the default number of +; rows that will be fetched automatically after statement execution. +; http://php.net/oci8.default-prefetch +;oci8.default_prefetch = 100 + +; Compatibility. Using On means oci_close() will not close +; oci_connect() and oci_new_connect() connections. +; http://php.net/oci8.old-oci-close-semantics +;oci8.old_oci_close_semantics = Off + +[PostgreSQL] +; Allow or prevent persistent links. +; http://php.net/pgsql.allow-persistent +pgsql.allow_persistent = On + +; Detect broken persistent links always with pg_pconnect(). +; Auto reset feature requires a little overheads. +; http://php.net/pgsql.auto-reset-persistent +pgsql.auto_reset_persistent = Off + +; Maximum number of persistent links. -1 means no limit. +; http://php.net/pgsql.max-persistent +pgsql.max_persistent = -1 + +; Maximum number of links (persistent+non persistent). -1 means no limit. +; http://php.net/pgsql.max-links +pgsql.max_links = -1 + +; Ignore PostgreSQL backends Notice message or not. +; Notice message logging require a little overheads. +; http://php.net/pgsql.ignore-notice +pgsql.ignore_notice = 0 + +; Log PostgreSQL backends Notice message or not. +; Unless pgsql.ignore_notice=0, module cannot log notice message. +; http://php.net/pgsql.log-notice +pgsql.log_notice = 0 + +[bcmath] +; Number of decimal digits for all bcmath functions. +; http://php.net/bcmath.scale +bcmath.scale = 0 + +[browscap] +; http://php.net/browscap +;browscap = extra/browscap.ini + +[Session] +; Handler used to store/retrieve data. +; http://php.net/session.save-handler +session.save_handler = files + +; Argument passed to save_handler. In the case of files, this is the path +; where data files are stored. Note: Windows users have to change this +; variable in order to use PHP's session functions. +; +; The path can be defined as: +; +; session.save_path = "N;/path" +; +; where N is an integer. Instead of storing all the session files in +; /path, what this will do is use subdirectories N-levels deep, and +; store the session data in those directories. This is useful if +; your OS has problems with many files in one directory, and is +; a more efficient layout for servers that handle many sessions. +; +; NOTE 1: PHP will not create this directory structure automatically. +; You can use the script in the ext/session dir for that purpose. +; NOTE 2: See the section on garbage collection below if you choose to +; use subdirectories for session storage +; +; The file storage module creates files using mode 600 by default. +; You can change that by using +; +; session.save_path = "N;MODE;/path" +; +; where MODE is the octal representation of the mode. Note that this +; does not overwrite the process's umask. +; http://php.net/session.save-path +;session.save_path = "/var/lib/php/sessions" + +; Whether to use strict session mode. +; Strict session mode does not accept an uninitialized session ID, and +; regenerates the session ID if the browser sends an uninitialized session ID. +; Strict mode protects applications from session fixation via a session adoption +; vulnerability. It is disabled by default for maximum compatibility, but +; enabling it is encouraged. +; https://wiki.php.net/rfc/strict_sessions +session.use_strict_mode = 0 + +; Whether to use cookies. +; http://php.net/session.use-cookies +session.use_cookies = 1 + +; http://php.net/session.cookie-secure +;session.cookie_secure = + +; This option forces PHP to fetch and use a cookie for storing and maintaining +; the session id. We encourage this operation as it's very helpful in combating +; session hijacking when not specifying and managing your own session id. It is +; not the be-all and end-all of session hijacking defense, but it's a good start. +; http://php.net/session.use-only-cookies +session.use_only_cookies = 1 + +; Name of the session (used as cookie name). +; http://php.net/session.name +session.name = PHPSESSID + +; Initialize session on request startup. +; http://php.net/session.auto-start +session.auto_start = 0 + +; Lifetime in seconds of cookie or, if 0, until browser is restarted. +; http://php.net/session.cookie-lifetime +session.cookie_lifetime = 0 + +; The path for which the cookie is valid. +; http://php.net/session.cookie-path +session.cookie_path = / + +; The domain for which the cookie is valid. +; http://php.net/session.cookie-domain +session.cookie_domain = + +; Whether or not to add the httpOnly flag to the cookie, which makes it +; inaccessible to browser scripting languages such as JavaScript. +; http://php.net/session.cookie-httponly +session.cookie_httponly = + +; Add SameSite attribute to cookie to help mitigate Cross-Site Request Forgery (CSRF/XSRF) +; Current valid values are "Lax" or "Strict" +; https://tools.ietf.org/html/draft-west-first-party-cookies-07 +session.cookie_samesite = + +; Handler used to serialize data. php is the standard serializer of PHP. +; http://php.net/session.serialize-handler +session.serialize_handler = php + +; Defines the probability that the 'garbage collection' process is started +; on every session initialization. The probability is calculated by using +; gc_probability/gc_divisor. Where session.gc_probability is the numerator +; and gc_divisor is the denominator in the equation. Setting this value to 1 +; when the session.gc_divisor value is 100 will give you approximately a 1% chance +; the gc will run on any given request. +; Default Value: 1 +; Development Value: 1 +; Production Value: 1 +; http://php.net/session.gc-probability +session.gc_probability = 0 + +; Defines the probability that the 'garbage collection' process is started on every +; session initialization. The probability is calculated by using the following equation: +; gc_probability/gc_divisor. Where session.gc_probability is the numerator and +; session.gc_divisor is the denominator in the equation. Setting this value to 100 +; when the session.gc_probability value is 1 will give you approximately a 1% chance +; the gc will run on any given request. Increasing this value to 1000 will give you +; a 0.1% chance the gc will run on any given request. For high volume production servers, +; this is a more efficient approach. +; Default Value: 100 +; Development Value: 1000 +; Production Value: 1000 +; http://php.net/session.gc-divisor +session.gc_divisor = 1000 + +; After this number of seconds, stored data will be seen as 'garbage' and +; cleaned up by the garbage collection process. +; http://php.net/session.gc-maxlifetime +session.gc_maxlifetime = 1440 + +; NOTE: If you are using the subdirectory option for storing session files +; (see session.save_path above), then garbage collection does *not* +; happen automatically. You will need to do your own garbage +; collection through a shell script, cron entry, or some other method. +; For example, the following script would is the equivalent of +; setting session.gc_maxlifetime to 1440 (1440 seconds = 24 minutes): +; find /path/to/sessions -cmin +24 -type f | xargs rm + +; Check HTTP Referer to invalidate externally stored URLs containing ids. +; HTTP_REFERER has to contain this substring for the session to be +; considered as valid. +; http://php.net/session.referer-check +session.referer_check = + +; Set to {nocache,private,public,} to determine HTTP caching aspects +; or leave this empty to avoid sending anti-caching headers. +; http://php.net/session.cache-limiter +session.cache_limiter = nocache + +; Document expires after n minutes. +; http://php.net/session.cache-expire +session.cache_expire = 180 + +; trans sid support is disabled by default. +; Use of trans sid may risk your users' security. +; Use this option with caution. +; - User may send URL contains active session ID +; to other person via. email/irc/etc. +; - URL that contains active session ID may be stored +; in publicly accessible computer. +; - User may access your site with the same session ID +; always using URL stored in browser's history or bookmarks. +; http://php.net/session.use-trans-sid +session.use_trans_sid = 0 + +; Set session ID character length. This value could be between 22 to 256. +; Shorter length than default is supported only for compatibility reason. +; Users should use 32 or more chars. +; http://php.net/session.sid-length +; Default Value: 32 +; Development Value: 26 +; Production Value: 26 +session.sid_length = 26 + +; The URL rewriter will look for URLs in a defined set of HTML tags. +;
is special; if you include them here, the rewriter will +; add a hidden field with the info which is otherwise appended +; to URLs. tag's action attribute URL will not be modified +; unless it is specified. +; Note that all valid entries require a "=", even if no value follows. +; Default Value: "a=href,area=href,frame=src,form=" +; Development Value: "a=href,area=href,frame=src,form=" +; Production Value: "a=href,area=href,frame=src,form=" +; http://php.net/url-rewriter.tags +session.trans_sid_tags = "a=href,area=href,frame=src,form=" + +; URL rewriter does not rewrite absolute URLs by default. +; To enable rewrites for absolute paths, target hosts must be specified +; at RUNTIME. i.e. use ini_set() +; tags is special. PHP will check action attribute's URL regardless +; of session.trans_sid_tags setting. +; If no host is defined, HTTP_HOST will be used for allowed host. +; Example value: php.net,www.php.net,wiki.php.net +; Use "," for multiple hosts. No spaces are allowed. +; Default Value: "" +; Development Value: "" +; Production Value: "" +;session.trans_sid_hosts="" + +; Define how many bits are stored in each character when converting +; the binary hash data to something readable. +; Possible values: +; 4 (4 bits: 0-9, a-f) +; 5 (5 bits: 0-9, a-v) +; 6 (6 bits: 0-9, a-z, A-Z, "-", ",") +; Default Value: 4 +; Development Value: 5 +; Production Value: 5 +; http://php.net/session.hash-bits-per-character +session.sid_bits_per_character = 5 + +; Enable upload progress tracking in $_SESSION +; Default Value: On +; Development Value: On +; Production Value: On +; http://php.net/session.upload-progress.enabled +;session.upload_progress.enabled = On + +; Cleanup the progress information as soon as all POST data has been read +; (i.e. upload completed). +; Default Value: On +; Development Value: On +; Production Value: On +; http://php.net/session.upload-progress.cleanup +;session.upload_progress.cleanup = On + +; A prefix used for the upload progress key in $_SESSION +; Default Value: "upload_progress_" +; Development Value: "upload_progress_" +; Production Value: "upload_progress_" +; http://php.net/session.upload-progress.prefix +;session.upload_progress.prefix = "upload_progress_" + +; The index name (concatenated with the prefix) in $_SESSION +; containing the upload progress information +; Default Value: "PHP_SESSION_UPLOAD_PROGRESS" +; Development Value: "PHP_SESSION_UPLOAD_PROGRESS" +; Production Value: "PHP_SESSION_UPLOAD_PROGRESS" +; http://php.net/session.upload-progress.name +;session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS" + +; How frequently the upload progress should be updated. +; Given either in percentages (per-file), or in bytes +; Default Value: "1%" +; Development Value: "1%" +; Production Value: "1%" +; http://php.net/session.upload-progress.freq +;session.upload_progress.freq = "1%" + +; The minimum delay between updates, in seconds +; Default Value: 1 +; Development Value: 1 +; Production Value: 1 +; http://php.net/session.upload-progress.min-freq +;session.upload_progress.min_freq = "1" + +; Only write session data when session data is changed. Enabled by default. +; http://php.net/session.lazy-write +;session.lazy_write = On + +[Assertion] +; Switch whether to compile assertions at all (to have no overhead at run-time) +; -1: Do not compile at all +; 0: Jump over assertion at run-time +; 1: Execute assertions +; Changing from or to a negative value is only possible in php.ini! (For turning assertions on and off at run-time, see assert.active, when zend.assertions = 1) +; Default Value: 1 +; Development Value: 1 +; Production Value: -1 +; http://php.net/zend.assertions +zend.assertions = -1 + +; Assert(expr); active by default. +; http://php.net/assert.active +;assert.active = On + +; Throw an AssertionError on failed assertions +; http://php.net/assert.exception +;assert.exception = On + +; Issue a PHP warning for each failed assertion. (Overridden by assert.exception if active) +; http://php.net/assert.warning +;assert.warning = On + +; Don't bail out by default. +; http://php.net/assert.bail +;assert.bail = Off + +; User-function to be called if an assertion fails. +; http://php.net/assert.callback +;assert.callback = 0 + +; Eval the expression with current error_reporting(). Set to true if you want +; error_reporting(0) around the eval(). +; http://php.net/assert.quiet-eval +;assert.quiet_eval = 0 + +[COM] +; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs +; http://php.net/com.typelib-file +;com.typelib_file = + +; allow Distributed-COM calls +; http://php.net/com.allow-dcom +;com.allow_dcom = true + +; autoregister constants of a component's typlib on com_load() +; http://php.net/com.autoregister-typelib +;com.autoregister_typelib = true + +; register constants casesensitive +; http://php.net/com.autoregister-casesensitive +;com.autoregister_casesensitive = false + +; show warnings on duplicate constant registrations +; http://php.net/com.autoregister-verbose +;com.autoregister_verbose = true + +; The default character set code-page to use when passing strings to and from COM objects. +; Default: system ANSI code page +;com.code_page= + +[mbstring] +; language for internal character representation. +; This affects mb_send_mail() and mbstring.detect_order. +; http://php.net/mbstring.language +;mbstring.language = Japanese + +; Use of this INI entry is deprecated, use global internal_encoding instead. +; internal/script encoding. +; Some encoding cannot work as internal encoding. (e.g. SJIS, BIG5, ISO-2022-*) +; If empty, default_charset or internal_encoding or iconv.internal_encoding is used. +; The precedence is: default_charset < internal_encoding < iconv.internal_encoding +;mbstring.internal_encoding = + +; Use of this INI entry is deprecated, use global input_encoding instead. +; http input encoding. +; mbstring.encoding_translation = On is needed to use this setting. +; If empty, default_charset or input_encoding or mbstring.input is used. +; The precedence is: default_charset < input_encoding < mbsting.http_input +; http://php.net/mbstring.http-input +;mbstring.http_input = + +; Use of this INI entry is deprecated, use global output_encoding instead. +; http output encoding. +; mb_output_handler must be registered as output buffer to function. +; If empty, default_charset or output_encoding or mbstring.http_output is used. +; The precedence is: default_charset < output_encoding < mbstring.http_output +; To use an output encoding conversion, mbstring's output handler must be set +; otherwise output encoding conversion cannot be performed. +; http://php.net/mbstring.http-output +;mbstring.http_output = + +; enable automatic encoding translation according to +; mbstring.internal_encoding setting. Input chars are +; converted to internal encoding by setting this to On. +; Note: Do _not_ use automatic encoding translation for +; portable libs/applications. +; http://php.net/mbstring.encoding-translation +;mbstring.encoding_translation = Off + +; automatic encoding detection order. +; "auto" detect order is changed according to mbstring.language +; http://php.net/mbstring.detect-order +;mbstring.detect_order = auto + +; substitute_character used when character cannot be converted +; one from another +; http://php.net/mbstring.substitute-character +;mbstring.substitute_character = none + +; overload(replace) single byte functions by mbstring functions. +; mail(), ereg(), etc are overloaded by mb_send_mail(), mb_ereg(), +; etc. Possible values are 0,1,2,4 or combination of them. +; For example, 7 for overload everything. +; 0: No overload +; 1: Overload mail() function +; 2: Overload str*() functions +; 4: Overload ereg*() functions +; http://php.net/mbstring.func-overload +;mbstring.func_overload = 0 + +; enable strict encoding detection. +; Default: Off +;mbstring.strict_detection = On + +; This directive specifies the regex pattern of content types for which mb_output_handler() +; is activated. +; Default: mbstring.http_output_conv_mimetype=^(text/|application/xhtml\+xml) +;mbstring.http_output_conv_mimetype= + +; This directive specifies maximum stack depth for mbstring regular expressions. It is similar +; to the pcre.recursion_limit for PCRE. +; Default: 100000 +;mbstring.regex_stack_limit=100000 + +[gd] +; Tell the jpeg decode to ignore warnings and try to create +; a gd image. The warning will then be displayed as notices +; disabled by default +; http://php.net/gd.jpeg-ignore-warning +;gd.jpeg_ignore_warning = 1 + +[exif] +; Exif UNICODE user comments are handled as UCS-2BE/UCS-2LE and JIS as JIS. +; With mbstring support this will automatically be converted into the encoding +; given by corresponding encode setting. When empty mbstring.internal_encoding +; is used. For the decode settings you can distinguish between motorola and +; intel byte order. A decode setting cannot be empty. +; http://php.net/exif.encode-unicode +;exif.encode_unicode = ISO-8859-15 + +; http://php.net/exif.decode-unicode-motorola +;exif.decode_unicode_motorola = UCS-2BE + +; http://php.net/exif.decode-unicode-intel +;exif.decode_unicode_intel = UCS-2LE + +; http://php.net/exif.encode-jis +;exif.encode_jis = + +; http://php.net/exif.decode-jis-motorola +;exif.decode_jis_motorola = JIS + +; http://php.net/exif.decode-jis-intel +;exif.decode_jis_intel = JIS + +[Tidy] +; The path to a default tidy configuration file to use when using tidy +; http://php.net/tidy.default-config +;tidy.default_config = /usr/local/lib/php/default.tcfg + +; Should tidy clean and repair output automatically? +; WARNING: Do not use this option if you are generating non-html content +; such as dynamic images +; http://php.net/tidy.clean-output +tidy.clean_output = Off + +[soap] +; Enables or disables WSDL caching feature. +; http://php.net/soap.wsdl-cache-enabled +soap.wsdl_cache_enabled=1 + +; Sets the directory name where SOAP extension will put cache files. +; http://php.net/soap.wsdl-cache-dir +soap.wsdl_cache_dir="/tmp" + +; (time to live) Sets the number of second while cached file will be used +; instead of original one. +; http://php.net/soap.wsdl-cache-ttl +soap.wsdl_cache_ttl=86400 + +; Sets the size of the cache limit. (Max. number of WSDL files to cache) +soap.wsdl_cache_limit = 5 + +[sysvshm] +; A default size of the shared memory segment +;sysvshm.init_mem = 10000 + +[ldap] +; Sets the maximum number of open links or -1 for unlimited. +ldap.max_links = -1 + +[dba] +;dba.default_handler= + +[opcache] +; Determines if Zend OPCache is enabled +;opcache.enable=1 + +; Determines if Zend OPCache is enabled for the CLI version of PHP +;opcache.enable_cli=0 + +; The OPcache shared memory storage size. +;opcache.memory_consumption=128 + +; The amount of memory for interned strings in Mbytes. +;opcache.interned_strings_buffer=8 + +; The maximum number of keys (scripts) in the OPcache hash table. +; Only numbers between 200 and 1000000 are allowed. +;opcache.max_accelerated_files=10000 + +; The maximum percentage of "wasted" memory until a restart is scheduled. +;opcache.max_wasted_percentage=5 + +; When this directive is enabled, the OPcache appends the current working +; directory to the script key, thus eliminating possible collisions between +; files with the same name (basename). Disabling the directive improves +; performance, but may break existing applications. +;opcache.use_cwd=1 + +; When disabled, you must reset the OPcache manually or restart the +; webserver for changes to the filesystem to take effect. +;opcache.validate_timestamps=1 + +; How often (in seconds) to check file timestamps for changes to the shared +; memory storage allocation. ("1" means validate once per second, but only +; once per request. "0" means always validate) +;opcache.revalidate_freq=2 + +; Enables or disables file search in include_path optimization +;opcache.revalidate_path=0 + +; If disabled, all PHPDoc comments are dropped from the code to reduce the +; size of the optimized code. +;opcache.save_comments=1 + +; Allow file existence override (file_exists, etc.) performance feature. +;opcache.enable_file_override=0 + +; A bitmask, where each bit enables or disables the appropriate OPcache +; passes +;opcache.optimization_level=0x7FFFBFFF + +;opcache.dups_fix=0 + +; The location of the OPcache blacklist file (wildcards allowed). +; Each OPcache blacklist file is a text file that holds the names of files +; that should not be accelerated. The file format is to add each filename +; to a new line. The filename may be a full path or just a file prefix +; (i.e., /var/www/x blacklists all the files and directories in /var/www +; that start with 'x'). Line starting with a ; are ignored (comments). +;opcache.blacklist_filename= + +; Allows exclusion of large files from being cached. By default all files +; are cached. +;opcache.max_file_size=0 + +; Check the cache checksum each N requests. +; The default value of "0" means that the checks are disabled. +;opcache.consistency_checks=0 + +; How long to wait (in seconds) for a scheduled restart to begin if the cache +; is not being accessed. +;opcache.force_restart_timeout=180 + +; OPcache error_log file name. Empty string assumes "stderr". +;opcache.error_log= + +; All OPcache errors go to the Web server log. +; By default, only fatal errors (level 0) or errors (level 1) are logged. +; You can also enable warnings (level 2), info messages (level 3) or +; debug messages (level 4). +;opcache.log_verbosity_level=1 + +; Preferred Shared Memory back-end. Leave empty and let the system decide. +;opcache.preferred_memory_model= + +; Protect the shared memory from unexpected writing during script execution. +; Useful for internal debugging only. +;opcache.protect_memory=0 + +; Allows calling OPcache API functions only from PHP scripts which path is +; started from specified string. The default "" means no restriction +;opcache.restrict_api= + +; Mapping base of shared memory segments (for Windows only). All the PHP +; processes have to map shared memory into the same address space. This +; directive allows to manually fix the "Unable to reattach to base address" +; errors. +;opcache.mmap_base= + +; Facilitates multiple OPcache instances per user (for Windows only). All PHP +; processes with the same cache ID and user share an OPcache instance. +;opcache.cache_id= + +; Enables and sets the second level cache directory. +; It should improve performance when SHM memory is full, at server restart or +; SHM reset. The default "" disables file based caching. +;opcache.file_cache= + +; Enables or disables opcode caching in shared memory. +;opcache.file_cache_only=0 + +; Enables or disables checksum validation when script loaded from file cache. +;opcache.file_cache_consistency_checks=1 + +; Implies opcache.file_cache_only=1 for a certain process that failed to +; reattach to the shared memory (for Windows only). Explicitly enabled file +; cache is required. +;opcache.file_cache_fallback=1 + +; Enables or disables copying of PHP code (text segment) into HUGE PAGES. +; This should improve performance, but requires appropriate OS configuration. +;opcache.huge_code_pages=1 + +; Validate cached file permissions. +;opcache.validate_permission=0 + +; Prevent name collisions in chroot'ed environment. +;opcache.validate_root=0 + +; If specified, it produces opcode dumps for debugging different stages of +; optimizations. +;opcache.opt_debug_level=0 + +; Specifies a PHP script that is going to be compiled and executed at server +; start-up. +; http://php.net/opcache.preload +;opcache.preload= + +; Prevents caching files that are less than this number of seconds old. It +; protects from caching of incompletely updated files. In case all file updates +; on your site are atomic, you may increase performance by setting it to "0". +;opcache.file_update_protection=2 + +; Absolute path used to store shared lockfiles (for *nix only). +;opcache.lockfile_path=/tmp + +[curl] +; A default value for the CURLOPT_CAINFO option. This is required to be an +; absolute path. +;curl.cainfo = + +[openssl] +; The location of a Certificate Authority (CA) file on the local filesystem +; to use when verifying the identity of SSL/TLS peers. Most users should +; not specify a value for this directive as PHP will attempt to use the +; OS-managed cert stores in its absence. If specified, this value may still +; be overridden on a per-stream basis via the "cafile" SSL stream context +; option. +;openssl.cafile= + +; If openssl.cafile is not specified or if the CA file is not found, the +; directory pointed to by openssl.capath is searched for a suitable +; certificate. This value must be a correctly hashed certificate directory. +; Most users should not specify a value for this directive as PHP will +; attempt to use the OS-managed cert stores in its absence. If specified, +; this value may still be overridden on a per-stream basis via the "capath" +; SSL stream context option. +;openssl.capath= + +[ffi] +; FFI API restriction. Possibe values: +; "preload" - enabled in CLI scripts and preloaded files (default) +; "false" - always disabled +; "true" - always enabled +;ffi.enable=preload diff --git a/etc/php/8.2/fpm/pool.d/lemper.conf b/etc/php/8.2/fpm/pool.d/lemper.conf new file mode 100644 index 00000000..138c43eb --- /dev/null +++ b/etc/php/8.2/fpm/pool.d/lemper.conf @@ -0,0 +1,60 @@ +[lemper] +user = lemper +group = lemper + +listen = /run/php/php8.2-fpm.$pool.sock +listen.owner = lemper +listen.group = lemper +listen.mode = 0660 +;listen.allowed_clients = 127.1.0.1 + +; Custom PHP-FPM optimization, adjust here to meet your specs. +; Default value here is optimized for a single CPU with at least 1GB RAM. +pm = dynamic +pm.max_children = 30 +pm.start_servers = 5 +pm.min_spare_servers = 5 +pm.max_spare_servers = 20 +pm.process_idle_timeout = 30s +pm.max_requests = 500 + +pm.status_path = /php-fpm_status +ping.path = /php-fpm_ping + +slowlog = /home/lemper/logs/php/php8.2-fpm_slow.log +request_slowlog_timeout = 10s + +;chroot = /home/lemper +chdir = /home/lemper + +;catch_workers_output = yes +;decorate_workers_output = no + +security.limit_extensions = .php .php8 .php81 + +; Custom PHP ini settings for LEMPer Stack. +php_admin_value[open_basedir] = /home/lemper +;php_admin_value[disable_functions] = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,exec,passthru,popen,proc_open,shell_exec,system +;php_admin_value[disable_classes] = +php_admin_flag[log_errors] = on +php_admin_value[error_log] = /home/lemper/logs/php/php8.2-fpm.log +php_admin_value[sys_temp_dir] = /home/lemper/.lemper/tmp +php_admin_value[upload_tmp_dir] = /home/lemper/.lemper/tmp +;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com +php_admin_value[opcache.file_cache] = /home/lemper/.lemper/tmp/php_opcache + +; Configuration below can be overwritten from PHP call 'ini_set'. +php_flag[short_open_tag] = off +php_value[max_execution_time] = 300 +php_value[max_input_time] = 60 +php_value[memory_limit] = 128M +php_value[post_max_size] = 50M +php_flag[file_uploads] = on +php_value[upload_max_filesize] = 50M +php_value[max_file_uploads] = 20 +php_value[default_socket_timeout] = 60 +php_value[error_reporting] = E_ALL & ~E_DEPRECATED & ~E_STRICT +php_flag[display_errors] = on +php_flag[cgi.fix_pathinfo] = 1 +php_value[date.timezone] = UTC +php_value[session.save_path] = /home/lemper/.lemper/tmp/php_sessions diff --git a/etc/php/8.2/fpm/pool.d/www.conf b/etc/php/8.2/fpm/pool.d/www.conf new file mode 100644 index 00000000..e21f9674 --- /dev/null +++ b/etc/php/8.2/fpm/pool.d/www.conf @@ -0,0 +1,461 @@ +; Start a new pool named 'www'. +; the variable $pool can be used in any directive and will be replaced by the +; pool name ('www' here) +[www] + +; Per pool prefix +; It only applies on the following directives: +; - 'access.log' +; - 'slowlog' +; - 'listen' (unixsocket) +; - 'chroot' +; - 'chdir' +; - 'php_values' +; - 'php_admin_values' +; When not set, the global prefix (or /usr) applies instead. +; Note: This directive can also be relative to the global prefix. +; Default Value: none +;prefix = /path/to/pools/$pool + +; Unix user/group of processes +; Note: The user is mandatory. If the group is not set, the default user's group +; will be used. +user = www-data +group = www-data + +; The address on which to accept FastCGI requests. +; Valid syntaxes are: +; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on +; a specific port; +; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on +; a specific port; +; 'port' - to listen on a TCP socket to all addresses +; (IPv6 and IPv4-mapped) on a specific port; +; '/path/to/unix/socket' - to listen on a unix socket. +; Note: This value is mandatory. +listen = /run/php/php8.2-fpm.sock + +; Set listen(2) backlog. +; Default Value: 511 (-1 on FreeBSD and OpenBSD) +;listen.backlog = 511 + +; Set permissions for unix socket, if one is used. In Linux, read/write +; permissions must be set in order to allow connections from a web server. Many +; BSD-derived systems allow connections regardless of permissions. +; Default Values: user and group are set as the running user +; mode is set to 0660 +listen.owner = www-data +listen.group = www-data +listen.mode = 0660 + +; When POSIX Access Control Lists are supported you can set them using +; these options, value is a comma separated list of user/group names. +; When set, listen.owner and listen.group are ignored +;listen.acl_users = +;listen.acl_groups = + +; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect. +; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original +; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address +; must be separated by a comma. If this value is left blank, connections will be +; accepted from any ip address. +; Default Value: any +;listen.allowed_clients = 127.0.0.1 + +; Specify the nice(2) priority to apply to the pool processes (only if set) +; The value can vary from -19 (highest priority) to 20 (lower priority) +; Note: - It will only work if the FPM master process is launched as root +; - The pool processes will inherit the master process priority +; unless it specified otherwise +; Default Value: no set +; process.priority = -19 + +; Set the process dumpable flag (PR_SET_DUMPABLE prctl) even if the process user +; or group is differrent than the master process user. It allows to create process +; core dump and ptrace the process for the pool user. +; Default Value: no +; process.dumpable = yes + +; Choose how the process manager will control the number of child processes. +; Possible Values: +; static - a fixed number (pm.max_children) of child processes; +; dynamic - the number of child processes are set dynamically based on the +; following directives. With this process management, there will be +; always at least 1 children. +; pm.max_children - the maximum number of children that can +; be alive at the same time. +; pm.start_servers - the number of children created on startup. +; pm.min_spare_servers - the minimum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is less than this +; number then some children will be created. +; pm.max_spare_servers - the maximum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is greater than this +; number then some children will be killed. +; ondemand - no children are created at startup. Children will be forked when +; new requests will connect. The following parameter are used: +; pm.max_children - the maximum number of children that +; can be alive at the same time. +; pm.process_idle_timeout - The number of seconds after which +; an idle process will be killed. +; Note: This value is mandatory. +pm = dynamic + +; The number of child processes to be created when pm is set to 'static' and the +; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. +; This value sets the limit on the number of simultaneous requests that will be +; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. +; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP +; CGI. The below defaults are based on a server without much resources. Don't +; forget to tweak pm.* to fit your needs. +; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand' +; Note: This value is mandatory. +pm.max_children = 5 + +; The number of child processes created on startup. +; Note: Used only when pm is set to 'dynamic' +; Default Value: (min_spare_servers + max_spare_servers) / 2 +pm.start_servers = 2 + +; The desired minimum number of idle server processes. +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.min_spare_servers = 1 + +; The desired maximum number of idle server processes. +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.max_spare_servers = 3 + +; The number of seconds after which an idle process will be killed. +; Note: Used only when pm is set to 'ondemand' +; Default Value: 10s +;pm.process_idle_timeout = 10s; + +; The number of requests each child process should execute before respawning. +; This can be useful to work around memory leaks in 3rd party libraries. For +; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. +; Default Value: 0 +;pm.max_requests = 500 + +; The URI to view the FPM status page. If this value is not set, no URI will be +; recognized as a status page. It shows the following informations: +; pool - the name of the pool; +; process manager - static, dynamic or ondemand; +; start time - the date and time FPM has started; +; start since - number of seconds since FPM has started; +; accepted conn - the number of request accepted by the pool; +; listen queue - the number of request in the queue of pending +; connections (see backlog in listen(2)); +; max listen queue - the maximum number of requests in the queue +; of pending connections since FPM has started; +; listen queue len - the size of the socket queue of pending connections; +; idle processes - the number of idle processes; +; active processes - the number of active processes; +; total processes - the number of idle + active processes; +; max active processes - the maximum number of active processes since FPM +; has started; +; max children reached - number of times, the process limit has been reached, +; when pm tries to start more children (works only for +; pm 'dynamic' and 'ondemand'); +; Value are updated in real time. +; Example output: +; pool: www +; process manager: static +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 62636 +; accepted conn: 190460 +; listen queue: 0 +; max listen queue: 1 +; listen queue len: 42 +; idle processes: 4 +; active processes: 11 +; total processes: 15 +; max active processes: 12 +; max children reached: 0 +; +; By default the status page output is formatted as text/plain. Passing either +; 'html', 'xml' or 'json' in the query string will return the corresponding +; output syntax. Example: +; http://www.foo.bar/status +; http://www.foo.bar/status?json +; http://www.foo.bar/status?html +; http://www.foo.bar/status?xml +; +; By default the status page only outputs short status. Passing 'full' in the +; query string will also return status for each pool process. +; Example: +; http://www.foo.bar/status?full +; http://www.foo.bar/status?json&full +; http://www.foo.bar/status?html&full +; http://www.foo.bar/status?xml&full +; The Full status returns for each process: +; pid - the PID of the process; +; state - the state of the process (Idle, Running, ...); +; start time - the date and time the process has started; +; start since - the number of seconds since the process has started; +; requests - the number of requests the process has served; +; request duration - the duration in µs of the requests; +; request method - the request method (GET, POST, ...); +; request URI - the request URI with the query string; +; content length - the content length of the request (only with POST); +; user - the user (PHP_AUTH_USER) (or '-' if not set); +; script - the main script called (or '-' if not set); +; last request cpu - the %cpu the last request consumed +; it's always 0 if the process is not in Idle state +; because CPU calculation is done when the request +; processing has terminated; +; last request memory - the max amount of memory the last request consumed +; it's always 0 if the process is not in Idle state +; because memory calculation is done when the request +; processing has terminated; +; If the process is in Idle state, then informations are related to the +; last request the process has served. Otherwise informations are related to +; the current request being served. +; Example output: +; ************************ +; pid: 31330 +; state: Running +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 63087 +; requests: 12808 +; request duration: 1250261 +; request method: GET +; request URI: /test_mem.php?N=10000 +; content length: 0 +; user: - +; script: /home/fat/web/docs/php/test_mem.php +; last request cpu: 0.00 +; last request memory: 0 +; +; Note: There is a real-time FPM status monitoring sample web page available +; It's available in: /usr/share/php/8.2/fpm/status.html +; +; Note: The value must start with a leading slash (/). The value can be +; anything, but it may not be a good idea to use the .php extension or it +; may conflict with a real PHP file. +; Default Value: not set +;pm.status_path = /status +pm.status_path = /php-fpm_status + +; The ping URI to call the monitoring page of FPM. If this value is not set, no +; URI will be recognized as a ping page. This could be used to test from outside +; that FPM is alive and responding, or to +; - create a graph of FPM availability (rrd or such); +; - remove a server from a group if it is not responding (load balancing); +; - trigger alerts for the operating team (24/7). +; Note: The value must start with a leading slash (/). The value can be +; anything, but it may not be a good idea to use the .php extension or it +; may conflict with a real PHP file. +; Default Value: not set +;ping.path = /ping +ping.path = /php-fpm_ping + +; This directive may be used to customize the response of a ping request. The +; response is formatted as text/plain with a 200 response code. +; Default Value: pong +;ping.response = pong + +; The access log file +; Default: not set +;access.log = log/$pool.access.log + +; The access log format. +; The following syntax is allowed +; %%: the '%' character +; %C: %CPU used by the request +; it can accept the following format: +; - %{user}C for user CPU only +; - %{system}C for system CPU only +; - %{total}C for user + system CPU (default) +; %d: time taken to serve the request +; it can accept the following format: +; - %{seconds}d (default) +; - %{miliseconds}d +; - %{mili}d +; - %{microseconds}d +; - %{micro}d +; %e: an environment variable (same as $_ENV or $_SERVER) +; it must be associated with embraces to specify the name of the env +; variable. Some exemples: +; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e +; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e +; %f: script filename +; %l: content-length of the request (for POST request only) +; %m: request method +; %M: peak of memory allocated by PHP +; it can accept the following format: +; - %{bytes}M (default) +; - %{kilobytes}M +; - %{kilo}M +; - %{megabytes}M +; - %{mega}M +; %n: pool name +; %o: output header +; it must be associated with embraces to specify the name of the header: +; - %{Content-Type}o +; - %{X-Powered-By}o +; - %{Transfert-Encoding}o +; - .... +; %p: PID of the child that serviced the request +; %P: PID of the parent of the child that serviced the request +; %q: the query string +; %Q: the '?' character if query string exists +; %r: the request URI (without the query string, see %q and %Q) +; %R: remote IP address +; %s: status (response code) +; %t: server time the request was received +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; The strftime(3) format must be encapsuled in a %{}t tag +; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t +; %T: time the log has been written (the request has finished) +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; The strftime(3) format must be encapsuled in a %{}t tag +; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t +; %u: remote user +; +; Default: "%R - %u %t \"%m %r\" %s" +;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%" + +; The log file for slow requests +; Default Value: not set +; Note: slowlog is mandatory if request_slowlog_timeout is set +;slowlog = log/$pool.log.slow +slowlog = /var/log/php/php8.2-fpm_slow.$pool.log + +; The timeout for serving a single request after which a PHP backtrace will be +; dumped to the 'slowlog' file. A value of '0s' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +;request_slowlog_timeout = 0 +request_slowlog_timeout = 10s + +; Depth of slow log stack trace. +; Default Value: 20 +;request_slowlog_trace_depth = 20 + +; The timeout for serving a single request after which the worker process will +; be killed. This option should be used when the 'max_execution_time' ini option +; does not stop script execution for some reason. A value of '0' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +;request_terminate_timeout = 0 + +; Set open file descriptor rlimit. +; Default Value: system defined value +;rlimit_files = 1024 + +; Set max core size rlimit. +; Possible Values: 'unlimited' or an integer greater or equal to 0 +; Default Value: system defined value +;rlimit_core = 0 + +; Chroot to this directory at the start. This value must be defined as an +; absolute path. When this value is not set, chroot is not used. +; Note: you can prefix with '$prefix' to chroot to the pool prefix or one +; of its subdirectories. If the pool prefix is not set, the global prefix +; will be used instead. +; Note: chrooting is a great security feature and should be used whenever +; possible. However, all PHP paths will be relative to the chroot +; (error_log, sessions.save_path, ...). +; Default Value: not set +;chroot = + +; Chdir to this directory at the start. +; Note: relative path can be used. +; Default Value: current directory or / when chroot +;chdir = /var/www +chdir = /usr/share/nginx/html + +; Redirect worker stdout and stderr into main error log. If not set, stdout and +; stderr will be redirected to /dev/null according to FastCGI specs. +; Note: on highloaded environement, this can cause some delay in the page +; process time (several ms). +; Default Value: no +;catch_workers_output = yes + +; Decorate worker output with prefix and suffix containing information about +; the child that writes to the log and if stdout or stderr is used as well as +; log level and time. This options is used only if catch_workers_output is yes. +; Settings to "no" will output data as written to the stdout or stderr. +; Default value: yes +;decorate_workers_output = no + +; Clear environment in FPM workers +; Prevents arbitrary environment variables from reaching FPM worker processes +; by clearing the environment in workers before env vars specified in this +; pool configuration are added. +; Setting to "no" will make all environment variables available to PHP code +; via getenv(), $_ENV and $_SERVER. +; Default Value: yes +;clear_env = no + +; Limits the extensions of the main script FPM will allow to parse. This can +; prevent configuration mistakes on the web server side. You should only limit +; FPM to .php extensions to prevent malicious users to use other extensions to +; execute php code. +; Note: set an empty value to allow all extensions. +; Default Value: .php +;security.limit_extensions = .php .php3 .php4 .php5 .php7 +security.limit_extensions = .php .php8 .php81 + +; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from +; the current environment. +; Default Value: clean env +;env[HOSTNAME] = $HOSTNAME +;env[PATH] = /usr/local/bin:/usr/bin:/bin +;env[TMP] = /tmp +;env[TMPDIR] = /tmp +;env[TEMP] = /tmp + +; Additional php.ini defines, specific to this pool of workers. These settings +; overwrite the values previously defined in the php.ini. The directives are the +; same as the PHP SAPI: +; php_value/php_flag - you can set classic ini defines which can +; be overwritten from PHP call 'ini_set'. +; php_admin_value/php_admin_flag - these directives won't be overwritten by +; PHP call 'ini_set' +; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no. + +; Defining 'extension' will load the corresponding shared extension from +; extension_dir. Defining 'disable_functions' or 'disable_classes' will not +; overwrite previously defined php.ini values, but will append the new value +; instead. + +; Note: path INI options can be relative and will be expanded with the prefix +; (pool, global or /usr) + +; Default Value: nothing is defined by default except the values in php.ini and +; specified at startup with the -d argument + +; Custom PHP ini settings for LEMPer Stack. +php_admin_value[open_basedir] = /usr/share/nginx/html +;php_admin_value[disable_functions] = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,exec,passthru,popen,proc_open,shell_exec,system +;php_admin_value[disable_classes] = +php_admin_flag[log_errors] = on +php_admin_value[error_log] = /var/log/php/php8.0-fpm.$pool_error.log +php_admin_value[sys_temp_dir] = /usr/share/nginx/html/.lemper/tmp +php_admin_value[upload_tmp_dir] = /usr/share/nginx/html/.lemper/tmp +;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com + +; Configuration below can be overwritten from PHP call 'ini_set'. +php_flag[short_open_tag] = off +php_value[max_execution_time] = 300 +php_value[max_input_time] = 60 +php_value[memory_limit] = 128M +php_value[post_max_size] = 50M +php_flag[file_uploads] = on +php_value[upload_max_filesize] = 50M +php_value[max_file_uploads] = 20 +php_value[default_socket_timeout] = 60 +php_value[error_reporting] = E_ALL & ~E_DEPRECATED & ~E_STRICT +php_flag[display_errors] = on +php_flag[cgi.fix_pathinfo] = 1 +php_value[date.timezone] = UTC +php_value[session.save_handler] = files +php_value[session.save_path] = /usr/share/nginx/html/.lemper/php/sessions +php_value[soap.wsdl_cache_dir] = /usr/share/nginx/html/.lemper/php/wsdlcache +php_value[opcache.file_cache] = /usr/share/nginx/html/.lemper/php/opcache diff --git a/install.sh b/install.sh index c2e40ed5..5525fea8 100755 --- a/install.sh +++ b/install.sh @@ -33,7 +33,7 @@ BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # Include helper functions. if [[ "$(type -t run)" != "function" ]]; then - . "${BASE_DIR}/scripts/helper.sh" + . "${BASE_DIR}/scripts/utils.sh" fi # Make sure only root can run this installer script. @@ -67,16 +67,10 @@ if [ -f ./scripts/install_dependencies.sh ]; then . ./scripts/install_dependencies.sh fi -### Clean-up server ### -if [ -f ./scripts/cleanup_server.sh ]; then +### Server clean-up ### +if [ -f ./scripts/server_cleanup.sh ]; then echo "" - . ./scripts/cleanup_server.sh -fi - -### Create and enable swap ### -if [[ "${ENABLE_SWAP}" == true ]]; then - echo "" - enable_swap + . ./scripts/server_cleanup.sh fi ### Create default account ### @@ -84,12 +78,6 @@ echo "" USERNAME=${LEMPER_USERNAME:-"lemper"} create_account "${USERNAME}" -### Nginx installation ### -if [ -f ./scripts/install_nginx.sh ]; then - echo "" - . ./scripts/install_nginx.sh -fi - ### Certbot Let's Encrypt SSL installation ### if [ -f ./scripts/install_certbotle.sh ]; then echo "" @@ -108,6 +96,12 @@ if [ -f ./scripts/install_phalcon.sh ]; then . ./scripts/install_phalcon.sh fi +### Nginx installation ### +if [ -f ./scripts/install_nginx.sh ]; then + echo "" + . ./scripts/install_nginx.sh +fi + ### MySQL database installation ### if [ -f ./scripts/install_mariadb.sh ]; then echo "" @@ -169,17 +163,23 @@ if [ -f ./scripts/install_tools.sh ]; then . ./scripts/install_tools.sh fi +### Basic server optimization ### +if [ -f ./scripts/server_optimization.sh ]; then + echo "" + . ./scripts/server_optimization.sh +fi + ### Basic server security setup ### -if [ -f ./scripts/secure_server.sh ]; then +if [ -f ./scripts/server_security.sh ]; then echo "" - . ./scripts/secure_server.sh + . ./scripts/server_security.sh fi ### FINAL SETUP ### if [[ "${FORCE_REMOVE}" == true ]]; then # Cleaning up all build dependencies hanging around on production server? echo -e "\nClean up installation process..." - run apt-get autoremove -qq -y + run apt-get autoremove -q -y # Cleanup build dir echo "Clean up build directory..." diff --git a/lemper.sh b/lemper.sh index f8de0d02..9bbaefe2 100755 --- a/lemper.sh +++ b/lemper.sh @@ -63,16 +63,10 @@ function lemper_install() { . ./scripts/install_dependencies.sh fi - ### Clean-up server ### - if [ -f ./scripts/cleanup_server.sh ]; then + ### Server clean-up ### + if [ -f ./scripts/server_cleanup.sh ]; then echo "" - . ./scripts/cleanup_server.sh - fi - - ### Create and enable swap ### - if [[ "${ENABLE_SWAP}" == true ]]; then - echo "" - enable_swap + . ./scripts/server_cleanup.sh fi ### Create default account ### @@ -80,12 +74,6 @@ function lemper_install() { USERNAME=${LEMPER_USERNAME:-"lemper"} create_account "${USERNAME}" - ### Nginx installation ### - if [ -f ./scripts/install_nginx.sh ]; then - echo "" - . ./scripts/install_nginx.sh - fi - ### Certbot Let's Encrypt SSL installation ### if [ -f ./scripts/install_certbotle.sh ]; then echo "" @@ -104,6 +92,12 @@ function lemper_install() { . ./scripts/install_phalcon.sh fi + ### Nginx installation ### + if [ -f ./scripts/install_nginx.sh ]; then + echo "" + . ./scripts/install_nginx.sh + fi + ### MySQL database installation ### if [ -f ./scripts/install_mariadb.sh ]; then echo "" @@ -165,17 +159,23 @@ function lemper_install() { . ./scripts/install_tools.sh fi + ### Basic server optimization ### + if [ -f ./scripts/server_optimization.sh ]; then + echo "" + . ./scripts/server_optimization.sh + fi + ### Basic server security setup ### - if [ -f ./scripts/secure_server.sh ]; then + if [ -f ./scripts/server_security.sh ]; then echo "" - . ./scripts/secure_server.sh + . ./scripts/server_security.sh fi ### FINAL SETUP ### if [[ "${FORCE_REMOVE}" == true ]]; then # Cleaning up all build dependencies hanging around on production server? echo -e "\nClean up installation process..." - run apt-get autoremove -qq -y + run apt-get autoremove -q -y # Cleanup build dir echo "Clean up build directory..." @@ -292,7 +292,7 @@ function lemper_remove() { # Fix broken install, first? if [[ "${FIX_BROKEN_INSTALL}" == true ]]; then run dpkg --configure -a - run apt-get install -qq -y --fix-broken + run apt-get install -q -y --fix-broken fi ### Remove Nginx ### @@ -357,9 +357,9 @@ function lemper_remove() { fi ### Remove server security setup ### - if [ -f ./scripts/secure_server.sh ]; then + if [ -f ./scripts/server_security.sh ]; then echo "" - . ./scripts/secure_server.sh --remove + . ./scripts/server_security.sh --remove fi ### Remove default user account ### @@ -409,9 +409,9 @@ function lemper_remove() { ### Remove unnecessary packages ### echo -e "\nCleaning up unnecessary packages..." - run apt-get autoremove -qq -y && \ - run apt-get autoclean -qq -y && \ - run apt-get clean -qq -y + run apt-get autoremove -q -y && \ + run apt-get autoclean -q -y && \ + run apt-get clean -q -y echo -e "\nLEMPer Stack has been removed completely." warning -e "\nDid you know? that we're so sad to see you leave :'( @@ -489,16 +489,16 @@ function git_clone_lemper() { if [[ -n $(command -v git) && ! -d LEMPer/.git ]]; then echo -e "\nCloning LEMPer from ${GIT_BRANCH} branch..." - git clone -q https://github.com/joglomedia/LEMPer.git + git clone https://github.com/joglomedia/LEMPer.git else echo -e "\nUpdating LEMPer from ${GIT_BRANCH} branch..." cd LEMPer - git pull -q + git pull cd .. fi cd LEMPer - git checkout -q "${GIT_BRANCH}" + git checkout "${GIT_BRANCH}" } ## @@ -557,7 +557,7 @@ function init_lemper_install() { shift NGINX_VERSION=${1} sed -i "s/INSTALL_NGINX=[a-zA-Z]*/INSTALL_NGINX=true/g" .env - sed -i "s/NGINX_VERSION=\"[0-9a-zA-Z._-\ ]*\"/NGINX_VERSION=\"${NGINX_VERSION}\"/g" .env + sed -i "s/NGINX_VERSION=\"[a-zA-Z0-9\ ._-]*\"/NGINX_VERSION=\"${NGINX_VERSION}\"/g" .env shift ;; # Usage: --with-nginx-installer @@ -567,7 +567,7 @@ function init_lemper_install() { NGINX_INSTALLER=${1} case "${NGINX_INSTALLER}" in source) - sed -i "s/NGINX_INSTALLER=\"[a-zA-Z.\ ]*\"/NGINX_INSTALLER=\"source\"/g" .env + sed -i "s/NGINX_INSTALLER=\"[a-zA-Z]*\"/NGINX_INSTALLER=\"source\"/g" .env ;; *) sed -i "s/NGINX_INSTALLER=\"[a-zA-Z]*\"/NGINX_INSTALLER=\"repo\"/g" .env @@ -580,7 +580,7 @@ function init_lemper_install() { shift NGINX_CUSTOMSSL_VERSION=${1-"openssl-1.1.1l"} sed -i "s/NGINX_WITH_CUSTOMSSL=[a-zA-Z]*/NGINX_WITH_CUSTOMSSL=true/g" .env - sed -i "s/NGINX_CUSTOMSSL_VERSION=\"[0-9a-zA-Z._-\ ]*\"/NGINX_CUSTOMSSL_VERSION=\"${NGINX_CUSTOMSSL_VERSION}\"/g" .env + sed -i "s/NGINX_CUSTOMSSL_VERSION=\"[a-zA-Z0-9\ ._-]*\"/NGINX_CUSTOMSSL_VERSION=\"${NGINX_CUSTOMSSL_VERSION}\"/g" .env shift ;; --with-nginx-lua) @@ -600,7 +600,7 @@ function init_lemper_install() { shift NGINX_PCRE_VERSION=${1-"8.45"} sed -i "s/NGINX_WITH_PCRE=[a-zA-Z]*/NGINX_WITH_PCRE=true/g" .env - sed -i "s/NGINX_PCRE_VERSION=\"[0-9a-zA-Z._-\ ]*\"/NGINX_PCRE_VERSION=\"${NGINX_PCRE_VERSION}\"/g" .env + sed -i "s/NGINX_PCRE_VERSION=\"[a-zA-Z0-9\ ._-]*\"/NGINX_PCRE_VERSION=\"${NGINX_PCRE_VERSION}\"/g" .env shift ;; --with-nginx-rtmp) @@ -613,7 +613,7 @@ function init_lemper_install() { shift PHP_VERSIONS=${1} sed -i "s/INSTALL_PHP=[a-zA-Z]*/INSTALL_PHP=true/g" .env - sed -i "s/PHP_VERSIONS=\"[0-9a-zA-Z._-\ ]*\"/PHP_VERSIONS=\"${PHP_VERSIONS}\"/g" .env + sed -i "s/PHP_VERSIONS=\"[a-zA-Z0-9\ ._-]*\"/PHP_VERSIONS=\"${PHP_VERSIONS}\"/g" .env shift ;; # Usage: --with-php-extensions= @@ -621,7 +621,7 @@ function init_lemper_install() { exit_if_optarg_is_empty "${1}" "${2}" shift PHP_EXTENSIONS=$( echo "${1}" | tr '[:upper:]' '[:lower:]' ) - sed -i "s/PHP_EXTENSIONS=\"[0-9a-zA-Z,._-\ ]*\"/PHP_EXTENSIONS=\"${PHP_EXTENSIONS}\"/g" .env + sed -i "s/PHP_EXTENSIONS=\"[0-9a-zA-Z\ ,._-]*\"/PHP_EXTENSIONS=\"${PHP_EXTENSIONS}\"/g" .env shift ;; # Usage: --with-php-loader @@ -673,7 +673,7 @@ function init_lemper_install() { ;; esac if [ -n "${MYSQL_SERVER_VER}" ]; then - sed -i "s/MYSQL_VERSION=\"[0-9a-zA-Z._-\ ]*\"/MYSQL_VERSION=\"${MYSQL_SERVER_VER}\"/g" .env + sed -i "s/MYSQL_VERSION=\"[a-zA-Z0-9\ ._-]*\"/MYSQL_VERSION=\"${MYSQL_SERVER_VER}\"/g" .env fi shift ;; @@ -683,7 +683,7 @@ function init_lemper_install() { shift MEMCACHED_VERSION=${1} sed -i "s/INSTALL_MEMCACHED=[a-zA-Z]*/INSTALL_MEMCACHED=true/g" .env - sed -i "s/MEMCACHED_VERSION=\"[0-9a-zA-Z._-\ ]*\"/MEMCACHED_VERSION=\"${MEMCACHED_VERSION}\"/g" .env + sed -i "s/MEMCACHED_VERSION=\"[a-zA-Z0-9\ ._-]*\"/MEMCACHED_VERSION=\"${MEMCACHED_VERSION}\"/g" .env shift ;; # Usage: --with-memcached-installer @@ -707,7 +707,7 @@ function init_lemper_install() { shift MONGODB_VERSION=${1} sed -i "s/INSTALL_MONGODB=[a-zA-Z]*/INSTALL_MONGODB=true/g" .env - sed -i "s/MONGODB_VERSION=\"[0-9a-zA-Z._-\ ]*\"/MONGODB_VERSION=\"${MONGODB_VERSION}\"/g" .env + sed -i "s/MONGODB_VERSION=\"[a-zA-Z0-9\ ._-]*\"/MONGODB_VERSION=\"${MONGODB_VERSION}\"/g" .env shift ;; # Usage: --with-mongodb-admin @@ -722,8 +722,8 @@ function init_lemper_install() { MONGODB_ADMIN_PASS="${MONGODB_ADMIN_AUTH[1]}" # Restore default IFS IFS=${_IFS} - sed -i "s/MONGODB_ADMIN_USER=\"[0-9a-zA-Z._-]*\"/MONGODB_ADMIN_USER=\"${MONGODB_ADMIN_USER}\"/g" .env - sed -i "s/MONGODB_ADMIN_PASSWORD=\"[0-9a-zA-Z._-\ ]*\"/MONGODB_ADMIN_PASSWORD=\"${MONGODB_ADMIN_PASS}\"/g" .env + sed -i "s/MONGODB_ADMIN_USER=\"[a-zA-Z0-9._-]*\"/MONGODB_ADMIN_USER=\"${MONGODB_ADMIN_USER}\"/g" .env + sed -i "s/MONGODB_ADMIN_PASSWORD=\"[a-zA-Z0-9\ ._-]*\"/MONGODB_ADMIN_PASSWORD=\"${MONGODB_ADMIN_PASS}\"/g" .env shift ;; # Usage: --with-redis @@ -733,7 +733,7 @@ function init_lemper_install() { REDIS_VERSION=${1} if [ -z "${REDIS_VERSION}" ]; then REDIS_VERSION="stable"; fi sed -i "s/INSTALL_REDIS=[a-zA-Z]*/INSTALL_REDIS=true/g" .env - sed -i "s/REDIS_VERSION=\"[0-9a-zA-Z._-\ ]*\"/REDIS_VERSION=\"${REDIS_VERSION}\"/g" .env + sed -i "s/REDIS_VERSION=\"[a-zA-Z0-9\ ._-]*\"/REDIS_VERSION=\"${REDIS_VERSION}\"/g" .env shift ;; # Usage: --with-redis-installer @@ -757,7 +757,7 @@ function init_lemper_install() { shift REDIS_PASSWORD=${1} sed -i "s/REDIS_REQUIRE_PASSWORD=[a-zA-Z]*/REDIS_REQUIRE_PASSWORD=true/g" .env - sed -i "s/REDIS_PASSWORD=\"[0-9a-zA-Z._-]*\"/REDIS_PASSWORD=\"${REDIS_PASSWORD}\"/g" .env + sed -i "s/REDIS_PASSWORD=\"[a-zA-Z0-9._-](.*)\"/REDIS_PASSWORD=\"${REDIS_PASSWORD}\"/g" .env shift ;; --with-ftp-server) @@ -781,11 +781,11 @@ function init_lemper_install() { ;; *) echo "Selected MySQL Server: ${FTP_SERVER_NAME} is not supported, fallback to VSFTPD." - sed -i "s/FTP_SERVER_NAME=\"[0-9a-zA-Z._-]*\"/FTP_SERVER_NAME=\"vsftpd\"/g" .env + sed -i "s/FTP_SERVER_NAME=\"[a-zA-Z0-9._-]*\"/FTP_SERVER_NAME=\"vsftpd\"/g" .env ;; esac if [ -n "${FTP_SERVER_VER}" ]; then - sed -i "s/FTP_SERVER_VERSION=\"[0-9a-zA-Z._-\ ]*\"/FTP_SERVER_VERSION=\"${FTP_SERVER_VER}\"/g" .env + sed -i "s/FTP_SERVER_VERSION=\"[a-zA-Z0-9\ ._-]*\"/FTP_SERVER_VERSION=\"${FTP_SERVER_VER}\"/g" .env fi shift ;; @@ -797,7 +797,7 @@ function init_lemper_install() { exit_if_optarg_is_empty "${1}" "${2}" shift MAIL_SENDER_DOMAIN=${1} - sed -i "s/SENDER_DOMAIN=\"[0-9a-zA-Z._-@\ ]*\"/SENDER_DOMAIN=\"${MAIL_SENDER_DOMAIN}\"/g" .env + sed -i "s/SENDER_DOMAIN=\"(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]\"/SENDER_DOMAIN=\"${MAIL_SENDER_DOMAIN}\"/g" .env shift ;; --with-ssh-port) @@ -820,14 +820,14 @@ function init_lemper_install() { exit_if_optarg_is_empty "${1}" "${2}" shift SSH_PUB_KEY=${1} - sed -i "s/SSH_PUB_KEY=\"[0-9a-zA-Z._-]*\"/SSH_PUB_KEY=\"${SSH_PUB_KEY}\"/g" .env + sed -i "s/SSH_PUB_KEY=\"[a-zA-Z0-9._-](.*)\"/SSH_PUB_KEY=\"${SSH_PUB_KEY}\"/g" .env shift ;; -e | --admin-email) exit_if_optarg_is_empty "${1}" "${2}" shift LEMPER_ADMIN_EMAIL=${1} - sed -i "s/LEMPER_ADMIN_EMAIL=\"[0-9a-zA-Z._-@\ ]*\"/LEMPER_ADMIN_EMAIL=\"${LEMPER_ADMIN_EMAIL}\"/g" .env + sed -i "s/LEMPER_ADMIN_EMAIL=\"[a-zA-Z0-9._-](.*)\@[a-zA-Z0-9._-](.*)\"/LEMPER_ADMIN_EMAIL=\"${LEMPER_ADMIN_EMAIL}\"/g" .env shift ;; -B | --fix-broken-install) @@ -861,7 +861,7 @@ function init_lemper_install() { exit_if_optarg_is_empty "${1}" "${2}" shift SERVER_HOSTNAME=${1} - sed -i "s/SERVER_HOSTNAME=\"[a-zA-Z0-9._-]*\"/SERVER_HOSTNAME=\"${SERVER_HOSTNAME}\"/g" .env + sed -i "s/SERVER_HOSTNAME=\"(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]\"/SERVER_HOSTNAME=\"${SERVER_HOSTNAME}\"/g" .env shift ;; -i | --ipv4) @@ -893,7 +893,7 @@ function init_lemper_install() { # Include helper functions. if [[ "$(type -t run)" != "function" ]]; then - . ./scripts/helper.sh + . ./scripts/utils.sh fi # Make sure only supported distribution can run this installer script. diff --git a/lib/lemper-create.sh b/lib/lemper-create.sh index 44267077..1bc6a1c7 100755 --- a/lib/lemper-create.sh +++ b/lib/lemper-create.sh @@ -207,7 +207,7 @@ server { } ## PHP-FPM status monitoring - location ~ ^/(status|ping)$ { + location ~ ^/php-fpm_(status|ping)$ { include /etc/nginx/fastcgi_params; fastcgi_pass unix:/run/php/php${PHP_VERSION}-fpm.${USERNAME}.sock; @@ -320,7 +320,7 @@ server { } ## PHP-FPM status monitoring - location ~ ^/(status|ping)$ { + location ~ ^/php-fpm_(status|ping)$ { include /etc/nginx/fastcgi_params; fastcgi_pass unix:/run/php/php${PHP_VERSION}-fpm.${USERNAME}.sock; @@ -434,7 +434,7 @@ server { } ## PHP-FPM status monitoring - location ~ ^/(status|ping)$ { + location ~ ^/php-fpm_(status|ping)$ { include /etc/nginx/fastcgi_params; fastcgi_pass unix:/run/php/php${PHP_VERSION}-fpm.${USERNAME}.sock; @@ -551,7 +551,7 @@ server { } ## PHP-FPM status monitoring - location ~ ^/(status|ping)$ { + location ~ ^/php-fpm_(status|ping)$ { include /etc/nginx/fastcgi_params; fastcgi_pass unix:/run/php/php${PHP_VERSION}-fpm.${USERNAME}.sock; @@ -694,8 +694,8 @@ pm.max_spare_servers = 20 pm.process_idle_timeout = 30s pm.max_requests = 500 -pm.status_path = /status -ping.path = /ping +pm.status_path = /php-fpm_status +ping.path = /php-fpm_ping slowlog = /home/${POOLNAME}/logs/php/php${PHPv}-fpm_slow.log request_slowlog_timeout = 10s @@ -713,11 +713,10 @@ php_admin_value[open_basedir] = /home/${POOLNAME} ;php_admin_value[disable_functions] = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,exec,passthru,popen,proc_open,shell_exec,system ;php_admin_value[disable_classes] = php_admin_flag[log_errors] = on -php_admin_value[error_log] = /home/${POOLNAME}/logs/php/php${PHPv}-fpm.log +php_admin_value[error_log] = /home/${POOLNAME}/logs/php/php8.0-fpm_error.log php_admin_value[sys_temp_dir] = /home/${POOLNAME}/.lemper/tmp php_admin_value[upload_tmp_dir] = /home/${POOLNAME}/.lemper/tmp ;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com -php_admin_value[opcache.file_cache] = /home/${POOLNAME}/.lemper/tmp/php_opcache ; Configuration below can be overwritten from PHP call 'ini_set'. php_flag[short_open_tag] = off @@ -733,7 +732,10 @@ php_value[error_reporting] = E_ALL & ~E_DEPRECATED & ~E_STRICT php_flag[display_errors] = on php_flag[cgi.fix_pathinfo] = 1 php_value[date.timezone] = UTC -php_value[session.save_path] = /home/${POOLNAME}/.lemper/tmp/php_sessions +php_value[session.save_handler] = files +php_value[session.save_path] = /home/${POOLNAME}/.lemper/php/sessions +php_value[soap.wsdl_cache_dir] = /home/${POOLNAME}/.lemper/php/wsdlcache +php_value[opcache.file_cache] = /home/${POOLNAME}/.lemper/php/opcache EOL } @@ -838,11 +840,12 @@ function install_wordpress() { if [[ "${INSTALL_APP}" == true ]]; then # Check WordPress install directory. if [ ! -f "${WEBROOT}/wp-includes/class-wp.php" ]; then - if ! command -v wp-cli &> /dev/null; then + if [[ -z $(command -v "wp-cli") ]]; then info "WP CLI command not found, trying to install it first." - run wget -q https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar \ + run wget https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar \ -O /usr/local/bin/wp-cli && \ - run chmod ugo+x /usr/local/bin/wp-cli + run chmod ugo+x /usr/local/bin/wp-cli && \ + run ln -sf /usr/local/bin/wp-cli /usr/bin/wp-cli fi # Download WordPress skeleton files. @@ -887,7 +890,7 @@ function init_lemper_create() { SERVERNAME="" WEBROOT="" FRAMEWORK="default" - PHP_VERSION="7.4" + PHP_VERSION="8.0" INSTALL_APP=false WPMS_SUBDOMAINS="" ENABLE_FASTCGI_CACHE=false @@ -1042,12 +1045,12 @@ function init_lemper_create() { fail "User account '${USERNAME}' does not exist. Please add new account first! Aborting..." fi - # PHP Commands. - PHP_BIN=$(command -v "php${PHP_VERSION}") - PHP_COMPOSER_BIN=$(command -v composer) + # Check PHP runtime version is exists. + if [[ -n $(command -v "php${PHP_VERSION}") && -d "/etc/php/${PHP_VERSION}/fpm" ]]; then + # PHP runtime commands. + PHP_BIN=$(command -v "php${PHP_VERSION}") + PHP_COMPOSER_BIN=$(command -v "composer") - # Check PHP fpm version is exists. - if [[ -n $(command -v "php-fpm${PHP_VERSION}") && -d "/etc/php/${PHP_VERSION}/fpm" ]]; then # Additional check - if FPM user's pool already exist. if [[ ! -f "/etc/php/${PHP_VERSION}/fpm/pool.d/${USERNAME}.conf" ]]; then info "The PHP${PHP_VERSION} FPM pool configuration for user ${USERNAME} doesn't exist." @@ -1059,8 +1062,9 @@ function init_lemper_create() { # Create default directories. run mkdir -p "/home/${USERNAME}/.lemper/tmp" - run mkdir -p "/home/${USERNAME}/.lemper/tmp/php_opcache" - run mkdir -p "/home/${USERNAME}/.lemper/tmp/php_sessions" + run mkdir -p "/home/${USERNAME}/.lemper/php/opcache" + run mkdir -p "/home/${USERNAME}/.lemper/php/sessions" + run mkdir -p "/home/${USERNAME}/.lemper/php/wsdlcache" run mkdir -p "/home/${USERNAME}/cgi-bin" run chown -hR "${USERNAME}:${USERNAME}" "/home/${USERNAME}/.lemper/" "/home/${USERNAME}/cgi-bin/" @@ -1121,7 +1125,7 @@ function init_lemper_create() { if [[ -n "${PHP_COMPOSER_BIN}" ]]; then run "${PHP_BIN}" "${PHP_COMPOSER_BIN}" create-project --prefer-source codeigniter4/appstarter "${WEBROOT}" else - run git clone -q --depth=1 --branch=master "https://github.com/codeigniter4/appstarter.git" "${WEBROOT}" || \ + run git clone --depth=1 --branch=master "https://github.com/codeigniter4/appstarter.git" "${WEBROOT}" || \ error "Something went wrong while downloading CodeIgniter v4 files." fi else @@ -1154,7 +1158,7 @@ function init_lemper_create() { echo "Downloading Drupal latest skeleton files..." if curl -sLI https://www.drupal.org/download-latest/zip | grep -q "HTTP/[.12]* [2].."; then - run wget -q https://www.drupal.org/download-latest/zip \ + run wget https://www.drupal.org/download-latest/zip \ -O "${TMPDIR}/drupal.zip" && \ run unzip -q "${TMPDIR}/drupal.zip" -d "${TMPDIR}" && \ run rsync -rq ${TMPDIR}/drupal-*/ "${WEBROOT}" && \ @@ -1195,7 +1199,7 @@ function init_lemper_create() { run sudo -u "${USERNAME}" -i -- "${PHP_BIN}" "${PHP_COMPOSER_BIN}" \ create-project --prefer-dist "laravel/${FRAMEWORK}" "${WEBROOT}" else - run git clone -q --depth=1 --branch=master "https://github.com/laravel/${FRAMEWORK}.git" "${WEBROOT}" || \ + run git clone --depth=1 --branch=master "https://github.com/laravel/${FRAMEWORK}.git" "${WEBROOT}" || \ error "Something went wrong while downloading ${FRAMEWORK^} files." fi @@ -1249,13 +1253,12 @@ function init_lemper_create() { ;; esac - PHP_PHALCON_BIN=$(command -v phalcon) - - if [[ -n "${PHP_PHALCON_BIN}" ]]; then + if [[ -n $(command -v phalcon) ]]; then + PHP_PHALCON_BIN=$(command -v phalcon) run sudo -u "${USERNAME}" -i -- "${PHP_PHALCON_BIN}" project \ --name="${SERVERNAME}" --type="${PHALCON_TYPE}" --directory="/home/${USERNAME}/webapps" else - run git clone -q --depth=1 --branch=master "https://github.com/joglomedia/${FRAMEWORK}-skeleton.git" "${WEBROOT}" || \ + run git clone --depth=1 --branch=master "https://github.com/joglomedia/${FRAMEWORK}-skeleton.git" "${WEBROOT}" || \ error "Something went wrong while downloading ${FRAMEWORK} files." fi else @@ -1295,7 +1298,7 @@ function init_lemper_create() { run composer create-project --prefer-dist symfony/website-skeleton "${WEBROOT}" else warning "Symfony CLI not found, trying to install it first..." - run wget -q https://get.symfony.com/cli/installer -O - | bash + run wget https://get.symfony.com/cli/installer -O - | bash if [[ -f "${HOME}/.symfony/bin/symfony" ]]; then run cp -f "${HOME}/.symfony/bin/symfony" /usr/local/bin/symfony @@ -1381,14 +1384,14 @@ function init_lemper_create() { if command -v wp-cli &> /dev/null; then run sudo -u "${USERNAME}" -i -- wp-cli core multisite-install "${WPMS_SUBDOMAINS}" --url="${SERVERNAME}" \ - --title="WordPress Multi-site Managed by LEMPer" --admin_user="${APP_ADMIN_USER}" \ + --title="WordPress Multisite Managed by LEMPer Stack" --admin_user="${APP_ADMIN_USER}" \ --admin_password="${APP_ADMIN_PASS}" --admin_email="${APP_ADMIN_EMAIL}" --path="${WEBROOT}" && \ run sudo -u "${USERNAME}" -i -- wp-cli plugin install \ akismet autoptimize cache-enabler classic-editor nginx-helper redis-cache --activate-network --path="${WEBROOT}" fi # Mercator domain mapping. - run git clone --depth=1 --branch=master -q https://github.com/humanmade/Mercator.git "${WEBROOT}/wp-content/mu-plugins/mercator" && \ + run git clone --depth=1 --branch=master https://github.com/humanmade/Mercator.git "${WEBROOT}/wp-content/mu-plugins/mercator" && \ cat > "${WEBROOT}/wp-content/sunrise.php" </dev/null > /dev/null; then - run systemctl reload nginx + run systemctl restart nginx echo "Nginx server reloaded with new configuration." else info "Something went wrong with Nginx configuration." diff --git a/lib/lemper-manage.sh b/lib/lemper-manage.sh index eced2309..8a149f45 100755 --- a/lib/lemper-manage.sh +++ b/lib/lemper-manage.sh @@ -222,7 +222,7 @@ function remove_vhost() { echo "No database found." fi - echo "+----------------------+" + echo "+-------------------------------+" until [[ "${DBNAME}" != "" ]]; do read -rp "MySQL Database: " -e DBNAME @@ -434,49 +434,70 @@ function enable_ssl() { local DOMAIN=${1} verify_vhost "${DOMAIN}" - #TODO: Generate Let's Encrypt SSL using Certbot. - if [ ! -d "/etc/letsencrypt/live/${DOMAIN}" ]; then - echo "Certbot: Get Let's Encrypt certificate..." - - # Get web root path from vhost config, first. - local WEBROOT && \ - WEBROOT=$(grep -wE "set\ \\\$root_path" "/etc/nginx/sites-available/${DOMAIN}.conf" | awk '{print $3}' | cut -d'"' -f2) - - # Certbot get Let's Encrypt SSL. - if [[ -n $(command -v certbot) ]]; then - # Is it wildcard vhost? - if grep -qwE "${DOMAIN}\ \*.${DOMAIN}" "/etc/nginx/sites-available/${DOMAIN}.conf"; then - run certbot certonly --manual --manual-public-ip-logging-ok --preferred-challenges dns \ - --server https://acme-v02.api.letsencrypt.org/directory --agree-tos \ - --webroot-path="${WEBROOT}" -d "${DOMAIN}" -d "*.${DOMAIN}" + if [[ ! -f "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" ]]; then + if [[ "${ENVIRONMENT}" == prod* ]]; then + echo "Certbot: Get Let's Encrypt certificate..." + + # Get web root path from vhost config, first. + local WEBROOT && \ + WEBROOT=$(grep -wE "set\ \\\$root_path" "/etc/nginx/sites-available/${DOMAIN}.conf" | awk '{print $3}' | cut -d'"' -f2) + + # Certbot get Let's Encrypt SSL. + if [[ -n $(command -v certbot) ]]; then + # Is it wildcard vhost? + if grep -qwE "${DOMAIN}\ \*.${DOMAIN}" "/etc/nginx/sites-available/${DOMAIN}.conf"; then + run certbot certonly --manual --manual-public-ip-logging-ok --preferred-challenges dns \ + --server https://acme-v02.api.letsencrypt.org/directory --agree-tos \ + --webroot-path="${WEBROOT}" -d "${DOMAIN}" -d "*.${DOMAIN}" + else + run certbot certonly --webroot --preferred-challenges http --agree-tos \ + --webroot-path="${WEBROOT}" -d "${DOMAIN}" + fi else - run certbot certonly --webroot --preferred-challenges http --agree-tos \ - --webroot-path="${WEBROOT}" -d "${DOMAIN}" + fail "Certbot executable binary not found. Install it first!" fi else - fail "Certbot executable binary not found. Install it first!" + # Self-signed SSL. + echo "Self-signed SSL: Generate SSL certificate..." + + generate_selfsigned_ssl "${DOMAIN}" + + if [ ! -d "/etc/letsencrypt/live/${DOMAIN}" ]; then + run mkdir -p "/etc/letsencrypt/live/${DOMAIN}" + run chmod 0700 /etc/letsencrypt/live + fi + + run ln -sf "/etc/lemper/ssl/${DOMAIN}/cert.pem" "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" && \ + run ln -sf "/etc/lemper/ssl/${DOMAIN}/privkey.pem" "/etc/letsencrypt/live/${DOMAIN}/privkey.pem" fi - fi - # Generate Diffie-Hellman parameters. - if [ ! -f /etc/nginx/ssl/dhparam-2048.pem ]; then - echo "Generating Diffie-Hellman parameters for enhanced HTTPS/SSL security." + # Generate Diffie-Hellman parameters. + if [ ! -f /etc/nginx/ssl/dhparam-2048.pem ]; then + echo "Generating Diffie-Hellman parameters for enhanced HTTPS/SSL security." - run openssl dhparam -out /etc/nginx/ssl/dhparam-2048.pem 2048 - #run openssl dhparam -out /etc/nginx/ssl/dhparam-4096.pem 4096 + run openssl dhparam -out /etc/nginx/ssl/dhparam-2048.pem 2048 + #run openssl dhparam -out /etc/nginx/ssl/dhparam-4096.pem 4096 + fi + else + info "SSL certificates is already exists for ${DOMAIN}." fi # Update vhost config. if [[ "${DRYRUN}" != true ]]; then # Ensure there is no HTTPS enabled server block. - if ! grep -qwE "^\ listen\ 443 ssl http2" "/etc/nginx/sites-available/${DOMAIN}.conf"; then + if ! grep -qwE "^\ listen\ (\b[0-9]{1,3}\.){3}[0-9]{1,3}\b:443\ ssl\ http2" "/etc/nginx/sites-available/${DOMAIN}.conf"; then # Make backup first. run cp -f "/etc/nginx/sites-available/${DOMAIN}.conf" "/etc/nginx/sites-available/${DOMAIN}.nonssl-conf" # Change listening port to 443. - run sed -i "s/listen\ 80/listen\ 443 ssl http2/g" "/etc/nginx/sites-available/${DOMAIN}.conf" - run sed -i "s/listen\ \[::\]:80/listen\ \[::\]:443 ssl http2/g" "/etc/nginx/sites-available/${DOMAIN}.conf" + if grep -qwE "^\ listen\ (\b[0-9]{1,3}\.){3}[0-9]{1,3}\b:80" "/etc/nginx/sites-available/${DOMAIN}.conf"; then + run sed -i "s/\:80/\:443 ssl http2/g" "/etc/nginx/sites-available/${DOMAIN}.conf" + else + run sed -i "s/listen\ 80/listen\ 443\ ssl\ http2/g" "/etc/nginx/sites-available/${DOMAIN}.conf" + fi + + run sed -i "s/listen\ \[::\]:80/listen\ \[::\]:443\ ssl\ http2/g" "/etc/nginx/sites-available/${DOMAIN}.conf" # Enable SSL configs. run sed -i "s/#ssl_certificate/ssl_certificate/g" "/etc/nginx/sites-available/${DOMAIN}.conf" @@ -539,15 +560,17 @@ function disable_ssl() { run unlink "/etc/nginx/sites-enabled/${DOMAIN}.conf" # Backup ssl config. + [[ -f "/etc/nginx/sites-available/${DOMAIN}.conf" ]] && \ run mv "/etc/nginx/sites-available/${DOMAIN}.conf" "/etc/nginx/sites-available/${DOMAIN}.ssl-conf" # Restore non ssl config. + [[ -f "/etc/nginx/sites-available/${DOMAIN}.nonssl-conf" ]] && \ run mv "/etc/nginx/sites-available/${DOMAIN}.nonssl-conf" "/etc/nginx/sites-available/${DOMAIN}.conf" - run ln -s "/etc/nginx/sites-available/${DOMAIN}.conf" "/etc/nginx/sites-enabled/${DOMAIN}.conf" + run ln -sf "/etc/nginx/sites-available/${DOMAIN}.conf" "/etc/nginx/sites-enabled/${DOMAIN}.conf" reload_nginx else - error "Something went wrong. You still could disable HTTPS manually." + error "It seems that SSL is not yet enabled." fi else info "Disabling HTTPS config in dry run mode." @@ -572,15 +595,15 @@ function remove_ssl() { run unlink "/etc/nginx/sites-enabled/${DOMAIN}.conf" # Backup ssl config. + [[ -f "/etc/nginx/sites-available/${DOMAIN}.conf" ]] && \ run mv "/etc/nginx/sites-available/${DOMAIN}.conf" "/etc/nginx/sites-available/${DOMAIN}.ssl-conf" # Restore non ssl config. + [[ -f "/etc/nginx/sites-available/${DOMAIN}.nonssl-conf" ]] && \ run mv "/etc/nginx/sites-available/${DOMAIN}.nonssl-conf" "/etc/nginx/sites-available/${DOMAIN}.conf" - run ln -s "/etc/nginx/sites-available/${DOMAIN}.conf" "/etc/nginx/sites-enabled/${DOMAIN}.conf" - - reload_nginx + run ln -sf "/etc/nginx/sites-available/${DOMAIN}.conf" "/etc/nginx/sites-enabled/${DOMAIN}.conf" else - error "Something went wrong. You still could disable HTTPS manually." + error "It seems that SSL is not yet enabled." fi # Remove SSL config. @@ -591,10 +614,28 @@ function remove_ssl() { # Remove SSL cert. echo "Removing SSL certificate..." - if [[ -n $(command -v certbot) ]]; then - run certbot delete --cert-name "${DOMAIN}" + if [[ "${ENVIRONMENT}" == prod* ]]; then + if [[ -n $(command -v certbot) ]]; then + run certbot delete --cert-name "${DOMAIN}" + else + fail "Certbot executable binary not found. Install it first!" + fi else - fail "Certbot executable binary not found. Install it first!" + if [ -f "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" ]; then + run unlink "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" + fi + + if [ -f "/etc/letsencrypt/live/${DOMAIN}/privkey.pem" ]; then + run unlink "/etc/letsencrypt/live/${DOMAIN}/privkey.pem" + fi + + if [ -d "/etc/letsencrypt/live/${DOMAIN}/" ]; then + run rm -rf "/etc/letsencrypt/live/${DOMAIN}/" + fi + + if [ -d "/etc/lemper/ssl/${DOMAIN}/" ]; then + run rm -rf "/etc/lemper/ssl/${DOMAIN}/" + fi fi reload_nginx @@ -611,12 +652,11 @@ function renew_ssl() { local DOMAIN=${1} verify_vhost "${DOMAIN}" - # Update vhost config. - if [[ "${DRYRUN}" != true ]]; then - echo "Renew SSL certificate..." + echo "Renew SSL certificate..." - # Renew Let's Encrypt SSL using Certbot. - if [ -d "/etc/letsencrypt/live/${DOMAIN}" ]; then + # Renew Let's Encrypt SSL using Certbot. + if [[ -d "/etc/letsencrypt/live/${DOMAIN}" ]]; then + if [[ "${ENVIRONMENT}" == prod* ]]; then echo "Certbot: Renew Let's Encrypt certificate..." # Get web root path from vhost config, first. @@ -637,13 +677,22 @@ function renew_ssl() { fail "Certbot executable binary not found. Install it first!" fi else - info "Certificate file not found. May be your SSL is not activated yet." - fi + # Re-generate self-signed certs. + generate_selfsigned_ssl "${DOMAIN}" + + if [[ ! -d "/etc/letsencrypt/live/${DOMAIN}" ]]; then + run mkdir -p "/etc/letsencrypt/live/${DOMAIN}" + run chmod 0700 /etc/letsencrypt/live + fi - reload_nginx + run ln -sf "/etc/lemper/ssl/${DOMAIN}/cert.pem" "/etc/letsencrypt/live/${DOMAIN}/fullchain.pem" + run ln -sf "/etc/lemper/ssl/${DOMAIN}/privkey.pem" "/etc/letsencrypt/live/${DOMAIN}/privkey.pem" + fi else - info "Renew SSL certificate in dry run mode." + info "Certificate file not found. May be your SSL is not activated yet." fi + + reload_nginx } ## @@ -775,7 +824,7 @@ function reload_nginx() { else error "Configuration couldn't be validated. Please correct the error below:"; nginx -t - [[ ${EXIT} ]] && exit 1 + exit 1 fi # Nginx service dead? Try to start it. else @@ -801,6 +850,90 @@ function reload_nginx() { fi } +## +# Generate sel-signed certificate. +## +function generate_selfsigned_ssl() { + # Verify user input hostname (domain name). + local DOMAIN=${1} + local SERVER_IP=${2:-$(get_ip_public)} + verify_vhost "${DOMAIN}" + + [ ! -d "/etc/lemper/ssl/${DOMAIN}" ] && run mkdir -p "/etc/lemper/ssl/${DOMAIN}" + + run sed -i "s|^CN\ =\ .*|CN\ =\ ${DOMAIN}|g" /etc/lemper/ssl/csr.conf && \ + run sed -i "s|^DNS\.1\ =\ .*|DNS\.1\ =\ ${DOMAIN}|g" /etc/lemper/ssl/csr.conf && \ + run sed -i "s|^DNS\.2\ =\ .*|DNS\.2\ =\ www\.${DOMAIN}|g" /etc/lemper/ssl/csr.conf && \ + run sed -r -i "s|^IP.1\ =\ (\b[0-9]{1,3}\.){3}[0-9]{1,3}\b$|IP.1\ =\ ${SERVER_IP}|g" /etc/lemper/ssl/csr.conf && \ + run sed -r -i "s|^IP.2\ =\ (\b[0-9]{1,3}\.){3}[0-9]{1,3}\b$|IP.2\ =\ ${SERVER_IP}|g" /etc/lemper/ssl/csr.conf && \ + run sed -i "s|^DNS\.1\ =\ .*|DNS\.1\ =\ ${DOMAIN}|g" /etc/lemper/ssl/cert.conf + + # Create Certificate Authority (CA). + if [[ ! -f /etc/lemper/ssl/lemperCA.key || ! -f /etc/lemper/ssl/lemperCA.crt ]]; then + run openssl req -x509 -sha256 -days 365000 -nodes -newkey rsa:2048 \ + -keyout "/etc/lemper/ssl/${DOMAIN}-ca.key" -out "/etc/lemper/ssl/${DOMAIN}-ca.crt" \ + -config /etc/lemper/ssl/ca.conf + #-subj "/CN=${HOSTNAME}/C=ID/L=Jakarta" + + CA_KEY_FILE="/etc/lemper/ssl/${DOMAIN}-ca.key" + CA_CRT_FILE="/etc/lemper/ssl/${DOMAIN}-ca.crt" + else + CA_KEY_FILE="/etc/lemper/ssl/lemperCA.key" + CA_CRT_FILE="/etc/lemper/ssl/lemperCA.crt" + fi + + # Create Server Private Key. + run openssl genrsa -out "/etc/lemper/ssl/${DOMAIN}/privkey.pem" 2048 && \ + + # Generate Certificate Signing Request (CSR) using Server Private Key. + run openssl req -new -key "/etc/lemper/ssl/${DOMAIN}/privkey.pem" \ + -out "/etc/lemper/ssl/${DOMAIN}/csr.csr" -config /etc/lemper/ssl/csr.conf + + # Generate SSL certificate With self signed CA. + run openssl x509 -req -sha256 -days 365000 -CAcreateserial \ + -CA "${CA_CRT_FILE}" -CAkey "${CA_KEY_FILE}" \ + -in "/etc/lemper/ssl/${DOMAIN}/csr.csr" -out "/etc/lemper/ssl/${DOMAIN}/cert.pem" \ + -extfile /etc/lemper/ssl/cert.conf + + # Create chain file. + run cat "/etc/lemper/ssl/${DOMAIN}/cert.pem" "${CA_CRT_FILE}" >> \ + "/etc/lemper/ssl/${DOMAIN}/chain.pem" + + if [ -f "/etc/lemper/ssl/${DOMAIN}/cert.pem" ]; then + success "Self-signed SSL certificate has been successfully generated." + else + fail "An error occurred when generating self-signed SSL certificate." + fi +} + +## +# Get server private IP Address. +## +function get_ip_private() { + local SERVER_IP_PRIVATE && \ + SERVER_IP_PRIVATE=$(ip addr | grep 'inet' | grep -v inet6 | \ + grep -vE '127\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | \ + grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -1) + + echo "${SERVER_IP_PRIVATE}" +} + +## +# Get server public IP Address. +## +function get_ip_public() { + local SERVER_IP_PRIVATE && SERVER_IP_PRIVATE=$(get_ip_private) + local SERVER_IP_PUBLIC && \ + SERVER_IP_PUBLIC=$(curl -sk --connect-timeout 10 --retry 3 --retry-delay 0 http://ipecho.net/plain) + + # Ugly hack to detect aws-lightsail public IP address. + if [[ "${SERVER_IP_PRIVATE}" == "${SERVER_IP_PUBLIC}" ]]; then + echo "${SERVER_IP_PRIVATE}" + else + echo "${SERVER_IP_PUBLIC}" + fi +} + ## # Main Manage CLI Wrapper diff --git a/lib/lemper-sslgen.sh b/lib/lemper-sslgen.sh new file mode 100755 index 00000000..5968abe7 --- /dev/null +++ b/lib/lemper-sslgen.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash + +# +-------------------------------------------------------------------------+ +# | Lemper Manage - Simple LEMP Virtual Host Manager | +# +-------------------------------------------------------------------------+ +# | Copyright (c) 2014-2022 MasEDI.Net (https://masedi.net/lemper) | +# +-------------------------------------------------------------------------+ +# | This source file is subject to the GNU General Public License | +# | that is bundled with this package in the file LICENSE.md. | +# | | +# | If you did not receive a copy of the license and are unable to | +# | obtain it through the world-wide-web, please send an email | +# | to license@lemper.cloud so we can send you a copy immediately. | +# +-------------------------------------------------------------------------+ +# | Authors: Edi Septriyanto | +# +-------------------------------------------------------------------------+ + +# Version control. +#PROG_NAME=$(basename "$0") +#PROG_VER="2.x.x" +#CMD_PARENT="lemper-cli" +#CMD_NAME="sslgen" + +# Make sure only root can access and not direct access. +if ! declare -F "requires_root" &>/dev/null; then + echo "Direct access to this script is not permitted." + exit 1 +fi + +# Usage: sslgen +function sslgen() { + DOMAIN=${1} + SERVER_IP=${2:-$(hostname -I | awk '{print $1}')} + KEY_HASH_LENGTH=2048 + + if [ -z "${DOMAIN}" ]; then + echo "Please specify domain name." + exit 1 + fi + + if [ ! -d "/etc/lemper/ssl/${DOMAIN}" ]; then + mkdir -p "/etc/lemper/ssl/${DOMAIN}" + fi + + # Self-signed certificate for local development environment. + sed -i "s|^CN\ =\ .*|CN\ =\ ${DOMAIN}|g" /etc/lemper/ssl/ca.conf && \ + sed -i "s|^CN\ =\ .*|CN\ =\ ${DOMAIN}|g" /etc/lemper/ssl/csr.conf && \ + sed -i "s|^DNS\.1\ =\ .*|DNS\.1\ =\ ${DOMAIN}|g" /etc/lemper/ssl/csr.conf && \ + sed -i "s|^DNS\.2\ =\ .*|DNS\.2\ =\ www\.${DOMAIN}|g" /etc/lemper/ssl/csr.conf && \ + sed -r -i "s|^IP.1\ =\ (\b[0-9]{1,3}\.){3}[0-9]{1,3}\b$|IP.1\ =\ ${SERVER_IP}|g" /etc/lemper/ssl/csr.conf && \ + sed -r -i "s|^IP.2\ =\ (\b[0-9]{1,3}\.){3}[0-9]{1,3}\b$|IP.2\ =\ ${SERVER_IP}|g" /etc/lemper/ssl/csr.conf && \ + sed -i "s|^DNS\.1\ =\ .*|DNS\.1\ =\ ${DOMAIN}|g" /etc/lemper/ssl/cert.conf + + # Create Certificate Authority (CA). + if [[ ! -f /etc/lemper/ssl/lemperCA.key || ! -f /etc/lemper/ssl/lemperCA.crt ]]; then + run openssl req -x509 -sha256 -days 365000 -nodes -newkey "rsa:${KEY_HASH_LENGTH}" \ + -keyout "/etc/lemper/ssl/${DOMAIN}-ca.key" -out "/etc/lemper/ssl/${DOMAIN}-ca.crt" \ + -config /etc/lemper/ssl/ca.conf + + CA_KEY_FILE="/etc/lemper/ssl/${DOMAIN}-ca.key" + CA_CRT_FILE="/etc/lemper/ssl/${DOMAIN}-ca.crt" + else + CA_KEY_FILE="/etc/lemper/ssl/lemperCA.key" + CA_CRT_FILE="/etc/lemper/ssl/lemperCA.crt" + fi + + # Create Server Private Key. + run openssl genrsa -out "/etc/lemper/ssl/${DOMAIN}/privkey.pem" "${KEY_HASH_LENGTH}" && \ + + # Generate Certificate Signing Request (CSR) using Server Private Key. + run openssl req -new -key "/etc/lemper/ssl/${DOMAIN}/privkey.pem" \ + -out "/etc/lemper/ssl/${DOMAIN}/csr.csr" -config /etc/lemper/ssl/csr.conf + + # Generate SSL certificate With self signed CA. + run openssl x509 -req -sha256 -days 365000 -CAcreateserial \ + -CA "${CA_CRT_FILE}" -CAkey "${CA_KEY_FILE}" \ + -in "/etc/lemper/ssl/${DOMAIN}/csr.csr" -out "/etc/lemper/ssl/${DOMAIN}/cert.pem" \ + -extfile /etc/lemper/ssl/cert.conf + + # Create chain file. + run cat "/etc/lemper/ssl/${DOMAIN}/cert.pem" "${CA_CRT_FILE}" >> \ + "/etc/lemper/ssl/${DOMAIN}/fullchain.pem" + + if [ -f "/etc/lemper/ssl/${DOMAIN}/cert.pem" ]; then + echo "Self-signed SSL certificate has been successfully generated." + echo "Certificate file: /etc/lemper/ssl/${DOMAIN}/cert.pem" + echo "Private key file: /etc/lemper/ssl/${DOMAIN}/privkey.pem" + exit 0 + else + echo "An error occurred when generating self-signed SSL certificate." + exit 1 + fi +} + +# Start running things from a call at the end so if this script is executed +# after a partial download it doesn't do anything. +sslgen "$@" diff --git a/remove.sh b/remove.sh index aa08042e..cb4ff758 100755 --- a/remove.sh +++ b/remove.sh @@ -33,7 +33,7 @@ BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # Include helper functions. if [[ "$(type -t run)" != "function" ]]; then - . "${BASE_DIR}/scripts/helper.sh" + . "${BASE_DIR}/scripts/utils.sh" fi # Make sure only root can run this installer script. @@ -58,7 +58,7 @@ fi # Fix broken install, first? if [[ "${FIX_BROKEN_INSTALL}" == true ]]; then run dpkg --configure -a - run apt-get install -qq -y --fix-broken + run apt-get install -q -y --fix-broken fi ### Remove Nginx ### @@ -123,9 +123,9 @@ if [ -f ./scripts/remove_fail2ban.sh ]; then fi ### Remove server security setup ### -if [ -f ./scripts/secure_server.sh ]; then +if [ -f ./scripts/server_security.sh ]; then echo "" - . ./scripts/secure_server.sh --remove + . ./scripts/server_security.sh --remove fi ### Remove default user account ### @@ -175,9 +175,9 @@ fi ### Remove unnecessary packages ### echo -e "\nCleaning up unnecessary packages..." -run apt-get autoremove -qq -y && \ -run apt-get autoclean -qq -y && \ -run apt-get clean -qq -y +run apt-get autoremove -q -y && \ +run apt-get autoclean -q -y && \ +run apt-get clean -q -y status -e "\nLEMPer Stack has been removed completely." warning -e "\nDid you know? that we're so sad to see you leave :'( diff --git a/scripts/build_nginx.sh b/scripts/build_nginx.sh index a0f3cb50..4cd3937f 100755 --- a/scripts/build_nginx.sh +++ b/scripts/build_nginx.sh @@ -639,7 +639,7 @@ with --no-deps-check." run cd "$nps_module_dir" else echo "Downloading ngx_pagespeed..." - run git clone -q "git@github.com:pagespeed/ngx_pagespeed.git" \ + run git clone "git@github.com:pagespeed/ngx_pagespeed.git" \ "$nps_module_dir" run cd "$nps_module_dir" run git checkout "$tag_name" @@ -661,7 +661,7 @@ with --no-deps-check." nps_baseurl="https://github.com/apache/incubator-pagespeed-ngx/archive" nps_downloaded="$TEMPDIR/$nps_downloaded_fname.zip" echo "Downloading ngx_pagespeed..." - run wget -q "$nps_baseurl/$tag_name.zip" -O "$nps_downloaded" + run wget "$nps_baseurl/$tag_name.zip" -O "$nps_downloaded" # Read the directory name from the zip, the first line is expected to have it. nps_module_dir=$(unzip -qql "$nps_downloaded" | head -n1 | tr -s ' ' | cut -d' ' -f5-) nps_module_dir="$BUILDDIR/${nps_module_dir::-1}" @@ -720,7 +720,7 @@ with --no-deps-check." fi echo "Downloading PSOL binary..." - run wget -q "$psol_url" + run wget "$psol_url" status "Extracting PSOL..." run tar -xzf $(basename "$psol_url") # extracts to psol/ @@ -825,7 +825,7 @@ with --no-deps-check." nginx_leaf="nginx-${NGINX_VERSION}.tar.gz" nginx_fname="$TEMPDIR/$nginx_leaf" echo "Downloading nginx..." - run wget -q "http://nginx.org/download/$nginx_leaf" -O "$nginx_fname" + run wget "http://nginx.org/download/$nginx_leaf" -O "$nginx_fname" nginx_dir="$BUILDDIR/nginx-${NGINX_VERSION}/" delete_if_already_exists "$nginx_dir" status "Extracting nginx..." diff --git a/scripts/install_certbotle.sh b/scripts/install_certbotle.sh index 4d4125d0..001a8fe7 100755 --- a/scripts/install_certbotle.sh +++ b/scripts/install_certbotle.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -43,13 +43,13 @@ function init_certbotle_install() { debian) case "${RELEASE_NAME}" in jessie) - run apt-get install -qq -y certbot -t jessie-backports + run apt-get install -q -y certbot -t jessie-backports ;; - stretch) - run apt-get install -qq -y certbot -t stretch-backports - ;; - buster) - run apt-get install -qq -y certbot + stretch | buster | bullseye) + run python -m pip install --upgrade pip && \ + run python -m pip install --upgrade setuptools && \ + run python -m pip install --upgrade cffi && \ + run python -m pip install --upgrade certbot ;; *) error "Unable to add Certbot, unsupported distribution release: ${DISTRIB_NAME^} ${RELEASE_NAME^}." @@ -59,23 +59,30 @@ function init_certbotle_install() { esac ;; ubuntu) - case "${RELEASE_NAME}" in - focal) - run apt-get install -qq -y certbot - ;; - *) - run add-apt-repository -y ppa:certbot/certbot - run apt-get update -qq -y - run apt-get install -qq -y certbot - ;; - esac + run python -m pip install --upgrade pip && \ + run python -m pip install --upgrade setuptools && \ + run python -m pip install --upgrade cffi && \ + run python -m pip install --upgrade certbot + ;; + centos | rocky*) + run dnf install-q -y epel-release && run dnf update -q -y && \ + run dnf install-q -y certbot + #run python -m pip install --upgrade pip && \ + #run python -m pip install --upgrade setuptools && \ + #run python -m pip install --upgrade cffi && \ + #run python -m pip install --upgrade certbot + ;; + *) + error "Unable to add Certbot, unsupported distribution release: ${DISTRIB_NAME^} ${RELEASE_NAME^}." + echo "Sorry your system is not supported yet, installing from source may fix the issue." + exit 1 ;; esac # Add Certbot auto renew command to cronjob. if [[ "${DRYRUN}" != true ]]; then export EDITOR=nano - CRONCMD='0 */3 * * * /usr/bin/certbot renew --quiet --renew-hook "/usr/sbin/service nginx reload -s"' + CRONCMD='0 */6 * * * /usr/bin/certbot renew --quiet --renew-hook "/usr/sbin/service nginx reload -s"' touch lemper.cron crontab -u root lemper.cron crontab -l > lemper.cron @@ -83,16 +90,17 @@ function init_certbotle_install() { if ! grep -qwE "/usr/bin/certbot\ renew" lemper.cron; then cat >> lemper.cron < \ + "/etc/lemper/ssl/${HOSTNAME}/chain.pem" + + if [ -f "/etc/lemper/ssl/${HOSTNAME}/cert.pem" ]; then + success "Self-signed SSL certificate has been successfully generated." + else + fail "An error occurred when generating self-signed SSL certificate." + fi fi if [[ "${DRYRUN}" != true ]]; then diff --git a/scripts/install_dependencies.sh b/scripts/install_dependencies.sh index 827b34a1..75772b39 100755 --- a/scripts/install_dependencies.sh +++ b/scripts/install_dependencies.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -21,26 +21,65 @@ fi echo "Installing required dependencies..." +DISTRIB_NAME=${DISTRIB_NAME:-$(get_distrib_name)} +RELEASE_NAME=${RELEASE_NAME:-$(get_release_name)} + # Fix broken install, first? if [[ "${FIX_BROKEN_INSTALL}" == true ]]; then run dpkg --configure -a - run apt-get install -qq -y --fix-broken + run apt-get install -q -y --fix-broken fi # Update repositories. echo "Updating repository, please wait..." -run apt-get update -qq -y && \ -run apt-get upgrade -qq -y +run apt-get update -q -y && \ +run apt-get upgrade -q -y # Install dependencies. echo "Installing packages, be patient..." -run apt-get install -qq -y \ +run apt-get install -q -y \ apt-transport-https apt-utils autoconf automake bash build-essential ca-certificates \ - cmake cron curl dmidecode dnsutils gcc geoip-bin geoip-database gettext git gnupg2 \ - htop iptables libc-bin libc6-dev libcurl4-openssl-dev libgd-dev libgeoip-dev libgpgme11-dev \ - libsodium-dev libssl-dev libxml2-dev libpcre3-dev libtool libxslt1-dev locales logrotate lsb-release \ - make net-tools openssh-server openssl pkg-config python python3 re2c rsync software-properties-common \ - sasl2-bin snmp sudo sysstat tar tzdata unzip wget whois xz-utils zlib1g-dev + cmake cron curl dmidecode dnsutils gcc git gnupg2 htop iptables libc-bin libc6-dev \ + libcurl4-openssl-dev libgpgme11-dev libssl-dev libpcre3-dev libxml2-dev libxslt1-dev \ + libtool locales logrotate lsb-release make net-tools openssh-server openssl pkg-config \ + re2c rsync software-properties-common sasl2-bin snmp sudo sysstat tar tzdata unzip wget \ + whois xz-utils zlib1g-dev geoip-bin geoip-database gettext libgeoip-dev + +# Install Python 3 +echo "Installing Python..." + +case "${DISTRIB_NAME}" in + debian) + case "${RELEASE_NAME}" in + stretch | buster | bullseye) + run add-apt-repository ppa:deadsnakes/ppa -y && \ + run apt-get update -q -y && \ + run apt-get install -q -y python3.7 python3.7-dev python3.7-venv \ + python3.9 python3.9-dev python3.9-venv && \ + run update-alternatives --install /usr/bin/python python "$(command -v python3.7)" 37 && \ + run update-alternatives --install /usr/bin/python python "$(command -v python3.9)" 39 && \ + run update-alternatives --set python /usr/bin/python3.7 + ;; + esac + ;; + ubuntu) + # Install Python + run add-apt-repository ppa:deadsnakes/ppa -y && \ + run apt-get update -q -y && \ + run apt-get install -q -y python3.7 python3.7-dev python3.7-venv \ + python3.9 python3.9-dev python3.9-venv && \ + run update-alternatives --install /usr/bin/python python "$(command -v python3.7)" 37 && \ + run update-alternatives --install /usr/bin/python python "$(command -v python3.9)" 39 && \ + run update-alternatives --set python /usr/bin/python3.7 + ;; + centos | rocky*) + run dnf install -y python3 python3-libs python3-pip-wheel python3-setuptools-wheel \ + python39 python39-libs python39-pip-wheel python39-setuptools-wheel && \ + run update-alternatives --install /usr/bin/unversioned-python python "$(command -v python3)" 3 && \ + run update-alternatives --install /usr/bin/unversioned-python python "$(command -v python3.9)" 39 && \ + run update-alternatives --set python /usr/bin/python3 + ;; +esac # Update locale echo "Reconfigure locale..." diff --git a/scripts/install_fail2ban.sh b/scripts/install_fail2ban.sh index ed440fd8..75a5e093 100755 --- a/scripts/install_fail2ban.sh +++ b/scripts/install_fail2ban.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -53,7 +53,7 @@ function init_fail2ban_install() { case "${SELECTED_INSTALLER}" in 1 | "repo") echo "Installing Fail2ban from repository..." - run apt-get install -qq -y fail2ban + run apt-get install -q -y fail2ban ;; 2 | "source") echo "Installing Fail2ban from source..." @@ -68,9 +68,12 @@ function init_fail2ban_install() { fail2ban_download_link="https://github.com/fail2ban/fail2ban/archive/${FAIL2BAN_VERSION}.tar.gz" if curl -sLI "${fail2ban_download_link}" | grep -q "HTTP/[.12]* [2].."; then - run wget -q "${fail2ban_download_link}" -O fail2ban.tar.gz && \ + run wget "${fail2ban_download_link}" -O fail2ban.tar.gz && \ run tar -zxf fail2ban.tar.gz && \ run cd fail2ban-*/ && \ + # Convert to Python3 codebase + run python -m pip install --upgrade 2to3 && \ + run ./fail2ban-2to3 && \ run python setup.py install && \ run cp files/debian-initd /etc/init.d/fail2ban && \ run update-rc.d fail2ban defaults @@ -108,6 +111,7 @@ maxretry = 3 [nginx-http-auth] enabled = true port = http,https,8082,8083 +filter = nginx-http-auth maxretry = 3 EOL @@ -132,7 +136,8 @@ EOL # Restart Fail2ban daemon. echo "Starting Fail2ban server..." - run systemctl start fail2ban + run systemctl start fail2ban && \ + run systemctl enable fail2ban if [[ "${DRYRUN}" != true ]]; then if [[ $(pgrep -c fail2ban-server) -gt 0 ]]; then diff --git a/scripts/install_imagemagick.sh b/scripts/install_imagemagick.sh index 7bd36a2f..4e323916 100755 --- a/scripts/install_imagemagick.sh +++ b/scripts/install_imagemagick.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -53,7 +53,7 @@ function init_imagemagick_install() { case "${SELECTED_INSTALLER}" in 1 | "repo") echo "Installing ImageMagick library from repository..." - run apt-get install -qq -y imagemagick + run apt-get install -q -y imagemagick ;; 2 | "source") echo "Installing ImageMagick library from source..." @@ -71,7 +71,7 @@ function init_imagemagick_install() { if curl -sLI "${IMAGEMAGICK_ZIP_URL}" | grep -q "HTTP/[.12]* [2].."; then run cd "${BUILD_DIR}" && \ - run wget -q "${IMAGEMAGICK_ZIP_URL}" && \ + run wget "${IMAGEMAGICK_ZIP_URL}" && \ run tar -xf "${IMAGEMAGICK_FILENAME}" && \ run cd ImageMagick-*/ && \ run ./configure && \ diff --git a/scripts/install_mailer.sh b/scripts/install_mailer.sh index 244aa32d..85997505 100755 --- a/scripts/install_mailer.sh +++ b/scripts/install_mailer.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -43,10 +43,10 @@ function install_postfix() { echo "Remove existing sendmail install..." run service sendmail stop && \ run update-rc.d -f sendmail remove && \ - run apt-get remove -qq -y sendmail + run apt-get remove -q -y sendmail fi - run apt-get install -qq -y mailutils postfix + run apt-get install -q -y mailutils postfix # Configure Postfix. echo "Configuring Postfix Mail-Transfer Agent..." @@ -167,7 +167,7 @@ function install_dovecot() { if [[ ${DO_INSTALL_DOVECOT} == y* || ${DO_INSTALL_DOVECOT} == Y* ]]; then echo "Installing Dovecot IMAP & POP3 Server..." - run apt-get install -qq -y dovecot-core dovecot-common dovecot-imapd dovecot-pop3d + run apt-get install -q -y dovecot-core dovecot-common dovecot-imapd dovecot-pop3d # Configure Dovecot. echo "Configuring Dovecot IMAP & POP3 Server..." @@ -324,7 +324,7 @@ function install_spf_dkim() { if [[ ${DO_INSTALL_SPFDKIM} == y* || ${DO_INSTALL_SPFDKIM} == Y* ]]; then echo "Installing Postfix Policy Agent and OpenDKIM..." - run apt-get install -qq -y postfix-policyd-spf-python opendkim opendkim-tools + run apt-get install -q -y postfix-policyd-spf-python opendkim opendkim-tools echo "Configuring SPF + DKIM..." diff --git a/scripts/install_mariadb.sh b/scripts/install_mariadb.sh index df25750d..4fda5ef1 100755 --- a/scripts/install_mariadb.sh +++ b/scripts/install_mariadb.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -39,7 +39,7 @@ function add_mariadb_repo() { run curl -sSL -o "${BUILD_DIR}/mariadb_repo_setup" "${MARIADB_REPO_SETUP_URL}" && \ run bash "${BUILD_DIR}/mariadb_repo_setup" --mariadb-server-version="mariadb-${MYSQL_VERSION}" \ --os-type="${DISTRIB_NAME}" --os-version="${RELEASE_NAME}" && \ - run apt-get update -qq -y + run apt-get update -q -y else error "MariaDB repo installer not found." fi @@ -69,7 +69,7 @@ function init_mariadb_install() { echo "Installing MariaDB (MySQL drop-in replacement) server..." # Install MariaDB - run apt-get install -qq -y libmariadb3 libmariadbclient18 "mariadb-client-${MYSQL_VERSION}" \ + run apt-get install -q -y libmariadb3 libmariadbclient18 "mariadb-client-${MYSQL_VERSION}" \ "mariadb-client-core-${MYSQL_VERSION}" mariadb-common mariadb-server "mariadb-server-${MYSQL_VERSION}" \ "mariadb-server-core-${MYSQL_VERSION}" mariadb-backup @@ -162,11 +162,17 @@ function init_mariadb_install() { else if [[ "${MYSQL_SECURE_INSTALL}" == true ]]; then while [[ "${DO_MYSQL_SECURE_INSTALL}" != "y" && "${DO_MYSQL_SECURE_INSTALL}" != "n" ]]; do - read -rp "Do you want to secure MySQL installation? [y/n]: " -e DO_MYSQL_SECURE_INSTALL + read -rp "Do you want to secure MariaDB installation? [y/n]: " -e DO_MYSQL_SECURE_INSTALL done if [[ "${DO_MYSQL_SECURE_INSTALL}" == y* || "${DO_MYSQL_SECURE_INSTALL}" == Y* ]]; then - run mysql_secure_installation + if [[ -n $(command -v mysql_secure_installation) ]]; then + run mysql_secure_installation + elif [[ -n $(command -v mariadb-secure-installation) ]]; then + run mariadb-secure-installation + else + error "Unable to secure MariaDB installation." + fi fi fi fi diff --git a/scripts/install_memcached.sh b/scripts/install_memcached.sh index 7668fa95..ad8a6d70 100755 --- a/scripts/install_memcached.sh +++ b/scripts/install_memcached.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -56,13 +56,13 @@ function init_memcached_install() { 1 | repo) echo "Installing Memcached server from repository..." - run apt-get install -qq -y \ + run apt-get install -q -y \ libevent-dev libsasl2-dev libmemcached-tools libmemcached11 libmemcachedutil2 memcached ;; 2 | source) echo "Installing Memcached server from source..." - run apt-get install -qq -y \ + run apt-get install -q -y \ libevent-dev libsasl2-dev libmemcached-tools libmemcached11 libmemcachedutil2 local CURRENT_DIR && \ @@ -73,7 +73,7 @@ function init_memcached_install() { # Install Libevent from source. #LIBEVENT_DOWNLOAD_URL="https://github.com/libevent/libevent/releases/download/release-2.1.11-stable/libevent-2.1.11-stable.tar.gz" #if curl -sLI "${LIBEVENT_DOWNLOAD_URL}" | grep -q "HTTP/[.12]* [2].."; then - # run wget -q -O libevent.tar.gz "${LIBEVENT_DOWNLOAD_URL}" + # run wget -O libevent.tar.gz "${LIBEVENT_DOWNLOAD_URL}" # run tar -zxf libevent.tar.gz # run cd libevent-* # run ./configure --prefix=/usr/local/libevent @@ -90,7 +90,7 @@ function init_memcached_install() { fi if curl -sLI "${MEMCACHED_DOWNLOAD_URL}" | grep -q "HTTP/[.12]* [2].."; then - run wget -q "${MEMCACHED_DOWNLOAD_URL}" -O memcached.tar.gz && \ + run wget "${MEMCACHED_DOWNLOAD_URL}" -O memcached.tar.gz && \ run tar -zxf memcached.tar.gz && \ run cd memcached-* && \ diff --git a/scripts/install_mongodb.sh b/scripts/install_mongodb.sh index 534e884d..7640ae19 100755 --- a/scripts/install_mongodb.sh +++ b/scripts/install_mongodb.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -60,7 +60,7 @@ function add_mongodb_repo() { run touch "/etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}-${RELEASE_NAME}.list" run bash -c "echo 'deb [ arch=${DISTRIB_ARCH} ] https://repo.mongodb.org/apt/debian ${RELEASE_NAME}/mongodb-org/${MONGODB_VERSION} main' > /etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}-${RELEASE_NAME}.list" - run apt-get update -qq -y + run apt-get update -q -y else info "MongoDB ${MONGODB_VERSION} repository already exists." fi @@ -75,7 +75,7 @@ function add_mongodb_repo() { run touch "/etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}-${RELEASE_NAME}.list" run bash -c "echo 'deb [ arch=${DISTRIB_ARCH} ] https://repo.mongodb.org/apt/ubuntu ${RELEASE_NAME}/mongodb-org/${MONGODB_VERSION} multiverse' > /etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}-${RELEASE_NAME}.list" - run apt-get update -qq -y + run apt-get update -q -y else info "MongoDB ${MONGODB_VERSION} repository already exists." fi @@ -113,7 +113,7 @@ function init_mongodb_install() { echo "Installing MongoDB server..." - run apt-get install -qq -y libbson-1.0 libmongoc-1.0-0 mongodb-org mongodb-org-server \ + run apt-get install -q -y libbson-1.0 libmongoc-1.0-0 mongodb-org mongodb-org-server \ mongodb-org-shell mongodb-org-tools mongodb-org-mongos mongodb-database-tools \ mongodb-org-database-tools-extra mongodb-mongosh diff --git a/scripts/install_nginx.sh b/scripts/install_nginx.sh index 2d2543d2..9afb4901 100755 --- a/scripts/install_nginx.sh +++ b/scripts/install_nginx.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -47,7 +47,7 @@ function add_nginx_repo() { run touch "/etc/apt/sources.list.d/ondrej-${NGINX_REPO}-${RELEASE_NAME}.list" run bash -c "echo 'deb https://packages.sury.org/${NGINX_REPO}/ ${RELEASE_NAME} main' > /etc/apt/sources.list.d/ondrej-${NGINX_REPO}-${RELEASE_NAME}.list" run wget -qO "/etc/apt/trusted.gpg.d/${NGINX_REPO}.gpg" "https://packages.sury.org/${NGINX_REPO}/apt.gpg" - run apt-get update -qq -y + run apt-get update -q -y else info "${NGINX_REPO} repository already exists." fi @@ -59,7 +59,7 @@ function add_nginx_repo() { run wget -qO "/etc/apt/trusted.gpg.d/${NGINX_REPO}.gpg" "https://packages.sury.org/${NGINX_REPO}/apt.gpg" run apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 14AA40EC0831756756D7F66C4F4EA0AAE5267A6C run add-apt-repository -y "ppa:ondrej/${NGINX_REPO}" - run apt-get update -qq -y + run apt-get update -q -y NGINX_PKG="nginx-extras" ;; @@ -278,7 +278,7 @@ function init_nginx_install() { fi # Install Nginx and its modules. - run apt-get install -qq -y "${NGINX_PKG}" "${EXTRA_MODULE_PKGS[@]}" + run apt-get install -q -y "${NGINX_PKG}" "${EXTRA_MODULE_PKGS[@]}" fi #else # fail "Unable to install Nginx, this GNU/Linux distribution is not supported." @@ -306,786 +306,802 @@ function init_nginx_install() { NGINX_RELEASE_VERSION="${NGINX_VERSION}" fi - #if [[ "${DRYRUN}" == true ]]; then - # run "${BUILD_DIR}/build_nginx" -v latest-stable \ - # -n "${NGINX_RELEASE_VERSION}" --dynamic-module --extra-modules -y --dryrun - #else - # Nginx configure arguments. - NGX_CONFIGURE_ARGS="" - - # Is gcc > 8.x? - #if gcc --version | grep -q "\ [8.]"; then - # NGX_CONFIGURE_ARGS="CFLAGS=\"-Wno-stringop-truncation -Wno-stringop-overflow -Wno-size-of-pointer-memaccess\"" - #fi - - # Additional configure arguments. - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --prefix=/usr/share/nginx \ - --sbin-path=/usr/sbin/nginx \ - --modules-path=/usr/lib/nginx/modules \ - --conf-path=/etc/nginx/nginx.conf \ - --error-log-path=/var/log/nginx/error.log \ - --http-log-path=/var/log/nginx/access.log \ - --pid-path=/run/nginx.pid \ - --lock-path=/var/lock/nginx.lock \ - --user=www-data \ - --group=www-data \ - --with-compat \ - --with-file-aio \ - --with-http_addition_module \ - --with-http_auth_request_module \ - --with-http_dav_module \ - --with-http_flv_module \ - --with-http_gunzip_module \ - --with-http_gzip_static_module \ - --with-http_mp4_module \ - --with-http_random_index_module \ - --with-http_realip_module \ - --with-http_secure_link_module \ - --with-http_slice_module \ - --with-http_ssl_module \ - --with-http_stub_status_module \ - --with-http_sub_module \ - --with-http_v2_module \ - --with-threads" - - # Custom build name. - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} --build=LEMPer" - - local CURRENT_DIR && \ - CURRENT_DIR=$(pwd) - - run cd "${BUILD_DIR}" && \ - - # Build with custom OpenSSL. - if "${NGINX_WITH_CUSTOMSSL}"; then - # Custom SSL version. - NGINX_CUSTOMSSL_VERSION=${NGINX_CUSTOMSSL_VERSION:-"openssl-1.1.1l"} - - echo "Build Nginx with custom SSL ${NGINX_CUSTOMSSL_VERSION^}..." - - # OpenSSL - if grep -iq openssl <<<"${NGINX_CUSTOMSSL_VERSION}"; then - OPENSSL_SOURCE_URL="https://www.openssl.org/source/${NGINX_CUSTOMSSL_VERSION}.tar.gz" - #OPENSSL_SOURCE_URL="https://github.com/openssl/openssl/archive/${NGINX_CUSTOMSSL_VERSION}.tar.gz" - - if curl -sLI "${OPENSSL_SOURCE_URL}" | grep -q "HTTP/[.12]* [2].."; then - run wget -q -O "${NGINX_CUSTOMSSL_VERSION}.tar.gz" "${OPENSSL_SOURCE_URL}" && \ - run tar -zxf "${NGINX_CUSTOMSSL_VERSION}.tar.gz" - - [[ -d "${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}" ]] && \ - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --with-openssl=${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION} \ - --with-openssl-opt=enable-ec_nistp_64_gcc_128 \ - --with-openssl-opt=no-nextprotoneg \ - --with-openssl-opt=no-weak-ssl-ciphers" - else - error "Unable to determine OpenSSL source page." - fi + # Nginx configure arguments. + NGX_CONFIGURE_ARGS="" - # LibreSSL - elif grep -iq libressl <<<"${NGINX_CUSTOMSSL_VERSION}"; then - LIBRESSL_SOURCE_URL="https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/${NGINX_CUSTOMSSL_VERSION}.tar.gz" + # Is gcc > 8.x? + #if gcc --version | grep -q "\ [8.]"; then + # NGX_CONFIGURE_ARGS="CFLAGS=\"-Wno-stringop-truncation -Wno-stringop-overflow -Wno-size-of-pointer-memaccess\"" + #fi - if curl -sLI "${LIBRESSL_SOURCE_URL}" | grep -q "HTTP/[.12]* [2].."; then - run wget -q -O "${NGINX_CUSTOMSSL_VERSION}.tar.gz" "${LIBRESSL_SOURCE_URL}" && \ - run tar -zxf "${NGINX_CUSTOMSSL_VERSION}.tar.gz" + # Additional configure arguments. + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --prefix=/usr/share/nginx \ + --sbin-path=/usr/sbin/nginx \ + --modules-path=/usr/lib/nginx/modules \ + --conf-path=/etc/nginx/nginx.conf \ + --error-log-path=/var/log/nginx/error.log \ + --http-log-path=/var/log/nginx/access.log \ + --pid-path=/run/nginx.pid \ + --lock-path=/var/lock/nginx.lock \ + --user=www-data \ + --group=www-data \ + --with-compat \ + --with-debug \ + --with-file-aio \ + --with-http_addition_module \ + --with-http_auth_request_module \ + --with-http_dav_module \ + --with-http_degradation_module \ + --with-http_flv_module \ + --with-http_gunzip_module \ + --with-http_gzip_static_module \ + --with-http_mp4_module \ + --with-http_random_index_module \ + --with-http_realip_module \ + --with-http_secure_link_module \ + --with-http_slice_module \ + --with-http_ssl_module \ + --with-http_stub_status_module \ + --with-http_sub_module \ + --with-http_v2_module \ + --with-threads" + + # Custom build name. + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} --build=LEMPer" + + local CURRENT_DIR && \ + CURRENT_DIR=$(pwd) + + run cd "${BUILD_DIR}" && \ + + # Build with custom OpenSSL. + if "${NGINX_WITH_CUSTOMSSL}"; then + # Custom SSL version. + NGINX_CUSTOMSSL_VERSION=${NGINX_CUSTOMSSL_VERSION:-"openssl-1.1.1l"} + + echo "Build Nginx with custom SSL ${NGINX_CUSTOMSSL_VERSION^}..." + + # OpenSSL + if grep -iq openssl <<<"${NGINX_CUSTOMSSL_VERSION}"; then + OPENSSL_SOURCE_URL="https://www.openssl.org/source/${NGINX_CUSTOMSSL_VERSION}.tar.gz" + #OPENSSL_SOURCE_URL="https://github.com/openssl/openssl/archive/${NGINX_CUSTOMSSL_VERSION}.tar.gz" + + if curl -sLI "${OPENSSL_SOURCE_URL}" | grep -q "HTTP/[.12]* [2].."; then + run wget -O "${NGINX_CUSTOMSSL_VERSION}.tar.gz" "${OPENSSL_SOURCE_URL}" && \ + run tar -zxf "${NGINX_CUSTOMSSL_VERSION}.tar.gz" + + [[ -d "${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}" ]] && \ + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --with-openssl=${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION} \ + --with-openssl-opt=enable-ec_nistp_64_gcc_128 \ + --with-openssl-opt=no-nextprotoneg \ + --with-openssl-opt=no-weak-ssl-ciphers" + else + error "Unable to determine OpenSSL source page." + fi - [[ -d "${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}" ]] && \ - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --with-openssl=${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION} \ - --with-openssl-opt=no-weak-ssl-ciphers" - else - error "Unable to determine LibreSSL source page." - fi + # LibreSSL + elif grep -iq libressl <<<"${NGINX_CUSTOMSSL_VERSION}"; then + LIBRESSL_SOURCE_URL="https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/${NGINX_CUSTOMSSL_VERSION}.tar.gz" - # BoringSSL - elif grep -iq boringssl <<< "${NGINX_CUSTOMSSL_VERSION}"; then - # BoringSSL requires Golang, install it first. - if [[ -z $(command -v go) ]]; then - GOLANG_VER="1.17.8" - - local DISTRIB_ARCH - case "${ARCH}" in - i386 | i486| i586 | i686) - DISTRIB_ARCH="386" - ;; - x86_64 | amd64) - DISTRIB_ARCH="amd64" - ;; - arm64 | aarch* | armv8*) - DISTRIB_ARCH="arm64" - ;; - arm | armv7*) - DISTRIB_ARCH="armv6l" - ;; - *) - DISTRIB_ARCH="386" - ;; - esac - - case "${DISTRIB_NAME}" in - debian) - GOLANG_DOWNLOAD_URL="https://go.dev/dl/go${GOLANG_VER}.linux-${DISTRIB_ARCH}.tar.gz" - - if curl -sLI "${GOLANG_DOWNLOAD_URL}" | grep -q "HTTP/[.12]* [2].."; then - run wget -q -O golang.tar.gz "${GOLANG_DOWNLOAD_URL}" && \ - run tar -C /usr/local -zxf golang.tar.gz && \ - run bash -c "echo -e '\nexport PATH=\"\$PATH:/usr/local/go/bin\"' >> ~/.profile" && \ - run source ~/.profile - else - info "Unable to determine Golang source page." - fi - ;; - ubuntu) - run add-apt-repository -y ppa:longsleep/golang-backports && \ - run apt-get update -qq -y && \ - run apt-get install -qq -y golang-go - ;; - *) - fail "Unsupported distribution." - ;; - esac - fi + if curl -sLI "${LIBRESSL_SOURCE_URL}" | grep -q "HTTP/[.12]* [2].."; then + run wget -O "${NGINX_CUSTOMSSL_VERSION}.tar.gz" "${LIBRESSL_SOURCE_URL}" && \ + run tar -zxf "${NGINX_CUSTOMSSL_VERSION}.tar.gz" - # Split BoringSSL version. - SAVEIFS=${IFS} # Save current IFS - IFS='- ' read -r -a BSPARTS <<< "${NGINX_CUSTOMSSL_VERSION}" - IFS=${SAVEIFS} # Restore IFS - BORINGSSL_VERSION=${BSPARTS[1]} - [[ -z ${BORINGSSL_VERSION} || ${BORINGSSL_VERSION} == "latest" ]] && BORINGSSL_VERSION="master" - BORINGSSL_SOURCE_URL="https://boringssl.googlesource.com/boringssl/+archive/refs/heads/${BORINGSSL_VERSION}.tar.gz" - - if curl -sLI "${BORINGSSL_SOURCE_URL}" | grep -q "HTTP/[.12]* [2].."; then - run wget -q -O "${NGINX_CUSTOMSSL_VERSION}.tar.gz" "${BORINGSSL_SOURCE_URL}" && \ - run mkdir -p "${NGINX_CUSTOMSSL_VERSION}" && \ - run tar -zxf "${NGINX_CUSTOMSSL_VERSION}.tar.gz" -C "${NGINX_CUSTOMSSL_VERSION}" && \ - run cd "${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}" && \ - - # Make an .openssl directory for nginx and then symlink BoringSSL's include directory tree. - run mkdir -p build .openssl/lib .openssl/include && \ - run ln -sf "${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}/include/openssl" .openssl/include/openssl && \ - - # Fix "Error 127" during build. - run touch "${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}/.openssl/include/openssl/ssl.h" && \ - - # Build BoringSSL static. - run cmake -B"${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}/build" -H"${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}" && \ - run make -C"${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}/build" -j"${NB_PROC}" && \ - - # Copy the BoringSSL crypto libraries to .openssl/lib so nginx can find them. - run cp build/crypto/libcrypto.a build/ssl/libssl.a .openssl/lib && \ - - # Back to extra module dir. - run cd "${EXTRA_MODULE_DIR}" || return 1 - - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --with-cc-opt=\"-I${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}/.openssl/include\" \ - --with-ld-opt=\"-L${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}/.openssl/lib\"" - else - info "Unable to determine BoringSSL source page." - fi + [[ -d "${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}" ]] && \ + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --with-openssl=${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION} \ + --with-openssl-opt=no-weak-ssl-ciphers" else - error "Unable to determine CustomSSL version." - echo "Revert back to use default system's OpenSSL..." + error "Unable to determine LibreSSL source page." fi - fi - # Build with PCRE. - if "${NGINX_WITH_PCRE}"; then - # Custom PCRE JIT source. - NGINX_PCRE_VERSION=${NGINX_PCRE_VERSION:-"8.45"} - PCRE_SOURCE_URL="https://onboardcloud.dl.sourceforge.net/project/pcre/pcre/${NGINX_PCRE_VERSION}/pcre-${NGINX_PCRE_VERSION}.tar.gz" + # BoringSSL + elif grep -iq boringssl <<< "${NGINX_CUSTOMSSL_VERSION}"; then + # BoringSSL requires Golang, install it first. + if [[ -z $(command -v go) ]]; then + GOLANG_VER="1.17.8" + + local DISTRIB_ARCH + case "${ARCH}" in + i386 | i486| i586 | i686) + DISTRIB_ARCH="386" + ;; + x86_64 | amd64) + DISTRIB_ARCH="amd64" + ;; + arm64 | aarch* | armv8*) + DISTRIB_ARCH="arm64" + ;; + arm | armv7*) + DISTRIB_ARCH="armv6l" + ;; + *) + DISTRIB_ARCH="386" + ;; + esac + + case "${DISTRIB_NAME}" in + debian) + GOLANG_DOWNLOAD_URL="https://go.dev/dl/go${GOLANG_VER}.linux-${DISTRIB_ARCH}.tar.gz" + + if curl -sLI "${GOLANG_DOWNLOAD_URL}" | grep -q "HTTP/[.12]* [2].."; then + run wget -O golang.tar.gz "${GOLANG_DOWNLOAD_URL}" && \ + run tar -C /usr/local -zxf golang.tar.gz && \ + run bash -c "echo -e '\nexport PATH=\"\$PATH:/usr/local/go/bin\"' >> ~/.profile" && \ + run source ~/.profile + else + info "Unable to determine Golang source page." + fi + ;; + ubuntu) + run add-apt-repository -y ppa:longsleep/golang-backports && \ + run apt-get update -q -y && \ + run apt-get install -q -y golang-go + ;; + *) + fail "Unsupported distribution." + ;; + esac + fi - echo "Build Nginx with PCRE JIT ${NGINX_PCRE_VERSION}..." + # Split BoringSSL version. + SAVEIFS=${IFS} # Save current IFS + IFS='- ' read -r -a BSPARTS <<< "${NGINX_CUSTOMSSL_VERSION}" + IFS=${SAVEIFS} # Restore IFS + BORINGSSL_VERSION=${BSPARTS[1]} + [[ -z ${BORINGSSL_VERSION} || ${BORINGSSL_VERSION} == "latest" ]] && BORINGSSL_VERSION="master" + BORINGSSL_SOURCE_URL="https://boringssl.googlesource.com/boringssl/+archive/refs/heads/${BORINGSSL_VERSION}.tar.gz" - if curl -sLI "${PCRE_SOURCE_URL}" | grep -q "HTTP/[.12]* [2].."; then - run wget -q -O "${NGINX_PCRE_VERSION}.tar.gz" "${PCRE_SOURCE_URL}" && \ - run tar -zxf "${NGINX_PCRE_VERSION}.tar.gz" + if curl -sLI "${BORINGSSL_SOURCE_URL}" | grep -q "HTTP/[.12]* [2].."; then + run wget -O "${NGINX_CUSTOMSSL_VERSION}.tar.gz" "${BORINGSSL_SOURCE_URL}" && \ + run mkdir -p "${NGINX_CUSTOMSSL_VERSION}" && \ + run tar -zxf "${NGINX_CUSTOMSSL_VERSION}.tar.gz" -C "${NGINX_CUSTOMSSL_VERSION}" && \ + run cd "${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}" && \ - if [ -d "${BUILD_DIR}/${NGINX_PCRE_VERSION}" ]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} --with-pcre=${BUILD_DIR}/${NGINX_PCRE_VERSION} --with-pcre-jit" - fi + # Make an .openssl directory for nginx and then symlink BoringSSL's include directory tree. + run mkdir -p build .openssl/lib .openssl/include && \ + run ln -sf "${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}/include/openssl" .openssl/include/openssl && \ + + # Fix "Error 127" during build. + run touch "${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}/.openssl/include/openssl/ssl.h" && \ + + # Build BoringSSL static. + run cmake -B"${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}/build" -H"${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}" && \ + run make -C"${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}/build" -j"${NB_PROC}" && \ + + # Copy the BoringSSL crypto libraries to .openssl/lib so nginx can find them. + run cp build/crypto/libcrypto.a build/ssl/libssl.a .openssl/lib && \ + + # Back to extra module dir. + run cd "${EXTRA_MODULE_DIR}" || return 1 + + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --with-cc-opt=\"-I${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}/.openssl/include\" \ + --with-ld-opt=\"-L${BUILD_DIR}/${NGINX_CUSTOMSSL_VERSION}/.openssl/lib\"" else - error "Unable to determine PCRE JIT ${NGINX_PCRE_VERSION} source." + info "Unable to determine BoringSSL source page." fi + else + error "Unable to determine CustomSSL version." + echo "Revert back to use default system's OpenSSL..." fi + fi - if "${NGINX_EXTRA_MODULES}"; then - echo "Build Nginx with extra modules..." + # Build with PCRE. + if "${NGINX_WITH_PCRE}"; then + # Custom PCRE JIT source. + NGINX_PCRE_VERSION=${NGINX_PCRE_VERSION:-"8.45"} + PCRE_SOURCE_URL="https://onboardcloud.dl.sourceforge.net/project/pcre/pcre/${NGINX_PCRE_VERSION}/pcre-${NGINX_PCRE_VERSION}.tar.gz" - local EXTRA_MODULE_DIR="${BUILD_DIR}/nginx_modules" + echo "Build Nginx with PCRE JIT ${NGINX_PCRE_VERSION}..." - if [ -d "${EXTRA_MODULE_DIR}" ]; then - run rm -rf "${EXTRA_MODULE_DIR}" + if curl -sLI "${PCRE_SOURCE_URL}" | grep -q "HTTP/[.12]* [2].."; then + run wget -O "${NGINX_PCRE_VERSION}.tar.gz" "${PCRE_SOURCE_URL}" && \ + run tar -zxf "${NGINX_PCRE_VERSION}.tar.gz" + + if [ -d "${BUILD_DIR}/${NGINX_PCRE_VERSION}" ]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} --with-pcre=${BUILD_DIR}/${NGINX_PCRE_VERSION} --with-pcre-jit" fi + else + error "Unable to determine PCRE JIT ${NGINX_PCRE_VERSION} source." + fi + fi - run mkdir -p "${EXTRA_MODULE_DIR}" && \ - run cd "${EXTRA_MODULE_DIR}" || return 1 + if "${NGINX_EXTRA_MODULES}"; then + echo "Build Nginx with extra modules..." - # Auth PAM module. - if "${NGX_HTTP_AUTH_PAM}"; then - echo "Adding ngx-http-auth-pam module..." + local EXTRA_MODULE_DIR="${BUILD_DIR}/nginx_modules" - run git clone -q --branch="master" --single-branch https://github.com/sto/ngx_http_auth_pam_module.git + if [[ -d "${EXTRA_MODULE_DIR}" && "${FORCE_REMOVE}" == true ]]; then + run rm -rf "${EXTRA_MODULE_DIR}" + fi - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/ngx_http_auth_pam_module" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/ngx_http_auth_pam_module" - fi + run mkdir -p "${EXTRA_MODULE_DIR}" && \ + run cd "${EXTRA_MODULE_DIR}" || return 1 + + # Auth PAM module. + if "${NGX_HTTP_AUTH_PAM}"; then + echo "Adding ngx-http-auth-pam module..." - # Requires libpam-dev - echo "Building Auth PAM module requires libpam-dev package, install now..." + run git clone --branch="master" --single-branch https://github.com/sto/ngx_http_auth_pam_module.git - run apt-get install -qq -y libpam-dev + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/ngx_http_auth_pam_module" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/ngx_http_auth_pam_module" fi - # Brotli compression module. - if "${NGX_HTTP_BROTLI}"; then - echo "Adding ngx-http-brotli module..." + # Requires libpam-dev + echo "Building Auth PAM module requires libpam-dev package, install now..." - run git clone -q https://github.com/google/ngx_brotli.git && \ - run cd ngx_brotli && \ - run git checkout master -q && \ - run git submodule update --init -q && \ - run cd ../ || return 1 + run apt-get install -q -y libpam-dev + fi - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/ngx_brotli" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/ngx_brotli" - fi + # Brotli compression module. + if "${NGX_HTTP_BROTLI}"; then + echo "Adding ngx-http-brotli module..." + + run git clone https://github.com/google/ngx_brotli.git && \ + run cd ngx_brotli && \ + run git checkout master -q && \ + run git submodule update --init -q && \ + run cd ../ || return 1 + + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/ngx_brotli" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/ngx_brotli" fi + fi - # Cache purge module. - if "${NGX_HTTP_CACHE_PURGE}"; then - echo "Adding ngx-http-cache-purge module..." + # Cache purge module. + if "${NGX_HTTP_CACHE_PURGE}"; then + echo "Adding ngx-http-cache-purge module..." - run git clone -q --branch="master" --single-branch https://github.com/nginx-modules/ngx_cache_purge.git - #run git clone -q https://github.com/joglomedia/ngx_cache_purge.git + run git clone --branch="master" --single-branch https://github.com/nginx-modules/ngx_cache_purge.git + #run git clone https://github.com/joglomedia/ngx_cache_purge.git - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/ngx_cache_purge" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/ngx_cache_purge" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/ngx_cache_purge" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/ngx_cache_purge" fi + fi - # Web DAV module. - if "${NGX_HTTP_DAV_EXT}"; then - echo "Adding ngx-http-dav-ext module..." + # Web DAV module. + if "${NGX_HTTP_DAV_EXT}"; then + echo "Adding ngx-http-dav-ext module..." - run git clone -q --branch="master" --single-branch https://github.com/arut/nginx-dav-ext-module.git + run git clone --branch="master" --single-branch https://github.com/arut/nginx-dav-ext-module.git - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/nginx-dav-ext-module" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/nginx-dav-ext-module" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/nginx-dav-ext-module" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/nginx-dav-ext-module" fi + fi - # Openresty Echo module. - if "${NGX_HTTP_ECHO}"; then - echo "Adding ngx-http-echo module..." + # Openresty Echo module. + if "${NGX_HTTP_ECHO}"; then + echo "Adding ngx-http-echo module..." - run git clone -q --branch="master" --single-branch https://github.com/openresty/echo-nginx-module.git + run git clone --branch="master" --single-branch https://github.com/openresty/echo-nginx-module.git - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/echo-nginx-module" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/echo-nginx-module" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/echo-nginx-module" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/echo-nginx-module" fi + fi - # Fancy indexes module for the Nginx web server. - if "${NGX_HTTP_FANCYINDEX}"; then - echo "Adding ngx-http-fancyindex module..." + # Fancy indexes module for the Nginx web server. + if "${NGX_HTTP_FANCYINDEX}"; then + echo "Adding ngx-http-fancyindex module..." - run git clone -q --branch="master" --single-branch https://github.com/aperezdc/ngx-fancyindex.git + run git clone --branch="master" --single-branch https://github.com/aperezdc/ngx-fancyindex.git - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/ngx-fancyindex" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/ngx-fancyindex" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/ngx-fancyindex" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/ngx-fancyindex" fi + fi - # GeoIP module. - if "${NGX_HTTP_GEOIP}"; then - echo "Adding ngx-http-geoip module..." + # GeoIP module. + if "${NGX_HTTP_GEOIP}"; then + echo "Adding ngx-http-geoip module..." - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --with-http_geoip_module=dynamic" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --with-http_geoip_module" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --with-http_geoip_module=dynamic" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --with-http_geoip_module" fi + fi - # GeoIP2 module. - if "${NGX_HTTP_GEOIP2}"; then - echo "Adding ngx-http-geoip2 module..." + # GeoIP2 module. + if "${NGX_HTTP_GEOIP2}"; then + echo "Adding ngx-http-geoip2 module..." - run git clone -q --branch="master" --single-branch https://github.com/leev/ngx_http_geoip2_module.git + run git clone --branch="master" --single-branch https://github.com/leev/ngx_http_geoip2_module.git - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/ngx_http_geoip2_module" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/ngx_http_geoip2_module" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/ngx_http_geoip2_module" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/ngx_http_geoip2_module" + fi - # install libmaxminddb - echo "GeoIP2 module requires MaxMind GeoIP2 library, install now..." + # install libmaxminddb + echo "GeoIP2 module requires MaxMind GeoIP2 library, install now..." - run cd "${BUILD_DIR}" || return 1 + run cd "${BUILD_DIR}" || return 1 - DISTRIB_NAME=${DISTRIB_NAME:-$(get_distrib_name)} + DISTRIB_NAME=${DISTRIB_NAME:-$(get_distrib_name)} - if [[ "${DISTRIB_NAME}" == "ubuntu" ]]; then - run add-apt-repository -y ppa:maxmind/ppa && \ - run apt-get update -qq -y && \ - run apt-get install -qq -y libmaxminddb0 libmaxminddb-dev mmdb-bin - else - if [ ! -d libmaxminddb ]; then - run git clone -q --recursive https://github.com/maxmind/libmaxminddb.git && \ - run cd libmaxminddb || return 1 - else - run cd libmaxminddb && \ - run git pull -q - fi + if [[ "${DISTRIB_NAME}" == "ubuntu" ]]; then + run add-apt-repository -y ppa:maxmind/ppa && \ + run apt-get update -q -y && \ + run apt-get install -q -y libmaxminddb0 libmaxminddb-dev mmdb-bin + else + if [ ! -d libmaxminddb ]; then + run git clone --recursive https://github.com/maxmind/libmaxminddb.git && \ + run cd libmaxminddb || return 1 + else + run cd libmaxminddb && \ + run git pull + fi - run ./bootstrap && \ - run ./configure && \ - run make -j"${NB_PROC}" && \ - run make install && \ - run bash -c "echo /usr/local/lib >> /etc/ld.so.conf.d/local.conf" && \ - run ldconfig && \ - run cd ../ || return 1 - fi + run ./bootstrap && \ + run ./configure && \ + run make -j"${NB_PROC}" && \ + run make install && \ + run bash -c "echo /usr/local/lib >> /etc/ld.so.conf.d/local.conf" && \ + run ldconfig && \ + run cd ../ || return 1 + fi - echo "Downloading MaxMind GeoIP2-GeoLite2 database..." + echo "Downloading MaxMind GeoIP2-GeoLite2 database..." - if [ -d geoip-db ]; then - run rm -rf geoip-db - fi + if [ -d geoip-db ]; then + run rm -rf geoip-db + fi - run mkdir -p geoip-db && \ - run cd geoip-db && \ - run mkdir -p /opt/geoip + run mkdir -p geoip-db && \ + run cd geoip-db && \ + run mkdir -p /opt/geoip - # Download MaxMind GeoLite2 database. - GEOLITE2_COUNTRY_SRC="https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=${GEOLITE2_LICENSE_KEY}&suffix=tar.gz" + # Download MaxMind GeoLite2 database. + if [[ ! -f GeoLite2-City.tar.gz ]]; then + GEOLITE2_COUNTRY_SRC="https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=${GEOLITE2_LICENSE_KEY}&suffix=tar.gz" - if curl -sLI "${GEOLITE2_COUNTRY_SRC}" | grep -q "HTTP/[.12]* [2].."; then - run wget -q "${GEOLITE2_COUNTRY_SRC}" -O GeoLite2-Country.tar.gz && \ - run tar -xf GeoLite2-Country.tar.gz && \ - run cd GeoLite2-Country_*/ && \ - run mv GeoLite2-Country.mmdb /opt/geoip/ && \ - run cd ../ || return 1 - fi + if curl -sLI "${GEOLITE2_COUNTRY_SRC}" | grep -q "HTTP/[.12]* [2].."; then + run wget "${GEOLITE2_COUNTRY_SRC}" -O GeoLite2-Country.tar.gz && \ + run tar -xf GeoLite2-Country.tar.gz && \ + run cd GeoLite2-Country_*/ && \ + run mv GeoLite2-Country.mmdb /opt/geoip/ && \ + run cd ../ || return 1 + fi + fi - GEOLITE2_CITY_SRC="https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=${GEOLITE2_LICENSE_KEY}&suffix=tar.gz" + if [[ ! -f GeoLite2-City.tar.gz ]]; then + GEOLITE2_CITY_SRC="https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=${GEOLITE2_LICENSE_KEY}&suffix=tar.gz" - if curl -sLI "${GEOLITE2_CITY_SRC}" | grep -q "HTTP/[.12]* [2].."; then - run wget -q "${GEOLITE2_CITY_SRC}" -O GeoLite2-City.tar.gz && \ - run tar -xf GeoLite2-City.tar.gz && \ - run cd GeoLite2-City_*/ && \ - run mv GeoLite2-City.mmdb /opt/geoip/ - fi + if curl -sLI "${GEOLITE2_CITY_SRC}" | grep -q "HTTP/[.12]* [2].."; then + run wget "${GEOLITE2_CITY_SRC}" -O GeoLite2-City.tar.gz && \ + run tar -xf GeoLite2-City.tar.gz && \ + run cd GeoLite2-City_*/ && \ + run mv GeoLite2-City.mmdb /opt/geoip/ + fi + fi - run cd "${EXTRA_MODULE_DIR}" || return 1 + run cd "${EXTRA_MODULE_DIR}" || return 1 - if [[ -f /opt/geoip/GeoLite2-City.mmdb && -f /opt/geoip/GeoLite2-Country.mmdb ]]; then - success "MaxMind GeoIP2-GeoLite2 database successfully installed." - else - error "Failed installing MaxMind GeoIP2-GeoLite2 database." - fi + if [[ -f /opt/geoip/GeoLite2-City.mmdb && -f /opt/geoip/GeoLite2-Country.mmdb ]]; then + success "MaxMind GeoIP2-GeoLite2 database successfully installed." + else + error "Failed installing MaxMind GeoIP2-GeoLite2 database." fi + fi - # Headers more module. - if "${NGX_HTTP_HEADERS_MORE}"; then - echo "Adding ngx-http-headers-more-filter module..." + # Headers more module. + if "${NGX_HTTP_HEADERS_MORE}"; then + echo "Adding ngx-http-headers-more-filter module..." - run git clone -q --branch="master" --single-branch https://github.com/openresty/headers-more-nginx-module.git + run git clone --branch="master" --single-branch https://github.com/openresty/headers-more-nginx-module.git - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/headers-more-nginx-module" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/headers-more-nginx-module" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/headers-more-nginx-module" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/headers-more-nginx-module" fi + fi - # HTTP Image Filter module. - if "${NGX_HTTP_IMAGE_FILTER}"; then - echo "Adding ngx-http-image-filter module..." + # HTTP Image Filter module. + if "${NGX_HTTP_IMAGE_FILTER}"; then + echo "Adding ngx-http-image-filter module..." - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --with-http_image_filter_module=dynamic" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --with-http_image_filter_module" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --with-http_image_filter_module=dynamic" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --with-http_image_filter_module" fi + fi - # Embed the power of Lua into Nginx HTTP Servers. - if "${NGX_HTTP_LUA}"; then - echo "Adding ngx-http-lua module..." + # Embed the power of Lua into Nginx HTTP Servers. + if "${NGX_HTTP_LUA}"; then + echo "Adding ngx-http-lua module..." - LUA_JIT_VERSION=${LUA_JIT_VERSION:-"v2.1-20211210"} - LUA_RESTY_CORE_VERSION=${LUA_RESTY_CORE_VERSION:-"v0.1.22"} - LUA_RESTY_LRUCACHE_VERSION=${LUA_RESTY_LRUCACHE_VERSION:-"v0.11"} + LUA_JIT_VERSION=${LUA_JIT_VERSION:-"v2.1-20211210"} + LUA_RESTY_CORE_VERSION=${LUA_RESTY_CORE_VERSION:-"v0.1.22"} + LUA_RESTY_LRUCACHE_VERSION=${LUA_RESTY_LRUCACHE_VERSION:-"v0.11"} - # Requires ngx-devel-kit enabled - NGX_HTTP_NDK=true + # Requires ngx-devel-kit enabled + NGX_HTTP_NDK=true - # Requires luajit library - echo "Lua module requires LuaJIT 2.1 library, installing now..." + # Requires luajit library + echo "Lua module requires LuaJIT 2.1 library, installing now..." - run cd "${BUILD_DIR}" || return 1 + run cd "${BUILD_DIR}" || return 1 - if [ ! -d luajit2 ]; then - run git clone -q https://github.com/openresty/luajit2.git && \ - run cd luajit2 || return 1 - else - run cd luajit2 && \ - run git fetch -q --all --tags - fi + if [ ! -d luajit2 ]; then + run git clone https://github.com/openresty/luajit2.git && \ + run cd luajit2 || return 1 + else + run cd luajit2 && \ + run git fetch -q --all --tags + fi - run git checkout "tags/${LUA_JIT_VERSION}" && \ - run make -j"${NB_PROC}" && \ - run make install + run git checkout "tags/${LUA_JIT_VERSION}" && \ + run make -j"${NB_PROC}" && \ + run make install - # Requires lua core library - echo "Lua module requires Lua Resty Core library, installing now..." + # Requires lua core library + echo "Lua module requires Lua Resty Core library, installing now..." - if [ ! -d lua-resty-core ]; then - run git clone -q https://github.com/openresty/lua-resty-core.git && \ - run cd lua-resty-core || return 1 - else - run cd lua-resty-core && \ - run git fetch -q --all --tags - fi + if [ ! -d lua-resty-core ]; then + run git clone https://github.com/openresty/lua-resty-core.git && \ + run cd lua-resty-core || return 1 + else + run cd lua-resty-core && \ + run git fetch -q --all --tags + fi - run git checkout "tags/${LUA_RESTY_CORE_VERSION}" && \ - run make install && \ - run cd ../ || return 1 + run git checkout "tags/${LUA_RESTY_CORE_VERSION}" && \ + run make install && \ + run cd ../ || return 1 - # Requires lua lru cache - echo "Lua module requires Lua-land LRU Cache library, installing now..." + # Requires lua lru cache + echo "Lua module requires Lua-land LRU Cache library, installing now..." - if [ ! -d lua-resty-lrucache ]; then - run git clone -q https://github.com/openresty/lua-resty-lrucache.git && \ - run cd lua-resty-lrucache || return 1 - else - run cd lua-resty-lrucache && \ - run git fetch -q --all --tags - fi + if [ ! -d lua-resty-lrucache ]; then + run git clone https://github.com/openresty/lua-resty-lrucache.git && \ + run cd lua-resty-lrucache || return 1 + else + run cd lua-resty-lrucache && \ + run git fetch -q --all --tags + fi - run git checkout "tags/${LUA_RESTY_LRUCACHE_VERSION}" && \ - run make install && \ - run cd "${EXTRA_MODULE_DIR}" || return 1 + run git checkout "tags/${LUA_RESTY_LRUCACHE_VERSION}" && \ + run make install && \ + run cd "${EXTRA_MODULE_DIR}" || return 1 - echo "Configuring Lua Nginx Module..." + echo "Configuring Lua Nginx Module..." - export LUAJIT_LIB=/usr/local/lib - export LUAJIT_INC=/usr/local/include/luajit-2.1 - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} --with-ld-opt=\"-Wl,-rpath,/usr/local/lib\"" + export LUAJIT_LIB=/usr/local/lib + export LUAJIT_INC=/usr/local/include/luajit-2.1 + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} --with-ld-opt=\"-Wl,-rpath,/usr/local/lib\"" - run git clone -q --branch="${LUA_NGINX_MODULE_VERSION}" --single-branch \ - https://github.com/openresty/lua-nginx-module.git + run git clone --branch="${LUA_NGINX_MODULE_VERSION}" --single-branch \ + https://github.com/openresty/lua-nginx-module.git - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/lua-nginx-module" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/lua-nginx-module" - fi - + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/lua-nginx-module" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/lua-nginx-module" fi + + fi - # Openresty Memc - An extended version of the standard memcached module. - if "${NGX_HTTP_MEMCACHED}"; then - echo "Adding ngx-http-memcached module..." + # Openresty Memc - An extended version of the standard memcached module. + if "${NGX_HTTP_MEMCACHED}"; then + echo "Adding ngx-http-memcached module..." - run git clone -q --branch="master" --single-branch https://github.com/openresty/memc-nginx-module.git + run git clone --branch="master" --single-branch https://github.com/openresty/memc-nginx-module.git - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/memc-nginx-module" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/memc-nginx-module" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/memc-nginx-module" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/memc-nginx-module" fi + fi - # NAXSI is an open-source, high performance, low rules maintenance WAF for Nginx. - if "${NGX_HTTP_NAXSI}"; then - echo "Adding ngx-http-naxsi (Web Application Firewall) module..." + # NAXSI is an open-source, high performance, low rules maintenance WAF for Nginx. + if "${NGX_HTTP_NAXSI}"; then + echo "Adding ngx-http-naxsi (Web Application Firewall) module..." - run git clone -q --branch="master" --single-branch https://github.com/nbs-system/naxsi.git + run git clone --branch="master" --single-branch https://github.com/nbs-system/naxsi.git - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/naxsi/naxsi_src" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/naxsi/naxsi_src" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/naxsi/naxsi_src" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/naxsi/naxsi_src" fi + fi - # NDK adds additional generic tools that module developers can use in their own modules. - if "${NGX_HTTP_NDK}"; then - echo "Adding ngx-http-ndk Nginx Devel Kit module..." + # NDK adds additional generic tools that module developers can use in their own modules. + if "${NGX_HTTP_NDK}"; then + echo "Adding ngx-http-ndk Nginx Devel Kit module..." - run git clone -q --branch="master" --single-branch https://github.com/vision5/ngx_devel_kit.git + run git clone --branch="master" --single-branch https://github.com/vision5/ngx_devel_kit.git - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/ngx_devel_kit" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/ngx_devel_kit" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/ngx_devel_kit" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/ngx_devel_kit" fi + fi - # NJS is a subset of the JavaScript language that allows extending nginx functionality. - # shellcheck disable=SC2153 - if "${NGX_HTTP_JS}"; then - echo "Adding ngx-http-js module..." + # NJS is a subset of the JavaScript language that allows extending nginx functionality. + # shellcheck disable=SC2153 + if "${NGX_HTTP_JS}"; then + echo "Adding ngx-http-js module..." - run git clone -q --branch="master" --single-branch https://github.com/nginx/njs.git + run git clone --branch="master" --single-branch https://github.com/nginx/njs.git - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/njs/nginx" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/njs/nginx" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/njs/nginx" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/njs/nginx" fi + fi - # Nginx mod HTTP Passenger. - if "${NGX_HTTP_PASSENGER}"; then - echo "Adding ngx-http-passenger module..." + # Nginx mod HTTP Passenger. + if "${NGX_HTTP_PASSENGER}"; then + echo "Adding ngx-http-passenger module..." - if [[ -n $(command -v passenger-config) ]]; then - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=$(passenger-config --nginx-addon-dir)" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=$(passenger-config --nginx-addon-dir)" - fi - else - error "Passenger module not found, skipped..." - fi + if [[ -n $(command -v passenger-config) ]]; then + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=$(passenger-config --nginx-addon-dir)" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=$(passenger-config --nginx-addon-dir)" + fi + else + error "Passenger module not found, skipped..." fi + fi - # Openresty Redis 2.0 protocol. - if "${NGX_HTTP_REDIS2}"; then - echo "Adding ngx-http-redis2 module..." + # Openresty Redis 2.0 protocol. + if "${NGX_HTTP_REDIS2}"; then + echo "Adding ngx-http-redis2 module..." - run git clone -q --branch="master" --single-branch https://github.com/openresty/redis2-nginx-module.git + run git clone --branch="master" --single-branch https://github.com/openresty/redis2-nginx-module.git - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/redis2-nginx-module" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/redis2-nginx-module" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/redis2-nginx-module" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/redis2-nginx-module" fi + fi - # A filter module which can do both regular expression and fixed string substitutions for nginx. - if "${NGX_HTTP_SUBS_FILTER}"; then - echo "Adding ngx-http-subs-filter module..." + # A filter module which can do both regular expression and fixed string substitutions for nginx. + if "${NGX_HTTP_SUBS_FILTER}"; then + echo "Adding ngx-http-subs-filter module..." - run git clone -q --branch="master" --single-branch https://github.com/yaoweibin/ngx_http_substitutions_filter_module.git + run git clone --branch="master" --single-branch https://github.com/yaoweibin/ngx_http_substitutions_filter_module.git - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/ngx_http_substitutions_filter_module" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/ngx_http_substitutions_filter_module" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/ngx_http_substitutions_filter_module" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/ngx_http_substitutions_filter_module" fi + fi - # Upstream Fair module enhances the standard round-robin load balancer provided with Nginx. - if "${NGX_HTTP_UPSTREAM_FAIR}"; then - echo "Adding ngx-http-nginx-upstream-fair module..." + # Upstream Fair module enhances the standard round-robin load balancer provided with Nginx. + if "${NGX_HTTP_UPSTREAM_FAIR}"; then + echo "Adding ngx-http-nginx-upstream-fair module..." - #run git clone -q https://github.com/gnosek/nginx-upstream-fair.git - run git clone -q --branch="lemper" https://github.com/joglomedia/nginx-upstream-fair + #run git clone https://github.com/gnosek/nginx-upstream-fair.git + run git clone --branch="lemper" https://github.com/joglomedia/nginx-upstream-fair - echo "Patch nginx-upstream-fair module with tengine-patches..." - run git clone -q --branch="master" --single-branch https://github.com/alibaba/tengine-patches.git + echo "Patch nginx-upstream-fair module with tengine-patches..." + run git clone --branch="master" --single-branch https://github.com/alibaba/tengine-patches.git - run cd nginx-upstream-fair && \ - run bash -c "patch -p1 < '${EXTRA_MODULE_DIR}/tengine-patches/nginx-upstream-fair/upstream-fair-upstream-check.patch'" - run cd "${EXTRA_MODULE_DIR}" || return 1 + run cd nginx-upstream-fair && \ + run bash -c "patch -p1 < '${EXTRA_MODULE_DIR}/tengine-patches/nginx-upstream-fair/upstream-fair-upstream-check.patch'" + run cd "${EXTRA_MODULE_DIR}" || return 1 - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - # Dynamic module not supported yet (testing lemper branch) - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/nginx-upstream-fair" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/nginx-upstream-fair" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + # Dynamic module not supported yet (testing lemper branch) + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/nginx-upstream-fair" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/nginx-upstream-fair" fi + fi - # Nginx virtual host traffic status module provides access to virtual host status information. - if "${NGX_HTTP_VTS}"; then - echo "Add ngxx-http-module-vts (VHost traffic status) module..." + # Nginx virtual host traffic status module provides access to virtual host status information. + if "${NGX_HTTP_VTS}"; then + echo "Add ngxx-http-module-vts (VHost traffic status) module..." - run git clone -q --branch="master" --single-branch https://github.com/vozlt/nginx-module-vts.git + run git clone --branch="master" --single-branch https://github.com/vozlt/nginx-module-vts.git - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/nginx-module-vts" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/nginx-module-vts" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/nginx-module-vts" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/nginx-module-vts" fi + fi - # HTTP XSLT module. - if "${NGX_HTTP_XSLT_FILTER}"; then - echo "Adding ngx-http-xslt-filter module..." + # HTTP XSLT module. + if "${NGX_HTTP_XSLT_FILTER}"; then + echo "Adding ngx-http-xslt-filter module..." - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --with-http_xslt_module=dynamic" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --with-http_xslt_module" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --with-http_xslt_module=dynamic" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --with-http_xslt_module" fi + fi - # Mail module. - if "${NGX_MAIL}"; then - echo "Adding ngx-mail module..." - - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --with-mail=dynamic \ - --with-mail_ssl_module" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --with-mail \ - --with-mail_ssl_module" - fi + # Mail module. + if "${NGX_MAIL}"; then + echo "Adding ngx-mail module..." + + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --with-mail=dynamic \ + --with-mail_ssl_module" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --with-mail \ + --with-mail_ssl_module" fi + fi - # Nchan pub/sub queuing server. - if "${NGX_NCHAN}"; then - echo "Adding ngx-nchan (Pub/Sub) module..." + # Nchan pub/sub queuing server. + if "${NGX_NCHAN}"; then + echo "Adding ngx-nchan (Pub/Sub) module..." - run git clone -q --branch="master" --single-branch https://github.com/slact/nchan.git + run git clone --branch="master" --single-branch https://github.com/slact/nchan.git - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/nchan" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/nchan" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/nchan" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/nchan" fi + fi - # RTMP media streaming server. - if "${NGX_RTMP}"; then - echo "Adding ngx-rtmp (Media Streaming Server) module..." + # RTMP media streaming server. + if "${NGX_RTMP}"; then + echo "Adding ngx-rtmp (Media Streaming Server) module..." - run git clone -q --branch="master" --single-branch https://github.com/arut/nginx-rtmp-module.git + run git clone --branch="master" --single-branch https://github.com/arut/nginx-rtmp-module.git - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/nginx-rtmp-module" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/nginx-rtmp-module" - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/nginx-rtmp-module" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/nginx-rtmp-module" fi + fi - # Stream module. - if "${NGX_STREAM}"; then - echo "Adding ngx-stream module..." - - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --with-stream=dynamic \ - --with-stream_geoip_module=dynamic \ - --with-stream_realip_module \ - --with-stream_ssl_module \ - --with-stream_ssl_preread_module" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --with-stream \ - --with-stream_geoip_module \ - --with-stream_realip_module \ - --with-stream_ssl_module \ - --with-stream_ssl_preread_module" - fi + # Stream module. + if "${NGX_STREAM}"; then + echo "Adding ngx-stream module..." + + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --with-stream=dynamic \ + --with-stream_geoip_module=dynamic \ + --with-stream_realip_module \ + --with-stream_ssl_module \ + --with-stream_ssl_preread_module" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --with-stream \ + --with-stream_geoip_module \ + --with-stream_realip_module \ + --with-stream_ssl_module \ + --with-stream_ssl_preread_module" + fi - if "${NGX_HTTP_LUA}"; then - echo "Adding ngx-stream-lua module..." + if "${NGX_HTTP_LUA}"; then + echo "Adding ngx-stream-lua module..." - run git clone -q --branch="master" --single-branch https://github.com/openresty/stream-lua-nginx-module.git + run git clone --branch="master" --single-branch https://github.com/openresty/stream-lua-nginx-module.git - if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-dynamic-module=${EXTRA_MODULE_DIR}/stream-lua-nginx-module" - else - NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ - --add-module=${EXTRA_MODULE_DIR}/stream-lua-nginx-module" - fi - fi + if [[ "${NGINX_DYNAMIC_MODULE}" == true ]]; then + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-dynamic-module=${EXTRA_MODULE_DIR}/stream-lua-nginx-module" + else + NGX_CONFIGURE_ARGS="${NGX_CONFIGURE_ARGS} \ + --add-module=${EXTRA_MODULE_DIR}/stream-lua-nginx-module" + fi fi fi + fi - run cd "${CURRENT_DIR}" || return 1 + run cd "${CURRENT_DIR}" || return 1 - # Build nginx from source installer. - echo -e "\nBuilding Nginx from source..." + # Build nginx from source installer. + echo -e "\nBuilding Nginx from source..." - #NGX_BUILD_URL="https://raw.githubusercontent.com/pagespeed/ngx_pagespeed/master/scripts/build_ngx_pagespeed.sh" - NGX_BUILD_URL="https://raw.githubusercontent.com/apache/incubator-pagespeed-ngx/master/scripts/build_ngx_pagespeed.sh" + #NGX_BUILD_URL="https://raw.githubusercontent.com/pagespeed/ngx_pagespeed/master/scripts/build_ngx_pagespeed.sh" + NGX_BUILD_URL="https://raw.githubusercontent.com/apache/incubator-pagespeed-ngx/master/scripts/build_ngx_pagespeed.sh" + if [[ -f "${BUILD_DIR}/build_nginx" ]]; then + echo "Using cached build_nginx script..." + else + echo "Downloading build_nginx script..." + if curl -sLI "${NGX_BUILD_URL}" | grep -q "HTTP/[.12]* [2].."; then - if [[ "${DRYRUN}" == true ]]; then - DRYRUN_ARG="--dryrun" - else - DRYRUN_ARG="" - fi - - run curl -sS -o "${BUILD_DIR}/build_nginx" "${NGX_BUILD_URL}" && \ - run bash "${BUILD_DIR}/build_nginx" -v latest-stable -n "${NGINX_RELEASE_VERSION}" --dynamic-module \ - -b "${BUILD_DIR}" -a "${NGX_CONFIGURE_ARGS}" -y "${DRYRUN_ARG}" + run curl -sS -o "${BUILD_DIR}/build_nginx" "${NGX_BUILD_URL}" else - error "Nginx from source installer not found." + fail "Nginx from source installer not found." fi - #fi + fi + + NGX_PAGESPEED_VERSION=${NGX_PAGESPEED_VERSION:-"latest-stable"} + NGX_BUILD_EXTRA_ARGS="" + + # Workaround for NPS issue https://github.com/apache/incubator-pagespeed-ngx/issues/1752 + if ! version_older_than "${NGINX_RELEASE_VERSION}" "1.22.99"; then + NGX_PAGESPEED_VERSION="master" + NGX_BUILD_EXTRA_ARGS="--psol-from-source" + fi + + [[ "${NGINX_DYNAMIC_MODULE}" == true ]] && NGX_BUILD_EXTRA_ARGS="${NGX_BUILD_EXTRA_ARGS} --dynamic-module" + [[ "${DRYRUN}" == true ]] && NGX_BUILD_EXTRA_ARGS="${NGX_BUILD_EXTRA_ARGS} --dryrun" + + # Build Nginx from source. + run bash "${BUILD_DIR}/build_nginx" -v "${NGX_PAGESPEED_VERSION}" -n "${NGINX_RELEASE_VERSION}" \ + -b "${BUILD_DIR}" -a "${NGX_CONFIGURE_ARGS}" -y "${NGX_BUILD_EXTRA_ARGS}" + echo "Configuring Nginx extra modules..." @@ -1584,7 +1600,9 @@ EOL CPU_CORES=$(grep -c processor /proc/cpuinfo) # Adjust worker processes. - #run sed -i "s/worker_processes\ auto/worker_processes\ ${CPU_CORES}/g" /etc/nginx/nginx.conf + if [[ "${CPU_CORES}" -gt 1 ]]; then + run sed -i "s/worker_processes\ auto/worker_processes\ ${CPU_CORES}/g" /etc/nginx/nginx.conf + fi local NGX_CONNECTIONS case ${CPU_CORES} in diff --git a/scripts/install_nodejs.sh b/scripts/install_nodejs.sh new file mode 100755 index 00000000..cc37ea83 --- /dev/null +++ b/scripts/install_nodejs.sh @@ -0,0 +1 @@ +# Ref: https://github.com/nodesource/distributions/blob/master/README.md#deb \ No newline at end of file diff --git a/scripts/install_phalcon.sh b/scripts/install_phalcon.sh index cd2c9273..6a3628b3 100755 --- a/scripts/install_phalcon.sh +++ b/scripts/install_phalcon.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -90,7 +90,7 @@ function install_phalcon() { run cd php-psr || return 1 else run cd php-psr && \ - run git pull -q + run git pull fi run "${PHPIZE_BIN}" && \ run ./configure --with-php-config="${PHPCONFIG_BIN}" && \ @@ -115,7 +115,7 @@ function install_phalcon() { CPHALCON_SOURCE="https://github.com/phalcon/cphalcon/archive/v${PHALCON_VERSION}.tar.gz" if curl -sLI "${CPHALCON_SOURCE}" | grep -q "HTTP/[.12]* [2].."; then - run wget -q -O "cphalcon-${PHALCON_VERSION}.tar.gz" "${CPHALCON_SOURCE}" && \ + run wget -O "cphalcon-${PHALCON_VERSION}.tar.gz" "${CPHALCON_SOURCE}" && \ run tar -zxf "cphalcon-${PHALCON_VERSION}.tar.gz" && \ run cd "cphalcon-${PHALCON_VERSION}/build" || return 1 elif curl -sLI "https://raw.githubusercontent.com/phalcon/cphalcon/${PHALCON_VERSION}/README.md" \ @@ -123,14 +123,14 @@ function install_phalcon() { # Clone repository. if [ ! -d cphalcon ]; then - run git clone -q https://github.com/phalcon/cphalcon.git && \ + run git clone https://github.com/phalcon/cphalcon.git && \ run cd cphalcon && \ run git checkout "${PHALCON_VERSION}" && \ run cd build || return 1 else run cd cphalcon && \ run git checkout "${PHALCON_VERSION}" && \ - run git pull -q && \ + run git pull && \ run cd build || return 1 fi else @@ -480,7 +480,7 @@ function init_phalcon_install() { if [[ -n $(command -v "php${PHPv}") ]]; then PHPLIB_DIR=$("php-config${PHPv}" | grep -wE "\--extension-dir" | cut -d'[' -f2 | cut -d']' -f1) if [[ ! -f "${PHPLIB_DIR}/phalcon.so" ]]; then - run apt-get install -qq -y "php-psr" "${PHP_PHALCON_PKG}" + run apt-get install -q -y "php-psr" "${PHP_PHALCON_PKG}" enable_phalcon "${PHPv}" else error "PHP ${PHPv} Phalcon extension already installed here ${PHPLIB_DIR}/phalcon.so." @@ -494,7 +494,7 @@ function init_phalcon_install() { if [[ -n $(command -v "php${PHPv}") ]]; then PHPLIB_DIR=$("php-config${PHPv}" | grep -wE "\--extension-dir" | cut -d'[' -f2 | cut -d']' -f1) if [[ ! -f "${PHPLIB_DIR}/phalcon.so" ]]; then - run apt-get install -qq -y "php${PHPv}-psr" "php${PHPv}-phalcon" + run apt-get install -q -y "php${PHPv}-psr" "php${PHPv}-phalcon" enable_phalcon "${PHPv}" else error "PHP ${PHPv} Phalcon extension already installed here ${PHPLIB_DIR}/phalcon.so." diff --git a/scripts/install_php.sh b/scripts/install_php.sh index 83e46eb0..b5f6c141 100755 --- a/scripts/install_php.sh +++ b/scripts/install_php.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -62,7 +62,8 @@ function add_php_repo() { esac info "Updating repository, please wait..." - run apt-get update -qq -y + run apt-get update -q -y && \ + run apt-get install -q -y libgd-dev libsodium-dev } ## @@ -141,7 +142,7 @@ function install_php() { echo "Installing PHP ${PHPv} and it's extensions..." if [[ "${#PHP_REPO_EXTS[@]}" -gt 0 ]]; then - run apt-get install -qq -y "php${PHPv}" "${PHP_REPO_EXTS[@]}" \ + run apt-get install -q -y "php${PHPv}" "${PHP_REPO_EXTS[@]}" \ dh-php php-common php-pear php-xml pkg-php-tools fcgiwrap spawn-fcgi fi @@ -284,10 +285,10 @@ function optimize_php_fpm() { run cp -f "etc/php/${PHPv}/fpm/php.ini" "/etc/php/${PHPv}/fpm/" else if [[ "${DRYRUN}" != true ]]; then - if [[ "${ENVIRONMENT}" =~ "prod" ]]; then + if [[ "${ENVIRONMENT}" == prod* ]]; then OVT="${OVT:-"0"}" else - OVT="${OVT:-"1"}" + OVT="${OVT:-"1"}" # Opcache is revalidated every file changes, good for development. fi cat >> "/etc/php/${PHPv}/fpm/php.ini" <> /home/${LEMPER_USERNAME}/.bashrc" run bash -c "echo '[ -d \"\$HOME/.composer/vendor/bin\" ] && export PATH=\"\$PATH:\$HOME/.composer/vendor/bin\"' >> /home/${LEMPER_USERNAME}/.bash_profile" run bash -c "echo '[ -d \"\$HOME/.composer/vendor/bin\" ] && export PATH=\"\$PATH:\$HOME/.composer/vendor/bin\"' >> /home/${LEMPER_USERNAME}/.profile" @@ -695,7 +697,7 @@ function install_ioncube_loader() { IC_ZIP_URL="https://raw.githubusercontent.com/joglomedia/php-loaders/main/${IC_ZIP_FILENAME}" if curl -sLI "${IC_ZIP_URL}" | grep -q "HTTP/[.12]* [2].."; then - run wget -q "${IC_ZIP_URL}" && \ + run wget "${IC_ZIP_URL}" && \ run tar -xzf "${IC_ZIP_FILENAME}" && \ run mv -f ioncube /usr/lib/php/loaders/ else @@ -766,7 +768,7 @@ function install_sourceguardian_loader() { SG_ZIP_URL="https://raw.githubusercontent.com/joglomedia/php-loaders/main/${SG_ZIP_FILENAME}" if curl -sLI "${SG_ZIP_URL}" | grep -q "HTTP/[.12]* [2].."; then - run wget -q "${SG_ZIP_URL}" && \ + run wget "${SG_ZIP_URL}" && \ run tar -xzf "${SG_ZIP_FILENAME}" && \ run mv -f "${BUILD_DIR}/sourceguardian" /usr/lib/php/loaders/ else @@ -947,10 +949,11 @@ function init_php_install() { echo " 3). PHP 7.1 (EOL)" echo " 4). PHP 7.2 (EOL)" echo " 5). PHP 7.3 (EOL)" - echo " 6). PHP 7.4 (SFO)" - echo " 7). PHP 8.0 (Stable)" - echo " 8). PHP 8.1 (Latest Stable)" - echo " 9). All available versions" + echo " 6). PHP 7.4 (EOL)" + echo " 7). PHP 8.0 (SFO)" + echo " 8). PHP 8.1 (Latest)" + echo " 9). PHP 8.2 (Latest Stable)" + echo " 10). All available versions" echo "--------------------------------------------" [[ -n "${DEFAULT_PHP_VERSION}" ]] && \ @@ -958,10 +961,12 @@ function init_php_install() { while [[ ${SELECTED_PHP} != "1" && ${SELECTED_PHP} != "2" && ${SELECTED_PHP} != "3" && \ ${SELECTED_PHP} != "4" && ${SELECTED_PHP} != "5" && ${SELECTED_PHP} != "6" && \ - ${SELECTED_PHP} != "7" && ${SELECTED_PHP} != "8" && ${SELECTED_PHP} != "9" && \ + ${SELECTED_PHP} != "7" && ${SELECTED_PHP} != "8" && \ + ${SELECTED_PHP} != "9" && ${SELECTED_PHP} != "10" && \ ${SELECTED_PHP} != "5.6" && ${SELECTED_PHP} != "7.0" && ${SELECTED_PHP} != "7.1" && \ ${SELECTED_PHP} != "7.2" && ${SELECTED_PHP} != "7.3" && ${SELECTED_PHP} != "7.4" && \ - ${SELECTED_PHP} != "8.0" && ${SELECTED_PHP} != "8.1" && ${SELECTED_PHP} != "all" ]]; do + ${SELECTED_PHP} != "8.0" && ${SELECTED_PHP} != "8.1" && \ + ${SELECTED_PHP} != "8.2" && ${SELECTED_PHP} != "all" ]]; do read -rp "Enter a PHP version from an option above [1-9]: " -i "${DEFAULT_PHP_VERSION}" -e SELECTED_PHP done @@ -988,11 +993,14 @@ function init_php_install() { SELECTED_PHP_VERSIONS+=("8.0") ;; 8 | "8.1") - SELECTED_PHP_VERSIONS+=("8.0") + SELECTED_PHP_VERSIONS+=("8.1") + ;; + 9 | "8.2") + SELECTED_PHP_VERSIONS+=("8.2") ;; - 9 | "all") + 10 | "all") # Select all PHP versions (except EOL & Beta). - SELECTED_PHP_VERSIONS=("5.6" "7.0" "7.1" "7.2" "7.3" "7.4" "8.0" "8.1") + SELECTED_PHP_VERSIONS=("5.6" "7.0" "7.1" "7.2" "7.3" "7.4" "8.0" "8.1" "8.2") ;; *) error "Your selected PHP version ${SELECTED_PHP} is not supported yet." @@ -1051,4 +1059,13 @@ if [[ -n $(command -v php5.6) && \ info "All available PHP version already exists, installation skipped." else init_php_install "$@" -fi + + # Set default PHP. + if [[ -n $(command -v "php${DEFAULT_PHP_VERSION}") ]]; then + run update-alternatives --set php "$(command -v "php${DEFAULT_PHP_VERSION}")" + run update-alternatives --set phar "$(command -v "phar${DEFAULT_PHP_VERSION}")" + run update-alternatives --set phar.phar "$(command -v "phar.phar${DEFAULT_PHP_VERSION}")" + run update-alternatives --set php-config "$(command -v "php-config${DEFAULT_PHP_VERSION}")" + run update-alternatives --set phpize "$(command -v "phpize${DEFAULT_PHP_VERSION}")" + fi +fi \ No newline at end of file diff --git a/scripts/install_pureftpd.sh b/scripts/install_pureftpd.sh index 61cb7f39..0efb1f8d 100755 --- a/scripts/install_pureftpd.sh +++ b/scripts/install_pureftpd.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -70,23 +70,24 @@ function init_pureftpd_install() { fi run cd "${BUILD_DIR}" && \ - run wget -q "${PUREFTPD_ZIP_URL}" && \ + run wget "${PUREFTPD_ZIP_URL}" && \ run tar -zxf "${PUREFTPD_FILENAME}" && \ run cd "${PUREFTPD_FILENAME%.*.*}" || return 1 # Enable MySQL support. - run ./configure --prefix=/usr --with-mysql --with-uploadscript --with-extauth --with-ftpwho --with-wrapper --with-virtualchroot --with-everything && \ + run ./configure --prefix=/usr --with-tls --with-mysql --with-puredb --with-uploadscript \ + --with-extauth --with-ftpwho --with-wrapper --with-virtualchroot --with-everything && \ # Make install. - run make && \ + run make && make check && \ run make install && \ run cd "${CURRENT_DIR}" || return 1 # Move executable to /usr/sbin. - #if [[ -x /usr/local/sbin/pure-ftpd ]]; then + if [[ -x /usr/local/sbin/pure-ftpd ]]; then # run mv /usr/local/sbin/pure-ftpd /usr/sbin/ - #run ln -sf /usr/local/sbin/pure-ftpd /usr/sbin/pure-ftpd - #fi + run ln -s /usr/local/sbin/pure-ftpd /usr/sbin/pure-ftpd + fi ;; *) # Skip installation. @@ -138,7 +139,7 @@ LimitRecursion 10000 8 AnonymousCanCreateDirs no MaxLoad 4 -PassivePortRange ${FTP_MIN_PORT} ${FTP_MAX_PORT} +# PassivePortRange ${FTP_MIN_PORT} ${FTP_MAX_PORT} # ForcePassiveIP ${SERVER_IP} # AntiWarez yes @@ -170,52 +171,65 @@ IPV4Only no EOL + + # Enable passv mode. + if [[ "${FTP_PASV_MODE}" == true ]]; then + run sed -i "s|^#\ PassivePortRange|PassivePortRange|g" /etc/pure-ftpd/pure-ftpd.conf + + # If we are behind NAT (such as AWS, GCP, Azure), set the Public IP. + if [[ "${SERVER_IP}" != "$(get_ip_private)" ]]; then + run sed -i "s|^#\ ForcePassiveIP|ForcePassiveIP|g" /etc/pure-ftpd/pure-ftpd.conf + fi + fi + # Enable SSL. - # TODO: Change the self-signed certificate with a valid Let's Encrypt certificate. if [[ "${FTP_SSL_ENABLE}" == true ]]; then + # Certificate files. + if [[ -n "${HOSTNAME_CERT_PATH}" && -f "${HOSTNAME_CERT_PATH}/fullchain.pem" ]]; then + RSA_CERT_FILE="${HOSTNAME_CERT_PATH}/fullchain.pem" + #RSA_KEY_FILE="${HOSTNAME_CERT_PATH}/privkey.pem" + elif [[ -f "/etc/lemper/ssl/${HOSTNAME}/cert.pem" ]]; then + RSA_CERT_FILE="/etc/lemper/ssl/${HOSTNAME}/cert.pem" + #RSA_KEY_FILE="/etc/lemper/ssl/${HOSTNAME}/privkey.pem" + else + RSA_CERT_FILE="/etc/ssl/certs/ssl-cert-snakeoil.pem" + #RSA_KEY_FILE="/etc/ssl/private/ssl-cert-snakeoil.key" + fi + cat >> /etc/pure-ftpd/pure-ftpd.conf </dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -101,7 +101,7 @@ function init_redis_install { fi if curl -sLI "${REDIS_DOWNLOAD_URL}" | grep -q "HTTP/[.12]* [2].."; then - run wget -q -O "redis.tar.gz" "${REDIS_DOWNLOAD_URL}" && \ + run wget -O "redis.tar.gz" "${REDIS_DOWNLOAD_URL}" && \ run tar -zxf "redis.tar.gz" && \ run cd redis-* && \ run make && \ @@ -166,6 +166,7 @@ function init_redis_install { # maxmemory ${REDISMEM_SIZE}mb maxmemory-policy allkeys-lru +#maxmemory-policy allkeys-lfu EOL # Is Redis password protected enable? @@ -182,31 +183,6 @@ EOL save_config "REDIS_PASSWORD=${REDIS_PASSWORD}" save_log -e "Redis server requirepass is enabled, here is your authentication password: ${REDIS_PASSWORD}\nSave this password and use it to authenticate your Redis connection (typically use -a parameter)." fi - - # Custom kernel optimization for Redis. - echo "Configure Redis kernel optimization." - - cat >> /etc/sysctl.conf < /sys/kernel/mm/transparent_hugepage/enabled" - - if [[ ! -f /etc/rc.local ]]; then - run touch /etc/rc.local - fi - - # Make the change persistent. - cat >> /etc/rc.local < /sys/kernel/mm/transparent_hugepage/enabled -EOL else info "Redis configuration skipped in dry run mode." fi diff --git a/scripts/install_tools.sh b/scripts/install_tools.sh index 039370ea..c44170a9 100755 --- a/scripts/install_tools.sh +++ b/scripts/install_tools.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -27,7 +27,8 @@ function init_tools_install() { echo -n "Installing LEMPer CLI tool..." run cp -f bin/lemper-cli.sh /usr/local/bin/lemper-cli && \ - run chmod ugo+x /usr/local/bin/lemper-cli + run chmod ugo+x /usr/local/bin/lemper-cli && \ + run ln -sf /usr/local/bin/lemper-cli /usr/bin/lemper-cli [ ! -d /etc/lemper/cli-plugins ] && run mkdir -p /etc/lemper/cli-plugins @@ -37,21 +38,21 @@ function init_tools_install() { run cp -f lib/lemper-site.sh /etc/lemper/cli-plugins/lemper-site && \ run chmod ugo+x /etc/lemper/cli-plugins/lemper-site - run cp -f lib/lemper-create.sh /etc/lemper/cli-plugins/lemper-create && \ - run chmod ugo+x /etc/lemper/cli-plugins/lemper-create && \ + #run cp -f lib/lemper-create.sh /etc/lemper/cli-plugins/lemper-create && \ + #run chmod ugo+x /etc/lemper/cli-plugins/lemper-create && \ run cp -f lib/lemper-create.sh /etc/lemper/cli-plugins/lemper-site-add && \ run chmod ugo+x /etc/lemper/cli-plugins/lemper-site-add - #[ ! -x /etc/lemper/cli-plugins/lemper-vhost ] && \ - # run ln -s /etc/lemper/cli-plugins/lemper-create /etc/lemper/cli-plugins/lemper-vhost + #run cp -f lib/lemper-manage.sh /etc/lemper/cli-plugins/lemper-manage && \ + #run chmod ugo+x /etc/lemper/cli-plugins/lemper-manage + + run cp -f lib/lemper-manage.sh /etc/lemper/cli-plugins/lemper-site-mod && \ + run chmod ugo+x /etc/lemper/cli-plugins/lemper-site-mod run cp -f lib/lemper-db.sh /etc/lemper/cli-plugins/lemper-db && \ run chmod ugo+x /etc/lemper/cli-plugins/lemper-db - run cp -f lib/lemper-manage.sh /etc/lemper/cli-plugins/lemper-manage && \ - run chmod ugo+x /etc/lemper/cli-plugins/lemper-manage - # Remove old LEMPer CLI tool. [ -d /usr/local/lib/lemper ] && run rm -fr /usr/local/lib/lemper/lemper-* @@ -105,7 +106,7 @@ function init_tools_install() { local CURRENT_DIR && \ CURRENT_DIR=$(pwd) run cd /usr/share/nginx/html/lcp/filemanager && \ - #run git pull -q + #run git pull run wget -q https://raw.githubusercontent.com/joglomedia/tinyfilemanager/lemperfm_1.3.0/index.php \ -O /usr/share/nginx/html/lcp/filemanager/index.php && \ run cd "${CURRENT_DIR}" || return 1 @@ -139,7 +140,7 @@ function init_tools_install() { CURRENT_DIR=$(pwd) run cd /usr/share/nginx/html/lcp/memcadmin && \ run git config --global --add safe.directory /usr/share/nginx/html/lcp/memcadmin && \ - run git pull -q && \ + run git pull && \ run cd "${CURRENT_DIR}" || return 1 fi diff --git a/scripts/install_vsftpd.sh b/scripts/install_vsftpd.sh index 98cfcbe0..69338298 100755 --- a/scripts/install_vsftpd.sh +++ b/scripts/install_vsftpd.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -50,23 +50,23 @@ function init_vsftpd_install() { done case "${SELECTED_INSTALLER}" in - 1 | "repo") + 1 | repo) echo "Installing FTP server (VSFTPD) from repository..." - run apt-get install -qq -y vsftpd + run apt-get install -q -y vsftpd ;; - 2 | "source") + 2 | source) echo "Installing FTP server (VSFTPD) from source..." # Install libraries. case "${DISTRIB_NAME}" in - "debian") + debian) case "${RELEASE_NAME}" in - "stretch") - run apt-get install -qq -y libpam0g libpam0g-dev libcapi20-3 libcapi20-dev \ - libcap-dev libcap2 libtirpc-common libtirpc-dev libtirpc1 + stretch) + run apt-get install -q -y libpam0g libpam0g-dev libcapi20-3 libcapi20-dev \ + libcap-dev libcap2 libtirpc-dev libtirpc1 ;; - "buster" | "bullseye") - run apt-get install -qq -y libpam0g libpam0g-dev libcapi20-3 libcapi20-dev \ + buster | bullseye) + run apt-get install -q -y libpam0g libpam0g-dev libcapi20-3 libcapi20-dev \ libcap-dev libcap2 libtirpc-common libtirpc-dev libtirpc3 ;; *) @@ -74,14 +74,14 @@ function init_vsftpd_install() { ;; esac ;; - "ubuntu") + ubuntu) case "${RELEASE_NAME}" in - "bionic") - run apt-get install -qq -y libpam0g libpam0g-dev libcapi20-3 libcapi20-dev \ + bionic) + run apt-get install -q -y libpam0g libpam0g-dev libcapi20-3 libcapi20-dev \ libcap-dev libcap2 libtirpc-dev libtirpc1 ;; - "focal") - run apt-get install -qq -y libpam0g libpam0g-dev libcapi20-3 libcapi20-dev \ + focal | jammy) + run apt-get install -q -y libpam0g libpam0g-dev libcapi20-3 libcapi20-dev \ libcap-dev libcap2 libtirpc-common libtirpc-dev libtirpc3 ;; *) @@ -89,11 +89,16 @@ function init_vsftpd_install() { ;; esac ;; + #centos | rocky*) + # run dnf install -q -y pam pam_cap libcap libcap-devel pam-devel libcap-devel libtirpc-devel + #;; *) fail "Unsupported OS distribution: ${DISTRIB_NAME^}." ;; esac + echo "Preparing to compile VSFTPD..." + # Fix error: sysdeputil.o: In function `vsf_sysdep_has_capabilities' LIB_GNU_DIR="/lib/${ARCH}-linux-gnu" @@ -103,12 +108,12 @@ function init_vsftpd_install() { LIB_DIR="/lib" fi - if [[ ! -f "${LIB_DIR}/libcap.so" ]]; then - if [[ -f "${LIB_GNU_DIR}/libcap.so.2" ]]; then + if [ ! -f "${LIB_DIR}/libcap.so" ]; then + if [ -f "${LIB_GNU_DIR}/libcap.so.2" ]; then run ln -s "${LIB_GNU_DIR}/libcap.so.2" "${LIB_DIR}/libcap.so" - elif [[ -f "${LIB_GNU_DIR}/libcap.so.1" ]]; then + elif [ -f "${LIB_GNU_DIR}/libcap.so.1" ]; then run ln -s "${LIB_GNU_DIR}/libcap.so.1" "${LIB_DIR}/libcap.so" - elif [[ -f "${LIB_GNU_DIR}/libcap.so" ]]; then + elif [ -f "${LIB_GNU_DIR}/libcap.so" ]; then run ln -s "${LIB_GNU_DIR}/libcap.so" "${LIB_DIR}/libcap.so" else echo "Cannot find libcap.so file." @@ -126,11 +131,18 @@ function init_vsftpd_install() { VSFTPD_ZIP_URL="https://security.appspot.com/downloads/${VSFTPD_FILENAME}" fi - run cd "${BUILD_DIR}" && \ - run wget -q "${VSFTPD_ZIP_URL}" && \ + run cd "${BUILD_DIR}" || return 1 + + if [ ! -f "${VSFTPD_FILENAME}" ]; then + echo "Downloading VSFTPD source code..." + run wget "${VSFTPD_ZIP_URL}" + fi + run tar -zxf "${VSFTPD_FILENAME}" && \ run cd "${VSFTPD_FILENAME%.*.*}" || return 1 + echo "Compile and install VSFTPD..." + # If SSL Enabled, modify the builddefs.h file. if [[ "${FTP_SSL_ENABLE}" == true ]]; then run sed -i 's/\#undef\ VSF_BUILD_SSL/\#define\ VSF_BUILD_SSL/g' ./builddefs.h @@ -164,7 +176,7 @@ function init_vsftpd_install() { FTP_MAX_PORT=${FTP_MAX_PORT:-45099} # Backup default vsftpd conf. - if [[ -f /etc/vsftpd.conf ]]; then + if [ -f /etc/vsftpd.conf ]; then run mv /etc/vsftpd.conf /etc/vsftpd.conf.bak fi @@ -188,9 +200,9 @@ allow_writeable_chroot=YES pam_service_name=vsftpd force_dot_files=YES -pasv_enable=YES -pasv_min_port=${FTP_MIN_PORT} -pasv_max_port=${FTP_MAX_PORT} +pasv_enable=NO +#pasv_min_port=${FTP_MIN_PORT} +#pasv_max_port=${FTP_MAX_PORT} #pasv_address=${SERVER_IP} #pasv_addr_resolve=YES @@ -202,9 +214,33 @@ userlist_file=/etc/vsftpd.userlist userlist_deny=NO EOL + # Enable passv mode. + if [[ "${FTP_PASV_MODE}" == true ]]; then + run sed -i 's/pasv_enable=NO/pasv_enable=YES/g' /etc/vsftpd.conf + run sed -i 's/\#pasv_min_port/pasv_min_port/g' /etc/vsftpd.conf + run sed -i 's/\#pasv_max_port/pasv_max_port/g' /etc/vsftpd.conf + + # If using elastic IP (such as AWS EC2), set the server IP. + if [[ "${ENVIRONMENT}" == prod* && "${SERVER_IP}" != "$(get_ip_private)" ]]; then + run sed -i "s|^#pasv_address=.*|pasv_address=${SERVER_IP}|g" /etc/vsftpd.conf + run sed -i "s|^#pasv_addr_resolve=.*|pasv_addr_resolve=YES|g" /etc/vsftpd.conf + fi + fi + # Enable SSL. - # TODO: Change the self-signed certificate with a valid Let's Encrypt certificate. if [[ "${FTP_SSL_ENABLE}" == true ]]; then + # Certificate files. + if [[ -n "${HOSTNAME_CERT_PATH}" && -f "${HOSTNAME_CERT_PATH}/fullchain.pem" ]]; then + RSA_CERT_FILE="${HOSTNAME_CERT_PATH}/fullchain.pem" + RSA_KEY_FILE="${HOSTNAME_CERT_PATH}/privkey.pem" + elif [[ -f "/etc/lemper/ssl/${HOSTNAME}/cert.pem" ]]; then + RSA_CERT_FILE="/etc/lemper/ssl/${HOSTNAME}/cert.pem" + RSA_KEY_FILE="/etc/lemper/ssl/${HOSTNAME}/privkey.pem" + else + RSA_CERT_FILE="/etc/ssl/certs/ssl-cert-snakeoil.pem" + RSA_KEY_FILE="/etc/ssl/private/ssl-cert-snakeoil.key" + fi + cat >> /etc/vsftpd.conf < /etc/pam.d/vsftpd < /etc/ftpusers </dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -24,17 +24,23 @@ function init_certbotle_removal() { echo "Found Certbot package installation. Removing..." # Remove Certbot. - run apt-get purge -qq -y certbot + run apt-get purge -q -y certbot [[ "${FORCE_REMOVE}" == true ]] && \ run add-apt-repository -y --remove ppa:certbot/certbot + elif snap list | awk '/certbot/ { print $1 }' | grep -qwE "^certbot$"; then + echo "Found Certbot snap installation. Removing..." + + # Remove Certbot. + [ -x /usr/bin/certbot ] && run unlink /usr/bin/certbot + [[ -n $(command -v snap) ]] && run snap remove certbot else echo "Certbot package not found, possibly installed from source." - echo "Remove it manually." CERTBOT_BIN=$(command -v certbot) - echo "Certbot binary executable: ${CERTBOT_BIN}" + + #run python -m pip uninstall certbot fi # Remove Certbot config files. diff --git a/scripts/remove_fail2ban.sh b/scripts/remove_fail2ban.sh index 25a6664d..191012d3 100755 --- a/scripts/remove_fail2ban.sh +++ b/scripts/remove_fail2ban.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -22,21 +22,21 @@ fi function init_fail2ban_removal() { # Stop fail2ban process. if [[ $(pgrep -c fail2ban-server) -gt 0 ]]; then + echo "Stopping fail2ban..." run systemctl stop fail2ban fi + run systemctl disable fail2ban + if dpkg-query -l | awk '/fail2ban/ { print $2 }' | grep -qwE "^fail2ban$"; then echo "Found fail2ban package installation. Removing..." - - run apt-get purge -qq -y fail2ban + run apt-get purge -q -y fail2ban && \ + run dpkg --purge fail2ban else info "Fail2ban package not found, possibly installed from source." - run rm -f /usr/local/bin/fail2ban-* fi - run dpkg --purge fail2ban - [ -f /etc/systemd/system/multi-user.target.wants/fail2ban.service ] && \ run unlink /etc/systemd/system/multi-user.target.wants/fail2ban.service [ -f /lib/systemd/system/fail2ban.service ] && run rm /lib/systemd/system/fail2ban.service diff --git a/scripts/remove_mailer.sh b/scripts/remove_mailer.sh index e46f754f..c891c416 100755 --- a/scripts/remove_mailer.sh +++ b/scripts/remove_mailer.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -21,14 +21,17 @@ fi function init_postfix_removal() { if [[ $(pgrep -c postfix) -gt 0 ]]; then + echo "Stopping postfix..." run systemctl stop postfix fi + run systemctl disable postfix + if dpkg-query -l | awk '/postfix/ { print $2 }' | grep -qwE "^postfix"; then echo "Found Postfix Mail-Transfer Agent package installation. Removing..." # shellcheck disable=SC2046 - run apt-get purge -qq -y postfix mailutils + run apt-get purge -q -y postfix mailutils else info "Postfix Mail-Transfer Agent package not found, possibly installed from source." echo "Remove it manually!!" @@ -37,7 +40,7 @@ function init_postfix_removal() { echo "Deleting Postfix binary executable: ${POSTFIX_BIN}" - [[ -x "${POSTFIX_BIN}" ]] && run rm -f "${POSTFIX_BIN}" + [[ -n $(command -v postfix) ]] && run rm -f "${POSTFIX_BIN}" fi warning "!! This action is not reversible !!" @@ -75,14 +78,17 @@ function init_postfix_removal() { function init_dovecot_removal() { if [[ $(pgrep -c dovecot) -gt 0 ]]; then + echo "Stopping dovecot..." run systemctl stop dovecot fi + run systemctl disable dovecot + if dpkg-query -l | awk '/dovecot/ { print $2 }' | grep -qwE "^dovecot"; then echo "Found Dovecot IMAP server package installation. Removing..." # shellcheck disable=SC2046 - run apt-get purge -qq -y dovecot-core dovecot-common dovecot-imapd dovecot-pop3d + run apt-get purge -q -y dovecot-core dovecot-common dovecot-imapd dovecot-pop3d else info "Dovecot IMAP server package not found, possibly installed from source." echo "Remove it manually!!" @@ -91,7 +97,7 @@ function init_dovecot_removal() { echo "Deleting Dovecot IMAP server executable: ${DOVECOT_BIN}" - [[ -x "${DOVECOT_BIN}" ]] && run rm -f "${DOVECOT_BIN}" + [[ -n "${DOVECOT_BIN}" ]] && run rm -f "${DOVECOT_BIN}" fi warning "!! This action is not reversible !!" @@ -136,7 +142,7 @@ function init_spfdkim_removal() { echo "Found OpenDKIM + SPF package installation. Removing..." # shellcheck disable=SC2046 - run apt-get purge -qq -y postfix-policyd-spf-python opendkim opendkim-tools + run apt-get purge -q -y postfix-policyd-spf-python opendkim opendkim-tools else info "OpenDKIM + SPF package not found, possibly installed from source." echo "Remove it manually!!" @@ -145,7 +151,7 @@ function init_spfdkim_removal() { echo "Deleting OpenDKIM executable: ${OPENDKIM_BIN}" - [[ -x "${OPENDKIM_BIN}" ]] && run rm -f "${OPENDKIM_BIN}" + [[ -x $(command -v opendkim) ]] && run rm -f "${OPENDKIM_BIN}" fi warning "!! This action is not reversible !!" diff --git a/scripts/remove_mariadb.sh b/scripts/remove_mariadb.sh index 5bd9d816..c66e790b 100755 --- a/scripts/remove_mariadb.sh +++ b/scripts/remove_mariadb.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -49,14 +49,17 @@ function init_mariadb_removal() { # Stop MariaDB mysql server process. if [[ $(pgrep -c mysqld) -gt 0 ]]; then + echo "Stopping mariadb..." run systemctl stop mysql fi + run systemctl disable mysql + if dpkg-query -l | awk '/mariadb/ { print $2 }' | grep -qwE "^mariadb-server-${MYSQL_VERSION}"; then echo "Found MariaDB ${MYSQL_VERSION} packages installation, removing..." # Remove MariaDB server. - run apt-get purge -qq -y libmariadb3 libmariadbclient18 "mariadb-client-${MYSQL_VERSION}" \ + run apt-get purge -q -y libmariadb3 libmariadbclient18 "mariadb-client-${MYSQL_VERSION}" \ "mariadb-client-core-${MYSQL_VERSION}" mariadb-common mariadb-server "mariadb-server-${MYSQL_VERSION}" \ "mariadb-server-core-${MYSQL_VERSION}" mariadb-backup @@ -72,7 +75,7 @@ function init_mariadb_removal() { echo "Found MySQL packages installation, removing..." # Remove MySQL server. - run apt-get purge -qq -y mysql-server mysql-client mysql-common mysql-server-core-* mysql-client-core-* + run apt-get purge -q -y mysql-server mysql-client mysql-common mysql-server-core-* mysql-client-core-* # Remove config. mariadb_remove_config diff --git a/scripts/remove_memcached.sh b/scripts/remove_memcached.sh index eaea0029..5250d3ad 100755 --- a/scripts/remove_memcached.sh +++ b/scripts/remove_memcached.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -22,6 +22,7 @@ fi function init_memcached_removal() { # Stop Memcached server process. if [[ $(pgrep -c memcached) -gt 0 ]]; then + echo "Stopping memcached..." #run service memcached@memcache stop #run service memcached@www-data stop # shellcheck disable=SC2046 @@ -32,7 +33,7 @@ function init_memcached_removal() { echo "Found Memcached package installation. Removing..." # Remove Memcached server. - run apt-get purge -qq -y libmemcached11 memcached php-igbinary \ + run apt-get purge -q -y libmemcached11 memcached php-igbinary \ php-memcache php-memcached php-msgpack else echo "Memcached package not found, possibly installed from source." @@ -42,7 +43,7 @@ function init_memcached_removal() { echo "Memcached binary executable: ${MEMCACHED_BIN}" - if [[ -n "${MEMCACHED_BIN}" ]]; then + if [[ -n $(command -v memcached) ]]; then # Disable systemctl. if [ -f /etc/systemd/system/multi-user.target.wants/memcached.service ]; then echo "Disabling Memcached service..." diff --git a/scripts/remove_mongodb.sh b/scripts/remove_mongodb.sh index b7054343..72236ff4 100755 --- a/scripts/remove_mongodb.sh +++ b/scripts/remove_mongodb.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -31,7 +31,7 @@ function remove_mongodb_repo() { if [[ -f "/etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}-${RELEASE_NAME}.list" ]]; then run rm -f "/etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}-${RELEASE_NAME}.list" - run apt-get update -qq -y + run apt-get update -q -y fi echo "Removing MongoDB repository key..." @@ -42,17 +42,18 @@ function remove_mongodb_repo() { function init_mongodb_removal() { # Stop MongoDB server process. if [[ $(pgrep -c mongod) -gt 0 ]]; then - echo "Stopping MongoDB server..." - + echo "Stopping mongodb..." run systemctl stop mongod fi + run systemctl disable mongod + if dpkg-query -l | awk '/mongodb/ { print $2 }' | grep -qwE "^mongodb"; then echo "Removing MongoDB packages..." # Remove MongoDB server. #shellcheck disable=SC2046 - run apt-get purge -qq -y $(dpkg-query -l | awk '/mongodb/ { print $2 }') + run apt-get purge -q -y $(dpkg-query -l | awk '/mongodb/ { print $2 }') if [[ "${AUTO_REMOVE}" == true ]]; then if [[ "${FORCE_REMOVE}" == true ]]; then diff --git a/scripts/remove_nginx.sh b/scripts/remove_nginx.sh index d8928fa7..602bb48f 100755 --- a/scripts/remove_nginx.sh +++ b/scripts/remove_nginx.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -23,9 +23,12 @@ fi function init_nginx_removal() { # Stop nginx HTTP server process. if [[ $(pgrep -c nginx) -gt 0 ]]; then + echo "Stopping nginx..." run systemctl stop nginx fi + run systemctl disable nginx + if [[ ${NGX_VERSION} == "mainline" || ${NGX_VERSION} == "latest" ]]; then local NGINX_REPO="nginx-mainline" else @@ -37,7 +40,7 @@ function init_nginx_removal() { echo "Found nginx-stable package installation, removing..." # shellcheck disable=SC2046 - run apt-get purge -qq -y $(dpkg-query -l | awk '/nginx/ { print $2 }' | grep -wE "^nginx") + run apt-get purge -q -y $(dpkg-query -l | awk '/nginx/ { print $2 }' | grep -wE "^nginx") if [[ "${FORCE_REMOVE}" == true ]]; then run add-apt-repository -y --remove ppa:nginx/stable fi @@ -45,7 +48,7 @@ function init_nginx_removal() { echo "Found nginx-custom package installation, removing..." # shellcheck disable=SC2046 - run apt-get purge -qq -y $(dpkg-query -l | awk '/nginx/ { print $2 }' | grep -wE "^nginx") + run apt-get purge -q -y $(dpkg-query -l | awk '/nginx/ { print $2 }' | grep -wE "^nginx") if [[ "${FORCE_REMOVE}" == true ]]; then run add-apt-repository -y --remove ppa:rtcamp/nginx fi @@ -53,7 +56,7 @@ function init_nginx_removal() { echo "Found nginx package installation, removing..." # shellcheck disable=SC2046 - run apt-get purge -qq -y $(dpkg-query -l | awk '/nginx/ { print $2 }' | grep -wE "^nginx") $(dpkg-query -l | awk '/libnginx/ { print $2 }' | grep -wE "^libnginx") + run apt-get purge -q -y $(dpkg-query -l | awk '/nginx/ { print $2 }' | grep -wE "^nginx") $(dpkg-query -l | awk '/libnginx/ { print $2 }' | grep -wE "^libnginx") if [[ "${FORCE_REMOVE}" == true ]]; then run add-apt-repository -y --remove "ppa:ondrej/${NGINX_REPO}" fi @@ -63,7 +66,7 @@ function init_nginx_removal() { NGINX_BIN=$(command -v nginx) - if [[ -n "${NGINX_BIN}" ]]; then + if [[ -n $(command -v nginx) ]]; then echo "Nginx binary executable: ${NGINX_BIN}" # Disable systemctl. diff --git a/scripts/remove_nodejs.sh b/scripts/remove_nodejs.sh new file mode 100755 index 00000000..e69de29b diff --git a/scripts/remove_php.sh b/scripts/remove_php.sh index b9c2c13a..ddb662de 100755 --- a/scripts/remove_php.sh +++ b/scripts/remove_php.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -33,9 +33,12 @@ function remove_php_fpm() { # Stop default PHP FPM process. if [[ $(pgrep -c "php-fpm${PHPv}") -gt 0 ]]; then + echo "Stopping php${PHPv}-fpm..." run systemctl stop "php${PHPv}-fpm" fi + run systemctl disable "php${PHPv}-fpm" + if dpkg-query -l | awk '/php/ { print $2 }' | grep -qwE "^php${PHPv}"; then echo "Removing PHP ${PHPv} packages installation..." @@ -59,7 +62,7 @@ function remove_php_fpm() { # Remove PHP packages. # shellcheck disable=SC2046 - run apt-get purge -qq -y $(dpkg-query -l | awk '/php/ { print $2 }' | grep -wE "^php${PHPv}") + run apt-get purge -q -y $(dpkg-query -l | awk '/php/ { print $2 }' | grep -wE "^php${PHPv}") # Remove PHP loaders. remove_php_loader "${PHPv}" "${REMOVED_PHP_LOADER}" @@ -393,7 +396,7 @@ function init_php_fpm_removal() { if [[ "${PHP_IS_EXISTS}" == false ]]; then echo "Removing additional unused PHP packages..." - run apt-get purge -qq -y dh-php php-common php-pear php-xml pkg-php-tools fcgiwrap spawn-fcgi + run apt-get purge -q -y dh-php php-common php-pear php-xml pkg-php-tools fcgiwrap spawn-fcgi # Remove openswoole official repository. if echo "${PHP_EXTENSIONS}" | grep -qwE "openswoole"; then diff --git a/scripts/remove_pureftpd.sh b/scripts/remove_pureftpd.sh index 98980c27..9005c8cd 100755 --- a/scripts/remove_pureftpd.sh +++ b/scripts/remove_pureftpd.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -22,13 +22,15 @@ fi function init_pureftpd_removal() { # Stop Pure-FTPd process. if [[ $(pgrep -c pure-ftpd) -gt 0 ]]; then + echo "Stopping pure-ftpd..." run systemctl stop pure-ftpd - run systemctl disable pure-ftpd fi + run systemctl disable pure-ftpd + if dpkg-query -l | awk '/pure-ftpd/ { print $2 }' | grep -qwE "^pure-ftpd$"; then echo "Found FTP server (Pure-FTPd) package installation. Removing..." - run apt-get purge -qq -y pure-ftpd pure-ftpd-common pure-ftpd-mysql + run apt-get purge -q -y pure-ftpd pure-ftpd-common pure-ftpd-mysql else info "FTP server (Pure-FTPd) package not found, possibly installed from source." echo "Remove it manually!!" @@ -36,7 +38,7 @@ function init_pureftpd_removal() { PUREFTPD_BIN=$(command -v pure-ftpd) echo "Deleting Pure-FTPd binary executable: ${PUREFTPD_BIN}" - [[ -x "${PUREFTPD_BIN}" ]] && run rm -f "${PUREFTPD_BIN}" + [[ -n $(command -v pure-ftpd) ]] && run rm -f "${PUREFTPD_BIN}" fi [[ -f /etc/systemd/system/multi-user.target.wants/pure-ftpd.service ]] && \ diff --git a/scripts/remove_redis.sh b/scripts/remove_redis.sh index 7f2a6d98..ef69beb5 100755 --- a/scripts/remove_redis.sh +++ b/scripts/remove_redis.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -22,15 +22,18 @@ fi function init_redis_removal() { # Stop Redis server process. if [[ $(pgrep -c redis-server) -gt 0 ]]; then + echo "Stopping redis-server..." run systemctl stop redis-server fi + run systemctl disable redis-server + # Remove Redis server. if dpkg-query -l | awk '/redis/ { print $2 }' | grep -qwE "^redis-server"; then echo "Found Redis package installation. Removing..." # shellcheck disable=SC2046 - run apt-get purge -qq -y $(dpkg-query -l | awk '/redis/ { print $2 }') + run apt-get purge -q -y $(dpkg-query -l | awk '/redis/ { print $2 }') if [[ "${FORCE_REMOVE}" == true ]]; then run add-apt-repository -y --remove ppa:chris-lea/redis-server fi @@ -42,7 +45,7 @@ function init_redis_removal() { echo "Deleting Redis binary executable: ${REDIS_BIN}" - [[ -x "${REDIS_BIN}" ]] && run rm -f "${REDIS_BIN}" + [[ -n $(command -v redis-server) ]] && run rm -f "${REDIS_BIN}" fi # Remove Redis config files. diff --git a/scripts/remove_vsftpd.sh b/scripts/remove_vsftpd.sh index 6564df4a..cc579496 100755 --- a/scripts/remove_vsftpd.sh +++ b/scripts/remove_vsftpd.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -22,13 +22,15 @@ fi function init_vsftpd_removal() { # Stop VSFTPD process. if [[ $(pgrep -c vsftpd) -gt 0 ]]; then + echo "Stopping vsftpd..." run systemctl stop vsftpd - run systemctl disable vsftpd fi + run systemctl disable vsftpd + if dpkg-query -l | awk '/vsftpd/ { print $2 }' | grep -qwE "^vsftpd$"; then echo "Found FTP server (VSFTPD) package installation. Removing..." - run apt-get purge -qq -y vsftpd + run apt-get purge -q -y vsftpd else info "FTP server (VSFTPD) package not found, possibly installed from source." echo "Remove it manually!!" @@ -36,7 +38,7 @@ function init_vsftpd_removal() { VSFTPD_BIN=$(command -v vsftpd) echo "Deleting vsftpd binary executable: ${VSFTPD_BIN}" - [[ -x "${VSFTPD_BIN}" ]] && run rm -f "${VSFTPD_BIN}" + [[ -n $(command -v vsftpd) ]] && run rm -f "${VSFTPD_BIN}" fi [[ -f /etc/systemd/system/multi-user.target.wants/vsftpd.service ]] && \ @@ -60,9 +62,11 @@ function init_vsftpd_removal() { fi if [[ "${REMOVE_VSFTPD_CONFIG}" == y* || "${REMOVE_VSFTPD_CONFIG}" == Y* ]]; then - [[ -f /etc/vsftpd.conf ]] && run rm -f /etc/vsftpd.conf - [[ -f /etc/vsftpd.conf.bak ]] && run rm -f /etc/vsftpd.conf.bak - [[ -f /etc/vsftpd.userlist ]] && run rm -f /etc/vsftpd.userlist + [ -f /etc/vsftpd.conf ] && run rm -f /etc/vsftpd.conf + [ -f /etc/vsftpd.conf.bak ] && run rm -f /etc/vsftpd.conf.bak + [ -f /etc/vsftpd.userlist ] && run rm -f /etc/vsftpd.userlist + [ -f /etc/ftpusers ] && run rm -f /etc/ftpusers + [ -f /etc/pam.d/vsftpd ] && run rm -f /etc/pam.d/vsftpd echo "All configuration files deleted permanently." fi diff --git a/scripts/cleanup_server.sh b/scripts/server_cleanup.sh similarity index 94% rename from scripts/cleanup_server.sh rename to scripts/server_cleanup.sh index 6534bf6a..d8897dab 100755 --- a/scripts/cleanup_server.sh +++ b/scripts/server_cleanup.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -30,7 +30,7 @@ if [[ "${FIX_BROKEN_INSTALL}" == true ]]; then [ -f /var/cache/apt/archives/lock ] && run rm /var/cache/apt/archives/lock run dpkg --configure -a - run apt --fix-broken install -qq -y + run apt --fix-broken install -q -y fi # Remove Apache2 service if exists. @@ -55,7 +55,7 @@ if [[ -n $(command -v apache2) || -n $(command -v httpd) ]]; then run systemctl stop apache2 # shellcheck disable=SC2046 - run apt-get purge -qq -y $(dpkg-query -l | awk '/apache2/ { print $2 }') \ + run apt-get purge -q -y $(dpkg-query -l | awk '/apache2/ { print $2 }') \ $(dpkg-query -l | awk '/httpd/ { print $2 }') else echo "Removing Apache2 installation in dry run mode." @@ -125,9 +125,9 @@ fi # Autoremove unused packages. echo -e "\nCleaning up unnecessary packages..." -run apt-get autoremove -qq -y && \ -run apt-get autoclean -qq -y && \ -run apt-get clean -qq -y +run apt-get autoremove -q -y && \ +run apt-get autoclean -q -y && \ +run apt-get clean -q -y if [[ -z $(command -v apache2) && -z $(command -v nginx) && -z $(command -v mysql) ]]; then status "Your server cleaned up." diff --git a/scripts/server_optimization.sh b/scripts/server_optimization.sh new file mode 100755 index 00000000..6dee7607 --- /dev/null +++ b/scripts/server_optimization.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env bash + +# Basic Server Security Hardening +# Min. Requirement : GNU/Linux Ubuntu 18.04 +# Last Build : 06/08/2022 +# Author : MasEDI.Net (me@masedi.net) +# Since Version : 2.6.4 + +# Include helper functions. +if [[ "$(type -t run)" != "function" ]]; then + BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) + # shellcheck disable=SC1091 + . "${BASE_DIR}/utils.sh" + + # Make sure only root can run this installer script. + requires_root "$@" + + # Make sure only supported distribution can run this installer script. + preflight_system_check +fi + +function init_server_optimization() { + ### Create and enable swap ### + if [[ "${ENABLE_SWAP}" == true ]]; then + echo "" + enable_swap + fi + + ### Create and enable sysctl ### + echo "Configure kernel optimization..." + + # Adjust swappiness, default Ubuntu set to 60 + # meaning that the swap file will be used fairly often if the memory usage is + # around half RAM, for production servers you may need to set a lower value. + if [[ "${ENABLE_SWAP}" == true ]]; then + echo "Adjusting swappiness..." + + if [[ $(cat /proc/sys/vm/swappiness) -gt 10 ]]; then + if [[ ${DRYRUN} != true ]]; then + run sed -i "s/vm.swappiness/#vm.swappiness/" /etc/sysctl.conf + cat >> /etc/sysctl.conf <> /etc/sysctl.conf <> /etc/sysctl.conf <> /etc/sysctl.conf < /sys/kernel/mm/transparent_hugepage/enabled" + + if [[ ! -f /etc/rc.local ]]; then + run touch /etc/rc.local + fi + + # Make the change persistent. + cat >> /etc/rc.local < /sys/kernel/mm/transparent_hugepage/enabled +EOL + fi + + run sysctl -p +} + +echo "[LEMPer Stack Basic Server Optimization]" + +# Start running things from a call at the end so if this script is executed +# after a partial download it doesn't do anything. +init_server_optimization "$@" \ No newline at end of file diff --git a/scripts/secure_server.sh b/scripts/server_security.sh similarity index 97% rename from scripts/secure_server.sh rename to scripts/server_security.sh index ead45c79..29d76c77 100755 --- a/scripts/secure_server.sh +++ b/scripts/server_security.sh @@ -10,7 +10,7 @@ if [[ "$(type -t run)" != "function" ]]; then BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ) # shellcheck disable=SC1091 - . "${BASE_DIR}/helper.sh" + . "${BASE_DIR}/utils.sh" # Make sure only root can run this installer script. requires_root "$@" @@ -152,7 +152,8 @@ EOL fi # Save config. - save_config -e "HOSTNAME=${HOSTNAME}\nSERVER_IP=${SERVER_IP}\nSSH_PORT=${SSH_PORT}" + #save_config -e "HOSTNAME=${HOSTNAME}\nSERVER_IP=${SERVER_IP}\nSSH_PORT=${SSH_PORT}" + run sudo sed -i "s|^SERVER_SSH_PORT=[0-9]*|SERVER_SSH_PORT=${SSH_PORT}|g" /etc/lemper/lemper.conf # Save log. save_log "Default SSH port updated to ${SSH_PORT}." @@ -185,7 +186,7 @@ function install_ufw() { fi # Install UFW - run apt-get install -qq -y ufw + run apt-get install -q -y ufw # UFW app rules is here /etc/ufw/applications.d if [[ -n $(command -v ufw) ]]; then @@ -287,7 +288,7 @@ function install_csf() { if [[ -n $(command -v cpan) ]]; then run cpan -i "LWP LWP::Protocol::https GD::Graph IO::Socket::INET6" else - run apt-get install -qq -y libwww-perl liblwp-protocol-https-perl \ + run apt-get install -q -y libwww-perl liblwp-protocol-https-perl \ libgd-graph-perl libio-socket-inet6-perl fi @@ -297,7 +298,7 @@ function install_csf() { echo "Installing CSF+LFD firewall..." if curl -sLI https://download.configserver.com/csf.tgz | grep -q "HTTP/[.12]* [2].."; then - run wget -q https://download.configserver.com/csf.tgz && \ + run wget https://download.configserver.com/csf.tgz && \ run tar -xzf csf.tgz && \ run cd csf/ && \ run sh install.sh && \ @@ -407,7 +408,7 @@ function install_apf() { if curl -sLI "https://github.com/rfxn/advanced-policy-firewall/archive/${APF_VERSION}.tar.gz" \ | grep -q "HTTP/[.12]* [2].."; then - run wget -q "https://github.com/rfxn/advanced-policy-firewall/archive/${APF_VERSION}.tar.gz" && \ + run wget "https://github.com/rfxn/advanced-policy-firewall/archive/${APF_VERSION}.tar.gz" && \ run tar -xf "${APF_VERSION}.tar.gz" && \ run cd advanced-policy-firewall-*/ && \ run bash install.sh && \ @@ -462,7 +463,7 @@ function remove_ufw() { echo "Removing UFW iptables firewall..." - run apt-get remove -qq -y ufw + run apt-get remove -q -y ufw fi } @@ -543,7 +544,7 @@ Any other iptables based firewall will be removed otherwise they will conflict." # Ensure that iptables installed. if [[ -z $(command -v iptables) ]]; then echo "Iptables is required, trying to install it first..." - run apt-get install -qq -y iptables + run apt-get install -q -y iptables fi case "${SELECTED_FW_CONFIGURATOR}" in diff --git a/scripts/helper.sh b/scripts/utils.sh old mode 100644 new mode 100755 similarity index 96% rename from scripts/helper.sh rename to scripts/utils.sh index 0fc7d406..2e531b1f --- a/scripts/helper.sh +++ b/scripts/utils.sh @@ -2,7 +2,7 @@ # Helper Functions # Min. Requirement : GNU/Linux Ubuntu 18.04 -# Last Build : 29/01/2022 +# Last Build : 06/08/2022 # Author : MasEDI.Net (me@masedi.net) # Since Version : 1.0.0 @@ -20,7 +20,7 @@ fi # Export environment variables. ENVFILE=$(echo "${BASE_DIR}/.env" | sed '$ s|\/scripts\/.env$|\/.env|') -if [[ -f "${ENVFILE}" ]]; then +if [ -f "${ENVFILE}" ]; then # Clean environemnt first. # shellcheck source=.env.dist # shellcheck disable=SC2046 @@ -219,7 +219,7 @@ function delete_if_already_exists() { if [[ "${DRYRUN}" == true ]]; then return; fi local directory="${1}" - if [[ -d "${directory}" ]]; then + if [ -d "${directory}" ]; then if [[ ${#directory} -lt 8 ]]; then fail "Not deleting ${directory}; name is suspiciously short. Something is wrong." fi @@ -338,7 +338,7 @@ function validate_fqdn() { # Get general distribution name. function get_distrib_name() { - if [[ -f "/etc/os-release" ]]; then + if [ -f /etc/os-release ]; then # Export os-release vars. . /etc/os-release @@ -359,7 +359,7 @@ function get_distrib_name() { # Get general release name. function get_release_name() { - if [[ -f "/etc/os-release" ]]; then + if [ -f /etc/os-release ]; then # Export os-release vars. . /etc/os-release @@ -367,7 +367,11 @@ function get_release_name() { [ -f /etc/lsb-release ] && . /etc/lsb-release # Get distribution name. - [[ "${ID_LIKE}" == "ubuntu" ]] && DISTRIB_NAME="ubuntu" || DISTRIB_NAME=${ID:-"unsupported"} + if [[ "${ID_LIKE}" == "ubuntu" ]]; then + DISTRIB_NAME="ubuntu" + else + DISTRIB_NAME=${ID:-"unsupported"} + fi # Get distribution release / version ID. DISTRO_VERSION=${VERSION_ID:-"${DISTRIB_RELEASE}"} @@ -422,9 +426,9 @@ function get_release_name() { # TODO for Amzn install ;; - centos) + centos | fedora | rocky) # CentOS - RELEASE_NAME="unsupported" + RELEASE_NAME="rhel" # TODO for CentOS install ;; @@ -432,7 +436,7 @@ function get_release_name() { RELEASE_NAME="unsupported" ;; esac - elif [[ -e /etc/system-release ]]; then + elif [ -f /etc/system-release ]; then RELEASE_NAME="unsupported" else # Red Hat /etc/redhat-release @@ -584,32 +588,13 @@ function create_swap() { else echo "Add persistent swap to fstab in dry run mode." fi - - # Adjust swappiness, default Ubuntu set to 60 - # meaning that the swap file will be used fairly often if the memory usage is - # around half RAM, for production servers you may need to set a lower value. - if [[ $(cat /proc/sys/vm/swappiness) -gt 10 ]]; then - if [[ ${DRYRUN} != true ]]; then - cat >> /etc/sysctl.conf <