Securing Ubooquity with Let’s Encrypt on Synology DSM

Update, 2020-06-11: I’m now using Synology’s built-in NGINX-based reverse proxy instead. The instructions below may not work.


Whew, that’s a very specific title. I don’t know if this will be useful to anyone else, but it took a fair amount of work to figure it out, so I figured I’d document it. There will be more Mac stuff soon, I promise!

If you haven’t heard, Let’s Encrypt is an excellent service, with the aim of securing the internet by offering free HTTPS certificates to anyone who requests one. In fact, I’m using one on this website right now. 🙂

With DSM 6.0, Synology added the ability to request a free certificate from Let’s Encrypt to secure your NAS. DSM handles renewing your certificate, which must happen every 90 days (one of the limitations of the free certificate, but nothing that can’t be automated).

Unrelated for the moment, but I’ve been using Ubooquity (through Docker!) for the past few months, and it’s been pretty neat. You can point Ubooquity to a directory of ePub and PDF files, and it’ll allow you to access the files remotely using reader apps like Marvin, KyBook, or Chunky. I have a habit of buying tech books and comics through Humble Bundle sales, but transferring the files to my iPad through iTunes/iBooks is clunky and requires a fair amount of disk space upfront.

Although Ubooquity supports user authentication, you’ll want that to happen over HTTPS, to keep your passwords secure. Luckily, Ubooquity supports HTTPS, but requires the certificate (and other associated files) to be in a format called a “keystore”. What?!

Here’s how to leverage DSM’s Let’s Encrypt support to secure Ubooquity, automatically.

  1. First, you’ll want to set up Let’s Encrypt in DSM’s Control Panel. See Synology’s documentation.
  2. Next, you’ll want to get Ubooquity up and running (I recommend the Docker image mentioned above). Synology’s documentation covers that, too. If your eBook library is a mess Calibre will make quick work of that.
  3. For this to work, you’ll also need the Java 8 JDK installed. This will give you access to the ‘keytool’ command you’ll need to create your keystore. Once again, see Synology’s documentation.
  4. Now, you’ll put all of this together. In a nutshell: you’re going to use the Let’s Encrypt certs that DSM has helpfully obtained for you, convert those to a keystore, put the keystore in Ubooquity’s config directory, and tell Ubooquity to use it to secure its interface. Here’s a script to get you started – note that you’ll need to edit lines 11, 12, and 15 for your environment. Thanks to Saltypoison on the Ubooquity forums for most of the code that became this script!
  5. Once you’ve successfully run the script, I recommend using DSM’s Task Scheduler to have it run once a day. This way, Ubooquity’s certificate will always be up to date with DSM’s certificate. That’s right, I’m going to link you to Synology’s documentation.
  6. Finally, you’ll need to tell Ubooquity where to find your keystore. Login to the Ubooquity admin interface, then click the Security tab. You’ll see two boxes – one for the path to your keystore, and one for the keystore password. Enter both. Click ‘Save and Restart’ at the top-right corner.
  7. Now, try accessing your Ubooquity instance using https and your FQDN! If it doesn’t work, make sure you’re forwarding the appropriate ports from your router to your Synology server – you’ll need to do this for both the eBook interface, and the admin interface (which are accessible via two different ports).

I’ll probably post more Synology/Docker stuff in the future, as I’ve been spending a lot of time with both. They’re really awesome!

Deploying JMP Pro 12.x and 13.x licenses

As I’m reorganizing my GitHub repositories, I’ve realized that I forgot to post about my work with Shea Craig and the JMP Team at SAS. Because of them, I was able to deploy JMP Pro 12.x and 13.x licenses to our Mac labs.

You can find code and instructions at my jmp_pro_12_license_pkg and jmp_pro_13_license_pkg GitHub repositories.

NoMAD Group Condition for Munki

One of the most powerful features of Munki are conditional items – and the ability for an admin to provide custom conditions for deploying or removing software. For example, we’ve been using the scripts that Hannes Juutilainen has published to determine which macOS version is supported by a particular Mac’s hardware.  We can then offer the most appropriate OS upgrade to each Mac.

We recently deployed the excellent NoMAD to single-user Macs, with the intention of resolving keychain issues (and eventually moving away from Active Directory binding altogether). If you’re using AD with your Macs, it’s absolutely worth checking out.

