Alpine 3.23 重装后普通用户没有主目录,导致 Neovim 和 SSH 密钥脚本报错的修复记录

记录使用 bin456789/reinstall 一键 DD Alpine 3.23 后,普通用户 jay 缺失或无法写入 /home/jay,导致 Neovim 无法创建 XDG 目录的诊断与修复流程。

这次是在 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.sh

Neovim 报错大意是无法创建 /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,同时直接设置所有者、所属组和权限。相比先 mkdirchown,它更不容易漏步骤。

情况二:/home/jay 存在但归属错误

如果目录存在,但所有者不是 jay,执行:

chown -R jay:jay /home/jay
chmod 755 /home/jay

chown -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$HOMEls -ld /home/jay,不要只盯着 Neovim 报错本身。