diff --git a/dapostinstall.sh b/dapostinstall.sh index d3288da..b9bdbd8 100755 --- a/dapostinstall.sh +++ b/dapostinstall.sh @@ -449,7 +449,7 @@ da build secure_php echo "Optymalizacja MySQL" cd $DAPOSTINSTALL_DIR -\cp -f my.cnf /etc/my.cnf +bash "$DAPOSTINSTALL_DIR/my-cnf-gen.sh" --output /etc/my.cnf systemctl restart mysqld echo "Instalacja bezpiecznego DMARC" diff --git a/my-cnf-gen.sh b/my-cnf-gen.sh new file mode 100755 index 0000000..aadad66 --- /dev/null +++ b/my-cnf-gen.sh @@ -0,0 +1,274 @@ +#!/usr/bin/env bash +set -euo pipefail + +MARIADB_MEMORY_PERCENT=25 +MIN_BUFFER_POOL_MB=256 +MAX_CONNECTIONS_MIN=80 +MAX_CONNECTIONS_MAX=300 + +usage() { + cat <<'EOF' +Usage: + my-cnf-gen.sh [--output PATH] + +Generates a conservative MariaDB 10.6 my.cnf for DirectAdmin servers. +The InnoDB buffer pool is sized to about 25% RAM so other DA services +such as web, exim, dovecot, redis and spam filtering keep enough memory. +EOF +} + +read_mem_total_mb() { + local mem_bytes + + if [[ -n "${MYSQL_GEN_MEM_MB:-}" ]]; then + printf '%s\n' "$MYSQL_GEN_MEM_MB" + return 0 + fi + + if [[ -r /proc/meminfo ]]; then + awk '/^MemTotal:/ { printf "%d\n", int($2 / 1024) }' /proc/meminfo + return 0 + fi + + mem_bytes="$(sysctl -n hw.memsize 2>/dev/null || true)" + if [[ -n "$mem_bytes" ]]; then + printf '%d\n' "$((mem_bytes / 1024 / 1024))" + return 0 + fi + + echo "Unable to detect total memory" >&2 + exit 1 +} + +read_cpu_cores() { + local cores + cores="" + + if [[ -n "${MYSQL_GEN_CPU_CORES:-}" ]]; then + printf '%s\n' "$MYSQL_GEN_CPU_CORES" + return 0 + fi + + if [[ -r /proc/cpuinfo ]]; then + cores="$(grep -c '^processor[[:space:]]*:' /proc/cpuinfo 2>/dev/null || true)" + fi + if [[ -z "$cores" || "$cores" -lt 1 ]]; then + cores="$(getconf _NPROCESSORS_ONLN 2>/dev/null || true)" + fi + if [[ -z "$cores" || "$cores" -lt 1 ]]; then + cores=1 + fi + printf '%s\n' "$cores" +} + +round_down_mb() { + local value_mb="$1" + local step_mb="$2" + local rounded + + rounded=$((value_mb / step_mb * step_mb)) + if (( rounded < step_mb )); then + rounded="$step_mb" + fi + printf '%s\n' "$rounded" +} + +format_size() { + local value_mb="$1" + + if (( value_mb >= 1024 && value_mb % 1024 == 0 )); then + printf '%sG\n' "$((value_mb / 1024))" + else + printf '%sM\n' "$value_mb" + fi +} + +calc_buffer_pool_mb() { + local mem_mb="$1" + local pool_mb + + pool_mb=$((mem_mb * MARIADB_MEMORY_PERCENT / 100)) + if (( pool_mb < MIN_BUFFER_POOL_MB )); then + pool_mb="$MIN_BUFFER_POOL_MB" + fi + round_down_mb "$pool_mb" 128 +} + +calc_buffer_pool_instances() { + local pool_mb="$1" + local cores="$2" + local instances=1 + + if (( pool_mb >= 8192 && cores >= 4 )); then + instances=4 + elif (( pool_mb >= 4096 && cores >= 2 )); then + instances=2 + fi + printf '%s\n' "$instances" +} + +calc_max_connections() { + local mem_mb="$1" + local cores="$2" + local connections + + connections=$((mem_mb / 128)) + if (( connections < MAX_CONNECTIONS_MIN )); then + connections="$MAX_CONNECTIONS_MIN" + fi + if (( connections > MAX_CONNECTIONS_MAX )); then + connections="$MAX_CONNECTIONS_MAX" + fi + if (( cores <= 2 && connections > 120 )); then + connections=120 + fi + printf '%s\n' "$connections" +} + +calc_log_file_mb() { + local pool_mb="$1" + local log_mb + + log_mb=$((pool_mb / 4)) + if (( log_mb < 128 )); then + log_mb=128 + elif (( log_mb > 1024 )); then + log_mb=1024 + fi + round_down_mb "$log_mb" 128 +} + +generate_config() { + local mem_mb="$1" + local cores="$2" + local pool_mb="$3" + local pool_instances="$4" + local max_connections="$5" + local log_file_mb="$6" + local io_capacity="$7" + local io_capacity_max="$8" + + cat <&2; exit 1; } + output="$1" + ;; + --help|-h) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 1 + ;; + esac + shift + done + + mem_mb="$(read_mem_total_mb)" + cores="$(read_cpu_cores)" + pool_mb="$(calc_buffer_pool_mb "$mem_mb")" + pool_instances="$(calc_buffer_pool_instances "$pool_mb" "$cores")" + max_connections="$(calc_max_connections "$mem_mb" "$cores")" + log_file_mb="$(calc_log_file_mb "$pool_mb")" + io_capacity=$((cores * 100)) + if (( io_capacity < 200 )); then + io_capacity=200 + elif (( io_capacity > 800 )); then + io_capacity=800 + fi + io_capacity_max=$((io_capacity * 2)) + + if [[ -n "$output" ]]; then + generate_config "$mem_mb" "$cores" "$pool_mb" "$pool_instances" "$max_connections" "$log_file_mb" "$io_capacity" "$io_capacity_max" > "$output" + else + generate_config "$mem_mb" "$cores" "$pool_mb" "$pool_instances" "$max_connections" "$log_file_mb" "$io_capacity" "$io_capacity_max" + fi +} + +main "$@" diff --git a/my.cnf b/my.cnf index 5735b29..256c392 100644 --- a/my.cnf +++ b/my.cnf @@ -1,67 +1,72 @@ +[client] +port=3306 +socket=/var/lib/mysql/mysql.sock +default-character-set=utf8mb4 [mysql] - -[client] -port = 3306 -socket = /var/lib/mysql/mysql.sock +default-character-set=utf8mb4 [mysqld] -local-infile = 0 -character-set-server=utf8 -collation-server=utf8_general_ci -sort_buffer_size=512K +# MariaDB 10.6 baseline for DirectAdmin stack hosts. +user=mysql +port=3306 +socket=/var/lib/mysql/mysql.sock +pid-file=/var/lib/mysql/mysql.pid +datadir=/var/lib/mysql + +# Security and compatibility +local_infile=0 +skip_name_resolve=1 +symbolic_links=0 +max_connect_errors=1000000 +max_allowed_packet=64M + +# Character set +character-set-server=utf8mb4 +collation-server=utf8mb4_unicode_ci skip-character-set-client-handshake -# GENERAL # -user = mysql -default-storage-engine = InnoDB -socket = /var/lib/mysql/mysql.sock -pid-file = /var/lib/mysql/mysql.pid +# Storage engines +default_storage_engine=InnoDB +myisam_recover_options=FORCE,BACKUP +key_buffer_size=32M -#Odhasowac tylko i wylaczenie gdy w kodzie sa stosowane zapytania i niewlasciwej skladni, -#od nowszych wersji mysql jest wymuszneie prawidlowej, optymalnej skladni do wersji 10.1 nie byla sprawdzana +# Connection and table limits +max_connections=200 +max_user_connections=50 +thread_cache_size=64 +table_open_cache=2048 +table_definition_cache=1024 +open_files_limit=65535 -#sql_mode="" +# Per-connection buffers kept intentionally small for shared DA hosts +sort_buffer_size=512K +join_buffer_size=512K +read_buffer_size=256K +read_rnd_buffer_size=512K -# MyISAM # -key-buffer-size = 128M -myisam-recover-options = FORCE,BACKUP +# Temporary tables +tmp_table_size=32M +max_heap_table_size=32M -# SAFETY # -max-allowed-packet = 16M -max-connect-errors = 1000000 -skip-name-resolve +# Query cache disabled for multi-core mixed workloads +query_cache_type=0 +query_cache_size=0 -# DATA STORAGE # -datadir = /var/lib/mysql/ - -# CACHES AND LIMITS # -tmp-table-size = 32M -max-heap-table-size = 32M -query-cache-type = 1 -query-cache-limit = 256K -query-cache-min-res-unit = 2k -query-cache-size = 80M -max-connections = 500 -max-user-connections = 100 -thread-cache-size = 16 -open-files-limit = 65535 -table-definition-cache = 4096 -table-open-cache = 10240 - -# INNODB # -innodb-log-files-in-group = 2 -innodb-log-file-size = 128M -innodb-flush-log-at-trx-commit = 1 -innodb-buffer-pool-size = 1G -innodb-buffer-pool-instances = 1 +# InnoDB +innodb_buffer_pool_size=1G +innodb_buffer_pool_instances=1 +innodb_log_file_size=256M +innodb_log_files_in_group=2 +innodb_flush_log_at_trx_commit=1 innodb_flush_method=O_DIRECT -#moze opozniac dzialania jak create zalecane gdy duze bazy danych -innodb_file_per_table = 1 -innodb_file_format = barracuda +innodb_file_per_table=1 +innodb_io_capacity=200 +innodb_io_capacity_max=400 -# LOGGING # -log-error = /var/lib/mysql/mysql-error.log -log-queries-not-using-indexes = 1 -slow-query-log = 0 -slow-query-log-file = /var/lib/mysql/mysql-slow.log +# Logging +log_error=/var/lib/mysql/mysql-error.log +slow_query_log=0 +slow_query_log_file=/var/lib/mysql/mysql-slow.log +long_query_time=2 +log_queries_not_using_indexes=0 diff --git a/tests/quality_checks.sh b/tests/quality_checks.sh index 63f8a9a..a0cde74 100644 --- a/tests/quality_checks.sh +++ b/tests/quality_checks.sh @@ -69,6 +69,7 @@ assert_plain_tar_archive_clean_for_linux_tar() { assert_bash_syntax "$ROOT_DIR/dapostinstall.sh" assert_bash_syntax "$ROOT_DIR/da_cli.sh" assert_bash_syntax "$ROOT_DIR/daupdate.sh" +assert_bash_syntax "$ROOT_DIR/my-cnf-gen.sh" php -l "$ROOT_DIR/lang_pl.php" >/dev/null || fail "lang_pl.php has invalid PHP syntax" assert_archive_clean_for_linux_tar "$ROOT_DIR/spolszczenie_enhanced.tar.gz" @@ -194,6 +195,21 @@ assert_file_not_contains "$ROOT_DIR/dapostinstall.sh" 'redis_migrate\.sh' assert_file_not_contains "$ROOT_DIR/dapostinstall.sh" 'redis_management\.tar\.gz' assert_file_not_contains "$ROOT_DIR/dapostinstall.sh" 'plugins/redis_management' assert_file_not_contains "$ROOT_DIR/dapostinstall.sh" 'tar -zxf imapsync\.tar\.gz' +assert_file_contains "$ROOT_DIR/dapostinstall.sh" 'bash "\$DAPOSTINSTALL_DIR/my-cnf-gen\.sh" --output /etc/my\.cnf' +assert_file_contains "$ROOT_DIR/my.cnf" 'character-set-server=utf8mb4' +assert_file_contains "$ROOT_DIR/my.cnf" 'collation-server=utf8mb4_unicode_ci' +assert_file_contains "$ROOT_DIR/my.cnf" 'query_cache_type=0' +assert_file_contains "$ROOT_DIR/my.cnf" 'query_cache_size=0' +assert_file_not_contains "$ROOT_DIR/my.cnf" 'query-cache-type' +assert_file_not_contains "$ROOT_DIR/my.cnf" 'query-cache-size' +assert_file_not_contains "$ROOT_DIR/my.cnf" 'innodb_file_format' +assert_file_contains "$ROOT_DIR/my-cnf-gen.sh" 'MARIADB_MEMORY_PERCENT=25' +assert_file_contains "$ROOT_DIR/my-cnf-gen.sh" 'MYSQL_GEN_MEM_MB' +assert_file_contains "$ROOT_DIR/my-cnf-gen.sh" 'MYSQL_GEN_CPU_CORES' +assert_file_contains "$ROOT_DIR/my-cnf-gen.sh" '/proc/meminfo' +assert_file_contains "$ROOT_DIR/my-cnf-gen.sh" '/proc/cpuinfo' +assert_file_contains "$ROOT_DIR/my-cnf-gen.sh" 'innodb_buffer_pool_size' +assert_file_contains "$ROOT_DIR/my-cnf-gen.sh" 'MariaDB 10.6' assert_file_contains "$ROOT_DIR/mail_powitalny.txt" '\{\{DA_HOSTNAME\}\}' assert_file_contains "$ROOT_DIR/mail_powitalny.txt" '\{\{DA_HASLO\}\}' assert_file_contains "$ROOT_DIR/mail_powitalny.txt" '\{\{DA_PHP_LIST\}\}' @@ -210,6 +226,12 @@ source "$COMMON_SH" tmp_dir="$(mktemp -d)" trap 'rm -rf "$tmp_dir"' EXIT +generated_my_cnf="$tmp_dir/generated-my.cnf" +MYSQL_GEN_MEM_MB=8192 MYSQL_GEN_CPU_CORES=4 "$ROOT_DIR/my-cnf-gen.sh" --output "$generated_my_cnf" +grep -qx 'innodb_buffer_pool_size=2G' "$generated_my_cnf" || fail "generated my.cnf should allocate 25% of 8G to InnoDB" +grep -qx 'max_connections=80' "$generated_my_cnf" || fail "generated my.cnf should keep low-RAM max_connections conservative" +grep -qx 'query_cache_size=0' "$generated_my_cnf" || fail "generated my.cnf should disable query cache" + kv_file="$tmp_dir/example.conf" printf 'ns1=old.example\nother=value\n' > "$kv_file" set_key_value "$kv_file" "ns1" "dns3.hitme.net.pl"