Hello 👋 I'm Dan.

I write PHP, Go, and JavaScript. I also care about web performance.

FreeRADIUS Monitoring Script Updated for Mavericks

I’ve updated the FreeRADIUS monitoring script for Nagios with support for OS X Mavericks Server. Mavericks changed the way the FreeRADIUS server is started, along with the paths of execution and storage.

Like the update to the Caching Server 2 monitoring script, I had to write a check to see if the current OS is running 10.9, and if it is, perform a Mavericks-specific check. Like I mentioned in the other article, doing a version check and comparison isn’t particularly easy in Bash, but thankfully, I only have the compare the major and minor release numbers which is nice given that it’s also a float. Using bc (the arbitrary precision calculator language - I should get that on a shirt!) I can quite easily calculate the difference between 10.8 and 10.9. Anyway, check the code below for how I get the version number.

sw_vers -productVersion | grep -E -o "[0-9]+\.[0-9]"

Next, the comparison is performed to see whether the current OS is less than 10.9. If the current OS is less than 10.9, 1 is returned. If it’s the same (or greater), the result is 0. This code is below:

echo $osVersion '< 10.9' | bc -l

Note that the above example requires the variable $osVersion. If you were hard coding the values, you could do something like below:

echo '10.8 < 10.9' | bc -l

The major difference in my script for OS X Mavericks is now there’s actually a process running called radiusd! Using ps and grep I now check to see if the FreeRADIUS server is running by doing this:

ps -ef | grep radiusd

Which, if the FreeRADIUS (or radiusd) is running, will return a non-empty string. If you run that and get an empty string (or nothing) back then your FreeRADIUS server isn’t running. Shit. I recommend doing radiusd -X to start your RADIUS server in debug mode. That or you forgot to get RADIUS added to launchd by entering radiusconfig -start. Anyway, that’s enough chit-chat, just get the damn code from the link below:

Check out the code on GitHub!

OS X Mavericks Server - Adding Groups

Along with adding users to your OS X Mavericks Server’s Open Directory you can also add groups to contain specific users to specific groups. For example, your sales team might have their own group called sales that provides them specific file sharepoints, jabber group and even add a special group mailing list for all users in that group. The group also allows you to specify different ACLs for each group.


  • Workgroup Manager
  • Command Line Goodness

First, I recommend following my guide adding users to add users to your Open Directory domain because groups are pretty useless without users! Anyway, onwards and upwards.

Server: No Groups Yet.

Server: No Groups Yet.

Okay, jump over to the Server app and load up the Groups section. If this is a base installation with Open Directory, you should only see one group in the Local Network Groups and it’s called Workgroup. By default, any user you add to the Open Directory domain will be added to this group. Given that I’m still rolling with characters from The Office, I’ll add some groups that relate to the users we added earlier. Click the plus in the bottom-left corner to add a new group.

Groups: Adding the Accounting Group.

Groups: Adding the Accounting Group.

First off, I’m going to make a group called Accounting. For the Full Name, enter Accounting and the Group Name will be accounting. Once you’ve entered those details, go ahead and click the Create button to add the group. Initially when you add the group there’s hardly any configuration aside from the name. Believe me, there’s more configuration to be done once you’ve added the group!

You’ll now be taken back to the list of groups, but now the group you just added will be in that list. Hooray! But we can’t celebrate yet because our group has no one in it! Let’s change that. Double click on your group to modify the settings and add/remove users.

Groups: Edit the Accounting Group

Groups: Edit the Accounting Group

Alrighty then, we can now modify some settings. First thing you’ll notice is that you can rename the “nice” name of the group, but you can’t change the shortname. Basically, if you didn’t name your group correctly the first time and you want to change its name, just delete the damn thing and create a new one. This may be more tedious if you’ve been using the group for a while, so make sure you do it right the first time. Next thing is giving the group a special shared folder on the Server, which is located at /Groups/<groupshortname> on the server. Enable this if you want that folder to be enabled, otherwise if you have your own folder structure you’re following, you can just add this group to the folder’s ACL.

Next is making the group members all buddies in Messages (or jabber). Enable it if you want the members to automatically be friends if they have the Messages app set up. If you’re not using the inbuilt Messages server, this option won’t need to be enabled. For the curious, if you enter the following command into Terminal, you’ll be shown all the groups and their Messages autobuddy status.

sudo serveradmin settings accounts

For example, if I were to enable or disable autobuddy via Terminal for the group accounting, I would enter the commands below:

sudo serveradmin settings accounts:GroupServices:EnableAutoBuddy:accounting = no # Disble autobuddy
sudo serveradmin settings accounts:GroupServices:EnableAutoBuddy:accounting = yes # Enable autobuddy

The next easy option is setting up a mailing list which, when email is sent to that address, will be sent to all the members of the group. This email address is the group’s short name. For example, accounting@pretendco.com or sales@pretendco.com. By default, only members of the group can send emails to that mailing list, otherwise, enable the “Allow mail from non-group members” to enable emails from anyone (yes, it’s literally everyone - not just people in the Open Directory domain).

Groups: Adding Users and Groups to Accounting.

Groups: Adding Users and Groups to Accounting.

It’s now time to add members to the group! Not only can you add users to a group, but you can also add groups to other groups! There’s a very cool hierarchy that you can configure with users and groups, but don’t over-complicate it otherwise your ACL precedence and inheritance are going to be very, very confusing. When you click the plus you can either start typing in a user name or group name (and it will auto suggest then click on the user to add it), otherwise, start typing browse then select Browse to bring up a list of all applicable users and groups that can be added to the group.

The Users and Groups Browse List.

The Users and Groups Browse List.

As per usual, you can add keywords and notes for the group. Once you’re done editing the group, click OK to save your changes.

Workgroup Manager

As with every other OS X Server release there has been a program called Workgroup Manager (internally I’ve heard the nickname Workgroup Mangler) which shows you all the users, groups, machines and machine groups for Open Directory domains. First off, Workgroup Manager isn’t distributed with Server so we need to download it seperately off Apple’s website so click here to download. Once you’ve downloaded and installed Workgroup Manager, open it up and connect to your server! Go to Server then click Connect…

Workgroup Manager: Connect to Server.

Workgroup Manager: Connect to Server.

Enter details for your local server to connect. For example, the address will be the FQDN (remember what that stands for?) so my server will be mavericks.pretendco.com. If you want to make any edits you’ll need to be logged in as the Master Directory Administrator (or any other user you’ve given Server administration rights to). If you’re just connecting to browse the Open Directory domain, log in as any admin user (for example, my Server Administrator login for the Server machine gives me read-only access to the Open Directory domain). Next, enter the applicable password. Hit Connect to… you know… connect.

Workgroup Manager: Connect to mavericks.pretendco.com

Workgroup Manager: Connect to mavericks.pretendco.com

If all goes well and you’ve entered the correct details you should now be shown a list of all the users in your Open Directory domain! Hooray!

Workgroup Manager: The User List.

Workgroup Manager: The User List.

You’ll notice that in the list of users, any user that has a pencil in their icon means that they have administration rights for the Open Directory domain you’ve connected to. Anyway, just above the list of users are four icons, the second one from the left is Groups - click it.

Workgroup Manager: The Group List.

Workgroup Manager: The Group List.

Excellent, we can now see all the groups in the Open Directory domain. Clicking on any group will show you the basic settings for the group, you can also change memberships for the group and even the Group Folder. Have a look around in Workgroup Manager, but make sure you know what changes you’re making, you could permanently damage a user or group by making the wrong change (word of advice, don’t change short names or IDs).

Command Line Goodness

Accessible via Terminal is the very powerful command dseditgroup which as you might guess, allow you to edit directory service groups. The name of the command however is a bit of a misnomer given that you can do more than just edit the group. I personally think the command should be called dsgroup but that’s just me. Anyway, now onto the usefulness of this command. Given that we’ve been playing with the group accounting, let’s use this command to show us details about the group!

dseditgroup -o list accounting

Essentially what we’re doing here is using the -o flag (otherwise known as operation), we specify that we’re requesting a list of the accounting group. Here’s the output of dseditgroup for the group accounting on my system:

dsAttrTypeStandard:GroupMembership -
dsAttrTypeStandard:Member -
dsAttrTypeStandard:GeneratedUID -
dsAttrTypeStandard:OwnerGUID -
dsAttrTypeStandard:AppleMetaRecordName -
dsAttrTypeStandard:AppleMetaNodeLocation -
dsAttrTypeStandard:RecordType -
dsAttrTypeStandard:GroupMembers -
dsAttrTypeStandard:PrimaryGroupID -
dsAttrTypeStandard:RealName -
dsAttrTypeStandard:RecordName -

Another useful command if you just want to check to see if a particular user is a member of a particular group, you can enter the following:

dseditgroup -o checkmember -m <usershortname> <groupshortname>

