# 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: # $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; } }