From 4b8654a2b0edc90798372cba357f23b15b51657c Mon Sep 17 00:00:00 2001 From: Ahmed Abdelhalim Date: Thu, 16 Jul 2026 16:45:53 +0200 Subject: Add pve-ssh support with hardening --- roles/pve-lxc-ssh/defaults/main.yml | 2 + roles/pve-lxc-ssh/meta/argument_specs.yml | 12 ++++++ roles/pve-lxc-ssh/meta/main.yml | 11 +++++ roles/pve-lxc-ssh/tasks/main.yml | 69 ++++++++++++++++++++++++++++++ roles/pve-lxc-ssh/templates/sshd_config.j2 | 13 ++++++ roles/pve-lxc/tasks/main.yml | 6 +-- roles/ssh/tasks/main.yml | 15 ------- 7 files changed, 110 insertions(+), 18 deletions(-) create mode 100644 roles/pve-lxc-ssh/defaults/main.yml create mode 100644 roles/pve-lxc-ssh/meta/argument_specs.yml create mode 100644 roles/pve-lxc-ssh/meta/main.yml create mode 100644 roles/pve-lxc-ssh/tasks/main.yml create mode 100644 roles/pve-lxc-ssh/templates/sshd_config.j2 (limited to 'roles') diff --git a/roles/pve-lxc-ssh/defaults/main.yml b/roles/pve-lxc-ssh/defaults/main.yml new file mode 100644 index 00000000..621cf068 --- /dev/null +++ b/roles/pve-lxc-ssh/defaults/main.yml @@ -0,0 +1,2 @@ +--- +pve_lxc_ssh_port: 2222 diff --git a/roles/pve-lxc-ssh/meta/argument_specs.yml b/roles/pve-lxc-ssh/meta/argument_specs.yml new file mode 100644 index 00000000..6f03937d --- /dev/null +++ b/roles/pve-lxc-ssh/meta/argument_specs.yml @@ -0,0 +1,12 @@ +--- +argument_specs: + main: + options: + pve_lxc_id: + type: "int" + required: true + description: "PVE LXC container ID" + pve_lxc_ssh_port: + type: "int" + default: 2222 + description: "SSH port to configure inside the container" diff --git a/roles/pve-lxc-ssh/meta/main.yml b/roles/pve-lxc-ssh/meta/main.yml new file mode 100644 index 00000000..79d075ca --- /dev/null +++ b/roles/pve-lxc-ssh/meta/main.yml @@ -0,0 +1,11 @@ +--- +dependencies: [] +galaxy_info: + author: "a14m" + description: "Harden SSH on PVE LXC containers via pct exec" + license: "MIT" + min_ansible_version: "2.18" + platforms: + - name: "Debian" + versions: + - "bookworm" diff --git a/roles/pve-lxc-ssh/tasks/main.yml b/roles/pve-lxc-ssh/tasks/main.yml new file mode 100644 index 00000000..7a6314cb --- /dev/null +++ b/roles/pve-lxc-ssh/tasks/main.yml @@ -0,0 +1,69 @@ +--- +- name: "Install openssh" + become: true + ansible.builtin.command: + cmd: > + pct exec {{ pve_lxc_id }} -- sh -c + 'which sshd > /dev/null 2>&1 && exit 0; + . /etc/os-release; + case $ID in + alpine) apk add --no-cache openssh ;; + debian|ubuntu) apt-get install -y openssh-server ;; + *) echo "Unsupported distro: $ID" && exit 1 ;; + esac; + echo "installed"' + register: pve_lxc_ssh_install + changed_when: "'installed' in pve_lxc_ssh_install.stdout" + tags: + - "molecule-notest" + +- name: "Generate ssh host keys" + become: true + ansible.builtin.command: + cmd: > + pct exec {{ pve_lxc_id }} -- sh -c + '[ -f /etc/ssh/ssh_host_ed25519_key ] && exit 0; + ssh-keygen -q -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -C "" -N ""; + echo "generated"' + register: pve_lxc_ssh_keygen + changed_when: "'generated' in pve_lxc_ssh_keygen.stdout" + tags: + - "molecule-notest" + +- name: "Render sshd_config" + ansible.builtin.template: + src: "sshd_config.j2" + dest: "/tmp/sshd_config_{{ pve_lxc_id }}" + mode: "0600" + tags: + - "molecule-notest" + +- name: "Push sshd_config into container" + become: true + ansible.builtin.command: + cmd: pct push {{ pve_lxc_id }} /tmp/sshd_config_{{ pve_lxc_id }} /etc/ssh/sshd_config --perms 0640 + changed_when: true + tags: + - "molecule-notest" + +- name: "Remove temp sshd_config" + ansible.builtin.file: + path: "/tmp/sshd_config_{{ pve_lxc_id }}" + state: absent + tags: + - "molecule-notest" + +- name: "Enable and start sshd" + become: true + ansible.builtin.command: + cmd: > + pct exec {{ pve_lxc_id }} -- sh -c + '. /etc/os-release; + case $ID in + alpine) rc-update add sshd default; rc-service sshd restart ;; + debian|ubuntu) systemctl enable --now ssh; systemctl restart ssh ;; + *) echo "Unsupported distro: $ID" && exit 1 ;; + esac' + changed_when: false + tags: + - "molecule-notest" diff --git a/roles/pve-lxc-ssh/templates/sshd_config.j2 b/roles/pve-lxc-ssh/templates/sshd_config.j2 new file mode 100644 index 00000000..d8ccc6d2 --- /dev/null +++ b/roles/pve-lxc-ssh/templates/sshd_config.j2 @@ -0,0 +1,13 @@ +Port {{ pve_lxc_ssh_port }} +PermitRootLogin prohibit-password +PasswordAuthentication no +AuthenticationMethods publickey +PermitEmptyPasswords no +KbdInteractiveAuthentication no +ChallengeResponseAuthentication no +UsePAM no +X11Forwarding no +PrintMotd yes +AuthorizedKeysFile .ssh/authorized_keys +HostKey /etc/ssh/ssh_host_ed25519_key +Subsystem sftp /usr/lib/ssh/sftp-server diff --git a/roles/pve-lxc/tasks/main.yml b/roles/pve-lxc/tasks/main.yml index b719bfd0..12a2e814 100644 --- a/roles/pve-lxc/tasks/main.yml +++ b/roles/pve-lxc/tasks/main.yml @@ -64,9 +64,9 @@ debian|ubuntu) apt-get install -y python3 ;; *) echo "Unsupported distro: $ID" && exit 1 ;; esac; - echo "python3 installed"' - register: cgit_python_bootstrap - changed_when: "'python3 installed' in cgit_python_bootstrap.stdout" + echo "installed"' + register: pve_lxc_bootstrap + changed_when: "'installed' in pve_lxc_bootstrap.stdout" tags: # PVE API not available in containers — requires proxmox-ve package - "molecule-notest" diff --git a/roles/ssh/tasks/main.yml b/roles/ssh/tasks/main.yml index 7df9efe8..f60c2640 100644 --- a/roles/ssh/tasks/main.yml +++ b/roles/ssh/tasks/main.yml @@ -8,18 +8,6 @@ name: "{{ ssh_package }}" state: "present" -- name: "Generate /etc/ssh/ RSA host key" - become: true - ansible.builtin.command: - cmd: "ssh-keygen -q -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -C '' -N ''" - creates: "/etc/ssh/ssh_host_rsa_key" - -- name: "Generate /etc/ssh/ ECDSA host key" - become: true - ansible.builtin.command: - cmd: "ssh-keygen -q -t ecdsa -b 521 -f /etc/ssh/ssh_host_ecdsa_key -C '' -N ''" - creates: "/etc/ssh/ssh_host_ecdsa_key" - - name: "Generate /etc/ssh/ Ed25519 host key" become: true ansible.builtin.command: @@ -52,9 +40,6 @@ UsePAM no # default installation is yes PrintMotd yes # default installation is no - # Host key configurations - HostKey /etc/ssh/ssh_host_rsa_key - HostKey /etc/ssh/ssh_host_ecdsa_key HostKey /etc/ssh/ssh_host_ed25519_key # Default sshd_config -- cgit v1.2.3