smazani
This commit is contained in:
@@ -1,605 +0,0 @@
|
||||
# Executes a command inside the OLS deployment container.
|
||||
# $@ (...): command and arguments to execute.
|
||||
function openlitespeedExec() {
|
||||
k3sRun exec deploy/"$olsKube" -c "$olsKube" -- "$@"
|
||||
}
|
||||
|
||||
# Executes a command inside a specific OLS pod.
|
||||
# $1 (pod): pod name.
|
||||
# $2+ (...): command and arguments to execute.
|
||||
function openlitespeedPodExec() {
|
||||
local pod="$1"
|
||||
[[ -n "$pod" ]] || { appError "Pod not specified"; return 1; }
|
||||
shift || true
|
||||
|
||||
k3sRun exec pod/"$pod" -c "$olsKube" -- "$@"
|
||||
}
|
||||
|
||||
# Edits an OpenLiteSpeed configuration file via the OLS config editor script.
|
||||
# $1 (file): config file path.
|
||||
# $2 (mode): edit mode passed to ols-editor.pl.
|
||||
# $3+ (...): additional editor arguments.
|
||||
function openlitespeedConfigEditFile() {
|
||||
local file="$1"
|
||||
local mode="$2"
|
||||
shift 2 || return 1
|
||||
|
||||
[[ -n "$file" ]] || { appError "Config file not specified"; return 1; }
|
||||
[[ -n "$mode" ]] || { appError "Edit mode not specified"; return 1; }
|
||||
|
||||
perl "$appPath/libs/modules/assets/ols-editor.pl" "$file" "$mode" "$@" || {
|
||||
appError "Failed edit config file: $file | mode=$mode"
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
# Edits the main OLS config file.
|
||||
# $@ (...): edit mode and arguments.
|
||||
function openlitespeedConfigEdit() {
|
||||
openlitespeedConfigEditFile "$olsConfigFile" "$@"
|
||||
}
|
||||
|
||||
# Adds a value to the main OLS config.
|
||||
function openlitespeedConfigKeyAdd() {
|
||||
openlitespeedConfigEdit key_add "$@"
|
||||
}
|
||||
|
||||
# Sets a value in the main OLS config.
|
||||
function openlitespeedConfigKeySet() {
|
||||
openlitespeedConfigEdit key_set "$@"
|
||||
}
|
||||
|
||||
# Sets a masked value in the main OLS config.
|
||||
function openlitespeedConfigKeyMaskSet() {
|
||||
openlitespeedConfigEdit key_mask_set "$@"
|
||||
}
|
||||
|
||||
# Deletes a value from the main OLS config.
|
||||
function openlitespeedConfigKeyDel() {
|
||||
openlitespeedConfigEdit key_del "$@"
|
||||
}
|
||||
|
||||
# Deletes masked values from the main OLS config.
|
||||
function openlitespeedConfigKeyMaskDel() {
|
||||
openlitespeedConfigEdit key_mask_del "$@"
|
||||
}
|
||||
|
||||
# Adds a generic section to the main OLS config.
|
||||
# $1 (header): section header text, e.g. "listener HTTP".
|
||||
function openlitespeedConfigBlockAdd() {
|
||||
openlitespeedConfigEdit block_add "$@"
|
||||
}
|
||||
|
||||
# Deletes a generic section from the main OLS config.
|
||||
# $1 (header_re): regex pattern matching the section header.
|
||||
function openlitespeedConfigBlockDel() {
|
||||
openlitespeedConfigEdit block_del "$@"
|
||||
}
|
||||
|
||||
# Lists OLS virtual hosts filtered by state.
|
||||
# [$1] (type): filter type: all, up, or down (defaults to all).
|
||||
function openlitespeedConfigVhostList() {
|
||||
local type="${1:-all}"
|
||||
arrayContains "$type" "all" "up" "down" || { appError "Unknown type: $type"; return 1; }
|
||||
|
||||
case "$olsVhostMode" in
|
||||
standalone) openlitespeedConfigEdit vhost_list "$type" || return 1 ;;
|
||||
template) openlitespeedConfigEdit member_list "$olsVhostTemplate" "$type" || return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
function openlitespeedConfigVhostSet() {
|
||||
local domain="$1"
|
||||
[[ -n "$domain" ]] || { appError "Domain not specified"; return 1; }
|
||||
shift
|
||||
|
||||
case "$olsVhostMode" in
|
||||
# standalone) openlitespeedConfigEdit vhost_set "$olsPodVhostsPath/$domain" "$domain" "$@" || return 1 ;;
|
||||
standalone) openlitespeedConfigEdit vhost_set "$olsPodVhostsPath/\$VH_NAME" "$domain" "$@" || return 1 ;;
|
||||
template) openlitespeedConfigEdit member_set "$olsVhostTemplate" "$domain" "$@" || return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Deletes a virtual host entry from the main OLS config.
|
||||
function openlitespeedConfigVhostDel() {
|
||||
local domain="$1"
|
||||
[[ -n "$domain" ]] || { appError "Domain not specified"; return 1; }
|
||||
|
||||
case "$olsVhostMode" in
|
||||
standalone) openlitespeedConfigEdit vhost_del "$domain" || return 1 ;;
|
||||
template) openlitespeedConfigEdit member_del "$olsVhostTemplate" "$domain" || return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Lists aliases assigned to a virtual host.
|
||||
# $1 (domain): site domain name.
|
||||
function openlitespeedConfigVhostAliasList() {
|
||||
local domain="$1"
|
||||
[[ -n "$domain" ]] || { appError "Domain not specified"; return 1; }
|
||||
|
||||
case "$olsVhostMode" in
|
||||
standalone) openlitespeedConfigEdit vhost_alias "$domain" || return 1 ;;
|
||||
template) openlitespeedConfigEdit member_alias "$olsVhostTemplate" "$domain" || return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Lists configured OLS aliases.
|
||||
function openlitespeedConfigAliasList() {
|
||||
case "$olsVhostMode" in
|
||||
standalone) openlitespeedConfigEdit vhost_alias all || return 1 ;;
|
||||
template) openlitespeedConfigEdit member_alias "$olsVhostTemplate" all || return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Marks a virtual host as active.
|
||||
# $1 (domain): site domain name.
|
||||
function openlitespeedConfigVhostUp() {
|
||||
local domain="$1"
|
||||
[[ -n "$domain" ]] || { appError "Domain not specified"; return 1; }
|
||||
openlitespeedConfigEdit suspended_del "$domain" || return 1
|
||||
}
|
||||
|
||||
# Marks a virtual host as suspended.
|
||||
# $1 (domain): site domain name.
|
||||
function openlitespeedConfigVhostDown() {
|
||||
local domain="$1"
|
||||
[[ -n "$domain" ]] || { appError "Domain not specified"; return 1; }
|
||||
openlitespeedConfigEdit suspended_add "$domain" || return 1
|
||||
}
|
||||
|
||||
function openlitespeedConfigRebuild() {
|
||||
local children php block
|
||||
children=$(configGet "$appAssetsPath/openlitespeed/profiles/memory-$kubeMemoryProfile.config" "children")
|
||||
|
||||
fileBackup "$olsConfigFile"
|
||||
|
||||
openlitespeedConfigBlockDel "wsgiDefaults"
|
||||
openlitespeedConfigBlockDel "nodeDefaults"
|
||||
openlitespeedConfigBlockDel "railsDefaults"
|
||||
openlitespeedConfigBlockDel "vh[Tt]emplate\h+centralConfigLog"
|
||||
openlitespeedConfigBlockDel "vh[Tt]emplate\h+EasyRailsWithSuEXEC"
|
||||
openlitespeedConfigBlockDel "vh[Tt]emplate\h+docker"
|
||||
openlitespeedConfigBlockDel "listener\h+Default"
|
||||
openlitespeedConfigBlockDel "virtual[Hh]ost\h+Example"
|
||||
openlitespeedConfigKeySet '' 'useIpInProxyHeader' '2'
|
||||
openlitespeedConfigKeySet 'fileAccessControl' 'checkSymbolLink' '1'
|
||||
openlitespeedConfigKeySet 'accessControl' 'deny' ''
|
||||
openlitespeedConfigKeySet 'accessControl' 'allow' '10.42.0.0/16T, 10.43.0.0/16T'
|
||||
|
||||
local phpList=("" "${olsPhpList[@]}")
|
||||
for php in "${phpList[@]}"; do
|
||||
block="extProcessor lsphp$php"
|
||||
openlitespeedConfigBlockDel "ext[Pp]rocessor lsphp$php"
|
||||
openlitespeedConfigBlockAdd "$block"
|
||||
openlitespeedConfigKeyAdd "$block" 'type' 'lsapi'
|
||||
openlitespeedConfigKeyAdd "$block" 'address' "uds://tmp/lshttpd/lsphp$php.sock"
|
||||
openlitespeedConfigKeyAdd "$block" 'path' "/usr/local/lsws/lsphp$php/bin/lsphp"
|
||||
openlitespeedConfigKeyAdd "$block" 'maxConns' "$children"
|
||||
openlitespeedConfigKeyAdd "$block" 'env' "PHP_LSAPI_CHILDREN=$children"
|
||||
openlitespeedConfigKeyAdd "$block" 'env' 'PHP_INI_SCAN_DIR=:/etc/ols-php-ini:/var/www/private/$VH_NAME/php'
|
||||
openlitespeedConfigKeyAdd "$block" 'env' 'LSAPI_AVOID_FORK=0'
|
||||
openlitespeedConfigKeyAdd "$block" 'env' 'LSAPI_MAX_IDLE=120'
|
||||
openlitespeedConfigKeyAdd "$block" 'env' 'LSAPI_MAX_IDLE_CHILDREN=1'
|
||||
openlitespeedConfigKeyAdd "$block" 'env' 'LSAPI_PGRP_MAX_IDLE=300'
|
||||
openlitespeedConfigKeyAdd "$block" 'env' 'LSAPI_MAX_PROCESS_TIME=300'
|
||||
openlitespeedConfigKeyAdd "$block" 'env' 'LSAPI_SLOW_REQ_MSECS=5000'
|
||||
openlitespeedConfigKeyAdd "$block" 'initTimeout' '60'
|
||||
openlitespeedConfigKeyAdd "$block" 'retryTimeout' '0'
|
||||
openlitespeedConfigKeyAdd "$block" 'persistConn' '1'
|
||||
openlitespeedConfigKeyAdd "$block" 'respBuffer' '0'
|
||||
openlitespeedConfigKeyAdd "$block" 'autoStart' '2'
|
||||
openlitespeedConfigKeyAdd "$block" 'backlog' '100'
|
||||
openlitespeedConfigKeyAdd "$block" 'instances' '1'
|
||||
openlitespeedConfigKeyAdd "$block" 'priority' '0'
|
||||
openlitespeedConfigKeyAdd "$block" 'memSoftLimit' '0'
|
||||
openlitespeedConfigKeyAdd "$block" 'memHardLimit' '0'
|
||||
openlitespeedConfigKeyAdd "$block" 'procSoftLimit' '700'
|
||||
openlitespeedConfigKeyAdd "$block" 'procHardLimit' '800'
|
||||
|
||||
openlitespeedConfigKeyAdd "script[Hh]andler" add "lsapi:lsphp$php lsphp$php"
|
||||
done
|
||||
openlitespeedConfigKeySet "extProcessor\h+lsphp" 'path' 'fcgi-bin/lsphp'
|
||||
|
||||
# module cache
|
||||
block="module cache"
|
||||
openlitespeedConfigBlockDel "module\h+cache"
|
||||
openlitespeedConfigBlockAdd "$block"
|
||||
openlitespeedConfigKeyAdd "$block" 'ls_enabled' '1'
|
||||
openlitespeedConfigKeyAdd "$block" 'checkPrivateCache' '1'
|
||||
openlitespeedConfigKeyAdd "$block" 'checkPublicCache' '1'
|
||||
openlitespeedConfigKeyAdd "$block" 'maxCacheObjSize' '10000000'
|
||||
openlitespeedConfigKeyAdd "$block" 'maxStaleAge' '200'
|
||||
openlitespeedConfigKeyAdd "$block" 'qsCache' '1'
|
||||
openlitespeedConfigKeyAdd "$block" 'reqCookieCache' '1'
|
||||
openlitespeedConfigKeyAdd "$block" 'respCookieCache' '1'
|
||||
openlitespeedConfigKeyAdd "$block" 'ignoreReqCacheCtrl' '1'
|
||||
openlitespeedConfigKeyAdd "$block" 'ignoreRespCacheCtrl' '0'
|
||||
openlitespeedConfigKeyAdd "$block" 'enableCache' '0'
|
||||
openlitespeedConfigKeyAdd "$block" 'expireInSeconds' '3600'
|
||||
openlitespeedConfigKeyAdd "$block" 'enablePrivateCache' '0'
|
||||
openlitespeedConfigKeyAdd "$block" 'privateExpireInSeconds' '3600'
|
||||
}
|
||||
|
||||
function openlitespeedVhostSet() {
|
||||
local domain
|
||||
domain=$(domainPrepare "$1")
|
||||
domainCheck "$domain" || return 1
|
||||
shift || true
|
||||
|
||||
local -a aliasesRaw=("$@")
|
||||
local -a aliases=()
|
||||
local aliasRaw alias error
|
||||
for aliasRaw in "${aliasesRaw[@]}"; do
|
||||
alias="$(domainPrepare "$aliasRaw")"
|
||||
[[ -n "$alias" ]] || continue
|
||||
[[ "$alias" == "$domain" ]] && continue
|
||||
runError error domainCheck "$alias" || { appError "$alias: $error"; return 1; }
|
||||
arrayContains "$alias" "${aliases[@]}" || aliases+=("$alias")
|
||||
done
|
||||
|
||||
local vhostAliasList vhostList aliasList
|
||||
run vhostAliasList error openlitespeedConfigVhostAliasList "$domain" || { appError "Failed get list of vhost alias: $error"; return 1; }
|
||||
run vhostList error openlitespeedConfigVhostList || { appError "Failed get list of vhost: $error"; return 1; }
|
||||
run aliasList error openlitespeedConfigAliasList || { appError "Failed get list of alias: $error"; return 1; }
|
||||
|
||||
# For a new domain vhostAliasList is empty, so this covers both create and update
|
||||
local aliasListOther
|
||||
aliasListOther=$(grep -Fvx -f <(printf '%s\n' "$vhostAliasList") <<< "$aliasList" || true)
|
||||
for alias in "${aliases[@]}"; do
|
||||
listContains "$alias" "$vhostList" && { appError "$alias: Is already exists as vhost"; return 1; }
|
||||
listContains "$alias" "$aliasListOther" && { appError "$alias: Is already exists as alias"; return 1; }
|
||||
done
|
||||
|
||||
local aliasValue=''
|
||||
[[ ${#aliases[@]} -gt 0 ]] && aliasValue="$(IFS=','; printf '%s\n' "${aliases[*]}")"
|
||||
|
||||
fileBackup "$olsConfigFile" || return 1
|
||||
openlitespeedConfigVhostSet "$domain" "${aliases[@]}" || return 1
|
||||
|
||||
local domainConfigFile="$appDataPath/config/$domain.config"
|
||||
configSet "$domainConfigFile" alias "$aliasValue" || { appError "Failed set alias in $domainConfigFile"; return 1; }
|
||||
|
||||
if [[ "$olsVhostMode" == "standalone" ]]; then
|
||||
local vHostFile="$olsVhostsConfigPath/$domain.conf"
|
||||
if [[ ! -f "$vHostFile" ]]; then
|
||||
local profileFile memory_limit max_execution_time post_max_size upload_max_filesize
|
||||
profileFile="$appAssetsPath/openlitespeed/profiles/memory-$kubeMemoryProfile.config"
|
||||
[[ -f "$profileFile" ]] || { appError "Profile not found: $profileFile"; return 1; }
|
||||
memory_limit=$(configGet "$profileFile" "memory_limit")
|
||||
max_execution_time=$(configGet "$profileFile" "max_execution_time")
|
||||
post_max_size=$(configGet "$profileFile" "post_max_size")
|
||||
upload_max_filesize=$(configGet "$profileFile" "upload_max_filesize")
|
||||
|
||||
# cp -f -- "$appAssetsPath/openlitespeed/vhost.conf" "$vHostFile" || { appError "Copy vhost template failed"; return 1; }
|
||||
# -e "s|{{domain}}|$domain|g" \
|
||||
cp -f -- "$appAssetsPath/openlitespeed/vhosts/$olsVhostFile" "$vHostFile" || { appError "Copy vhost template failed"; return 1; }
|
||||
sed -i \
|
||||
-e "s|{{memory_limit}}|$memory_limit|g" \
|
||||
-e "s|{{max_execution_time}}|$max_execution_time|g" \
|
||||
-e "s|{{post_max_size}}|$post_max_size|g" \
|
||||
-e "s|{{upload_max_filesize}}|$upload_max_filesize|g" \
|
||||
-- "$vHostFile" || { appError "Template substitution failed: $vHostFile"; return 1; }
|
||||
fi
|
||||
fi
|
||||
|
||||
printf '%s' "$aliasValue"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Removes a virtual host from the OLS main config, listener map, and config files.
|
||||
# Idempotent: safe to call even if the vhost does not exist.
|
||||
# $1 (domain): site domain name.
|
||||
function openlitespeedVhostConfigDel() {
|
||||
local domain
|
||||
domain=$(domainPrepare "$1")
|
||||
domainCheck "$domain" || return 1
|
||||
|
||||
fileBackup "$olsConfigFile" || return 1
|
||||
openlitespeedConfigVhostUp "$domain"
|
||||
openlitespeedConfigVhostDel "$domain"
|
||||
|
||||
if [[ "$olsVhostMode" == "standalone" ]]; then
|
||||
rm -f -- "$olsVhostsConfigPath/$domain.conf" &>/dev/null
|
||||
rm -f -- "$olsVhostsConfigPath/$domain.conf0" &>/dev/null
|
||||
rm -f -- "$olsVhostsConfigPath/$domain.txt" &>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
# Marks a virtual host as active.
|
||||
# $1 (domain): site domain name.
|
||||
function openlitespeedVhostConfigUp() {
|
||||
local domain vhostList error
|
||||
domain=$(domainPrepare "$1")
|
||||
domainCheck "$domain" || return 1
|
||||
|
||||
run vhostList error openlitespeedConfigVhostList || return 1
|
||||
listContains "$domain" "$vhostList" || return 1
|
||||
|
||||
openlitespeedConfigVhostUp "$domain"
|
||||
}
|
||||
|
||||
# Marks a virtual host as suspended.
|
||||
# $1 (domain): site domain name.
|
||||
function openlitespeedVhostConfigDown() {
|
||||
local domain vhostList error
|
||||
domain=$(domainPrepare "$1")
|
||||
domainCheck "$domain" || return 1
|
||||
|
||||
run vhostList error openlitespeedConfigVhostList || return 1
|
||||
runSilent fileCheckLineLength "$olsConfigFile" 8000 || { appError "fileCheckLineLength 8000"; return 1; }
|
||||
listContains "$domain" "$vhostList" || return 1
|
||||
|
||||
openlitespeedConfigVhostDown "$domain"
|
||||
}
|
||||
|
||||
# Rebuilds filesystem layout, ownership, and permissions for a virtual host.
|
||||
# $1 (vhostPath): virtual host chroot path.
|
||||
# $2 (privatePath): virtual host private path.
|
||||
# $3 (ug): system user/group name for the site.
|
||||
function openlitespeedVhostPermissionSet() {
|
||||
local vhostPath="$1"
|
||||
local privatePath="$2"
|
||||
local ug="$3"
|
||||
[[ -n "$vhostPath" ]] || { appError "vhostPath not specified"; return 1; }
|
||||
[[ -n "$privatePath" ]] || { appError "privatePath not specified"; return 1; }
|
||||
[[ -n "$ug" ]] || { appError "ug not specified"; return 1; }
|
||||
|
||||
# Create site directories
|
||||
mkdir -p -- "$vhostPath"/{www,tmp,session} || { appError "Create vhost directories failed: $vhostPath"; return 1; }
|
||||
|
||||
# Chroot directory: owned by root (required for OpenSSH)
|
||||
chown root:root -- "$vhostPath" || { appError "Change owner of chroot directory failed: $vhostPath"; return 1; }
|
||||
chmod 755 -- "$vhostPath" || { appError "Change permission of chroot directory failed: $vhostPath"; return 1; }
|
||||
|
||||
# Site directories: owned by site user
|
||||
chown -R -- "$ug:$ug" "$vhostPath/www" "$vhostPath/tmp" "$vhostPath/session" || { appError "Change owner of site directories failed: $vhostPath"; return 1; }
|
||||
|
||||
# Permissions: www
|
||||
find "$vhostPath/www" -type d -exec chmod 2750 -- {} + || { appError "Change permissions of www directories failed"; return 1; }
|
||||
find "$vhostPath/www" -type f -exec chmod 640 -- {} + || { appError "Change permissions of www files failed"; return 1; }
|
||||
|
||||
# Permissions: tmp
|
||||
find "$vhostPath/tmp" -type d -exec chmod 700 -- {} + || { appError "Change permissions of tmp directories failed"; return 1; }
|
||||
find "$vhostPath/tmp" -type f -exec chmod 600 -- {} + || { appError "Change permissions of tmp files failed"; return 1; }
|
||||
|
||||
# Permissions: session
|
||||
find "$vhostPath/session" -type d -exec chmod 700 -- {} + || { appError "Change permissions of session directories failed"; return 1; }
|
||||
find "$vhostPath/session" -type f -exec chmod 600 -- {} + || { appError "Change permissions of session files failed"; return 1; }
|
||||
|
||||
# Vhost data directory and bootstrap.php
|
||||
mkdir -p -- "$privatePath" || { appError "Create vhost private directory failed: $privatePath"; return 1; }
|
||||
# mkdir -p -- "$privatePath/php" || { appError "Create vhost private/php directory failed: $privatePath"; return 1; }
|
||||
touch -- "$privatePath/bootstrap.php" || { appError "Create bootstrap.php failed: $privatePath/bootstrap.php"; return 1; }
|
||||
chown -R -- "$ug:$ug" "$privatePath" || { appError "Change owner of vhost private directory failed: $privatePath"; return 1; }
|
||||
find "$privatePath" -type d -exec chmod 700 -- {} + || { appError "Change permissions of vhost private directories failed"; return 1; }
|
||||
find "$privatePath" -type f -exec chmod 600 -- {} + || { appError "Change permissions of vhost private files failed"; return 1; }
|
||||
}
|
||||
|
||||
# Rebuilds ACL rules for a virtual host.
|
||||
# Resets existing ACLs, then grants OLS nobody user read access to www/data and rw to tmp/session.
|
||||
# $1 (vhostPath): virtual host chroot path.
|
||||
# $2 (privatePath): virtual host private path.
|
||||
function openlitespeedVhostAclSet() {
|
||||
local vhostPath="$1"
|
||||
local privatePath="$2"
|
||||
[[ -n "$vhostPath" ]] || { appError "vhostPath not specified"; return 1; }
|
||||
[[ -n "$privatePath" ]] || { appError "privatePath not specified"; return 1; }
|
||||
|
||||
# ACL reset: vhostPath
|
||||
setfacl -R -b -- "$vhostPath" || { appError "Clean ACL rules for vhost path failed: $vhostPath"; return 1; }
|
||||
find "$vhostPath" -type d -exec setfacl -k -- {} + || { appError "Clean default ACL rules for vhost directories failed: $vhostPath"; return 1; }
|
||||
|
||||
# ACL for OLS user nobody: www
|
||||
# Directories: read/traverse + inheritance | Files: read
|
||||
find "$vhostPath/www" -type d -exec setfacl -m u:nobody:rx,m:rx,d:u:nobody:rx,d:m:rx -- {} + || { appError "Set ACL for nobody on www directories failed"; return 1; }
|
||||
find "$vhostPath/www" -type f -exec setfacl -m u:nobody:r,m:r -- {} + || { appError "Set ACL for nobody on www files failed"; return 1; }
|
||||
|
||||
# ACL for OLS user nobody: tmp/session
|
||||
# Directories: rwx + inheritance | Files: rw
|
||||
find "$vhostPath/tmp" "$vhostPath/session" -type d -exec setfacl -m u:nobody:rwx,m:rwx,d:u:nobody:rwx,d:m:rwx -- {} + || { appError "Set ACL for nobody on tmp/session directories failed"; return 1; }
|
||||
find "$vhostPath/tmp" "$vhostPath/session" -type f -exec setfacl -m u:nobody:rw,m:rw -- {} + || { appError "Set ACL for nobody on tmp/session files failed"; return 1; }
|
||||
|
||||
# ACL reset: privatePath
|
||||
setfacl -R -b -- "$privatePath" || { appError "Clean ACL rules for vhost private path failed: $privatePath"; return 1; }
|
||||
find "$privatePath" -type d -exec setfacl -k -- {} + || { appError "Clean default ACL rules for vhost private directories failed: $privatePath"; return 1; }
|
||||
|
||||
# ACL for OLS user nobody: privatePath
|
||||
find "$privatePath" -type d -exec setfacl -m u:nobody:rx,m:rx,d:u:nobody:rx,d:m:rx -- {} + || { appError "Set ACL for nobody on vhost private directories failed"; return 1; }
|
||||
find "$privatePath" -type f -exec setfacl -m u:nobody:r,m:r -- {} + || { appError "Set ACL for nobody on vhost private files failed"; return 1; }
|
||||
}
|
||||
|
||||
# Prints disk and inode quota hard limits for a user on the virtual host filesystem.
|
||||
# Output format: <blockLimit> <inodeLimit>
|
||||
# $1 (user): username or numeric UID.
|
||||
function openlitespeedVhostQuotaGet() {
|
||||
local user="$1"
|
||||
[[ -n "$user" ]] || { appError "User not specified"; return 1; }
|
||||
|
||||
local quotaMount
|
||||
quotaMount=$(findmnt -no TARGET --target "$olsVhostsPath")
|
||||
[[ -n "$quotaMount" ]] || { appError "Quota mount not found: $olsVhostsPath"; return 1; }
|
||||
|
||||
local quotaLimits error
|
||||
run quotaLimits error quota -u "$user" --filesystem "$quotaMount" || { appError "$error"; return 1; }
|
||||
quotaLimits=$(awk 'NR>2 && $1 != "" { print $4, $7; exit }' <<< "$quotaLimits")
|
||||
[[ -n "$quotaLimits" ]] || { appError "Parse quota limits failed: user=$user mount=$quotaMount"; return 1; }
|
||||
|
||||
printf '%s\n' "$quotaLimits"
|
||||
}
|
||||
|
||||
# Sets user disk and inode quota for a virtual host.
|
||||
# Requires user quota to be already enabled and active on the target filesystem.
|
||||
# $1 (domain): site domain name.
|
||||
function openlitespeedVhostQuotaSet() {
|
||||
local domain
|
||||
domain=$(domainPrepare "$1")
|
||||
domainCheck "$domain" || return 1
|
||||
|
||||
local ug
|
||||
ug=$(domainToUser "$domain")
|
||||
|
||||
local quotaMount
|
||||
quotaMount=$(findmnt -no TARGET --target "$olsVhostsPath")
|
||||
[[ -n "$quotaMount" ]] || { appError "Quota mount not found: $olsVhostsPath"; return 1; }
|
||||
|
||||
local quotaBlockLimit quotaInodeLimit
|
||||
quotaBlockLimit=$(siteConfigGetOrSet "$domain" "quotaBlockLimit" "$olsQuotaBlockLimit")
|
||||
quotaInodeLimit=$(siteConfigGetOrSet "$domain" "quotaInodeLimit" "$olsQuotaInodeLimit")
|
||||
setquota -u "$ug" "$quotaBlockLimit" "$quotaBlockLimit" "$quotaInodeLimit" "$quotaInodeLimit" "$quotaMount" || {
|
||||
appError "Set quota failed: ug=$ug mount=$quotaMount"
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
# Configures XFS project quota for a virtual host.
|
||||
# $1 (vhostPath): virtual host path to assign to an XFS project.
|
||||
# $2 (projectId): numeric XFS project ID.
|
||||
# $3 (projectName): XFS project name.
|
||||
function openlitespeedVhostXfsSet() {
|
||||
local vhostPath="$1"
|
||||
local projectId="$2"
|
||||
local projectName="$3"
|
||||
[[ -n "$vhostPath" ]] || { appError "vhostPath not specified"; return 1; }
|
||||
[[ -n "$projectId" ]] || { appError "projectId not specified"; return 1; }
|
||||
[[ -n "$projectName" ]] || { appError "projectName not specified"; return 1; }
|
||||
|
||||
local quotaFs
|
||||
quotaFs=$(findmnt -no FSTYPE --target "$vhostPath")
|
||||
[[ "$quotaFs" == "xfs" ]] || {
|
||||
appError "XFS quota filesystem mismatch: vhostPath=$vhostPath fs=$quotaFs expected=xfs"
|
||||
return 1
|
||||
}
|
||||
|
||||
local quotaMount
|
||||
quotaMount=$(findmnt -no TARGET --target "$vhostPath")
|
||||
[[ -n "$quotaMount" ]] || { appError "Detect XFS quota mount failed: $vhostPath"; return 1; }
|
||||
[[ "$quotaMount" == '/' || "$vhostPath" == "$quotaMount"/* ]] || {
|
||||
appError "XFS quota mount mismatch: vhostPath=$vhostPath quotaMount=$quotaMount expected=$olsVhostsPath"
|
||||
return 1
|
||||
}
|
||||
|
||||
local quotaOptions
|
||||
quotaOptions=$(findmnt -no OPTIONS --target "$vhostPath")
|
||||
[[ "$quotaOptions" != *noquota* && ( "$quotaOptions" == *prjquota* || "$quotaOptions" == *pquota* ) ]] || {
|
||||
appError "XFS project quota is not enabled: vhostPath=$vhostPath mount=$quotaMount options=$quotaOptions"
|
||||
return 1
|
||||
}
|
||||
|
||||
touch /etc/projects /etc/projid || { appError "Create XFS quota registry files failed"; return 1; }
|
||||
# /etc/projects format: projectId:path
|
||||
sed -i "\#:$vhostPath\$#d" /etc/projects
|
||||
sed -i "\#^$projectId:#d" /etc/projects
|
||||
printf '%s:%s\n' "$projectId" "$vhostPath" >> /etc/projects
|
||||
# /etc/projid format: projectName:projectId
|
||||
sed -i "\#^$projectName:#d" /etc/projid
|
||||
sed -i "\#:$projectId\$#d" /etc/projid
|
||||
printf '%s:%s\n' "$projectName" "$projectId" >> /etc/projid
|
||||
|
||||
xfs_quota -x -c "project -s $projectName" "$quotaMount" || {
|
||||
appError "Set XFS project quota project failed: $projectName $vhostPath"
|
||||
return 1
|
||||
}
|
||||
xfs_quota -x -c "limit -p bhard=$openlitespeedVhostBlockHard ihard=$openlitespeedVhostInodeHard $projectName" "$quotaMount" || {
|
||||
appError "Set XFS project quota limits failed: $projectName"
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
# Rebuilds a virtual host: user/group, filesystem layout, permissions, and ACLs.
|
||||
# $1 (domain): site domain name.
|
||||
function openlitespeedVhostRebuild() {
|
||||
local domain
|
||||
domain=$(domainPrepare "$1")
|
||||
domainCheck "$domain" || return 1
|
||||
|
||||
local ug vhostPath privatePath
|
||||
ug=$(domainToUser "$domain")
|
||||
vhostPath="$olsVhostsPath/$domain"
|
||||
privatePath="$olsPrivatePath/$domain"
|
||||
|
||||
# User and group
|
||||
if ! getent group "$ug" >/dev/null 2>&1; then
|
||||
groupadd -- "$ug" || { appError "Create group failed: $ug"; return 1; }
|
||||
fi
|
||||
if ! id "$ug" >/dev/null 2>&1; then
|
||||
useradd -M -g "$ug" -d "$vhostPath" -s /usr/sbin/nologin -- "$ug" >/dev/null 2>&1 || { appError "Create user failed: $ug"; return 1; }
|
||||
else
|
||||
usermod -g "$ug" -d "$vhostPath" -s /usr/sbin/nologin -- "$ug" >/dev/null 2>&1 || { appError "Update user failed: $ug"; return 1; }
|
||||
fi
|
||||
|
||||
openlitespeedVhostPermissionSet "$vhostPath" "$privatePath" "$ug" || return 1
|
||||
openlitespeedVhostAclSet "$vhostPath" "$privatePath" || return 1
|
||||
|
||||
# Quota
|
||||
# openlitespeedVhostQuotaSet "$domain" || return 1
|
||||
|
||||
# XFS [ NO USE ! | Only for XFS + prjquota ]
|
||||
# local uId
|
||||
# uId=$(id -u "$ug" 2>/dev/null)
|
||||
# [[ -n "$uId" ]] || { appError "Get user id failed: $ug"; return 1; }
|
||||
# openlitespeedVhostXfsSet "$vhostPath" "$uId" "$domain" || return 1
|
||||
}
|
||||
|
||||
# Edits the OLS WebAdmin config file.
|
||||
# $@ (...): edit mode and arguments.
|
||||
function openlitespeedAdminConfigEdit() {
|
||||
openlitespeedConfigEditFile "$olsAdminPath/admin_config.conf" "$@"
|
||||
}
|
||||
|
||||
# Sets a value in the OLS WebAdmin config.
|
||||
function openlitespeedAdminConfigKeySet() {
|
||||
openlitespeedAdminConfigEdit key_set "$@"
|
||||
}
|
||||
|
||||
# Updates the Traefik middleware IP whitelist for the OLS admin panel from $olsAdminWhiteList.
|
||||
function openlitespeedAdminWhiteList() {
|
||||
local ipList=() whiteList error
|
||||
for i in "${!olsAdminWhiteList[@]}"; do
|
||||
ipList[$i]="\"${olsAdminWhiteList[$i]}\""
|
||||
done
|
||||
whiteList=$(IFS=','; printf '%s' "${ipList[*]}")
|
||||
|
||||
runError error k3sRun patch middleware "$olsKube-admin-allowlist" --type=merge -p "{\"spec\":{\"ipWhiteList\":{\"sourceRange\":[${whiteList}]}}}" \
|
||||
|| { appError "$error"; return 1; }
|
||||
|
||||
printf '%s' "$whiteList"
|
||||
}
|
||||
|
||||
# Restricts OLS admin access to Traefik pod IPs only by updating the admin_config.conf ACL.
|
||||
function openlitespeedAdminAllowList() {
|
||||
local podList
|
||||
podList=$("$k3sCmd" kubectl -n kube-system get pod -l app.kubernetes.io/name=traefik -o jsonpath='{range .items[*]}{.status.podIP}{"\n"}{end}' | awk 'NF')
|
||||
local -a ipList
|
||||
mapfile -t ipList < <(printf '%s\n' "$podList")
|
||||
[[ "${#ipList[@]}" -gt 0 ]] || { appError "Traefik pod IPs not found"; return 1; }
|
||||
|
||||
local allowList
|
||||
allowList=$(IFS=','; printf '%s' "${ipList[*]}")
|
||||
|
||||
fileBackup "$olsAdminPath/admin_config.conf" || return 1
|
||||
openlitespeedAdminConfigKeySet 'accessControl' 'deny' 'ALL' || return 1
|
||||
openlitespeedAdminConfigKeySet 'accessControl' 'allow' "$allowList" || return 1
|
||||
|
||||
printf '%s' "$allowList"
|
||||
}
|
||||
|
||||
# Checks whether user quota support is ready on the virtual host filesystem.
|
||||
function openlitespeedQuotaCheck() {
|
||||
local quotaMount
|
||||
quotaMount=$(findmnt -no TARGET --target "$olsVhostsPath")
|
||||
[[ -n "$quotaMount" ]] || { appError "Quota mount not found: $olsVhostsPath"; return 1; }
|
||||
|
||||
local quotaOptions
|
||||
quotaOptions=$(findmnt -no OPTIONS --target "$quotaMount")
|
||||
[[ "$quotaOptions" == *usrquota* || "$quotaOptions" == *uquota* ]] || {
|
||||
appError "User quota is not enabled: mount=$quotaMount options=$quotaOptions"
|
||||
return 1
|
||||
}
|
||||
|
||||
quotaon -p "$quotaMount" 2>/dev/null | grep -qi "user quota on" || {
|
||||
appError "User quota is not active: mount=$quotaMount"
|
||||
return 1
|
||||
}
|
||||
|
||||
command -v setquota >/dev/null 2>&1 || { appError "setquota command not found"; return 1; }
|
||||
}
|
||||
Reference in New Issue
Block a user