#!/usr/bin/env sh set -eu role="${DOSH_ROLE:-both}" repo="${DOSH_REPO:-}" server="${DOSH_SERVER:-}" dosh_host="${DOSH_HOST:-${DOSH_DOSH_HOST:-}}" port="${DOSH_PORT:-50000}" prefix="${PREFIX:-$HOME/.local}" from_current=0 start_server=1 force_config=0 update_cache="${DOSH_UPDATE_CACHE:-$HOME/.cache/dosh/source}" usage() { cat <<'EOF' Usage: install.sh [server|client|both] [options] Options: --repo URL Git repository to clone when not run from a checkout --server HOST Default SSH target for client config, for example user@host --dosh-host HOST UDP host for Dosh packets when different from SSH target --port PORT Dosh UDP port; default 50000 --prefix DIR Install prefix; default ~/.local --update-cache DIR Persistent source checkout for incremental updates --no-start Install server but do not start it --force-config Rewrite existing ~/.config/dosh/*.toml files Environment alternatives: DOSH_REPO, DOSH_ROLE, DOSH_SERVER, DOSH_HOST, DOSH_PORT, PREFIX, DOSH_UPDATE_CACHE EOF } while [ "$#" -gt 0 ]; do case "$1" in server|client|both) role="$1" ;; --repo) repo="$2" shift ;; --server) server="$2" shift ;; --dosh-host) dosh_host="$2" shift ;; --port) port="$2" shift ;; --prefix) prefix="$2" shift ;; --update-cache) update_cache="$2" shift ;; --from-current) from_current=1 ;; --no-start) start_server=0 ;; --force-config) force_config=1 ;; -h|--help) usage exit 0 ;; *) echo "unknown argument: $1" >&2 usage >&2 exit 2 ;; esac shift done case "$role" in server|client|both) ;; *) echo "role must be server, client, or both" >&2 exit 2 ;; esac need() { if ! command -v "$1" >/dev/null 2>&1; then echo "missing required command: $1" >&2 exit 1 fi } ensure_cargo() { if command -v cargo >/dev/null 2>&1; then return fi need curl echo "cargo not found; installing Rust toolchain with rustup" >&2 curl --proto '=https' --tlsv1.2 -fsSL https://sh.rustup.rs | sh -s -- -y # shellcheck disable=SC1091 . "$HOME/.cargo/env" } ensure_cargo cleanup() { if [ -n "${tmpdir:-}" ]; then rm -rf "$tmpdir" fi } trap cleanup EXIT INT TERM if [ "$from_current" -eq 1 ] || [ -f Cargo.toml ]; then src_dir="$(pwd)" else if [ -z "$repo" ]; then echo "DOSH_REPO or --repo is required when running the installer from curl" >&2 exit 2 fi case "$update_cache" in ""|"/"|"$HOME"|"$HOME/"|"$HOME/.cache") echo "refusing unsafe update cache path: $update_cache" >&2 exit 2 ;; esac need git mkdir -p "$(dirname "$update_cache")" if [ -d "$update_cache/.git" ]; then git -C "$update_cache" remote set-url origin "$repo" git -C "$update_cache" fetch --depth 1 origin main git -C "$update_cache" checkout -q -B main FETCH_HEAD else rm -rf "$update_cache" git clone --depth 1 --branch main "$repo" "$update_cache" >/dev/null fi src_dir="$update_cache" fi cd "$src_dir" if [ "$role" = "client" ]; then cargo build --release --bin dosh-client else cargo build --release fi bindir="$prefix/bin" config_dir="$HOME/.config/dosh" data_dir="$HOME/.local/share/dosh" systemd_user_dir="$HOME/.config/systemd/user" mkdir -p "$bindir" "$config_dir" "$data_dir" install -m 0755 target/release/dosh-client "$bindir/dosh-client" ln -sf dosh-client "$bindir/dosh" if [ "$role" = "server" ] || [ "$role" = "both" ]; then install -m 0755 target/release/dosh-server "$bindir/dosh-server" install -m 0755 target/release/dosh-auth "$bindir/dosh-auth" fi if [ -f target/release/dosh-bench ]; then install -m 0755 target/release/dosh-bench "$bindir/dosh-bench" fi if [ "$role" = "server" ] || [ "$role" = "both" ]; then server_config="$config_dir/server.toml" if [ "$force_config" -eq 1 ] || [ ! -f "$server_config" ]; then login_shell="$( if command -v getent >/dev/null 2>&1; then getent passwd "$(id -un)" | awk -F: '{print $7}' fi )" login_shell="${login_shell:-${SHELL:-/bin/sh}}" cat >"$server_config" </dev/null 2>&1; then mkdir -p "$systemd_user_dir" sed "s#ExecStart=%h/.local/bin/dosh-server serve#ExecStart=$bindir/dosh-server serve#" \ packaging/systemd/dosh-server.service >"$systemd_user_dir/dosh-server.service" if [ "$start_server" -eq 1 ] && systemctl --user daemon-reload >/dev/null 2>&1; then systemctl --user enable --now dosh-server.service fi elif [ "$start_server" -eq 1 ]; then nohup "$bindir/dosh-server" serve >"$data_dir/dosh-server.log" 2>&1 & fi fi if [ "$role" = "client" ] || [ "$role" = "both" ]; then case ":$PATH:" in *":$bindir:"*) ;; *) if [ "$(uname -s)" = "Darwin" ] || [ "$(basename "${SHELL:-}")" = "zsh" ]; then shell_rc="$HOME/.zshrc" else shell_rc="$HOME/.profile" fi mkdir -p "$(dirname "$shell_rc")" if [ ! -f "$shell_rc" ] || ! grep -F "$bindir" "$shell_rc" >/dev/null 2>&1; then printf '\nexport PATH="%s:$PATH"\n' "$bindir" >>"$shell_rc" fi ;; esac client_config="$config_dir/client.toml" if [ "$force_config" -eq 1 ] || [ ! -f "$client_config" ]; then default_server="${server:-user@example.com}" update_repo="${repo:-https://git.palav.dev/Palav/dosh.git}" if [ -n "$dosh_host" ]; then dosh_host_line="dosh_host = \"$dosh_host\"" else dosh_host_line="# dosh_host = \"public.example.com\"" fi cat >"$client_config" <