这次是在 VPS 上通过 bin456789/reinstall 一键 DD 了新的 Alpine 3.23 系统。重装过程中选择创建普通用户 jay,也配置了登录密码。系统起来以后,确实可以用 jay 这个普通用户 SSH 登录。
问题出在登录后才发现:/home/ 下面没有正常的 jay 主目录,或者主目录存在但归属权限不对。后面切到 root 管理环境以后安装了基础工具:
apk update
apk upgrade
apk add curl nano nvim然后再回到普通用户使用 nvim 编辑脚本,就会遇到 Neovim 创建运行目录失败的问题。这个坑很隐蔽,因为 SSH 登录本身能成功,容易误以为普通用户环境已经完整初始化了。
现象
普通用户 jay 执行:
nvim alpine_user_ssh.shNeovim 报错大意是无法创建 /home/jay/.local 下面的目录,或者提示权限被拒。
这类报错说明重点不在 Neovim 本身,而在用户主目录:
/home/jay根本不存在;/home/jay存在,但所有者是root;$HOME指向/home/jay,但普通用户无法在里面创建.local、.cache、.config;- 后续
.ssh/authorized_keys、Neovim 缓存和配置目录都会一起受影响。
先确认问题
先用普通用户登录后检查当前身份和主目录变量:
whoami
echo "$HOME"
pwd
id正常情况下,whoami 应该输出:
jay$HOME 应该是:
/home/jay再检查 /etc/passwd 里记录的主目录:
grep '^jay:' /etc/passwd正常应该类似:
jay:x:1000:1000:Linux User,,,:/home/jay:/bin/ash然后检查主目录是否存在、归属是谁:
ls -ld /home /home/jay如果 /home/jay 不存在,会看到类似:
ls: /home/jay: No such file or directory如果目录被 root 占用,可能看到类似:
drwxr-xr-x 2 root root 4096 Jun 8 09:00 /home/jay这两种情况都会导致普通用户无法正常写入自己的配置、缓存和 SSH 目录。
用 root 修复主目录
因为 root 没有配置密码,也没有必要开放 root SSH 登录,所以这里的管理入口是先用普通用户 SSH 登录,再执行:
sudo -i进入 root 后,先确认用户存在:
id jay
grep '^jay:' /etc/passwd如果用户不存在,先不要继续套用下面的命令,应先回到用户创建流程排查。这里的前提是 jay 已经存在,只是主目录缺失或权限异常。
情况一:/home/jay 根本不存在
在 root 下执行:
install -d -o jay -g jay -m 755 /home/jay这条命令会创建 /home/jay,同时直接设置所有者、所属组和权限。相比先 mkdir 再 chown,它更不容易漏步骤。
情况二:/home/jay 存在但归属错误
如果目录存在,但所有者不是 jay,执行:
chown -R jay:jay /home/jay
chmod 755 /home/jaychown -R 的目的,是把主目录和里面已经生成的文件全部交还给 jay。如果之前用 root 在 /home/jay 下建过 .ssh、.local 或其它文件,不递归修复,普通用户后面还是会在某个子目录继续报权限错误。
修复后检查:
ls -ld /home/jay应看到类似:
drwxr-xr-x 2 jay jay 4096 Jun 8 09:10 /home/jay回到普通用户初始化基础目录
退出 root:
exit确认已经回到普通用户:
whoami
echo "$HOME"然后用普通用户身份创建 Neovim 需要的 XDG 目录:
mkdir -p "$HOME/.local/share/nvim"
mkdir -p "$HOME/.cache/nvim"
mkdir -p "$HOME/.config/nvim"这里不要加 sudo。这些目录是普通用户自己的运行目录、缓存目录和配置目录,如果用 root 创建,后面又会变成同一个权限坑。
验证 Neovim:
nvim alpine_user_ssh.sh能正常打开编辑器,就说明 /home/jay 的基础写入能力已经恢复。
同步修复 SSH 目录权限
这个问题也会影响普通用户的 SSH 密钥管理。建议一起把 .ssh 目录初始化好:
mkdir -p "$HOME/.ssh"
touch "$HOME/.ssh/authorized_keys"
chmod 700 "$HOME/.ssh"
chmod 600 "$HOME/.ssh/authorized_keys"再确认归属:
ls -ld "$HOME" "$HOME/.ssh"
ls -l "$HOME/.ssh/authorized_keys"正常应该都属于当前用户 jay。如果这里出现 root root,说明之前又用 root 写过普通用户目录,需要回到 root 下重新执行:
chown -R jay:jay /home/jay普通用户 SSH 密钥管理脚本
下面这个脚本适合在普通用户下运行,只管理当前用户自己的 ~/.ssh/authorized_keys,不修改系统级 SSH 配置,也不负责安装系统依赖。
脚本也保存到了本文同级 assets 目录:
使用方式:
nvim alpine_user_ssh.sh
chmod +x alpine_user_ssh.sh
./alpine_user_ssh.sh脚本内容如下:
#!/bin/ash
# 动态获取当前用户家目录
USER_HOME=$HOME
# 颜色定义
gl_lv='\033[32m'
gl_huang='\033[33m'
gl_hong='\033[31m'
gl_bai='\033[0m'
gl_hui='\e[37m'
# 检查依赖:普通用户无法使用 apk 安装,仅做缺失提示
init_check() {
if ! command -v curl >/dev/null 2>&1 || ! command -v nano >/dev/null 2>&1; then
echo -e "${gl_huang}警告: 系统缺失 curl 或 nano,部分功能受限,请联系管理员安装。${gl_bai}"
sleep 2
fi
}
# 获取 IP 地址
ip_address() {
ipv4_address=$(curl -s --connect-timeout 5 https://ipinfo.io/ip)
[ -z "$ipv4_address" ] && ipv4_address="VPS_IP"
}
# 确保目录权限正确
ensure_ssh_dir() {
[ ! -d "$USER_HOME/.ssh" ] && mkdir -p "$USER_HOME/.ssh"
chmod 700 "$USER_HOME/.ssh"
[ ! -f "$USER_HOME/.ssh/authorized_keys" ] && touch "$USER_HOME/.ssh/authorized_keys"
chmod 600 "$USER_HOME/.ssh/authorized_keys"
}
# 1. 生成新密钥对
add_sshkey() {
ensure_ssh_dir
local key_path="$USER_HOME/.ssh/sshkey"
ssh-keygen -t ed25519 -C "${USER}@vps" -f "$key_path" -N ""
cat "${key_path}.pub" >> "$USER_HOME/.ssh/authorized_keys"
ip_address
echo -e "\n${gl_lv}密钥对生成成功!${gl_bai}"
echo -e "请保存私钥,建议文件名: ${gl_huang}${ipv4_address}_${USER}_ssh.key${gl_bai}"
echo "------------------------------------------------"
cat "$key_path"
echo "------------------------------------------------"
printf "\n按回车继续..."
read dummy
}
# 2. 手动导入公钥
import_sshkey() {
ensure_ssh_dir
printf "${gl_hui}请粘贴公钥内容: ${gl_bai}"
read pub_content
if [ -z "$pub_content" ]; then
echo -e "${gl_hong}错误:输入内容为空${gl_bai}"
sleep 1
return 1
fi
echo "$pub_content" >> "$USER_HOME/.ssh/authorized_keys"
echo -e "${gl_lv}公钥导入完成${gl_bai}"
sleep 1
}
# 3. 从 GitHub 导入
import_github() {
ensure_ssh_dir
printf "${gl_hui}请输入 GitHub 用户名: ${gl_bai}"
read username
if [ -n "$username" ]; then
curl -fsSL "https://github.com/${username}.keys" >> "$USER_HOME/.ssh/authorized_keys"
echo -e "${gl_lv}GitHub 公钥导入尝试完成${gl_bai}"
sleep 1
fi
}
# 主菜单
sshkey_panel() {
init_check
while true; do
clear
echo -e "Alpine SSH 密钥管理面板 (当前用户: ${gl_lv}${USER}${gl_bai})"
echo "------------------------------------------------"
echo "1. 生成新密钥对 (ED25519)"
echo "2. 手动输入已有公钥"
echo "3. 从 GitHub 导入公钥"
echo "4. 编辑公钥文件 (authorized_keys)"
echo "5. 查看当前密钥信息"
echo "0. 退出"
echo "------------------------------------------------"
printf "请输入选择: "
read choice
case $choice in
1) add_sshkey ;;
2) import_sshkey ;;
3) import_github ;;
4) nano "$USER_HOME/.ssh/authorized_keys" ;;
5)
echo -e "\n${gl_huang}--- 已授权公钥 ---${gl_bai}"
[ -s "$USER_HOME/.ssh/authorized_keys" ] && cat "$USER_HOME/.ssh/authorized_keys" || echo "为空"
echo -e "\n${gl_huang}--- 本地私钥 (如有) ---${gl_bai}"
[ -f "$USER_HOME/.ssh/sshkey" ] && cat "$USER_HOME/.ssh/sshkey" || echo "未找到"
printf "\n按回车继续..."
read dummy
;;
0) exit 0 ;;
*) echo "无效选择"; sleep 1 ;;
esac
done
}
sshkey_panel以后重装后先做这组检查
以后只要是用一键 DD、reinstall、极简 Alpine 镜像、或者安装过程中创建普通用户,都建议在第一次登录后先跑这组命令:
whoami
echo "$HOME"
grep "^$USER:" /etc/passwd
ls -ld "$HOME"
touch "$HOME/.home-write-test" && rm "$HOME/.home-write-test"如果 touch 都失败,就先不要急着配置 Neovim、SSH key、Git、Docker 或其它用户级工具。先修主目录,否则后面每一步都会变成权限问题。
总结
这次的根因不是 nvim 配置坏了,也不是 SSH 密钥脚本有问题,而是普通用户 jay 的主目录没有被正确创建或没有正确归属给 jay。
稳定修复顺序是:
sudo -i
install -d -o jay -g jay -m 755 /home/jay
chown -R jay:jay /home/jay
exit
mkdir -p "$HOME/.local/share/nvim" "$HOME/.cache/nvim" "$HOME/.config/nvim"
mkdir -p "$HOME/.ssh"
touch "$HOME/.ssh/authorized_keys"
chmod 700 "$HOME/.ssh"
chmod 600 "$HOME/.ssh/authorized_keys"
nvim alpine_user_ssh.sh以后遇到类似问题,先看 /etc/passwd、$HOME、ls -ld /home/jay,不要只盯着 Neovim 报错本身。