Samba4 Domain Controller on Ubuntu 18.04

Quick Background

I volunteer as a Systems Administrator for a small medical clinic. They have a very slim IT budget so while their desktop systems are primarily Windows 11, I’ve configured most of their server infrastructure with Linux. A Proxmox server is used to manage their virtualized environment and I’m using Samba4 for their Active Directory Domain Controller.

When I first set up Samba4 as their Active Directory I was able to use CentOS 6 with the Samba4 binary packages from SerNet. Although this has been working well enough, it has always been a little quirky and I had only ever set up a single Domain Controller. So recently I decided to upgrade their Domain Controllers to the newest version and add a second Domain Controller.

Initially I tried to find the SerNet packages but it appears they have rebranded themselves as Samba+ and now charge a subscription fee for the binary packages. While I would love to support them, paying a subscription fee is not an option for this clinic.

I’d really like to stick with CentOS as the server distribution as I have a lot of experience with it and have always found it to be a solid, minimial distribution. However, for reasons RedHat has decided that the Samba4 build that comes with Fedora should not include the ability to act as an Active Directory Domain Controller.

I could build the sources from scratch and still use CentOS, but that would require installing all the build tools on each server and I’m trying to keep them as light as possible. Plus, building from scratch often introduces its own host of challenges and I really just want to set this up and move on to my next project. So instead I’m going to give a go at using Ubuntu, which I really like as a desktop system but have never been terribly thrilled with as a server system.

For setting this up I am mostly following the instructions from tecmint and specifically this one. However, these instructions were written for Ubuntu 16.04 so I’m making this post to document the steps I took in setting up Samba4 on an Ubuntu 18.04 system.

Networking overview

For reference, the main gateway is a pfSense system set up at 10.0.1.1. This runs as the primary DNS and DHCP server for the network. The domain name I’ll use in these instructions is hrakaroo.lan.

The Active Directory domain is ad.hrakaroo.lan. I’ve specifically set this up so that Active Directory is on it’s own sub domain as I don’t want the rest of the server infrastructure to be dependent on Active Directory. I’d rather isolate Active Directory to its own area.

Creating a new system in Proxmox

In Proxmox I’ve created the following new host

Hostname: adc1
Memory: 2 G
Disk: 32 G
Processors: 1
Cores: 2

In retrospect (by looking at the usage charts in Proxmox) it looks like I could have cut the memory, disk and cores in half and it would have been fine, but I’m going to leave it as is for now.

Once the vm is created, start the server.

Most of the installation is pretty straightforward so I’m only going to highlight when I didn’t select the default.

Installer update available

During the install it suggests that an update to the installer is available and asks if you want to update. I’m not sure if it matters much, but I said yes.

Networking

Edit the IPv4 configuration and select Manual

Subnet: 10.0.1.0/24
Address: 10.0.1.25
Gateway: 10.0.1.1
Name servers: 10.0.1.26
Search domains: ad.hrakaroo.lan

10.0.1.26 is the name servers for the existing Active Directory Domain Controller. Once the system is fully configured I’ll change this, but it makes the initial setup much easier if this points at your existing Domain Controller.

Profile Setup

This is the first thing I don’t like about Ubuntu. I’d rather just have a password set for the root account. I get the reason why they are doing this, but for a super small setup this is more of an annoyance than a help. Sadly you also can’t use general accounts like ‘admin’ or ‘staff’ either. So I ended up creating a personal account for Joshua Gerth. (This turned out to be a bit of a mistake, more on this can be found in the additional things at the bottom.)

SSH Setup

[X] Enable install the OpenSSH server.

Basic Server Configuration

For almost all of these commands I find it easier to work by ssh’ing into the box rather than using the Proxmox console as copy/paste and editing all work better.

Update and install emacs

Okay, once the server is up and running I always run the update commands to make sure everything is up to date:

$ sudo apt update 
$ sudo apt upgrade
$ sudo apt dist-upgrade

and also, because vi is terrible I always install emacs:

$ sudo apt install -y emacs

Turn off IPv6

This may not be necessary, but I find that debugging things when only IPv4 is enabled to be a lot easier. The environment I’m installing this in is small enough that we are not at risk of running out of IP numbers any time soon and since everything gets NAT’ed anyhow I don’t really see a need to enable IPv6.

That said, this is the second thing that I don’t care for about Ubuntu. In CentOS turning off IPv6 is sort of trivial, but on Ubuntu I this proved to be rather difficult. Most of the existing suggestions only turned off part of IPv6 and it was only after a lot of trial and error did I happen on a post with the best answer.

Basically you need to edit /etc/default/grub and set

  GRUB_CMDLINE_LINUX="xxxxx ipv6.disable=1"

(For me there was nothing in the xxxxx area, but if you have any existing options then leave them there and add the ipv6.disable at the end.)

and then run

$ update-grub

Turn off dnsmasq

