711 lines
20 KiB
Bash
Executable File
711 lines
20 KiB
Bash
Executable File
#!/bin/sh
|
|
# RPCD backend for VHost Manager (UCI-driven)
|
|
|
|
. /lib/functions.sh
|
|
. /usr/share/libubox/jshn.sh
|
|
|
|
get_pkg_version() {
|
|
local ctrl="/usr/lib/opkg/info/luci-app-vhost-manager.control"
|
|
if [ -f "$ctrl" ]; then
|
|
awk -F': ' '/^Version/ { print $2; exit }' "$ctrl"
|
|
else
|
|
echo "unknown"
|
|
fi
|
|
}
|
|
|
|
PKG_VERSION="$(get_pkg_version)"
|
|
|
|
NGINX_VHOST_DIR="/etc/nginx/conf.d"
|
|
ACME_STATE_DIR="/etc/acme"
|
|
VHOSTS_CONFIG="/etc/config/vhosts"
|
|
|
|
TLS_CERT_PATH=""
|
|
TLS_KEY_PATH=""
|
|
TLS_ACTIVE=0
|
|
CERT_EXPIRES=""
|
|
CERT_ISSUER=""
|
|
CERT_SUBJECT=""
|
|
|
|
init_dirs() {
|
|
mkdir -p "$NGINX_VHOST_DIR" "$ACME_STATE_DIR"
|
|
[ -f "$VHOSTS_CONFIG" ] || cat <<'CFG' > "$VHOSTS_CONFIG"
|
|
config global 'global'
|
|
option enabled '1'
|
|
option auto_reload '1'
|
|
CFG
|
|
}
|
|
|
|
normalize_bool() {
|
|
local value="$1"
|
|
case "$value" in
|
|
1|true|on|yes|enabled) echo 1 ;;
|
|
*) echo 0 ;;
|
|
esac
|
|
}
|
|
|
|
resolve_tls_mode() {
|
|
local tls_mode="$1"
|
|
local legacy_ssl="$2"
|
|
if [ -n "$tls_mode" ]; then
|
|
echo "$tls_mode"
|
|
return
|
|
fi
|
|
legacy_ssl=$(normalize_bool "$legacy_ssl")
|
|
if [ "$legacy_ssl" = "1" ]; then
|
|
echo "acme"
|
|
else
|
|
echo "off"
|
|
fi
|
|
}
|
|
|
|
find_section() {
|
|
__target="$1"
|
|
__found_section=""
|
|
config_load vhosts
|
|
config_foreach __match_section vhost
|
|
echo "$__found_section"
|
|
}
|
|
|
|
__match_section() {
|
|
local section="$1"
|
|
config_get domain "$section" domain
|
|
if [ "$domain" = "$__target" ]; then
|
|
__found_section="$section"
|
|
fi
|
|
}
|
|
|
|
write_htpasswd() {
|
|
local domain="$1"
|
|
local user="$2"
|
|
local pass="$3"
|
|
local file="/etc/nginx/.luci-app-vhost-manager_${domain}"
|
|
mkdir -p /etc/nginx
|
|
local hash
|
|
hash=$(openssl passwd -apr1 "$pass")
|
|
printf '%s:%s\n' "$user" "$hash" > "$file"
|
|
chmod 600 "$file"
|
|
}
|
|
|
|
remove_htpasswd() {
|
|
local domain="$1"
|
|
rm -f "/etc/nginx/.luci-app-vhost-manager_${domain}"
|
|
}
|
|
|
|
sanitize_section_name() {
|
|
local domain="$1"
|
|
local safe
|
|
safe=$(echo "$domain" | tr 'A-Z' 'a-z' | tr -cd 'a-z0-9_')
|
|
[ -z "$safe" ] && safe="vh$(date +%s)"
|
|
echo "vh_${safe}"
|
|
}
|
|
|
|
set_tls_context() {
|
|
local domain="$1"
|
|
local tls_mode="$2"
|
|
local cert_path="$3"
|
|
local key_path="$4"
|
|
|
|
TLS_ACTIVE=0
|
|
TLS_CERT_PATH=""
|
|
TLS_KEY_PATH=""
|
|
|
|
case "$tls_mode" in
|
|
acme)
|
|
TLS_CERT_PATH="/etc/acme/${domain}/fullchain.cer"
|
|
TLS_KEY_PATH="/etc/acme/${domain}/${domain}.key"
|
|
;;
|
|
manual)
|
|
TLS_CERT_PATH="$cert_path"
|
|
TLS_KEY_PATH="$key_path"
|
|
;;
|
|
*)
|
|
TLS_CERT_PATH=""
|
|
TLS_KEY_PATH=""
|
|
;;
|
|
esac
|
|
|
|
if [ -n "$TLS_CERT_PATH" ] && [ -f "$TLS_CERT_PATH" ] && \
|
|
[ -n "$TLS_KEY_PATH" ] && [ -f "$TLS_KEY_PATH" ]; then
|
|
TLS_ACTIVE=1
|
|
else
|
|
TLS_CERT_PATH=""
|
|
TLS_KEY_PATH=""
|
|
TLS_ACTIVE=0
|
|
fi
|
|
}
|
|
|
|
read_cert_metadata() {
|
|
local file="$1"
|
|
CERT_EXPIRES=""
|
|
CERT_ISSUER=""
|
|
CERT_SUBJECT=""
|
|
[ -f "$file" ] || return 1
|
|
CERT_EXPIRES="$(openssl x509 -in "$file" -noout -enddate 2>/dev/null | cut -d'=' -f2)"
|
|
CERT_ISSUER="$(openssl x509 -in "$file" -noout -issuer 2>/dev/null | cut -d'=' -f2-)"
|
|
CERT_SUBJECT="$(openssl x509 -in "$file" -noout -subject 2>/dev/null | cut -d'=' -f2-)"
|
|
}
|
|
|
|
_count_vhost() {
|
|
local section="$1"
|
|
config_get_bool enabled "$section" enabled 1
|
|
[ "$enabled" = "1" ] || return
|
|
count=$((count + 1))
|
|
}
|
|
|
|
append_vhost_json() {
|
|
local section="$1"
|
|
config_get domain "$section" domain
|
|
[ -n "$domain" ] || return
|
|
|
|
config_get upstream "$section" upstream
|
|
config_get tls "$section" tls
|
|
config_get cert_path "$section" cert_path
|
|
config_get key_path "$section" key_path
|
|
config_get_bool auth "$section" auth 0
|
|
config_get auth_user "$section" auth_user
|
|
config_get_bool websocket "$section" websocket 0
|
|
config_get_bool enabled "$section" enabled 1
|
|
|
|
set_tls_context "$domain" "${tls:-off}" "$cert_path" "$key_path"
|
|
[ "$TLS_ACTIVE" = "1" ] && read_cert_metadata "$TLS_CERT_PATH"
|
|
|
|
json_add_object ""
|
|
json_add_string "section" "$section"
|
|
json_add_string "domain" "$domain"
|
|
json_add_string "backend" "$upstream"
|
|
json_add_string "upstream" "$upstream"
|
|
json_add_string "tls_mode" "${tls:-off}"
|
|
json_add_boolean "ssl" "$TLS_ACTIVE"
|
|
json_add_boolean "auth" "$auth"
|
|
json_add_string "auth_user" "${auth_user:-}"
|
|
json_add_boolean "websocket" "$websocket"
|
|
json_add_boolean "enabled" "$enabled"
|
|
json_add_string "config_file" "$NGINX_VHOST_DIR/${domain}.conf"
|
|
|
|
if [ "$TLS_ACTIVE" = "1" ]; then
|
|
json_add_string "cert_file" "$TLS_CERT_PATH"
|
|
[ -n "$CERT_EXPIRES" ] && json_add_string "cert_expires" "$CERT_EXPIRES"
|
|
[ -n "$CERT_ISSUER" ] && json_add_string "cert_issuer" "$CERT_ISSUER"
|
|
[ -n "$CERT_SUBJECT" ] && json_add_string "cert_subject" "$CERT_SUBJECT"
|
|
fi
|
|
|
|
json_close_object
|
|
}
|
|
|
|
|
|
render_vhost_section() {
|
|
local section="$1"
|
|
config_get domain "$section" domain
|
|
config_get upstream "$section" upstream
|
|
config_get tls "$section" tls
|
|
config_get cert_path "$section" cert_path
|
|
config_get key_path "$section" key_path
|
|
config_get_bool auth "$section" auth 0
|
|
config_get auth_user "$section" auth_user
|
|
config_get auth_pass "$section" auth_pass
|
|
config_get_bool websocket "$section" websocket 0
|
|
config_get_bool enabled "$section" enabled 1
|
|
[ -z "$domain" ] && return
|
|
[ -z "$upstream" ] && return
|
|
local conf="$NGINX_VHOST_DIR/${domain}.conf"
|
|
|
|
if [ "$enabled" != "1" ]; then
|
|
rm -f "$conf"
|
|
remove_htpasswd "$domain"
|
|
return
|
|
fi
|
|
|
|
if [ "$auth" = "1" ] && [ -n "$auth_user" ] && [ -n "$auth_pass" ]; then
|
|
write_htpasswd "$domain" "$auth_user" "$auth_pass"
|
|
else
|
|
remove_htpasswd "$domain"
|
|
fi
|
|
|
|
set_tls_context "$domain" "${tls:-off}" "$cert_path" "$key_path"
|
|
generate_vhost_config "$domain" "$upstream" "$TLS_ACTIVE" "$auth" "$websocket"
|
|
}
|
|
|
|
render_all_vhosts() {
|
|
config_load vhosts
|
|
config_foreach render_vhost_section vhost
|
|
}
|
|
|
|
generate_vhost_config() {
|
|
local domain="$1"
|
|
local backend="$2"
|
|
local ssl="$3"
|
|
local auth="$4"
|
|
local websocket="$5"
|
|
local config_file="$NGINX_VHOST_DIR/${domain}.conf"
|
|
|
|
cat > "$config_file" <<NGINXEOF
|
|
# VHost for ${domain}
|
|
# Generated by LuCI VHost Manager
|
|
|
|
server {
|
|
listen 80;
|
|
server_name ${domain};
|
|
NGINXEOF
|
|
|
|
if [ "$ssl" = "1" ]; then
|
|
cat >> "$config_file" <<NGINXEOF
|
|
return 301 https://\$host\$request_uri;
|
|
}
|
|
|
|
server {
|
|
listen 443 ssl http2;
|
|
server_name ${domain};
|
|
ssl_certificate ${TLS_CERT_PATH};
|
|
ssl_certificate_key ${TLS_KEY_PATH};
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
|
ssl_prefer_server_ciphers on;
|
|
NGINXEOF
|
|
fi
|
|
|
|
if [ "$auth" = "1" ]; then
|
|
cat >> "$config_file" <<NGINXEOF
|
|
auth_basic "Restricted Access";
|
|
auth_basic_user_file /etc/nginx/.luci-app-vhost-manager_${domain};
|
|
NGINXEOF
|
|
fi
|
|
|
|
cat >> "$config_file" <<NGINXEOF
|
|
location / {
|
|
proxy_pass ${backend};
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host \$host;
|
|
proxy_set_header X-Real-IP \$remote_addr;
|
|
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto \$scheme;
|
|
NGINXEOF
|
|
|
|
if [ "$websocket" = "1" ]; then
|
|
cat >> "$config_file" <<NGINXEOF
|
|
proxy_set_header Upgrade \$http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
NGINXEOF
|
|
fi
|
|
|
|
cat >> "$config_file" <<NGINXEOF
|
|
proxy_connect_timeout 60s;
|
|
proxy_send_timeout 60s;
|
|
proxy_read_timeout 60s;
|
|
}
|
|
access_log /var/log/nginx/${domain}_access.log;
|
|
error_log /var/log/nginx/${domain}_error.log;
|
|
}
|
|
NGINXEOF
|
|
}
|
|
|
|
validate_backend() {
|
|
local backend="$1"
|
|
echo "$backend" | grep -Eq '^https?://' || return 1
|
|
return 0
|
|
}
|
|
|
|
probe_backend() {
|
|
local backend="$1"
|
|
local host port
|
|
host=$(echo "$backend" | sed 's|https\?://||' | cut -d'/' -f1 | cut -d':' -f1)
|
|
port=$(echo "$backend" | sed 's|https\?://||' | cut -d'/' -f1 | cut -d':' -f2)
|
|
if [ -z "$port" ]; then
|
|
if echo "$backend" | grep -q '^https://'; then
|
|
port=443
|
|
else
|
|
port=80
|
|
fi
|
|
fi
|
|
if [ -n "$host" ]; then
|
|
nc -z -w 5 "$host" "$port" 2>/dev/null
|
|
return $?
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
add_or_update_vhost() {
|
|
local domain="$1"
|
|
local backend="$2"
|
|
local tls_mode="$3"
|
|
local auth="$4"
|
|
local auth_user="$5"
|
|
local auth_pass="$6"
|
|
local websocket="$7"
|
|
local enabled="$8"
|
|
local cert_path="$9"
|
|
local key_path="${10}"
|
|
|
|
local section
|
|
section=$(find_section "$domain")
|
|
if [ -z "$section" ]; then
|
|
local safe
|
|
safe=$(sanitize_section_name "$domain")
|
|
section=$(uci add vhosts vhost)
|
|
uci rename vhosts.$section="$safe"
|
|
section="$safe"
|
|
uci set vhosts.$section.domain="$domain"
|
|
fi
|
|
|
|
local normalized_tls="${tls_mode:-off}"
|
|
local normalized_auth
|
|
local normalized_websocket
|
|
local normalized_enabled
|
|
|
|
normalized_auth=$(normalize_bool "$auth")
|
|
normalized_websocket=$(normalize_bool "$websocket")
|
|
if [ -n "$enabled" ]; then
|
|
normalized_enabled=$(normalize_bool "$enabled")
|
|
else
|
|
normalized_enabled=1
|
|
fi
|
|
|
|
uci set vhosts.$section.upstream="$backend"
|
|
uci set vhosts.$section.tls="$normalized_tls"
|
|
if [ -n "$cert_path" ]; then
|
|
uci set vhosts.$section.cert_path="$cert_path"
|
|
else
|
|
uci -q delete vhosts.$section.cert_path
|
|
fi
|
|
if [ -n "$key_path" ]; then
|
|
uci set vhosts.$section.key_path="$key_path"
|
|
else
|
|
uci -q delete vhosts.$section.key_path
|
|
fi
|
|
uci set vhosts.$section.auth="$normalized_auth"
|
|
if [ -n "$auth_user" ]; then
|
|
uci set vhosts.$section.auth_user="$auth_user"
|
|
else
|
|
uci -q delete vhosts.$section.auth_user
|
|
fi
|
|
if [ -n "$auth_pass" ]; then
|
|
uci set vhosts.$section.auth_pass="$auth_pass"
|
|
else
|
|
uci -q delete vhosts.$section.auth_pass
|
|
fi
|
|
uci set vhosts.$section.websocket="$normalized_websocket"
|
|
uci set vhosts.$section.enabled="$normalized_enabled"
|
|
|
|
uci commit vhosts
|
|
config_load vhosts
|
|
render_vhost_section "$section"
|
|
}
|
|
|
|
list_response_schema() {
|
|
json_init
|
|
json_add_object "status"
|
|
json_close_object
|
|
json_add_object "list_vhosts"
|
|
json_close_object
|
|
json_add_object "get_vhost"
|
|
json_add_string "domain" "string"
|
|
json_close_object
|
|
json_add_object "add_vhost"
|
|
json_add_string "domain" "string"
|
|
json_add_string "backend" "string"
|
|
json_add_string "tls_mode" "string"
|
|
json_add_string "auth" "bool"
|
|
json_add_string "auth_user" "string"
|
|
json_add_string "auth_pass" "string"
|
|
json_add_string "websocket" "bool"
|
|
json_add_string "enabled" "bool"
|
|
json_add_string "cert_path" "string"
|
|
json_add_string "key_path" "string"
|
|
json_close_object
|
|
json_add_object "update_vhost"
|
|
json_add_string "domain" "string"
|
|
json_add_string "backend" "string"
|
|
json_add_string "tls_mode" "string"
|
|
json_add_string "auth" "bool"
|
|
json_add_string "auth_user" "string"
|
|
json_add_string "auth_pass" "string"
|
|
json_add_string "websocket" "bool"
|
|
json_add_string "enabled" "bool"
|
|
json_add_string "cert_path" "string"
|
|
json_add_string "key_path" "string"
|
|
json_close_object
|
|
json_add_object "delete_vhost"
|
|
json_add_string "domain" "string"
|
|
json_close_object
|
|
json_add_object "test_backend"
|
|
json_add_string "backend" "string"
|
|
json_close_object
|
|
json_add_object "request_cert"
|
|
json_add_string "domain" "string"
|
|
json_add_string "email" "string"
|
|
json_close_object
|
|
json_add_object "list_certs"
|
|
json_close_object
|
|
json_add_object "reload_nginx"
|
|
json_close_object
|
|
json_add_object "get_access_logs"
|
|
json_add_string "domain" "string"
|
|
json_add_string "lines" "int"
|
|
json_close_object
|
|
json_dump
|
|
}
|
|
|
|
init_dirs
|
|
|
|
case "$1" in
|
|
list)
|
|
list_response_schema
|
|
;;
|
|
call)
|
|
case "$2" in
|
|
status)
|
|
init_dirs
|
|
json_init
|
|
json_add_boolean "enabled" 1
|
|
json_add_string "module" "vhost-manager"
|
|
json_add_string "version" "$PKG_VERSION"
|
|
if pgrep -x nginx >/dev/null 2>&1; then
|
|
json_add_boolean "nginx_running" 1
|
|
json_add_string "nginx_version" "$(nginx -v 2>&1 | grep -o 'nginx/[0-9.]*' | cut -d'/' -f2)"
|
|
else
|
|
json_add_boolean "nginx_running" 0
|
|
json_add_string "nginx_version" "unknown"
|
|
fi
|
|
if command -v acme.sh >/dev/null 2>&1; then
|
|
json_add_boolean "acme_available" 1
|
|
json_add_string "acme_version" "$(acme.sh --version 2>/dev/null | head -1)"
|
|
else
|
|
json_add_boolean "acme_available" 0
|
|
json_add_string "acme_version" "not installed"
|
|
fi
|
|
count=0
|
|
config_load vhosts
|
|
config_foreach _count_vhost vhost
|
|
json_add_int "vhost_count" "$count"
|
|
json_dump
|
|
;;
|
|
list_vhosts)
|
|
json_init
|
|
json_add_array "vhosts"
|
|
config_load vhosts
|
|
config_foreach append_vhost_json vhost
|
|
json_close_array
|
|
json_dump
|
|
;;
|
|
get_vhost)
|
|
read -r input
|
|
json_load "$input"
|
|
json_get_var domain domain
|
|
local section=$(find_section "$domain")
|
|
json_init
|
|
if [ -n "$section" ]; then
|
|
config_load vhosts
|
|
config_get upstream "$section" upstream
|
|
config_get tls "$section" tls
|
|
config_get_bool auth "$section" auth 0
|
|
config_get auth_user "$section" auth_user
|
|
config_get_bool websocket "$section" websocket 0
|
|
config_get_bool enabled "$section" enabled 1
|
|
config_get cert_path "$section" cert_path
|
|
config_get key_path "$section" key_path
|
|
set_tls_context "$domain" "${tls:-off}" "$cert_path" "$key_path"
|
|
[ "$TLS_ACTIVE" = "1" ] && read_cert_metadata "$TLS_CERT_PATH"
|
|
json_add_boolean "exists" 1
|
|
json_add_string "domain" "$domain"
|
|
json_add_string "backend" "$upstream"
|
|
json_add_string "tls_mode" "${tls:-off}"
|
|
json_add_boolean "ssl" "$TLS_ACTIVE"
|
|
json_add_boolean "auth" "$auth"
|
|
[ -n "$auth_user" ] && json_add_string "auth_user" "$auth_user"
|
|
json_add_boolean "websocket" "$websocket"
|
|
json_add_boolean "enabled" "$enabled"
|
|
json_add_string "config_file" "$NGINX_VHOST_DIR/${domain}.conf"
|
|
[ -n "$cert_path" ] && json_add_string "cert_path" "$cert_path"
|
|
[ -n "$key_path" ] && json_add_string "key_path" "$key_path"
|
|
if [ "$TLS_ACTIVE" = "1" ]; then
|
|
json_add_string "cert_file" "$TLS_CERT_PATH"
|
|
[ -n "$CERT_EXPIRES" ] && json_add_string "cert_expires" "$CERT_EXPIRES"
|
|
[ -n "$CERT_ISSUER" ] && json_add_string "cert_issuer" "$CERT_ISSUER"
|
|
fi
|
|
else
|
|
json_add_boolean "exists" 0
|
|
fi
|
|
json_dump
|
|
;;
|
|
add_vhost)
|
|
read -r input
|
|
json_load "$input"
|
|
json_get_var domain domain
|
|
json_get_var backend backend
|
|
json_get_var tls_mode tls_mode
|
|
json_get_var ssl legacy_ssl
|
|
json_get_var auth auth
|
|
json_get_var auth_user auth_user
|
|
json_get_var auth_pass auth_pass
|
|
json_get_var websocket websocket
|
|
json_get_var enabled enabled
|
|
json_get_var cert_path cert_path
|
|
json_get_var key_path key_path
|
|
if [ -z "$domain" ] || [ -z "$backend" ]; then
|
|
json_init; json_add_boolean "success" 0; json_add_string "message" "Domain and backend required"; json_dump; exit 0
|
|
fi
|
|
if ! validate_backend "$backend"; then
|
|
json_init; json_add_boolean "success" 0; json_add_string "message" "Backend must be http(s) URL"; json_dump; exit 0
|
|
fi
|
|
local existing_section
|
|
existing_section=$(find_section "$domain")
|
|
if [ -n "$existing_section" ]; then
|
|
json_init; json_add_boolean "success" 0; json_add_string "message" "VHost already exists"; json_dump; exit 0
|
|
fi
|
|
tls_mode=$(resolve_tls_mode "$tls_mode" "$legacy_ssl")
|
|
if [ "$tls_mode" = "manual" ] && { [ -z "$cert_path" ] || [ -z "$key_path" ]; }; then
|
|
json_init; json_add_boolean "success" 0; json_add_string "message" "Manual TLS requires cert_path and key_path"; json_dump; exit 0
|
|
fi
|
|
add_or_update_vhost "$domain" "$backend" "$tls_mode" "$auth" "$auth_user" "$auth_pass" "$websocket" "$enabled" "$cert_path" "$key_path"
|
|
json_init; json_add_boolean "success" 1; json_add_boolean "reload_required" 1; json_dump
|
|
;;
|
|
update_vhost)
|
|
read -r input
|
|
json_load "$input"
|
|
json_get_var domain domain
|
|
json_get_var backend backend
|
|
json_get_var tls_mode tls_mode
|
|
json_get_var ssl legacy_ssl
|
|
json_get_var auth auth
|
|
json_get_var auth_user auth_user
|
|
json_get_var auth_pass auth_pass
|
|
json_get_var websocket websocket
|
|
json_get_var enabled enabled
|
|
json_get_var cert_path cert_path
|
|
json_get_var key_path key_path
|
|
if [ -z "$domain" ]; then
|
|
json_init; json_add_boolean "success" 0; json_add_string "message" "Domain required"; json_dump; exit 0
|
|
fi
|
|
local section
|
|
section=$(find_section "$domain")
|
|
if [ -z "$section" ]; then
|
|
json_init; json_add_boolean "success" 0; json_add_string "message" "VHost not found"; json_dump; exit 0
|
|
fi
|
|
if [ -n "$backend" ] && ! validate_backend "$backend"; then
|
|
json_init; json_add_boolean "success" 0; json_add_string "message" "Backend must be http(s) URL"; json_dump; exit 0
|
|
fi
|
|
config_load vhosts
|
|
if [ -z "$backend" ]; then
|
|
config_get backend "$section" upstream
|
|
fi
|
|
if [ -z "$enabled" ]; then
|
|
config_get_bool enabled "$section" enabled 1
|
|
fi
|
|
local current_tls current_cert_path current_key_path
|
|
config_get current_tls "$section" tls
|
|
config_get current_cert_path "$section" cert_path
|
|
config_get current_key_path "$section" key_path
|
|
if [ -n "$tls_mode" ] || [ -n "$legacy_ssl" ]; then
|
|
tls_mode=$(resolve_tls_mode "$tls_mode" "$legacy_ssl")
|
|
else
|
|
tls_mode="${current_tls:-off}"
|
|
fi
|
|
[ -n "$cert_path" ] || cert_path="$current_cert_path"
|
|
[ -n "$key_path" ] || key_path="$current_key_path"
|
|
if [ "$tls_mode" = "manual" ] && { [ -z "$cert_path" ] || [ -z "$key_path" ]; }; then
|
|
json_init; json_add_boolean "success" 0; json_add_string "message" "Manual TLS requires cert_path and key_path"; json_dump; exit 0
|
|
fi
|
|
add_or_update_vhost "$domain" "$backend" "$tls_mode" "$auth" "$auth_user" "$auth_pass" "$websocket" "$enabled" "$cert_path" "$key_path"
|
|
json_init; json_add_boolean "success" 1; json_add_boolean "reload_required" 1; json_dump
|
|
;;
|
|
delete_vhost)
|
|
read -r input
|
|
json_load "$input"
|
|
json_get_var domain domain
|
|
local section=$(find_section "$domain")
|
|
local conf="$NGINX_VHOST_DIR/${domain}.conf"
|
|
if [ -n "$section" ]; then
|
|
uci delete vhosts.$section
|
|
uci commit vhosts
|
|
fi
|
|
rm -f "$conf"
|
|
remove_htpasswd "$domain"
|
|
json_init; json_add_boolean "success" 1; json_add_boolean "reload_required" 1; json_dump
|
|
;;
|
|
test_backend)
|
|
read -r input
|
|
json_load "$input"
|
|
json_get_var backend backend
|
|
json_init
|
|
json_add_string "backend" "$backend"
|
|
if [ -n "$backend" ] && probe_backend "$backend"; then
|
|
json_add_boolean "reachable" 1
|
|
json_add_string "status" "Backend is reachable"
|
|
else
|
|
json_add_boolean "reachable" 0
|
|
json_add_string "status" "Backend is unreachable"
|
|
fi
|
|
json_dump
|
|
;;
|
|
request_cert)
|
|
read -r input
|
|
json_load "$input"
|
|
json_get_var domain domain
|
|
json_get_var email email
|
|
json_init
|
|
if ! command -v acme.sh >/dev/null 2>&1; then
|
|
json_add_boolean "success" 0
|
|
json_add_string "message" "acme.sh not installed"
|
|
json_dump
|
|
return
|
|
fi
|
|
if acme.sh --issue -d "$domain" --standalone --accountemail "$email" --force >/tmp/acme.log 2>&1; then
|
|
json_add_boolean "success" 1
|
|
json_add_string "message" "Certificate requested"
|
|
else
|
|
json_add_boolean "success" 0
|
|
json_add_string "message" "Certificate request failed"
|
|
fi
|
|
json_dump
|
|
;;
|
|
list_certs)
|
|
json_init
|
|
json_add_array "certificates"
|
|
if [ -d "$ACME_STATE_DIR" ]; then
|
|
find "$ACME_STATE_DIR" -name "fullchain.cer" -type f 2>/dev/null | while read -r cert_file; do
|
|
local domain
|
|
domain=$(basename "$(dirname "$cert_file")")
|
|
local expires issuer subject
|
|
expires=$(openssl x509 -in "$cert_file" -noout -enddate 2>/dev/null | cut -d'=' -f2)
|
|
issuer=$(openssl x509 -in "$cert_file" -noout -issuer 2>/dev/null | cut -d'=' -f2-)
|
|
subject=$(openssl x509 -in "$cert_file" -noout -subject 2>/dev/null | cut -d'=' -f2-)
|
|
json_add_object
|
|
json_add_string "domain" "$domain"
|
|
json_add_string "expires" "$expires"
|
|
json_add_string "issuer" "$issuer"
|
|
json_add_string "subject" "$subject"
|
|
json_add_string "cert_file" "$cert_file"
|
|
json_close_object
|
|
done
|
|
fi
|
|
json_close_array
|
|
json_dump
|
|
;;
|
|
reload_nginx)
|
|
if nginx -t >/dev/null 2>&1; then
|
|
/etc/init.d/nginx reload
|
|
json_init; json_add_boolean "success" 1; json_dump
|
|
else
|
|
json_init; json_add_boolean "success" 0; json_add_string "message" "nginx config invalid"; json_dump
|
|
fi
|
|
;;
|
|
get_access_logs)
|
|
read -r input
|
|
json_load "$input"
|
|
json_get_var domain domain
|
|
json_get_var lines lines
|
|
lines=${lines:-100}
|
|
local file="/var/log/nginx/${domain}_access.log"
|
|
json_init
|
|
json_add_string "domain" "$domain"
|
|
json_add_array "logs"
|
|
if [ -f "$file" ]; then
|
|
tail -n "$lines" "$file" | while read -r line; do json_add_string "" "$line"; done
|
|
fi
|
|
json_close_array
|
|
json_dump
|
|
;;
|
|
*) json_init; json_add_string "error" "unknown method"; json_dump ;;
|
|
esac
|
|
;;
|
|
esac
|