For example, if I want to check to see if Oscar Martinez is a member of Accounting, I can enter this:

dseditgroup -o checkmember -m omartinez accounting

You should get the response below:

yes omartinez is a member of accounting

Or if if the user isn’t a member of the group, you’ll get the following response:

no jhalpert is NOT a member of accounting

Finally, another way of looking up groups via the command line is by using dscl, or the Directory Service command line utility. To get a list of all the groups in the local Open Directory domain, you would use the command below:

dscl /LDAPv3/ -list /Groups

This give you the shortname of each group:


If you prefer to get a little bit more information, you can also request a specific value like GeneratedUID, RealName, AppleMetaRecordName or Member. If I wanted to get a list of the shortnames of members for each group I could enter something like below:

dscl /LDAPv3/ -list /Groups Member

Which will in turn show me all the groups and their members (as requested):

accounting      aschrute kmalone omartinez
admin           masterdiradmin mscott
administration  omartinez cbratton mpalmer kmalone dphilbin ehannon aschrute tflenderson kkapoor
management      mscott phalpert
sales           abernard jhalpert dschrute shudson phalpert rhoward plapinvance
staff           root
workgroup       jhalpert mscott phalpert dschrute rhoward abernard aschrute kkapoor omartinez dphilbin ehannon tflenderson kmalone plapinvance shudson mpalmer cbratton ictadmin

Caching Server Nagios Script Updated for Mavericks

Just a quick heads up that Jedda and I’s check_osx_caching monitoring script for Nagios and OS X has been updated to support OS X Mavericks Server. Given that Caching Server 2 in 10.9 adds more verbosity to what content is taking up what space, I’ve added support for each content type and has been added to the performance data that is returned in the script.

As content usage is not tracked in Mountain Lion’s Caching Server I had to do a check of the operating system to see what version the script is being run on. To do this, I used the function sw_vers and added the flag productVersion to only have the product version returned. Now, on a first release of the OS you’ll get a clean float like 10.9 or 10.8 which makes it really easy to do a comparison using bc (a precision calculator language). Where it becomes a problem is when you get numbers like 10.8.5 which, because they have two periods, mean they don’t work with bc. I decided I could either write a function that does a full comparison of the version numbers, or just get the major and minor release and do a standard mathematical float comparison. Using grep I can pull the major and minor release information and assign it to a variable. See below for the code:

sw_vers -productVersion | grep -E -o "[0-9]+\.[0-9]"

Next, the comparison is performed to see whether the current OS is less than 10.9. If the current OS is less than 10.9, 1 is returned. If it’s the same (or greater), the result is 0. This code is below:

echo $osVersion '< 10.9' | bc -l

Note that the above example requires the variable $osVersion. If you were hard coding the values, you could do something like below:

echo '10.8 < 10.9' | bc -l

Now, if the value of the expression is 0, we will now grab all the Mavericks Caching Server usage data, and assign it to a variable called mavericksPerfData which is appended to the end of the final return printf.

I’ll be updating our RRDtool graph for the Caching Server 2 and will post the code soon! Stay tuned.

Check out the code on GitHub!

OS X Mavericks Server - My Tutorials

Over the past few weeks I’ve been writing tutorials for OS X Mavericks Server, and now that it has come out, I can finally post all my articles! See below for the list:

I hope you enjoy these articles. Please let me know if you have any queries or input by messaging me on Twitter at @yesdevnull.

OS X Mavericks Server - Setting Up FreeRADIUS

In the past year or so I’ve done a few more deployments using OS X Server’s inbuilt FreeRADIUS server for authentication via enterprise Wi-Fi base-stations and routers. While OS X Server will automatically configure RADIUS for AirPort base-stations, there’s no way via the Server GUI to configure third-party authenticators.

My buddy Jedda wrote an excellent article last year on configuring RADIUS for 10.8 Server, but in Mavericks Server, things have changed slightly. FreeRADIUS has been updated from 2.1.12 to 2.2.0 and all the configuration files have been moved from /etc/raddb to /Library/Server/radius/raddb.

First off, we will need to add the user to the RADIUS access group, which is called com.apple.access_radius. Any user that will authenticate through RADIUS must be added to this group.

dseditgroup -q -o create -u <admin_user> -a <your_username> -n . com.apple.access_radius

For example, as I’m doing this on the same server as the FreeRADIUS server, I’m going to add my Server Administrator user (serveradmin) to the RADIUS access group. I entered the command below:

dseditgroup -q -o create -u serveradmin -a serveradmin -n . com.apple.access_radius

Okay, now onto the proper configuration. Lets start by changing a few RADIUS settings so we can get some more verbosity in the logs regarding authentication attempts. By default, RADIUS does not log authentication requests, let’s change that. By entering the following command, radiusconfig changes a variable in the /Library/Server/radius/raddb/radiusd.conf to now log authentication requests.

sudo radiusconfig -setconfig auth yes

Note: for the curious, radiusconfig’s location is /Applications/Server.app/Contents/ServerRoot/usr/sbin/radiusconfig.

Next, we’ll enter a command to log bad authentication requests. This also changes a variable in the above file, it’s a few lines further down in the config file.

sudo radiusconfig -setconfig auth_badpass yes

Now, let’s also log successful authentication requests:

sudo radiusconfig -setconfig auth_goodpass yes

It’s now time to add a client to the RADIUS server. Any device that directly communicates with the RADIUS server must first be added to a list before it’s allowed to start processing requests. The structure of the command is as follows:

sudo radiusconfig -addclient ip_address identifier nas_type

For example, if your Wi-Fi base-station allows RADIUS authentication, you can use it to be an authenticator for your RADIUS server. First of all, your Wi-Fi base-station must have a static IP address on the network, because as I mentioned earlier, each device must be manually defined before it’s allowed to authenticate to the RADIUS server. Next up, the identifier is a way you can easily identify the Network Access Server (NAS), and must be unique it is used in Access-Request packets. The RFC recommends using the FQDN for the identifier. Finally, we specify the NAS Type. Typically you would use other unless you have a special device that uses another NAS Type. You can review /Library/Server/radius/raddb/clients.conf to see if you need to use another NAS Type identifier.

Bearing all that in mind, let’s set up a client for the network. Pretend that you have an Aerohive AP that can be used to authenticate users that connect to a WPA2 Enterprise wireless network. The Aerohive AP 330 sits on the network at and has an A record for aerohive.pretendco.com. As this device doesn’t have a special identifier that’s required by RADIUS we will use other. With all these details, let’s add the client using radiusconfig:

sudo radiusconfig -addclient aerohive.pretendco.com other

You’ll now be asked to provide a shared secret that is used to encrypt packets sent between the NAS and the RADIUS server with md5. Best to use an app like 1Password to generate a random alphanumeric shared secret. Make sure you save this shared secret, because you’ll need to give it to the Aerohive later on so it can communicate with the RADIUS server. Once you provide the shared secret, hit Return. You should get the following message: added to the nas list

Hooray, the Aerohive has been added to the NAS list! Now, we need to give the RADIUS server a real certificate. When RADIUS is run for the first time it will automatically generate a self-signed certificate that it uses to provide security to users. This is okay if you’re testing RADIUS, but in a live environment, you should really be providing your own certificate that is signed by a known Certificate Authority (CA). You can get SSL certificates from a number of providers, check out Namecheap for great value SSL certificates. As this article is about configuring RADIUS, I’m going to assume your certificate is signed by a globally recognised Certificate Authority.

Open up Keychain Access then on the left-side click on the System keychain. Scroll down the list until you find the certificate and private key with your FQDN. For example, the server I’ve been using in these articles has a FQDN of mavericks.pretendco.com, using the command key I’ll click on the certificate and private key that’s called mavericks.pretendco.com. Now, go to File, then click on Export Items…”

Save the file as a Personal Information Exchange (.p12) on the Desktop called RADIUS. You’ll now be asked to authenticate to unlock the System keychain. Next, enter in a password that will be used to secure the certificate and private key file. For this example, I’m using server but please never use this in production environments! Enter the password twice then hit OK. Your RADIUS.p12 will now be available on the Desktop.

Jump back to Terminal because we’re now going to export these into the certs folder in raddb. We first need to export the private key as a .key. Enter the following command to replace the default .key with our own. Make sure you have that password you used to encrypt the exported items handy as you’ll have to enter it for the next two commands.

sudo openssl pkcs12 -in ~/Desktop/RADIUS.p12 -out /Library/Server/radius/raddb/certs/server.key -nodes -nocerts

Enter in the password for the .p12, then hit Return. Now, we will export the certificate, and override the default one in the process.

sudo openssl pkcs12 -in ~/Desktop/RADIUS.p12 -out /Library/Server/radius/raddb/certs/server.crt -nodes -nokeys