When a user logs into NoMAD, some data about the user’s AD account is retrieved for later usage – such as their group membership (also known as Organizational Units, or OUs). In our environment, users are divided into different groups based on their department. What if we could use that for deploying printers, similar to Group Policy on Windows?

You might see where I’m going with this – check out the script on GitHub for requirements and usage instructions.

Deploying Gaussian

I thought I blogged about deploying Gaussian 09 when I published this GitHub repository, but I guess I forgot to do that.  Anyhow, here’s some code for deploying Gaussian 16, the latest version of the Gaussian software.

Munki 101 Presentation

For our April 2017 Greater Philadelphia Mac Admins meeting, I presented on Munki 101. Here’s the summary (along with the slides), and here is the video:

Resolving a freezing problem on lab Macs

This post has been brewing for a while, and a MacEnterprise thread from today finally got me to write about this problem, and how we resolved it.

Our university has many computer labs – some in public, open spaces, and some in classrooms. Although we don’t use roaming profiles (a technology that Apple finally removed in macOS 10.12), we do bind to Active Directory and create mobile accounts upon logging in with a valid AD account.  To prevent the buildup of cruft, we remove student and faculty accounts periodically. In the public labs, we do it overnight, using a script based off of this one from Marnin Goldberg:

#!/bin/bash
# This script works well for removing local accounts that are older than 1 day.
# Obviously the 1 day timeframe can be modified (-mtime +1).
# Runs using Launch Daemon – /Library/LaunchDaemons/edu.org.deleteaccounts.plist
# version .7
DATE=`date "+%Y-%m-%d %H:%M:%S"`
# Don't delete local accounts
keep1="/Users/admin"
keep2="/Users/admin2"
keep3="/Users/Shared"
currentuser=`ls -l /dev/console | cut -d " " -f 4`
keep4=/Users/$currentuser
USERLIST=`/usr/bin/find /Users -type d -maxdepth 1 -mindepth 1 -mtime +1`
for a in $USERLIST ; do
[[ "$a" == "$keep1" ]] && continue #skip admin
[[ "$a" == "$keep2" ]] && continue #skip admin2
[[ "$a" == "$keep3" ]] && continue #skip shared
[[ "$a" == "$keep4" ]] && continue #skip current user
# Log results
echo ${DATE} – "Deleting account and home directory for" $a >> "/Library/Logs/deleted user accounts.log"
# Delete the account
/usr/bin/dscl . -delete $a
# Delete the home directory
# dscl . list /Users UniqueID | awk '$2 > 500 { print $1 }' | grep -v Shared | grep -v admin | grep -v admin1 | grep -v .localized
/bin/rm -rf $a
done
exit 0
view raw gistfile1.txt hosted with ❤ by GitHub
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Disabled</key>
<false/>
<key>Label</key>
<string>edu.org.deleteaccounts</string>
<key>ProgramArguments</key>
<array>
<string>/Library/Scripts/delete-accounts.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>7</integer>
<key>Minute</key>
<integer>30</integer>
</dict>
<key>StartInterval</key>
<integer>86400</integer>
</dict>
</plist>
view raw gistfile2.txt hosted with ❤ by GitHub

The most important parts of that script are:

# Delete the account
/usr/bin/dscl . -delete $a

This deletes the cached Active Directory account from the system.

# Delete the home directory
/bin/rm -rf $a

This deletes the home folder, freeing up space for more accounts.

We noticed something strange, though. After a couple of weeks of usage, the iMacs in our public labs would freeze at random points: at boot, at login, when using applications, when logging out, even when shutting down. Here’s a list of things we noted while trying to resolve the issue:

  • We use Munki to deploy software, so one by one, we removed potential culprits from the manifests.  Eventually, we whittled down the manifest items to three things we could not remove from this particular lab: Microsoft Office, the Xerox printer driver, and Active Directory binding.
  • We investigated if this was an issue with our network, power, or Active Directory setup.  For a few weeks, all iMacs were plugged into UPSs.
  • We replaced all of the iMacs with brand new models – some with SSDs, and some not.
  • As this issue persisted over ~3 years or so, we tested against multiple macOS versions – including 10.9, 10.10, and 10.11 (and the minor versions in between).
  • We enabled OD debug logging, but couldn’t make much sense of the logs.  They were very, very verbose.
  • Ultimately, the best fix was to reimage the Mac.  This would hold off the freezing for at least another week or two.
  • The freezing seemed linked to computer usage.  If an entire lab was reimaged at the same time, the first Macs to freeze were located near the printers. During the summer, when usage was decreased, we rarely had reports of freezing issues in the public labs.

