--- - name: 等待首次用户初始化 ansible.builtin.command: argv: [incus, exec, "local:{{ incus_container }}", --, cloud-init, status, --wait] changed_when: false - name: 检查 SSH server 是否安装 ansible.builtin.command: argv: [incus, exec, "local:{{ incus_container }}", --, dpkg-query, -W, '-f=${Status}', openssh-server] register: container_ssh_package changed_when: false failed_when: container_ssh_package.rc not in [0, 1] - name: 刷新容器包索引 ansible.builtin.command: argv: [incus, exec, "local:{{ incus_container }}", --, apt-get, -o, Acquire::Retries=3, update] when: "'install ok installed' not in container_ssh_package.stdout" changed_when: true register: container_apt_update retries: 3 delay: 5 until: container_apt_update.rc == 0 - name: 安装 SSH server ansible.builtin.command: argv: [incus, exec, "local:{{ incus_container }}", --env, DEBIAN_FRONTEND=noninteractive, --, apt-get, -o, Acquire::Retries=3, install, -y, --no-install-recommends, openssh-server] when: "'install ok installed' not in container_ssh_package.stdout" changed_when: true register: container_apt_install retries: 3 delay: 5 until: container_apt_install.rc == 0 # cloud-init 在未安装 sshd 时预先生成了只有 PasswordAuthentication 的配置; # OpenSSH 默认 UsePAM=no 会拒绝锁定密码的公钥账号,显式采用 Ubuntu 的 PAM 模式。 - name: 读取 SSH 配置 ansible.builtin.command: argv: [incus, exec, "local:{{ incus_container }}", --, cat, /etc/ssh/sshd_config] register: container_sshd_config changed_when: false - name: 声明仅公钥 SSH 与 PAM 账号检查 ansible.builtin.command: argv: [incus, exec, "local:{{ incus_container }}", --, tee, /etc/ssh/sshd_config] stdin: "{{ container_sshd_desired }}" vars: container_sshd_desired: | UsePAM yes PubkeyAuthentication yes PasswordAuthentication no KbdInteractiveAuthentication no PermitRootLogin no Subsystem sftp internal-sftp when: container_sshd_config.stdout | trim != container_sshd_desired | trim register: container_sshd_write changed_when: true # 24.04 新装时只有 ssh.socket 运行,/run/sshd 要等 ssh.service 的 RuntimeDirectory 才创建, # 缺它时 sshd -t 直接失败;按同样的 0755 预建(/run 为 tmpfs,不留持久状态)。 - name: 校验 SSH 配置 ansible.builtin.command: argv: [incus, exec, "local:{{ incus_container }}", --, sh, -c, install -d -m 0755 /run/sshd && exec /usr/sbin/sshd -t] changed_when: false - name: 更新运行中的 SSH 配置 ansible.builtin.command: argv: [incus, exec, "local:{{ incus_container }}", --, systemctl, restart, ssh] when: container_sshd_write is changed changed_when: true - name: 检查 SSH service ansible.builtin.command: argv: [incus, exec, "local:{{ incus_container }}", --, systemctl, is-active, ssh] register: container_ssh_active changed_when: false failed_when: container_ssh_active.rc not in [0, 3, 4] - name: 检查 SSH 自启 ansible.builtin.command: argv: [incus, exec, "local:{{ incus_container }}", --, systemctl, is-enabled, ssh] register: container_ssh_enabled changed_when: false failed_when: container_ssh_enabled.rc not in [0, 1, 3, 4] - name: 启用 SSH ansible.builtin.command: argv: [incus, exec, "local:{{ incus_container }}", --, systemctl, enable, --now, ssh] when: container_ssh_active.rc != 0 or container_ssh_enabled.stdout != 'enabled' changed_when: true