### IMPORTANT ###
This post is an archive of an interesting experiment. Beginning with macOS 10.11, the OS does not appear to appreciate symlinked local folders to network destination, and may result in data loss on the remote home directory.
Please only read out of interest – do not use this technique.
— Tim
#################
I’m attempting to improve the user experience when OSX is bound to our university Active Directory system. Although grad students by-and-large carry Mac laptops around as their personal computers, I am seeing much more Windows use in a dual-boot cluster that I support. I suspect this is due to better support for Roaming Profiles in our environment for Windows, so I’m trying to improve that a bit for the OS X user.
What prevents me from just un-ticking the “Force Local Home” option and allowing the user directory from existing solely on AD is two-fold:
- I need to retain some control over certain aspects of the local machine config – e.g. Users need to have a consistent dock, and
- Students do not get a ton of storage on AD so I have to be mindful of large folders like ~/Library/Caches.
So ultimately, I want a couple of key folders to redirect to the AD space to provide a somewhat portable environment for the user, but I need to keep some locally on the machine for both management and storage considerations.
I accomplished this with two separate scripts. One loginhook that redirects the Desktop and Documents folders to the mounted AD share, and a second script that is called from Launchd upon login that detects if certain preferences already exist on the user’s AD profile home, creates them if they don’t, and then links to them. I had to do this because the loginhook script was firing prior to the user share being mounted, so any “detection” logic for pre-existing preferences and application data was failing.
The starter list for this “portability”:
~/Desktop
~/Documents
~/Library/Safari (for bookmarks and history)
~/Library/Application Support/Google (ditto)
~/Library/Application Support/Firefox (you guessed it)
I’m populating the dock and finder preferences (among others) via a custom user template. I also have a logouthook script that wipes the local home folder that is created when a user logs in, and rsyncs everything to a recent-users folder within /Users/Shared – just as a fail-safe to keep the machine tidy while providing a safety net for the students (but that’s another post).
- Here’s the code:
#! /bin/bash ## ## LoginHook script by Tim Schutt, 2013 ## echo "##############################" echo "Logging in user is $1" if [ ! "$1" = "admin" ] && [ ! "$1" = "root" ]; then ## test if the user is local admin or not echo "Reassigning Desktop folder." rm -r /Users/$1/Desktop ## remove Desktop folder created by OS X ln -s /Volumes/$1\$/Desktop /Users/$1 ## create soft-link to Desktop folder in AD home echo "Reassigning Documents folder." rm -r /Users/$1/Documents ## remove Docs folder created by OS X ln -s /Volumes/$1\$/Documents /Users/$1 ## create soft-link to Docs folder in AD home fi echo "##############################" exit 0
And the Launchd script:
#! /bin/bash ## ## launchd script to redirect key folders for Active Directory users - Tim Schutt, 2013 ## LIUSER=$(ls -l /dev/console | cut -d " " -f 4) ## pulls username in for currently logged in user LIGRP=$(ls -l /dev/console | cut -d " " -f 6 | cut -d "\\" -f 1) ## extracts group of currently logged in user - used to test if "AD" NETLIB=/Volumes/$LIUSER\$/Library ## shortcut - I get lazy sometimes. if [ "$LIGRP" = "AD" ] ## if the logged in user is an AD user then if [ ! -d $NETLIB ]; then ## Test if Library folder exists on AD share and execute if it does not echo "Library does not exist in network home - creating it." mkdir $NETLIB fi if [ ! -d $NETLIB/Application\ Support ]; then ## test if Application Support exists. echo "Application Support does not exist - creating it." mkdir $NETLIB/Application\ Support ## create it if not fi if [ ! -d $NETLIB/Application\ Support/Google ]; then if [ -d /Users/$LIUSER/Library/Application\ Support/Google ]; then echo "Copying Chrome prefs to network home." cp -fR /Users/$LIUSER/Library/Application\ Support/Google $NETLIB/Application\ Support/Google ## copy Chrome prefs to AD space else echo "Creating Chrome prefs folder." mkdir $NETLIB/Application\ Support/Google fi fi if [ /Users/$LIUSER/Library/Application\ Support/Google ]; then echo "Removing local Chrome prefs." rm -R /Users/$LIUSER/Library/Application\ Support/Google ## Remove the local copy of the Chrome prefs fi echo "Linking to network Chrome prefs." ln -s $NETLIB/Application\ Support/Google /Users/$LIUSER/Library/Application\ Support ## link to the AD version of the prefs if [ ! -d $NETLIB/Application\ Support/Firefox ]; then if [ -d /Users/$LIUSER/Library/Application\ Support/Firefox ]; then echo "Copying Firefox prefs to network home." cp -R /Users/$LIUSER/Library/Application\ Support/Firefox $NETLIB/Application\ Support/Firefox ## copy Firefox prefs to AD space else echo "Creating Firefox prefs folder." mkdir $NETLIB/Application\ Support/Firefox fi fi if [ -d /Users/$LIUSER/Library/Application\ Support/Firefox ]; then echo "Removing local Firefox prefs." rm -R /Users/$LIUSER/Library/Application\ Support/Firefox ## Remove the local copy of the Firefox prefs fi echo "Linking to network Firefox prefs." ln -s $NETLIB/Application\ Support/Firefox /Users/$LIUSER/Library/Application\ Support ## link to the AD version of the prefs if [ ! -d $NETLIB/Safari ]; then ## test if Safari prefs exist. if [ -d /Users/$LIUSER/Library/Safari ]; then echo "Copying Safari prefs." cp -R /Users/$LIUSER/Library/Safari $NETLIB/Safari ## copy them from template if not. else echo "Creating network safari prefs folder" mkdir /Volumes/$LIUSER\$/Library/Safari fi fi if [ -d /Users/$LIUSER/Library/Safari ] && [ ! -h /Users/$LIUSER/Library/Safari ]; then echo "Removing local Safari prefs." rm -R /Users/$LIUSER/Library/Safari ## remove local safari prefs else echo "Safari prefs are already linked" fi if [ ! -h /Users/$LIUSER/Library/Safari ]; then echo "Linking to network Safari prefs." ln -s $NETLIB/Safari /Users/$LIUSER/Library ## create link to safari prefs on network home. fi fi exit 0
And the Launchd .plist placed in /Library/LaunchAgents (I store the previous two scripts in /usr/hookfiles)
<?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>Label</key> <string>org.yours.goes.here</string> <key>LimitLoadToSessionType</key> <array> <string>Aqua</string> </array> <key>ProgramArguments</key> <array> <string>/usr/hookfiles/mapping.sh</string> </array> <key>RunAtLoad</key> <true/> </dict> </plist>
This is very much still a work in progress…