We were in the process of reaching out to our Apple Systems Engineer, when we found a long-running thread on Jamf Nation, detailing the exact problems we were facing.  It was a relief to see others were trying similar tactics, too.  Then, towards the bottom of the thread, Frank Kong noted that with every use login, some files were being left behind – and the script we were using did not clear those out.  In System Preferences > Sharing > File Sharing, you could see a long list of shares, all named things similar to “Mike Solin’s Public Folder”.  Bingo, there’s our culprit.

Alan Petty, in the same thread, added this code to his profile deletion script:

/usr/bin/find /private/var/db/dslocal/nodes/Default/sharepoints -name "*" -type f -delete
/usr/bin/find /private/var/db/dslocal/nodes/Default/groups -name "com.apple.sharepoint*" -type f -delete

We found this code can be run while a user is logged in, so we don’t need to exclude the current user from this part of the script. It will, however, delete all file shares present on the computer (whether they are for public folders or not). This isn’t an issue in our labs, but it’s still worth mentioning.

We’ve had this fix in production for just over a month, and I can safely say the freezing problems haven’t returned.

Long-term, it might be best to look into deleting profiles using a configuration profile – Marnin posted his here.  For now, we’re sticking with the script, as it gives us more control over where and when it runs.

Allow specific users with no password to use sudo

As a sequel to the first post I made to this blog, I’ve found myself tackling this same thing with every macOS release.  Today, however, I discovered a line in /private/etc/sudoers that I hadn’t noticed before:

## Read drop-in files from /private/etc/sudoers.d
## (the '#' here does not indicate a comment)
#includedir /private/etc/sudoers.d

After some research, I discovered that you can drop a file in /private/etc/sudoers.d (a directory), and, as long as the syntax is correct, it will merge those with the main sudoers file.  In the event of a conflict, the last rule that applies takes effect – and, the main sudoers file is read first, so you can essentially override behavior by dropping a file into the sudoers.d directory.  Awesome!

I’ve posted the working code to my GitHub repository.  In the event that you want to make a change, be sure to check the file before packaging it up – or you risk breaking sudo:

/usr/sbin/visudo -csf /path/to/your/file

New Munki tool: Computer Name

managedsoftwareupdate has several methods you can use to identify your Macs to your Munki server. While the hierarchy is documented on the Munki wiki, the ComputerName field (accessible in System Preferences –> Sharing), is not one of them. Since our inventory system is tied to the computer name, we wanted Munki to use that as the identifier for manifests, too.

I wrote a small LaunchDaemon and script to write the ComputerName field to Munki’s ClientIdentifier field (which overrides the hierarchy mentioned above) each time it’s changed. This allows IT to rename Macs and manifests as needed, but also audit unauthorized computer name changes through MunkiReport.

The code is available on my GitHub repository.

Greater Philadelphia Mac Admins

I’m not sure how I hadn’t posted about this yet, but I help organize a local meetup group for Mac / iOS admins, called Greater Philadelphia Mac Admins. We meet monthly – if you’re in the area, you should consider attending! The meetings are free, and dinner is provided.

For more information, please see our website.

Also, I presented on Munki a few months ago, at the October 2015 meeting. Check it out!

Boot Scheduler

Like most things, Boot Scheduler was written to scratch an itch: students were powering off lab computers, which could stay off for weeks or months at a time (particularly in the smaller labs). These Macs would stop checking in to Munki, would be horribly out of date, and would behave unpredictably once powered on again – the AD binding could become broken, or they might reboot unexpectedly to apply security patches.

We discussed using the built-in pmset tool to power on all Mac labs daily, but we have a long winter break – we don’t want these Macs turning on and wasting energy without anyone around to use them. Since pmset has no concept of calendar dates beyond days of the week, we had to develop something custom.

My hope is that if you’re facing similar issues, Boot Scheduler can help you. You can grab it from my GitHub repository – be sure to check out the README for installation and customization instructions.

Page 3 of 5

Powered by WordPress & Theme by Anders Norén