334 lines
8.2 KiB
Bash
Executable File
334 lines
8.2 KiB
Bash
Executable File
#!/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}"
|
|
quiet="${DOSH_UPDATE_QUIET:-0}"
|
|
|
|
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
|
|
[ "$quiet" = "1" ] && echo "Updating Dosh source"
|
|
git -C "$update_cache" remote set-url origin "$repo"
|
|
if [ "$quiet" = "1" ]; then
|
|
git -C "$update_cache" fetch -q --depth 1 origin main
|
|
else
|
|
git -C "$update_cache" fetch --depth 1 origin main
|
|
fi
|
|
git -C "$update_cache" checkout -q -B main FETCH_HEAD
|
|
else
|
|
[ "$quiet" = "1" ] && echo "Downloading Dosh source"
|
|
rm -rf "$update_cache"
|
|
if [ "$quiet" = "1" ]; then
|
|
git clone -q --depth 1 --branch main "$repo" "$update_cache" >/dev/null
|
|
else
|
|
git clone --depth 1 --branch main "$repo" "$update_cache" >/dev/null
|
|
fi
|
|
fi
|
|
src_dir="$update_cache"
|
|
fi
|
|
|
|
cd "$src_dir"
|
|
[ "$quiet" = "1" ] && echo "Building Dosh $role"
|
|
if [ "$role" = "client" ]; then
|
|
if [ "$quiet" = "1" ]; then
|
|
cargo build -q --release --bin dosh-client
|
|
else
|
|
cargo build --release --bin dosh-client
|
|
fi
|
|
else
|
|
if [ "$quiet" = "1" ]; then
|
|
cargo build -q --release
|
|
else
|
|
cargo build --release
|
|
fi
|
|
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" <<EOF
|
|
port = $port
|
|
bind = "0.0.0.0"
|
|
scrollback = 5000
|
|
auth_ttl_secs = 30
|
|
attach_ticket_ttl_secs = 3600
|
|
allow_attach_tickets = true
|
|
client_timeout_secs = 86400
|
|
retransmit_window = 256
|
|
default_input_mode = "read-write"
|
|
prewarm_sessions = ["default"]
|
|
create_on_attach = true
|
|
shell = "$login_shell"
|
|
sessions_dir = "~/.local/share/dosh/sessions"
|
|
secret_path = "~/.config/dosh/secret"
|
|
native_auth = true
|
|
host_key = "~/.config/dosh/host_key"
|
|
authorized_keys = ["~/.ssh/authorized_keys", "~/.config/dosh/authorized_keys"]
|
|
native_auth_rate_limit_per_minute = 30
|
|
allow_tcp_forwarding = true
|
|
allow_remote_forwarding = false
|
|
allow_agent_forwarding = false
|
|
EOF
|
|
fi
|
|
|
|
if command -v systemctl >/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" <<EOF
|
|
update_repo = "$update_repo"
|
|
update_port = $port
|
|
server = "$default_server"
|
|
$dosh_host_line
|
|
ssh_auth_command = "~/.local/bin/dosh-auth"
|
|
# ssh_port = 22
|
|
dosh_port = $port
|
|
default_session = "new"
|
|
reconnect_timeout_secs = 5
|
|
view_only = false
|
|
predict = false
|
|
cache_attach_tickets = true
|
|
credential_cache = "~/.local/share/dosh/credentials"
|
|
auth_preference = "native,ssh"
|
|
trust_on_first_use = false
|
|
native_auth_timeout_ms = 700
|
|
known_hosts = "~/.config/dosh/known_hosts"
|
|
identity_files = ["~/.ssh/id_ed25519"]
|
|
use_ssh_agent = true
|
|
forward_agent = false
|
|
EOF
|
|
fi
|
|
|
|
hosts_config="$config_dir/hosts.toml"
|
|
if [ "$force_config" -eq 1 ] || [ ! -f "$hosts_config" ]; then
|
|
default_server="${server:-user@example.com}"
|
|
if [ -n "$dosh_host" ]; then
|
|
host_udp="$dosh_host"
|
|
else
|
|
host_udp="$default_server"
|
|
fi
|
|
cat >"$hosts_config" <<EOF
|
|
# Example:
|
|
# [palav]
|
|
# ssh = "palav"
|
|
# dosh_host = "palav.dev"
|
|
# port = 50000
|
|
# default_command = "tm"
|
|
# predict = false
|
|
|
|
[default]
|
|
ssh = "$default_server"
|
|
dosh_host = "$host_udp"
|
|
port = $port
|
|
predict = false
|
|
EOF
|
|
fi
|
|
fi
|
|
|
|
cat <<EOF
|
|
Installed Dosh to $bindir
|
|
Configured UDP port $port
|
|
EOF
|
|
|
|
if [ "$role" = "client" ] || [ "$role" = "both" ]; then
|
|
cat <<EOF
|
|
|
|
Client command:
|
|
$bindir/dosh ${server:-user@host}
|
|
EOF
|
|
fi
|
|
|
|
if [ "$role" = "server" ] || [ "$role" = "both" ]; then
|
|
cat <<EOF
|
|
|
|
Server command:
|
|
$bindir/dosh-server serve
|
|
EOF
|
|
fi
|