This is the third thing that I don’t like about Ubuntu, it runs a stub dnsmasq as a DNS caching server. Again, I get why they did this, but I’ve never found this to be useful on a server and nine out of ten times it just causes problems.

To disable it I’m mostly following these instructions.

Edit /etc/systemd/resolved.conf and add

DNSStubListener=no

Then remove the existing symlink at /etc/resolv.conf and rebuild it

$ rm /etc/resolv.conf
$ ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf

Since this has been such a thorn in my side I prefer to reboot here to make damn sure the new settings have taken.

/etc/resolv.conf should now show the values that you entered on initial setup.

NTP

Domain Controllers are sensitive to clock drift and need to be configured to use a network time server. Normally I would configure ntpd on the host, but Ubuntu has decided to ship with timedatectl instead which claims to be a lightweight ntp client. (Humorously, 90% of the google searches for timedatectl suggest turning it off and replacing it with a real ntpd, however, I’m going to try sticking with timedatectl for now.)

First I like to set the timezone so I don’t need to convert everything

$ timedatectl set-timezone America/Los_Angeles

Now, edit the /etc/systemd/timesyncd.conf file and set the NTP entry to point to your NTP server. (I’m running an NTP server on another VM at 10.0.1.22).

[Time]
NTP=10.0.1.22

restart the timesyncd

$ systemctl restart systemd-timesyncd

and verify it with

$ cat /var/log/syslog | grep systemd-timesyncd
   XXX adc1 systemd-timesyncd[1416]: Synchronized to time server 10.0.1.22:123 (10.0.1.22).

Install Samba

Since we are actually about to install Samba I like to do one more reboot here.

Update the hosts file

The /etc/hosts file should have an entry for every domain controller, including itself. (I also removed the old IPv6 stuff)

127.0.0.1 localhost
10.0.1.25 adc1.ad.hrakaroo.lan adc1
10.0.1.26 oldadc.ad.hrakaroo.lan oldadc

Again, 10.0.1.25 is this box, the new Active Directory server and 10.0.1.26 is the old Active Directory server.

Install Samba4

Actually install samba

$ apt install -y samba krb5-user krb5-config winbind libpam-winbind libnss-winbind

If you already have things correctly setup then this should automatically find the kerberos SRV records for your domain which are being hosted on your existing Active Directory server, if not it may prompt you for them. If it does prompt you enter the domain in all upper case for the Default realm and in regular case for the Kerberos servers and Administrative server.

   Default Kerberos realm:  AD.HRAKAROO.LAN
   Kerberos servers realm:  ad.hrakaroo.lan
   Administrative server:   ad.hrakaroo.lan

Verify kerberos works by

$ kinit jgerth@AD.HRAKAROO.LAN
   Password for jgerth@AD.HRAKAROO.LAN:  <passwd>
$ klist
   Ticket cache: FILE:/tmp/krb5cc_0
   Default principal: jgerth@AD.HRAKAROO.LAN

   Valid starting     Expires            Service principal
   03/27/20 18:54:49  03/28/20 04:54:49  krbtgt/AD.HRAKAROO.LAN@AD.HRAKAROO.LAN
           renew until 03/28/20 18:54:46

Join the Domain

Remove the existing smb.conf as it will be recreated by samba-tool.

$ systemctl stop samba-ad-dc smbd nmbd winbind
$ mv /etc/samba/smb.conf /etc/samba/smb.conf.initial

Use samba-tool to join the domain

$ samba-tool domain join ad.hrakaroo.lan DC -U "AD\jgerth"

Now configure the server to start samba-ad-dc automatically

$ systemctl mask smbd nmbd winbind
   Created symlink /etc/systemd/system/smbd.service → /dev/null.
   Created symlink /etc/systemd/system/nmbd.service → /dev/null.
   Created symlink /etc/systemd/system/winbind.service → /dev/null.
$ systemctl unmask samba-ad-dc
   Removed /etc/systemd/system/samba-ad-dc.service.
$ systemctl enable samba-ad-dc

Use the host command to verify your configuration. This apparently hits every nameserver listed so you may get some errors when it tries to hit the non-active directory DNS servers.

$ host ad.hrakaroo.lan
   ad.hrakaroo.lan has address 10.0.1.26
   ad.hrakaroo.lan has address 10.0.1.25
   Host ad.hrakaroo.lan not found: 3(NXDOMAIN)
   Host ad.hrakaroo.lan not found: 3(NXDOMAIN)

$ host -t SRV _kerberos._udp.ad.hrakaroo.lan
   _kerberos._udp.ad.hrakaroo.lan has SRV record 0 100 88 oldadc.ad.hrakaroo.lan.
   _kerberos._udp.ad.hrakaroo.lan has SRV record 0 100 88 adc1.ad.hrakaroo.lan.

