diff --git a/bin/v-bunkerweb-migrate b/bin/v-bunkerweb-migrate new file mode 100644 index 0000000..a409ffc --- /dev/null +++ b/bin/v-bunkerweb-migrate @@ -0,0 +1,127 @@ +#!/opt/brepo/ruby33/bin/ruby +# info: utility to prepare existing server with hestiacp to use bunkerweb +# do not run this script n the server, where bunkerweb was installed with hestiacp +# installation +# options: COMMAND +# +# example: v-bunkerweb-migrate migrate-nginx +# +# Commands: +# migratenginx - move old nginx configs to the new port and path +# migratetobunkerweb - create items of sites in the bunkerweb database + +#------------------------------------------# +# Variables & Functions # +#------------------------------------------# + +# Argument definition +v_command = ARGV[0] + +require "/usr/local/hestia/func_ruby/global_options" + +load_ruby_options_defaults +$HESTIA = load_hestia_default_path_from_env + +require "main" +require "modules" +require "HestiaBunkerWebApi" + +require 'json' unless defined?(JSON) +require 'fileutils' + +def copy_nginx_files(src_root, dest_root) + FileUtils.mkdir_p(dest_root) + Dir.foreach(src_root) do |entry| + next if entry == '.' || entry == '..' + next if entry == 'modules' || entry == 'modules-enabled' + src_path = File.join(src_root, entry) + dest_path = File.join(dest_root, entry) + if File.directory?(src_path) + FileUtils.mkdir_p(dest_path) + copy_nginx_files(src_path, dest_path) + else + FileUtils.cp(src_path, dest_path) + end + end +end + +# Function to log and execute migration stages +def log_migrate_stage(stage) + log_file = '/usr/local/hestia/log/bunkerweb_migrate_stages.log' + # Check if the stage has already been recorded + if File.exist?(log_file) && File.readlines(log_file).any? { |line| line.strip == stage } + puts "Stage #{stage} already completed, skipping." + return + end + # Execute the stage block + begin + yield + # Record the successful stage + File.open(log_file, 'a') { |f| f.puts stage } + puts "Stage #{stage} completed." + rescue => e + hestia_print_error_message_to_cli "Stage #{stage} failed: #{e.message}" + exit 1 + end +end + +hestia_check_privileged_user + +load_global_bash_variables "/etc/hestiacp/hestia.conf" +if $HESTIA.nil? + hestia_print_error_message_to_cli "Can't find HESTIA base path" + exit 1 +end + +load_global_bash_variables "#{$HESTIA}/conf/hestia.conf" + +#------------------------------------------# +# Verifications # +#------------------------------------------# + +check_args 1, ARGV, "COMMAND" + +# Perform verification if read-only mode is enabled +check_hestia_demo_mode + +#------------------------------------------# +# Action # +#------------------------------------------# + +case v_command.to_sym +when :migratenginx + log_migrate_stage('stage1') do + if $BUNKERWEB.nil? + hestia_change_sys_config_value("BUNKERWEB", "yes") + end + end + log_migrate_stage('stage2') do + unless system('yum install -y nginx-system') + hestia_print_error_message_to_cli "Failed to install nginx-system via yum" + log_event E_ARGS, $ARGUMENTS + exit 1 + end + end + log_migrate_stage('stage3') do + hestia_change_sys_config_value("PROXY_PORT", "8078") + hestia_change_sys_config_value("PROXY_SSL_PORT", "8079") + end + log_migrate_stage('stage4') do + FileUtils.rm_f Dir.glob('/usr/local/hestia/nginx-system/etc/nginx/conf.d/*.conf') + src_root = '/etc/nginx' + dest_root = '/usr/local/hestia/nginx-system/etc/nginx' + copy_nginx_files(src_root, dest_root) + end + #stage5 замена /etc/nginx на /usr/local/hestia/nginx-system/etc/nginx + #stage6 замена портов на 8078 + #stage7 проверить, нужно ли что-то менять в шаблонах + #stage8 активация из запуск nginx-system +when :migratetobunkerweb + #TODO настройка bunkerweb +else + hestia_print_error_message_to_cli "unknown command" + log_event E_ARGS, $ARGUMENTS + exit 1 +end + +exit 0 diff --git a/func_ruby/main.rb b/func_ruby/main.rb index cd03a34..051d5bd 100644 --- a/func_ruby/main.rb +++ b/func_ruby/main.rb @@ -315,3 +315,72 @@ def hestia_save_file_key_pair(file, key, value) end end end + +def hestia_change_sys_config_value(key, value) + # Privileged access check + hestia_check_privileged_user unless Process.uid == 0 + + config_file = "/usr/local/hestia/conf/hestia.conf" + + if File.exist?(config_file) + File.open(config_file, File::RDWR | File::LOCK_SH) do |f| + # Check if key exists in the configuration file + existing_line_index = -1 + + f.each_with_index do |line, idx| + line_stripped = line.strip + # Skip comment lines + next if line_stripped.start_with?("#") + next if line_stripped.empty? + + key_match = line_stripped.match(/^\s*#{Regexp.escape(key)}='\s*(.*?)\s*$/) + if key_match + existing_line_index = idx + 1 + break + end + end + + if existing_line_index.nil? || existing_line_index == -1 + # Key doesn't exist - append new line to file + File.open(config_file, "a") do |append_f| + append_f.flock(File::LOCK_EX) + append_f.puts("#{key}='#{value}'") + end + OK + else + # Key exists - update value using Ruby operators (in-place edit) + # Use temporary file for safety and atomic replacement + temp_file = "#{config_file}.tmp" + + File.open(config_file, "r") do |input_f| + lines = [] + + input_f.each do |line| + line_stripped = line.strip + # Skip comment lines + next if line_stripped.start_with?("#") + next if line_stripped.empty? + + # Match and replace the key-value pair + if line.match(/^\s*#{Regexp.escape(key)}='[^']*'/) + lines << "#{key}='#{value}'" + else + lines << line + end + end + + File.open(temp_file, "w") do |output_f| + output_f.flock(File::LOCK_EX) + lines.each { |l| output_f.puts(l) } + end + + # Atomic file replacement + File.rename(temp_file, config_file) + OK + end + end + end + else + check_result error_code: E_NOTEXIST, error_message: "Configuration file #{config_file} does not exist" + end +end