Compare commits
27 Commits
aae561716c
...
bunkerweb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
317e3e215e | ||
|
|
4f999094f3 | ||
|
|
5e32af0148 | ||
|
|
6ff9d67909 | ||
|
|
af9e6bfb82 | ||
|
|
e0419fea4b | ||
|
|
3cc428df43 | ||
|
|
9d1afcdf28 | ||
|
|
adef1a98bb | ||
|
|
3263dbecab | ||
|
|
3c5a5924d6 | ||
|
|
8b911372af | ||
|
|
a3888d10b4 | ||
|
|
8add078e7c | ||
|
|
54f549db62 | ||
|
|
fd67d9c546 | ||
|
|
86bf9fccf5 | ||
|
|
f64f034b7b | ||
|
|
dae9aca295 | ||
|
|
592b954a9f | ||
|
|
4b023ea671 | ||
|
|
4cb55905cc | ||
|
|
d76624ff43 | ||
|
|
27b237a3c7 | ||
|
|
5349d46d71 | ||
|
|
75df7a2554 | ||
|
|
479a65e0dd |
@@ -79,9 +79,9 @@ EOF
|
||||
chown root:$user $fastcgi
|
||||
chmod 640 $fastcgi
|
||||
|
||||
str="fastcgi_cache_path /var/cache/nginx/micro/$domain levels=1:2"
|
||||
str="fastcgi_cache_path /usr/local/hestia/nginx-system/var/cache/nginx/micro/$domain levels=1:2"
|
||||
str="$str keys_zone=$domain:10m max_size=512m inactive=30m use_temp_path=off;"
|
||||
conf='/etc/nginx/conf.d/fastcgi_cache_pool.conf'
|
||||
conf='/usr/local/hestia/nginx-system/etc/nginx/conf.d/fastcgi_cache_pool.conf'
|
||||
if [ -f "$conf" ]; then
|
||||
if [ -z "$(grep "=${domain}:" $conf)" ]; then
|
||||
echo "$str" >> $conf
|
||||
@@ -90,7 +90,7 @@ else
|
||||
echo "$str" >> $conf
|
||||
fi
|
||||
|
||||
mkdir -p /var/cache/nginx/micro/$domain
|
||||
mkdir -p /usr/local/hestia/nginx-system/var/cache/nginx/micro/$domain
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Hestia #
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
# www.domain.tld type will be automatically assigned to the domain unless
|
||||
# "none" is transmited as argument. If ip have associated dns name, this
|
||||
# domain will also get the alias domain-tpl.$ipname. An alias with the ip
|
||||
# name is useful during the site testing while dns isn't moved to server yet.
|
||||
# name is useful during the site testing while dns isn't moved to server yaliet.
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
@@ -251,6 +251,15 @@ check_result $? "Web restart failed" > /dev/null
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
# Execute bunkerweb_module if it's enabled
|
||||
module_state=$($BIN/v-ext-modules state bunkerweb_module json | jq -r '.[0].STATE')
|
||||
if [ "$module_state" = "enabled" ]; then
|
||||
$BIN/v-ext-modules-run bunkerweb_module add "$domain" "$ip"
|
||||
if [ -n "%$ALIAS" ]; then
|
||||
$BIN/v-ext-modules-run bunkerweb_module alias "$domain" "$ALIAS"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Added new web domain (Name: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
@@ -108,6 +108,13 @@ check_result $? "Web restart failed" > /dev/null
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
# Execute bunkerweb_module if it's enabled
|
||||
module_state=$($BIN/v-ext-modules state bunkerweb_module json | jq -r '.[0].STATE')
|
||||
if [ "$module_state" = "enabled" ]; then
|
||||
get_domain_values 'web'
|
||||
$BIN/v-ext-modules-run bunkerweb_module alias "$domain" "$ALIAS"
|
||||
fi
|
||||
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Added new web domain alias (Alias: $aliases, Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
|
||||
@@ -136,6 +136,25 @@ if [ -n "$UPDATE_SSL_SCRIPT" ]; then
|
||||
eval "$UPDATE_SSL_SCRIPT $user $domain"
|
||||
fi
|
||||
|
||||
# Execute bunkerweb_module if it's enabled
|
||||
module_state=$($BIN/v-ext-modules state bunkerweb_module json | jq -r '.[0].STATE')
|
||||
if [ "$module_state" = "enabled" ] && [ "$BUNKERWEB" = "yes" ]; then
|
||||
BUNKW_DIR=$HOMEDIR/$user/conf/web/$domain/ssl/bunkerweb
|
||||
if [ ! -d "$BUNKW_DIR" ]; then
|
||||
mkdir -p "$BUNKW_DIR"
|
||||
chmod 0755 "$BUNKW_DIR"
|
||||
fi
|
||||
cp -f "$HOMEDIR/$user/conf/web/$domain/ssl/$domain.crt" "$BUNKW_DIR/"
|
||||
cp -f "$HOMEDIR/$user/conf/web/$domain/ssl/$domain.key" "$BUNKW_DIR/"
|
||||
cp -f "$HOMEDIR/$user/conf/web/$domain/ssl/$domain.pem" "$BUNKW_DIR/"
|
||||
if [ -e "$HOMEDIR/$user/conf/web/$domain/ssl/$domain.ca" ]; then
|
||||
cp -f "$HOMEDIR/$user/conf/web/$domain/ssl/$domain.ca" "$BUNKW_DIR/"
|
||||
fi
|
||||
chown root:nginx "$BUNKW_DIR"/*
|
||||
chmod 0640 "$BUNKW_DIR"/*
|
||||
$BIN/v-ext-modules-run bunkerweb_module addssl "$domain" "$BUNKW_DIR/$domain.pem" "$BUNKW_DIR/$domain.key"
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Added certificate and enabled SSL (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
@@ -84,10 +84,10 @@ if [ "$LOCAL_PHP" == "yes" ]; then
|
||||
fi
|
||||
else
|
||||
# Packages in Remi repo have names with php$version-php- prefixes
|
||||
mph="php$version-php-fpm php$version-php-cgi php$version-php-mysqlnd php$version-php-pgsql
|
||||
php$version-php-pdo php$version-php-common php$version-php-pecl-imagick php$version-php-imap
|
||||
php$version-php-ldap php$version-php-pecl-apcu php$version-php-pecl-zip php$version-php-cli
|
||||
php$version-php-opcache php$version-php-xml php$version-php-gd php$version-php-intl
|
||||
mph="php$version-php-fpm php$version-php-cgi php$version-php-mysqlnd php$version-php-pgsql
|
||||
php$version-php-pdo php$version-php-common php$version-php-pecl-imagick php$version-php-imap
|
||||
php$version-php-ldap php$version-php-pecl-apcu php$version-php-pecl-zip php$version-php-cli
|
||||
php$version-php-opcache php$version-php-xml php$version-php-gd php$version-php-intl
|
||||
php$version-php-mbstring php$version-php-pspell php$version-php-readline"
|
||||
if [ "$version" = "56" ]; then
|
||||
mph=$(sed -e "s/php$version-php-pecl-apcu//")
|
||||
@@ -156,23 +156,15 @@ else
|
||||
fi
|
||||
|
||||
# Check if required modules for apache2 are enabled
|
||||
if [ "$WEB_SYSTEM" = "apache2" ]; then
|
||||
if [ -f /etc/redhat-release ]; then
|
||||
if ! httpd -M | grep 'proxy_fcgi_module' ; then
|
||||
sed 's/#LoadModule proxy_fcgi_module/LoadModule proxy_fcgi_module/' -i /etc/httpd/conf.modules.d/00-proxy.conf
|
||||
sed 's/#LoadModule proxy_module/LoadModule proxy_module/' -i /etc/httpd/conf.modules.d/00-proxy.conf
|
||||
fi
|
||||
if ! httpd -M | grep 'setenvif_module' ; then
|
||||
sed 's/#LoadModule setenvif_module/LoadModule setenvif_module/' -i /etc/httpd/conf.modules.d/00-base.conf
|
||||
fi
|
||||
else
|
||||
if ! a2query -q -m proxy_fcgi; then
|
||||
a2enmod -q proxy_fcgi
|
||||
fi
|
||||
if ! a2query -q -m setenvif; then
|
||||
a2enmod -q setenvif
|
||||
fi
|
||||
if [ "$WEB_SYSTEM" = "httpd" ]; then
|
||||
if ! httpd -M | grep 'proxy_fcgi_module' ; then
|
||||
sed 's/#LoadModule proxy_fcgi_module/LoadModule proxy_fcgi_module/' -i /etc/httpd/conf.modules.d/00-proxy.conf
|
||||
sed 's/#LoadModule proxy_module/LoadModule proxy_module/' -i /etc/httpd/conf.modules.d/00-proxy.conf
|
||||
fi
|
||||
if ! httpd -M | grep 'setenvif_module' ; then
|
||||
sed 's/#LoadModule setenvif_module/LoadModule setenvif_module/' -i /etc/httpd/conf.modules.d/00-base.conf
|
||||
fi
|
||||
|
||||
$BIN/v-restart-web "yes"
|
||||
fi
|
||||
|
||||
|
||||
574
bin/v-bunkerweb-migrate
Executable file
574
bin/v-bunkerweb-migrate
Executable file
@@ -0,0 +1,574 @@
|
||||
#!/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'
|
||||
require 'time'
|
||||
require 'pathname'
|
||||
|
||||
|
||||
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 }
|
||||
hestia_print_error_message_to_cli "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 }
|
||||
hestia_print_info_message_to_cli "Stage #{stage} completed."
|
||||
rescue => e
|
||||
hestia_print_error_message_to_cli "Stage #{stage} failed: #{e.message}"
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
|
||||
# Function to parse and migrate nginx.conf from /usr/local/hestia/nginx-system/etc/nginx/nginx.conf
|
||||
def migrate_nginx_config_from_file(source_path)
|
||||
return false unless File.exist?(source_path)
|
||||
|
||||
hestia_print_info_message_to_cli "Processing nginx config from: #{source_path}"
|
||||
|
||||
content = File.read(source_path)
|
||||
original_content = content.dup
|
||||
|
||||
modified = false
|
||||
|
||||
# Replace all paths starting with /var/ to /usr/local/hestia/nginx-system/var/
|
||||
# This pattern matches any absolute path that starts with /var/ anywhere in the line
|
||||
content = content.gsub(/\/var\//, '/usr/local/hestia/nginx-system/var/')
|
||||
|
||||
# Replace pid path from /run/nginx.pid to /run/nginx-system.pid
|
||||
content = content.gsub(/pid\s+\S+/) { |match| match.gsub('/run/nginx.pid', '/run/nginx-system.pid') }
|
||||
|
||||
if content != original_content
|
||||
File.write(source_path, content)
|
||||
hestia_print_info_message_to_cli "Updated config: #{source_path}"
|
||||
modified = true
|
||||
end
|
||||
|
||||
modified
|
||||
end
|
||||
|
||||
def parse_listen(line)
|
||||
# Попытка найти IP:port
|
||||
m = line.match(/^\s*listen\s+([^\s:]+):(\d+)/i)
|
||||
return [m[1], m[2]] if m
|
||||
# Если только порт после listen
|
||||
m = line.match(/^\s*listen\s+(\d+);?\s*$/i)
|
||||
return [nil, m[1]] if m
|
||||
nil
|
||||
end
|
||||
|
||||
# Helper function to parse and replace ports in listen directives using temp placeholders
|
||||
def parse_and_replace_listen_directive(line, proxy_port, proxy_ssl_port)
|
||||
return line unless line.match?(/\blisten\b/i)
|
||||
|
||||
new_line = line.dup
|
||||
|
||||
# Define target ports (always migrate to these values regardless of input)
|
||||
target_http_port = '8078'
|
||||
target_ssl_port = '8079'
|
||||
|
||||
result = parse_listen(line)
|
||||
return line unless result
|
||||
ip, port = result
|
||||
|
||||
if port == proxy_port
|
||||
if ip
|
||||
new_line.gsub!("#{ip}:#{port}", "#{ip}:#{target_http_port}")
|
||||
else
|
||||
new_line.gsub!(port, target_http_port)
|
||||
end
|
||||
elsif port == proxy_ssl_port
|
||||
if ip
|
||||
new_line.gsub!("#{ip}:#{port}", "#{ip}:#{target_ssl_port}")
|
||||
else
|
||||
new_line.gsub!(port, target_ssl_port)
|
||||
end
|
||||
end
|
||||
|
||||
new_line
|
||||
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('stage0') do
|
||||
# Create backup of /etc/nginx with timestamp
|
||||
|
||||
timestamp = Time.now.strftime('%Y%m%d_%H%M%S')
|
||||
backup_root = "/etc/nginx_backup_#{timestamp}"
|
||||
FileUtils.mkdir_p(backup_root)
|
||||
|
||||
src_root = '/etc/nginx'
|
||||
dest_root = backup_root
|
||||
|
||||
# Custom copy function to handle symlinks in conf.d/domains
|
||||
def copy_with_symlinks(src, dest)
|
||||
Dir.foreach(src) do |entry|
|
||||
next if entry == '.' || entry == '..'
|
||||
src_path = File.join(src, entry)
|
||||
dest_path = File.join(dest, entry)
|
||||
|
||||
if File.symlink?(src_path)
|
||||
# Check if symlink is inside conf.d/domains
|
||||
if src_path.include?(File.join('conf.d', 'domains'))
|
||||
# Resolve the target of the symlink
|
||||
target_path = File.readlink(src_path)
|
||||
# Resolve relative symlink paths
|
||||
unless Pathname.new(target_path).absolute?
|
||||
target_path = File.expand_path(target_path, File.dirname(src_path))
|
||||
end
|
||||
if File.exist?(target_path) && File.file?(target_path)
|
||||
content = File.read(target_path)
|
||||
new_file_name = "#{entry}_content.conf"
|
||||
new_file_path = File.join(dest, new_file_name)
|
||||
File.write(new_file_path, content)
|
||||
end
|
||||
else
|
||||
# Preserve the symlink as is
|
||||
FileUtils.mkdir_p(File.dirname(dest_path))
|
||||
target = File.readlink(src_path)
|
||||
FileUtils.ln_s(target, dest_path)
|
||||
end
|
||||
elsif File.directory?(src_path)
|
||||
FileUtils.mkdir_p(dest_path)
|
||||
copy_with_symlinks(src_path, dest_path)
|
||||
else
|
||||
FileUtils.cp(src_path, dest_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
copy_with_symlinks(src_root, dest_root)
|
||||
end
|
||||
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
|
||||
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
|
||||
log_migrate_stage('stage4') do
|
||||
# Find all files under the nginx-system directory
|
||||
nginx_conf_dir = '/usr/local/hestia/nginx-system/etc/nginx'
|
||||
Dir.glob(File.join(nginx_conf_dir, '**', '*')).each do |path|
|
||||
hestia_print_info_message_to_cli "stage 4 processing file #{path}"
|
||||
next if File.directory?(path)
|
||||
content = File.read(path)
|
||||
new_content = content.gsub(/(?<!\/usr\/local\/hestia\/nginx-system)\/etc\/nginx/, '/usr/local/hestia/nginx-system/etc/nginx')
|
||||
if new_content != content
|
||||
hestia_print_info_message_to_cli "Changed path to config in file #{path}"
|
||||
File.open(path, 'w') { |f| f.write(new_content) }
|
||||
end
|
||||
end
|
||||
end
|
||||
log_migrate_stage('stage4.1') do
|
||||
# Parse nginx.conf file to replace paths
|
||||
if migrate_nginx_config_from_file("/usr/local/hestia/nginx-system/etc/nginx/nginx.conf")
|
||||
hestia_print_info_message_to_cli "Completed migration of nginx.conf paths"
|
||||
else
|
||||
hestia_print_error_message_to_cli "Warning: Could not migrate nginx.conf from #{File.expand_path('/usr/local/hestia/nginx-system/etc/nginx/nginx.conf')}"
|
||||
end
|
||||
end
|
||||
log_migrate_stage('stage5') do
|
||||
nginx_conf_dir = '/usr/local/hestia/nginx-system/etc/nginx'
|
||||
|
||||
# Read proxy ports from configuration
|
||||
#proxy_port = $PROXY_PORT.nil? || $PROXY_PORT.empty? ? '80' : $PROXY_PORT
|
||||
#proxy_ssl_port = $PROXY_SSL_PORT.nil? || $PROXY_SSL_PORT.empty? ? '443' : $PROXY_SSL_PORT
|
||||
|
||||
proxy_port = '80'
|
||||
proxy_ssl_port = '443'
|
||||
|
||||
hestia_print_info_message_to_cli "Migrating ports: #{proxy_port} -> 8078, #{proxy_ssl_port} -> 8079"
|
||||
|
||||
# Find and replace port in all .conf files
|
||||
Dir.glob(File.join(nginx_conf_dir, '**', '*.conf')).each do |conf_file|
|
||||
hestia_print_info_message_to_cli "stage 5 processing file #{conf_file}"
|
||||
content = File.read(conf_file)
|
||||
modified = false
|
||||
|
||||
# Process line by line - only replace ports in listen directives
|
||||
new_lines = []
|
||||
|
||||
content.each_line do |line|
|
||||
# Check if line is a listen directive (starts with optional whitespace then 'listen')
|
||||
if /^\s*listen\s+/i.match?(line) || /^listen\s+/i.match?(line)
|
||||
# This is a listen line - process it
|
||||
new_line = parse_and_replace_listen_directive(line, proxy_port, proxy_ssl_port)
|
||||
modified = true unless new_line == line
|
||||
new_lines << new_line
|
||||
else
|
||||
# Not a listen line, keep as is
|
||||
new_lines << line
|
||||
end
|
||||
end
|
||||
|
||||
# Write changes back if modified
|
||||
if modified
|
||||
File.open(conf_file, 'w') { |f| f.write(new_lines.join) }
|
||||
hestia_print_info_message_to_cli " Updated: #{conf_file}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
log_migrate_stage('stage6') do
|
||||
hestia_change_sys_config_value("PROXY_PORT", "8078")
|
||||
hestia_change_sys_config_value("PROXY_SSL_PORT", "8079")
|
||||
end
|
||||
log_migrate_stage('stage7') do
|
||||
if system('/usr/local/hestia/bin/v-ext-modules enable update_module')
|
||||
output = IO.popen("/usr/local/hestia/bin/v-ext-modules state update_module json").read
|
||||
begin
|
||||
parsed = JSON.parse(output)
|
||||
if parsed.is_a?(Array) && parsed.first && parsed.first['STATE'] == 'enabled'
|
||||
system('/usr/local/hestia/bin/v-ext-modules-run update_module synctemplates')
|
||||
else
|
||||
hestia_print_error_message_to_cli "update_module not enabled after enable command"
|
||||
exit 1
|
||||
end
|
||||
rescue JSON::ParserError => e
|
||||
hestia_print_error_message_to_cli "Failed to parse JSON from state command: #{e.message}"
|
||||
exit 1
|
||||
end
|
||||
else
|
||||
hestia_print_error_message_to_cli "Failed to enable update_module"
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
log_migrate_stage('stage8') do
|
||||
hestia_change_sys_config_value("PROXY_PORT", "8078")
|
||||
hestia_change_sys_config_value("PROXY_SSL_PORT", "8079")
|
||||
end
|
||||
#stage8 активация из запуск nginx-system
|
||||
log_migrate_stage('stage9') do
|
||||
# Delete all contents inside /etc/nginx
|
||||
FileUtils.rm_rf Dir.glob('/etc/nginx/*')
|
||||
# Stop nginx service
|
||||
system('systemctl stop nginx')
|
||||
# Start nginx-system service
|
||||
system('systemctl enable nginx-system')
|
||||
system('systemctl start nginx-system')
|
||||
end
|
||||
when :migratetobunkerweb
|
||||
log_migrate_stage('stage10') do
|
||||
if system('/usr/local/hestia/bin/v-ext-modules enable bunkerweb_module')
|
||||
output = IO.popen("/usr/local/hestia/bin/v-ext-modules state bunkerweb_module json").read
|
||||
begin
|
||||
parsed = JSON.parse(output)
|
||||
if parsed.is_a?(Array) && parsed.first && parsed.first['STATE'] == 'enabled'
|
||||
result = system('/usr/local/hestia/bin/v-ext-modules-run bunkerweb_module configure')
|
||||
unless result
|
||||
hestia_print_error_message_to_cli "bunkerweb_module configure command failed"
|
||||
exit 1
|
||||
end
|
||||
else
|
||||
hestia_print_error_message_to_cli "bunkerweb_module not enabled after enable command"
|
||||
exit 1
|
||||
end
|
||||
rescue JSON::ParserError => e
|
||||
hestia_print_error_message_to_cli "Failed to parse JSON from state command: #{e.message}"
|
||||
exit 1
|
||||
end
|
||||
else
|
||||
hestia_print_error_message_to_cli "Failed to enable bunkerweb_module"
|
||||
exit 1
|
||||
end
|
||||
hestia_print_info_message_to_cli "Ожидаем минуту для перезапуска сервиса bunkerweb..."
|
||||
sleep 60
|
||||
end
|
||||
LIST_DOMAINS=[]
|
||||
|
||||
log_migrate_stage('stage11') do
|
||||
hestia_print_info_message_to_cli "Stage 11: Migrating users and domains to BunkerWeb..."
|
||||
|
||||
# Get all users from HestiaCP in JSON format
|
||||
user_list_output = IO.popen("/usr/local/hestia/bin/v-list-users json").read
|
||||
begin
|
||||
user_data = JSON.parse(user_list_output)
|
||||
rescue JSON::ParserError => e
|
||||
hestia_print_error_message_to_cli "Failed to parse users JSON: #{e.message}"
|
||||
exit 1
|
||||
end
|
||||
|
||||
# Iterate over each user
|
||||
user_data.each do |username, user_info|
|
||||
next unless user_info.is_a?(Hash)
|
||||
|
||||
web_domains_count = user_info['U_WEB_DOMAINS']
|
||||
next unless web_domains_count && web_domains_count.to_i > 0
|
||||
|
||||
hestia_print_info_message_to_cli "Processing user: #{username} (#{web_domains_count} domains)"
|
||||
|
||||
# Get web domains for this user in JSON format
|
||||
domain_list_output = IO.popen("/usr/local/hestia/bin/v-list-web-domains #{username} json").read
|
||||
begin
|
||||
domain_data = JSON.parse(domain_list_output)
|
||||
rescue JSON::ParserError => e
|
||||
hestia_print_error_message_to_cli "Failed to parse domains JSON for user #{username}: #{e.message}"
|
||||
next
|
||||
end
|
||||
|
||||
# Process each domain
|
||||
domain_data.each do |domain_name, domain_info|
|
||||
next unless domain_info.is_a?(Hash)
|
||||
|
||||
ssl_status = domain_info['SSL'] || 'no'
|
||||
is_ssl = ssl_status == 'yes'
|
||||
|
||||
# Get IP from domain info - should be available in the parsed JSON
|
||||
proxy_host = domain_info['IP'] || (domain_info['IP6'].present? ? domain_info['IP6'].strip : "127.0.0.1")
|
||||
proxy_host = proxy_host.nil? || proxy_host.empty? ? "127.0.0.1" : proxy_host
|
||||
|
||||
# Create alias list from domain info (ALIAS field contains comma-separated aliases)
|
||||
raw_aliases = domain_info['ALIAS'] || ''
|
||||
if raw_aliases && !raw_aliases.empty?
|
||||
# Hestia uses comma-separated, pass as-is to v-bunkerweb-module (it handles conversion internally)
|
||||
aliases_list = raw_aliases
|
||||
else
|
||||
aliases_list = domain_name # No aliases, use domain name only
|
||||
end
|
||||
|
||||
hestia_print_info_message_to_cli "Processing domain: #{domain_name} (SSL: #{is_ssl}, IP: #{proxy_host})"
|
||||
|
||||
begin
|
||||
# Add domain to BunkerWeb via module script (without SSL)
|
||||
cmd = "/usr/local/hestia/bin/v-bunkerweb-module add #{domain_name} #{proxy_host}"
|
||||
puts_cmd = " Added #{domain_name}: Executing command: #{cmd}"
|
||||
hestia_print_info_message_to_cli puts_cmd
|
||||
|
||||
result = system(cmd)
|
||||
|
||||
if result
|
||||
# Команда успешно выполнена
|
||||
hestia_print_info_message_to_cli " Status: Success"
|
||||
else
|
||||
hestia_print_error_message_to_cli " Failed to add domain #{domain_name}"
|
||||
next
|
||||
end
|
||||
rescue => e
|
||||
hestia_print_error_message_to_cli "Failed to add domain #{domain_name} to BunkerWeb: #{e.message}"
|
||||
next
|
||||
end
|
||||
|
||||
# Add aliases to the domain via module script
|
||||
begin
|
||||
cmd = "/usr/local/hestia/bin/v-bunkerweb-module alias #{domain_name} \"#{aliases_list}\""
|
||||
puts_cmd = " Added aliases for #{domain_name}: Executing command: #{cmd}"
|
||||
hestia_print_info_message_to_cli puts_cmd
|
||||
|
||||
result = system(cmd)
|
||||
|
||||
if result
|
||||
hestia_print_info_message_to_cli " Status: Success"
|
||||
else
|
||||
hestia_print_error_message_to_cli " Failed to set aliases for #{domain_name}"
|
||||
next
|
||||
end
|
||||
rescue => e
|
||||
hestia_print_error_message_to_cli "Failed to set aliases for #{domain_name}: #{e.message}"
|
||||
next
|
||||
end
|
||||
|
||||
# Handle SSL configuration if enabled
|
||||
if is_ssl
|
||||
original_ssl_dir = "/home/#{username}/conf/web/#{domain_name}/ssl"
|
||||
|
||||
# Check if SSL directory and files exist
|
||||
unless Dir.exist?(original_ssl_dir) || File.exist?("#{original_ssl_dir}/#{domain_name}.pem")
|
||||
hestia_print_error_message_to_cli "Warning: SSL files not found for #{domain_name}"
|
||||
LIST_DOMAINS << {
|
||||
user: username,
|
||||
domain: domain_name,
|
||||
is_ssl: true,
|
||||
path_to_ssl: nil
|
||||
}
|
||||
next
|
||||
end
|
||||
|
||||
# Define bunkerweb directory for this domain's certificates
|
||||
bunkerweb_ssl_dir = "/home/#{username}/conf/web/#{domain_name}/ssl/bunkerweb"
|
||||
|
||||
begin
|
||||
# Create bunkerweb SSL directory if it doesn't exist
|
||||
FileUtils.mkdir_p(bunkerweb_ssl_dir)
|
||||
FileUtils.chmod(0755, bunkerweb_ssl_dir)
|
||||
|
||||
# Define paths in bunkerweb directory
|
||||
crt_path_bunkerweb = "#{bunkerweb_ssl_dir}/#{domain_name}.crt"
|
||||
cert_path_bunkerweb = "#{bunkerweb_ssl_dir}/#{domain_name}.pem"
|
||||
key_path_bunkerweb = "#{bunkerweb_ssl_dir}/#{domain_name}.key"
|
||||
|
||||
# Copy all SSL files if they exist (matching v-add-web-domain-ssl behavior)
|
||||
original_crt = "#{original_ssl_dir}/#{domain_name}.crt"
|
||||
original_pem = "#{original_ssl_dir}/#{domain_name}.pem"
|
||||
original_key = "#{original_ssl_dir}/#{domain_name}.key"
|
||||
original_ca = "#{original_ssl_dir}/#{domain_name}.ca"
|
||||
|
||||
# Copy .crt file if exists
|
||||
if File.exist?(original_crt)
|
||||
FileUtils.cp(original_crt, crt_path_bunkerweb)
|
||||
end
|
||||
|
||||
if File.exist?(original_pem)
|
||||
# Only use .pem if .crt doesn't exist (fallback like the backup script)
|
||||
FileUtils.cp(original_pem, cert_path_bunkerweb)
|
||||
end
|
||||
|
||||
# Copy .key file if exists
|
||||
if File.exist?(original_key)
|
||||
FileUtils.cp(original_key, key_path_bunkerweb)
|
||||
end
|
||||
|
||||
# Copy .ca file if exists
|
||||
if File.exist?(original_ca)
|
||||
FileUtils.cp(original_ca, "#{bunkerweb_ssl_dir}/#{domain_name}.ca")
|
||||
end
|
||||
|
||||
# Set ownership and permissions (nginx user can read, others cannot)
|
||||
FileUtils.chown('root', 'nginx', bunkerweb_ssl_dir)
|
||||
FileUtils.chmod(0755, bunkerweb_ssl_dir)
|
||||
|
||||
FileUtils.chown('root', 'nginx', cert_path_bunkerweb) if File.exist?(cert_path_bunkerweb)
|
||||
FileUtils.chmod(0640, cert_path_bunkerweb) if File.exist?(cert_path_bunkerweb)
|
||||
|
||||
FileUtils.chown('root', 'nginx', key_path_bunkerweb) if File.exist?(key_path_bunkerweb)
|
||||
FileUtils.chmod(0640, key_path_bunkerweb) if File.exist?(key_path_bunkerweb)
|
||||
|
||||
FileUtils.chown('root', 'nginx', crt_path_bunkerweb) if File.exist?(crt_path_bunkerweb)
|
||||
FileUtils.chmod(0640, crt_path_bunkerweb) if File.exist?(crt_path_bunkerweb)
|
||||
|
||||
# Add SSL configuration to BunkerWeb via module script (use proxy_host from earlier)
|
||||
|
||||
cmd = "/usr/local/hestia/bin/v-bunkerweb-module addssl #{domain_name} #{crt_path_bunkerweb} #{key_path_bunkerweb}"
|
||||
puts_cmd = " Added SSL for #{domain_name}: Executing command: #{cmd}"
|
||||
hestia_print_info_message_to_cli puts_cmd
|
||||
|
||||
result = system(cmd)
|
||||
|
||||
if result
|
||||
hestia_print_info_message_to_cli " Status: Success"
|
||||
else
|
||||
hestia_print_error_message_to_cli " Failed to configure SSL for #{domain_name}"
|
||||
end
|
||||
|
||||
# Update path_to_ssl to point to bunkerweb directory
|
||||
ssl_cert_path = crt_path_bunkerweb
|
||||
rescue => e
|
||||
hestia_print_error_message_to_cli "Failed to configure SSL for #{domain_name}: #{e.message}"
|
||||
end
|
||||
end
|
||||
|
||||
# Populate LIST_DOMAINS array with domain info
|
||||
LIST_DOMAINS << {
|
||||
user: username,
|
||||
domain: domain_name,
|
||||
proxy_host: proxy_host.to_s,
|
||||
is_ssl: is_ssl == true ? "yes" : "no", # Convert boolean/string to proper string format
|
||||
path_to_ssl: ssl_cert_path ? ssl_cert_path : nil
|
||||
}
|
||||
|
||||
hestia_print_info_message_to_cli "Successfully migrated #{domain_name} for user #{username}"
|
||||
end
|
||||
end
|
||||
|
||||
# Output the populated LIST_DOMAINS array
|
||||
if !LIST_DOMAINS.empty?
|
||||
hestia_print_info_message_to_cli "\n=== Populated LIST_DOMAINS ==="
|
||||
LIST_DOMAINS.each_with_index do |entry, idx|
|
||||
hestia_print_info_message_to_cli "#{idx + 1}. user: #{entry[:user]}, domain: #{entry[:domain]}, is_ssl: #{entry[:is_ssl].to_s}, path_to_ssl: #{entry[:path_to_ssl]}"
|
||||
end
|
||||
else
|
||||
hestia_print_error_message_to_cli "No domains were migrated to BunkerWeb"
|
||||
end
|
||||
|
||||
hestia_print_info_message_to_cli "Stage 11 completed."
|
||||
end
|
||||
else
|
||||
hestia_print_error_message_to_cli "unknown command (use migratetobunkerweb or migratenginx)"
|
||||
log_event E_ARGS, $ARGUMENTS
|
||||
exit 1
|
||||
end
|
||||
|
||||
exit 0
|
||||
267
bin/v-bunkerweb-module
Executable file
267
bin/v-bunkerweb-module
Executable file
@@ -0,0 +1,267 @@
|
||||
#!/opt/brepo/ruby33/bin/ruby
|
||||
# info: action with bunkerweb API
|
||||
# options: COMMAND [SERVICE_NAME | SSL_CERT | SSL_KEY | FORMAT]
|
||||
#
|
||||
# example: v-bunkerweb-module list json
|
||||
#
|
||||
# This function enables and disables additional modules
|
||||
#
|
||||
# Commands:
|
||||
# add [domain_name] [ip]
|
||||
# addssl [domain_name] [SSL_CERT_PATH] [SSL_KEY_PATH]
|
||||
# delete [domain_name]
|
||||
# updssl [domain] [SSL_CERT_PATH] [SSL_KEY_PATH]
|
||||
# list
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
v_command = ARGV[0]
|
||||
v_format = nil
|
||||
|
||||
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)
|
||||
|
||||
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 [COMMAND_OPTIONS] [ACTION]"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#----------------------------------------------------------#
|
||||
# Action #
|
||||
#----------------------------------------------------------#
|
||||
|
||||
case v_command.to_sym
|
||||
when :add
|
||||
|
||||
v_domain = ARGV[1].strip
|
||||
v_ip = ARGV[2] ? ARGV[2].strip : nil
|
||||
v_format = ARGV[3] unless ARGV[2].nil?
|
||||
|
||||
if v_domain.nil? || v_domain == "" || v_ip.nil? || v_ip == ""
|
||||
hestia_print_error_message_to_cli "domain and ip should not be empty"
|
||||
log_event E_ARGS, $ARGUMENTS
|
||||
exit 1
|
||||
else
|
||||
|
||||
begin
|
||||
api = HestiaBunkerWebApi.new("http://127.0.0.1:8888")
|
||||
existing_services = api.list_services()
|
||||
if existing_services.nil?
|
||||
result_arr = []
|
||||
else
|
||||
if existing_services["services"]
|
||||
if existing_services["services"].any? { |s| s["id"] == v_domain }
|
||||
hestia_print_error_message_to_cli "domain already exists"
|
||||
log_event E_EXISTS, $ARGUMENTS
|
||||
exit 1
|
||||
end
|
||||
result_arr = existing_services["services"]
|
||||
else
|
||||
result_arr = []
|
||||
end
|
||||
end
|
||||
api.create_service(v_domain, {
|
||||
ssl: "no",
|
||||
reverse_proxy_host: "http://#{v_ip}:#{$PROXY_PORT}"
|
||||
})
|
||||
rescue BunkerWebApiError => e
|
||||
hestia_print_error_message_to_cli "[ERROR] Ошибка API: #{e.message}"
|
||||
log_event E_INVALID, $ARGUMENTS
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
when :alias
|
||||
|
||||
v_domain = ARGV[1].strip
|
||||
v_alias = ARGV[2].strip
|
||||
v_format = ARGV[3] unless ARGV[3].nil?
|
||||
|
||||
if v_domain.nil? || v_domain == ""
|
||||
hestia_print_error_message_to_cli "domain should not be empty"
|
||||
log_event E_ARGS, $ARGUMENTS
|
||||
exit 1
|
||||
else
|
||||
|
||||
begin
|
||||
api = HestiaBunkerWebApi.new("http://127.0.0.1:8888")
|
||||
existing_services = api.list_services()
|
||||
if existing_services.nil?
|
||||
result_arr = []
|
||||
else
|
||||
if existing_services["services"]
|
||||
result_arr = existing_services["services"]
|
||||
else
|
||||
result_arr = []
|
||||
end
|
||||
end
|
||||
unless result_arr.any? { |s| s["id"] == v_domain }
|
||||
hestia_print_error_message_to_cli "domain does not exist"
|
||||
log_event E_NOTEXIST, $ARGUMENTS
|
||||
exit 1
|
||||
end
|
||||
api.set_alias(v_domain, v_alias)
|
||||
rescue BunkerWebApiError => e
|
||||
hestia_print_error_message_to_cli "[ERROR] Ошибка API: #{e.message}"
|
||||
log_event E_INVALID, $ARGUMENTS
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
when :delete
|
||||
|
||||
v_domain = ARGV[1].strip
|
||||
v_format = ARGV[2] unless ARGV[2].nil?
|
||||
|
||||
if v_domain.nil? || v_domain == ""
|
||||
hestia_print_error_message_to_cli "domain should not be empty"
|
||||
log_event E_ARGS, $ARGUMENTS
|
||||
exit 1
|
||||
else
|
||||
|
||||
begin
|
||||
api = HestiaBunkerWebApi.new("http://127.0.0.1:8888")
|
||||
existing_services = api.list_services()
|
||||
if existing_services.nil?
|
||||
result_arr = []
|
||||
else
|
||||
if existing_services["services"]
|
||||
result_arr = existing_services["services"]
|
||||
else
|
||||
result_arr = []
|
||||
end
|
||||
end
|
||||
unless result_arr.any? { |s| s["id"] == v_domain }
|
||||
hestia_print_error_message_to_cli "domain does not exist"
|
||||
log_event E_NOTEXIST, $ARGUMENTS
|
||||
exit 1
|
||||
end
|
||||
api.delete_service(v_domain)
|
||||
rescue BunkerWebApiError => e
|
||||
hestia_print_error_message_to_cli "[ERROR] Ошибка API: #{e.message}"
|
||||
log_event E_INVALID, $ARGUMENTS
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
when :addssl, :updssl
|
||||
|
||||
v_domain = ARGV[1].strip
|
||||
v_ssl_cert = ARGV[2]
|
||||
v_ssl_key = ARGV[3]
|
||||
v_format = ARGV[4] unless ARGV[4].nil?
|
||||
|
||||
if v_domain.nil? || v_domain == "" || v_ssl_cert.nil? || v_ssl_key.nil? || !File.exist?(v_ssl_cert) || !File.exist?(v_ssl_key)
|
||||
hestia_print_error_message_to_cli "domain, SSL cert and key must be provided and must exist"
|
||||
log_event E_ARGS, $ARGUMENTS
|
||||
exit 1
|
||||
else
|
||||
begin
|
||||
api = HestiaBunkerWebApi.new("http://127.0.0.1:8888")
|
||||
existing_services = api.list_services()
|
||||
if existing_services.nil?
|
||||
result_arr = []
|
||||
else
|
||||
if existing_services["services"]
|
||||
result_arr = existing_services["services"]
|
||||
else
|
||||
result_arr = []
|
||||
end
|
||||
end
|
||||
unless result_arr.any? { |s| s["id"] == v_domain }
|
||||
hestia_print_error_message_to_cli "domain does not exist"
|
||||
log_event E_NOTEXIST, $ARGUMENTS
|
||||
exit 1
|
||||
end
|
||||
api.update_service_ssl(v_domain, v_ssl_cert, v_ssl_key)
|
||||
rescue BunkerWebApiError => e
|
||||
hestia_print_error_message_to_cli "[ERROR] Ошибка API: #{e.message}"
|
||||
log_event E_INVALID, $ARGUMENTS
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
when :deletessl
|
||||
|
||||
v_domain = ARGV[1].strip
|
||||
v_format = ARGV[2] unless ARGV[2].nil?
|
||||
|
||||
if v_domain.nil? || v_domain == ""
|
||||
hestia_print_error_message_to_cli "domain should not be empty"
|
||||
log_event E_ARGS, $ARGUMENTS
|
||||
exit 1
|
||||
else
|
||||
|
||||
begin
|
||||
api = HestiaBunkerWebApi.new("http://127.0.0.1:8888")
|
||||
existing_services = api.list_services()
|
||||
if existing_services.nil?
|
||||
result_arr = []
|
||||
else
|
||||
if existing_services["services"]
|
||||
result_arr = existing_services["services"]
|
||||
else
|
||||
result_arr = []
|
||||
end
|
||||
end
|
||||
unless result_arr.any? { |s| s["id"] == v_domain }
|
||||
hestia_print_error_message_to_cli "domain does not exist"
|
||||
log_event E_NOTEXIST, $ARGUMENTS
|
||||
exit 1
|
||||
end
|
||||
api.delete_service_ssl(v_domain)
|
||||
rescue BunkerWebApiError => e
|
||||
hestia_print_error_message_to_cli "[ERROR] Ошибка API: #{e.message}"
|
||||
log_event E_INVALID, $ARGUMENTS
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
when :list
|
||||
v_format = ARGV[1] unless ARGV[1].nil?
|
||||
|
||||
begin
|
||||
api = HestiaBunkerWebApi.new("http://127.0.0.1:8888")
|
||||
existing_services = api.list_services()
|
||||
if existing_services.nil?
|
||||
result_arr = []
|
||||
else
|
||||
if existing_services["services"]
|
||||
result_arr = existing_services["services"]
|
||||
else
|
||||
result_arr = []
|
||||
end
|
||||
end
|
||||
hestia_print_array_of_hashes(result_arr, v_format, "id, method, is_draft, creation_date, last_update, template, security_mode")
|
||||
rescue BunkerWebApiError => e
|
||||
hestia_print_error_message_to_cli "[ERROR] Ошибка API: #{e.message}"
|
||||
log_event E_INVALID, $ARGUMENTS
|
||||
exit 1
|
||||
end
|
||||
else
|
||||
hestia_print_error_message_to_cli "unknown command"
|
||||
log_event E_ARGS, $ARGUMENTS
|
||||
exit 1
|
||||
end
|
||||
|
||||
exit 0
|
||||
488
bin/v-bunkerweb-module-install
Executable file
488
bin/v-bunkerweb-module-install
Executable file
@@ -0,0 +1,488 @@
|
||||
#!/opt/brepo/ruby33/bin/ruby
|
||||
# info: action with bunkerweb API
|
||||
# options: [SSL_CERT_PATH SSL_KEY_PATH]
|
||||
#
|
||||
# example: v-bunkerweb-module-install
|
||||
#
|
||||
# This function enables and disables additional modules
|
||||
#
|
||||
#------------------------------------------#
|
||||
# Variables & Functions #
|
||||
#------------------------------------------#
|
||||
|
||||
# Argument definition
|
||||
|
||||
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 "securerandom"
|
||||
require "socket"
|
||||
require 'json' unless defined?(JSON)
|
||||
require 'etc'
|
||||
|
||||
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"
|
||||
|
||||
# Perform verification if read-only mode is enabled
|
||||
check_hestia_demo_mode
|
||||
|
||||
#------------------------------------------#
|
||||
# Action #
|
||||
#------------------------------------------#
|
||||
|
||||
puts "========================================================"
|
||||
puts "=== AUTOMATED BUNKERWEB SETUP SCRIPT ==="
|
||||
puts "========================================================"
|
||||
puts ""
|
||||
|
||||
# Parse command line arguments for SSL cert and key paths
|
||||
SSL_CERT_PATH = ARGV[0] || nil # First argument: SSL certificate path
|
||||
SSL_KEY_PATH = ARGV[1] || nil # Second argument: SSL key path
|
||||
|
||||
# Generate secure passwords (meeting BunkerWeb password policy requirements)
|
||||
api_env_file = "/etc/bunkerweb/api.env"
|
||||
api_password = nil
|
||||
if File.exist?(api_env_file)
|
||||
File.foreach(api_env_file) do |line|
|
||||
if line =~ /^\s*API_PASSWORD=(.*)/
|
||||
val = $1.strip
|
||||
api_password = val unless val.empty?
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
specials = '!@#$%^&*()-_=+[]{}|;:,.<>?'
|
||||
API_PASSWORD = api_password || (SecureRandom.alphanumeric(24) + specials.chars.sample(3).join).chars.shuffle.join
|
||||
|
||||
ui_env_file = "/etc/bunkerweb/ui.env"
|
||||
admin_password = nil
|
||||
if File.exist?(ui_env_file)
|
||||
File.foreach(ui_env_file) do |line|
|
||||
if line =~ /^\s*ADMIN_PASSWORD=(.*)/
|
||||
val = $1.strip
|
||||
admin_password = val unless val.empty?
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
ADMIN_PASSWORD = admin_password || (SecureRandom.alphanumeric(24) + specials.chars.sample(3).join).chars.shuffle.join
|
||||
|
||||
puts "[INFO] Get server IP address"
|
||||
|
||||
server_ip_addr = "127.0.0.1" # default fallback
|
||||
# Attempt to retrieve server IP via Hestia utility
|
||||
begin
|
||||
cmd = "/usr/local/hestia/bin/v-list-sys-ips json"
|
||||
ips_output = `#{cmd}`.strip
|
||||
unless ips_output.empty?
|
||||
parsed_ips = JSON.parse(ips_output)
|
||||
parsed_ips.each do |ip, details|
|
||||
if details["OWNER"] == "admin"
|
||||
server_ip_addr = ip
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue JSON::ParserError, Errno::ENOENT
|
||||
# If the command fails or output is invalid, keep default fallback
|
||||
end
|
||||
|
||||
puts ""
|
||||
|
||||
# Compute nginx group ID once
|
||||
nginx_gid = Etc.getgrnam('nginx').gid
|
||||
|
||||
# Step 1: Create /etc/bunkerweb/api.env configuration file
|
||||
puts "[INFO] Creating API configuration at /etc/bunkerweb/api.env..."
|
||||
api_env_content = <<~APIENV
|
||||
# ==============================
|
||||
# BunkerWeb API Configuration
|
||||
# This file lists all supported API environment variables with their defaults.
|
||||
# Uncomment and adjust as needed. Lines starting with # are ignored.
|
||||
# ==============================
|
||||
|
||||
# --- Network & Proxy ---
|
||||
# Listen address/port for the API
|
||||
LISTEN_ADDR=127.0.0.1
|
||||
LISTEN_PORT=8888
|
||||
# Trusted proxy IPs for X-Forwarded-* headers (comma-separated).
|
||||
# Default is restricted to loopback for security.
|
||||
FORWARDED_ALLOW_IPS=127.0.0.1,::1
|
||||
# Trusted proxy IPs for PROXY protocol (comma-separated).
|
||||
# Defaults to FORWARDED_ALLOW_IPS when unset.
|
||||
PROXY_ALLOW_IPS=127.0.0.1,::1
|
||||
|
||||
# --- Logging & Runtime ---
|
||||
# LOG_LEVEL affects most components; CUSTOM_LOG_LEVEL overrides when provided.
|
||||
# LOG_LEVEL=info
|
||||
LOG_TYPES=file
|
||||
LOG_FILE_PATH=/var/log/bunkerweb/api.log
|
||||
# Number of workers/threads (auto if unset).
|
||||
# MAX_WORKERS=<auto>
|
||||
# MAX_THREADS=<auto>
|
||||
|
||||
# --- Authentication & Authorization ---
|
||||
# Optional admin Bearer token (grants full access when provided).
|
||||
# API_TOKEN=#{API_PASSWORD}
|
||||
# Bootstrap admin user (created/validated on startup if provided).
|
||||
API_USERNAME=admin
|
||||
API_PASSWORD=#{API_PASSWORD}
|
||||
# Force re-applying bootstrap admin credentials on startup (use with care).
|
||||
# OVERRIDE_API_CREDS=no
|
||||
# Fine-grained ACLs can be enabled/disabled here.
|
||||
# API_ACL_BOOTSTRAP_FILE=
|
||||
|
||||
# --- IP allowlist ---
|
||||
# Enable and shape inbound IP allowlist for the API.
|
||||
API_WHITELIST_ENABLED=yes
|
||||
WHITELIST_IPS=127.0.0.1
|
||||
|
||||
# --- FastAPI surface ---
|
||||
# Customize or disable documentation endpoints. Use 'disabled' to turn off.
|
||||
# API_TITLE=BunkerWeb API
|
||||
# API_DOCS_URL=/docs
|
||||
# API_REDOC_URL=/redoc
|
||||
# API_OPENAPI_URL=/openapi.json
|
||||
# Mount the API under a subpath (useful behind reverse proxies).
|
||||
# API_ROOT_PATH=
|
||||
|
||||
# --- TLS/SSL ---
|
||||
# Enable TLS for the API listener (requires cert and key).
|
||||
# API_SSL_ENABLED=no
|
||||
# Path to PEM-encoded certificate and private key.
|
||||
# API_SSL_CERTFILE=/etc/ssl/certs/bunkerweb-api.crt
|
||||
# API_SSL_KEYFILE=/etc/ssl/private/bunkerweb-api.key
|
||||
# Optional chain/CA bundle and cipher suite.
|
||||
# API_SSL_CA_CERTS=
|
||||
# API_SSL_CIPHERS_CUSTOM=
|
||||
# API_SSL_CIPHERS_LEVEL=modern # choices: modern|intermediate
|
||||
|
||||
# --- Biscuit keys & policy ---
|
||||
# Bind token to client IP (except private ranges).
|
||||
# CHECK_PRIVATE_IP=yes
|
||||
# Biscuit token lifetime in seconds (0 disables expiry).
|
||||
# API_BISCUIT_TTL_SECONDS=3600
|
||||
# Provide Biscuit keys via env (hex) instead of files.
|
||||
# BISCUIT_PUBLIC_KEY=
|
||||
# BISCUIT_PRIVATE_KEY=
|
||||
|
||||
# --- Rate limiting ---
|
||||
# Enable/disable and shape rate limiting.
|
||||
API_RATE_LIMIT_ENABLED=no
|
||||
API_RATE_LIMIT_HEADERS_ENABLED=no
|
||||
# Global default limit (times per seconds).
|
||||
# API_RATE_LIMIT_TIMES=100
|
||||
# API_RATE_LIMIT_SECONDS=60
|
||||
# Authentication endpoint limit.
|
||||
# API_RATE_LIMIT_AUTH_TIMES=10
|
||||
# API_RATE_LIMIT_AUTH_SECONDS=60
|
||||
# Advanced limits and rules (CSV/JSON/YAML).
|
||||
# API_RATE_LIMIT_DEFAULTS="200/minute"
|
||||
# API_RATE_LIMIT_APPLICATION_LIMITS=
|
||||
# API_RATE_LIMIT_RULES=
|
||||
# Strategy: fixed-window | moving-window | sliding-window-counter
|
||||
# API_RATE_LIMIT_STRATEGY=fixed-window
|
||||
# Key selector: ip | user | path | method | header:<Name>
|
||||
# API_RATE_LIMIT_KEY=ip
|
||||
# Exempt IPs (space or comma-separated CIDRs).
|
||||
# API_RATE_LIMIT_EXEMPT_IPS=
|
||||
# Storage options in JSON (merged with Redis settings if USE_REDIS=yes).
|
||||
# API_RATE_LIMIT_STORAGE_OPTIONS=
|
||||
|
||||
# --- Redis (optional, for rate limiting storage) ---
|
||||
# USE_REDIS=no
|
||||
# REDIS_HOST=
|
||||
# REDIS_PORT=6379
|
||||
# REDIS_DATABASE=0
|
||||
# REDIS_USERNAME=
|
||||
# REDIS_PASSWORD=
|
||||
# REDIS_SSL=no
|
||||
# REDIS_SSL_VERIFY=yes
|
||||
# REDIS_TIMEOUT=1000
|
||||
# REDIS_KEEPALIVE_POOL=10
|
||||
# REDIS_SENTINEL_HOSTS=sentinel1:26379 sentinel2:26379
|
||||
# REDIS_SENTINEL_MASTER=mymaster
|
||||
# REDIS_SENTINEL_USERNAME=
|
||||
# REDIS_SENTINEL_PASSWORD=
|
||||
APIENV
|
||||
|
||||
File.write("/etc/bunkerweb/api.env", api_env_content)
|
||||
File.chmod(0o660, "/etc/bunkerweb/api.env")
|
||||
File.chown(0, nginx_gid, "/etc/bunkerweb/api.env")
|
||||
puts "[SUCCESS] API configuration file created at /etc/bunkerweb/api.env"
|
||||
puts ""
|
||||
|
||||
variables_env_content = <<~VENV
|
||||
DNS_RESOLVERS=9.9.9.9 149.112.112.112 8.8.8.8 8.8.4.4
|
||||
HTTP_PORT=80
|
||||
HTTPS_PORT=443
|
||||
API_LISTEN_IP=127.0.0.1
|
||||
MULTISITE=yes
|
||||
UI_HOST=http://127.0.0.1:7000
|
||||
SERVER_NAME=
|
||||
|
||||
API_WHITELIST_IP=127.0.0.0/8
|
||||
USE_SERVE_FILES=no
|
||||
VENV
|
||||
|
||||
File.write("/etc/bunkerweb/variables.env", variables_env_content)
|
||||
File.chmod(0o660, "/etc/bunkerweb/variables.env")
|
||||
File.chown(0, nginx_gid, "/etc/bunkerweb/variables.env")
|
||||
puts "[SUCCESS] Variables configuration file created at /etc/bunkerweb/variables.env"
|
||||
puts ""
|
||||
|
||||
# Step 2: Enable and start bunkerweb-api service, wait for it to be running
|
||||
puts "[INFO] Enabling bunkerweb-api service..."
|
||||
system("systemctl enable bunkerweb-api")
|
||||
puts "[INFO] Starting bunkerweb-api service..."
|
||||
system("systemctl start bunkerweb-api")
|
||||
|
||||
sleep(30)
|
||||
|
||||
# Wait for the service to be ready (max 30 seconds)
|
||||
puts "[INFO] Waiting for bunkerweb-api service to be running..."
|
||||
max_attempts = 60 # Wait up to 30 seconds (check every half second)
|
||||
attempt = 0
|
||||
|
||||
while attempt < max_attempts
|
||||
status_output = `systemctl is-active bunkerweb-api 2>&1`
|
||||
status = status_output.strip
|
||||
|
||||
if status == "active" || status == "running"
|
||||
puts "[SUCCESS] bunkerweb-api service is running!"
|
||||
break
|
||||
elsif status == "failed"
|
||||
puts "[ERROR] bunkerweb-api service failed to start!"
|
||||
exit 1
|
||||
else
|
||||
print "."
|
||||
sleep(0.5)
|
||||
attempt += 1
|
||||
end
|
||||
end
|
||||
|
||||
if attempt >= max_attempts
|
||||
puts ""
|
||||
puts "[ERROR] bunkerweb-api service did not become active within timeout"
|
||||
puts "[INFO] Current status: #{status_output.strip}"
|
||||
log_event E_INVALID, $ARGUMENTS
|
||||
exit 1
|
||||
end
|
||||
|
||||
puts ""
|
||||
|
||||
# Step 3: Configure UI settings based on documentation at https://docs.bunkerweb.io/latest/web-ui/
|
||||
puts "[INFO] Configuring Web UI..."
|
||||
|
||||
# Determine SSL settings for UI
|
||||
ui_ssl_enabled = "no"
|
||||
if SSL_CERT_PATH && SSL_KEY_PATH && File.exist?(SSL_CERT_PATH) && File.exist?(SSL_KEY_PATH)
|
||||
ui_ssl_enabled = "yes"
|
||||
end
|
||||
|
||||
ui_env_content = <<~UIENV
|
||||
# ==============================
|
||||
# BunkerWeb UI Configuration
|
||||
# This file configures the Web UI settings.
|
||||
# ==============================
|
||||
|
||||
# --- Listener & TLS ---
|
||||
# Bind address for the UI (use server IP for external access)
|
||||
UI_LISTEN_ADDR=127.0.0.1
|
||||
# Bind port for the UI
|
||||
UI_LISTEN_PORT=7000
|
||||
# Enable TLS in the UI container
|
||||
UI_SSL_ENABLED=#{ui_ssl_enabled}
|
||||
UIENV
|
||||
|
||||
# Add SSL cert/key paths if provided
|
||||
if ui_ssl_enabled == "yes"
|
||||
ui_env_content += <<~SSLCONF
|
||||
|
||||
# SSL Certificate and Key paths
|
||||
UI_SSL_CERTFILE=#{SSL_CERT_PATH}
|
||||
UI_SSL_KEYFILE=#{SSL_KEY_PATH}
|
||||
SSLCONF
|
||||
end
|
||||
|
||||
ui_env_content += <<~UIENV2
|
||||
|
||||
# --- Admin Authentication ---
|
||||
# Seed admin account
|
||||
ADMIN_USERNAME=admin
|
||||
ADMIN_PASSWORD=#{ADMIN_PASSWORD}
|
||||
|
||||
# --- Proxy settings ---
|
||||
# Trusted proxy IPs for X-Forwarded-* headers
|
||||
# UI_FORWARDED_ALLOW_IPS=127.0.0.1,::1
|
||||
|
||||
UIENV2
|
||||
|
||||
File.write("/etc/bunkerweb/ui.env", ui_env_content)
|
||||
File.chmod(0o660, "/etc/bunkerweb/ui.env")
|
||||
File.chown(0, nginx_gid, "/etc/bunkerweb/ui.env")
|
||||
puts "[SUCCESS] UI configuration file created at /etc/bunkerweb/ui.env"
|
||||
puts ""
|
||||
|
||||
# Step 4: Reload the bunkerweb-ui service to apply new configuration
|
||||
puts "[INFO] Reloading bunkerweb-ui service..."
|
||||
system("systemctl restart bunkerweb-ui")
|
||||
|
||||
# Wait for UI to be ready (max 10 seconds)
|
||||
sleep(2)
|
||||
|
||||
if system("systemctl is-active bunkerweb-ui >/dev/null 2>&1")
|
||||
puts "[SUCCESS] bunkerweb-ui service is running!"
|
||||
else
|
||||
puts "[WARN] bunkerweb-ui service status could not be verified"
|
||||
end
|
||||
|
||||
puts ""
|
||||
|
||||
# Step 5: Now proceed with the original service creation logic
|
||||
puts "[INFO] Connecting to BunkerWeb API..."
|
||||
|
||||
API_URL = "http://127.0.0.1:8888"
|
||||
|
||||
USERNAME = "admin"
|
||||
PASSWORD = API_PASSWORD
|
||||
|
||||
# Default services to create after setup
|
||||
DEFAULT_SERVICES = [
|
||||
{
|
||||
name: "#{server_ip_addr}",
|
||||
options: {
|
||||
ssl: "no",
|
||||
reverse_proxy_host: "http://127.0.0.1:7000",
|
||||
use_template: "ui",
|
||||
reverse_proxy_url: "/kormilo",
|
||||
use_reverse_proxy: "yes"
|
||||
}
|
||||
},
|
||||
# Add more services here if needed:
|
||||
# {
|
||||
# name: "secure.example.com",
|
||||
# options: {
|
||||
# ssl: "yes",
|
||||
# certificate_path: "/etc/ssl/certs/example.crt",
|
||||
# key_path: "/etc/ssl/private/example.key"
|
||||
# }
|
||||
# }
|
||||
]
|
||||
|
||||
begin
|
||||
api = HestiaBunkerWebApi.new(API_URL, USERNAME, PASSWORD)
|
||||
|
||||
puts ""
|
||||
puts "[SUCCESS] API connected successfully!"
|
||||
puts ""
|
||||
|
||||
# List existing services
|
||||
services = api.list_services()
|
||||
services = api.list_services()
|
||||
if services && services.is_a?(Hash) && services.key?('services')
|
||||
services = services['services']
|
||||
services = nil if services.is_a?(Array) && services.empty?
|
||||
else
|
||||
services = nil
|
||||
end
|
||||
if services.nil?
|
||||
puts "[INFO] No services found - creating default configuration..."
|
||||
|
||||
DEFAULT_SERVICES.each do |service_config|
|
||||
begin
|
||||
puts "[INFO] Creating service: #{service_config[:name]}"
|
||||
result = api.create_service(service_config[:name], service_config[:options])
|
||||
puts " ✓ Service '#{service_config[:name]}' created"
|
||||
rescue BunkerWebApiError => e
|
||||
if e.message.include?("already exists")
|
||||
puts " ℹ Service '#{service_config[:name]}' already exists, skipping..."
|
||||
else
|
||||
raise
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
puts "[SUCCESS] Default services created!"
|
||||
|
||||
else
|
||||
puts "[INFO] Existing services:"
|
||||
services.each { |s| puts " - #{s['server_name']}" }
|
||||
puts ""
|
||||
end
|
||||
|
||||
# Reload configuration on all instances
|
||||
puts "[INFO] Reloading configuration..."
|
||||
api.reload_instance()
|
||||
|
||||
puts "[INFO] Restarting bunkerweb service..."
|
||||
system("systemctl restart bunkerweb")
|
||||
puts "[INFO] Restarting bunkerweb-scheduler service..."
|
||||
system("systemctl restart bunkerweb-scheduler")
|
||||
|
||||
puts ""
|
||||
puts "======================================================"
|
||||
puts "=== SETUP COMPLETED SUCCESSFULLY ==="
|
||||
puts "======================================================"
|
||||
puts ""
|
||||
puts "Web UI is now accessible at:"
|
||||
if ui_ssl_enabled == "yes"
|
||||
puts " https://#{server_ip_addr}/kormilo"
|
||||
else
|
||||
puts " http://#{server_ip_addr}/kormilo"
|
||||
end
|
||||
puts ""
|
||||
puts "API URL: #{API_URL}"
|
||||
puts ""
|
||||
puts "API Credentials:"
|
||||
puts " Username: admin"
|
||||
puts " Password: #{PASSWORD}"
|
||||
puts ""
|
||||
|
||||
puts "UI Credentials:"
|
||||
puts " Username: admin"
|
||||
puts " Password: #{ADMIN_PASSWORD}"
|
||||
puts ""
|
||||
|
||||
rescue BunkerWebApiError => e
|
||||
|
||||
if e.message.include?("Authentication") || e.message.include?("Connection refused")
|
||||
puts "[ERROR] Could not connect to BunkerWeb API"
|
||||
puts "[INFO] This means the setup has NOT been completed correctly"
|
||||
puts ""
|
||||
puts "Please verify that:"
|
||||
puts " 1. bunkerweb-api service is running: systemctl status bunkerweb-api"
|
||||
puts " 2. API configuration file exists at /etc/bunkerweb/api.env"
|
||||
puts " 3. Check logs: journalctl -u bunkerweb-api -f"
|
||||
puts ""
|
||||
log_event E_INVALID, $ARGUMENTS
|
||||
exit 1
|
||||
|
||||
else
|
||||
puts "[ERROR] #{e.message}"
|
||||
log_event E_INVALID, $ARGUMENTS
|
||||
exit 1
|
||||
end
|
||||
|
||||
rescue => e
|
||||
puts "[ERROR] Unexpected error: #{e.message}"
|
||||
puts "Backtrace:"
|
||||
puts e.backtrace.inspect
|
||||
log_event E_INVALID, $ARGUMENTS
|
||||
exit 1
|
||||
end
|
||||
|
||||
exit 0
|
||||
@@ -68,13 +68,13 @@ if [ "$type" = "pma" ] || [ "$type" = "PMA" ] || [ "$type" = "phpmyadmin" ]; the
|
||||
$BIN/v-restart-service httpd
|
||||
fi
|
||||
|
||||
if [ -e "/etc/nginx/conf.d/phpmyadmin.inc" ]; then
|
||||
rm -f /etc/nginx/conf.d/phpmyadmin.inc
|
||||
cp -f $HESTIA_INSTALL_DIR/nginx/phpmyadmin.inc /etc/nginx/conf.d/phpmyadmin.inc
|
||||
sed -i "s|%pma_alias%|$alias|g" /etc/nginx/conf.d/phpmyadmin.inc
|
||||
if [ -e "/usr/local/hestia/nginx-system/etc/nginx/conf.d/phpmyadmin.inc" ]; then
|
||||
rm -f /usr/local/hestia/nginx-system/etc/nginx/conf.d/phpmyadmin.inc
|
||||
cp -f $HESTIA_INSTALL_DIR/nginx/phpmyadmin.inc /usr/local/hestia/nginx-system/etc/nginx/conf.d/phpmyadmin.inc
|
||||
sed -i "s|%pma_alias%|$alias|g" /usr/local/hestia/nginx-system/etc/nginx/conf.d/phpmyadmin.inc
|
||||
|
||||
# Restart services
|
||||
$BIN/v-restart-service nginx
|
||||
$BIN/v-restart-service nginx-system
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -105,13 +105,13 @@ if [ "$type" = "pga" ] || [ "$type" = "PGA" ] || [ "$type" = "phppgadmin" ]; the
|
||||
$BIN/v-restart-service httpd
|
||||
fi
|
||||
|
||||
if [ -e "/etc/nginx/conf.d/phppgadmin.inc" ]; then
|
||||
rm -f /etc/nginx/conf.d/phppgadmin.inc
|
||||
cp -f $HESTIA_INSTALL_DIR/nginx/phppgadmin.inc /etc/nginx/conf.d/phppgadmin.inc
|
||||
sed -i "s|%pga_alias%|$alias|g" /etc/nginx/conf.d/phppgadmin.inc
|
||||
if [ -e "/usr/local/hestia/nginx-system/etc/nginx/conf.d/phppgadmin.inc" ]; then
|
||||
rm -f /usr/local/hestia/nginx-system/etc/nginx/conf.d/phppgadmin.inc
|
||||
cp -f $HESTIA_INSTALL_DIR/nginx/phppgadmin.inc /usr/local/hestia/nginx-system/etc/nginx/conf.d/phppgadmin.inc
|
||||
sed -i "s|%pga_alias%|$alias|g" /usr/local/hestia/nginx-system/etc/nginx/conf.d/phppgadmin.inc
|
||||
|
||||
# Restart services
|
||||
$BIN/v-restart-service nginx
|
||||
$BIN/v-restart-service nginx-system
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -65,18 +65,18 @@ fi
|
||||
|
||||
# Defining dst config path
|
||||
case $service in
|
||||
nginx) dst='/etc/nginx/nginx.conf' ;;
|
||||
nginx) dst='/usr/local/hestia/nginx-system/etc/nginx/nginx.conf' ;;
|
||||
httpd) dst='/etc/httpd/conf/httpd.conf' ;;
|
||||
apache2) dst='/etc/apache2/apache2.conf' ;;
|
||||
exim) dst='/etc/exim/exim.conf' ;;
|
||||
exim4) dst='/etc/exim4/exim4.conf.template' ;;
|
||||
vsftpd) dst=$(find /etc/vsftpd* -name 'vsftpd.conf') ;;
|
||||
proftpd) dst=$(find /etc/proftpd* -name 'proftpd.conf') ;;
|
||||
php)
|
||||
php)
|
||||
if [ "$LOCAL_PHP" == "yes" ]; then
|
||||
dst=$(find /opt/brepo/php${php_v} -name php.ini)
|
||||
dst=$(find /opt/brepo/php${php_v} -name php.ini)
|
||||
else
|
||||
dst=$(find /etc/opt/remi/php${php_v} -name php.ini)
|
||||
dst=$(find /etc/opt/remi/php${php_v} -name php.ini)
|
||||
fi
|
||||
;;
|
||||
mysql) dst=$(find /etc/my* -name my.cnf) ;;
|
||||
@@ -136,7 +136,7 @@ if [ "$update" = 'yes' ] && [ "$restart" != 'no' ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
$BIN/v-restart-service "$service" > /dev/null 2>&1
|
||||
$BIN/v-restart-service "$service" > /dev/null 2>&1
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
for config in $dst; do
|
||||
|
||||
@@ -88,6 +88,25 @@ check_result $? "Web restart failed" > /dev/null
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
# Execute bunkerweb_module if it's enabled
|
||||
module_state=$($BIN/v-ext-modules state bunkerweb_module json | jq -r '.[0].STATE')
|
||||
if [ "$module_state" = "enabled" ] && [ "$BUNKERWEB" = "yes" ]; then
|
||||
BUNKW_DIR=$HOMEDIR/$user/conf/web/$domain/ssl/bunkerweb
|
||||
if [ ! -d "$BUNKW_DIR" ]; then
|
||||
mkdir -p "$BUNKW_DIR"
|
||||
chmod 0755 "$BUNKW_DIR"
|
||||
fi
|
||||
cp -f "$HOMEDIR/$user/conf/web/$domain/ssl/$domain.crt" "$BUNKW_DIR/"
|
||||
cp -f "$HOMEDIR/$user/conf/web/$domain/ssl/$domain.key" "$BUNKW_DIR/"
|
||||
cp -f "$HOMEDIR/$user/conf/web/$domain/ssl/$domain.pem" "$BUNKW_DIR/"
|
||||
if [ -e "$HOMEDIR/$user/conf/web/$domain/ssl/$domain.ca" ]; then
|
||||
cp -f "$HOMEDIR/$user/conf/web/$domain/ssl/$domain.ca" "$BUNKW_DIR/"
|
||||
fi
|
||||
chown root:nginx "$BUNKW_DIR"/*
|
||||
chmod 0640 "$BUNKW_DIR"/*
|
||||
$BIN/v-ext-modules-run bunkerweb_module addssl "$domain" "$BUNKW_DIR/$domain.pem" "$BUNKW_DIR/$domain.key"
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "SSL certificate changed (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
@@ -31,7 +31,7 @@ SERVICE_NAME="$1"
|
||||
|
||||
case "$SERVICE_NAME" in
|
||||
nginx )
|
||||
/usr/sbin/nginx -t >> "$DEBUG_LOG_FILE" 2>&1
|
||||
/usr/local/hestia/nginx-system/sbin/nginx -t >> "$DEBUG_LOG_FILE" 2>&1
|
||||
V_RESULT=$?
|
||||
exit $V_RESULT
|
||||
;;
|
||||
@@ -47,5 +47,3 @@ esac
|
||||
|
||||
# Something like error, we shouldn't be here
|
||||
exit 1
|
||||
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ if [ -f "$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.fastcgi_cache.conf" ]; then
|
||||
rm -rf $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.fastcgi_cache.conf
|
||||
fi
|
||||
|
||||
conf='/etc/nginx/conf.d/fastcgi_cache_pool.conf'
|
||||
conf='/usr/local/hestia/nginx-system/etc/nginx/conf.d/fastcgi_cache_pool.conf'
|
||||
if [ -f "$conf" ]; then
|
||||
sed -i "/ keys_zone=$domain/d" $conf
|
||||
if [ ! -s "$conf" ]; then
|
||||
@@ -58,7 +58,7 @@ if [ -f "$conf" ]; then
|
||||
fi
|
||||
|
||||
# Delete FastCGI cache folder
|
||||
if [ -d "/var/cache/nginx/micro/$domain" ]; then
|
||||
if [ -d "/usr/local/hestia/nginx-system/var/cache/nginx/micro/$domain" ]; then
|
||||
rm -rf /var/cache/nginx/micro/$domain
|
||||
fi
|
||||
|
||||
|
||||
@@ -170,6 +170,12 @@ check_result $? "Proxy restart failed" > /dev/null
|
||||
$BIN/v-restart-web-backend "$restart" "$version"
|
||||
check_result $? "PHP restart failed" > /dev/null
|
||||
|
||||
# Execute bunkerweb_module if it's enabled
|
||||
module_state=$($BIN/v-ext-modules state bunkerweb_module json | jq -r '.[0].STATE')
|
||||
if [ "$module_state" = "enabled" ]; then
|
||||
$BIN/v-ext-modules-run bunkerweb_module delete "$domain"
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Deleted web domain (Name: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
@@ -92,6 +92,13 @@ check_result $? "Web restart failed" > /dev/null
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
# Execute bunkerweb_module if it's enabled
|
||||
module_state=$($BIN/v-ext-modules state bunkerweb_module json | jq -r '.[0].STATE')
|
||||
if [ "$module_state" = "enabled" ]; then
|
||||
get_domain_values 'web'
|
||||
$BIN/v-ext-modules-run bunkerweb_module alias "$domain" "$ALIAS"
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "Deleted web domain alias (Alias: $dom_alias, Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
@@ -90,6 +90,16 @@ check_result $? "Web restart failed" > /dev/null
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
# Execute bunkerweb_module if it's enabled
|
||||
module_state=$($BIN/v-ext-modules state bunkerweb_module json | jq -r '.[0].STATE')
|
||||
if [ "$module_state" = "enabled" ] && [ "$BUNKERWEB" = "yes" ]; then
|
||||
BUNKW_DIR=$HOMEDIR/$user/conf/web/$domain/ssl/bunkerweb
|
||||
if [ -d "$BUNKW_DIR" ]; then
|
||||
$BIN/v-ext-modules-run bunkerweb_module deletessl "$domain"
|
||||
rm -f $BUNKW_DIR/$domain.*
|
||||
fi
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Warning" "Web" "SSL disabled (Domain: $domain)."
|
||||
log_event "$OK" "$ARGUMENTS"
|
||||
|
||||
@@ -65,7 +65,7 @@ csv_list() {
|
||||
#----------------------------------------------------------#
|
||||
|
||||
# Defining config path
|
||||
config_path='/etc/nginx/nginx.conf'
|
||||
config_path='/usr/local/hestia/nginx-system/etc/nginx/nginx.conf'
|
||||
|
||||
# Defining keys
|
||||
keys="worker_processes |worker_connections |send_timeout"
|
||||
|
||||
@@ -48,13 +48,13 @@ conf=$(grep "DOMAIN='$domain'" "$USER_DATA/web.conf")
|
||||
parse_object_kv_list "$conf"
|
||||
|
||||
# Purge nginx FastCGI cache
|
||||
if [ -d "/var/cache/nginx/micro/$domain" ]; then
|
||||
rm -rf /var/cache/nginx/micro/$domain/*
|
||||
if [ -d "/usr/local/hestia/nginx-system/var/cache/nginx/micro/$domain" ]; then
|
||||
rm -rf /usr/local/hestia/nginx-system/var/cache/nginx/micro/$domain/*
|
||||
fi
|
||||
|
||||
# Purge nginx proxy cache
|
||||
if [ -d "/var/cache/nginx/$domain" ]; then
|
||||
rm -rf /var/cache/nginx/$domain/*
|
||||
if [ -d "/usr/local/hestia/nginx-system/var/cache/nginx/$domain" ]; then
|
||||
rm -rf /usr/local/hestia/nginx-system/var/cache/nginx/$domain/*
|
||||
fi
|
||||
|
||||
#----------------------------------------------------------#
|
||||
|
||||
@@ -25,10 +25,14 @@ send_email_report() {
|
||||
email=$(echo "$email" | cut -f 2 -d "'")
|
||||
tmpfile=$(mktemp)
|
||||
subj="$(hostname): $PROXY_SYSTEM restart failed"
|
||||
nginx -t >> $tmpfile 2>&1
|
||||
/usr/local/hestia/nginx-system/sbin/nginx -t >> $tmpfile 2>&1
|
||||
|
||||
if [ "$1" == "DO_RESTART" ]; then
|
||||
service "$PROXY_SYSTEM" restart >> $tmpfile 2>&1
|
||||
if [ "$PROXY_SYSTEM" = "nginx" ]; then
|
||||
service nginx-system restart >> $tmpfile 2>&1
|
||||
else
|
||||
service "$PROXY_SYSTEM" restart >> $tmpfile 2>&1
|
||||
fi
|
||||
fi
|
||||
cat "$tmpfile" | $SENDMAIL -s "$subj" "$email"
|
||||
if [ "$DEBUG_MODE" = "true" ]; then
|
||||
|
||||
@@ -73,7 +73,7 @@ for service in $service_list; do
|
||||
$BIN/v-stop-firewall
|
||||
$BIN/v-update-firewall
|
||||
elif [ "$restart" = "ssl" ] && [ "$service" = "nginx" ]; then
|
||||
service $service upgrade >> $log 2>&1
|
||||
service nginx-system upgrade >> $log 2>&1
|
||||
elif [ -z "$restart" -o "$restart" = "no" ] && [ \
|
||||
"$service" = "nginx" -o \
|
||||
"$service" = "httpd" -o \
|
||||
@@ -86,10 +86,19 @@ for service in $service_list; do
|
||||
"$service" = "proftpd" -o \
|
||||
"$service" = "ssh" -o \
|
||||
"$service" = "fail2ban" ]; then
|
||||
systemctl reload-or-restart "$service" >> $log 2>&1
|
||||
if [ "$service" = "nginx" ]; then
|
||||
systemctl reload-or-restart nginx-system >> $log 2>&1
|
||||
else
|
||||
systemctl reload-or-restart "$service" >> $log 2>&1
|
||||
fi
|
||||
else
|
||||
systemctl reset-failed "$service" >> $log 2>&1
|
||||
systemctl restart "$service" >> $log 2>&1
|
||||
if [ "$service" = "nginx" ]; then
|
||||
systemctl reset-failed nginx-system >> $log 2>&1
|
||||
systemctl restart nginx-system >> $log 2>&1
|
||||
else
|
||||
systemctl reset-failed "$service" >> $log 2>&1
|
||||
systemctl restart "$service" >> $log 2>&1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check the result of the service restart and report whether it failed.
|
||||
|
||||
@@ -47,7 +47,11 @@ for service in $service_list; do
|
||||
if [ "$service" = "iptables" ]; then
|
||||
$BIN/v-stop-firewall
|
||||
else
|
||||
systemctl stop "$service"
|
||||
if [ "$service" = "nginx" ]; then
|
||||
systemctl stop nginx-system
|
||||
else
|
||||
systemctl stop "$service"
|
||||
fi
|
||||
result=$?
|
||||
if [ "$result" -ne 0 ]; then
|
||||
$BIN/v-log-action "system" "Error" "System" "Service failed to stop (Name: $service)."
|
||||
|
||||
282
bin/v-system-nginx-migrate
Executable file
282
bin/v-system-nginx-migrate
Executable file
@@ -0,0 +1,282 @@
|
||||
#!/opt/brepo/ruby33/bin/ruby
|
||||
# info: utility to prepare existing server with hestiacp to use new alternative nginx
|
||||
# options: COMMAND
|
||||
#
|
||||
# example: v-system-nginx-migrate migrate-nginx
|
||||
#
|
||||
# Commands:
|
||||
# migratenginx - move old nginx configs to the new port and path
|
||||
#
|
||||
#
|
||||
|
||||
#------------------------------------------#
|
||||
# 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 'json' unless defined?(JSON)
|
||||
require 'fileutils'
|
||||
require 'time'
|
||||
require 'pathname'
|
||||
|
||||
|
||||
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 }
|
||||
hestia_print_error_message_to_cli "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 }
|
||||
hestia_print_info_message_to_cli "Stage #{stage} completed."
|
||||
rescue => e
|
||||
hestia_print_error_message_to_cli "Stage #{stage} failed: #{e.message}"
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
|
||||
# Function to parse and migrate nginx.conf from /usr/local/hestia/nginx-system/etc/nginx/nginx.conf
|
||||
def migrate_nginx_config_from_file(source_path)
|
||||
return false unless File.exist?(source_path)
|
||||
|
||||
hestia_print_info_message_to_cli "Processing nginx config from: #{source_path}"
|
||||
|
||||
content = File.read(source_path)
|
||||
original_content = content.dup
|
||||
|
||||
modified = false
|
||||
|
||||
# Replace all paths starting with /var/ to /usr/local/hestia/nginx-system/var/
|
||||
# This pattern matches any absolute path that starts with /var/ anywhere in the line
|
||||
content = content.gsub(/\/var\//, '/usr/local/hestia/nginx-system/var/')
|
||||
|
||||
# Replace pid path from /run/nginx.pid to /run/nginx-system.pid
|
||||
content = content.gsub(/pid\s+\S+/) { |match| match.gsub('/run/nginx.pid', '/run/nginx-system.pid') }
|
||||
|
||||
if content != original_content
|
||||
File.write(source_path, content)
|
||||
hestia_print_info_message_to_cli "Updated config: #{source_path}"
|
||||
modified = true
|
||||
end
|
||||
|
||||
modified
|
||||
end
|
||||
|
||||
def parse_listen(line)
|
||||
# Попытка найти IP:port
|
||||
m = line.match(/^\s*listen\s+([^\s:]+):(\d+)/i)
|
||||
return [m[1], m[2]] if m
|
||||
# Если только порт после listen
|
||||
m = line.match(/^\s*listen\s+(\d+);?\s*$/i)
|
||||
return [nil, m[1]] if m
|
||||
nil
|
||||
end
|
||||
|
||||
# Helper function to parse and replace ports in listen directives using temp placeholders
|
||||
def parse_and_replace_listen_directive(line, proxy_port, proxy_ssl_port)
|
||||
return line unless line.match?(/\blisten\b/i)
|
||||
|
||||
new_line = line.dup
|
||||
|
||||
# Define target ports (always migrate to these values regardless of input)
|
||||
target_http_port = '8078'
|
||||
target_ssl_port = '8079'
|
||||
|
||||
result = parse_listen(line)
|
||||
return line unless result
|
||||
ip, port = result
|
||||
|
||||
if port == proxy_port
|
||||
if ip
|
||||
new_line.gsub!("#{ip}:#{port}", "#{ip}:#{target_http_port}")
|
||||
else
|
||||
new_line.gsub!(port, target_http_port)
|
||||
end
|
||||
elsif port == proxy_ssl_port
|
||||
if ip
|
||||
new_line.gsub!("#{ip}:#{port}", "#{ip}:#{target_ssl_port}")
|
||||
else
|
||||
new_line.gsub!(port, target_ssl_port)
|
||||
end
|
||||
end
|
||||
|
||||
new_line
|
||||
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('nstage0') do
|
||||
# Create backup of /etc/nginx with timestamp
|
||||
|
||||
timestamp = Time.now.strftime('%Y%m%d_%H%M%S')
|
||||
backup_root = "/etc/nginx_backup_#{timestamp}"
|
||||
FileUtils.mkdir_p(backup_root)
|
||||
|
||||
src_root = '/etc/nginx'
|
||||
dest_root = backup_root
|
||||
|
||||
# Custom copy function to handle symlinks in conf.d/domains
|
||||
def copy_with_symlinks(src, dest)
|
||||
Dir.foreach(src) do |entry|
|
||||
next if entry == '.' || entry == '..'
|
||||
src_path = File.join(src, entry)
|
||||
dest_path = File.join(dest, entry)
|
||||
|
||||
if File.symlink?(src_path)
|
||||
# Check if symlink is inside conf.d/domains
|
||||
if src_path.include?(File.join('conf.d', 'domains'))
|
||||
# Resolve the target of the symlink
|
||||
target_path = File.readlink(src_path)
|
||||
# Resolve relative symlink paths
|
||||
unless Pathname.new(target_path).absolute?
|
||||
target_path = File.expand_path(target_path, File.dirname(src_path))
|
||||
end
|
||||
if File.exist?(target_path) && File.file?(target_path)
|
||||
content = File.read(target_path)
|
||||
new_file_name = "#{entry}_content.conf"
|
||||
new_file_path = File.join(dest, new_file_name)
|
||||
File.write(new_file_path, content)
|
||||
end
|
||||
else
|
||||
# Preserve the symlink as is
|
||||
FileUtils.mkdir_p(File.dirname(dest_path))
|
||||
target = File.readlink(src_path)
|
||||
FileUtils.ln_s(target, dest_path)
|
||||
end
|
||||
elsif File.directory?(src_path)
|
||||
FileUtils.mkdir_p(dest_path)
|
||||
copy_with_symlinks(src_path, dest_path)
|
||||
else
|
||||
FileUtils.cp(src_path, dest_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
copy_with_symlinks(src_root, dest_root)
|
||||
end
|
||||
log_migrate_stage('nstage2') 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('nstage3') 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
|
||||
log_migrate_stage('nstage4') do
|
||||
# Find all files under the nginx-system directory
|
||||
nginx_conf_dir = '/usr/local/hestia/nginx-system/etc/nginx'
|
||||
Dir.glob(File.join(nginx_conf_dir, '**', '*')).each do |path|
|
||||
hestia_print_info_message_to_cli "stage 4 processing file #{path}"
|
||||
next if File.directory?(path)
|
||||
content = File.read(path)
|
||||
new_content = content.gsub(/(?<!\/usr\/local\/hestia\/nginx-system)\/etc\/nginx/, '/usr/local/hestia/nginx-system/etc/nginx')
|
||||
if new_content != content
|
||||
hestia_print_info_message_to_cli "Changed path to config in file #{path}"
|
||||
File.open(path, 'w') { |f| f.write(new_content) }
|
||||
end
|
||||
end
|
||||
end
|
||||
log_migrate_stage('nstage4.1') do
|
||||
# Parse nginx.conf file to replace paths
|
||||
if migrate_nginx_config_from_file("/usr/local/hestia/nginx-system/etc/nginx/nginx.conf")
|
||||
hestia_print_info_message_to_cli "Completed migration of nginx.conf paths"
|
||||
else
|
||||
hestia_print_error_message_to_cli "Warning: Could not migrate nginx.conf from #{File.expand_path('/usr/local/hestia/nginx-system/etc/nginx/nginx.conf')}"
|
||||
end
|
||||
end
|
||||
log_migrate_stage('nstage7') do
|
||||
if system('/usr/local/hestia/bin/v-ext-modules enable update_module')
|
||||
output = IO.popen("/usr/local/hestia/bin/v-ext-modules state update_module json").read
|
||||
begin
|
||||
parsed = JSON.parse(output)
|
||||
if parsed.is_a?(Array) && parsed.first && parsed.first['STATE'] == 'enabled'
|
||||
system('/usr/local/hestia/bin/v-ext-modules-run update_module synctemplates')
|
||||
else
|
||||
hestia_print_error_message_to_cli "update_module not enabled after enable command"
|
||||
exit 1
|
||||
end
|
||||
rescue JSON::ParserError => e
|
||||
hestia_print_error_message_to_cli "Failed to parse JSON from state command: #{e.message}"
|
||||
exit 1
|
||||
end
|
||||
else
|
||||
hestia_print_error_message_to_cli "Failed to enable update_module"
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
log_migrate_stage('stage9') do
|
||||
# Delete all contents inside /etc/nginx
|
||||
FileUtils.rm_rf Dir.glob('/etc/nginx/*')
|
||||
# Stop nginx service
|
||||
system('systemctl stop nginx')
|
||||
system('systemctl disable nginx')
|
||||
# Start nginx-system service
|
||||
system('systemctl enable nginx-system')
|
||||
system('systemctl start nginx-system')
|
||||
end
|
||||
else
|
||||
hestia_print_error_message_to_cli "unknown command (use migratenginx)"
|
||||
log_event E_ARGS, $ARGUMENTS
|
||||
exit 1
|
||||
end
|
||||
|
||||
exit 0
|
||||
@@ -86,7 +86,11 @@ if [ -n "$old_ip" ]; then
|
||||
|
||||
# Updating PROXY
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
cd /etc/$PROXY_SYSTEM/$pconfd
|
||||
if [ "$PROXY_SYSTEM" = "nginx" ]; then
|
||||
cd /usr/local/hestia/nginx-system/etc/nginx/$pconfd
|
||||
else
|
||||
cd /etc/$PROXY_SYSTEM/$pconfd
|
||||
fi
|
||||
if [ -e "$old_ip.conf" ]; then
|
||||
mv $old_ip.conf $new_ip.conf
|
||||
sed -i "s/$old_ip/$new_ip/g" $new_ip.conf
|
||||
@@ -95,7 +99,11 @@ if [ -n "$old_ip" ]; then
|
||||
|
||||
# Updating WEB
|
||||
if [ -n "$WEB_SYSTEM" ]; then
|
||||
cd /etc/$WEB_SYSTEM/$confd
|
||||
if [ "$WEB_SYSTEM" = "nginx" ]; then
|
||||
cd /usr/local/hestia/nginx-system/etc/nginx/$confd
|
||||
else
|
||||
cd /etc/$WEB_SYSTEM/$confd
|
||||
fi
|
||||
|
||||
if [ -e "$old_ip.conf" ]; then
|
||||
mv $old_ip.conf $new_ip.conf
|
||||
@@ -161,8 +169,8 @@ for ip in $ips; do
|
||||
prefixlen="$(ip -d -j addr show | jq --arg IP "$ip" -r '.[].addr_info[] | if .local == $IP then .prefixlen else empty end')"
|
||||
netmask="$(convert_cidr "$prefixlen")"
|
||||
$BIN/v-add-sys-ip "$ip" "$netmask" "$interface"
|
||||
elif [ -e "/etc/nginx/conf.d/$ip.conf" ]; then
|
||||
process_http2_directive "/etc/nginx/conf.d/$ip.conf"
|
||||
elif [ -e "/usr/local/hestia/nginx-system/etc/nginx/conf.d/$ip.conf" ]; then
|
||||
process_http2_directive "/usr/local/hestia/nginx-system/etc/nginx/conf.d/$ip.conf"
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
@@ -90,6 +90,25 @@ check_result $? "Web restart failed" > /dev/null
|
||||
$BIN/v-restart-proxy "$restart"
|
||||
check_result $? "Proxy restart failed" > /dev/null
|
||||
|
||||
# Execute bunkerweb_module if it's enabled
|
||||
module_state=$($BIN/v-ext-modules state bunkerweb_module json | jq -r '.[0].STATE')
|
||||
if [ "$module_state" = "enabled" ] && [ "$BUNKERWEB" = "yes" ]; then
|
||||
BUNKW_DIR=$HOMEDIR/$user/conf/web/$domain/ssl/bunkerweb
|
||||
if [ ! -d "$BUNKW_DIR" ]; then
|
||||
mkdir -p "$BUNKW_DIR"
|
||||
chmod 0755 "$BUNKW_DIR"
|
||||
fi
|
||||
cp -f "$HOMEDIR/$user/conf/web/$domain/ssl/$domain.crt" "$BUNKW_DIR/"
|
||||
cp -f "$HOMEDIR/$user/conf/web/$domain/ssl/$domain.key" "$BUNKW_DIR/"
|
||||
cp -f "$HOMEDIR/$user/conf/web/$domain/ssl/$domain.pem" "$BUNKW_DIR/"
|
||||
if [ -e "$HOMEDIR/$user/conf/web/$domain/ssl/$domain.ca" ]; then
|
||||
cp -f "$HOMEDIR/$user/conf/web/$domain/ssl/$domain.ca" "$BUNKW_DIR/"
|
||||
fi
|
||||
chown root:nginx "$BUNKW_DIR"/*
|
||||
chmod 0640 "$BUNKW_DIR"/*
|
||||
$BIN/v-ext-modules-run bunkerweb_module updssl "$domain" "$BUNKW_DIR/$domain.pem" "$BUNKW_DIR/$domain.key"
|
||||
fi
|
||||
|
||||
# Logging
|
||||
$BIN/v-log-action "$user" "Info" "Web" "SSL certificate updated (Domain: $domain)."
|
||||
log_event "$OK" "$EVENT"
|
||||
|
||||
@@ -148,4 +148,4 @@ bundle install
|
||||
bundle install --path=vendor
|
||||
```
|
||||
|
||||
для установки пользователю необходимых гемов локально.
|
||||
для установки пользователю необходимых гемов локально.
|
||||
|
||||
@@ -112,11 +112,11 @@ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
try_files $uri =404;
|
||||
fastcgi_pass %backend_lsnr%;
|
||||
fastcgi_index index.php;
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
}
|
||||
```
|
||||
|
||||
Добавьте следующие строки под `include /etc/nginx/fastcgi_params;`:
|
||||
Добавьте следующие строки под `include /usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;`:
|
||||
|
||||
```bash
|
||||
include %home%/%user%/conf/web/%domain%/nginx.fastcgi_cache.conf*;
|
||||
|
||||
119
func/domain.sh
119
func/domain.sh
@@ -383,7 +383,11 @@ add_web_config() {
|
||||
|
||||
if [[ "$TPLNM" =~ stpl$ ]]; then
|
||||
rm -f /etc/$1/$confd/domains/$domain.ssl.conf
|
||||
ln -s $conf /etc/$1/$confd/domains/$domain.ssl.conf
|
||||
if [ "$1" = "nginx" ]; then
|
||||
ln -s $conf /usr/local/hestia/nginx-system/etc/$1/$confd/domains/$domain.ssl.conf
|
||||
else
|
||||
ln -s $conf /etc/$1/$confd/domains/$domain.ssl.conf
|
||||
fi
|
||||
|
||||
# Rename/Move extra SSL config files
|
||||
find=$(find $HOMEDIR/$user/conf/web/*.$domain.org* 2> /dev/null)
|
||||
@@ -399,8 +403,13 @@ add_web_config() {
|
||||
fi
|
||||
done
|
||||
else
|
||||
rm -f /etc/$1/$confd/domains/$domain.conf
|
||||
ln -s $conf /etc/$1/$confd/domains/$domain.conf
|
||||
if [ "$1" = "nginx" ]; then
|
||||
rm -f /usr/local/hestia/nginx-system/etc/$1/$confd/domains/$domain.conf
|
||||
ln -s $conf /usr/local/hestia/nginx-system/etc/$1/$confd/domains/$domain.conf
|
||||
else
|
||||
rm -f /etc/$1/$confd/domains/$domain.conf
|
||||
ln -s $conf /etc/$1/$confd/domains/$domain.conf
|
||||
fi
|
||||
# Rename/Move extra config files
|
||||
find=$(find $HOMEDIR/$user/conf/web/*.$domain.org* 2> /dev/null)
|
||||
for f in $find; do
|
||||
@@ -425,14 +434,18 @@ add_web_config() {
|
||||
|
||||
MOD_CONF="/etc/httpd/conf.modules.d/09-mod-php.conf"
|
||||
PHP_DEFAULT="/usr/bin/php-cgi"
|
||||
php_ver=$(grep -m1 '^LoadModule php_module ' "$MOD_CONF" | grep -oP 'php\d{2}')
|
||||
if [ -e $MOD_CONF ]; then
|
||||
php_ver=$(grep -m1 '^LoadModule php_module ' "$MOD_CONF" | grep -oP 'php\d{2}')
|
||||
else
|
||||
php_ver=$(find /etc/httpd/conf.modules.d -maxdepth 1 -type f -name '*-php*-php.conf' -print -quit | sed -n 's/.*-\(php[0-9]\+\)-php\.conf$/\1/p')
|
||||
fi
|
||||
php_cgi_path=$PHP_DEFAULT
|
||||
|
||||
if [ -n "$php_ver" ]; then
|
||||
if [ -n "$php_type" ]; then
|
||||
php_cgi_path="/opt/brepo/${php_ver}/bin/php-cgi"
|
||||
else
|
||||
php_cgi_path="/etc/opt/remi/php${php_ver}/bin/php-cgi"
|
||||
php_cgi_path="/opt/remi/${php_ver}/root/bin/php-cgi"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -514,17 +527,29 @@ del_web_config() {
|
||||
rm -f $legacyconf
|
||||
|
||||
# Remove old global includes file
|
||||
rm -f /etc/$1/$confd/hestia.conf
|
||||
if [ "$1" = "nginx" ]; then
|
||||
rm -f /usr/local/hestia/nginx-system/etc/$1/$confd/hestia.conf
|
||||
else
|
||||
rm -f /etc/$1/$confd/hestia.conf
|
||||
fi
|
||||
fi
|
||||
|
||||
# Remove domain configuration files and clean up symbolic links
|
||||
rm -f "$conf"
|
||||
|
||||
if [ -n "$WEB_SYSTEM" ] && [ "$WEB_SYSTEM" = "$1" ]; then
|
||||
rm -f "/etc/$WEB_SYSTEM/$confd/domains/$confname"
|
||||
if [ "$WEB_SYSTEM" = "nginx" ]; then
|
||||
rm -f "/usr/local/hestia/nginx-system/etc/$WEB_SYSTEM/$confd/domains/$confname"
|
||||
else
|
||||
rm -f "/etc/$WEB_SYSTEM/$confd/domains/$confname"
|
||||
fi
|
||||
fi
|
||||
if [ -n "$PROXY_SYSTEM" ] && [ "$PROXY_SYSTEM" = "$1" ]; then
|
||||
rm -f "/etc/$PROXY_SYSTEM/$confd/domains/$confname"
|
||||
if [ "$PROXY_SYSTEM" = "nginx" ]; then
|
||||
rm -f "/usr/local/hestia/nginx-system/etc/$PROXY_SYSTEM/$confd/domains/$confname"
|
||||
else
|
||||
rm -f "/etc/$PROXY_SYSTEM/$confd/domains/$confname"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -913,8 +938,16 @@ del_mail_ssl_config() {
|
||||
|
||||
# Remove SSL vhost configuration
|
||||
rm -f $HOMEDIR/$user/conf/mail/$domain/*.*ssl.conf
|
||||
rm -f /etc/$WEB_SYSTEM/$confd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
rm -f /etc/$PROXY_SYSTEM/$pconfd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
if [ "$WEB_SYSTEM" = "nginx" ]; then
|
||||
rm -f /usr/local/hestia/nginx-system/etc/$WEB_SYSTEM/$confd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
else
|
||||
rm -f /etc/$WEB_SYSTEM/$confd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
fi
|
||||
if [ "$PROXY_SYSTEM" = "nginx" ]; then
|
||||
rm -f /usr/local/hestia/nginx-system/etc/$PROXY_SYSTEM/$pconfd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
else
|
||||
rm -f /etc/$PROXY_SYSTEM/$pconfd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
fi
|
||||
|
||||
# Remove SSL certificates
|
||||
rm -f $HOMEDIR/$user/conf/mail/$domain/ssl/*
|
||||
@@ -1002,13 +1035,23 @@ add_webmail_config() {
|
||||
if [[ "$2" =~ stpl$ ]]; then
|
||||
if [ -n "$WEB_SYSTEM" ]; then
|
||||
forcessl="$HOMEDIR/$user/conf/mail/$domain/$WEB_SYSTEM.forcessl.conf"
|
||||
rm -f /etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
ln -s $conf /etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
if [ "$1" = "nginx" ]; then
|
||||
rm -f /usr/local/hestia/nginx-system/etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
ln -s $conf /usr/local/hestia/nginx-system/etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
else
|
||||
rm -f /etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
ln -s $conf /etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
fi
|
||||
fi
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
forcessl="$HOMEDIR/$user/conf/mail/$domain/$PROXY_SYSTEM.forcessl.conf"
|
||||
rm -f /etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
ln -s $conf /etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
if [ "$1" = "nginx" ]; then
|
||||
rm -f /usr/local/hestia/nginx-system/etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
ln -s $conf /usr/local/hestia/nginx-system/etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
else
|
||||
rm -f /etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
ln -s $conf /etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
fi
|
||||
fi
|
||||
|
||||
# Add rewrite rules to force HTTPS/SSL connections
|
||||
@@ -1023,12 +1066,22 @@ add_webmail_config() {
|
||||
find $HOMEDIR/$user/conf/mail/ -maxdepth 1 -type f \( -name "$domain.*" -o -name "ssl.$domain.*" -o -name "*nginx.$domain.*" \) -exec rm {} \;
|
||||
else
|
||||
if [ -n "$WEB_SYSTEM" ]; then
|
||||
rm -f /etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.conf
|
||||
ln -s $conf /etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.conf
|
||||
if [ "$1" = "nginx" ]; then
|
||||
rm -f /usr/local/hestia/nginx-system/etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.conf
|
||||
ln -s $conf /usr/local/hestia/nginx-system/etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.conf
|
||||
else
|
||||
rm -f /etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.conf
|
||||
ln -s $conf /etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.conf
|
||||
fi
|
||||
fi
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
rm -f /etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.conf
|
||||
ln -s $conf /etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.conf
|
||||
if [ "$1" = "nginx" ]; then
|
||||
rm -f /usr/local/hestia/nginx-system/etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.conf
|
||||
ln -s $conf /usr/local/hestia/nginx-system/etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.conf
|
||||
else
|
||||
rm -f /etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.conf
|
||||
ln -s $conf /etc/$1/$confd/domains/$WEBMAIL_ALIAS.$domain.conf
|
||||
fi
|
||||
fi
|
||||
# Clear old configurations
|
||||
find $HOMEDIR/$user/conf/mail/ -maxdepth 1 -type f \( -name "$domain.*" \) -exec rm {} \;
|
||||
@@ -1049,12 +1102,20 @@ del_webmail_config() {
|
||||
fi
|
||||
if [ -n "$WEB_SYSTEM" ]; then
|
||||
rm -f $HOMEDIR/$user/$confd/mail/$domain/$WEB_SYSTEM.conf
|
||||
rm -f /etc/$WEB_SYSTEM/$confd/domains/$WEBMAIL_ALIAS.$domain.conf
|
||||
if [ "$WEB_SYSTEM" = "nginx" ]; then
|
||||
rm -f /usr/local/hestia/nginx-system/etc/$WEB_SYSTEM/$confd/domains/$WEBMAIL_ALIAS.$domain.conf
|
||||
else
|
||||
rm -f /etc/$WEB_SYSTEM/$confd/domains/$WEBMAIL_ALIAS.$domain.conf
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
rm -f $HOMEDIR/$user/conf/mail/$domain/$PROXY_SYSTEM.*conf
|
||||
rm -f /etc/$PROXY_SYSTEM/$pconfd/domains/$WEBMAIL_ALIAS.$domain.conf
|
||||
if [ "$PROXY_SYSTEM" = "nginx" ]; then
|
||||
rm -f /usr/local/hestia/nginx-system/etc/$PROXY_SYSTEM/$pconfd/domains/$WEBMAIL_ALIAS.$domain.conf
|
||||
else
|
||||
rm -f /etc/$PROXY_SYSTEM/$pconfd/domains/$WEBMAIL_ALIAS.$domain.conf
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -1072,12 +1133,20 @@ del_webmail_ssl_config() {
|
||||
fi
|
||||
if [ -n "$WEB_SYSTEM" ]; then
|
||||
rm -f $HOMEDIR/$user/conf/mail/$domain/$WEB_SYSTEM.*ssl.conf
|
||||
rm -f /etc/$WEB_SYSTEM/$confd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
if [ "$WEB_SYSTEM" = "nginx" ]; then
|
||||
rm -f /usr/local/hestia/nginx-system/etc/$WEB_SYSTEM/$confd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
else
|
||||
rm -f /etc/$WEB_SYSTEM/$confd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -n "$PROXY_SYSTEM" ]; then
|
||||
rm -f $HOMEDIR/$user/conf/mail/$domain/$PROXY_SYSTEM.*ssl.conf
|
||||
rm -f /etc/$PROXY_SYSTEM/$pconfd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
if [ "$PROXY_SYSTEM" = "nginx" ]; then
|
||||
rm -f /usr/local/hestia/nginx-system/etc/$PROXY_SYSTEM/$pconfd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
else
|
||||
rm -f /etc/$PROXY_SYSTEM/$pconfd/domains/$WEBMAIL_ALIAS.$domain.ssl.conf
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -1183,14 +1252,14 @@ is_base_domain_owner() {
|
||||
#----------------------------------------------------------#
|
||||
|
||||
process_http2_directive() {
|
||||
if [ -e /etc/nginx/conf.d/http2-directive.conf ]; then
|
||||
if [ -e /usr/local/hestia/nginx-system/etc/nginx/conf.d/http2-directive.conf ]; then
|
||||
while IFS= read -r old_param; do
|
||||
new_param="$(echo "$old_param" | sed 's/\shttp2//')"
|
||||
sed -i "s/$old_param/$new_param/" "$1"
|
||||
done < <(grep -E "listen.*(\bssl\b(\s|.+){1,}\bhttp2\b|\bhttp2\b(\s|.+){1,}\bssl\b).*;" "$1")
|
||||
else
|
||||
if version_ge "$(nginx -v 2>&1 | cut -d'/' -f2)" "1.25.1"; then
|
||||
echo "http2 on;" > /etc/nginx/conf.d/http2-directive.conf
|
||||
if version_ge "$(/usr/local/hestia/nginx-system/sbin/nginx -v 2>&1 | cut -d'/' -f2)" "1.25.1"; then
|
||||
echo "http2 on;" > /usr/local/hestia/nginx-system/etc/nginx/conf.d/http2-directive.conf
|
||||
|
||||
while IFS= read -r old_param; do
|
||||
new_param="$(echo "$old_param" | sed 's/\shttp2//')"
|
||||
|
||||
@@ -56,11 +56,12 @@ upgrade_health_check() {
|
||||
|
||||
upgrade_welcome_message() {
|
||||
echo
|
||||
echo ' _ _ _ _ ____ ____ '
|
||||
echo ' | | | | ___ ___| |_(_) __ _ / ___| _ \ '
|
||||
echo ' | |_| |/ _ \/ __| __| |/ _` | | | |_) | '
|
||||
echo ' | _ | __/\__ \ |_| | (_| | |___| __/ '
|
||||
echo ' |_| |_|\___||___/\__|_|\__,_|\____|_| '
|
||||
echo ' _ _ _ _ ____ ____ '
|
||||
echo ' | | | | ___ ___| |_(_) __ _ / ___| _ \ _ _ . . '
|
||||
echo ' | |_| |/ _ \/ __| __| |/ _` | | | |_) | | \| \|\/| '
|
||||
echo ' | _ | __/\__ \ |_| | (_| | |___| __/ |_/|_/| | '
|
||||
echo ' |_| |_|\___||___/\__|_|\__,_|\____|_| | \| | | '
|
||||
echo " "
|
||||
echo " "
|
||||
echo " Hestia Control Panel Software Update "
|
||||
echo " Version: ${DISPLAY_VER}"
|
||||
@@ -535,7 +536,7 @@ upgrade_cloudflare_ip() {
|
||||
cf_ips="$(curl -fsLm5 --retry 2 https://api.cloudflare.com/client/v4/ips)"
|
||||
|
||||
if [ -n "$cf_ips" ] && [ "$(echo "$cf_ips" | jq -r '.success//""')" = "true" ]; then
|
||||
cf_inc="/etc/nginx/conf.d/cloudflare.inc"
|
||||
cf_inc="/usr/local/hestia/nginx-system/etc/nginx/conf.d/cloudflare.inc"
|
||||
|
||||
echo "[ * ] Updating Cloudflare IP Ranges for NGINX..."
|
||||
echo "# Cloudflare IP Ranges" > $cf_inc
|
||||
|
||||
630
func_ruby/HestiaBunkerWebApi.rb
Normal file
630
func_ruby/HestiaBunkerWebApi.rb
Normal file
@@ -0,0 +1,630 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require 'json'
|
||||
require 'net/http'
|
||||
require 'uri'
|
||||
require 'openssl'
|
||||
|
||||
class BunkerWebApiError < StandardError; end
|
||||
class HestiaBunkerWebApi
|
||||
# Override puts to accumulate logs into @extra_info
|
||||
def puts(*args)
|
||||
@extra_info ||= ""
|
||||
@extra_info << args.join("\n") << "\n"
|
||||
end
|
||||
|
||||
# Accessor for @extra_info
|
||||
def extra_info
|
||||
@extra_info || ""
|
||||
end
|
||||
end
|
||||
|
||||
# Hook to wrap methods of HestiaBunkerWebApi to reset @extra_info at start
|
||||
class Module
|
||||
alias_method :orig_method_added, :method_added
|
||||
def method_added(name)
|
||||
orig_method_added(name)
|
||||
# Skip wrapping for the overridden puts method
|
||||
return if name == :puts
|
||||
if self.name == 'HestiaBunkerWebApi'
|
||||
@__wrapping ||= false
|
||||
return if @__wrapping
|
||||
@__wrapping = true
|
||||
original = instance_method(name)
|
||||
define_method(name) do |*args, &block|
|
||||
@extra_info = ""
|
||||
original.bind(self).call(*args, &block)
|
||||
end
|
||||
@__wrapping = false
|
||||
end
|
||||
end
|
||||
end
|
||||
class HestiaBunkerWebApi
|
||||
# Retrieve API username and password from /etc/bunkerweb/api.env if available
|
||||
def get_api_user_password
|
||||
env_path = "/etc/bunkerweb/api.env"
|
||||
return nil unless File.file?(env_path)
|
||||
|
||||
username = nil
|
||||
password = nil
|
||||
|
||||
File.foreach(env_path) do |line|
|
||||
line.strip!
|
||||
next if line.empty? || line.start_with?('#')
|
||||
key, value = line.split('=', 2)
|
||||
next unless key && value
|
||||
case key
|
||||
when 'API_USERNAME'
|
||||
username = value
|
||||
when 'API_PASSWORD'
|
||||
password = value
|
||||
end
|
||||
end
|
||||
|
||||
if username && password
|
||||
[username, password]
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(api_url, username = nil, password = nil)
|
||||
@api_base = api_url
|
||||
if username.nil?
|
||||
result = get_api_user_password
|
||||
if result.nil?
|
||||
raise BunkerWebApiError.new("Authentication error: no username or password")
|
||||
else
|
||||
@username = result[0]
|
||||
@password = result[1]
|
||||
end
|
||||
else
|
||||
@username = username
|
||||
@password = password
|
||||
end
|
||||
@token = nil
|
||||
@extra_info = ""
|
||||
|
||||
# Authenticate and get token
|
||||
authenticate!
|
||||
|
||||
puts "[INFO] Successfully authenticated with BunkerWeb API"
|
||||
end
|
||||
|
||||
def authenticate!
|
||||
uri = URI(@api_base)
|
||||
http = Net::HTTP.new(uri.host, uri.port)
|
||||
http.use_ssl = (uri.scheme == "https")
|
||||
|
||||
# Try both Basic Auth and JSON body with credentials
|
||||
request = Net::HTTP::Post.new("/auth")
|
||||
request.content_type = "application/json"
|
||||
request.body = { username: @username, password: @password }.to_json
|
||||
|
||||
response = http.request(request)
|
||||
|
||||
if response.code != '200'
|
||||
raise BunkerWebApiError.new("Authentication failed: #{response.code} - #{response.message}")
|
||||
end
|
||||
|
||||
body = JSON.parse(response.body)
|
||||
|
||||
unless body['token']
|
||||
raise BunkerWebApiError.new("Authentication succeeded but no token received")
|
||||
end
|
||||
|
||||
@token = body['token']
|
||||
rescue => e
|
||||
raise BunkerWebApiError.new("Authentication error: #{e.message}")
|
||||
end
|
||||
|
||||
def api_call(method, path, headers = {}, body = nil)
|
||||
uri = URI(@api_base + path)
|
||||
http = Net::HTTP.new(uri.host, uri.port)
|
||||
http.use_ssl = (uri.scheme == "https")
|
||||
|
||||
request = case method
|
||||
when "GET"
|
||||
Net::HTTP::Get.new(uri.path)
|
||||
when "POST"
|
||||
req = Net::HTTP::Post.new(uri.path)
|
||||
req.body = body if body
|
||||
req
|
||||
when "PATCH"
|
||||
req = Net::HTTP::Patch.new(uri.path)
|
||||
req.body = body if body
|
||||
req
|
||||
when "DELETE"
|
||||
Net::HTTP::Delete.new(uri.path)
|
||||
else
|
||||
raise BunkerWebApiError.new("Unsupported HTTP method: #{method}")
|
||||
end
|
||||
|
||||
# Add Authorization header with token for most operations (except /auth)
|
||||
unless path == "/auth"
|
||||
headers["Authorization"] = "Bearer #{@token}" if @token
|
||||
end
|
||||
|
||||
# Add Content-Type if not already set and we have a body
|
||||
if body && !headers.key?("Content-Type")
|
||||
headers["Content-Type"] = "application/json"
|
||||
end
|
||||
|
||||
headers.each { |k, v| request[k] = v }
|
||||
|
||||
response = http.request(request)
|
||||
parsed_body = begin
|
||||
JSON.parse(response.body)
|
||||
rescue => e
|
||||
nil
|
||||
end
|
||||
|
||||
{ status: response.code.to_i, body: parsed_body || {}, raw_body: response.body }
|
||||
rescue => e
|
||||
raise BunkerWebApiError.new("API call to #{path} failed: #{e.message}")
|
||||
end
|
||||
|
||||
# === Service Operations ===
|
||||
|
||||
def create_service(service_name, options = {})
|
||||
@extra_info = ""
|
||||
# Create a new service with the given configuration.
|
||||
#
|
||||
# Args:
|
||||
# service_name (String): The domain name for this service (server_name)
|
||||
# options (Hash): Service configuration including:
|
||||
# - USE_TEMPLATE (default: "high")
|
||||
# - USE_SSL (default: "no") - if not "no", you need CERTIFICATE and KEY paths
|
||||
# - REVERSE_PROXY_HOST (optional)
|
||||
# - REVERSE_PROXY_URL (optional, default: "~ ^/(.*)$")
|
||||
# - Additional options like:
|
||||
# - USE_REVERSE_PROXY (default: "yes" if REVERSE_PROXY_HOST is set)
|
||||
# - USE_REAL_IP, REAL_IP_FROM
|
||||
# - USE_MODSECURITY, USE_ANTIBOT
|
||||
# - LISTEN_HTTP_PORT, LISTEN_HTTPS_PORT
|
||||
# - CERTIFICATE_FILE_PATH (if USE_SSL != "no")
|
||||
# - KEY_FILE_PATH (if USE_SSL != "no")
|
||||
# Returns: Hash with creation response
|
||||
|
||||
variables = {
|
||||
"USE_TEMPLATE" => options[:use_template] || "high",
|
||||
"USE_REVERSE_PROXY" => options[:reverse_proxy_host].nil? ? "no" : "yes",
|
||||
"LIMIT_REQ_RATE" => options[:limit_req_rate] || "10r/s",
|
||||
}
|
||||
|
||||
# SSL configuration - only if USE_SSL != "no"
|
||||
ssl_enabled = options[:ssl] && options[:ssl] != "no"
|
||||
variables["USE_CUSTOM_SSL"] = ssl_enabled ? "yes" : "no"
|
||||
|
||||
if ssl_enabled
|
||||
unless options[:certificate_path] && options[:key_path]
|
||||
raise BunkerWebApiError.new("Certificate and Key paths are required when USE_SSL is enabled")
|
||||
end
|
||||
|
||||
# Set certificate paths in variables
|
||||
variables["CUSTOM_SSL_CERT"] = options[:certificate_path]
|
||||
variables["CUSTOM_SSL_KEY"] = options[:key_path]
|
||||
|
||||
variables["LISTEN_HTTPS_PORT"] = (options[:https_port] || "443").to_s
|
||||
variables["USE_REVERSE_PROXY_SSL"] = options[:reverse_proxy_ssl] || "yes"
|
||||
else
|
||||
# No SSL - HTTP only
|
||||
# API expects string "null", not nil/JSON null
|
||||
variables["LISTEN_HTTPS_PORT"] = "null"
|
||||
variables["LISTEN_HTTP_PORT"] = (options[:http_port] || "80").to_s
|
||||
end
|
||||
|
||||
# Reverse proxy configuration if specified
|
||||
if options[:reverse_proxy_host]
|
||||
variables["REVERSE_PROXY_HOST"] = options[:reverse_proxy_host]
|
||||
variables["REVERSE_PROXY_URL"] = options[:reverse_proxy_url] || "~ ^(?!/challenge)(.*)$"
|
||||
|
||||
# Real IP settings for reverse proxy
|
||||
unless options[:real_ip_from].nil?
|
||||
variables["USE_REAL_IP"] = "yes"
|
||||
variables["REAL_IP_FROM"] = options[:real_ip_from]
|
||||
end
|
||||
|
||||
# Additional security settings from High template
|
||||
variables["USE_MODSECURITY"] = options[:use_modsecurity] || "yes"
|
||||
variables["USE_ANTIBOT"] = options[:anti_bot] || "captcha"
|
||||
end
|
||||
|
||||
variables["ANTIBOT_IGNORE_URI"] = options[:anti_bot_ignore_uri] || "^/\.well-known/acme-challenge/.+$"
|
||||
variables["LETS_ENCRYPT_PASSTHROUGH"] = options[:lets_encrypt_passthrough] || "yes"
|
||||
|
||||
|
||||
service_body = {
|
||||
server_name: service_name,
|
||||
is_draft: false,
|
||||
variables: variables
|
||||
}
|
||||
|
||||
response = api_call("POST", "/services", {}, JSON.generate(service_body))
|
||||
|
||||
# Accept both 201 (Created) and 200 (OK) for successful creation
|
||||
if [201, 200].include?(response[:status])
|
||||
puts "[INFO] Service '#{service_name}' created successfully"
|
||||
elsif response[:status] == 409
|
||||
raise BunkerWebApiError.new("Service '#{service_name}' already exists")
|
||||
else
|
||||
raise BunkerWebApiError.new("Failed to create service: status=#{response[:status]}, body=#{response[:raw_body]}")
|
||||
end
|
||||
|
||||
return response[:body] || {}
|
||||
end
|
||||
|
||||
def update_service_ssl(service_name, certificate_path, key_path, https_port = nil)
|
||||
# Update or change the SSL certificate path for an existing service.
|
||||
#
|
||||
# Args:
|
||||
# service_name (String): Name of the service to update
|
||||
# certificate_path (String): Path to the SSL certificate file
|
||||
# key_path (String): Path to the SSL private key file
|
||||
# https_port (Integer, optional): HTTPS port (default 443)
|
||||
# Returns: Hash with update response
|
||||
|
||||
@extra_info = ""
|
||||
|
||||
# First get current service configuration to preserve existing settings
|
||||
get_service_response = api_call("GET", "/services/#{service_name}", {})
|
||||
|
||||
if get_service_response[:status] != 200
|
||||
raise BunkerWebApiError.new("Service '#{service_name}' not found")
|
||||
end
|
||||
|
||||
# Extract variables from config - API stores them in 'config' not 'variables'
|
||||
# Each variable is a hash with 'value' as the actual setting value
|
||||
current_vars = {}
|
||||
if get_service_response[:body]["config"]
|
||||
get_service_response[:body]["config"].each do |key, value_hash|
|
||||
if value_hash.is_a?(Hash) && value_hash.key?("value")
|
||||
current_vars[key] = value_hash["value"]
|
||||
else
|
||||
current_vars[key] = value_hash
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Update SSL settings
|
||||
updated_vars = {
|
||||
"USE_CUSTOM_SSL" => "yes",
|
||||
"CUSTOM_SSL_CERT" => certificate_path,
|
||||
"CUSTOM_SSL_KEY" => key_path,
|
||||
"LISTEN_HTTPS_PORT" => (https_port || "443").to_s,
|
||||
"USE_REVERSE_PROXY_SSL" => "yes"
|
||||
}
|
||||
|
||||
# Merge with existing variables (keep non-SSL settings)
|
||||
final_vars = current_vars.merge(updated_vars)
|
||||
|
||||
service_body = {
|
||||
server_name: nil, # Not changing name
|
||||
is_draft: false, # Keep as online
|
||||
variables: final_vars
|
||||
}
|
||||
|
||||
response = api_call("PATCH", "/services/#{service_name}", {}, JSON.generate(service_body))
|
||||
|
||||
if response[:status] == 200
|
||||
puts "[INFO] SSL configuration updated for service '#{service_name}'"
|
||||
else
|
||||
raise BunkerWebApiError.new("Failed to update SSL configuration: status=#{response[:status]}, body=#{response[:raw_body]}")
|
||||
end
|
||||
|
||||
return response[:body] || {}
|
||||
end
|
||||
|
||||
|
||||
def set_alias(service_name, list_aliases)
|
||||
@extra_info = ""
|
||||
|
||||
# First get current service configuration to preserve existing settings
|
||||
get_service_response = api_call("GET", "/services/#{service_name}", {})
|
||||
|
||||
if get_service_response[:status] != 200
|
||||
raise BunkerWebApiError.new("Service '#{service_name}' not found")
|
||||
end
|
||||
|
||||
# Save the entire current configuration (except server_name which will be replaced)
|
||||
current_config = get_service_response[:body]
|
||||
|
||||
# Extract variables from config - API stores them in 'config' not 'variables'
|
||||
# Each variable is a hash with 'value' as the actual setting value
|
||||
current_vars = {}
|
||||
if current_config["config"]
|
||||
current_config["config"].each do |key, value_hash|
|
||||
if key != "SERVER_NAME"
|
||||
if value_hash.is_a?(Hash) && value_hash.key?("value")
|
||||
current_vars[key] = value_hash["value"]
|
||||
else
|
||||
current_vars[key] = value_hash
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Clean the list_aliases string according to the rules
|
||||
cleaned_aliases = list_aliases.to_s
|
||||
|
||||
# Replace commas (with or without space) with a single space
|
||||
cleaned_aliases.gsub!(/,\s?/, ' ')
|
||||
|
||||
# Replace multiple spaces with a single space
|
||||
cleaned_aliases.gsub!(/\s{2,}/, ' ')
|
||||
|
||||
# Strip leading/trailing whitespace
|
||||
cleaned_aliases.strip!
|
||||
|
||||
# Ensure the main service name appears first in the alias list
|
||||
aliases_array = cleaned_aliases.split(' ')
|
||||
if aliases_array.include?(service_name)
|
||||
aliases_array.delete(service_name)
|
||||
end
|
||||
# Rebuild cleaned string
|
||||
cleaned_aliases = aliases_array.join(' ')
|
||||
current_vars["SERVER_NAME"]=cleaned_aliases
|
||||
|
||||
# Step 1: Delete the old service
|
||||
delete_response = api_call("DELETE", "/services/#{service_name}")
|
||||
if delete_response[:status] != 200 && delete_response[:status] != 204
|
||||
raise BunkerWebApiError.new("Failed to delete service '#{service_name}': status=#{delete_response[:status]}")
|
||||
end
|
||||
puts "[INFO] Service '#{service_name}' deleted"
|
||||
|
||||
# Step 2: Create a new service with the cleaned alias list as server_name
|
||||
# and preserve all existing configuration variables
|
||||
service_body = {
|
||||
server_name: service_name, # Use the full alias list including service_name first
|
||||
is_draft: current_config["is_draft"] || false,
|
||||
variables: current_vars # Preserve all existing variables from the original service
|
||||
}
|
||||
|
||||
post_response = api_call("POST", "/services", {}, JSON.generate(service_body))
|
||||
|
||||
if post_response[:status] == 200 || post_response[:status] == 201
|
||||
puts "[INFO] Service recreated successfully with aliases: #{cleaned_aliases}"
|
||||
elsif post_response[:status] == 409
|
||||
raise BunkerWebApiError.new("Service '#{service_name}' already exists")
|
||||
else
|
||||
raise BunkerWebApiError.new("Failed to create service: status=#{post_response[:status]}, body=#{post_response[:raw_body]}")
|
||||
end
|
||||
|
||||
return post_response || {}
|
||||
end
|
||||
|
||||
|
||||
def delete_service_ssl(service_name)
|
||||
|
||||
@extra_info = ""
|
||||
|
||||
# First get current service configuration to preserve existing settings
|
||||
get_service_response = api_call("GET", "/services/#{service_name}", {})
|
||||
|
||||
if get_service_response[:status] != 200
|
||||
raise BunkerWebApiError.new("Service '#{service_name}' not found")
|
||||
end
|
||||
|
||||
# Extract variables from config - API stores them in 'config' not 'variables'
|
||||
# Each variable is a hash with 'value' as the actual setting value
|
||||
current_vars = {}
|
||||
if get_service_response[:body]["config"]
|
||||
get_service_response[:body]["config"].each do |key, value_hash|
|
||||
if value_hash.is_a?(Hash) && value_hash.key?("value")
|
||||
current_vars[key] = value_hash["value"]
|
||||
else
|
||||
current_vars[key] = value_hash
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Update SSL settings
|
||||
updated_vars = {
|
||||
"USE_CUSTOM_SSL" => "no",
|
||||
"CUSTOM_SSL_CERT" => "",
|
||||
"CUSTOM_SSL_KEY" => ""
|
||||
}
|
||||
|
||||
# Merge with existing variables (keep non-SSL settings)
|
||||
final_vars = current_vars.merge(updated_vars)
|
||||
|
||||
service_body = {
|
||||
server_name: nil, # Not changing name
|
||||
is_draft: false, # Keep as online
|
||||
variables: final_vars
|
||||
}
|
||||
|
||||
response = api_call("PATCH", "/services/#{service_name}", {}, JSON.generate(service_body))
|
||||
|
||||
if response[:status] == 200
|
||||
puts "[INFO] SSL configuration updated for service '#{service_name}'"
|
||||
else
|
||||
raise BunkerWebApiError.new("Failed to update SSL configuration: status=#{response[:status]}, body=#{response[:raw_body]}")
|
||||
end
|
||||
|
||||
return response[:body] || {}
|
||||
end
|
||||
|
||||
def delete_service(service_name)
|
||||
# Delete a service by its name.
|
||||
#
|
||||
# Args:
|
||||
# service_name (String): Name of the service to delete
|
||||
# Returns: Hash with deletion response
|
||||
|
||||
@extra_info = ""
|
||||
# Verify service exists first
|
||||
get_response = api_call("GET", "/services/#{service_name}", {})
|
||||
|
||||
if get_response[:status] != 200
|
||||
raise BunkerWebApiError.new("Service '#{service_name}' not found")
|
||||
end
|
||||
|
||||
response = api_call("DELETE", "/services/#{service_name}")
|
||||
|
||||
if response[:status] == 200 || response[:status] == 204
|
||||
puts "[INFO] Service '#{service_name}' deleted successfully"
|
||||
return response[:body] || {}
|
||||
else
|
||||
raise BunkerWebApiError.new("Failed to delete service: status=#{response[:status]}, body=#{response[:raw_body]}")
|
||||
end
|
||||
end
|
||||
|
||||
# === Additional Utility Methods ===
|
||||
|
||||
def list_services(drafts = false)
|
||||
# List all services.
|
||||
#
|
||||
# Args:
|
||||
# drafts (Boolean): Include draft services (default: false, set to true to include drafts)
|
||||
# Returns: Array of service objects
|
||||
|
||||
@extra_info = ""
|
||||
response = api_call("GET", "/services")
|
||||
|
||||
if response[:status] != 200
|
||||
raise BunkerWebApiError.new("Failed to list services: status=#{response[:status]}")
|
||||
end
|
||||
|
||||
return response[:body] || []
|
||||
end
|
||||
|
||||
def get_service(service_name)
|
||||
# Get details of a specific service.
|
||||
#
|
||||
# Args:
|
||||
# service_name (String): Name of the service to retrieve
|
||||
# Returns: Hash with service configuration
|
||||
|
||||
@extra_info = ""
|
||||
response = api_call("GET", "/services/#{service_name}")
|
||||
|
||||
if response[:status] != 200
|
||||
raise BunkerWebApiError.new("Service '#{service_name}' not found")
|
||||
end
|
||||
|
||||
return response[:body] || {}
|
||||
end
|
||||
|
||||
def reload_instance(instance_hostname = nil)
|
||||
# Reload configuration on an instance.
|
||||
#
|
||||
# Args:
|
||||
# instance_hostname (String, optional): Instance hostname to reload (if nil, reloads all instances)
|
||||
# Returns: Hash with reload response
|
||||
|
||||
@extra_info = ""
|
||||
path = if instance_hostname.nil?
|
||||
"/instances/reload"
|
||||
else
|
||||
"/instances/#{instance_hostname}/reload"
|
||||
end
|
||||
|
||||
response = api_call("POST", "#{path}?test=no")
|
||||
|
||||
if response[:status] == 200 || response[:status] == 201
|
||||
puts "[INFO] Configuration reloaded successfully"
|
||||
return response[:body] || {}
|
||||
else
|
||||
raise BunkerWebApiError.new("Failed to reload configuration: status=#{response[:status]}")
|
||||
end
|
||||
end
|
||||
|
||||
def list_instances()
|
||||
# List all registered instances.
|
||||
# Returns: Array of instance objects
|
||||
|
||||
@extra_info = ""
|
||||
response = api_call("GET", "/instances")
|
||||
|
||||
if response[:status] != 200
|
||||
raise BunkerWebApiError.new("Failed to list instances: status=#{response[:status]}")
|
||||
end
|
||||
|
||||
return response[:body] || []
|
||||
end
|
||||
|
||||
def create_instance(hostname, name = nil, port = 8888, https_port = nil)
|
||||
# Create/register a new BunkerWeb instance (worker node).
|
||||
#
|
||||
# Args:
|
||||
# hostname (String): IP address or hostname of the worker node
|
||||
# name (String, optional): Human-readable name for the instance
|
||||
# port (Integer): API port on the worker node (default 8888)
|
||||
# https_port (Integer, optional): HTTPS port
|
||||
# Returns: Hash with creation response
|
||||
|
||||
@extra_info = ""
|
||||
instance_body = {
|
||||
hostname: hostname,
|
||||
name: name || "BunkerWeb Instance",
|
||||
port: port,
|
||||
listen_https: !https_port.nil?,
|
||||
https_port: https_port,
|
||||
server_name: hostname,
|
||||
method: "api" # Using API deployment method
|
||||
}
|
||||
|
||||
response = api_call("POST", "/instances", {}, JSON.generate(instance_body))
|
||||
|
||||
if response[:status] == 201
|
||||
puts "[INFO] Instance '#{hostname}' registered successfully"
|
||||
elsif response[:status] == 409
|
||||
# Instance already exists - that's OK, we just want to use it
|
||||
puts "[INFO] Instance '#{hostname}' already exists, will be used for this service"
|
||||
else
|
||||
raise BunkerWebApiError.new("Failed to create instance: status=#{response[:status]}, body=#{response[:raw_body]}")
|
||||
end
|
||||
|
||||
return response[:body] || {}
|
||||
end
|
||||
|
||||
def delete_instance(hostname)
|
||||
"""
|
||||
Delete a registered instance.
|
||||
|
||||
Args:
|
||||
hostname (String): Hostname of the instance to delete
|
||||
"""
|
||||
|
||||
@extra_info = ""
|
||||
response = api_call("DELETE", "/instances/#{hostname}")
|
||||
|
||||
if response[:status] == 200 || response[:status] == 204
|
||||
puts "[INFO] Instance '#{hostname}' deleted successfully"
|
||||
return true
|
||||
else
|
||||
raise BunkerWebApiError.new("Failed to delete instance: status=#{response[:status]}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# === Example Usage (can be run as script) ===
|
||||
|
||||
if __FILE__ == $0
|
||||
# Example usage demonstration
|
||||
begin
|
||||
api = HestiaBunkerWebApi.new(
|
||||
"http://127.0.0.1:8888",
|
||||
"admin",
|
||||
"your_password"
|
||||
)
|
||||
|
||||
puts ""
|
||||
puts "[INFO] Creating service 'example.my.domain'"
|
||||
result = api.create_service("example.my.domain", {
|
||||
reverse_proxy_host: "http://192.168.3.51:8078",
|
||||
ssl: "no",
|
||||
use_template: "high"
|
||||
})
|
||||
|
||||
puts ""
|
||||
puts "[INFO] Listing services:"
|
||||
services = api.list_services()
|
||||
services.each { |s| puts "- #{s['server_name']}" }
|
||||
|
||||
rescue BunkerWebApiError => e
|
||||
puts "[ERROR] #{e.message}"
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
467
func_ruby/docs/BunkerWebApiDoc.md
Normal file
467
func_ruby/docs/BunkerWebApiDoc.md
Normal file
@@ -0,0 +1,467 @@
|
||||
# HestiaBunkerWebApi - Ruby класс для работы с BunkerWeb API
|
||||
|
||||
## Описание
|
||||
|
||||
Класс `HestiaBunkerWebApi` предоставляет простой интерфейс для управления сервисами BunkerWeb через REST API. Класс реализует:
|
||||
|
||||
- **Аутентификацию** с получением токена
|
||||
- **Управление сервисами** (создание, обновление, удаление)
|
||||
- **Управление SSL сертификатами**
|
||||
- **Управление instances** (worker nodes)
|
||||
- **Полное исключение ошибок** при любых проблемах
|
||||
|
||||
## Установка и импорт
|
||||
|
||||
```bash
|
||||
# Ruby 3.3+ рекомендуется
|
||||
ruby --version
|
||||
# ruby 3.3.x or later
|
||||
|
||||
# Класс использует стандартные библиотеки Ruby:
|
||||
# - json (для JSON парсинга)
|
||||
# - net/http (для HTTP запросов)
|
||||
# - uri (для URL парсинга)
|
||||
```
|
||||
|
||||
## Использование класса
|
||||
|
||||
### Базовое использование
|
||||
|
||||
```ruby
|
||||
require_relative "HestiaBunkerWebApi.rb"
|
||||
|
||||
# Создаём экземпляр API с аутентификацией
|
||||
api = HestiaBunkerWebApi.new(
|
||||
"http://127.0.0.1:8888", # URL API (можно https://)
|
||||
"admin", # username
|
||||
"password" # password
|
||||
)
|
||||
# или
|
||||
api = HestiaBunkerWebApi.new(
|
||||
"http://127.0.0.1:8888", # URL API (можно https://)
|
||||
)
|
||||
# в этом случае пароль и логин читаются автоматически из файла /etc/bunkerweb/api.env
|
||||
|
||||
|
||||
# При создании экземпляра автоматически происходит аутентификация
|
||||
# Если ошибка - выбрасывается BunkerWebApiError с описанием проблемы
|
||||
```
|
||||
|
||||
### Обработка ошибок
|
||||
|
||||
Все ошибки наследуются от `StandardError` через класс `BunkerWebApiError`:
|
||||
|
||||
```ruby
|
||||
begin
|
||||
api.create_service("example.domain", options)
|
||||
rescue BunkerWebApiError => e
|
||||
puts "[ERROR] Ошибка API: #{e.message}"
|
||||
|
||||
# Примеры возможных ошибок:
|
||||
# - "Authentication failed: 401 - Unauthorized"
|
||||
# - "Service 'x' already exists"
|
||||
# - "Certificate and Key paths are required when USE_SSL is enabled"
|
||||
# - "Failed to create service: status=500, body={...}"
|
||||
|
||||
exit 1
|
||||
end
|
||||
```
|
||||
|
||||
## Методы класса
|
||||
|
||||
### Конструктор
|
||||
|
||||
```ruby
|
||||
HestiaBunkerWebApi.new(api_url, username, password)
|
||||
```
|
||||
|
||||
**Параметры:**
|
||||
- `api_url` - URL BunkerWeb API в формате `http://ip:port` или `https://ip:port`
|
||||
- `username` - имя администратора для аутентификации
|
||||
- `password` - пароль для аутентификации
|
||||
|
||||
**Действие:** При создании автоматически пытается аутентифицироваться через POST /auth и сохраняет токен.
|
||||
|
||||
### Создание сервиса
|
||||
|
||||
```ruby
|
||||
api.create_service(service_name, options = {})
|
||||
```
|
||||
|
||||
**Параметры:**
|
||||
- `service_name` - имя домена/сервиса (например, "example.my.domain")
|
||||
- `options` - хэш с конфигурацией:
|
||||
|
||||
| Параметр | Тип | Описание | Пример |
|
||||
|----------|-----|----------|--------|
|
||||
| `ssl` | String | "yes" для SSL, "no" для HTTP | `"no"` |
|
||||
| `certificate_path` | String | Путь к SSL сертификату (если ssl="yes") | `"/etc/ssl/certs/example.crt"` |
|
||||
| `key_path` | String | Путь к приватному ключу (если ssl="yes") | `"/etc/ssl/private/example.key"` |
|
||||
| `use_template` | String | Безопасность шаблона | `"high"` (default) |
|
||||
| `reverse_proxy_host` | String | Target reverse proxy | `"http://192.168.3.51:8078"` |
|
||||
| `reverse_proxy_url` | String | URL трансформация | `"~ ^/(.*)$"` |
|
||||
| `real_ip_from` | String | CIDR trusted network для RealIP | `"192.168.3.0/24"` |
|
||||
| `use_modsecurity` | String | WAF включение | `"yes"` (default) |
|
||||
| `anti_bot` | String | Bot protection | `"captcha"` (default) |
|
||||
| `http_port` | Integer/nil | HTTP порт | `"80"` или `null` |
|
||||
| `https_port` | Integer | HTTPS порт | `443` или `null` |
|
||||
|
||||
**Пример - создание reverse proxy сервиса без SSL:**
|
||||
```ruby
|
||||
result = api.create_service("example.my.domain", {
|
||||
ssl: "no",
|
||||
reverse_proxy_host: "http://192.168.3.51:8078"
|
||||
})
|
||||
|
||||
# Генерирует variables:
|
||||
# - USE_TEMPLATE: "high"
|
||||
# - USE_SSL: "no"
|
||||
# - LISTEN_HTTPS_PORT: "null"
|
||||
# - LISTEN_HTTP_PORT: "80"
|
||||
# - USE_REVERSE_PROXY: "yes"
|
||||
# - REVERSE_PROXY_HOST: "http://192.168.3.51:8078"
|
||||
```
|
||||
|
||||
**Пример - создание сервиса с SSL + reverse proxy:**
|
||||
```ruby
|
||||
result = api.create_service("example.my.domain", {
|
||||
ssl: "yes", # Включаем SSL
|
||||
|
||||
certificate_path: "/etc/ssl/certs/example.crt", # Путь к сертификату
|
||||
key_path: "/etc/ssl/private/example.key", # Путь к ключу
|
||||
|
||||
reverse_proxy_host: "http://192.168.3.51:8078", # Reverse proxy target
|
||||
|
||||
use_template: "high",
|
||||
anti_bot: "captcha"
|
||||
})
|
||||
|
||||
# Генерирует variables:
|
||||
# - USE_TEMPLATE: "high"
|
||||
# - USE_SSL: "yes"
|
||||
# - SSL_CERTIFICATE_FILE_PATH: "/etc/ssl/certs/example.crt"
|
||||
# - SSL_KEY_FILE_PATH: "/etc/ssl/private/example.key"
|
||||
# - LISTEN_HTTPS_PORT: "443"
|
||||
# - LISTEN_HTTP_PORT: "80"
|
||||
```
|
||||
|
||||
### Обновление SSL сертификата для существующего сервиса
|
||||
|
||||
```ruby
|
||||
api.update_service_ssl(service_name, certificate_path, key_path, https_port = nil)
|
||||
```
|
||||
|
||||
**Параметры:**
|
||||
- `service_name` - имя уже созданного сервиса
|
||||
- `certificate_path` - новый путь к SSL сертификату
|
||||
- `key_path` - новый путь к приватному ключу
|
||||
- `https_port` (optional) - HTTPS порт (default: 443)
|
||||
|
||||
**Пример:**
|
||||
```ruby
|
||||
api.update_service_ssl(
|
||||
"example.my.domain",
|
||||
"/etc/ssl/certs/example.crt",
|
||||
"/etc/ssl/private/example.key"
|
||||
)
|
||||
|
||||
# Обновляет существующий сервис, сохраняя reverse proxy настройки
|
||||
```
|
||||
|
||||
### Удаление сервиса
|
||||
|
||||
```ruby
|
||||
api.delete_service(service_name)
|
||||
```
|
||||
|
||||
**Параметры:**
|
||||
- `service_name` - имя сервиса для удаления
|
||||
|
||||
**Пример:**
|
||||
```ruby
|
||||
api.delete_service("example.my.domain")
|
||||
# Удаляет сервис и конфигурацию
|
||||
```
|
||||
|
||||
### Получение списка всех сервисов
|
||||
|
||||
```ruby
|
||||
api.list_services(drafts = false)
|
||||
```
|
||||
|
||||
**Параметры:**
|
||||
- `drafts` (optional) - включать draft сервисы (default: false)
|
||||
|
||||
**Возвращает:** Array of service objects
|
||||
|
||||
**Пример:**
|
||||
```ruby
|
||||
services = api.list_services()
|
||||
services.each { |s| puts "- #{s['server_name']}" }
|
||||
```
|
||||
|
||||
### Получение деталей конкретного сервиса
|
||||
|
||||
```ruby
|
||||
api.get_service(service_name)
|
||||
```
|
||||
|
||||
**Параметры:**
|
||||
- `service_name` - имя сервиса для получения деталей
|
||||
|
||||
**Возвращает:** Hash with service configuration (variables, settings, etc.)
|
||||
|
||||
**Пример:**
|
||||
```ruby
|
||||
config = api.get_service("example.my.domain")
|
||||
puts config.inspect
|
||||
```
|
||||
|
||||
### Перезагрузка конфигурации на instance
|
||||
|
||||
```ruby
|
||||
api.reload_instance(instance_hostname = nil)
|
||||
```
|
||||
|
||||
**Параметры:**
|
||||
- `instance_hostname` (optional) - hostname instance для перезагрузки (если nil, reloads all instances)
|
||||
|
||||
**Пример:**
|
||||
```ruby
|
||||
# Reload все instances
|
||||
api.reload_instance()
|
||||
|
||||
# Reload конкретный instance
|
||||
api.reload_instance("192.168.3.50")
|
||||
```
|
||||
|
||||
### Получение списка всех instances
|
||||
|
||||
```ruby
|
||||
api.list_instances()
|
||||
```
|
||||
|
||||
**Возвращает:** Array of instance objects (hostname, name, port, etc.)
|
||||
|
||||
### Создание/регистрация BunkerWeb instance (worker node)
|
||||
|
||||
```ruby
|
||||
api.create_instance(hostname, name = nil, port = 8888, https_port = nil)
|
||||
```
|
||||
|
||||
**Параметры:**
|
||||
- `hostname` - IP address или hostname worker node
|
||||
- `name` (optional) - Human-readable имя instance
|
||||
- `port` - API port на worker node (default: 8888)
|
||||
- `https_port` (optional) - HTTPS port если есть
|
||||
|
||||
**Пример:**
|
||||
```ruby
|
||||
api.create_instance(
|
||||
"192.168.3.50", # IP worker node
|
||||
"BunkerWeb Worker Node", # Optional name
|
||||
8888 # API port
|
||||
)
|
||||
|
||||
# Возвращает: { status: 201/409, body: {...} }
|
||||
# Если статус 201 - instance создан
|
||||
# Если статус 409 - instance уже существует (это OK)
|
||||
```
|
||||
|
||||
### Удаление BunkerWeb instance
|
||||
|
||||
```ruby
|
||||
api.delete_instance(hostname)
|
||||
```
|
||||
|
||||
**Параметры:**
|
||||
- `hostname` - hostname instance для удаления
|
||||
|
||||
## Примеры полного использования
|
||||
|
||||
### Пример 1: Создание и управление сервисом
|
||||
|
||||
```ruby
|
||||
require_relative "HestiaBunkerWebApi.rb"
|
||||
|
||||
begin
|
||||
# 1. Подключаемся к API
|
||||
api = HestiaBunkerWebApi.new(
|
||||
"http://127.0.0.1:8888",
|
||||
"admin",
|
||||
"your_password"
|
||||
)
|
||||
|
||||
# 2. Создаём reverse proxy сервис без SSL
|
||||
result = api.create_service("u4.my.brp", {
|
||||
ssl: "no",
|
||||
reverse_proxy_host: "http://192.168.3.51:8078"
|
||||
})
|
||||
|
||||
puts "[INFO] Service created: #{result.inspect}"
|
||||
|
||||
# 3. Добавляем SSL сертификат позже (если нужно)
|
||||
api.update_service_ssl(
|
||||
"u4.my.brp",
|
||||
"/etc/ssl/certs/u4.crt",
|
||||
"/etc/ssl/private/u4.key"
|
||||
)
|
||||
|
||||
# 4. Проверяем список сервисов
|
||||
services = api.list_services()
|
||||
puts "[INFO] All services:"
|
||||
services.each { |s| puts "- #{s['server_name']}" }
|
||||
|
||||
# 5. Удаление сервиса (при необходимости)
|
||||
api.delete_service("u4.my.brp")
|
||||
|
||||
rescue BunkerWebApiError => e
|
||||
puts "[ERROR] Ошибка API: #{e.message}"
|
||||
exit 1
|
||||
end
|
||||
```
|
||||
|
||||
### Пример 2: Управление несколькими сервисами
|
||||
|
||||
```ruby
|
||||
require_relative "HestiaBunkerWebApi.rb"
|
||||
|
||||
api = HestiaBunkerWebApi.new("http://127.0.0.1:8888", "admin", "password")
|
||||
|
||||
# Создаём несколько сервисов с разными конфигурациями
|
||||
services_to_create = [
|
||||
{ name: "service1.domain", ssl: "no", reverse_proxy_host: "http://192.168.3.50:80" },
|
||||
{ name: "service2.domain", ssl: "yes", certificate_path: "/certs/service2.crt", key_path: "/keys/service2.key", reverse_proxy_host: "http://192.168.3.51:8078" }
|
||||
]
|
||||
|
||||
services_to_create.each do |opts|
|
||||
begin
|
||||
api.create_service(opts[:name], opts)
|
||||
rescue BunkerWebApiError => e
|
||||
puts "[ERROR] #{e.message}" if e.message.include?("already exists")
|
||||
end
|
||||
end
|
||||
|
||||
# Reload конфигурации на instance
|
||||
api.reload_instance("192.168.3.50")
|
||||
```
|
||||
|
||||
### Пример 3: Обработка ошибок и логирование
|
||||
|
||||
```ruby
|
||||
require_relative "HestiaBunkerWebApi.rb"
|
||||
|
||||
def safe_create_service(api_url, username, password, service_name, options)
|
||||
begin
|
||||
api = HestiaBunkerWebApi.new(api_url, username, password)
|
||||
|
||||
result = api.create_service(service_name, options)
|
||||
return { success: true, data: result }
|
||||
|
||||
rescue BunkerWebApiError => e
|
||||
if e.message.include?("Authentication")
|
||||
puts "[FATAL] Authentication failed: #{e.message}"
|
||||
elsif e.message.include?("already exists")
|
||||
begin
|
||||
existing = api.get_service(service_name)
|
||||
return { success: false, already_exists: true, service: existing }
|
||||
rescue => get_error
|
||||
return { success: false, error: "Can't retrieve service: #{get_error.message}" }
|
||||
else
|
||||
return { success: false, error: e.message }
|
||||
end
|
||||
end
|
||||
|
||||
{ success: false, error: "Unknown error" }
|
||||
end
|
||||
|
||||
# Использование
|
||||
result = safe_create_service("http://127.0.0.1:8888", "admin", "password", "example.domain", { ssl: "yes" })
|
||||
|
||||
if result[:success]
|
||||
puts "[SUCCESS] Service created"
|
||||
elsif result[:already_exists]
|
||||
puts "[INFO] Service exists:"
|
||||
puts JSON.generate(result[:service])
|
||||
else
|
||||
puts "[FAILED] #{result[:error]}"
|
||||
end
|
||||
```
|
||||
|
||||
## Ошибки и их обработка
|
||||
|
||||
### Типичные ошибки:
|
||||
|
||||
| Код ответа | Описание | Пример сообщения |
|
||||
|------------|----------|------------------|
|
||||
| **401** | Authentication failed | "Authentication failed: 401 - Unauthorized" |
|
||||
| **200 (no token)** | Auth passed but no token | "Authentication succeeded but no token received" |
|
||||
| **Connection error** | API недоступен | "Authentication error: Connection refused" |
|
||||
| **409 Conflict** | Service already exists | "Service 'x' already exists" |
|
||||
| **422 Unprocessable Entity** | Invalid data (например, LISTEN_HTTPS_PORT = nil) | "Failed to create service: status=422..." |
|
||||
| **429 Too Many Requests** | Rate limit exceeded | "Rate limit exceeded: 10 per 1 minute" |
|
||||
|
||||
### Решение проблем с rate limiting
|
||||
|
||||
Если получаете ошибку `429` (rate limit), нужно отключить или увеличить лимит в `/etc/bunkerweb/api.env`:
|
||||
|
||||
```bash
|
||||
# Откройте конфиг и найдите секцию Rate limiting
|
||||
nano /etc/bunkerweb/api.env
|
||||
|
||||
# Добавьте/измените:
|
||||
API_RATE_LIMIT_ENABLED=no # Отключение rate limiting
|
||||
# или
|
||||
API_RATE_LIMIT=1000/minute # Увеличение лимита до 1000/m
|
||||
```
|
||||
|
||||
Затем перезагрузите API service:
|
||||
|
||||
```bash
|
||||
systemctl reload bunkerweb-api.service
|
||||
```
|
||||
|
||||
## Особенности реализации
|
||||
|
||||
### 1. SSL сертификатные пути
|
||||
|
||||
Когда `ssl: "no"` - API ожидает `"LISTEN_HTTPS_PORT" => "null"` (строка), а не JSON null (`nil`):
|
||||
|
||||
```ruby
|
||||
# ❌ Ошибка:
|
||||
variables["LISTEN_HTTPS_PORT"] = nil # → 422 error
|
||||
|
||||
# ✅ Правильно:
|
||||
variables["LISTEN_HTTPS_PORT"] = "null" # → 200 OK
|
||||
```
|
||||
|
||||
### 2. Статусы ответа для создания сервиса
|
||||
|
||||
BunkerWeb API возвращает **200 OK** вместо стандартного **201 Created**:
|
||||
|
||||
```ruby
|
||||
# Класс принимает оба статуса как успех:
|
||||
if [201, 200].include?(response[:status])
|
||||
puts "[INFO] Service created successfully"
|
||||
end
|
||||
```
|
||||
|
||||
### 3. Поддержка HTTP методов
|
||||
|
||||
Класс поддерживает все основные HTTP методы для API операций:
|
||||
- **GET** - получение данных (services, instances)
|
||||
- **POST** - создание (services, instances, auth)
|
||||
- **PATCH** - обновление (services)
|
||||
- **DELETE** - удаление (services, instances)
|
||||
|
||||
## Совместимость
|
||||
|
||||
- **Ruby**: 3.0+
|
||||
- **BunkerWeb API**: 1.6.x и выше
|
||||
- **ZooKeeper/Redis**: не требуются для этого класса (работает через HTTP API напрямую)
|
||||
|
||||
## Дополнительные ресурсы
|
||||
|
||||
- [Документация BunkerWeb API](https://docs.bunkerweb.io/api.md)
|
||||
- [API Swagger docs at /docs](http://127.0.0.1:8888/docs)
|
||||
- [OpenAPI schema](http://127.0.0.1:8888/openapi.json)
|
||||
240
func_ruby/ext-modules/bunkerweb_module.mod
Normal file
240
func_ruby/ext-modules/bunkerweb_module.mod
Normal file
@@ -0,0 +1,240 @@
|
||||
#!/opt/brepo/ruby33/bin/ruby
|
||||
|
||||
require 'shellwords'
|
||||
|
||||
class BunkerwebWorker < Kernel::ModuleCoreWorker
|
||||
MODULE_ID = "bunkerweb_module"
|
||||
|
||||
def info
|
||||
{
|
||||
ID: 5,
|
||||
NAME: MODULE_ID,
|
||||
DESCR: "Bunkerweb enabling",
|
||||
REQ: "",
|
||||
CONF: "yes",
|
||||
}
|
||||
end
|
||||
|
||||
def enable
|
||||
log_file = get_log
|
||||
f_inst_pp = get_module_paydata("bunkerweb_installer.yml")
|
||||
if !check
|
||||
inf = info
|
||||
log("Req error, needed #{inf[:REQ]}")
|
||||
"Req error, needed #{inf[:REQ]}"
|
||||
else
|
||||
begin
|
||||
log("install packages for bunkerweb support: /usr/bin/ansible-playbook -vv #{f_inst_pp}")
|
||||
result_action = `LC_ALL=C.UTF-8 /usr/bin/ansible-playbook -vv "#{f_inst_pp}" 2>&1`
|
||||
ex_status = $?.exitstatus
|
||||
if ex_status.to_i == 0 || ex_status.to_i == 2
|
||||
log(result_action)
|
||||
super
|
||||
end
|
||||
rescue => e
|
||||
log("module installation error #{e.message} #{e.backtrace.first}")
|
||||
"module installation error. See log #{log_file}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def command(args)
|
||||
return log_return("Not enough arguments. Needed command") if args.length < 1
|
||||
log_file = get_log
|
||||
|
||||
m_command = args[0].strip
|
||||
case m_command
|
||||
when "add"
|
||||
m_domain = args[1].strip unless args[1].nil?
|
||||
m_ip = args[2].strip unless args[2].nil?
|
||||
if m_domain.nil? || m_ip.nil?
|
||||
log_return("Domain and IP should be specified. #{args}")
|
||||
else
|
||||
|
||||
log("add domain to bunkerweb protection")
|
||||
output = `/usr/local/hestia/bin/v-bunkerweb-module add #{m_domain} #{m_ip} shell`
|
||||
exit_status = $?.exitstatus
|
||||
if exit_status != 0
|
||||
log_return("Command failed with status #{exit_status}")
|
||||
else
|
||||
ACTION_OK
|
||||
end
|
||||
end
|
||||
when "delete"
|
||||
m_domain = args[1].strip unless args[1].nil?
|
||||
if m_domain.nil?
|
||||
log_return("Domain should be specified. #{args}")
|
||||
else
|
||||
|
||||
log("add domain to bunkerweb protection")
|
||||
output = `/usr/local/hestia/bin/v-bunkerweb-module delete #{m_domain} shell`
|
||||
exit_status = $?.exitstatus
|
||||
if exit_status != 0
|
||||
log_return("Command failed with status #{exit_status}")
|
||||
else
|
||||
ACTION_OK
|
||||
end
|
||||
end
|
||||
when "addssl"
|
||||
m_domain = args[1].strip unless args[1].nil?
|
||||
m_ssl_cert = args[2].strip unless args[2].nil?
|
||||
m_ssl_key = args[3].strip unless args[3].nil?
|
||||
if m_domain.nil? || m_ssl_cert.nil? || m_ssl_key.nil? || m_ssl_cert.empty? || m_ssl_key.empty?
|
||||
log_return("Domain, SSL cert and SSL key must be specified. #{args}")
|
||||
else
|
||||
log("add ssl cert to bunkerweb protection")
|
||||
output = `/usr/local/hestia/bin/v-bunkerweb-module addssl #{m_domain} #{m_ssl_cert} #{m_ssl_key} shell`
|
||||
exit_status = $?.exitstatus
|
||||
if exit_status != 0
|
||||
log_return("Command failed with status #{exit_status}")
|
||||
else
|
||||
ACTION_OK
|
||||
end
|
||||
end
|
||||
when "updssl"
|
||||
m_domain = args[1].strip unless args[1].nil?
|
||||
m_ssl_cert = args[2].strip unless args[2].nil?
|
||||
m_ssl_key = args[3].strip unless args[3].nil?
|
||||
if m_domain.nil? || m_ssl_cert.nil? || m_ssl_key.nil? || m_ssl_cert.empty? || m_ssl_key.empty?
|
||||
log_return("Domain, SSL cert and SSL key must be specified. #{args}")
|
||||
else
|
||||
log("update ssl cert to bunkerweb protection")
|
||||
output = `/usr/local/hestia/bin/v-bunkerweb-module updssl #{m_domain} #{m_ssl_cert} #{m_ssl_key} shell`
|
||||
exit_status = $?.exitstatus
|
||||
if exit_status != 0
|
||||
log_return("Command failed with status #{exit_status}")
|
||||
else
|
||||
ACTION_OK
|
||||
end
|
||||
end
|
||||
when "deletessl"
|
||||
m_domain = args[1].strip unless args[1].nil?
|
||||
if m_domain.nil?
|
||||
log_return("Domain should be specified. #{args}")
|
||||
else
|
||||
|
||||
log("delete ssl cert to bunkerweb protection")
|
||||
output = `/usr/local/hestia/bin/v-bunkerweb-module deletessl #{m_domain} shell`
|
||||
exit_status = $?.exitstatus
|
||||
if exit_status != 0
|
||||
log_return("Command failed with status #{exit_status}")
|
||||
else
|
||||
ACTION_OK
|
||||
end
|
||||
end
|
||||
when "list"
|
||||
format = (args[1].nil? ? "shell" : args[1].strip)
|
||||
log("list of services")
|
||||
output = `/usr/local/hestia/bin/v-bunkerweb-module list #{format}`
|
||||
exit_status = $?.exitstatus
|
||||
if exit_status != 0
|
||||
log_return("Command failed with status #{exit_status}")
|
||||
else
|
||||
puts output
|
||||
ACTION_OK
|
||||
end
|
||||
when "passwd"
|
||||
format = (args[1].nil? ? "shell" : args[1].strip)
|
||||
cred = {}
|
||||
api_file = "/etc/bunkerweb/api.env"
|
||||
if File.exist?(api_file)
|
||||
File.readlines(api_file).each do |line|
|
||||
line.strip!
|
||||
next if line.empty? || line.start_with?('#')
|
||||
key, value = line.split('=', 2)
|
||||
if %w[API_USERNAME API_PASSWORD].include?(key)
|
||||
cred[key] = value
|
||||
end
|
||||
end
|
||||
else
|
||||
cred["API_USERNAME"] = nil
|
||||
cred["API_PASSWORD"] = nil
|
||||
end
|
||||
cred["API_USERNAME"] ||= nil
|
||||
cred["API_PASSWORD"] ||= nil
|
||||
|
||||
ui_file = "/etc/bunkerweb/ui.env"
|
||||
if File.exist?(ui_file)
|
||||
File.readlines(ui_file).each do |line|
|
||||
line.strip!
|
||||
next if line.empty? || line.start_with?('#')
|
||||
key, value = line.split('=', 2)
|
||||
if %w[ADMIN_USERNAME ADMIN_PASSWORD].include?(key)
|
||||
cred[key] = value
|
||||
end
|
||||
end
|
||||
else
|
||||
cred["ADMIN_USERNAME"] = nil
|
||||
cred["ADMIN_PASSWORD"] = nil
|
||||
end
|
||||
cred["ADMIN_USERNAME"] ||= nil
|
||||
cred["ADMIN_PASSWORD"] ||= nil
|
||||
|
||||
result = []
|
||||
result << cred
|
||||
hestia_print_array_of_hashes(result, format, "API_USERNAME,API_PASSWORD,ADMIN_USERNAME,ADMIN_PASSWORD")
|
||||
ACTION_OK
|
||||
when "configure"
|
||||
param1 = args[1]
|
||||
param2 = args[2]
|
||||
if param1 && param2 && !param1.strip.empty? && !param2.strip.empty?
|
||||
cmd = "/usr/local/hestia/bin/v-bunkerweb-module-install #{Shellwords.escape(param1)} #{Shellwords.escape(param2)}"
|
||||
else
|
||||
cmd = "/usr/local/hestia/bin/v-bunkerweb-module-install"
|
||||
end
|
||||
output = `#{cmd} 2>&1`
|
||||
exit_status = $?.exitstatus
|
||||
if exit_status != 0
|
||||
log_return("#{output}\nCommand failed with status #{exit_status}")
|
||||
else
|
||||
puts output
|
||||
ACTION_OK
|
||||
end
|
||||
when "alias"
|
||||
m_domain = args[1].strip unless args[1].nil?
|
||||
m_alias = args[2].strip unless args[2].nil?
|
||||
if m_domain.nil?
|
||||
log_return("Domain should be specified. #{args}")
|
||||
else
|
||||
|
||||
log("add alias #{m_alias} to domain #{m_domain} to bunkerweb protection")
|
||||
output = `/usr/local/hestia/bin/v-bunkerweb-module alias #{m_domain} "#{m_alias}" shell`
|
||||
exit_status = $?.exitstatus
|
||||
if exit_status != 0
|
||||
log_return("Command failed with status #{exit_status}")
|
||||
else
|
||||
ACTION_OK
|
||||
end
|
||||
end
|
||||
when "help"
|
||||
puts "#{$0} bunkerweb_module COMMAND [OPTIONS] [json|csv|plain]"
|
||||
puts "COMMANDS:"
|
||||
puts " add domain - add domain to bunkerweb"
|
||||
puts " delete domain - delete domain from bunkerweb"
|
||||
puts " addssl domain [path_to_cert] [path_to_key] - add existsing certificate to bunkerweb domain"
|
||||
puts " updssl domain [path_to_cert] [path_to_key] - update existsing certificate to bunkerweb domain"
|
||||
puts " passwd - get ui and api passwd"
|
||||
puts " configure [path_to_cert] [path_to_key] - start initial setup of bunkerweb should do only once"
|
||||
puts " help - help"
|
||||
ACTION_OK
|
||||
else
|
||||
log_return("Unknown command. #{args}")
|
||||
end
|
||||
end
|
||||
|
||||
implements IPluginInterface
|
||||
end
|
||||
|
||||
module BunkerwebModule
|
||||
def get_object
|
||||
Proc.new { BunkerwebWorker.new }
|
||||
end
|
||||
|
||||
module_function :get_object
|
||||
end
|
||||
|
||||
class Kernel::PluginConfiguration
|
||||
include BunkerwebModule
|
||||
|
||||
@@loaded_plugins[BunkerwebWorker::MODULE_ID] = BunkerwebModule.get_object
|
||||
end
|
||||
1
func_ruby/ext-modules/last_free_id
Normal file
1
func_ruby/ext-modules/last_free_id
Normal file
@@ -0,0 +1 @@
|
||||
7
|
||||
@@ -20,15 +20,15 @@ class PassengerWorker < Kernel::ModuleCoreWorker
|
||||
ID: 2,
|
||||
NAME: MODULE_ID,
|
||||
DESCR: "Added passenger support for nginx",
|
||||
REQ: "puppet_installer",
|
||||
REQ: "",
|
||||
CONF: "yes",
|
||||
}
|
||||
end
|
||||
|
||||
def enable
|
||||
log_file = get_log
|
||||
f_inst_pp = get_module_paydata("passenger_installer.pp")
|
||||
f_uninst_pp = get_module_paydata("passenger_uninstaller.pp")
|
||||
f_inst_pp = get_module_paydata("passenger_installer.yml")
|
||||
f_uninst_pp = get_module_paydata("passenger_uninstaller.yml")
|
||||
if !check
|
||||
inf = info
|
||||
log("Req error, needed #{inf[:REQ]}")
|
||||
@@ -36,16 +36,16 @@ class PassengerWorker < Kernel::ModuleCoreWorker
|
||||
else
|
||||
begin
|
||||
prepare_default_ruby_conf
|
||||
log("install packages for passenger + nginx support: /usr/bin/puppet apply --detailed-exitcodes #{f_inst_pp}")
|
||||
result_action = `/usr/bin/puppet apply --detailed-exitcodes "#{f_inst_pp}" 2>&1`
|
||||
log("install packages for passenger + nginx support: /usr/bin/ansible-playbook -vv #{f_inst_pp}")
|
||||
result_action = `LC_ALL=C.UTF-8 /usr/bin/ansible-playbook -vv "#{f_inst_pp}" 2>&1`
|
||||
ex_status = $?.exitstatus
|
||||
if ex_status.to_i == 0 || ex_status.to_i == 2
|
||||
log(result_action)
|
||||
super
|
||||
else
|
||||
log(result_action)
|
||||
log("Try to disable action: /usr/bin/puppet apply --detailed-exitcodes #{f_uninst_pp}")
|
||||
result_action = `/usr/bin/puppet apply --detailed-exitcodes "#{f_uninst_pp}" 2>&1`
|
||||
log("Try to disable action: /usr/bin/ansible-playbook -vv #{f_uninst_pp}")
|
||||
result_action = `LC_ALL=C.UTF-8 /usr/bin/ansible-playbook -vv "#{f_uninst_pp}" 2>&1`
|
||||
"module installation error. See log #{log_file}"
|
||||
end
|
||||
rescue => e
|
||||
@@ -57,14 +57,14 @@ class PassengerWorker < Kernel::ModuleCoreWorker
|
||||
|
||||
def disable
|
||||
log_file = get_log
|
||||
f_uninst_pp = get_module_paydata("passenger_uninstaller.pp")
|
||||
f_uninst_pp = get_module_paydata("passenger_uninstaller.yml")
|
||||
if !check_domains_with_passenger
|
||||
return log_return("Presents domains with passenger support disable it first")
|
||||
end
|
||||
begin
|
||||
log("uninstall packages for passenger + nginx support")
|
||||
log("Try to disable action: /usr/bin/puppet apply --detailed-exitcodes #{f_uninst_pp}")
|
||||
result_action = `/usr/bin/puppet apply --detailed-exitcodes "#{f_uninst_pp}" 2>&1`
|
||||
log("Try to disable action: /usr/bin/ansible-playbook -vv #{f_uninst_pp}")
|
||||
result_action = `LC_ALL=C.UTF-8 /usr/bin/ansible-playbook -vv "#{f_uninst_pp}" 2>&1`
|
||||
ex_status = $?.exitstatus
|
||||
if ex_status.to_i == 0 || ex_status.to_i == 2
|
||||
log(result_action)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
- name: Install Bunkerweb on localhost
|
||||
hosts: localhost
|
||||
connection: local
|
||||
become: true
|
||||
gather_facts: false
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
LC_ALL: en_US.UTF-8
|
||||
tasks:
|
||||
- name: Install bunkerweb
|
||||
ansible.builtin.dnf:
|
||||
name: bunkerweb
|
||||
state: present
|
||||
@@ -0,0 +1,69 @@
|
||||
---
|
||||
- name: Install Passenger and configure Nginx on localhost
|
||||
hosts: localhost
|
||||
connection: local
|
||||
become: true
|
||||
gather_facts: false
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
LC_ALL: en_US.UTF-8
|
||||
tasks:
|
||||
# Устанавливаем Ruby и зависимости
|
||||
- name: Install rubygems-devel
|
||||
ansible.builtin.dnf:
|
||||
name: rubygems-devel
|
||||
state: present
|
||||
- name: Install rubygem-rake
|
||||
ansible.builtin.dnf:
|
||||
name: rubygem-rake
|
||||
state: present
|
||||
- name: Install ruby-devel
|
||||
ansible.builtin.dnf:
|
||||
name: ruby-devel
|
||||
state: present
|
||||
- name: Install rubygem-rack
|
||||
ansible.builtin.dnf:
|
||||
name: rubygem-rack
|
||||
state: present
|
||||
- name: Install alt-brepo-ruby33-devel
|
||||
ansible.builtin.dnf:
|
||||
name: alt-brepo-ruby33-devel
|
||||
state: present
|
||||
- name: Install alt-brepo-ruby33-rubygem-rake
|
||||
ansible.builtin.dnf:
|
||||
name: alt-brepo-ruby33-rubygem-rake
|
||||
state: present
|
||||
# Устанавливаем Passenger и модуль Nginx
|
||||
- name: Install passenger-devel
|
||||
ansible.builtin.dnf:
|
||||
name: passenger-devel
|
||||
state: present
|
||||
- name: Install passenger
|
||||
ansible.builtin.dnf:
|
||||
name: passenger
|
||||
state: present
|
||||
- name: Install nginx-mod-http-passenger
|
||||
ansible.builtin.dnf:
|
||||
name: nginx-mod-http-passenger
|
||||
state: present
|
||||
# Конфигурируем Nginx для Passenger
|
||||
- name: Create passenger.conf
|
||||
ansible.builtin.copy:
|
||||
dest: /usr/local/hestia/nginx-system/etc/nginx/conf.d/passenger.conf
|
||||
content: |
|
||||
passenger_root /usr/share/ruby/vendor_ruby/phusion_passenger/locations.ini;
|
||||
passenger_ruby /usr/bin/ruby;
|
||||
passenger_instance_registry_dir /var/run/passenger-instreg;
|
||||
passenger_user_switching on;
|
||||
passenger_env_var PASSENGER_COMPILE_NATIVE_SUPPORT_BINARY 0;
|
||||
passenger_env_var PASSENGER_DOWNLOAD_NATIVE_SUPPORT_BINARY 0;
|
||||
- name: Create passenger_includer.conf
|
||||
ansible.builtin.copy:
|
||||
dest: /usr/local/hestia/nginx-system/etc/nginx/conf.d/main/passenger.conf
|
||||
content: |
|
||||
load_module modules/ngx_http_passenger_module.so;
|
||||
# Перезапускаем Nginx
|
||||
- name: Restart nginx service
|
||||
ansible.builtin.service:
|
||||
name: nginx-system
|
||||
state: restarted
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
- name: Uninstall Passenger and configure Nginx on localhost
|
||||
hosts: localhost
|
||||
connection: local
|
||||
become: true
|
||||
gather_facts: false
|
||||
environment:
|
||||
LANG: en_US.UTF-8
|
||||
LC_ALL: en_US.UTF-8
|
||||
tasks:
|
||||
# Удалаем модуль nginx-passenger
|
||||
- name: Remove nginx-mod-http-passenger package
|
||||
ansible.builtin.dnf:
|
||||
name: nginx-mod-http-passenger
|
||||
state: absent
|
||||
# Удалаем passenger и зависимости
|
||||
- name: Remove passenger-devel package
|
||||
ansible.builtin.dnf:
|
||||
name: passenger-devel
|
||||
state: absent
|
||||
- name: Remove passenger package
|
||||
ansible.builtin.dnf:
|
||||
name: passenger
|
||||
state: absent
|
||||
# Удаляем конфигурационные файлы Nginx
|
||||
- name: Remove passenger.conf
|
||||
ansible.builtin.file:
|
||||
path: /usr/local/hestia/nginx-system/etc/nginx/conf.d/passenger.conf
|
||||
state: absent
|
||||
- name: Remove passenger_includer.conf
|
||||
ansible.builtin.file:
|
||||
path: /usr/local/hestia/nginx-system/etc/nginx/conf.d/main/passenger.conf
|
||||
state: absent
|
||||
# Перезапускаем Nginx (необязательно, но полезно)
|
||||
- name: Restart nginx service
|
||||
ansible.builtin.service:
|
||||
name: nginx-system
|
||||
state: restarted
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/opt/brepo/ruby33/bin/ruby
|
||||
|
||||
class EmptyWorker < Kernel::ModuleCoreWorker
|
||||
class PHPWorker < Kernel::ModuleCoreWorker
|
||||
MODULE_ID = "php_brepo_modules"
|
||||
|
||||
def info
|
||||
@@ -241,16 +241,16 @@ class EmptyWorker < Kernel::ModuleCoreWorker
|
||||
implements IPluginInterface
|
||||
end
|
||||
|
||||
module EmptyModule
|
||||
module PHPModule
|
||||
def get_object
|
||||
Proc.new { EmptyWorker.new }
|
||||
Proc.new { PHPWorker.new }
|
||||
end
|
||||
|
||||
module_function :get_object
|
||||
end
|
||||
|
||||
class Kernel::PluginConfiguration
|
||||
include EmptyModule
|
||||
include PHPModule
|
||||
|
||||
@@loaded_plugins[EmptyWorker::MODULE_ID] = EmptyModule.get_object
|
||||
@@loaded_plugins[PHPWorker::MODULE_ID] = PHPModule.get_object
|
||||
end
|
||||
|
||||
122
func_ruby/ext-modules/update_module.mod
Normal file
122
func_ruby/ext-modules/update_module.mod
Normal file
@@ -0,0 +1,122 @@
|
||||
#!/opt/brepo/ruby33/bin/ruby
|
||||
|
||||
require 'pathname'
|
||||
require 'fileutils'
|
||||
require 'digest'
|
||||
|
||||
class UpdateWorker < Kernel::ModuleCoreWorker
|
||||
MODULE_ID = "update_module"
|
||||
|
||||
def info
|
||||
{
|
||||
ID: 6,
|
||||
NAME: MODULE_ID,
|
||||
DESCR: "Module for updating HestiaCP data and templates",
|
||||
REQ: "",
|
||||
CONF: "yes",
|
||||
}
|
||||
end
|
||||
|
||||
def file_changed?(new_file, old_file)
|
||||
return true unless File.exist?(old_file)
|
||||
new_hash = Digest::SHA256.file(new_file).hexdigest
|
||||
old_hash = Digest::SHA256.file(old_file).hexdigest
|
||||
new_hash != old_hash
|
||||
end
|
||||
|
||||
def get_templates_map()
|
||||
{ :templates=>
|
||||
[
|
||||
{:new=>"/usr/local/hestia/install/rpm/templates/web/awstats", :old=>"/usr/local/hestia/data/templates/web/awstats"},
|
||||
{:new=>"/usr/local/hestia/install/rpm/templates/web/httpd", :old=>"/usr/local/hestia/data/templates/web/httpd"},
|
||||
{:new=>"/usr/local/hestia/install/rpm/templates/web/nginx", :old=>"/usr/local/hestia/data/templates/web/nginx"},
|
||||
{:new=>"/usr/local/hestia/install/rpm/templates/web/php-fpm", :old=>"/usr/local/hestia/data/templates/web/php-fpm"}
|
||||
]
|
||||
}
|
||||
end
|
||||
|
||||
# New helper method to get list of changed template files
|
||||
def get_changed_template_files
|
||||
templates_map = get_templates_map()[:templates]
|
||||
result = []
|
||||
templates_map.each do |tpl|
|
||||
new_dir = tpl[:new]
|
||||
old_dir = tpl[:old]
|
||||
Dir.glob(File.join(new_dir, '**', '*')).each do |new_file|
|
||||
next if File.directory?(new_file)
|
||||
rel_path = Pathname.new(new_file).relative_path_from(Pathname.new(new_dir)).to_s
|
||||
old_file = File.join(old_dir, rel_path)
|
||||
result << [new_dir, new_file, old_file] if file_changed?(new_file, old_file)
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def command(args)
|
||||
return log_return("Not enough arguments. Needed command") if args.length < 1
|
||||
log_file = get_log
|
||||
|
||||
m_command = args[0].strip
|
||||
case m_command
|
||||
when "synctemplates"
|
||||
result = get_changed_template_files
|
||||
result.each do |new_dir, new_file, old_file|
|
||||
if !File.exist?(old_file)
|
||||
FileUtils.cp(new_file, old_file)
|
||||
else
|
||||
stat = File.stat(old_file)
|
||||
uid = stat.uid
|
||||
gid = stat.gid
|
||||
mode = stat.mode & 0o7777
|
||||
FileUtils.cp(new_file, old_file)
|
||||
File.chown(uid, gid, old_file)
|
||||
File.chmod(mode, old_file)
|
||||
end
|
||||
end
|
||||
ACTION_OK
|
||||
when "listsynctemplates"
|
||||
format = (args[1].nil? ? "shell" : args[1].strip)
|
||||
list = get_changed_template_files
|
||||
result = []
|
||||
result = list.map do |new_dir, new_file, old_file|
|
||||
file_name = Pathname.new(new_file).relative_path_from(Pathname.new(new_dir)).to_s
|
||||
dir_name = File.basename(new_dir)
|
||||
relative_path = Pathname.new(new_file).relative_path_from(Pathname.new(new_dir)).to_s
|
||||
file_name = File.join(dir_name, relative_path)
|
||||
{
|
||||
"FILE_NAME" => file_name,
|
||||
"NEW_SIZE" => File.size(new_file),
|
||||
"OLD_SIZE" => File.exist?(old_file) ? File.size(old_file) : "-"
|
||||
}
|
||||
end
|
||||
|
||||
hestia_print_array_of_hashes(result, format, "FILE_NAME,NEW_SIZE,OLD_SIZE")
|
||||
ACTION_OK
|
||||
when "help"
|
||||
puts "#{$0} update_module COMMAND [json|csv|plain]"
|
||||
puts "COMMANDS:"
|
||||
puts " synctemplates - sync web templates"
|
||||
puts " listsynctemplates - show changed web templates"
|
||||
puts " help - help"
|
||||
ACTION_OK
|
||||
else
|
||||
log_return("Unknown command. #{args}")
|
||||
end
|
||||
end
|
||||
|
||||
implements IPluginInterface
|
||||
end
|
||||
|
||||
module UpdateModule
|
||||
def get_object
|
||||
Proc.new { UpdateWorker.new }
|
||||
end
|
||||
|
||||
module_function :get_object
|
||||
end
|
||||
|
||||
class Kernel::PluginConfiguration
|
||||
include UpdateModule
|
||||
|
||||
@@loaded_plugins[UpdateWorker::MODULE_ID] = UpdateModule.get_object
|
||||
end
|
||||
@@ -77,6 +77,10 @@ class File
|
||||
end
|
||||
end
|
||||
|
||||
def hestia_print_info_message_to_cli(error_message)
|
||||
puts "Info: #{error_message}"
|
||||
end
|
||||
|
||||
def hestia_print_error_message_to_cli(error_message)
|
||||
puts "Error: #{error_message}"
|
||||
end
|
||||
@@ -315,3 +319,80 @@ 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)
|
||||
# First pass: read entire file to check if key exists and get all lines
|
||||
content = nil
|
||||
|
||||
File.open(config_file, "r") do |f|
|
||||
content = f.read
|
||||
end
|
||||
|
||||
if content
|
||||
lines = content.split("\n")
|
||||
|
||||
# Check if key exists in the configuration file
|
||||
existing_line_index = -1
|
||||
|
||||
lines.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.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"
|
||||
|
||||
# Second pass: rebuild the content with updated value
|
||||
new_lines = []
|
||||
|
||||
lines.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)}='[^']*'/)
|
||||
new_lines << "#{key}='#{value}'"
|
||||
else
|
||||
new_lines << line
|
||||
end
|
||||
end
|
||||
|
||||
File.open(temp_file, "w") do |output_f|
|
||||
new_lines.each { |l| output_f.puts(l) }
|
||||
end
|
||||
|
||||
# Atomic file replacement
|
||||
File.rename(temp_file, config_file)
|
||||
OK
|
||||
end
|
||||
else
|
||||
OK
|
||||
end
|
||||
else
|
||||
check_result error_code: E_NOTEXIST, error_message: "Configuration file #{config_file} does not exist"
|
||||
end
|
||||
end
|
||||
|
||||
0
hestiacp/install/hst-install.sh
Normal file
0
hestiacp/install/hst-install.sh
Normal file
@@ -13,7 +13,7 @@ location /%pma_alias% {
|
||||
|
||||
location ~ ^/%pma_alias%/(.*\.php)$ {
|
||||
alias /usr/share/phpmyadmin/$1;
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
|
||||
@@ -3,7 +3,7 @@ location /%pga_alias% {
|
||||
|
||||
location ~ ^/%pga_alias%/(.*\.php)$ {
|
||||
alias /usr/share/phppgadmin/$1;
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
|
||||
@@ -39,7 +39,7 @@ server {
|
||||
}
|
||||
|
||||
location ~ ^/(.*\.php)$ {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -32,7 +32,7 @@ server {
|
||||
}
|
||||
|
||||
location ~ ^/(.*\.php)$ {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
|
||||
@@ -34,7 +34,7 @@ server {
|
||||
}
|
||||
|
||||
location ~ ^/(.*\.php)$ {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -27,7 +27,7 @@ server {
|
||||
}
|
||||
|
||||
location ~ ^/(.*\.php)$ {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $request_filename;
|
||||
|
||||
@@ -70,7 +70,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -61,7 +61,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -40,7 +40,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_paramsystem/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -31,7 +31,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -56,7 +56,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_paramsystem/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -47,7 +47,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -61,7 +61,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_paramsystem/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -51,7 +51,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -111,7 +111,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_paramsystem/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -102,7 +102,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -38,7 +38,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_paramsystem/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -29,7 +29,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -42,7 +42,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_paramsystem/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -33,7 +33,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -68,7 +68,7 @@ server {
|
||||
location ~ [^/]\.php(/|$)|^/update.php {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -60,7 +60,7 @@ server {
|
||||
location ~ [^/]\.php(/|$)|^/update.php {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -68,7 +68,7 @@ server {
|
||||
location ~ [^/]\.php(/|$)|^/update.php {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -59,7 +59,7 @@ server {
|
||||
location ~ [^/]\.php(/|$)|^/update.php {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -78,7 +78,7 @@ server {
|
||||
location ~ [^/]\.php(/|$)|^/update.php {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -69,7 +69,7 @@ server {
|
||||
location ~ [^/]\.php(/|$)|^/update.php {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -32,7 +32,7 @@ server {
|
||||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -23,7 +23,7 @@ server {
|
||||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -40,7 +40,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -31,7 +31,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -57,7 +57,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -47,7 +47,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -51,7 +51,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -42,7 +42,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -32,7 +32,7 @@ server {
|
||||
root %sdocroot%;
|
||||
|
||||
location ~ ^/setup/index.php {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
@@ -57,7 +57,7 @@ server {
|
||||
root %sdocroot%;
|
||||
|
||||
location ~ ^/update/index.php {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
@@ -171,7 +171,7 @@ server {
|
||||
location ~ (index|get|static|report|404|503)\.php$ {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_buffers 1024 4k;
|
||||
fastcgi_connect_timeout 600s;
|
||||
|
||||
@@ -28,7 +28,7 @@ server {
|
||||
|
||||
fastcgi_pass %backend_lsnr%;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
include %home%/%user%/conf/web/%domain%/nginx.fastcgi_cache.conf*;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ server {
|
||||
root %docroot%;
|
||||
|
||||
location ~ ^/update/index.php {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
@@ -159,7 +159,7 @@ server {
|
||||
location ~ (index|get|static|report|404|503)\.php$ {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_buffers 1024 4k;
|
||||
fastcgi_connect_timeout 600s;
|
||||
|
||||
@@ -68,7 +68,7 @@ server {
|
||||
}
|
||||
|
||||
location ~ [^/]\.php(/|$) {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -60,7 +60,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_paramsystem/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -51,7 +51,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -66,7 +66,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $fastcgi_script_name =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_intercept_errors on;
|
||||
|
||||
@@ -57,7 +57,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $fastcgi_script_name =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_intercept_errors on;
|
||||
|
||||
@@ -40,7 +40,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -31,7 +31,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -76,7 +76,7 @@ server {
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -67,7 +67,7 @@ server {
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param PATH_INFO $path_info;
|
||||
|
||||
@@ -63,7 +63,7 @@ server {
|
||||
try_files $uri $uri/ /index.php;
|
||||
|
||||
location ~ \.php(?:$|/) {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
#fastcgi_param HTTPS on;
|
||||
|
||||
@@ -54,7 +54,7 @@ server {
|
||||
try_files $uri $uri/ /index.php;
|
||||
|
||||
location ~ \.php(?:$|/) {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
#fastcgi_param HTTPS on;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
|
||||
@@ -50,7 +50,7 @@ server {
|
||||
|
||||
# Pass the php scripts to FastCGI server specified in upstream declaration.
|
||||
location ~ \.php(/|$) {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
||||
@@ -81,7 +81,7 @@ server {
|
||||
|
||||
# Pass the php scripts to fastcgi server specified in upstream declaration.
|
||||
location ~ \.php(/|$) {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
||||
|
||||
@@ -41,7 +41,7 @@ server {
|
||||
|
||||
# Pass the php scripts to FastCGI server specified in upstream declaration.
|
||||
location ~ \.php(/|$) {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_paramsystem/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
||||
@@ -71,7 +71,7 @@ server {
|
||||
|
||||
# Pass the php scripts to fastcgi server specified in upstream declaration.
|
||||
location ~ \.php(/|$) {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_paramsystem/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
||||
|
||||
@@ -50,7 +50,7 @@ server {
|
||||
location ~* ^/(?:index|piwik)\.php$ {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -41,7 +41,7 @@ server {
|
||||
location ~* ^/(?:index|piwik)\.php$ {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_paramsystem/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $fastcgi_script_name /index.php$uri&$args =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -111,7 +111,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $fastcgi_script_name /index.php$uri&$args =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_paramsystem/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -63,7 +63,7 @@ server {
|
||||
location ~ \.php$ {
|
||||
try_files $fastcgi_script_name =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_intercept_errors on;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -53,7 +53,7 @@ server {
|
||||
location ~ \.php$ {
|
||||
try_files $fastcgi_script_name =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_intercept_errors on;
|
||||
fastcgi_param front_controller_active true;
|
||||
|
||||
@@ -44,7 +44,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -35,7 +35,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_paramsystem/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -55,7 +55,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param HTTP_EARLY_DATA $rfc_early_data if_not_empty;
|
||||
|
||||
@@ -46,7 +46,7 @@ server {
|
||||
location ~ [^/]\.php(/|$) {
|
||||
try_files $uri =404;
|
||||
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
|
||||
@@ -49,7 +49,7 @@ server {
|
||||
# This rule should only be placed on your development environment
|
||||
# In production, don't include this and don't deploy app_dev.php or config.php
|
||||
location ~ ^/(app_dev|config)\.php(/|$) {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
# When you are using symlinks to link the document root to the
|
||||
# current version of your application, you should pass the real
|
||||
@@ -70,7 +70,7 @@ server {
|
||||
|
||||
# PROD
|
||||
location ~ ^/app\.php(/|$) {
|
||||
include /etc/nginx/fastcgi_params;
|
||||
include /usr/local/hestia/nginx-system/etc/nginx/fastcgi_params;
|
||||
|
||||
# When you are using symlinks to link the document root to the
|
||||
# current version of your application, you should pass the real
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user