This commit is contained in:
Mateusz Gruszczyński committed 2026-10-07 09:23:17 +02:00
1 parent cce1081f75
commit 2b8f11ef8c
36 files changed
+1868 -309

No files matched your search

+276
View File
@@ -0,0 +1,276 @@
#!/bin/sh
# PROVIDE: rustproxy
# REQUIRE: LOGIN NETWORKING
# KEYWORD: shutdown
. /etc/rc.subr
name="rustproxy"
rcvar="${name}_enable"
load_rc_config "$name"
: ${rustproxy_enable:="NO"}
# RustProxy on OPNsense/FreeBSD runs as root. In practice the application
# needs access to its complete data/certificate state and service startup was
# unreliable after daemon(8) dropped privileges to the dedicated account.
: ${rustproxy_user:="root"}
: ${rustproxy_group:="wheel"}
: ${rustproxy_data_dir:="/var/db/rustproxy"}
: ${rustproxy_log_dir:="/var/log/rustproxy"}
: ${rustproxy_log_file:="${rustproxy_log_dir}/rustproxy.log"}
: ${rustproxy_run_dir:="/var/run/rustproxy"}
: ${rustproxy_command:="/usr/local/sbin/rust-proxy"}
: ${rustproxy_restart_delay:="5"}
: ${rustproxy_allow_remote_admin:="1"}
# FreeBSD uses jemalloc rather than glibc. Keep the same low-arena intent as
# Linux MALLOC_ARENA_MAX=2 with the native jemalloc knob. rc.conf can override
# rustproxy_malloc_conf or set it to an empty value to disable the tuning.
if [ "${rustproxy_malloc_conf+x}" != "x" ]; then
rustproxy_malloc_conf="${MALLOC_CONF:-narenas:2}"
fi
# Split listener settings written by the current OPNsense model.
: ${rustproxy_proxy_address:=""}
: ${rustproxy_proxy_port:=""}
: ${rustproxy_tls_enabled:="1"}
: ${rustproxy_tls_address:=""}
: ${rustproxy_tls_port:=""}
: ${rustproxy_admin_address:=""}
: ${rustproxy_admin_port:=""}
# Combined listener settings used by plugin model 1.2.x and earlier.
: ${rustproxy_proxy_listen_legacy:=""}
: ${rustproxy_tls_listen_legacy:=""}
: ${rustproxy_admin_listen_legacy:=""}
# Old rc.conf-style variable names are also accepted for hand-written configs.
: ${rustproxy_proxy_listen:=""}
: ${rustproxy_tls_listen:=""}
: ${rustproxy_admin_listen:=""}
enabled="0"
config_file="/usr/local/etc/rustproxy/opnsense.conf"
if [ -r "$config_file" ]; then
. "$config_file"
fi
if [ "$enabled" = "1" ]; then
rustproxy_enable="YES"
else
rustproxy_enable="NO"
fi
rustproxy_valid_port()
{
case "$1" in
''|*[!0-9]*) return 1 ;;
esac
[ "$1" -ge 1 ] 2>/dev/null && [ "$1" -le 65535 ] 2>/dev/null
}
rustproxy_valid_listener()
{
_rp_listener="$1"
case "$_rp_listener" in
\[*\]:*) _rp_port="${_rp_listener##*:}" ;;
*:*) _rp_port="${_rp_listener##*:}" ;;
*) return 1 ;;
esac
rustproxy_valid_port "$_rp_port"
}
rustproxy_format_listener()
{
_rp_address="$1"
_rp_port="$2"
case "$_rp_address" in
\[*\]) printf '%s:%s\n' "$_rp_address" "$_rp_port" ;;
*:*) printf '[%s]:%s\n' "$_rp_address" "$_rp_port" ;;
*) printf '%s:%s\n' "$_rp_address" "$_rp_port" ;;
esac
}
rustproxy_resolve_listener()
{
_rp_address="$1"
_rp_port="$2"
_rp_legacy="$3"
_rp_old_rc="$4"
_rp_default_address="$5"
_rp_default_port="$6"
_rp_name="$7"
# New split settings are authoritative as soon as either half is set.
if [ -n "$_rp_address" ] || [ -n "$_rp_port" ]; then
[ -n "$_rp_address" ] || _rp_address="$_rp_default_address"
[ -n "$_rp_port" ] || _rp_port="$_rp_default_port"
if ! rustproxy_valid_port "$_rp_port"; then
echo "Invalid RustProxy ${_rp_name} port: ${_rp_port}" >&2
return 1
fi
rustproxy_format_listener "$_rp_address" "$_rp_port"
return 0
fi
# Preserve a valid listener from plugin 1.2.x during upgrade.
if [ -n "$_rp_legacy" ] && rustproxy_valid_listener "$_rp_legacy"; then
printf '%s\n' "$_rp_legacy"
return 0
fi
# Preserve hand-written rc.conf settings as another compatibility path.
if [ -n "$_rp_old_rc" ] && rustproxy_valid_listener "$_rp_old_rc"; then
printf '%s\n' "$_rp_old_rc"
return 0
fi
# Malformed legacy values such as "0.0.0.0:" must never reach RustProxy.
# Fall back to a known-good listener and let the user set the separate port
# field in Services -> RustProxy.
rustproxy_format_listener "$_rp_default_address" "$_rp_default_port"
}
rustproxy_proxy_listen_resolved="$(rustproxy_resolve_listener \
"$rustproxy_proxy_address" "$rustproxy_proxy_port" \
"$rustproxy_proxy_listen_legacy" "$rustproxy_proxy_listen" \
"0.0.0.0" "8080" "HTTP")" || exit 1
rustproxy_tls_listen_resolved="$(rustproxy_resolve_listener \
"$rustproxy_tls_address" "$rustproxy_tls_port" \
"$rustproxy_tls_listen_legacy" "$rustproxy_tls_listen" \
"0.0.0.0" "8181" "HTTPS/TLS")" || exit 1
rustproxy_admin_listen_resolved="$(rustproxy_resolve_listener \
"$rustproxy_admin_address" "$rustproxy_admin_port" \
"$rustproxy_admin_listen_legacy" "$rustproxy_admin_listen" \
"0.0.0.0" "9090" "admin")" || exit 1
rustproxy_runtime_args="--data-dir ${rustproxy_data_dir} --admin-listen ${rustproxy_admin_listen_resolved} --update-check-interval-secs 0 serve --proxy-listen ${rustproxy_proxy_listen_resolved}"
if [ "$rustproxy_tls_enabled" = "1" ]; then
rustproxy_runtime_args="${rustproxy_runtime_args} --tls-listen ${rustproxy_tls_listen_resolved}"
fi
if [ "$rustproxy_allow_remote_admin" = "1" ]; then
rustproxy_runtime_args="${rustproxy_runtime_args} --allow-remote-admin"
fi
pidfile="${rustproxy_run_dir}/daemon.pid"
child_pidfile="${rustproxy_run_dir}/rustproxy.pid"
command="/usr/sbin/daemon"
rustproxy_daemon_user_arg=""
if [ "$rustproxy_user" != "root" ]; then
rustproxy_daemon_user_arg="-u ${rustproxy_user}"
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()
{
# RustProxy on OPNsense/FreeBSD uses jemalloc. MALLOC_ARENA_MAX is a
# glibc/Linux setting and has no useful effect here, so export MALLOC_CONF
# instead. daemon(8) inherits this environment and passes it to RustProxy.
if [ -n "${rustproxy_malloc_conf}" ]; then
MALLOC_CONF="${rustproxy_malloc_conf}"
export MALLOC_CONF
else
unset MALLOC_CONF
fi
# /var/run is ephemeral and recreated on boot.
/usr/bin/install -d -o "${rustproxy_user}" -g "${rustproxy_group}" -m 0750 "${rustproxy_run_dir}"
/usr/sbin/chown "${rustproxy_user}:${rustproxy_group}" "${rustproxy_run_dir}"
/bin/chmod 0750 "${rustproxy_run_dir}"
/usr/bin/install -d -o "${rustproxy_user}" -g "${rustproxy_group}" -m 0700 "${rustproxy_data_dir}"
/usr/sbin/chown "${rustproxy_user}:${rustproxy_group}" "${rustproxy_data_dir}"
/bin/chmod 0700 "${rustproxy_data_dir}"
/usr/bin/install -d -o "${rustproxy_user}" -g "${rustproxy_group}" -m 0750 "${rustproxy_log_dir}"
/usr/bin/touch "${rustproxy_log_file}"
/usr/sbin/chown "${rustproxy_user}:${rustproxy_group}" "${rustproxy_log_file}"
/bin/chmod 0640 "${rustproxy_log_file}"
echo "RustProxy listeners: HTTP=${rustproxy_proxy_listen_resolved} TLS=${rustproxy_tls_listen_resolved} ADMIN=${rustproxy_admin_listen_resolved}"
if [ -n "${rustproxy_malloc_conf}" ]; then
echo "RustProxy allocator: MALLOC_CONF=${rustproxy_malloc_conf}"
fi
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()
{
/bin/rm -f "${child_pidfile}" "${pidfile}"
}
run_rc_command "$1"
+4
View File
@@ -0,0 +1,4 @@
#!/bin/sh
/usr/local/sbin/configctl template reload OPNsense/RustProxy >/dev/null 2>&1 || true
/usr/local/sbin/configctl rustproxy boot >/dev/null 2>&1 || true