#!/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