$ host -t SRV _ldap._tcp.ad.hrakaroo.lan
   _ldap._tcp.ad.hrakaroo.lan has SRV record 0 100 389 oldadc.ad.hrakaroo.lan.
   _ldap._tcp.ad.hrakaroo.lan has SRV record 0 100 389 adc1.ad.hrakaroo.lan.

Change DNS

At this point you could be done as the server is now up and running. However, it is technically using the other domain controller for DNS lookups. Even if I wasn’t planning on decommissioning the older server this would still be creating an out of band dependency between them and as Active Directory is, itself, a DNS server I prefer to update the server to use itself for DNS lookups. (Similar to what Ubuntu was initially trying to do with the dnsmasq stuff).

To do this, modify /etc/netplan and set 127.0.0.1 as first in your nameserver list and then the upstream DNS server second.

Also verify that search is set to use the ad domain first and then your global domain. Like this

            nameservers:
                addresses:
                - 127.0.0.1
                - 10.0.1.1
                search:
                - ad.hrakaroo.lan
                - hrakaroo.lan

As always, reboot and check the values in the /etc/resolv.conf and do a couple of tests with nslookup.

Configure Proxmox to boot the server

I also configure Proxmox to start the service at boot. This way if there is a power outage Proxmox will be sure to start your domain controllers.

Options -> Start at boot -> True

Additional things

Decommissioning the old Active Directory Controller

With the new Domain Controller up you can now decommission the old Domain Controller by moving the roles (7) from the old DC to your new one. However, the version of Samba which shipps with Ubuntu 18.04 is 4.7 which, apparently, has a bug with the python code that you use to move the roles. To fix this I had to edit /usr/lib/python2.7/dist-packages/samba/netcmd/fsmo.py

and insert line

import samba.drs_utils

just after

import samba

around line 20. After doing this the command to move the roles worked just fine and I was able to fully decommission the older active domain controller.

Removing the profile

It turns out that creating the profile as I did during the initial set up of Ubuntu was a bit of a mistake. It didn’t cause an issue for this server but it did on a file server I set up later which was also on Ubuntu. The issue was that the Ubuntu account jgerth conflicted with the Active Directory accouunt jgerth and made testing Windows File Sharing under my account difficult.

I could have addressed this by using a unique login on the Ubuntu server (like jogerth) but that feels like a pretty hacky solution. Plus, it raises the bigger issue that ultimately someday someone else is probably going to take over for me as the sysadmin and I don’t really want them to have to use my account. The right way to solve this is to create an LDAP server for the Linux boxes and host the logins centrally, but this feels a bit like overkill to me as we currently only have around 5 Linux systems and, at least for the time being, I would be the only person in the LDAP server.

I suppose I could bind the Linux boxes in to the Active Directory LDAP server, but that creates a bit of a chicken and egg dependency on Active Directory that I’m just not comfortable with.

What I really want is just a generic sysadmin account, but if you are going to do that then why not use the one that already comes with every Unix/Linux system, root. So in the end I configured an explicit password for root, enabled SSH login for root and deleted the account I created on setup. I would never recommend this for a larger environment, but for a small setup this worked out best.

Closing thoughts

In the end I’m glad I set this up from scratch rather than use the build and instructions from SerNet. I have a better understanding of what everything is doing and the weird quirkiness I was experiencing with the old server has gone away (although, to be fair, that could have been due to the older version I was running.) I also feel more comfortable with the samba tool and adding and removing domain controllers.

I’m still not a huge fan of Ubuntu as a server. I don’t care for the dnsmasq stub, the replacement for ntpd or how it forces you to create a non-root account, but since it is a popular system I was able to search for most of the errors I did encounter.

Supporting Windows 11 22H2

In the two years since I set this system up it has been running nearly flawlessly. The only real issue is that with Windows 11 update 22H2 Microsoft changed the encryption protocol (or something similar) and they are no longer able to bind to the domain controller. (This does not seem to impact existing systems that are already bound to the domain.)

The following Reddit link talks about the issue in depth https://www.reddit.com/r/sysadmin/comments/xoqend/samba_495_windows_11_22h2_kerberos/

The fix is to update Samba to version 4.16.0, which isn’t directly available for Ubuntu 18.04. The recommended path is probably to upgrade to Ubuntu 22.x, but since that’s bound to cause it’s own host of complications I instead opted to just change the source for Samba by following these instructions

https://ubunlog.com/en/ya-fue-liberada-la-nueva-version-de-samba-4-16-0-y-estos-son-sus-cambios/

sudo add-apt-repository ppa:linux-schools/samba-latest
sudo apt-get update
sudo apt install samba

This was enough to upgrade samba on 18.04 to 4.16.0. Once I restarted both domain controllers the Windows 11 with update 22H2 system was able to bind to the Domain.

Joshua Gerth
Joshua Gerth
Engineering Manager
Distributed Systems Engineer
Systems Architect

My research interests include big data, language parsing and ray tracing.