Like the last command, enter the password for the .p12 then hit Return. Now, using Terminal lets change directory to certs folder by entering the following command:

cd /Library/Server/radius/raddb/certs

We’re now going to validate that the modulus of both the private key and certificate are the same to ensure we have the right certificates, and to ensure that they are for the same matched pair. Enter in the following command to get the modulus of the certificate:

openssl x509 -noout -modulus -in server.crt | openssl md5

This will echo out an md5 hash of the modulus of the certificate. Now enter:

openssl rsa -noout -modulus -in server.key | openssl md5

Another md5 hash of the private key’s modulus will be echoed. Here’s the md5 hash of both my private key and certificate

222b9f6176126d06872c56809a0ef34b # server.crt
222b9f6176126d06872c56809a0ef34b # server.key

Check the numbers to ensure they match, because if they don’t you have the wrong certificate and private keys! After ensuring that the modulus’ match, we will now configure RADIUS to use our supplied certificates. Enter the following command into Terminal:

radiusconfig -installcerts /Library/Server/radius/raddb/certs/server.key /Library/Server/radius/raddb/certs/server.crt

Note that the private key must come before the certificate, otherwise the command won’t work. The RADIUS server will now generate a random and dh file (very important for the RADIUS server) and should only take up to 10 seconds to complete. Once that has completed, we’re now ready to test the RADIUS server! We’re first going to start FreeRADIUS in debug mode to ensure it’s starting correctly.

radiusd -X

The FreeRADIUS server will start up within seconds and the last line you should see in your Terminal prompt is Ready to process requests.. Great, it’s now running happily. Terminate the process by hitting Ctrl+C (^C) and we’ll get the FreeRADIUS server setup with launchd so it’ll start every time the server is rebooted.

sudo radiusconfig -start

This’ll add the org.freeradius.radiusd.plist (which is located in: /Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons/org.freeradius.radiusd.plist) to launchd. Let’s now test it out via Terminal to make sure we can communicate with the FreeRADIUS server. Our command structure is as follows:

echo "User-Name=<username>,User-Password=<password>,Framed-Protocol=PPP " | radclient -x -r 1 -t 2 localhost:1812 auth testing123

We have to pipe in a few authentication details to radclient, then provide the details for the RADIUS server. If you’re running this on the same machine as the FreeRADIUS server, your shared secret is testing123. I will enter the following settings to test on my server:

echo "User-Name=serveradmin,User-Password=serverpass,Framed-Protocol=PPP " | radclient -x -r 1 -t 2 localhost:1812 auth testing123

You should see the following result:

Sending Access-Request of id 220 to port 1812
    User-Name = "serveradmin"
    User-Password = "serverpass"
    Framed-Protocol = PPP
rad_recv: Access-Accept packet from host port 1812, id=220, length=32
    Framed-Protocol = PPP
    Framed-Compression = Van-Jacobson-TCP-IP

That’s it! The last thing we’ll do is allow Console to display the radiusd.log so we can read it. For the last time, jump in to Terminal and enter the following command:

chmod -R 755 /var/log/radius

Open up Terminal and now you can view the radiusd.log! Use it to troubleshoot any issues you may have.

Well, you’re all done now. You have configured a FreeRADIUS server, and it can process requests successfully, along with authenticating the allowed users.

OS X Mavericks Server - Setting Up Caching Server

The Caching Server in OS X Mavericks Server is used to speed up downloads of content distributed by Apple over the internet. Caching Server caches all updates, App Store and iBooks downloads, and Internet Recovery software that your OS X v10.8.2+ and iOS 7 devices download.


  • Shared Caching Over Subnets
  • Peer Review
  • Monitoring
Caching Server - Hasn't Been Started Yet.

Caching Server - Hasn't Been Started Yet.

Caching Server 2 which came out with OS X Mavericks Server raised the bar from Caching Server in OS X Mountain Lion Server by adding software updates, iOS app updates, iBooks and Internet Recovery downloads. Also added is the support for multiple Caching Server 2 servers on the same public IP network. If there are multiple Caching Servers on the same network and one doesn’t contain a requested download, the Caching Server will consult with its peer servers on the same network to see if they have the requested download. This information is then passed onto the client, that will then select the right server automatically.

One important thing to note is that from OS X v10.8.2, Caching Server will do all software updates for clients, this doesn’t necessarily mean it can replace the Software Update Server that has been with OS X Server for a long time. Even though Software Update Server does require more maintenance and client configuration (you have to configure each client), you still maintain control over which clients get which updates. Caching Server 2 does not have the ability to deny updates for any devices. Maybe that will be added in the future, but for now if you need to control who gets what update, Caching Server 2 is not for you.

Okay, enough chit-chatter, let’s get Caching Server 2 running! Open the Server app then click on the section named Caching. Depending on your requirements, you might want to store all the downloads on a separate drive that’s connected to the server. I usually configure servers with small SSD boot drives, so storing Caching Server 2 downloads on a small SSD is not an option. Once you’ve chosen your storage device, you can now select the maximum cache size for Caching Server 2. There’s only one rule with Caching Server 2 storage, the minimum storage size is 25GB. Caching Server 2 has a buffer of 25GB where the least-used content is deleted to make way for more popular and requested downloads. We’re now ready to start the caching server! Hit the On button in the top-right corner.

Caching Server After Some Content Has Been Cached.

Caching Server After Some Content Has Been Cached.

After Caching Server 2 has started, try going to the App Store and downloading a few apps, and iBooks to download a few books. Check back in a few minutes to see your Usage graph, it should now be populated with details of the usage split, with detailed numbers of how much each cache category is using. Another way to check out how Caching Server 2 is going is by using Terminal! Open up Terminal and enter the following command:

sudo serveradmin fullstatus caching

You should see something like below:

caching:Active = yes
caching:state = "RUNNING"
caching:CacheUsed = 125027720
caching:Port = 61090
caching:TotalBytesRequested = 124886938
caching:RegistrationStatus = 1
caching:CacheLimit = 25000000000
caching:CacheFree = 4025427456
caching:Peers = _empty_array
caching:TotalBytesFromPeers = 0
caching:StartupStatus = "OK"
caching:TotalBytesFromOrigin = 124886938
caching:CacheStatus = "OK"
caching:TotalBytesReturned = 124886938
caching:CacheDetails:_array_index:0:BytesUsed = 60543656
caching:CacheDetails:_array_index:0:LocalizedType = "Mac Apps"
caching:CacheDetails:_array_index:0:MediaType = "Mac Apps"
caching:CacheDetails:_array_index:0:Language = "en"
caching:CacheDetails:_array_index:1:BytesUsed = 53730125
caching:CacheDetails:_array_index:1:LocalizedType = "iOS Apps"
caching:CacheDetails:_array_index:1:MediaType = "iOS Apps"
caching:CacheDetails:_array_index:1:Language = "en"
caching:CacheDetails:_array_index:2:BytesUsed = 10753939
caching:CacheDetails:_array_index:2:LocalizedType = "Books"
caching:CacheDetails:_array_index:2:MediaType = "Books"
caching:CacheDetails:_array_index:2:Language = "en"
caching:CacheDetails:_array_index:3:BytesUsed = 0
caching:CacheDetails:_array_index:3:LocalizedType = "Movies"
caching:CacheDetails:_array_index:3:MediaType = "Movies"
caching:CacheDetails:_array_index:3:Language = "en"
caching:CacheDetails:_array_index:4:BytesUsed = 0
caching:CacheDetails:_array_index:4:LocalizedType = "Music"
caching:CacheDetails:_array_index:4:MediaType = "Music"
caching:CacheDetails:_array_index:4:Language = "en"
caching:CacheDetails:_array_index:5:BytesUsed = 0
caching:CacheDetails:_array_index:5:LocalizedType = "Other"
caching:CacheDetails:_array_index:5:MediaType = "Other"
caching:CacheDetails:_array_index:5:Language = "en"

When your caching server first connects to Apple’s servers to let them know we have set up a caching server, it is assigned a GUID that other peers and clients can use to identify the server. To obtain this GUID you can enter the following into Terminal:

sudo serveradmin settings caching:ServerGUID

Shared Caching Over Subnets

