Tiny Deathstars of Foulness

In past versions of this guide, I covered Time Machine Server. Here, we’re going to look at backing up the settings of a macOS Server using Bender. To do so, we’re going to install a little app called Bender from the great folks at Robot Cloud. You can download that from
Screen Shot 2015-09-24 at 10.51.00 PM
Once downloaded, run the package installer.
Screen Shot 2015-09-24 at 10.49.32 PM
At the Welcome to Bender screen, click Continue.
Screen Shot 2015-09-24 at 10.52.03 PM
Agree to the licensing agreement by clicking the Continue button. Screen Shot 2015-09-24 at 10.52.22 PM
Click Agree again (assuming of course that you agree to the license). Screen Shot 2015-09-24 at 10.52.57 PM
Choose who you wish to install the software for and click Continue. Screen Shot 2015-09-24 at 10.53.52 PM
I’d go ahead and install Bender at the default location, so click Install. Once the installer is complete, you can view the installed LaunchDaemon at /Library/LaunchDaemons/net.robotcloud.bender.plist. Note that it calls the /usr/local/robotcloud/bin/bender binary when run at 22:00 every day. If you edit this file, the following settings are available:

host=$(hostname) macOS=$(sw_vers | awk ‘/ProductVersion/{print substr($2,1,5)}’ | tr -d “.”) macSN=$(system_profiler SPHardwareDataType | awk ‘/Serial Number/{print $4}’) date=$(date +%Y-%m-%d-%H%M) pass=$(system_profiler SPHardwareDataType | awk ‘/Hardware UUID/{print $3}’) logPath=”/usr/local/robotcloud/logs/bender.log” pipPath=”/usr/local/robotcloud/bin/scroobiuspip” pipTitle=”Bender Backup Error on: $macSN” backupDestination=”/Backups/$date” keepUntil=”14″ version=”2.3″ versionCheck=”$1″

The most important of these is the backupDestination. You can set this to be the /Backups folder as it is above, or set it to be an external drive. Either should be backed up using your standard backup software.

September 28th, 2017

Posted In: Mac OS X Server

Tags: , , , , ,

macOS Server 5.4, running on High Sierra, comes with a number of alerts that can be sent to administrators via servermgrd and configured since the 5th version of the Server app. To configure alerts on the server, open the Server app and then click on Alerts in the Server app sidebar.

Next, click on the Delivery tab.


At the Delivery screen, click on the Edit button for Email Addresses and enter every email address that should receive alerts sent from the server. Then click on the Edit button for Push Notifications. Here, check the box for each administrator of the server. The email address on file for the user then receives push notifications of events from the server.


Then, check the boxes for Email and Push for each of the alerts you want to receive (you don’t have to check both for each entry). Alerts have changed in macOS Server, they are no longer based on the SMART status of drives or capacity; instead Delivery is now based on service settings.

September 27th, 2017

Posted In: Mac OS X Server

Tags: , , , ,

DHCP, or Dynamic Host Control Protocol, is the service used to hand out IP addresses and other network settings by network appliances and servers. The DHCP Server built into macOS Server 5.4 on High Sierra is similar to the DHCP service that was included in Server 10.2 and 10.2 and from the good ‘ole Panther days. It’s pretty simple to use and transparent, just as DHCP services should be.

To install the service, open the Server app and then click on the Show button beside Advanced in the server sidebar. Then click on DHCP.
At the DHCP screen, you’ll see two tabs: Settings, used for managing the service and Clients, used to see leases in use by computers that obtain IP address information from the server. You’ll also see an ON and OFF switch, but we’re going to configure our scopes, or Networks as they appear in the Server app, before we enable the service. To configure a scope, double-click on the first entry in the Networks list.
Each scope, or Network, will have the following options:
  • Name: A name for the scope, used only on the server to keep track of things.
  • Lease Duration: Select an hour, a day, a week or 30 days. This is how long a lease that is provided to a client is valid before the lease expires and the client must find a new lease, either from the server you’re configuring or a different host.
  • Network Interface: The network interface you’d like to share IPs over. Keep in mind that you can tag multiple VLANs on a NIC, assign each an interface in OS X and therefore provide different scopes for different VLANs with the same physical computer and NIC.
  • Starting IP Address: The first IP address used. For example, if you configure a scope to go from to you would have 50 useable IP addresses.
  • Ending IP Address: The last IP address used in a scope.
  • Subnet Mask: The subnet mask used for the client configuration. This setting determines the size of the network.
  • Router: The default gateway, or router for the network. Often a .1 address for the subnet used in the Starting and Ending IP address fields. Note that while in DHCP you don’t actually have to use a gateway, OS X Server does force you to do so or you cannot save changes to each scope.
  • DNS: Use the Edit button for DNS to bring up a screen that allows you to configure the DNS settings provided as part of each DHCP scope you create, taking note that by default you will be handing out a server of if you don’t configure this setting.
The DNS settings in the DHCP scope are really just the IP addresses to use for the DNS servers and the search domain. The search domain is the domain name appended to all otherwise incomplete Fully Qualified Domain Names. For example, if we use internal.krypted.lan and we have a DNS record for wiki.internal.krypted.lan then we could just type wiki into Safari to bring up the wiki server. Click the minus sign button to remove any data in these fields and then click on the plus sign to enter new values.
Click OK to save DNS settings and then OK to save each scope. Once you’ve build all required scopes, start the service. Once started, verify that a new client on the network gets an IP. Also, make sure that there are no overlapping scopes and that if you are moving a scope from one device to another (e.g. the server you’re setting up right now) that you renew all leases on client systems, most easily done using a quick reboot, or using “ipconfig /release” on a Windows computer. If you have problems with leases not renewing in macOS, check out this article I did awhile back. So far, totally easy. Each time you make a change, the change updates a few different things.

