diff --git a/playbooks/roles/vhosts/common/tasks/include_gpu.yaml b/playbooks/roles/vhosts/common/tasks/addons/gpu.yml similarity index 78% rename from playbooks/roles/vhosts/common/tasks/include_gpu.yaml rename to playbooks/roles/vhosts/common/tasks/addons/gpu.yml index 09f86bf..804eefd 100644 --- a/playbooks/roles/vhosts/common/tasks/include_gpu.yaml +++ b/playbooks/roles/vhosts/common/tasks/addons/gpu.yml @@ -1,5 +1,6 @@ -- name: Add NVIDIA repositories - shell: | +--- +- name: Addon(GPU) | add NVIDIA repositories + ansible.builtin.shell: | add-apt-repository -y ppa:graphics-drivers distribution=$(. /etc/os-release;echo $ID$VERSION_ID) curl -s -L https://nvidia.github.io/libnvidia-container/gpgkey | apt-key add - @@ -7,13 +8,15 @@ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | apt-key add - curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | tee /etc/apt/sources.list.d/nvidia-docker.list apt-get update + become: true -- name: Install NVIDIA driver and container runtime - apt: - name: +- name: Addon(GPU) | install NVIDIA driver and container runtime + ansible.builtin.apt: + name: - nvidia-modprobe - nvidia-driver-535 - nvidia-headless-535 - nvidia-container-toolkit state: present update_cache: yes + become: true diff --git a/playbooks/roles/vhosts/common/tasks/configure_s3fs.yml b/playbooks/roles/vhosts/common/tasks/addons/s3fs.yml similarity index 100% rename from playbooks/roles/vhosts/common/tasks/configure_s3fs.yml rename to playbooks/roles/vhosts/common/tasks/addons/s3fs.yml diff --git a/playbooks/roles/vhosts/common/tasks/common_debian.yml b/playbooks/roles/vhosts/common/tasks/common_debian.yml new file mode 100644 index 0000000..8743f83 --- /dev/null +++ b/playbooks/roles/vhosts/common/tasks/common_debian.yml @@ -0,0 +1,15 @@ +--- +- name: Common(Debian) | repo & keys + ansible.builtin.include_tasks: repo_setup.yml + vars: + repo_config: "{{ repo.apt | default({}) }}" + when: (repo.apt.enabled | default(false)) | bool + tags: [repo, baseline] + +- name: Common(Debian) | packages + ansible.builtin.include_tasks: packages.yml + vars: + package_config: "{{ packages.apt | default({}) }}" + package_manager: apt + when: (packages.apt.enabled | default(false)) | bool + tags: [pkgs, baseline] diff --git a/playbooks/roles/vhosts/common/tasks/common_redhat.yml b/playbooks/roles/vhosts/common/tasks/common_redhat.yml new file mode 100644 index 0000000..a9cf759 --- /dev/null +++ b/playbooks/roles/vhosts/common/tasks/common_redhat.yml @@ -0,0 +1,8 @@ +--- +- name: Common(RedHat) | packages + ansible.builtin.include_tasks: packages.yml + vars: + package_config: "{{ packages.yum | default({}) }}" + package_manager: dnf + when: (packages.yum.enabled | default(false)) | bool + tags: [pkgs, baseline] diff --git a/playbooks/roles/vhosts/common/tasks/main.yml b/playbooks/roles/vhosts/common/tasks/main.yml index 1397ce1..8cc69b2 100644 --- a/playbooks/roles/vhosts/common/tasks/main.yml +++ b/playbooks/roles/vhosts/common/tasks/main.yml @@ -1,81 +1,57 @@ -- name: Set timezone - shell: "timedatectl set-timezone Asia/Shanghai" +--- +# ===== Base system (always) ===== +- name: Base | set timezone + ansible.builtin.command: "timedatectl set-timezone Asia/Shanghai" + changed_when: false + become: true -- name: Render hostname file +- name: Base | render /etc/hostname ansible.builtin.template: src: templates/hostname.j2 dest: /etc/hostname owner: root group: root mode: "0644" + become: true -- name: Set hostname using modern module - hostname: +- name: Base | set hostname + ansible.builtin.hostname: name: "{{ inventory_hostname }}" + become: true -- name: Update /etc/hosts - template: src=templates/hosts dest=/etc/hosts owner=root group=root mode=0644 force=yes unsafe_writes=yes +- name: Base | update /etc/hosts + ansible.builtin.template: + src: templates/hosts + dest: /etc/hosts + owner: root + group: root + mode: "0644" + become: true -- name: Run secure_ssh.sh script - script: files/secure_ssh.sh +- name: Base | harden ssh + ansible.builtin.script: files/secure_ssh.sh + become: true -- name: "Common | Run on Debian family only" +# ===== Common baseline (OS split) ===== +- name: Common | Debian family baseline + ansible.builtin.import_tasks: common_debian.yml when: - enable_common | bool - - ansible_facts.os_family == 'Debian' - vars: - apt_repo_config: "{{ repo.apt | default({}) }}" - apt_package_config: "{{ packages.apt | default({}) }}" - block: - - name: "Common | Repo & keys" - ansible.builtin.include_tasks: repo_setup.yml - when: apt_repo_config.enabled | default(false) | bool - vars: - repo_config: "{{ apt_repo_config }}" - tags: [repo, baseline] + - ansible_facts.os_family == "Debian" - - name: "Common | Packages" - ansible.builtin.include_tasks: packages.yml - when: apt_package_config.enabled | default(false) | bool - vars: - package_config: "{{ apt_package_config }}" - package_manager: apt - tags: [pkgs, baseline] - - - name: "Common | S3FS 挂载" - ansible.builtin.include_tasks: configure_s3fs.yml - when: s3fs_enable | default(false) | bool - vars: - s3fs_config: "{{ s3fs_config | default({}) }}" - tags: [s3fs, mount] - -- name: "Common | Run on RedHat family only" +- name: Common | RedHat family baseline + ansible.builtin.import_tasks: common_redhat.yml when: - enable_common | bool - - ansible_facts.os_family == 'RedHat' - vars: - yum_package_config: "{{ packages.yum | default({}) }}" - block: - - name: "Common | Packages" - ansible.builtin.include_tasks: packages.yml - when: yum_package_config.enabled | default(false) | bool - vars: - package_config: "{{ yum_package_config }}" - package_manager: dnf - tags: [pkgs, baseline] + - ansible_facts.os_family == "RedHat" -#- name: Include GPU Configuration -# include_tasks: include_gpu.yaml -# when: (ansible_facts['distribution'] == "Ubuntu") or (ansible_facts['distribution'] == "Debian") -# tags: -# - k3s -# - gpu -# - nvidia +# ===== Add-ons (default OFF) ===== +- name: Addon | S3FS mount + ansible.builtin.import_tasks: addons/s3fs.yml + when: s3fs_enable | default(false) | bool + tags: [s3fs, mount] -#- name: enable ip_forward -# shell: 'echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf; echo "net.ipv4.conf.all.proxy_arp = 1" >> /etc/sysctl.conf ; sysctl -p /etc/sysctl.conf' - - -#- name: Install packages -# shell: "yum makecache && yum install -y audit container-selinux" -# when: (ansible_facts['distribution'] != "Ubuntu") or (ansible_facts['distribution'] != "Debian") +- name: Addon | GPU configuration + ansible.builtin.import_tasks: addons/gpu.yml + when: gpu_enable | default(false) | bool + tags: [gpu, nvidia] diff --git a/playbooks/roles/vhosts/common/tasks/repo_setup.yml b/playbooks/roles/vhosts/common/tasks/repo_setup.yml index be0a7dd..f9c6bd9 100644 --- a/playbooks/roles/vhosts/common/tasks/repo_setup.yml +++ b/playbooks/roles/vhosts/common/tasks/repo_setup.yml @@ -1,137 +1,115 @@ --- -- name: Normalize apt repo config +- name: Repo | normalize apt repo config ansible.builtin.set_fact: - apt_repo_config: "{{ { + apt_repo: "{{ { 'key_dir': '/etc/apt/keyrings', 'enable_universe': false, 'auto_update_cache': true, - 'keyrings': [], + 'cache_valid_time': 3600, + 'bootstrap_packages': ['ca-certificates', 'gnupg'], 'legacy_paths': [], 'entries': [] } | combine(repo_config | default({}), recursive=True) }}" -# 0) 统一 keyring 路径 -- name: Ensure keyring dir exists +- name: Repo | ensure keyring dir ansible.builtin.file: - path: "{{ apt_repo_config.key_dir }}" + path: "{{ apt_repo.key_dir }}" state: directory owner: root group: root - mode: '0755' + mode: "0755" become: true -# 0.1) 确保 dearmor 可用 -- name: Ensure gnupg is present for dearmor +- name: Repo | ensure bootstrap packages (for key download/dearmor) ansible.builtin.apt: - name: gnupg + name: "{{ apt_repo.bootstrap_packages }}" state: present - update_cache: false + update_cache: true + cache_valid_time: "{{ apt_repo.cache_valid_time }}" + when: (apt_repo.bootstrap_packages | default([])) | length > 0 become: true -# 0.2) 声明式 keyring 管理 -- name: "Manage declared apt keyrings" - ansible.builtin.include_tasks: manage_keyring.yml - when: (apt_repo_config.keyrings | default([])) | length > 0 - loop: "{{ apt_repo_config.keyrings | default([]) }}" - loop_control: - loop_var: apt_keyring - label: "{{ apt_keyring.name | default(apt_keyring.dest | default('custom-keyring')) }}" - vars: - keyring_dest: "{{ apt_keyring.dest | default(apt_repo_config.key_dir ~ '/' ~ apt_keyring.name ~ '.gpg') }}" - keyring_ascii: "{{ apt_keyring.asc_path | default(apt_repo_config.key_dir ~ '/' ~ apt_keyring.name ~ '.asc') }}" - keyring_state: "{{ apt_keyring.state | default('present') }}" - tags: [repo, baseline] - -# 1) 清理历史遗留 -- name: Remove legacy repo/keyring paths +- name: Repo | remove legacy repo/keyring paths ansible.builtin.file: path: "{{ item }}" state: absent - loop: "{{ apt_repo_config.legacy_paths | default([]) }}" + loop: "{{ apt_repo.legacy_paths | default([]) }}" become: true -# 2) Ubuntu 可选 universe -- name: Enable Ubuntu 'universe' component (Ubuntu only) - ansible.builtin.apt_repository: - repo: "deb http://archive.ubuntu.com/ubuntu {{ ansible_distribution_release }} main universe" - state: present - filename: "ubuntu-{{ ansible_distribution_release }}-universe" +# Ubuntu 可选 universe(补齐 updates/security) +- name: Repo | enable Ubuntu universe (optional) + become: true when: - - ansible_facts.distribution == 'Ubuntu' - - apt_repo_config.enable_universe | default(false) | bool - become: true - -# 3) 每个仓库:下载 key(可选)→ dearmor(可选)→ 添加 .list(含 signed-by) -- name: "Fetch ASCII key (if key_url provided)" - ansible.builtin.get_url: - url: "{{ repo.key_url }}" - dest: "{{ apt_repo_config.key_dir }}/{{ repo.name }}.asc" - mode: '0644' - when: repo.key_url is defined and repo.key_url | length > 0 - loop: "{{ apt_repo_config.entries | default([]) }}" - loop_control: - loop_var: repo - label: "{{ repo.name }}" - become: true - -- name: "Dearmor key" - ansible.builtin.command: - cmd: "gpg --dearmor -o {{ apt_repo_config.key_dir }}/{{ repo.name }}.gpg {{ apt_repo_config.key_dir }}/{{ repo.name }}.asc" - creates: "{{ apt_repo_config.key_dir }}/{{ repo.name }}.gpg" - when: repo.key_url is defined and repo.key_url | length > 0 - loop: "{{ apt_repo_config.entries | default([]) }}" - loop_control: - loop_var: repo - label: "{{ repo.name }}" - become: true - -- name: "Ensure keyring permission" - ansible.builtin.file: - path: "{{ (repo.signed_by | default(apt_repo_config.key_dir ~ '/' ~ repo.name ~ '.gpg')) }}" - owner: root - group: root - mode: '0644' - state: file - when: (repo.key_url is defined and repo.key_url | length > 0) or (repo.signed_by is defined) - loop: "{{ apt_repo_config.entries | default([]) }}" - loop_control: - loop_var: repo - label: "{{ repo.name }}" - become: true - -- name: "Cleanup repo specific paths" - when: repo.cleanup is defined and (repo.cleanup | length > 0) - become: true - loop: "{{ apt_repo_config.entries | default([]) }}" - loop_control: - loop_var: repo - label: "{{ repo.name }}" + - ansible_facts.distribution == "Ubuntu" + - apt_repo.enable_universe | bool block: - - name: "Cleanup repo specific path" + - name: Repo | universe main + ansible.builtin.apt_repository: + repo: "deb http://archive.ubuntu.com/ubuntu {{ ansible_distribution_release }} universe" + filename: "ubuntu-{{ ansible_distribution_release }}-universe" + state: present + + - name: Repo | universe updates + ansible.builtin.apt_repository: + repo: "deb http://archive.ubuntu.com/ubuntu {{ ansible_distribution_release }}-updates universe" + filename: "ubuntu-{{ ansible_distribution_release }}-universe" + state: present + + - name: Repo | universe security + ansible.builtin.apt_repository: + repo: "deb http://security.ubuntu.com/ubuntu {{ ansible_distribution_release }}-security universe" + filename: "ubuntu-{{ ansible_distribution_release }}-universe" + state: present + +# 声明式添加自定义仓库:key_url -> dearmor -> add repo +- name: Repo | configure declared apt repositories + become: true + loop: "{{ apt_repo.entries | default([]) }}" + loop_control: + loop_var: repo + label: "{{ repo.name }}" + when: repo.enabled | default(false) | bool + block: + - name: Repo | fetch ASCII key (optional) + ansible.builtin.get_url: + url: "{{ repo.key_url }}" + dest: "{{ apt_repo.key_dir }}/{{ repo.name }}.asc" + mode: "0644" + when: repo.key_url is defined and (repo.key_url | length > 0) + + - name: Repo | dearmor key (optional) + ansible.builtin.command: + cmd: "gpg --dearmor -o {{ apt_repo.key_dir }}/{{ repo.name }}.gpg {{ apt_repo.key_dir }}/{{ repo.name }}.asc" + creates: "{{ apt_repo.key_dir }}/{{ repo.name }}.gpg" + when: repo.key_url is defined and (repo.key_url | length > 0) + + - name: Repo | ensure keyring permission + ansible.builtin.file: + path: "{{ repo.signed_by | default(apt_repo.key_dir ~ '/' ~ repo.name ~ '.gpg') }}" + owner: root + group: root + mode: "0644" + state: file + when: (repo.key_url is defined and (repo.key_url | length > 0)) or (repo.signed_by is defined) + + - name: Repo | cleanup repo specific paths (optional) ansible.builtin.file: path: "{{ item }}" state: absent - loop: "{{ repo.cleanup }}" - loop_control: - label: "{{ repo.name }} -> {{ item }}" + loop: "{{ repo.cleanup | default([]) }}" + when: (repo.cleanup | default([])) | length > 0 -- name: "Add classic .list repo with signed-by" - ansible.builtin.apt_repository: - repo: >- - deb [signed-by={{ repo.signed_by | default(apt_repo_config.key_dir ~ '/' ~ repo.name ~ '.gpg') }}] - {{ repo.uri }} {{ repo.suite }} {{ (repo.components | default(['main'])) | join(' ') }} - filename: "{{ repo.name }}" - state: "{{ (repo.enabled | default(false) | bool) | ternary('present','absent') }}" - when: repo.enabled | default(false) | bool - loop: "{{ apt_repo_config.entries | default([]) }}" - loop_control: - loop_var: repo - label: "{{ repo.name }}" - become: true + - name: Repo | add apt repository (signed-by) + ansible.builtin.apt_repository: + repo: >- + deb [signed-by={{ repo.signed_by | default(apt_repo.key_dir ~ '/' ~ repo.name ~ '.gpg') }}] + {{ repo.uri }} {{ repo.suite }} {{ (repo.components | default(['main'])) | join(' ') }} + filename: "{{ repo.name }}" + state: present -# 4) 统一更新 apt cache(可控) -- name: Update apt cache after repo setup +- name: Repo | update apt cache after repo setup (optional) ansible.builtin.apt: update_cache: true - when: apt_repo_config.auto_update_cache | default(false) | bool + cache_valid_time: "{{ apt_repo.cache_valid_time }}" + when: apt_repo.auto_update_cache | bool become: true