Files
bash/scripts/linux_user_bootstrap.sh
T

111 lines
2.9 KiB
Bash

#!/usr/bin/env bash
#
# Create a Linux user and install an SSH public key.
#
# This script is designed for repeatable server onboarding. It creates the user
# if missing, prepares ~/.ssh, writes the authorized key, and can optionally add
# the user to a sudo-capable group.
#
# Usage:
# sudo bash linux_user_bootstrap.sh --user deploy --ssh-key "ssh-ed25519 AAAA..."
# sudo bash linux_user_bootstrap.sh --user deploy --ssh-key-file ./deploy.pub --sudo
#
# Options:
# --user NAME Linux username to create or update.
# --ssh-key KEY Public SSH key content.
# --ssh-key-file FILE File containing the public SSH key.
# --sudo Add the user to sudo or wheel group.
# --help Show this help message.
set -Eeuo pipefail
target_user=""
ssh_key=""
ssh_key_file=""
grant_sudo=false
usage() {
sed -n '2,21p' "$0" | sed 's/^# \{0,1\}//'
}
log() {
printf '[%s] %s\n' "$(date -Is)" "$*"
}
while [[ "$#" -gt 0 ]]; do
case "$1" in
--user)
target_user="${2:-}"
shift 2
;;
--ssh-key)
ssh_key="${2:-}"
shift 2
;;
--ssh-key-file)
ssh_key_file="${2:-}"
shift 2
;;
--sudo)
grant_sudo=true
shift
;;
--help|-h)
usage
exit 0
;;
*)
printf 'ERROR: unknown option: %s\n' "$1" >&2
usage >&2
exit 1
;;
esac
done
[[ "$(id -u)" -eq 0 ]] || { printf 'ERROR: this script must run as root.\n' >&2; exit 1; }
[[ "$target_user" =~ ^[a-z_][a-z0-9_-]*[$]?$ ]] || { printf 'ERROR: invalid Linux username: %s\n' "$target_user" >&2; exit 1; }
if [[ -n "$ssh_key_file" ]]; then
[[ -f "$ssh_key_file" ]] || { printf 'ERROR: SSH key file not found: %s\n' "$ssh_key_file" >&2; exit 1; }
ssh_key="$(< "$ssh_key_file")"
fi
[[ "$ssh_key" == ssh-* || "$ssh_key" == ecdsa-* ]] || { printf 'ERROR: a valid public SSH key is required.\n' >&2; exit 1; }
if id "$target_user" >/dev/null 2>&1; then
log "User already exists: ${target_user}"
else
log "Creating user: ${target_user}"
useradd --create-home --shell /bin/bash "$target_user"
fi
home_dir="$(getent passwd "$target_user" | cut -d: -f6)"
ssh_dir="${home_dir}/.ssh"
authorized_keys="${ssh_dir}/authorized_keys"
install -d -m 700 -o "$target_user" -g "$target_user" "$ssh_dir"
touch "$authorized_keys"
chmod 600 "$authorized_keys"
chown "$target_user:$target_user" "$authorized_keys"
if ! grep -qxF "$ssh_key" "$authorized_keys"; then
log "Installing SSH public key for ${target_user}"
printf '%s\n' "$ssh_key" >> "$authorized_keys"
fi
if [[ "$grant_sudo" == true ]]; then
if getent group sudo >/dev/null 2>&1; then
usermod -aG sudo "$target_user"
log "Added ${target_user} to sudo group."
elif getent group wheel >/dev/null 2>&1; then
usermod -aG wheel "$target_user"
log "Added ${target_user} to wheel group."
else
printf 'ERROR: no sudo or wheel group found.\n' >&2
exit 1
fi
fi
log "User bootstrap completed successfully."