First, it updates the /etc/bootpd.plist property list, which looks something like this (note the correlation between these keys and the settings in the above screen shots.:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" ""> <plist version="1.0"> <dict> <key>NetBoot</key> <dict/> <key>Subnets</key> <array> <dict> <key>allocate</key> <true/> <key>dhcp_domain_name</key> <string></string> <key>dhcp_domain_name_server</key> <array> <string></string> </array> <key>dhcp_domain_search</key> <array/> <key>dhcp_router</key> <string></string> <key>lease_max</key> <integer>3600</integer> <key>name</key> <string>192.168.210 Wi-Fi</string> <key>net_address</key> <string></string> <key>net_mask</key> <string></string> <key>net_range</key> <array> <string></string> <string></string> </array> <key>selected_port_name</key> <string>en0</string> <key>uuid</key> <string>B03BAE3C-AB79-4108-9E5E-F0ABAF32179E</string> </dict> </array> <key>allow</key> <array/> <key>bootp_enabled</key> <false/> <key>deny</key> <array/> <key>detect_other_dhcp_server</key> <false/> <key>dhcp_enabled</key> <false/> <key>old_netboot_enabled</key> <false/> <key>relay_enabled</key> <false/> <key>relay_ip_list</key> <array/> </dict> </plist>

Settings from this file include:
  • dhcp_enabled – Used to enable dhcp for each network interface. Replace the <false/> immediately below with <array> <string>en0</string> </array>. For additional entries, duplice the string line and enter each from ifconfig that you’d like to use dhcp on.
  • bootp_enabled – This can be left as Disabled or set to an array of the adapters that should be enabled if you wish to use the bootp protocol in addition to dhcp. Note that the server can do both bootp and dhcp simultaneously.
  • allocate – Use the allocate key for each subnet in the Subnets array to enable each subnet once the service is enabled.
  • Subnets – Use this array to create additional scopes or subnets that you will be serving up DHCP for. To do so, copy the entry in the array and paste it immediately below the existing entry. The entry is a dictionary so copy all of the data between and including the <dict> and </dict> immediately after the <array> entry for the subnet itself.
  • lease_max and lease_min – Set these integers to the time for a client to retain its dhcp lease
  • name – If there are multiple subnet entries, this should be unique and reference a friendly name for the subnet itself.
  • net_address – The first octets of the subnet followed by a 0. For example, assuming a /24 and 172.16.25 as the first three octets the entry would be
  • net_mask – The subnet mask clients should have
  • net_range – The first entry should have the first IP in the range and the last should have the last IP in the range. For example, in the following example the addressing is to
  • dhcp_domain_name_server – There should be a string for each DNS server supplied by dhcp in this array
  • dhcp_domain_search – Each domain in the domain search field should be suppled in a string within this array, if one is needed. If not, feel free to delete the key and the array if this isn’t needed.
  • dhcp_router – This entry should contain the router or default gateway used for clients on the subnet, if there is one. If not, you can delete the key and following string entries.
If you run the serveradmin command, followed by the settings verb and then the dhcp service, you’ll see the other place that gets updated:

serveradmin settings dhcp

The output indicates that

dhcp:static_maps = _empty_array
dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:WINS_secondary_server = ""
dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:selected_port_name = "en0"
dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:dhcp_router = ""
dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:dhcp_domain_name_server:_array_index:0 = ""
dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:net_mask = ""
dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:WINS_NBDD_server = ""
dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:net_range_start = ""
dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:lease_max = 3600
dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:dhcp_domain_search:_array_index:0 = "internal.krypted.lan"
dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:descriptive_name = "192.168.210 Wi-Fi"
dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:WINS_primary_server = ""
dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:net_range_end = ""
dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:dhcp_ldap_url = _empty_array
dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:WINS_node_type = "NOT_SET"
dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:net_address = ""
dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:dhcp_enabled = yes
dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:dhcp_domain_name = "internal.krypted.lan"
dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:WINS_scope_id = ""
dhcp:subnet_defaults:logVerbosity = "MEDIUM"
dhcp:subnet_defaults:WINS_node_type_list:_array_index:0 = "BROADCAST_B_NODE"
dhcp:subnet_defaults:WINS_node_type_list:_array_index:1 = "HYBRID_H_NODE"
dhcp:subnet_defaults:WINS_node_type_list:_array_index:2 = "NOT_SET"
dhcp:subnet_defaults:WINS_node_type_list:_array_index:3 = "PEER_P_NODE"
dhcp:subnet_defaults:WINS_node_type_list:_array_index:4 = "MIXED_M_NODE"
dhcp:subnet_defaults:dhcp_domain_name = ""
dhcp:subnet_defaults:WINS_node_type = "NOT_SET"
dhcp:subnet_defaults:routers = _empty_dictionary
dhcp:subnet_defaults:logVerbosityList:_array_index:0 = "LOW"
dhcp:subnet_defaults:logVerbosityList:_array_index:1 = "MEDIUM"
dhcp:subnet_defaults:logVerbosityList:_array_index:2 = "HIGH"
dhcp:subnet_defaults:dhcp_domain_name_server:_array_index:0 = ""
dhcp:subnet_defaults:selected_port_key = "en0"
dhcp:subnet_defaults:selected_port_key_list:_array_index:0 = "bridge0"
dhcp:subnet_defaults:selected_port_key_list:_array_index:1 = "en0"
dhcp:subnet_defaults:selected_port_key_list:_array_index:2 = "p2p0"
dhcp:subnet_defaults:selected_port_key_list:_array_index:3 = "en1"
dhcp:logging_level = "MEDIUM"

Notice the correlation between the uuid string in /etc/bootp.plist and the arrayid entry for each subnet/network/scope (too many terms referring to the same thing, ahhhh!). Using the serveradmin command you can configure a lot more than you can configure in the Server app gui. For example, on a dedicated DHCP server, you could increase logging level to HIGH (as root/with sudo of course):

serveradmin settings dhcp:logging_level = "MEDIUM"

You can also change settings within a scope. For example, if you realized that you were already using and 201 for statically assigned IPs elsewhere you can go ahead and ssh into the server and change the first IP in a scope to 202 using the following (assuming the uuid of the domain is the same as in the previous examples):

serveradmin settings dhcp:subnets:_array_id:B03BAE3C-AB79-4108-9E5E-F0ABAF32179E:net_range_start = ""

You can also obtain some really helpful information using the fullstatus verb with serveradmin:

serveradmin fullstatus dhcp

This output includes the number of active leases, path to log file (tailing that file is helpful when troubleshooting issues), static mappings (configured using the command line if needed), etc.

dhcp:state = "RUNNING"
dhcp:backendVersion = "10.11"
dhcp:timeOfModification = "2017-9-04 04:24:17 +0000"
dhcp:numDHCPActiveClients = 0
dhcp:timeOfSnapShot = "2017-9-04 04:24:19 +0000"
dhcp:dhcpLeasesArray = _empty_array
dhcp:logPaths:systemLog = "/var/log/system.log"
dhcp:numConfiguredStaticMaps = 1
dhcp:timeServiceStarted = "2017-9-04 04:24:17 +0000"
dhcp:setStateVersion = 1
dhcp:numDHCPLeases = 21
dhcp:readWriteSettingsVersion = 1

Once started, configure reservations using  the /etc/bootptab file. This file should have a column for the name of a computer, the hardware type (1), the hwaddr (the MAC address) and ipaddr for the desired IP address of each entry:

%% # hostname hwtype hwaddr ipaddr bootfile
a.krypted.lan 1 00:00:00:aa:bb:cc
b.krypted.lan 1 00:00:00:aa:bb:cc

You can start and stop the service either using the serveradmin command:

serveradmin stop dhcp serveradmin start dhcp

Or using the launchctl:

sudo /bin/launchctl unload -w /System/Library/LaunchDaemons/bootps.plist sudo /bin/launchctl load -w /System/Library/LaunchDaemons/bootps.plist

You can also add DHCP Reservations, or static maps. To do so, click on the clients tab and then click on the plus sign (“+”). From here, you can add a hostname and IP address to a given MAC address in order to allow that MAC address to always be assigned the IP you’d like.

Finally, you can define DHCP options in /etc/bootp.plist. This process isn’t necessarily support, there is no GUI control for options, and options are not as widely used with devices as they once were. However, it’s absolutely an option if needed.

September 26th, 2017

Posted In: Mac OS X, Mac OS X Server

Tags: , , , , , ,

Previously, we looked at setting up an Open Directory Master in macOS. An Open Directory Replica keeps a copy of the Open Directory database available for users even when the Master goes offline. But it can also take a part of the load from the Open Directory Master and when using the new Locales feature, balance network traffic. To get started with an Open Directory Replica, first enable SSH, now disabled by default. If SSH is not enabled, you will not be able to create an Open Directory Replica. SSH is enabled on a server by opening the Server app, clicking on the name of the server and then clicking on the Settings tab. here, check the box for “Secure shell connections (SSH)”.
Next, use the changeip to check the host name. While the Server app is cool, it caches stuff and I’ve seen it let things go threat shouldn’t be let go. Therefore, in order to make sure that the server has such an address, I still recommend using changeip, but I also recommend using the Server application. In OS X Server, I’ve seen each find things that other misses. Additionally, in Yosemite and above, OS X Server now requires to be able to lookup whatever the hostname is set to in order to actually promote either to a replica or a master. To use changeip to verify the hostname is set appropriately:

sudo changeip -checkhostname

The address and host names should look correct and match what you see in the Server application’s Next Steps drawer.

Primary address = Current HostName = DNS HostName = The names match. There is nothing to change. dirserv:success = “success”

Provided everything is cool with the hostname, use the slapconfig command to preflight a replica prior to promotion. The syntax there is the same as the -createreplica syntax, used as follows, assuming the master has an IP address of

/usr/sbin/slapconfig -preflightreplica diradmin

Provided that the server is ready, open the Server app on a freshly installed computer you want to be your Open Directory replica.

Then, click on the Open Directory service.

Then, use the ON button to start the configuration process. When prompted, click on “Join an existing Open Directory domain as a replica” and click on the Next button.

When prompted, enter the parent Open Directory server’s host name (likely the name of the Open Directory Master), directory admin user name (the diradmin or custom username provided when Open Directory was configured), and then the directory admin password.

Then click on the Next button again to setup the services.

At the Confirm settings screen, click on the Set Up button and the replica is completed provided there are no issues with the configuration. Check Server app on both the Replica and the Master and verify that the server is displayed under the Master.

Once you’ve created your first replica, you can then start to define replica trees, where each replica looks at one above it, which then looks at another. I’ll do another article later on replica trees.

Note: If there are any problems during promotion, I start over every time using slapconfig along with the -destroyldapserver option to nuke everything in OD:

sudo slapconfig -destroyldapserver

Use the logs to help if you’re having replica creation problems. These can be added using the -enableslapdlog option:

sudo slapconfig -enableslapdlog

You can use the -addreplica option to add replicas manually while running tail on the slapd logs:

sudo tail -f /var/log/slapd.log

Once the replica has been created, you can add more and split them into locales. You can also get pretty granular with the slurpd (the daemon that manages Open Directory replication) logs by invoking slurpd with a -d option followed by a number from 4 to 65535, with logging intensity of logs getting more as the number gets higher. You can also use the -r option to indicate a specific log file. If you have more than 32 replicas then it stands to reason that you also have a large number of objects in Open Directory, a fair amount of change occurring to said objects and therefore a fair amount of replication IO. In order to offload this you can move your replication temp directory onto SSD drives, by specifying the -t option when invoking slurpd.

The slurpd replication occurs over port 389 (by default). Therefore, in a larger environment you should be giving priority to network traffic. If you choose to custom make/install slurpd then you’ll also need to go ahead and build your Kerberos principles manually. In this case you would get a srvtab file for the slurpd server and then configure slapd to accept Kerberos Authentication for slaves. Having said this, I haven’t seen an environment where I had to configure slurpd in this fashion.

September 26th, 2017

Posted In: Mac OS X Server

Tags: , , , , ,

Getting started with Messages Server couldn’t really be easier. Messages Server in the macOS Server 5.4 version of the Server app uses the open source jabber project as the back-end code base. The jabber binary is located at /Applications/ directory and the autobuddy binary is at /Applications/ The actual jabberd binary is also stored at /Applications/, where there are a couple of perl scripts used to migrate the service between various versions as well.

Setting up the Messages service is simple. Open the Server app and click on Messages in the Server app sidebar. 

Click on the Edit… button for the Permissions. Here, define which users and interfaces are allowed to use the service.

From Server app, click on the checkbox for “Enable server-to-server federation” if you have multiple Messages servers and provide the address for servers to federate to.

Next, click on the checkbox for “Archive all chat messages” if you’d like transcripts of all Messages sessions that route through the server to be saved on the server.

You should use an SSL certificate with the Messages service. If enabling federation so you can have multiple Messages servers, you have to. Before enabling the service, click on the name of the server in the sidebar of Server app and then click on the Settings tab. From here, click on Edit for the SSL Certificate (which should be plural btw) entry to bring up a screen to select SSL Certificates.

At the SSL Certificates screen (here it’s plural!), select the certificate the Messages service should use from the available list supplied beside that entry and click on the OK button. If you need to setup federation, click back on the Messages service in the sidebar of Server app and then click on the Edit button. Then, click on the checkbox for Require server-to-server federation (making sure each server has the other’s SSL certificate installed) and then choose whether to allow any server to federate with yours or to restrict which servers are allowed. I have always restricted unless I was specifically setting up a server I wanted to be public (like public as in everyone in the world can federate to it, including the gorram reavers that want to wear your skin).

To restrict the service, then provide a list of each server address capable of communicating with your server. Once all the servers are entered, click the OK button. Obviously, if you only have one server, you can skip that. Once the settings are as you wish them to be, click on the ON/OFF switch to light up the service. To see the status of the service, once started, use the fullstatus option with serveradmin followed by the jabber indicator:

sudo serveradmin fullstatus jabber

The output includes whether the service is running, the location of jabber log files, the name of the server as well as the time the service was started, as can be seen here:

jabber:state = "RUNNING"
jabber:roomsState = "RUNNING"
jabber:logPaths:PROXY_LOG = "/private/var/jabberd/log/proxy65.log"
jabber:logPaths:MUC_STD_LOG = "/var/log/system.log"
jabber:logPaths:JABBER_LOG = "/var/log/system.log"
jabber:proxyState = "RUNNING"
jabber:currentConnections = "0"
jabber:currentConnectionsPort1 = "0"
jabber:currentConnectionsPort2 = "0"
jabber:pluginVersion = "10.8.211"
jabber:servicePortsAreRestricted = "NO"
jabber:servicePortsRestrictionInfo = _empty_array
jabber:hostsCommaDelimitedString = "osxserver.krypted.lan"
jabber:hosts:_array_index:0 = "osxserver.krypted.lan"
jabber:setStateVersion = 1
jabber:startedTime = ""
jabber:readWriteSettingsVersion = 1

There are also a few settings not available in the Server app. One of these that can be important is the port used to communicate between the Messages client and the Messages service on the server. For example, to customize this to 8080, use serveradmin followed by settings and then jabber:jabberdClientPortSSL = 8080, as follows:

sudo serveradmin settings jabber:jabberdClientPortSSL = 8080

To change the location of the saved Messages transcripts (here, we’ll set it to /Volumes/Pegasus/Book:

sudo serveradmin settings jabber:savedChatsLocation = “/Volumes/Pegasus/Book”

To see a full listing of the options, just run settings with the jabber service:

sudo serveradmin settings jabber

The output lists each setting configurable:

jabber:dataLocation = “/Library/Server/Messages”
jabber:s2sRestrictDomains = no
jabber:jabberdDatabasePath = “/Library/Server/Messages/Data/sqlite/jabberd2.db”
jabber:sslCAFile = “/etc/certificates/”
jabber:jabberdClientPortTLS = 5222
jabber:sslKeyFile = “/etc/certificates/”
jabber:initialized = yes
jabber:enableXMPP = yes
jabber:savedChatsArchiveInterval = 7
jabber:authLevel = “STANDARD”
jabber:hostsCommaDelimitedString = “”
jabber:jabberdClientPortSSL = 5223
jabber:requireSecureS2S = yes
jabber:savedChatsLocation = “/Library/Server/Messages/Data/message_archives”
jabber:enableSavedChats = yes
jabber:enableAutoBuddy = no
jabber:s2sAllowedDomains = _empty_array
jabber:logLevel = “ALL”
jabber:hosts:_array_index:0 = “”
jabber:eventLogArchiveInterval = 7
jabber:jabberdS2SPort = 5269

To stop the service:

sudo serveradmin stop jabber

And to start it back up:

sudo serveradmin start jabber

It’s also worth noting something that’s completely missing in this whole thing: Apple Push Notifications… Why is that important? Well, you use the Messages application to communicate not only with macOS and other jabber clients, but you can also use Messages to send text messages. Given that there’s nothing in the server that has anything to do with texts, push or anything of the sort, it’s worth noting that these messages don’t route through the server and therefore still require an iCloud account. Not a huge deal, but worth mentioning that Messages server doesn’t have the same updates built into the Messages app. Because messages don’t traverse the server, there’s no transcripts.

September 26th, 2017

Posted In: Mac OS X Server

Tags: , , , ,

Profile Manager first appeared in OS X Lion Server as the Apple-provided tool for managing Apple devices, including Mobile Device Management (MDM) for iOS based devices as well as Profile management for macOS based computers, including MacBooks, MacBook Airs, Mac Minis, Mac Pros and iMacs running Mac OS X 10.7 and up. Profile Manager has seen a few more updates over the years, primarily in integrating new MDM options provided by Apple and keeping up with the rapidly changing MDM landscape. Apple has added DEP functionality, content distribution, VPP, and other features over the years. In macOS Server 5.4, there are plenty of new options, including the ability to deploy VPP apps to devices rather than Apple IDs. In this article we’ll get Profile Manager setup and perform some basic tasks.

Preparing For Profile Manager

Before we get started, let’s prep the system for the service. This starts with configuring a static IP address and properly configuring a host name for the server. In this example, the hostname will be We’ll also be using a self-signed certificate, although it’s easy enough to generate a CSR and install it ahead of time. For the purposes of this example, we have installed Server from the App Store (and done nothing else with Server except open it the first time so it downloads all of its components from the web) and configured the static IP address using the Network System Preferences. Next, we’ll set the hostname to odr using the scutil tool.

sudo scutil --set HostName

Then the ComputerName:

sudo scutil --set ComputerName

And finally, the LocalHostName:

sudo scutil --set LocalHostName our

Now check changeip:

sudo changeip -checkhostname

The changeip command should output something similar to the following:

Primary address = Current HostName = DNS HostName = The names match. There is nothing to change. dirserv:success = "success"

If you don’t see the success and that the names match, you might have some DNS work to do next, according to whether you will be hosting DNS on this server as well. If you will be hosting your own DNS on the Profile Manager server, then the server’s DNS setting should be set to the IP address of the Server. To manage DNS, start the DNS service and configure as shown previously:
Provided your DNS is configured properly then changeip should work. If you’re hosting DNS on an Active Directory integrated DNS server or some other box then just make sure you have a forward and reverse record for the hostname/IP in question. Profile Manager is built atop the web service and APNS. Next, click on the Web service and just hit start. While not required for Profile Manager to function, it can be helpful.

We’re not going to configure anything else with this service in this article so as not to accidentally break Profile Manager. Do not click on anything while waiting for the service to start. While the indicator light can go away early, note that the Web service isn’t fully started until the path to the default websites is shown (the correct entry, as seen here, should be /Library/Server/Web/Data/Sites/Default) and a View Server Website link is shown at the bottom of the screen. If you touch anything too early then you’re gonna’ mess something up, so while I know it’s difficult to do so, be patient (honestly, it takes less than a minute, wait for it, wait for it, there!).
Once the Web service is started and good, click on the View Server Web Site link at the bottom and verify that the Welcome to macOS Server page loads.

Setting Up Profile Manager

Provided the Welcome to macOS Server page loads, click on the Profile Manager service. Here, click on the ON button.
At the first screen of the Configure Device Management assistant, enter the name and phone number and click on Next.

The computer will then become a CA.  Choose an SSL certificate from the list provided and click Next. 

Note: This can be the certificate provided when Open Directory is initially configured, which is self-signed, or you can select a certificate that you have installed using a CSR from a 3rd party provider. At this point, if you’re using a 3rd party Code Signing certificate you will want to have installed it as well. Choose a certificate from the Certificate: drop-down list and then click on Next. If using a self-signed certificate you will be prompted that the certificate isn’t signed by a 3rd party. Click Next if this is satisfactory. 

At the Get An Apple Push Notification Device certificate screen, if you do not already have a push certificate installed for the system, you will then be prompted to enter the credentials for an Apple Push Notification Service (APNS) certificate. This can be any valid AppleID. It is best to use an institutional AppleID (e.g. rather than a private one (e.g. Once you have entered a valid AppleID username and password, click Next. Provided everything is working, you’ll then be prompted that the system meets the Profile Manager requirements. Click on the Finish button to complete the assistant.

Click Finish to complete the Profile Manager setup.   

When the assistant closes, you will be back at the Profile Manager screen in the Server application. Here, check the box for Sign Configuration Profiles.


The Code Signing Certificate screen then appears. Here, choose the certificate from the Certificate field.


Unless you’re using a 3rd party certificate there should only be one certificate in the list. Choose it and then click on OK. If you are using a 3rd party certificate then you can import it here, using the Import… selection. Then click OK to save your settings. Back at the Profile Manager screen, you will see a field for the Default Configuration Profile. If you host all of your services on the one server (Mail, Calendars, VPN, etc) then leave the box checked for Include configuration for services; otherwise uncheck it.


Profile Manager has the ability to distribute apps and content from the App Store Volume Purchase Program or Apple School Manager through Profile Manager. To use this option, first sign up on the VPP site. Once done, you will receive a token file. Using the token file, check the box in Profile Manager for Volume Purchase Program” or “Apple School Manager” and then use the Configure… button to select the token file.

Now that everything you need is in place, click on the ON button to start the service and wait for it to finish starting (happens pretty quickly).
The process is the same for adding a DEP token. If you’re just using Profile Manager to create profiles that you’ll import into other tools (Casper, Deploy Studio, Apple Configurator, etc) you can skip adding these tokens as they’re likely to cause more problems than they help with. Once you’ve got everything configured, start the service. Once started, click on the Open Safari link for Profile Manager and the login page opens. Administrators can login to Profile Manager to setup profiles and manage devices.

The URL for this (for is Use the Everyone profile to automatically configure profiles for services installed on the server if you want them deployed to all users. Use custom created profiles for everything else. Also, under the Restrictions section for the everyone group, you can choose what to allow all users to do, or whether to restrict access to certain Profile Manager features to certain users. These include access to My Devices (where users enroll in the system), device lock (so users can lock their own devices if they loose them) and device wipe. You can also allow users to automatically enroll via DEP and Configurator using this screen.

Enrolling Into Profile Manager

To enroll devices for management, use the URL (replacing the hostname with your own). Click on the Profiles tab to bring up a list of profiles that can be installed manually.


From Profiles, click or tap the Enroll button. The profile is downloaded and when prompted to install the profile, click Continue.

Screen Shot 2015-09-25 at 8.58.18 PM

Then click Install if installing using a certificate not already trusted.

Screen Shot 2015-09-25 at 8.58.35 PM

Once enrolled, click on the Profile in the Profiles System Preference pane to see the settings being deployed.

Screen Shot 2015-09-25 at 8.59.12 PM
You can then wipe or lock the device from the My Devices portal. Management profiles from the MDM server are then used. Devices can opt out from management at any time. If you’re looking for more information on moving Managed Preferences (MCX) from Open Directory to a profile-based policy management environment, review this article and note that there are new options in dscl for removing all managed preferences and working with profiles in Mavericks (10.9), Yosemite (10.10), El Capitan (10.11), Sierra (10.12), and now High Sierra (10.13).

If there are any problems when you’re first getting started, an option is always to run the script that resets the Profile Manager (aka, devicemgr) database. This can be done by running the following command:

sudo /Applications/

Automating Enrollment & Random Management Tips

The two profiles needed to setup a client on the server are accessible from the web interface of the Server app. Saving these two profiles to a macOS computer then allows you to automatically enroll devices into Profile Manager using Apple Configurator, as shown in this previous article. When setting up profiles, note that the username and other objects that are dynamically populated can be replaced through a form of variable expansion using payload variables in Profile Manager. For more on doing so, see this article.

Note: As the database hasn’t really changed, see this article for more information on backing up and reindexing the Profile Manager database.

Device Management

Once you’ve got devices enrolled, those devices can easily be managed from a central location. The first thing we’re going to do is force a passcode on a device. Click on Devices in the Profile Manager sidebar.
Click on a device in Profile Manager’s admin portal, located at https:///profilemanager (in this case Here, you can see:
  • General Information: the type of computer, capacity of the drive, version of OS X, build version, serial number of the system and the currently logged in user.
  • Details: UDID, Ethernet MAC, Wi-Fi MAC, Model, Last Checkin Time, Available disk space, whether Do Not Disturb is enabled and whether the Personal Hotspot is enabled.
  • Security information: If FileVault is enabled, whether a Personal Recovery is set and whether an Institutional Recovery Key has been installed.
  • Restrictions, whether any restrictions have been deployed to the device from Profile Manager.
  • Installed Apps: A list of all the apps installed (packages, App Store, Drivers, via MDM, etc).
  • In Device Groups: What groups are running on the system.
  • Certificates: A list of each certificate installed on the computer.
Screen Shot 2015-09-25 at 9.08.31 PM

The device screen is where much of the management of each device is handled, such as machine-specific settings or using the cog-wheel icon, wiping, locking, etc. From the device (or user, group, user group or device group objects), click on the Settings tab and then click on the Edit button.
Here, you can configure a number of settings on devices. There are sections for iOS specific devices, macOS specific settings and those applicable to both platforms. Let’s configure a passcode requirement for an iPad.
Click on Passcode, then click on Configure.
At the Passcode settings, let’s check the box for Allow simple value and then set the Minimum Passcode Length to 4. I find that with iOS, 4 characters is usually enough as it’ll wipe far before someone can brute force that. However, if a fingerprint can unlock your devices then more characters is fine as it’s quick to enter them. Click OK to commit the changes.
Once configured, click Save. At the “Save Changes?” screen, click Save. The device then prompts you to set a passcode a few moments later. The next thing we’re going to do is push an app. To do so, first find an app in your library that you want to push out. Right-click (or control-click) on the app and click on Show in Finder. You can install an Enterprise App from your library or browse to it using the VPP program if the app is on the store. Before you start configuring apps, click on the Apps entry in the Profile Manager sidebar.
At the Apps screen, use the Enterprise App entry to select an app or use the Volume Purchase Program button to open the VPP and purchase an app. Then, from the https:///profilemanager portal, click on an object to manage and at the bottom of the About screen, click Enable VPP Managed Distribution Services.
Click on the Apps tab.
From the Apps tab, click on the plus sign icon (“+”). At the Add Apps screen, choose the app added earlier and then authenticate if needed, ultimately selecting the app. The app is then uploaded and displayed in the list. Click Add to add to the selected group. Then, click on Done. Then click on Save… and an App Installation dialog will appear on the iOS device you’re pushing the app to. At the App Installation screen on the iPad, click on the Install button (unless you’re using Device-based VPP) and the app will instantly be copied to the last screen of apps on the device. Tap on the app to open it and verify it works. Assuming it does open then it’s safe to assume that you’ve run the App Store app logged in as a user who happens to own the app.

You can sign out of the App Store and the app will still open. However, you won’t be able to update the app as can be seen here.

Note: If you push an app to a device and the user taps on the app and the screen goes black then make sure the app is owned by the AppleID signed into the device. If it is, have the user open App Store and update any other app and see if the app then opens.

Finally, let’s wipe a device. From the Profile Manager web interface, click on a device and then from the cog wheel icon at the bottom of the screen, select wipe. At the Wipe screen, click on the device and then click Wipe. When prompted, click on the Wipe button again, entering a passcode to be used to unlock the device if possible. The iPad then says Resetting iPad and just like that, the technical walkthrough is over.

Screen Shot 2015-09-25 at 9.15.11 PM

Note: For fun, you can use the MyDevices portal to wipe your iPad from the iPad itself.


To quote Apple’s Profile Manager page:
Profile Manager simplifies deploying, configuring, and managing them all. It’s one place where you control everything: You can create profiles to set up user accounts for mail, calendar, contacts, and messages; configure system settings; enforce restrictions; set PIN and password policies; and more. Because it’s integrated with the Apple Push Notification service, Profile Manager can send out updated configurations over the air, automatically. And it includes web-based administration, so you can manage your server from any modern web browser. Profile Manager even gives users access to a self-service web portal where they can download and install new configuration profiles, as well as clear passcodes and remotely lock or wipe their Mac, iPhone, or iPad if it’s lost or stolen.
For the money, Profile Manager is an awesome tool. Apps such as Casper, AirWatch, Zenprise, MaaS360, etc all have far more options, but aren’t as easy to install (well, Bushel is… 😉 and nor do they come at such a low price point. Profile Manager is a great option if all of the tasks you need to perform are available within the tool. If not, then it’s worth a look, if only as a means to learn more about the third party tools and to export profiles you’ll use in other solutions.

September 26th, 2017

Posted In: Mac OS X Server

Tags: , , , , , , , , ,

OS X Server stores most logs in files that are in the /Library/Logs/ProfileManager directory. Logs are split up between php, devicemgrd.log, scep_helper.log, servermgr_devicemgr.log, profilemanager.log and others. In my experience, if there’s a lot of errors at first, or if the service doesn’t work, just reformat and start over. But, once a server is in production, you don’t want to re-enroll devices after you do that. So, as with all good error prodding, start with the logs to troubleshoot. By default the logs can appear a bit anemic. You can enable more information by increasing the logging level. Here, we’ll shoot it up to 6, which can be done with the following command: sudo debugDeviceMgr 6 Debug levels go all the way to 9, but at that point things get… Noisy. And to turn it back off, use: sudo debugDeviceMgr 1 Basically, this command sets the required services in /Applications/ to debug mode as well as /Applications/ and /Applications/ to configure debug mode. In other words, it touches a lot of services. And given how chatty some can be, only leave logging levels higher than I’d say 2 in the event of short-term troubleshooting.

December 29th, 2016

Posted In: Mac OS X, Mac OS X Server, Mac Security, Mass Deployment

Tags: , , , , , , ,

Servers can have problems. When they have problems, you need to grab logs and stuff. Ever wonder what Apple developers think is important, when it comes to logs and stuff? Try serverdiagnose! serverdiagnose Then hit the Enter (return) key. Then it collects some logs into a tgz. Why a tgz? No clue. But it ends up in /tmp. Notice the name as ServerLogs- followed by the hostname, then a date stamp (yearmonthday) and an underscore followed by a timestamp. Inside the tgz is /Library/Logs, /Library/Server, /tmp/dsdiagnose (a dump of OD debug logs), serverlogs_S3vKsy (configuration statuses), a couple of things from /var/db (the most important of which is PreviousSystemLogs), and /var/log.

November 9th, 2016

Posted In: Mac OS X Server

Tags: , , , , ,

The Time Machine service in macOS Server 5.2 hasn’t changed much from the service in previous operating systems. To enable the Time Machine service, open the Server app, click on Time Machine in the SERVICES sidebar. If the service hasn’t been enabled to date, the ON/OFF switch will be in the OFF position and no “Backup destination” will be shown in the Settings pane. screen-shot-2016-09-29-at-8-56-29-pm Click on the ON button to see the New Destination screen, used to configure a list of volumes as a destinations for Time Machine backups. The selection volume should be large enough to have space for all of the users that can potentially use the Time Machine service hosted on the server. When you click the Choose button, a list of volumes appears in a standard Finder selection screen. screen-shot-2016-09-29-at-8-57-19-pm Here, click on the volume to save your backups to in the sidebar. In most cases the Backup destination will be a mass storage device and not the boot volume of the computer. Once selected, click Choose and then if desired, limit the amount of storage on the volume to be used for backups. Click Create and a share called Backups is created and the service will start. Don’t touch anything until the service starts. Once started, add a backup destination at any time using the plus sign button (“+”) and defining another destination. screen-shot-2016-09-29-at-8-57-40-pm Time Machine Server works via Bonjour. Open the Time Machine System Preference pane and then click on the Select Backup Disk button from a client to see the server in the list of available targets, much as you would do with an Apple Time Capsule. screen-shot-2016-09-29-at-8-58-33-pm Under the hood, a backup share is creating in the file sharing service. To see the attributes of this share, use the serveradmin command followed by the settings option and then the sharing:sharePointList:_array_id:, so for a path of /Volumes/New Volume 1/Shared Items/Backups use: sudo serveradmin settings sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups The output indicates the options configured for the share, including how locking is handled, guest access disabled, generated identifiers and the protocols the backups share listens as:
sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:name = "Backups"
sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:smbName = "Backups"
sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:nfsExportRecord = _empty_array
sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:afpIsGuestAccessEnabled = no
sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:isTimeMachineBackup = yes
sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:dsAttrTypeNative\:sharepoint_group_id = "F4610C2C-70CD-47CF-A75B-3BAFB26D9EF3"
sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:isIndexingEnabled = yes
sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:mountedOnPath = "/Volumes/New Volume 1"
sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:dsAttrTypeStandard\:GeneratedUID = "FAB13586-2A2A-4DB2-97C7-FDD2D747A0CD"
sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:path = "/Volumes/New Volume 1/Shared Items/Backups"
sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:smbIsShared = no
sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:smbIsGuestAccessEnabled = no
sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:afpName = "Backups"
sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:smbDirectoryMask = "755"
sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:afpIsShared = yes
sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:smbCreateMask = "644"
sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:ftpName = "Backups"
sharing:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:timeMachineBackupUUID = "844A1C43-61C9-4F99-91DE-C105EA95BD45"
Once the service is running, administrators frequently fill up the target volume. To move data to another location, first stop the service and then move the folder (e.g. using mv). Once moved, use the serveradmin command to send settings to the new backup path. For example, to change the target to /Volumes/bighonkindisk, use the following command: sudo serveradmin settings sharing:sharePointList:_array_id:/Shared Items/Backups:path = "/Volumes/bighonkindisk" Another way to see the share and attributes of the share is through the sharing command: sharing -l Which should show output similar to the following: List of Share Points
name: Backups
path: /Shared Items/Backups
afp: {
name: Backups
shared: 1
guest access: 0
inherit perms: 0
ftp: {
name: Backups
shared: 0
guest access: 0
smb: {
name: Backups
shared: 0
guest access: 0
} There’s also a Bonjour service published that announces to other clients on the same subnet that the server can be used as a backup destination (the same technology used in a Time Capsule). One major update from back in Mavericks Server is the addition of the timemachine service in the severadmin command line interface. To see the command line settings for Time Machine: sudo serveradmin settings timemachine The output shows that share info is displayed as with the sharing service, but you can also see the GUID assigned to each share that is a part of the backup pool of storage:
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:dsAttrTypeStandard\:GeneratedUID = "FAB13586-2A2A-4DB2-97C7-FDD2D747A0CD"
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:smbName = "Backups"
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:afpIsGuestAccessEnabled = no
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:smbDirectoryMask = "755"
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:afpName = "Backups"
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:smbCreateMask = "644"
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:nfsExportRecord = _empty_array
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:path = "/Volumes/New Volume 1/Shared Items/Backups"
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:smbIsGuestAccessEnabled = no
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:name = "Backups"
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:ftpName = "Backups"
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:smbIsShared = no
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:afpIsShared = yes
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:timeMachineBackupUUID = "844A1C43-61C9-4F99-91DE-C105EA95BD45"
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:isTimeMachineBackup = yes
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:backupQuota = 0
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:dsAttrTypeNative\:sharepoint_group_id = "F4610C2C-70CD-47CF-A75B-3BAFB26D9EF3"
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:isIndexingEnabled = yes
timemachine:sharePointList:_array_id:/Volumes/New Volume 1/Shared Items/Backups:mountedOnPath = "/Volumes/New Volume 1" Additionally you can also query for the service to verify it’s running using full status: sudo serveradmin fullstatus timemachine Which outputs something similar to the following: timemachine:command = "getState"
timemachine:state = "RUNNING"
While I found plenty to ramble on about in this article, Mass deployment is still the same, as is client side configuration.

October 15th, 2016

Posted In: Mac OS X, Mac OS X Server, Time Machine

Tags: , , , , , , , , , , , ,

Next Page »