2026-02-02 14:05:21 -05:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
PORT="9000"
|
|
|
|
|
USER=""
|
|
|
|
|
PASS=""
|
|
|
|
|
DOCROOT=""
|
2026-02-03 13:19:20 -05:00
|
|
|
MEDIA_ROOT_ARG=""
|
2026-02-02 14:05:21 -05:00
|
|
|
|
|
|
|
|
read_pass_stdin=false
|
|
|
|
|
prompt=false
|
|
|
|
|
|
|
|
|
|
usage() {
|
|
|
|
|
cat <<'EOF'
|
|
|
|
|
Usage:
|
2026-02-03 13:19:20 -05:00
|
|
|
start-media-server.sh --user <username> [--pass <password> | --pass-stdin | --prompt]
|
|
|
|
|
[--media-root <path>] [--port <port>] [--dir <docroot>]
|
2026-02-02 14:05:21 -05:00
|
|
|
|
|
|
|
|
Options:
|
2026-02-03 13:19:20 -05:00
|
|
|
--user <u> Username to set in MEDIA_USER (required)
|
|
|
|
|
--pass <p> Password to hash (insecure: visible in process list & shell history)
|
|
|
|
|
--pass-stdin Read password from stdin (safer)
|
|
|
|
|
--prompt Prompt for password (safer; hidden input)
|
|
|
|
|
--media-root <p> Base directory containing Videos/ and Music/ (recommended)
|
|
|
|
|
--port <p> Listen port (default: 9000)
|
|
|
|
|
--dir <path> cd into docroot before starting (optional)
|
|
|
|
|
-h, --help Show help
|
2026-02-02 14:05:21 -05:00
|
|
|
|
|
|
|
|
Examples:
|
2026-02-03 13:19:20 -05:00
|
|
|
./start-media-server.sh --user admin --prompt --media-root /mnt/media --port 9000 --dir /home/me/samba-serv
|
|
|
|
|
printf '%s\n' 'test123' | ./start-media-server.sh --user admin --pass-stdin --media-root /mnt/media
|
2026-02-02 14:05:21 -05:00
|
|
|
EOF
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
have_cmd() { command -v "$1" >/dev/null 2>&1; }
|
|
|
|
|
|
|
|
|
|
pick_php_runner() {
|
|
|
|
|
if have_cmd php; then
|
|
|
|
|
echo "php"
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if have_cmd frankenphp; then
|
|
|
|
|
if frankenphp php-cli -v >/dev/null 2>&1; then
|
|
|
|
|
echo "frankenphp php-cli"
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
return 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (($#)); do
|
|
|
|
|
case "$1" in
|
|
|
|
|
--user) USER="${2-}"; shift 2 ;;
|
|
|
|
|
--pass) PASS="${2-}"; shift 2 ;;
|
|
|
|
|
--pass-stdin) read_pass_stdin=true; shift ;;
|
|
|
|
|
--prompt) prompt=true; shift ;;
|
2026-02-03 13:19:20 -05:00
|
|
|
--media-root) MEDIA_ROOT_ARG="${2-}"; shift 2 ;;
|
2026-02-02 14:05:21 -05:00
|
|
|
--port) PORT="${2-}"; shift 2 ;;
|
|
|
|
|
--dir) DOCROOT="${2-}"; shift 2 ;;
|
|
|
|
|
-h|--help) usage; exit 0 ;;
|
|
|
|
|
*)
|
|
|
|
|
echo "Unknown argument: $1" >&2
|
|
|
|
|
usage
|
|
|
|
|
exit 2
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
if [[ -z "$USER" ]]; then
|
|
|
|
|
echo "Error: --user is required" >&2
|
|
|
|
|
usage
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if $read_pass_stdin && $prompt; then
|
|
|
|
|
echo "Error: choose only one of --pass-stdin or --prompt" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [[ -z "$PASS" ]]; then
|
|
|
|
|
if $read_pass_stdin; then
|
|
|
|
|
IFS= read -r PASS
|
|
|
|
|
elif $prompt; then
|
|
|
|
|
read -r -s -p "Password: " PASS
|
|
|
|
|
echo
|
|
|
|
|
else
|
|
|
|
|
echo "Error: provide --pass, --pass-stdin, or --prompt" >&2
|
|
|
|
|
usage
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if ! [[ "$PORT" =~ ^[0-9]+$ ]] || ((PORT < 1 || PORT > 65535)); then
|
|
|
|
|
echo "Error: invalid --port '$PORT'" >&2
|
|
|
|
|
exit 2
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if ! have_cmd frankenphp; then
|
|
|
|
|
echo "Error: frankenphp not found in PATH" >&2
|
|
|
|
|
exit 127
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
PHP_RUNNER="$(pick_php_runner)" || {
|
|
|
|
|
echo "Error: neither 'php' nor 'frankenphp php-cli' is available for hashing" >&2
|
|
|
|
|
exit 127
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Generate bcrypt hash without needing to escape $.
|
|
|
|
|
MEDIA_PASS_HASH="$(
|
|
|
|
|
P="$PASS" $PHP_RUNNER -r 'echo password_hash(getenv("P"), PASSWORD_BCRYPT), PHP_EOL;'
|
|
|
|
|
)"
|
|
|
|
|
|
|
|
|
|
export MEDIA_USER="$USER"
|
|
|
|
|
export MEDIA_PASS_HASH
|
|
|
|
|
|
2026-02-03 13:19:20 -05:00
|
|
|
# Export MEDIA_ROOT if provided
|
|
|
|
|
if [[ -n "${MEDIA_ROOT_ARG}" ]]; then
|
|
|
|
|
export MEDIA_ROOT="${MEDIA_ROOT_ARG}"
|
|
|
|
|
fi
|
|
|
|
|
|
2026-02-02 14:05:21 -05:00
|
|
|
if [[ -n "$DOCROOT" ]]; then
|
|
|
|
|
cd "$DOCROOT"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo "Using PHP runner: $PHP_RUNNER"
|
|
|
|
|
echo "Starting frankenphp on :$PORT"
|
|
|
|
|
echo "MEDIA_USER=$MEDIA_USER"
|
|
|
|
|
echo "MEDIA_PASS_HASH set (bcrypt)"
|
2026-02-03 13:19:20 -05:00
|
|
|
if [[ -n "${MEDIA_ROOT:-}" ]]; then
|
|
|
|
|
echo "MEDIA_ROOT=$MEDIA_ROOT"
|
|
|
|
|
else
|
|
|
|
|
echo "MEDIA_ROOT not set (get_files.php / serve_media.php will error)"
|
|
|
|
|
fi
|
2026-02-02 14:05:21 -05:00
|
|
|
echo
|
|
|
|
|
|
|
|
|
|
exec frankenphp php-server --listen ":$PORT"
|
|
|
|
|
|