A nifty feature is the ability for the caching server to traverse across subnets to share cached downloads. This feature is enabled by unticking the “Only cache content for local networks”. By default, Caching Server will only cache content for the current subnet (in my case, An alternative way to enable multi-subnet caching through Terminal is to alter the LocalSubnetsOnly option, do this command to enable subnet traversal:

sudo serveradmin settings caching:LocalSubnetsOnly = no

This change doesn’t require a reboot of the Caching Server, but reboot just to make sure. If you want to disable subnet traversal, do this:

sudo serveradmin settings caching:LocalSubnetsOnly = yes

Those changes that you make will be reflected in the logs. If you take a look in the Debug.log (located at /Library/Server/Caching/Logs/Debug.log) you’ll see something like this:

2013/10/31 18:09:36:979  Registering with local address:; local subnet range only:
2013/10/31 18:09:38:284  Request for registration from https://lcdn-registration.apple.com/lcdn/register succeeded
2013/10/31 18:09:38:284  Got back public IP xx.xx.xxx.xx
2013/10/31 18:09:38:288  This server has 0 peer(s)

This feature requires you to be using Network Address Translation (NAT) and the same public IP address - both requirements of Apple. If you have multiple subnets if your office or workplace but only have the resources for one Caching Server, it would be wise to enable this feature on the server. Also make sure your firewall will allow traffic over port 61090/TCP for internal traffic only (this port may need to be changed if you specified a custom port when configuring caching server, or if you have multiple caching servers). If you don’t know what port your Caching Server is available at, you can enter this command to find out:

serveradmin fullstatus caching | grep "Port"

In most cases you should have 61090 returned. Generally, the only time this will be different is if you have multiple caching servers (see below) in the one workplace.

If you have a look at the settings for Caching Server in Terminal, you’ll see that the Caching Server port is set to 0. This means that when it starts up it’ll check for an available port on startup and choose an appropriate one (I presume this is defined when it registers with Apple). For example: if Caching Server was hard-wired to start on 61090, some of your machines or firewall may detect conflicts. Otherwise, you can hard-code a port for it to run on by firstly shutting down the Caching Server in the Server app, or in Terminal by entering sudo serveradmin stop caching. Next, decide on a port that you know to be available. As far as I can tell any port is okay, as long as it’s not already in use on the LAN. If I wanted to specify the Caching Server to run on 61000 I would enter this into Terminal:

sudo serveradmin settings caching:Port = 61000

Hit return then start Caching Server either in the Server app or by entering sudo serveradmin start caching. Give the Caching Server a few seconds to start, then enter sudo serveradmin fullstatus caching. I’ll trim the output, but the line you’re looking for should now show this:

caching:Port = 61000

Huzzah! Your Caching Server is now running on your custom port. Change it back to 0 if you want it to randomise the port on registration. Note that changing it back to default may not take into effect straight away, you may have to reboot Caching Server after a little while as Caching Server will cache registration settings, along with its last port (found with defaults read /Library/Server/Caching/Config/Config.plist LastPort). I’ve also updated the Nagios script for checking Caching Server to include port-specific checks, check it out!.

Peer Review

I really like the idea of a peer-based system with Caching Server 2 so I decided to spin up another OS X Mavericks Server instance and get it set up with Caching Server 2 also. After getting them both registered with Apple’s backend system (an automated process by the way, and should only take 2 minutes for each machine), I ran sudo serveradmin fullstatus caching on both machines so I could check out what the caching:Peers array would hold. Here are my results:

mavericks.pretendco.com -

caching:Peers:_array_index:0:guid = "7B4E17C1-14E2-48E0-8062-34660B4C041B"
caching:Peers:_array_index:0:version = "73"
caching:Peers:_array_index:0:healthy = yes
caching:Peers:_array_index:0:address = ""
caching:Peers:_array_index:0:port = 50294

replica.pretendco.com -

caching:Peers:_array_index:0:guid = "8594F0EF-E810-4993-A74F-A1473C6B099D"
caching:Peers:_array_index:0:version = "73"
caching:Peers:_array_index:0:healthy = yes
caching:Peers:_array_index:0:address = ""
caching:Peers:_array_index:0:port = 49486

On each machine you can also enter sudo serveradmin fullstatus caching | grep TotalBytesFromPeers and sudo serveradmin fullstatus caching | grep TotalBytesFromOrigin to get the number of bytes transferred from peers and origin respectively. I noticed a huge speed increase when downloading a purchased app from the App Store when it had already been cached by the other caching server - as you would expect. After downloading about 15 different apps across my two OS X Mavericks Server instances, I check out the cached totals via the command line. Here’s what I got:

mavericks.pretendco.com -

caching:TotalBytesFromPeers = 4957598
caching:TotalBytesFromOrigin = 15591778

Which equates to 4.96 MB from peers and 15.59 MB from itself.

replica.pretendco.com -

caching:TotalBytesFromPeers = 17628454
caching:TotalBytesFromOrigin = 167213809

Which equates to 17.63 MB from peers and 167.21 MB from itself.

Note: Caching Server reports all its usage in the SI format, not the standard base 2 format, so make sure you factor that in to any calculations you may make.


Along with the original Caching Server, Caching Server 2 has a whole host of options to check the health of the service via the command line. Here’s a few commands you can use the ensure Caching Server 2 is alive and happy!

sudo serveradmin fullstatus caching | grep "Active"

This will return no if the service is in “STARTING” mode, and will not return anything if the service is in “STOPPED” mode.

sudo serveradmin fullstatus caching | grep "StartupStatus"

This should return “OK” if the service is running OK (d’uh, that’s obvious). If the service is in “STARTING” mode, this will return “PENDING”.

sudo serveradmin fullstatus caching | grep "CacheStatus"

This should return “OK” if the cache status is healthy. I’ve tried to break this to get it to return something other than OK but I haven’t been successful. Even deleting the entire /Library/Server/Caching directory doesn’t cause this to fail.

sudo serveradmin fullstatus caching | grep "CacheFree"

Theoretically Caching Server 2 should never let this dip down to anywhere near zero, but doesn’t mean you can’t monitor it.

sudo serveradmin fullstatus caching | grep "RegistrationStatus"

Typically this only equals 0 when Caching Server 2 has been started for the first time. While 0 (zero), the caching server is talking to Apple to get a GUID and register itself. This process generally takes no longer than two minutes, and will change to a 1 (one) once it has completed registration.

defaults read /Library/Server/Caching/Config/Config.plist LastRegOrFlush

This will tell you the last time Caching Server 2 checked in with Apple and retrieved an updated list of peers (and their status).

Finally, there’s a great debug log that is really verbose in what is happening during any stage of Caching Server’s life. The location of the log is /Library/Server/Caching/Logs/Debug.log, so tail -f it when you’re playing around to see what it does.

Hopefully this article has helped you get familiar with Caching Server 2 and set it up correctly.

OS X Mavericks Server - Setting Up Contacts

The Contact service in OS X Mavericks Server is a great way to easily sync contacts between users and groups. Along with the Calendar service, it has deep ties with the Apple Push Notification Service (APNS) to push all new changes to your devices.


  • Pro-Tip: SRV Record For Easy Configuration
  • Setting Up In Contacts.app Using CardDAV

What you may not know is that the Contact service is actually tied into the Calendar service. If you enter serveradmin settings calendar and serveradmin settings addressbook you’ll find that they match line for line (with exception to the name of course). You may also notice that there’s not really much that can be configured for Contacts (annoyingly, Contacts is still called Address Book in the serveradmin backend), pretty much the only thing you can change in the GUI are settings for APNS and whether Address Book is allowed to query the Directory Service.

Open up the Server app and click on the Contacts section so we can start it up! Click the On button to start the Contacts server! If you enter tail -f /var/log/caldavd/servermgr_calendar.log in Terminal before you turn Contacts on, you’ll see the config changes get pushed, then the collaboration services will restart.

Now that Contacts is running, you’re pretty much done! You can optionally allow contacts to be shared via LDAP, but that’s not a requirement. Typically you won’t need to enable this.

Pro-Tip: SRV Record For Easy Configuration

Along with Calendar, you can set up a SRV DNS record for the CardDAV TCP protocol. Essentially, it’s like an MX record, but for other protocols. We can utilise the DNS service in OS X Mavericks Server to create this SRV record.

If you open up the Server app and go to the DNS section, I’ll show you how to create a SRV record. Select your Primary Zone, then hit the + (plus) in the bottom-left corner, then click “Add Service Record…”. This will bring up a window overlay with some empty fields.

In these tutorials we’ve only been working with a primary zone, so we won’t change it. Actually, you can’t even change it (because there’s only one zone), so don’t even bother trying. The primary zone should be your domain name.

Next, for Service Name, leave this blank as we aren’t using any Bonjour browser goodness. Finally, the first field we actually enter something in is Service Type. Because we’re using the SSL version of the CardDAV protocol over TCP, we will enter _carddavs._tcp. If you don’t want to use SSL (why?), enter _carddav._tcp.

For the host name, enter the FQDN (Fully Qualified Domain Name) of the server you want to be your CardDAV server. Given the fact that in these examples we have only been using one server, just enter the host name for your server. Mine is mavericks.pretendco.com. The next field is Port, which defines what port this service is running on. Because we’re using SSL, we’ll enter in 8443. If you weren’t using SSL, you’d enter 8008.

If you’re unsure what port your Contact server is using, enter the command below to get your port. Note the command to the right of either command, use the top one if you use SSL, use the bottom command if you don’t.

sudo serveradmin settings addressbook:SSLPort # Using SSL
sudo serveradmin settings addressbook:HTTPPort # Not Using SSL :(

If you really have no idea if you’re using SSL or not, you can enter sudo serveradmin settings addressbook:RedirectHTTPToHTTPS to find out if you are. If the answer is yes, then you’re using SSL.

Okay, that’s enough ranting about ports. The last two important fields are Priority and Weight. As I’ve said a few times earlier, we’re only using one server in these examples, so enter 0 for Priority and 1 for Weight. The final field is Text, we are leaving it blank. Some services may need some information in the Text field, but CalDAV/CardDAV don’t.

For a more readable list, see below:

  • Zone: pretendco.com
  • Service Name: Leave Blank!
  • Service Type: _carddavs._tcp
  • Host Name: mavericks.pretendco.com
  • Port: 8443
  • Priority: 0
  • Weight: 1
  • Text: Leave Blank!

All in all, you should have something that looks like this:

The CardDAV SRV Record.

The CardDAV SRV Record.

Now that you’re done, click Create to create the SRV record. If all goes well, you should be taken back to your DNS Records list, and your new SRV record should be in that list. If not, you probably did something wrong (hint: maybe you put a space in the Service Name field). To verify that the SRV record has been added, enter the following command in Terminal on the server:

dig SRV _carddavs._tcp.pretendco.com

If all goes well, you should see something like this:

; <<>> DiG 9.8.3-P1 <<>> SRV _carddavs._tcp.pretendco.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10499
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1

;_carddavs._tcp.pretendco.com.	IN	SRV

_carddavs._tcp.pretendco.com. 10800 IN	SRV	0 1 8443 mavericks.pretendco.com.

pretendco.com.		10800	IN	NS	mavericks.pretendco.com.

mavericks.pretendco.com. 10800	IN	A

;; Query time: 4 msec
;; WHEN: Sat Oct 19 22:27:32 2013
;; MSG SIZE  rcvd: 119

Hooray, everything is OK.

Setting Up In Contacts.app Using CardDAV

So, you’ve got the Contacts service up and running, and now you want to add it to the Contacts app in OS X Mavericks so your users can start adding contacts to their contact list. Open up the Contacts app then go to Preferences then click on the Accounts pane.

Contacts: Add Other Contacts Account.

Contacts: Add Other Contacts Account.

Hit the + (plus) in the bottom-left corner to add an account. Because we’re using our own contact system, use the option at the very bottom called “Other contacts account…” then click Continue. Sadly, Contacts still isn’t as nice as Calendar when setting up a custom CardDAV account, you don’t get the nice automatic/manual/advanced options. All you get is CardDAV or LDAP. Given that we’re using CardDAV, ensure that CardDAV is selected.

Contacts: CardDAV User Details.

Contacts: CardDAV User Details.

In the User Name field, enter your username. I’m going with Jim Halpert, so I’ll enter in jhalpert. Next up is the Password, and Jim’s password is pam.

Finally, we enter the Server Address. If you did the SRV record step about, you only have to enter your domain name! In my case, it’s pretendco.com. If not, enter the FQDN for your server (mavericks.pretendco.com). If you try and set up the user using the SRV method and you haven’t made the SRV record, you’ll get an error about not being able to make a secure connection. If all is successful, click Create to create the user.

Note: In my testing, I’ve noticed that on OS X Mavericks when adding the CardDAV account Contacts.app freezes for a couple of seconds before adding the account, or it freezes until killed. Just take that into account when adding your account!

OS X Mavericks Server - Setting Up Calendaring

The Calendar service in OS X Mavericks Server is a really easy way to get collaboration between users set up, along with allowing them to allocate resources and locations within your business to events. With deep ties in the Apple Push Notification Service (APNS) and Mail services, notifying people about your events is quick and easy.


  • Getting Started
  • Pro-Tip: SRV Record For Easy Configuration
  • Email Invitations
  • Resources & Locations

Getting Started

First up, let’s actually get Calendaring up and running! Open the Server app and click on the Calendar section. Hit the little On button to start it up!

When turning on Calendar for the first time, or when you’re upgrading, it’s worth taking a look at a few logs to get an idea of what’s happening in the backend. Getting in the habit of reading logs is a great way to learn, and of course, troubleshoot. All of the Calendaring logs are stored in /var/log/caldavd/, but the most interesting logs at this stage will be /var/log/caldavd/servermgr_calendar.log, /var/log/caldavd/migration.log and /var/log/caldavd/error.log. Once the Calendar server has started we’re ready to rock and/or roll.

The Calendar service is now running!

The Calendar service is now running!

Pro-Tip: SRV Record For Easy Configuration

If you are hosting DNS on your server, or have full access to creating DNS records with your hosting provider, you can add SRV records that can make it that little bit quicker to add Calendar accounts for all your users. From here on, I’m assuming you’re creating the DNS record in the Server app.

Go to the DNS section of the Server app, and click the + (plus) in the bottom-left corner then click on “Add Service Record…”

Because we only have one DNS zone (aka, the Primary Zone), leave the Zone field alone (if you’ve only got one zone, you can’t even change it). Leave the Service Name field blank as it is for an optional Bonjour browsing field, which we aren’t using.

Next up, we enter the Service Type. The Server app thinks it can be helpful by offering you a few suggestions, but the CalDAV service isn’t listed there. We need to add it. In the Service Type field, enter _caldavs._tcp. If you’re not using SSL, remove the s from caldavs.

For Host Name, enter your hostname. I will be entering mavericks.pretendco.com. As we are using SSL, we’ll put in 8443 as that is the default SSL port for CalDAV. If for some reason you decided you aren’t using SSL, you should enter 8008 as the port instead.

If you’re using multiple servers for collaboration, you can specify different priority and weight numbers. In a normal environment with one server, we will enter 0 for priority, and 1 for weight, as they are the defaults. Leave Text blank, we don’t need it.

For a more readable list, see below:

  • Zone: pretendco.com
  • Service Name: Leave Blank!
  • Service Type: _caldavs._tcp
  • Host Name: mavericks.pretendco.com
  • Port: 8443
  • Priority: 0
  • Weight: 1
  • Text: Leave Blank!

You should now see something like this:

The CalDAV SRV Record.

The CalDAV SRV Record.

To double-check this is working, enter the following command in Terminal:

dig SRV _caldavs._tcp.pretendco.com

With any hope, you should see the following result:

; <<>> DiG 9.8.3-P1 <<>> SRV _caldavs._tcp.pretendco.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 21649
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1

;_caldavs._tcp.pretendco.com.	IN	SRV

_caldavs._tcp.pretendco.com. 10800 IN	SRV	0 1 8443 mavericks.pretendco.com.

pretendco.com.		10800	IN	NS	mavericks.pretendco.com.

mavericks.pretendco.com. 10800	IN	A

;; Query time: 0 msec
;; WHEN: Sat Oct 19 16:28:47 2013
;; MSG SIZE  rcvd: 118

Hooray! Your SRV record is now working correctly. Go over to the Calendar app and we can set up a user account. Open Preferences in the Calendar app and jump over to the Accounts section, then click the + (plus) to add a new account

Add a New Account in the Calendar app.

Add a New Account in the Calendar app.

Now, choose the option “Add CalDAV Account…” and then click Continue.

Add Our User Using the "Automatic" Method.

Add Our User Using the "Automatic" Method.

Because we set up the SRV record, we don’t have to choose the “Manual” or “Advanced” options. Type in your email address and password, then click Create. For example, the user Jim Halpert that we set up earlier, we would enter the details below:

  • Email Address: jhalpert@pretendco.com
  • Password: pam

Once you’ve clicked Create, you should be taken back to the Accounts pane of Preferences. The first thing I change is the Description to the first name of the user. For example, I’ll change it to Jim. The only other option you might want to change is the Availability field.

Account Information for the User Jim Halpert.

Account Information for the User Jim Halpert.

Email Invitations

First up, we’ll configure our Email user that will be able to send and receive calendar invitations. To do this, check the box next to “Enable invitations by email”. This will run you through a few steps of configuration, most of which you shouldn’t have to change.

Set Up A Calendar Email User.

Set Up A Calendar Email User.

The first setting to review is the email address of the Calendar user. Normally, I would leave this as com.apple.calendarserver@mavericks.pretendco.com, but you can change it to another user (if you’ve already added them into the Open Directory database). It would be wise to leave it alone.

Enter the Calendar Email User IMAP Details.

Enter the Calendar Email User IMAP Details.

Next up is configuring the incoming mail server settings for the Calendar email user. If the server you’re configuring is the same server as your Mail server, you won’t have to change a thing. Otherwise, you’ll have to enter your Mail server settings for IMAP (or POP, but please tell me you’re using IMAP!). Note that the email address you chose in the first step should match the user name for authentication.

Enter the Calendar Email User SMTP Details.

Enter the Calendar Email User SMTP Details.

Now it’s time to configure the SMTP server settings for sending Calendar invitations. Like above, you may not have to change any settings at all, but if you’re using another Mail server, enter the configuration details as applicable.

Double-Check Your Email User Settings.

Double-Check Your Email User Settings.

Finally, ensure all your settings are correct before clicking Finish. Once you click Finish, the Calendar server will restart to save those changes. Now you’re all done configuring mail for the Calendar service. For the curious, enter sudo serveradmin settings calendar | grep "iMIP" to see all the settings for the sending and receiving of Calendar invitations by email.

If you create a sample event then invite yourself using an email address, you’ll get an email invitation that has some interesting information that you can look at.

You’ll notice that the reply-to email address is in the format calendar-email-user+event-guid@domain.com. For example, a sample event I did had the reply-to email address com.apple.calendarserver+35f7b7c1-1295-4513-a9b7-c859ec3a7d94@mavericks.pretendco.com. This uses the concept of email address tagging whereby you have the local part of the email address (com.apple.calendarserver, mscott, etc) then you add a + (plus) and enter the tag. What this does is allows the mail server to do is, using a combination of rules, direct email flow depending on what tag it has. A few modern mail providers (like Gmail) support tagging. Essentially, if I replied to the email address com.apple.calendarserver+35f7b7c1-1295-4513-a9b7-c859ec3a7d94@mavericks.pretendco.com, the inbuilt mail server would know that this email is related to the event that has a GUID of 35f7b7c1-1295-4513-a9b7-c859ec3a7d94. Pretty clever huh?

Another neat’o trick is when you invite someone who isn’t in Open Directory domain they’ll get an email with the event details, along with an .ics that they can add to their own calendar! For those curious about what an .ics (or iCalendar file) contains, take a look below:

X-WR-CALNAME:Board Meeting
PRODID:-//Apple Inc.//Mac OS X 10.9//EN
X-APPLE-STRUCTURED-LOCATION;VALUE=URI;X-TITLE="Meeting Room 1, 13927 Saticoy Street, Panorama City, CA 91402, USA":
ORGANIZER;CN="Michael Scott";EMAIL="mscott@pretendco.com":urn:uuid:1C3F7FD2-2ECA-4F5E-A332-458D59BF3EAE
LOCATION:Meeting Room 1\, 13927 Saticoy Street\, Panorama City\, CA 91402\, USA
DESCRIPTION:Be sure to bring the monthly reports.
X-CALENDARSERVER-ATTENDEE-COMMENT;X-CALENDARSERVER-ATTENDEE-REF="urn:uuid:B6103F55-0E50-4254-80B45CFF73E32B8E";X-CALENDARSERVER-DTSTAMP=2013101 9T003950Z:Will bring this months estimates too!
SUMMARY:Board Meeting
ATTENDEE;CN="Michael Scott";CUTYPE=INDIVIDUAL;EMAIL="mscott@pretendco.com";PARTSTAT=ACCEPTED:urn:uuid:1C3F7FD2-2ECA-4F5E-A332-458D59BF3EAE

And here is the event in Calendar:

The Board Meeting event as it appears in the Calendar app.

The Board Meeting event as it appears in the Calendar app.

Resources & Locations

As with almost any other calendaring solution, OS X Mavericks Server has the ability to define unique resources and locations. These resources and locations are defined as invitees so you can allocate them events as, you guessed it, resources and locations.

For example, say the company has a car that can be used by employees for onsite visits or meetings. For them to use the car, they first have to allocate it to their event. If the car is already being used by someone else, they will be told when adding the car that it is not available, otherwise, they’ll be able to add the car to the event and have it assigned to them. First, we need to create the car resource!

Resource: PretendCo Car

Resource: PretendCo Car

In the “Locations and Resources” section of the Calendar pane in the Server app you’ll see a + (plus) in the bottom-left corner. Click it to create a new Location or Resource. Since the car is obviously a resource and not a location, we’ll make the Type a “Resource”.

Next, we need to give the resource a unique name. Given that PretendCo only has one car, we’ll call the resource “PretendCo Car”. We’re going to trust our employees enough to be able to organise the car amongst themselves so we won’t require the resource to be approved by a delegate.

Finally, with Delegate, I’m going to leave it blank. You can however enter a username or groupname that can both view and manage the resource (or location). Even though you have automatically accept requests for this resource, delegates can override that status to manually deny a request.

Click Create to create your first resource! You can now assign this resource in an event by entering “PretendCo Car” as an invitee. Give it a go, you’ll see that the PretendCo car is automatically approved.

Next up is Locations. Locations, like Resources, give you the ability to define specific locations that are applicable for your server, and allow people to assign locations to their events. Along with resources, these can be reserved, and give users that are trying to organise times for locations the ability to check their availability.

Location: Meeting Room 1

Location: Meeting Room 1

Like we did with resources, click the plus in the bottom-left corner to create a new location. Make sure to change the Type to Location in the drop down menu. You need to ensure that locations are actually added as locations, because you add them in a different place when creating an event.

Next we give it a name. I’m going to go with “Meeting Room 1” because it’s simple. Because this is a meeting room, I’m going to make the Management group approve every request to use the room. Why? Because I can. And it’s a good reason to talk about delegation. With that in mind, change Accepted Invitations to “With Delegate Approval” in the drop down menu.

In the Delegate field you can enter either a username, or a group name if you’d like a specific group to manage delegation. For example, if you have one person in the company you trust to manage delegation, enter that person’s username into the field. Otherwise, you may have a group of people that manage delegation, so enter their group name in.

Finally, for Accept Group, you can enter the name of a group that this location will automatically accept requests from, even if you require invitations to be accepted with delegate approval. Typically, you would probably add your Management group to that list. For PretendCo, I did.

Click Create and you have now created your first location. Open up the Calendar app and create an event. The field down from the event title is location. Start typing in Meeting Room 1, Calendar should predict you’re going to invite Meeting Room 1, so click on it (or press Return). Note that if you assign a location that’s in the Open Directory domain, you can add a secondary location, i.e. the address of said Meeting Room 1. See my event below for an example of two locations being assigned for 1 event.

Calendar Event with a Location and Address.

Calendar Event with a Location and Address.

OS X Mavericks Server - Adding New Users

Adding users to your server is probably going to be something you will end up doing the most once the server has been configured, so it’s important that you’re doing right. Personally I’ve found to be the most valuable tip when creating users is to… keep it consistent! I’ve been brought into far too many environments when the shortnames, email addresses and even names are inconsistent. Personally, it drives me nuts and can cause confusion between staff about what their username is.


  • SACLs
  • User Templates

Before we start, here’s my style guide:

  • Name: Firstname Surname
  • Shortname: fsurname
  • Email: fsurname@pretendco.com

You’d think it’s pretty basic and obvious, but you’d be surprised how many people forgo style and consistency. Now, how about we get to creating users.

Open the Server app and go to the “Users” tab. If you’re using Open Directory (which you should be!), ensure you’re looking at “Local Network Users”. You’d hate to add users to the server, only to find that you’ve added them to the local domain, rather than the Local Network Domain (Your Open Directory domain). So far, you should only see the Directory Administrator user. Let’s change that. Click the + (plus) in the bottom-left corner to add a user!

  • Full Name: the full name of the user you’re adding. This is required, but does not have to be unique. While your Mac will require unique Full Names, Open Directory will allow you to have multiple users with the same Full Name.
  • Short Name: the shortname of the user you’re adding. This is also required, and must be unique. You will not be able to add more than one user with the same shortname, so if you have two people with the shortname jhalpert, consider having a counter at the end of the shortname, e.g. jhalpert, jhalpert2, jhalpert3 and so on. I opt to have the first user with no number because you may not always know if someone with the same shortname will be added the server, so it just looks neater to have no numbers on the end of the first shortname.
  • Email: the email for the user. This field isn’t required, and you can use it even if your server isn’t running Mail services. It’s purely cosmetic, and is used for the global address list in the Open Directory domain. Note: if you do use this field, but enter a different username and are running Mail on the server you must add an alias for that shortname, if you have jhalpert as the user shortname, but jim as the email username, Jim won’t receive email to jim until that name has been entered as an alias (coming up soon).
  • Password & Verify: enter the users password twice. Best to generate a password, save it to a Numbers document then distribute the password to each user. Otherwise, set a generic one then require them to change password on next login.
  • Allow user to administer this server: having this checked enables the user to successfully authenticate and have full authorisation for the Server app. Use it wisely.
  • Home Folder: I absolutely despise networked home folders, they screw up so often and are very hard to fix (sometimes impossible to fix). I will always change this to None - Services Only. Takes up less space on the server too, as it doesn’t generate a home folder in /Users.
  • Keywords: Add keywords for your user. This field is not required, and acts as a tag field for the user. It’s new to the GUI for Mavericks Server. I have yet to see a solid use case for this field, but I’m sure someone is using it to the full effect.
  • Notes: Add notes for the user. Like keywords, this field is optional, and again, I’ve yet to see a good use for this field.

Given that I love the hit TV show The Office (US) (P.S. I really love the UK original too), I’m going to use fake users that are named after main characters from the show. My first user will be Jim Halpert. Following the style guide as above, you’ll be entering something like this:

  • Full Name: Jim Halpert
  • Account Name: jhalpert
  • Email: jhalpert@pretendco.com
  • Password: a random password of your choice (for this example, I just did pam)
  • Home Folder: None - Services Only
  • Keywords: sales
  • Notes: Often plays pranks on Dwight.

Note: In reality, keywords and notes aren’t important to the functionality of OS X Server and Open Directory, it can help with usability, however. Note that adding the keyword sales won’t add them to a group called sales. Keywords are purely for easy searching.

Adding a New User: Jim Halpert.

Adding a New User: Jim Halpert.

I’ve also added a picture for Jim, I suspect most people don’t realise you can drag and drop and image file onto the generic user picture to add a picture for that person.

Once you’ve added those details, click “Create” to add the user! If there’s any errors, you’ll be notified and the window won’t change, otherwise, you should be redirected back to the Users list (with your new user in the list!)


A handy feature in the Server app is the ability to restrict specific users to specific services. For example, you might say that newer employees are not allowed access to the VPN service, or maybe you want a shared account that only has access to File Sharing or collaboration services.

First off, what is a SACL? SACL stands for Service Access Control List, which, as the name would suggest, are lists that define user and group access to each service in OS X Mavericks Server. The lists themselves aren’t necessarily files in OS X, they’re memberships to specific groups in the local directory. For example, the service Contacts is actually a membership to the group com.apple.access_addressbook.

The SACL Groups in OS X Server.

The SACL Groups in OS X Server.

By default, all users are allowed access to all services. To change a specific users access to a group, you can do one of two things. The first option is to right click on the user (in the Users list) and then click “Edit Access to Services…”. You’ll be shown a list of the most common services (note: not all the services), where you can uncheck each box you don’t want the user to have access too.

Alternatively, you can go to the Groups section of the Server app and change the membership there. First off, you’ll have to enable to option to see system accounts, as they are hidden by default. Go up to View, then click on “Show System Accounts”. Now you’ll see a huge list of accounts, lots with interesting names. Scroll down until you get to the groups starting with com.apple.access_. If you open up those groups, you can add and remove members from there. Otherwise, you can go to the user in the Users section of the Server app and add or remove group memberships from there.

User Templates

New in OS X Mavericks Server is the ability to add users that conform to a specified template. You might decide that most users only need access to AFP, Contacts, Calendars, and Mail. You also decide that they won’t have a home folder (services only) on the server and cannot administer the server. To make a template, go to the Users section in Server app, then click the gear in the bottom-left corner and click on the “Edit Templates…” button.

The User Template window with no templates.

The User Template window with no templates.

Hit the plus to create a new template! I’m going to call mine Standard Sales User as I want to use it for all standard sales people.

Our Standard Sales User Template.

Our Standard Sales User Template.

Next, I’m going to ensure that “administer this server” is unticked, because standard sales users shouldn’t be allowed to modify the server in any way! Next, change home folder to “None - Services Only”. Then, change Login shell to “/bin/bash/false” (the default for OS X Mavericks Server).

Leave the Primary Group as staff, you don’t want to mess with that as the user may never be able to log in. Next up, with groups we can utilise what we learnt with SACLs to restrict what groups (and services) they have access too. As with all users, I’ll put them in the default “Workgroup” group, but we’ll also add them to a few other groups. As I mentioned, I want to restrict these users to only having access to several services. These services are AFP, Contacts, Calendars and Mail. Click the + (plus) for adding groups, and enter the following groups: com.apple.access_afp, com.apple.access_addressbook, com.apple.access_calendar and com.apple.access_mail.

If you want to add or remove any other services, refer to the list below which has the service name and group name for the Services in OS X Mavericks Server.

  • Contactscom.apple.access_addressbook
  • AFPcom.apple.access_afp
  • Time Machinecom.apple.access_backup
  • Calendarcom.apple.access_calendar
  • iMessagecom.apple.access_chat
  • Profile Managercom.apple.access_devicemanagement
  • FTPcom.apple.access_ftp
  • Mailcom.apple.access_mail
  • RADIUScom.apple.access_radius
  • SMBcom.apple.access_smb
  • VPNcom.apple.access_vpn

Finally, you can add keywords and notes for the user template. I’m just going to add sales for a keyword, and that’s it. Finally, click “Done” to add the template. Now to test out the template!

You’ll now notice that when you go to add a new user, at the top of the form you’ll have a new field called “Template” that has a drop-down menu of all your templates! I’m going to enter a fake account for a user called John Citizen. Check the image below for my configuration:

User John with Standard Sales User Template.

User John with Standard Sales User Template.

Now, click “Create” to create the user from the specified “Standard Sales User” template. Once the user has been created, right-click on the user then click “Edit Access to Services…”. This will bring a window that shows you all the services John Citizen is a member for. As you’ll see, all the services we entered above are ticked (with exception for File Sharing, as that combines AFP and SMB).

John and his Services.

John and his Services.

Excellent, John has the right privileges and is associated with the right groups, all thanks to our user template! I believe at this stage the User Template system is still in its infancy, but could grow to become a really powerful tool. I’d love to see the ability to customise the way it grabs the full name and brings that across to short name and email address.

OS X Mavericks Server - Setting Up Mail

So far in these posts you should have set up your OS X Mavericks Server, DNS, and set up an Open Directory Master, but now you’d like to set up Mail so you communicate with other people. Luckily, the initial set up of Mail is pretty easy, but there can be a few gotchas.


  • Extra Configuration Options
  • Virtual Domains

Firstly, before setting up Mail you must make sure you can connect to the internet. This may sound like a strange requirement, but if you start Mail for the first time and you’re not connected to the internet, Mail won’t start because ClamAV won’t start because it can’t download the latest anti-virus definitions and will time out. When testing, Mail wouldn’t start for 10 minutes before I gave up because ClamAV and Amavis couldn’t connect to the internet and would not start, thus causing the rest of the Mail services to throttle respawn and re-launch every 6-10 seconds. Fun!

Before continuing, make sure you’ve completed everything in the server set up, DNS configuration, and Open Directory posts to ensure your DNS and server is healthy.

OK, we’re now ready to click that big On button in Server app to start Mail, but before we do, open up Console, then under /Library/Logs, expand the Mail disclosure arrow and click on mail-info.log (or tail -f /Library/Logs/Mail/mail-info.log) to check out what happens in the backend when you start Mail. There’s also a few other logs you can take a gander at when starting the service, check them out in that same Mail section in Console.

Mail, The Service is now Running.

Mail, The Service is now Running.

Within a few minutes you should see that the status for Mail has changed to “Available at <your domain>”. As with Open Directory (and all other standard OS X Server services), you can query the basic status of Mail by entering the following:

sudo serveradmin status mail

And you’re receive the rather generic response (at least it’s concise):

mail:state = "RUNNING"

Now, if you’d like some more information regarding the status of Mail, its log paths, and which of the Mail services are running, you can enter the following:

sudo serveradmin fullstatus mail

And you’ll get something like this:

mail:startedTime = "2013-10-08 08:11:34 +0000"
mail:setStateVersion = 1
mail:state = "RUNNING"
mail:protocolsArray:_array_index:0:status = "ON"
mail:protocolsArray:_array_index:0:kind = "INCOMING"
mail:protocolsArray:_array_index:0:protocol = "IMAP"
mail:protocolsArray:_array_index:0:state = "RUNNING"
mail:protocolsArray:_array_index:0:service = "MailAccess"
mail:protocolsArray:_array_index:0:error = ""
mail:protocolsArray:_array_index:1:status = "ON"
mail:protocolsArray:_array_index:1:kind = "INCOMING"
mail:protocolsArray:_array_index:1:protocol = "POP3"
mail:protocolsArray:_array_index:1:state = "RUNNING"
mail:protocolsArray:_array_index:1:service = "MailAccess"
mail:protocolsArray:_array_index:1:error = ""
mail:protocolsArray:_array_index:2:status = "ON"
mail:protocolsArray:_array_index:2:kind = "INCOMING"
mail:protocolsArray:_array_index:2:protocol = "SMTP"
mail:protocolsArray:_array_index:2:state = "RUNNING"
mail:protocolsArray:_array_index:2:service = "MailTransferAgent"
mail:protocolsArray:_array_index:2:error = ""
mail:protocolsArray:_array_index:3:status = "ON"
mail:protocolsArray:_array_index:3:kind = "OUTGOING"
mail:protocolsArray:_array_index:3:protocol = "SMTP"
mail:protocolsArray:_array_index:3:state = "RUNNING"
mail:protocolsArray:_array_index:3:service = "MailTransferAgent"
mail:protocolsArray:_array_index:3:error = ""
mail:protocolsArray:_array_index:4:status = "OFF"
mail:protocolsArray:_array_index:4:kind = "INCOMING"
mail:protocolsArray:_array_index:4:protocol = ""
mail:protocolsArray:_array_index:4:state = "STOPPED"
mail:protocolsArray:_array_index:4:service = "ListServer"
mail:protocolsArray:_array_index:4:error = ""
mail:protocolsArray:_array_index:5:status = "ON"
mail:protocolsArray:_array_index:5:kind = "INCOMING"
mail:protocolsArray:_array_index:5:protocol = ""
mail:protocolsArray:_array_index:5:state = "RUNNING"
mail:protocolsArray:_array_index:5:service = "JunkMailFilter"
mail:protocolsArray:_array_index:5:error = ""
mail:protocolsArray:_array_index:6:status = "ON"
mail:protocolsArray:_array_index:6:kind = "INCOMING"
mail:protocolsArray:_array_index:6:protocol = ""
mail:protocolsArray:_array_index:6:state = "RUNNING"
mail:protocolsArray:_array_index:6:service = "VirusScanner"
mail:protocolsArray:_array_index:6:error = ""
mail:protocolsArray:_array_index:7:status = "ON"
mail:protocolsArray:_array_index:7:kind = "INCOMING"
mail:protocolsArray:_array_index:7:protocol = ""
mail:protocolsArray:_array_index:7:state = "RUNNING"
mail:protocolsArray:_array_index:7:service = "VirusDatabaseUpdater"
mail:protocolsArray:_array_index:7:error = ""
mail:logPaths:Server Error Log = "/Library/Logs/Mail/mail-err.log"
mail:logPaths:IMAP Log = "/Library/Logs/Mail/mail-info.log"
mail:logPaths:Server Log = "/Library/Logs/Mail/mail-info.log"
mail:logPaths:POP Log = "/Library/Logs/Mail/mail-info.log"
mail:logPaths:SMTP Log = "/var/log/mail.log"
mail:logPaths:List Server Log = "/Library/Logs/Mail/listserver.log"
mail:logPaths:Migration Log = "/Library/Logs/MailMigration.log"
mail:logPaths:Virus Log = "/Library/Logs/Mail/clamav.log"
mail:logPaths:Amavisd Log = "/Library/Logs/Mail/amavis.log"
mail:logPaths:Virus DB Log = "/Library/Logs/Mail/freshclam.log"
mail:imapStartedTime = "2013-10-08 08:11:34 +0000"
mail:postfixStartedTime = "2013-10-08 08:12:20 +0000"
mail:servicePortsRestrictionInfo = _empty_array
mail:servicePortsAreRestricted = "NO"
mail:connectionCount = 0
mail:readWriteSettingsVersion = 1
mail:serviceStatus = "ENABLED"

Hooray, Mail is now working and running! You can quickly test to see if SMTP is up by telnetting in. To do that, you would enter this (assuming you’re running the command on that box):

telnet 25

If you receive a message like the one below, you’re off to a good start:

Connected to localhost.
Escape character is '^]'.
220 mavericks.pretendco.com ESMTP Postfix

Otherwise, if SMTP isn’t running, telnet’s connection will time out. Given that you’re telnetting in on the same machine, it should be almost instant. If the service is running but telnet takes longer than a second, something is horribly wrong.

Extra Configuration Options

With the Mail service, you have a lot of configuration options which you can change, some of which can be changed through the Server app interface, but the majority of changes are done through Terminal. I’m going to go over a few common ones now.

First up, I disable cleartext authentication, and roll with using Open Directory authentication only. To do this, I go to the Mail tab in the Server app, then click on “Edit…” to the right of “Authentication:“.

Mail Authentication Settings.

Mail Authentication Settings.

Click on the drop-down box next to “Authenticate using:” and select “Open Directory”. This will use Kerberos, CRAM-MD5 and Digest-MD5 to authenticate users. I despise cleartext, and since we’ll be disabling POP (or POOP… get it?) very shortly, we’ll want APOP disabled too. Click OK to save the changes.

Next up is disabling POP, and it’s finally time to start using the command line to full effect! The majority of Mail settings can be changed using the friendly serveradmin command. let’s do it now:

sudo serveradmin settings mail:imap:enable_pop = no

Great, we’ve told the Mail service (Dovecot to be precise) that we no longer want to use POP anymore, but that change won’t come into effect until you restart the service. To do that, you’ll need to enter two commands:

sudo serveradmin stop mail
sudo serveradmin start mail

This should only take a few seconds. If you run sudo serveradmin fullstatus mail you’ll see that the STATUS for POP is now OFF. Even though it says RUNNING below, the POP server is actually not running, and does not respond to requests (because it’s not running). The last setting that I would change in a standard setup is the change to an email subject when OS X Server believes the email is spam. I prefer to change it from ***JUNK MAIL*** to ***FLAGGED AS SPAM***. To make this change, you’ll need to command line it:

sudo serveradmin settings mail:postfix:spam_subject_tag = "***FLAGGED AS SPAM***"

Press Enter then do the serveradmin stop start commands (and dance). Now your spam emails will be more obviously marked as spam!

Virtual Domains

One handy feature of the Mail service is the ability to add virtual domains. “What are virtual domains?” I hear you ask. Say, for example, that you have a few domains you want to provide email for. You might have pretendco.com and example.net and you want to provide mail for both of those domains. It’s pretty easy to set up, but there are a few very important caveats that you must be aware of before using this feature.

Mail: No Virtual Domains Configured.

Mail: No Virtual Domains Configured.

  1. Certificates: The Mail service will use the certificate that is assigned to the Mail service, or the default certificate. This means that if you’ve set up Mail to use the certificate mavericks.pretendco.com, any user that adds an account for mavericks.example.net in Mail (or any other email client), they’ll get a certificate warning. While I’m no security expert (nor do I claim to be), I know it’s not good practice to tell your users to blindly skip any certificate mismatch errors. Some people with more restrictive IMAP servers may reject emails because the domain of the email sender doesn’t match the SSL certificate of the server it came from.
  2. Unified Inbox (not in the cool, power-user way): OS X Server only defines one inbox for each user, so emails to jhalpert@pretendco.com and jhalpert@example.net will go to the same inbox, which can get pretty darn confusing. If one account is a personal account and the other is business, users may send to and/or from the wrong account.

With that in mind, setting up virtual domains is a pinch. First off, you’ll need to configure the DNS service in Server to add records for your primary zone. See the image below for how I configured DNS for example.net.

DNS for example.net

DNS for example.net

Next, in Server app, go to the Mail section and click on the Edit button for “Provide Mail for”. Your primary domain will be at the top in the “Domain Name” field, but you’ll see in Virtual Domains, you can provide a list of other domain names that this Mail server can also provide Mail services for. For this example, I’m going to provide Mail for example.net. I’ll click the little + (plus) in the corner to add a new line. Enter in example.net then click OK.

Mail: Virtual Domains List with example.net

Mail: Virtual Domains List with example.net

Quickly verify the MX record has been set up correctly by using the domain information groper (DiG) by entering the following command:

dig mx example.net

You should see that the A record for mavericks.example.net is the same IP address as mavericks.pretendco.com.

DiG of example.net's MX record.

DiG of example.net's MX record.

Next, we need to add the email address for the user(s) who will receive email at both @pretendco.com and @example.net. Make sure you’ve got a copy of Workgroup Manager (don’t? Download here). Open it up and connect to the server. Click on the user you want, then select the “Info” tab. Hit the plus to the right of the “Email” field then enter the new email address.

Multiple Email Accounts for Jim Halpert.

Multiple Email Accounts for Jim Halpert.

The step above is a critical step. If you don’t add the email address for the user into the “virtual alias table”, you’ll get an error like below:

User Doesn't Exist In the Virtual Alias Table.

User Doesn't Exist In the Virtual Alias Table.

Alrighty then, everything is now ready to send and receive email through your virtual domain! Let’s now open our Mail program and set up the account. I’ve already set up the PretendCo email, along with the Example email account also.

Jim Halpert @ PretendCo Inbox.

Jim Halpert @ PretendCo Inbox.

Jim Halpert @ Example Inbox.

Jim Halpert @ Example Inbox.

Different Email Domains, Same Inbox.

As you can see, both emails accounts technically link up to the same inbox, which can be quite confusing. This will get you up and running with virtual domains, but make sure you or your users pay close attention to every email and the address they came to if they’ve got multiple accounts set up in the one mail client.