Archived
New script setup-linux-admin-user.sh creates the Linux system user, installs an SSH authorized key, and adds the user to the sudo group. Integrated into bootstrap.sh before harden-ssh.sh so key-based access is in place before password authentication is disabled. bootstrap.sh now accepts ADMIN_USER and ADMIN_SSH_KEY env vars to run user setup and setup-admin-sudo.sh automatically at the right point. audit.sh checks that at least one non-root user has an authorized key. docs/04-security-hardening.md updated with the new steps and ordering. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
83 lines
2.5 KiB
Bash
Executable File
83 lines
2.5 KiB
Bash
Executable File
#!/bin/bash
|
|
# Create a Linux system user for SSH access and sudo, and install their
|
|
# authorized SSH public key. Run this before harden-ssh.sh so that
|
|
# key-based access is in place before password authentication is disabled.
|
|
#
|
|
# Idempotent - safe to re-run. Run as root on the PVE host.
|
|
#
|
|
# Usage:
|
|
# ./setup-linux-admin-user.sh <username> <ssh-public-key>
|
|
# ./setup-linux-admin-user.sh <username> --key-file <path-to-.pub>
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
# shellcheck source=lib/common.sh
|
|
source "${SCRIPT_DIR}/lib/common.sh"
|
|
require_root
|
|
|
|
USERNAME="${1:-}"
|
|
if [ -z "$USERNAME" ]; then
|
|
echo "Usage: $0 <username> <ssh-public-key>" >&2
|
|
echo " $0 <username> --key-file <path-to-.pub>" >&2
|
|
exit 1
|
|
fi
|
|
|
|
shift
|
|
SSH_KEY=""
|
|
if [ "${1:-}" = "--key-file" ]; then
|
|
KEY_FILE="${2:-}"
|
|
[ -z "$KEY_FILE" ] && { echo "ERROR: --key-file requires a path." >&2; exit 1; }
|
|
[ -f "$KEY_FILE" ] || { echo "ERROR: key file not found: $KEY_FILE" >&2; exit 1; }
|
|
SSH_KEY="$(cat "$KEY_FILE")"
|
|
else
|
|
SSH_KEY="${1:-}"
|
|
fi
|
|
|
|
if [ -z "$SSH_KEY" ]; then
|
|
echo "ERROR: an SSH public key is required (key string or --key-file <path>)." >&2
|
|
exit 1
|
|
fi
|
|
|
|
if ! echo "$SSH_KEY" | grep -qE '^(ssh-rsa|ssh-ed25519|ecdsa-sha2-nistp[0-9]+) [A-Za-z0-9+/=]'; then
|
|
echo "ERROR: argument doesn't look like a valid SSH public key." >&2
|
|
exit 1
|
|
fi
|
|
|
|
# --- create Linux user if missing ---
|
|
if id "$USERNAME" >/dev/null 2>&1; then
|
|
echo "User '${USERNAME}' already exists - skipping useradd."
|
|
else
|
|
useradd --create-home --shell /bin/bash "$USERNAME"
|
|
echo "Created Linux user '${USERNAME}'."
|
|
fi
|
|
|
|
# --- sudo group membership ---
|
|
if id -nG "$USERNAME" | grep -qw sudo; then
|
|
echo "User '${USERNAME}' is already in the sudo group."
|
|
else
|
|
usermod --append --groups sudo "$USERNAME"
|
|
echo "Added '${USERNAME}' to the sudo group."
|
|
fi
|
|
|
|
# --- install authorized SSH key ---
|
|
HOME_DIR="$(getent passwd "$USERNAME" | cut -d: -f6)"
|
|
SSH_DIR="${HOME_DIR}/.ssh"
|
|
AUTH_FILE="${SSH_DIR}/authorized_keys"
|
|
|
|
mkdir -p "$SSH_DIR"
|
|
chmod 700 "$SSH_DIR"
|
|
touch "$AUTH_FILE"
|
|
chmod 600 "$AUTH_FILE"
|
|
chown -R "${USERNAME}:${USERNAME}" "$SSH_DIR"
|
|
|
|
if grep -qF "$SSH_KEY" "$AUTH_FILE" 2>/dev/null; then
|
|
echo "SSH key is already present in ${AUTH_FILE}."
|
|
else
|
|
echo "$SSH_KEY" >> "$AUTH_FILE"
|
|
echo "Installed SSH key in ${AUTH_FILE}."
|
|
fi
|
|
|
|
echo
|
|
echo "Linux user '${USERNAME}' is ready for SSH key-based login with sudo access."
|
|
echo "Next: run setup-admin-sudo.sh ${USERNAME} to grant NOPASSWD for pvesh/qm/pct."
|