Files
homelab-infra/infrastructure/samba-ad/ansible/roles/samba_ad_dc/tasks/main.yml
T
panxiao81 2e05b1a96a
yaml / yaml (pull_request) Failing after 25s
terraform / validate (pull_request) Successful in 51s
ansible / collection-test (pull_request) Successful in 1m27s
ansible / lint (pull_request) Successful in 3m45s
声明式管理 Proxmox API 对象与 Samba DNS 上游
2026-09-17 13:22:50 +00:00

212 lines
7.4 KiB
YAML

---
# Provision a Samba Active Directory Domain Controller.
# Idempotent: the provision step is guarded by the existence of the sam.ldb database,
# so re-running the playbook against an already-provisioned DC is a no-op there.
#
# DNS ordering is deliberate: the box keeps using its normal upstream resolver for
# apt + provisioning, and is only repointed at its OWN Samba DNS *after* samba-ad-dc
# is up and serving :53. That way an interruption can never strand the DC on dead DNS.
- name: Assert required variables are set
ansible.builtin.assert:
that:
- samba_ad_realm | length > 0
- samba_ad_domain | length > 0
- samba_ad_dc_ip | length > 0
- samba_ad_admin_password is defined
- samba_ad_admin_password | length >= 8
fail_msg: >-
Set samba_ad_realm/domain/dc_ip and provide samba_ad_admin_password from vault.
- name: Set hostname to the DC FQDN
ansible.builtin.hostname:
name: "{{ samba_ad_dc_hostname }}.{{ samba_ad_realm | lower }}"
- name: Pin DC FQDN to its real IP in /etc/hosts (never 127.0.1.1)
ansible.builtin.lineinfile:
path: /etc/hosts
regexp: '\s{{ samba_ad_dc_hostname }}\.{{ samba_ad_realm | lower | regex_escape }}\b'
line: "{{ samba_ad_dc_ip }} {{ samba_ad_dc_hostname }}.{{ samba_ad_realm | lower }} {{ samba_ad_dc_hostname }}"
state: present
- name: Install Samba AD DC packages
ansible.builtin.apt:
name: "{{ samba_ad_packages }}"
state: present
update_cache: true
- name: Ensure time sync is active (Kerberos dies on >5min skew)
ansible.builtin.service:
name: chrony
state: started
enabled: true
# --- Stop conflicting daemons --------------------------------------------------
- name: Disable distro smbd/nmbd/winbind (AD DC uses the unified samba service)
ansible.builtin.systemd:
name: "{{ item }}"
state: stopped
enabled: false
masked: false
loop:
- smbd
- nmbd
- winbind
failed_when: false
- name: Unmask samba-ad-dc service
ansible.builtin.systemd:
name: samba-ad-dc
masked: false
# --- Provision the domain (guarded) --------------------------------------------
- name: Check whether the domain is already provisioned
ansible.builtin.stat:
path: /var/lib/samba/private/sam.ldb
register: samba_sam_db
- name: Move stock smb.conf aside before first provision
ansible.builtin.command:
cmd: mv /etc/samba/smb.conf /etc/samba/smb.conf.orig
removes: /etc/samba/smb.conf
when: not samba_sam_db.stat.exists
- name: Provision the Active Directory domain
ansible.builtin.command:
argv:
- samba-tool
- domain
- provision
- "--use-rfc2307"
- "--realm={{ samba_ad_realm }}"
- "--domain={{ samba_ad_domain }}"
- "--server-role=dc"
- "--dns-backend=SAMBA_INTERNAL"
- "--adminpass={{ samba_ad_admin_password }}"
- "--option=dns forwarder = {{ samba_ad_dns_forwarder }}"
creates: /var/lib/samba/private/sam.ldb
no_log: true # keep the admin password out of logs
- name: 持续管理已初始化域控的 DNS 上游
ansible.builtin.import_tasks: dns_forwarder.yml
- name: Install the generated krb5.conf system-wide
ansible.builtin.copy:
src: /var/lib/samba/private/krb5.conf
dest: /etc/krb5.conf
remote_src: true
mode: "0644"
- name: Replace default LDAPS cert (positive serial + SANs) for modern Go clients
ansible.builtin.import_tasks: tls.yml
# --- Free port 53, then bring Samba's internal DNS online ----------------------
# Do this only now: up to here the box still resolves via its upstream (DHCP/cloud-init)
# resolver, so apt + provision above always had working DNS.
- name: Ensure resolved.conf.d drop-in directory exists
ansible.builtin.file:
path: /etc/systemd/resolved.conf.d
state: directory
mode: "0755"
- name: Disable systemd-resolved stub listener (frees :53 for Samba)
ansible.builtin.copy:
dest: /etc/systemd/resolved.conf.d/no-stub.conf
content: |
[Resolve]
DNSStubListener=no
mode: "0644"
register: stub_dropin
- name: Restart systemd-resolved to release :53 before Samba binds it
ansible.builtin.systemd:
name: systemd-resolved
state: restarted
when: stub_dropin is changed
- name: Enable and start samba-ad-dc
ansible.builtin.systemd:
name: samba-ad-dc
state: started
enabled: true
- name: Point the DC at its own Samba DNS (now that it is serving :53)
ansible.builtin.copy:
dest: /etc/resolv.conf
content: |
nameserver {{ samba_ad_dc_ip }}
search {{ samba_ad_realm | lower }}
follow: false
force: true
mode: "0644"
- name: Legacy client support (Win9x/NT4/2000/XP)
ansible.builtin.import_tasks: legacy.yml
when: samba_ad_legacy_clients | default(false) | bool
# --- Post-provision: reverse DNS zone (optional) -------------------------------
- name: Create reverse DNS zone
ansible.builtin.command:
cmd: >-
samba-tool dns zonecreate {{ samba_ad_dc_ip }} {{ samba_ad_reverse_zone }}
-U administrator%{{ samba_ad_admin_password }}
when: samba_ad_reverse_zone | length > 0
register: revzone
changed_when: "'already exists' not in (revzone.stderr | default(''))"
failed_when:
- revzone.rc != 0
- "'already exists' not in (revzone.stderr | default(''))"
no_log: true
- name: Register the DC's own PTR record in the reverse zone
ansible.builtin.command:
cmd: >-
samba-tool dns add {{ samba_ad_dc_ip }} {{ samba_ad_reverse_zone }}
{{ samba_ad_dc_ip.split('.')[3] }} PTR {{ samba_ad_dc_hostname }}.{{ samba_ad_realm | lower }}.
-U administrator%{{ samba_ad_admin_password }}
when: samba_ad_reverse_zone | length > 0
register: ptr_add
changed_when: "'Record added successfully' in (ptr_add.stdout | default(''))"
failed_when:
- ptr_add.rc != 0
- "'already exists' not in (ptr_add.stderr | default('')) + (ptr_add.stdout | default(''))"
no_log: true
# --- KMS auto-activation records (_vlmcs SRV → vlmcsd) --------------------------
- name: Register the KMS host A record (SRV target)
ansible.builtin.command:
cmd: >-
samba-tool dns add {{ samba_ad_dc_ip }} {{ samba_ad_realm | lower }}
{{ samba_ad_kms_hostname }} A {{ samba_ad_kms_host_ip }}
-U administrator%{{ samba_ad_admin_password }}
when: samba_ad_kms_host_ip | length > 0
register: kms_a
changed_when: "'Record added successfully' in (kms_a.stdout | default(''))"
failed_when:
- kms_a.rc != 0
- "'already exists' not in (kms_a.stderr | default('')) + (kms_a.stdout | default(''))"
no_log: true
- name: Register the _vlmcs._tcp SRV record for KMS auto-discovery
ansible.builtin.command:
cmd: >-
samba-tool dns add {{ samba_ad_dc_ip }} {{ samba_ad_realm | lower }}
_vlmcs._tcp SRV "{{ samba_ad_kms_hostname }}.{{ samba_ad_realm | lower }} {{ samba_ad_kms_port }} 0 100"
-U administrator%{{ samba_ad_admin_password }}
when: samba_ad_kms_host_ip | length > 0
register: kms_srv
changed_when: "'Record added successfully' in (kms_srv.stdout | default(''))"
failed_when:
- kms_srv.rc != 0
- "'already exists' not in (kms_srv.stderr | default('')) + (kms_srv.stdout | default(''))"
no_log: true
# --- Directory objects and explicitly managed DNS records ----------------------
- name: Service accounts and RBAC groups
ansible.builtin.import_tasks: directory_objects.yml
tags: [directory, accounts]
- name: Reconcile static AD DNS records
ansible.builtin.import_tasks: dns_records.yml
tags: [dns]