Creating Self Service URL Plug-ins via script

Legendary Contributor III

Hi all.

I wanted to post something that I put together about a month or so back, in case it would be useful to some of you.

We don't really use Self Service URL plug-ins here, despite my occasional urging that they are, or would be, extremely useful to our user base. One of the reasons I was told we don't use them is because, since the Mac user base is so diverse, trying to figure out who would need what url plug-ins is complicated, and we don't want to clutter up everyone's Self Service sidebar with a bunch of URLs that aren't useful to them. Meaning, we want them to be more targeted. Since SS URL Plug-ins deploy to all Macs by default unless you package and deploy them individually, this has led us to not use them currently.
As such, I set about looking at ways I could create a policy, in Self Service itself, where users could choose the plug-ins they might want to use from a simple check-box list of all available ones, and only have those plug-ins installed. I was then able to get some working examples together that can be run from Self Service to install only selected Plug-ins.

As part of this project, I had to create a few Self Service URL plug-ins in our JSS, and then pull them down to my Mac, and then immediately delete it, lest it start getting pulled down on other managed Macs. This process is in general, a pain in the butt, and tedious. While I could also use a dev server, it doesn't negate the need to create them in the JSS interface, then run sudo jamf manage on a test Mac pointed to the dev server to have it pulled down, as this KB article outlines:

So, I started looking at an easier, possibly faster way I could make my own plug-ins. It didn't take too much work to figure out the format of what makes them tick, and just a little more work from there on how to script the process.

This leads me to what I'm posting. On my github page I've put up a script I made that will assist in creating your own Self Service URL plug-ins, direct on your Mac, not from the JSS, named

A few details:
1) The script is interactive in that it will 'guide' you on what you need to enter each step of the way and take input on the command line.
2) The script indicates what items are Required versus those that are Optional.
3) The script can accept images in a variety of formats to use for the icon and convert them into the correct binary format
4) The script will create SS URL plug-ins with unique IDs that start in the 1000+ range. This is done so (hopefully) none of the ones you create will conflict with any you created directly in your JSS. To note, the JSS will start with ID 1 and increment from there, even if you delete any plug-ins later (i.e, IDs don't get reused). My hope is that no-one has created 1000 Self Service URL Plug-ins in their JSS, so starting at ID 1000 should be safe (?)
5) The script will create the necessary folder hierarchy (if needed) on a Casper managed Mac, and save it to the appropriate location. If run on a non managed Mac, it will save the resulting plug-in .plist to your Desktop
The script notes the resulting Plug-in's ID/name, so it should be easy to locate and wrap into a package later if you decide to do that.

You can find the script here (called

It requires root (sudo) in Terminal since it would need those privileges to save into the Self Service/Plug-ins directory on a managed Mac. It will stop immediately if it sees its not running as 'root' and alert you to that fact.

Any feedback is welcome. I'm providing it more or less 'as is' and don't really have plans right now on adding any additional features (mostly because there isn't much that can even be added), but of course, if you run into any weird issues with it, send me a note and I'll look into it.

UPDATE: The script was updated on github with a few bits of changed code. My previous version used whatever image you threw at it without conversion, and also did not check to see if the image was in a square aspect ratio.
The new version alerts you if you choose an image that is not square. Non square images (depending on how different width and height are) can result in distorted images in the resulting Plug-in. Right now it does not let you select a new image on the spot (other than restarting the script), but it at least warns you about it.
Secondly, I'm using sips (scriptable image processing system) to both check the image format to make sure its an acceptable one, rather than using the file extension, AND, it uses sips to pre-convert the image down to 128 x 128 into a temp file to use for the Plug-in. I did this because if you happen to use an extremely large image, say 3000 x 2500 pixels, the resulting base64 encoded data is very large and bloats the plist file. Pre-converting it down to 128 x 128 keeps them to a sane size. As an example, I used an image that was 1387 x 600 in the older script and the resulting plist file was 564 K. With the new script, the resulting Plug-in was 16 K. That's a [s]~65%[/s] ~97% reduction. Nothing monumental, but better to create slimmer plists than fat ones for no good reason :)



Valued Contributor

That is seriously cool, thanks for sharing!

Valued Contributor III
Valued Contributor III

Legendary Contributor III

@emilykausalik - Lol! Thanks! :)

Be sure to grab the just updated version in case you already pulled the script down. See my notes above in my OP on the changes.

Honored Contributor II
Honored Contributor II

Great stuff @mm2270, thanks!

Valued Contributor II

@mm2270 thanks so much for sharing this. Tested it out quick and it works great. In regards to your original post, will you be using portions of your software update script to display the list of plugins that are available?

Legendary Contributor III

Hey Jason, thanks. So, the end result won't be that exact same script, but something very similar to that.
The general flow will look something like the following:

  1. Create any and all of the Self Service URL plug-ins that you might want to deploy, using your own method, for example a dev JSS or my script.
  2. Create a new folder in /private/tmp/ and copy the resulting plist files into that folder.
  3. Package up that folder in Composer or similar and upload into Casper Admin. That part's done.
  4. Then in a policy, add that pkg and add the script I've put together (not posted yet) to run as "After".
  5. The script extracts the plug-in titles and IDs as it loops through them in the temp directory, places the titles into an array that is used for the cocoaDialog checkboxes.
  6. The boxes that are checked by the user become the plist selections in the other array, and are then copied into /Library/Application Support/JAMF/Self Service/Plug-ins/

I've already got all of this working, I just need to do a little bit of cleanup on the script and a little bit more testing and then I'll post it up on my GitHub page.

Legendary Contributor III

Just a quick note here for anyone following this.
I uploaded a new companion script yesterday to my same github repo that can be used to do the user selectable Self Service Plug-in installation out of Self Service. The script is called ""
Along with the general description, I added an outline in the ReadMe of the suggested workflow to make it work in a policy. It requires (of course) cocoaDialog for the checkbox dialog presented to the end user.

Honored Contributor

Late to this party, but this is awesome @mm2270. Thank you.