- Bash
- adduser.sh
Adds user, generates keys, disables (local) password and generates a putty file. - E.g.: adduser.sh user123
- adduser.sh
#!/bin/bash
#
# Create a new user with SSH key pair (OpenSSH + PuTTY format)
#
set -euo pipefail
readonly BDIR="/home"
readonly KEY_TYPE="ed25519"
# ---------- output helpers ----------
if [[ -t 1 ]]; then
readonly BOLD=$(tput bold)
readonly NORMAL=$(tput sgr0)
readonly RED=$(tput setaf 1)
readonly GREEN=$(tput setaf 2)
else
readonly BOLD="" NORMAL="" RED="" GREEN=""
fi
die() { echo "${RED}Error:${NORMAL} $*" >&2; exit 1; }
info() { echo "$*"; }
# ---------- preflight ----------
[[ $EUID -eq 0 ]] || die "Must be run as root."
command -v puttygen >/dev/null || die "puttygen missing. Install putty-tools first!"
command -v ssh-keygen >/dev/null || die "ssh-keygen missing."
# ---------- args ----------
readonly NUSER="${1:-}"
[[ -n "$NUSER" ]] || die "Usage: $0 <username>"
[[ "$NUSER" =~ ^[a-z_][a-z0-9_-]*$ ]] || die "Invalid username: $NUSER"
readonly NHOME="${BDIR}/${NUSER}"
[[ ! -e "$NHOME" ]] || die "User or home already exists: $NHOME"
id "$NUSER" &>/dev/null && die "User already exists: $NUSER"
# ---------- password prompt ----------
read -rs -p "Password for key (empty for none): " password1; echo
if [[ -n "$password1" ]]; then
read -rs -p "Repeat password: " password2; echo
[[ "$password1" == "$password2" ]] || die "Password mismatch!"
unset password2
fi
# ---------- create user ----------
NPASS=$(tr -dc 'A-Za-z0-9_-' </dev/urandom | head -c 32)
useradd "$NUSER" -d "$NHOME" -m -p "$NPASS" -s /bin/bash
passwd -q -l "$NUSER"
unset NPASS
# ---------- ssh keys ----------
readonly SSHDIR="${NHOME}/.ssh"
readonly KEYFILE="${SSHDIR}/id_${KEY_TYPE}"
install -d -m 700 -o "$NUSER" -g "$NUSER" "$SSHDIR"
# Generate key with no passphrase first (avoids passing it on the command line).
ssh-keygen -t "$KEY_TYPE" -f "$KEYFILE" -N "" -C "${NUSER}@${HOSTNAME}" -q
# If a passphrase was requested, apply it now via stdin so it never appears
# in /proc/*/cmdline. ssh-keygen -p reads: <old_pass>\n<new_pass>\n<new_pass>\n
if [[ -n "$password1" ]]; then
printf '%s\n%s\n%s\n' "" "$password1" "$password1" \
| ssh-keygen -p -f "$KEYFILE" -q >/dev/null
fi
info "Generating PuTTY .ppk file..."
# puttygen also accepts the passphrase on stdin when --old-passphrase-file
# points to /dev/stdin. This avoids exposing it via argv too.
if [[ -n "$password1" ]]; then
puttygen "$KEYFILE" -o "${KEYFILE}.ppk" \
--old-passphrase /dev/stdin \
--new-passphrase /dev/stdin <<<"$password1"
else
puttygen "$KEYFILE" -o "${KEYFILE}.ppk"
fi
unset password1
install -m 600 -o "$NUSER" -g "$NUSER" \
"${KEYFILE}.pub" "${SSHDIR}/authorized_keys"
chown -R "${NUSER}:${NUSER}" "$SSHDIR"
chmod 600 "$KEYFILE" "${KEYFILE}.pub" "${KEYFILE}.ppk" "${SSHDIR}/authorized_keys"
# ---------- done ----------
info "${BOLD}PuTTY PPK:${NORMAL} ${GREEN}${KEYFILE}.ppk${NORMAL}"
info "Done adding ${BOLD}${NUSER}${NORMAL} at ${BOLD}${NHOME}${NORMAL}."