diff --git a/opnsense-plugin/www/rustproxy/+POST_INSTALL.pre b/opnsense-plugin/www/rustproxy/+POST_INSTALL.pre index a19b863..36e6097 100755 --- a/opnsense-plugin/www/rustproxy/+POST_INSTALL.pre +++ b/opnsense-plugin/www/rustproxy/+POST_INSTALL.pre @@ -21,6 +21,13 @@ fi # therefore refresh configd before the MVC service controller can call them. /usr/sbin/service configd restart >/dev/null 2>&1 || true /usr/local/sbin/pluginctl -cq cache_flush >/dev/null 2>&1 || true + +# Apply model migrations before rendering the service template. In particular +# 1.4.0 copies the old combined listener values into the split address/port +# fields so upgrades keep their existing ports instead of falling back. +if [ -x /usr/local/opnsense/mvc/script/run_migrations.php ]; then + /usr/local/opnsense/mvc/script/run_migrations.php >/dev/null 2>&1 || true +fi /usr/local/sbin/configctl template reload OPNsense/RustProxy >/dev/null 2>&1 || true exit 0 diff --git a/opnsense-plugin/www/rustproxy/Makefile b/opnsense-plugin/www/rustproxy/Makefile index 546dce8..abd1039 100644 --- a/opnsense-plugin/www/rustproxy/Makefile +++ b/opnsense-plugin/www/rustproxy/Makefile @@ -1,6 +1,6 @@ PLUGIN_NAME= rustproxy PLUGIN_VERSION?= 0.23.3 -PLUGIN_REVISION?= 0 +PLUGIN_REVISION?= 1 PLUGIN_COMMENT= RustProxy reverse proxy service PLUGIN_MAINTAINER?= local@localhost PLUGIN_WWW?= https://git.linuxiarz.pl/gru/RustProxy diff --git a/opnsense-plugin/www/rustproxy/src/etc/rc.d/rustproxy b/opnsense-plugin/www/rustproxy/src/etc/rc.d/rustproxy index 6907b0c..0f651b4 100755 --- a/opnsense-plugin/www/rustproxy/src/etc/rc.d/rustproxy +++ b/opnsense-plugin/www/rustproxy/src/etc/rc.d/rustproxy @@ -160,7 +160,9 @@ fi command_args="-r -R ${rustproxy_restart_delay} -P ${pidfile} -p ${child_pidfile} ${rustproxy_daemon_user_arg} -o ${rustproxy_log_file} ${rustproxy_command} ${rustproxy_runtime_args}" required_files="${rustproxy_command}" start_precmd="rustproxy_prestart" +start_postcmd="rustproxy_poststart" stop_postcmd="rustproxy_poststop" +status_cmd="rustproxy_status" rustproxy_prestart() { @@ -179,6 +181,72 @@ rustproxy_prestart() /bin/chmod 0640 "${rustproxy_log_file}" echo "RustProxy listeners: HTTP=${rustproxy_proxy_listen_resolved} TLS=${rustproxy_tls_listen_resolved} ADMIN=${rustproxy_admin_listen_resolved}" + echo "RustProxy exec: ${rustproxy_command} ${rustproxy_runtime_args}" + printf '%s\n' "${rustproxy_command} ${rustproxy_runtime_args}" > "${rustproxy_run_dir}/command.txt" + /bin/chmod 0640 "${rustproxy_run_dir}/command.txt" +} + +rustproxy_child_pid() +{ + [ -r "${child_pidfile}" ] || return 1 + _rp_pid="$(/bin/cat "${child_pidfile}" 2>/dev/null)" + case "${_rp_pid}" in + ''|*[!0-9]*) return 1 ;; + esac + /bin/kill -0 "${_rp_pid}" 2>/dev/null || return 1 + printf '%s\n' "${_rp_pid}" +} + +rustproxy_poststart() +{ + # daemon(8) may stay alive with -r even when rust-proxy exits immediately. + # Verify the supervised child so service/configd cannot report a false OK. + /bin/sleep 1 + if _rp_pid="$(rustproxy_child_pid)"; then + echo "RustProxy child started as PID ${_rp_pid}" + return 0 + fi + + echo "RustProxy failed to stay running; stopping the restart supervisor." >&2 + if [ -s "${rustproxy_log_file}" ]; then + echo "Last RustProxy log lines:" >&2 + /usr/bin/tail -n 40 "${rustproxy_log_file}" >&2 + fi + if [ -r "${pidfile}" ]; then + _rp_supervisor_pid="$(/bin/cat "${pidfile}" 2>/dev/null)" + case "${_rp_supervisor_pid}" in + ''|*[!0-9]*) ;; + *) /bin/kill -TERM "${_rp_supervisor_pid}" 2>/dev/null || true ;; + esac + fi + /bin/sleep 1 + /bin/rm -f "${child_pidfile}" "${pidfile}" + return 1 +} + +rustproxy_status() +{ + if _rp_pid="$(rustproxy_child_pid)"; then + echo "rustproxy is running as pid ${_rp_pid}" + return 0 + fi + + _rp_supervisor_pid="" + if [ -r "${pidfile}" ]; then + _rp_supervisor_pid="$(/bin/cat "${pidfile}" 2>/dev/null)" + fi + case "${_rp_supervisor_pid}" in + ''|*[!0-9]*) ;; + *) + if /bin/kill -0 "${_rp_supervisor_pid}" 2>/dev/null; then + echo "rustproxy is not running (daemon supervisor ${_rp_supervisor_pid} is waiting/restarting)" + return 1 + fi + ;; + esac + + echo "rustproxy is not running" + return 1 } rustproxy_poststop() diff --git a/opnsense-plugin/www/rustproxy/src/opnsense/mvc/app/controllers/OPNsense/RustProxy/Api/ServiceController.php b/opnsense-plugin/www/rustproxy/src/opnsense/mvc/app/controllers/OPNsense/RustProxy/Api/ServiceController.php index f96d74b..9f25c66 100644 --- a/opnsense-plugin/www/rustproxy/src/opnsense/mvc/app/controllers/OPNsense/RustProxy/Api/ServiceController.php +++ b/opnsense-plugin/www/rustproxy/src/opnsense/mvc/app/controllers/OPNsense/RustProxy/Api/ServiceController.php @@ -13,6 +13,8 @@ class ServiceController extends ApiMutableServiceControllerBase protected function reconfigureForceRestart() { - return 0; + // Listener addresses are process startup arguments, so Apply must + // always stop and start the service after regenerating the template. + return 1; } } diff --git a/opnsense-plugin/www/rustproxy/src/opnsense/mvc/app/controllers/OPNsense/RustProxy/forms/general.xml b/opnsense-plugin/www/rustproxy/src/opnsense/mvc/app/controllers/OPNsense/RustProxy/forms/general.xml index 7d599f6..f7e8bdb 100644 --- a/opnsense-plugin/www/rustproxy/src/opnsense/mvc/app/controllers/OPNsense/RustProxy/forms/general.xml +++ b/opnsense-plugin/www/rustproxy/src/opnsense/mvc/app/controllers/OPNsense/RustProxy/forms/general.xml @@ -20,13 +20,13 @@ rustproxy.general.proxyAddress text - HTTP bind address. Leave empty for 0.0.0.0 or to keep the legacy combined listener after an upgrade. + HTTP bind address. Default: 0.0.0.0. Existing installations are migrated from the legacy combined listener automatically. rustproxy.general.proxyPort text - HTTP port passed as --proxy-listen. Leave empty for 8080 or to keep the legacy combined listener after an upgrade. + HTTP port passed as --proxy-listen. Default: 8080. @@ -44,13 +44,13 @@ rustproxy.general.tlsAddress text - HTTPS/TLS bind address. Leave empty for 0.0.0.0 or to keep the legacy combined listener after an upgrade. + HTTPS/TLS bind address. Default: 0.0.0.0. Existing installations are migrated automatically. rustproxy.general.tlsPort text - HTTPS/TLS port passed as --tls-listen. Leave empty for 8181 or to keep the legacy combined listener after an upgrade. + HTTPS/TLS port passed as --tls-listen. Default: 8181. @@ -62,13 +62,13 @@ rustproxy.general.adminAddress text - Administration bind address. Leave empty for 0.0.0.0 or to keep the legacy combined listener after an upgrade. + Administration bind address. Default: 0.0.0.0. Existing installations are migrated automatically. rustproxy.general.adminPort text - Administration port passed as --admin-listen. Leave empty for 9090 or to keep the legacy combined listener after an upgrade. + Administration port passed as --admin-listen. Default: 9090. rustproxy.general.allowRemoteAdmin diff --git a/opnsense-plugin/www/rustproxy/src/opnsense/mvc/app/models/OPNsense/RustProxy/Migrations/M1_4_0.php b/opnsense-plugin/www/rustproxy/src/opnsense/mvc/app/models/OPNsense/RustProxy/Migrations/M1_4_0.php new file mode 100644 index 0000000..202805c --- /dev/null +++ b/opnsense-plugin/www/rustproxy/src/opnsense/mvc/app/models/OPNsense/RustProxy/Migrations/M1_4_0.php @@ -0,0 +1,68 @@ + 65535) { + return null; + } + + return [$address, (string)$number]; + } + + private function migrateListener($general, $legacyField, $addressField, $portField) + { + $parts = $this->splitListener((string)$general->$legacyField); + if ($parts === null) { + return; + } + $general->$addressField = $parts[0]; + $general->$portField = $parts[1]; + } + + public function run($model) + { + parent::run($model); + + // Deliberately prefer valid 1.2.x values during this one migration. + // This also repairs hosts that already installed the broken 1.3.x model. + $this->migrateListener($model->general, 'proxyListen', 'proxyAddress', 'proxyPort'); + $this->migrateListener($model->general, 'tlsListen', 'tlsAddress', 'tlsPort'); + $this->migrateListener($model->general, 'adminListen', 'adminAddress', 'adminPort'); + } +} diff --git a/opnsense-plugin/www/rustproxy/src/opnsense/mvc/app/models/OPNsense/RustProxy/RustProxy.xml b/opnsense-plugin/www/rustproxy/src/opnsense/mvc/app/models/OPNsense/RustProxy/RustProxy.xml index 1e56de7..fa791fb 100644 --- a/opnsense-plugin/www/rustproxy/src/opnsense/mvc/app/models/OPNsense/RustProxy/RustProxy.xml +++ b/opnsense-plugin/www/rustproxy/src/opnsense/mvc/app/models/OPNsense/RustProxy/RustProxy.xml @@ -1,6 +1,6 @@ //OPNsense/rustproxy - 1.3.0 + 1.4.0 RustProxy service settings @@ -17,10 +17,14 @@ fields below for upgrade compatibility, but new UI writes these. --> + 0.0.0.0 + Y N Enter a valid HTTP bind address, for example 0.0.0.0. + 8080 + Y Enter a valid HTTP port between 1 and 65535. @@ -28,17 +32,25 @@ Y + 0.0.0.0 + Y N Enter a valid HTTPS/TLS bind address, for example 0.0.0.0. + 8181 + Y Enter a valid HTTPS/TLS port between 1 and 65535. + 0.0.0.0 + Y N Enter a valid administration bind address, for example 0.0.0.0. + 9090 + Y Enter a valid administration port between 1 and 65535. diff --git a/scripts/check.sh b/scripts/check.sh index 2eb4727..4030d7e 100755 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -64,6 +64,16 @@ grep -q 'rustproxy_resolve_listener' "$rc_script" grep -q 'rustproxy_valid_port' "$rc_script" grep -q 'pidfile="${rustproxy_run_dir}/daemon.pid"' "$rc_script" grep -q 'child_pidfile="${rustproxy_run_dir}/rustproxy.pid"' "$rc_script" +grep -q '1.4.0' "$model" +grep -q '0.0.0.0' "$model" +grep -q '8080' "$model" +grep -q '8181' "$model" +grep -q '9090' "$model" +grep -q 'class M1_4_0 extends BaseModelMigration' "$ROOT/opnsense-plugin/www/rustproxy/src/opnsense/mvc/app/models/OPNsense/RustProxy/Migrations/M1_4_0.php" +grep -q 'start_postcmd="rustproxy_poststart"' "$rc_script" +grep -q 'status_cmd="rustproxy_status"' "$rc_script" +grep -q 'RustProxy exec:' "$rc_script" +grep -q 'return 1;' "$ROOT/opnsense-plugin/www/rustproxy/src/opnsense/mvc/app/controllers/OPNsense/RustProxy/Api/ServiceController.php" grep -q '' "$model" grep -q '' "$model" grep -q '' "$model"