# ===================================================================================== # Samba AD Domain Controller - production shape. # # cp .env.example .env && chmod 600 .env # make build && make up && make verify # # WHY host networking by default # ---------------------------- # An AD DC writes *its own IP* into DNS A records and Windows clients then connect to # that IP on 88/389/445/3268 plus dynamically allocated DCE-RPC ports. NAT/port # publishing breaks that contract: the DC advertises an address the client cannot route # to, and group policy / Kerberos / secure channel fail in ways that look like auth bugs. # With network_mode: host, host IP == DC IP == the published record: self-consistent. # # Before `make up`: # * nothing may hold TCP/UDP 53 (systemd-resolved stub!), 88, 135, 139, 445, 3268 # * get the host a DHCP reservation. A DHCP lease change silently rots the DNS A record. # # Other modes: # AD_NETWORK_MODE=adlan -> use the named bridge below (lab; needs published ports) # macvlan -> see docs/docker-compose.macvlan.yml.example # ===================================================================================== name: windowsad x-ad-dc: &ad-dc image: local/samba-ad-dc:4.22-debian13 build: context: . dockerfile: image/Dockerfile args: SAMBA_VERSION: "2:4.22.11+dfsg-0+deb13u1" # bump deliberately, see README "Upgrades" env_file: - .env volumes: - ./conf:/etc/samba # smb.conf lives here so you can read it on the host - ./data/samba:/var/lib/samba # sam.ldb + SYSVOL + private keys -> BACK THIS UP - ./secrets:/run/ad-secrets:ro - /etc/localtime:/etc/localtime:ro # password expiry / logs follow host TZ stop_grace_period: 90s # let SMB sessions and the LDB/BDK close cleanly restart: unless-stopped # Least privilege this image actually runs with (validated by tests/smoke.sh). cap_drop: [ALL] cap_add: - CHOWN - FOWNER - SETUID - SETGID - DAC_OVERRIDE - NET_BIND_SERVICE - SYS_NICE - SYS_RESOURCE - AUDIT_WRITE # Required: Samba stores NT ACLs in the security.NTACL xattr, which the kernel # refuses without CAP_SYS_ADMIN inside a container (provisioning dies on SYSVOL ACLs). - SYS_ADMIN services: # ---- only / primary domain controller --------------------------------------------- ad-dc: <<: *ad-dc container_name: ${AD_CONTAINER:-ad-dc} hostname: ${AD_HOSTNAME:-dc1}.${AD_DNS_DOMAIN:-ad.example.com} network_mode: ${AD_NETWORK_MODE:-host} # ---- second domain controller (HA / replica) -------------------------------------- # Because this uses host networking, run this profile on a SECOND MACHINE with the repo # synced to it (or switch to macvlan so each DC gets its own LAN address). # In .env set: AD_HOSTNAME2=dc2 AD_IP= AD_JOIN_SERVER=dc1. # AD_JOIN_USER=administrator AD_JOIN_PASSWORD= # Then: docker compose --profile replica up -d ad-dc2: <<: *ad-dc profiles: ["replica"] container_name: ${AD_CONTAINER2:-ad-dc2} hostname: ${AD_HOSTNAME2:-dc2}.${AD_DNS_DOMAIN:-ad.example.com} network_mode: ${AD_NETWORK_MODE:-host} volumes: - ./conf-dc2:/etc/samba - ./data/samba-dc2:/var/lib/samba - ./secrets:/run/ad-secrets:ro - /etc/localtime:/etc/localtime:ro networks: # Only used when AD_NETWORK_MODE=adlan. Kept here so `make up` can be switched to a # sandboxed bridge without editing YAML. Real Win11 joins from the LAN will NOT work in # this mode - see docs/ for macvlan if you need LAN-reachable without host networking. adlan: name: adlan driver: bridge ipam: config: - subnet: 172.28.90.0/24