#!/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"