Skip to content

Repository files navigation

ansible-samba-ad

Ansible Debian Samba Proxmox VE Tested with Vagrant

License: MIT Last commit Repo size GitLab mirror

Provision a Samba Active Directory domain on Debian 13 "trixie", end to end: an AD domain controller and a separate, domain-joined member file/print server, with optional Proxmox VE VM creation. Managed day-to-day from Windows RSAT.

The DC and the file server are deliberately separate hosts. A member server's vfs objects = acl_xattr / idmap config smb.conf is exactly what must never run on a DC (it breaks samba-ad-dc), so file and print services get their own box. Both are provisioned here.

What it deploys

Domain controller (domain_controllers group):

Component Purpose
samba-ad-dc KDC, LDAP, AD-integrated DNS (SAMBA_INTERNAL + forwarders), SYSVOL; FL 2016, --use-rfc2307
domain_seed Tier-0/1/2 OU tree, security groups, t0-admin, tier-0 PSO, baseline password policy, empty deny-logon GPOs linked to the tier OUs, NOT_DELEGATED on the built-in Administrator
domain_users End-user accounts with group membership; optional home drive and logon drive maps
chrony Signed NTP (MS-SNTP) for Windows clients
nftables Default-drop firewall, DC service ports only
samba_backup (opt-in) Nightly samba-tool domain backup online on a systemd timer

Member file/print server (file_servers group):

Component Purpose
samba (member) security = ADS, winbind, rid idmap, acl_xattr NT ACLs
samba_shares Data-driven SMB shares; SeDiskOperatorPrivilege to a storage-admin group; optional [homes]
samba_printers (opt-in) CUPS print sharing — driverless IPP (default) or legacy print$
nftables Default-drop firewall, SMB (+ IPP) only

Additional DCs (additional_dcs group) join for HA and pull SYSVOL from the PDC emulator over an SSH forced-command rsync on a timer.

Roles

Role Does
proxmox_vm Clones a Debian 13 cloud-init template over the API; idempotent on VMID, never destroys
os_base Hostname, /etc/hosts, resolv.conf, base packages; asserts a static IP
time_sync chrony — signed-NTP server on the DC, client on members
samba_ad_dc Provisions the first DC
domain_seed OU / group / admin / PSO / GPO model
domain_users End-user accounts, home drives, drive maps
samba_dc_join Joins an additional DC and bootstraps SYSVOL sync
samba_member_join Joins the member server (security = ADS)
samba_shares NT-ACL file shares and [homes]
samba_printers CUPS / Samba print sharing
acidnetworks.base_debian.base_firewall nftables host firewall (external) — SSH via mgmt tier, AD/SMB ports via the service-CIDR tier
samba_backup DC online-backup timer

Setup

1. Install collections

ansible-galaxy collection install -r requirements.yml

community.general; community.proxmox is only needed if the repo creates the VMs.

2. Generate the deploy key

Keys are gitignored — generate your own. The public half is injected into VMs created on Proxmox.

ssh-keygen -t ed25519 -f ~/.ssh/samba-ad-deploy -N "" -C "samba-ad-deploy"
cp ~/.ssh/samba-ad-deploy.pub files/ssh/deploy.pub

3. Set the vault

Edit inventory/group_vars/all/vault.yml (a plaintext stub) with real values, then encrypt it:

ansible-vault encrypt inventory/group_vars/all/vault.yml

Secrets: vault_administrator_password, vault_tier0_admin_password, vault_join_password, vault_user_initial_password, and — for Proxmox — vault_pve_api_token_secret.

4. Edit the inventory

Set the realm/NetBIOS, hosts and IPs. inventory/group_vars/all/main.yml holds the realm, the OU/group model, users, and drive maps; group_vars/file_servers.yml holds the share definitions. Put production hosts in inventory/hosts.yml, or use inventory/proxmox.yml to create them (below).

5. Provision — DC first, then member

ansible-playbook playbooks/provision-dc.yml --ask-vault-pass
ansible-playbook playbooks/provision-fileserver.yml --ask-vault-pass

Day-2 and HA:

ansible-playbook playbooks/join-dc.yml --ask-vault-pass   # add an HA DC + SYSVOL sync
ansible-playbook playbooks/shares.yml --ask-vault-pass    # change file shares only

Provision on Proxmox (create the VMs too)

site.yml clones the VMs from the cloud-init template pve_template_id, then provisions the DC and member. Create an API token (e.g. root@pam!ansible) with VM create/clone/config rights, put the secret in the vault, set the API host/node/storage and the per-host VMIDs/IPs in inventory/proxmox.yml, then:

ansible-playbook -i inventory/proxmox.yml site.yml --ask-vault-pass

Re-runs are idempotent; an existing VMID is left untouched. Teardown is manual (qm destroy <vmid>). A run that fails after the clone leaves a half-configured VM that a re-run will skip — qm destroy that VMID and re-run.

Manual steps (RSAT)

Two things can't be automated and need a Windows box with RSAT:

  • Deny-logon URA GPOs — the role creates and links empty tier GPOs; samba-tool can't write User Rights Assignment, so author the "Deny log on …" entries in GPME. Never link a deny-logon GPO at the domain root.
  • Printer install (print$ mode only) — pre-stage drivers; don't weaken Windows Point-and-Print hardening to make it work.

Point the client's DNS at the DC and its DNS suffix at the realm first.

Verify

On the DC:

sudo samba-tool domain info 127.0.0.1
sudo samba-tool domain level show            # 2016 / 2016
host -t SRV _ldap._tcp.<realm> 127.0.0.1

On the member:

sudo net ads testjoin                        # Join is OK
wbinfo -u | head                             # domain users resolve
smbclient -L //localhost -U administrator    # shares listed

Test (Vagrant, no Proxmox)

Two Debian 13 boxes (dc, fs) on a private network with a throwaway realm and plaintext test passwords — no vault. Run each playbook twice; the second run must report changed=0.

vagrant up
ansible-galaxy collection install -r requirements.yml                          # base_debian + hardening_debian
ansible-playbook -i inventory/vagrant.yml playbooks/provision-dc.yml
ansible-playbook -i inventory/vagrant.yml playbooks/provision-dc.yml           # changed=0
ansible-playbook -i inventory/vagrant.yml playbooks/provision-fileserver.yml
ansible-playbook -i inventory/vagrant.yml playbooks/provision-fileserver.yml   # changed=0
# Hardening layer (what site.yml runs last in prod), over dc + fs:
ansible-playbook -i inventory/vagrant.yml acidnetworks.hardening_debian.harden
ssh vagrant@10.99.0.10                                                         # DC must still answer
vagrant destroy -f

Per-role test playbooks live in tests/ (tests/test-<role>.yml).

Requirements

  • Ansible core ≥ 2.16 with community.general (plus community.proxmox to create the VMs).
  • Managed hosts: fresh Debian 13 with a static IP and clocks within Kerberos tolerance; os_base asserts the static IP and does not configure NICs.
  • An owned subdomain for the realm (e.g. ad.example.com) — never a .local realm.
  • Run from the repo root. If your shell exports ANSIBLE_ROLES_PATH or ANSIBLE_COLLECTIONS_PATH, unset them so ansible.cfg takes effect.

About

Ansible automation for a Samba Active Directory domain controller and domain-joined file/print server on Debian 13, with optional Proxmox VE provisioning.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages