#!/usr/bin/env bash set -euo pipefail # start-media-server.sh # # Starts frankenphp with MEDIA_USER and MEDIA_PASS_HASH set. # Hash is generated via: # - system php (preferred) OR # - frankenphp php-cli (fallback) # # Usage: # ./start-media-server.sh --user admin --prompt [--port 9000] [--dir /path/to/docroot] # # Security: # Avoid --pass on command line; use --prompt or --pass-stdin to keep it out of `ps`/history. PORT="9000" USER="" PASS="" DOCROOT="" read_pass_stdin=false prompt=false usage() { cat <<'EOF' Usage: start-media-server.sh --user [--pass | --pass-stdin | --prompt] [--port ] [--dir ] Options: --user Username to set in MEDIA_USER (required) --pass

Password to hash (insecure: visible in process list & shell history) --pass-stdin Read password from stdin (safer) --prompt Prompt for password (safer; hidden input) --port

Listen port (default: 9000) --dir cd into docroot before starting (optional) -h, --help Show help Examples: ./start-media-server.sh --user admin --prompt --port 9000 --dir /home/me/samba-serv printf '%s\n' 'test123' | ./start-media-server.sh --user admin --pass-stdin EOF } have_cmd() { command -v "$1" >/dev/null 2>&1; } # Pick a PHP hashing command: # - If `php` exists: use it. # - Else if `frankenphp` exists and supports php-cli: use it. pick_php_runner() { if have_cmd php; then echo "php" return 0 fi if have_cmd frankenphp; then # Verify php-cli is available (frankenphp subcommand) 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 ;; --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 echo "Install php OR ensure frankenphp supports 'php-cli'." >&2 exit 127 } # Generate bcrypt hash without needing to escape $. # We pass the password via an env var P to avoid quoting surprises in -r strings. 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 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)" echo exec frankenphp php-server --listen ":$PORT"