infra/setup-remote.sh
Tommy Rantti 1f111b78f3 Add rdp-test.sh for diagnosing the RDP auth failure
xfreerdp gives far more specific error output than GNOME Connections'
generic "Authentication failed: connection failed" message. Run on
the travel laptop, writes output to rdp-test-output.txt in this same
repo so it can just be committed/pushed back rather than pasted.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-26 21:54:59 +03:00

166 lines
5.3 KiB
Bash
Executable file

#!/usr/bin/env bash
set -uo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=lib.sh
source "$SCRIPT_DIR/lib.sh"
RDP_PORT=3389
TLS_DIR="/etc/gnome-remote-desktop/tls"
print_summary() {
local any_failed=0
print_summary_table || any_failed=1
if [ "$any_failed" = 1 ]; then
echo "One or more steps failed. Fix the issue above and re-run this script -"
echo "already-completed steps are safe to skip and will not be repeated."
exit 1
fi
echo "All steps OK or already satisfied."
echo
echo "================== next steps ======================"
echo "Connect from the travel laptop with GNOME Connections (or xfreerdp)"
echo "to this machine's tailscale address, port $RDP_PORT. You'll be asked"
echo "for the RDP username/password you just set - that gets you to the"
echo "actual login screen, where you still log in with your real account"
echo "password same as sitting at the machine."
echo "====================================================="
}
preflight_env() {
section "preflight: environment"
if [ "$(id -u)" = "0" ]; then
step_fail "environment check" "do not run as root - script uses sudo for the specific commands that need it"
print_summary
exit 1
fi
if ! command -v grdctl >/dev/null 2>&1; then
step_fail "environment check" "grdctl not found - this script targets a machine with gnome-remote-desktop installed"
print_summary
exit 1
fi
step_ok "environment check"
}
harden_firewall() {
section "firewall (restrict RDP to tailscale)"
if ! command -v ufw >/dev/null 2>&1; then
step_fail "firewall" "ufw not installed"
return
fi
if ! sudo ufw status | head -1 | grep -qi "^Status: active"; then
echo "ufw is currently inactive on this machine. Enabling it switches to a"
echo "deny-incoming-by-default posture, which could affect any other LAN"
echo "service here that doesn't already have an explicit allow rule."
echo "Rules that will be in place once enabled:"
sudo ufw show added
read -rp "Type 'yes' to enable ufw now: " confirm
if [ "$confirm" != "yes" ]; then
step_fail "firewall" "not confirmed - ufw left inactive, RDP rule not added"
return
fi
sudo ufw --force enable
fi
if sudo ufw status | grep -qF "${RDP_PORT}/tcp on tailscale0"; then
step_skip "firewall" "RDP already restricted to tailscale0"
return
fi
if sudo ufw allow in on tailscale0 to any port "$RDP_PORT" proto tcp; then
step_ok "firewall" "RDP (${RDP_PORT}/tcp) allowed on tailscale0 only"
else
step_fail "firewall" "ufw rule failed to apply"
fi
}
configure_tls() {
section "tls certificate"
sudo mkdir -p "$TLS_DIR"
if sudo test -f "$TLS_DIR/cert.pem" && sudo test -f "$TLS_DIR/key.pem"; then
step_skip "tls certificate" "already present at $TLS_DIR - not regenerating (would invalidate the fingerprint clients already trust)"
else
if sudo openssl req -x509 -newkey rsa:4096 -nodes \
-keyout "$TLS_DIR/key.pem" -out "$TLS_DIR/cert.pem" \
-days 3650 -subj "/CN=$(hostname)" >/tmp/grd-tls.log 2>&1; then
sudo chown gnome-remote-desktop:gnome-remote-desktop "$TLS_DIR/key.pem" "$TLS_DIR/cert.pem"
sudo chmod 600 "$TLS_DIR/key.pem"
sudo chmod 644 "$TLS_DIR/cert.pem"
step_ok "tls certificate" "self-signed cert generated at $TLS_DIR"
else
step_fail "tls certificate" "openssl req failed - see /tmp/grd-tls.log"
return
fi
fi
sudo grdctl --system rdp set-tls-cert "$TLS_DIR/cert.pem"
sudo grdctl --system rdp set-tls-key "$TLS_DIR/key.pem"
}
configure_credentials() {
section "rdp credentials"
local rdp_status
rdp_status=$(sudo grdctl --system rdp status --show-credentials 2>&1)
if ! echo "$rdp_status" | grep -q "Username: (null)"; then
step_skip "rdp credentials" "already configured - not touching an existing password"
return
fi
local rdp_user
read -rp "RDP username [$(whoami)]: " rdp_user
rdp_user="${rdp_user:-$(whoami)}"
echo "RDP password - a separate secret from your account login password,"
echo "gates only the initial RDP connection (you still log into the actual"
echo "session with your real account password afterwards). Not stored by"
echo "this script anywhere. Paste/type it, then press Enter and Ctrl-D:"
local rdp_pass
rdp_pass=$(cat)
rdp_pass="${rdp_pass//[[:space:]]/}"
if [ -z "$rdp_pass" ]; then
step_fail "rdp credentials" "empty password entered - not setting"
return
fi
if sudo grdctl --system rdp set-credentials "$rdp_user" "$rdp_pass"; then
step_ok "rdp credentials" "set for user $rdp_user"
else
step_fail "rdp credentials" "grdctl set-credentials failed"
fi
unset rdp_pass
}
enable_rdp() {
section "enable rdp backend"
sudo grdctl --system rdp set-port "$RDP_PORT"
sudo grdctl --system rdp disable-port-negotiation
if sudo grdctl --system rdp status 2>&1 | grep -qi "Status: *enabled"; then
step_skip "enable rdp backend" "already enabled"
return
fi
if sudo grdctl --system rdp enable; then
step_ok "enable rdp backend"
else
step_fail "enable rdp backend" "grdctl --system rdp enable failed"
fi
}
main() {
preflight_env
harden_firewall
configure_tls
configure_credentials
enable_rdp
print_summary
}
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi