Files
2026-10-19 11:09:13 +02:00

136 lines
4.6 KiB
Bash

#!/bin/sh
# PROVIDE: rustproxy
# REQUIRE: LOGIN NETWORKING
# KEYWORD: shutdown
. /etc/rc.subr
name=rustproxy
rcvar=rustproxy_enable
load_rc_config "$name"
: ${rustproxy_enable:="NO"}
: ${rustproxy_user:="rustproxy"}
: ${rustproxy_group:="rustproxy"}
: ${rustproxy_data_dir:="/var/db/rustproxy"}
: ${rustproxy_log_dir:="/var/log/rustproxy"}
: ${rustproxy_run_dir:="/var/run/rustproxy"}
: ${rustproxy_config:=""}
: ${rustproxy_proxy_listen:="0.0.0.0:8080"}
: ${rustproxy_tls_listen:=""}
: ${rustproxy_admin_listen:="127.0.0.1:9090"}
: ${rustproxy_allow_remote_admin:="NO"}
: ${rustproxy_update_check_interval_secs:="3600"}
# rc.subr expands command_args; permit only simple shell-safe paths and
# IPv4 socket addresses to avoid command injection from rc.conf settings.
rustproxy_safe_path()
{
case "$1" in
/*) ;;
*) echo "RustProxy requires absolute paths: $1" >&2; return 1 ;;
esac
case "$1" in
*[!a-zA-Z0-9_./-]*) echo "Unsupported path characters: $1" >&2; return 1 ;;
esac
}
rustproxy_safe_listen()
{
case "$1" in
*[!0-9.:]*|''|*::*) echo "Only IPv4 host:port listeners are supported by this rc.d script: $1" >&2; return 1 ;;
*:*) ;;
*) echo "Missing listener port: $1" >&2; return 1 ;;
esac
}
case "${rustproxy_user}:${rustproxy_group}" in
*[!a-zA-Z0-9_:-]*) echo 'Unsupported user/group name' >&2; exit 1 ;;
esac
for rp_path in "$rustproxy_data_dir" "$rustproxy_log_dir" "$rustproxy_run_dir"; do
rustproxy_safe_path "$rp_path" || exit 1
done
if [ -n "$rustproxy_config" ]; then
rustproxy_safe_path "$rustproxy_config" || exit 1
fi
rustproxy_safe_listen "$rustproxy_proxy_listen" || exit 1
rustproxy_safe_listen "$rustproxy_admin_listen" || exit 1
if [ -n "$rustproxy_tls_listen" ]; then
rustproxy_safe_listen "$rustproxy_tls_listen" || exit 1
fi
case "$rustproxy_update_check_interval_secs" in
''|*[!0-9]*) echo 'Invalid update interval' >&2; exit 1 ;;
esac
rustproxy_bin="/usr/local/sbin/rust-proxy"
rustproxy_config_arg=""
if [ -n "$rustproxy_config" ]; then
rustproxy_config_arg="--config ${rustproxy_config}"
fi
rustproxy_args="--data-dir ${rustproxy_data_dir} ${rustproxy_config_arg} --admin-listen ${rustproxy_admin_listen} --update-check-interval-secs ${rustproxy_update_check_interval_secs} serve --proxy-listen ${rustproxy_proxy_listen}"
if [ -n "$rustproxy_tls_listen" ]; then
rustproxy_args="${rustproxy_args} --tls-listen ${rustproxy_tls_listen}"
fi
if checkyesno rustproxy_allow_remote_admin; then
rustproxy_args="${rustproxy_args} --allow-remote-admin"
fi
pidfile="${rustproxy_run_dir}/daemon.pid"
child_pidfile="${rustproxy_run_dir}/rustproxy.pid"
command="/usr/sbin/daemon"
command_args="-r -R 5 -H -P ${pidfile} -p ${child_pidfile} -u ${rustproxy_user} -o ${rustproxy_log_dir}/rustproxy.log ${rustproxy_bin} ${rustproxy_args}"
required_files="${rustproxy_bin}"
start_precmd="rustproxy_prestart"
stop_postcmd="rustproxy_poststop"
status_cmd="rustproxy_status"
extra_commands="reload"
reload_cmd="rustproxy_reload"
rustproxy_prestart()
{
/usr/bin/install -d -m 0750 -o "${rustproxy_user}" -g "${rustproxy_group}" "${rustproxy_run_dir}"
/usr/bin/install -d -m 0700 -o "${rustproxy_user}" -g "${rustproxy_group}" "${rustproxy_data_dir}"
/usr/bin/install -d -m 0750 -o "${rustproxy_user}" -g "${rustproxy_group}" "${rustproxy_log_dir}"
/usr/bin/touch "${rustproxy_log_dir}/rustproxy.log"
/usr/sbin/chown "${rustproxy_user}:${rustproxy_group}" "${rustproxy_log_dir}/rustproxy.log"
/bin/chmod 0640 "${rustproxy_log_dir}/rustproxy.log"
}
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_status()
{
if rp_pid=$(rustproxy_child_pid); then
echo "rustproxy is running as pid $rp_pid"
return 0
fi
echo 'rustproxy is not running'
return 1
}
rustproxy_reload()
{
rustproxy_child_pid >/dev/null || {
echo 'RustProxy is not running; cannot reload' >&2
return 1
}
# Change to the daemon's UID. Reload creates a short-lived SQLite session.
# A root-owned SQLite WAL would make the next reload/save fail.
rp_port="${rustproxy_admin_listen##*:}"
rp_command="${rustproxy_bin} --data-dir ${rustproxy_data_dir} ${rustproxy_config_arg} --admin-listen 127.0.0.1:${rp_port} reload"
/usr/bin/su -m "${rustproxy_user}" -c "exec ${rp_command}"
}
rustproxy_poststop()
{
/bin/rm -f "$child_pidfile" "$pidfile"
}
run_rc_command "$1"