How to Bind WatchGuard Firewall to Apple Open Directory for IPSec Mobile VPN Authentication

In this article I’ll show you how to configure a Watchguard firewall for Mac OS X and iOS, and how to bind a WatchGuard firewall to Apple Open Directory for VPN authentication.

WatchGuard has an excellent article here with detailed instructions on configuring a WatchGuard to mimic the behavior of Cisco IPSec. This allows us to use Mac OS X’s built-in Cisco IPSec profile when setting up VPN instead of having to use a 3rd-party VPN app, and some of the instructions below are extracted from it.

Binding a WatchGuard to Apple’s Open Directory is pretty straight forward in itself, however WatchGuard’s LDAP binding relies on the property memberOf to determine membership of an user account (which doesn’t exist in Apple Open Directory), we’ll need to perform a workaround to circumvent this.

What we’ll need to do:

1. Create service user and group on the Open Directory server.
2. Bind WatchGuard to Open Directory Server.
3. Configure WathcGuard Mobile VPN with IPSec.
4. Configure VPN on client machine.
5. Overcome the lack of memberOf property in Apple Open Directory.

Most of the configurations can be done in both the web interface and the WatchGuard System Management software (Windows only), except the last part. For consistency’s sake, I’ll only include screen shots for WatchGuard System Management.

1. Create service user and group on the Open Directory server.

We’ll first need to create an directory administrator account for the firewall. You can use the default diradmin account, but I prefer to have a separate account for the firewall. I will call mine firewall_admin.

We’ll then need to create a service group on the Open Directory server. Be mindful to the short name of the group. You’ll later need to match it to the Group Name of your IPSec rule. I will call mine ipsec_default.

pUuAA-6t-s1

Once you have the group created, move all user accounts who need VPN access into the group.

pUuAA-6t-s2

2. Bind WatchGuard to Open Directory Server.

In Fireware XTM Policy Manager, select Setup -> Authentication -> Authenticaion Servers.

pUuAA-6t-s3

Select the LDAP tap, and fill out the information according to your Open Directory server setup:

• Enter the IP of your Open Directory server.
• An example of Search Base would be: dc=server,dc=example,dc=com
• Group String can remain memberOf, since it doesn’t apply to Apple Open Directory.
• An example of DN of Searching User would be: uid=firewall_admin,cn=users,dc=server,dc=example,dc=com
• Everything else stays default.

pUuAA-6t-s4

3. Configure WatchGuard Mobile VPN with IPSec.

In Fireware XTM Policy Manager, select VPN -> Mobile VPN -> IPSec. Click Add to add a new configuration, then click Next.

pUuAA-6t-s5

Select LDAP for Authenticaion Server, and for Group Name use the short name of the service group you created earlier in Open Directory. In my case it would be ipsec_default. Click Next.

pUuAA-6t-s6

Select Use this passphrase and type in a secure password. This is the shared secret you’ll need when configuring a client machine. click Next.

Select Yse, force all Internet traffic to flow through the tunnel. (less flexible, more secure). Click Next.

pUuAA-6t-s7

Here you can define what your VPN users have access to. Leave it to default if you want them to have access to everything. If you do change it, make sure you allow the external port, otherwise your VPN user will lose Internet access after connecting to VPN. click Next.

pUuAA-6t-s8

Assign a range of IP addresses used by the VPN service. Make sure this pool of IP addresses don’t overlap with your DHCP or any static IP device on the network. Click Next and Finish.

pUuAA-6t-s9

• Select the configuration we just created, and click Edit…

pUuAA-6t-s10

• Under IPsec Tunnel tab, change Encryption to AES (256-bit).

pUuAA-6t-s11

• Click on Advanced. Change Key Group to Diffie-Hellman Group2. Click OK.

pUuAA-6t-s12

• Click on Proposal. Make sure Authenticaion is SHA1, Encryption is AES (256-bit), change Force Key Expiration time to 1 hour, and disable Force Key Expiration by Traffic. Click OK.

pUuAA-6t-s13

• Disable PFS. Click OK.

pUuAA-6t-s14

4. Configure VPN on client machine.

Open System Preferences, select Network. Click on the + button to add a new interface. Use the following settings in the drop-down window:
Interface: VPN
VPN Type: Cisco IPSec
Service Name: This can be anything you want.

pUuAA-6t-s15

Select the new interface, and enter the following settings:

Server Address: The external IP address or domain name of your firewall.
Account Name: The short name of the user account in Open Directory

pUuAA-6t-s16

Click on Authentication Settings, type in the shared secret you created in the IPSec configuration and the group name, which in my case would be ipsec_default. Hit OK.

5. Overcome the lack of memberOf in Apple Open Directory.

Now if you click on the Connect button, you’ll find that the VPN connection establishes without error, but you can’t access any of the internal devices. You’ll also see a lot of denied messages on your log server similar to this:

2014-04-22 12:49:12 Deny 192.168.1.123 8.8.8.8 dns/udp 55821 53 1-Trusted 0-External Denied 68 254 (Unhandled MUVPN Packet.in-01) proc_id="firewall" rc="101" src_user="tonyswu@LDAP” Traffic

This is the tricky part. The WatchGuard is bound to Open Directory, so the authentication part works, but because the group string memberOf doesn’t exist in Apple Open Directory, WatchGuard cannot determine what group the user belongs to. The request, with no IPSec rule to apply to, ends up being denied, which is why the denial reason is Unhandled MUVPN Packet. We can overcome this by manually assigning users to the IPSec rule.

In Fireware XTM Policy Manager, select Setup -> Authentication -> Authorized Users/Groups.

pUuAA-6t-s17

Click Add. Enter the user’s short name in Open Directory, select User in Type, and LDAP in Authentication Server.

pUuAA-6t-s18

Under Mobile VPN with IPSec tab, double click on the IPSec rule for your mobile VPN configuration.

pUuAA-6t-s19

Click Specify Users, and add the user.

pUuAA-6t-s20

You will need to repeat this process for each of the VPN user.

Conclusion.

It is unfortunate that we need to specify username again in the IPSec rule. However it at least allows you to manage the password from Open Directory. I’ve submitted multiple feature requests to WatchGuard, but I suspect this is probably not on the top of their list. If you feel like this is something they should improve upon, please submit feather request of your own. The more they get, the more likely they’ll start making their device compatible with Apple Open Directory.

Reference:

Use Mobile VPN with IPSec with a Mac OS X or iOS Device

How to Kick Start Carbon Copy Cloner Backup At Your Schedule

What is Carbon Copy Cloner?

Carbon Copy Cloner is an application that is capable of making bootable image / clone of a running Mac computer without disruption. It is very useful when you need to make a bootable clone of a server without having to shut it down, and it is a program I use on a daily basis. It makes disaster recovery so easy you almost want to intentionally create a disaster just to get a feeling of it.

However, we recently ran into a small issue with Carbon Copy Cloner: There is no real monthly scheduling. If you try to schedule a backup task on a monthly basis, here is the settings that are available:

CCC Monthly Schedule

In other words, if you need a backup to trigger on the first of every month, you are out of luck. I flagged this to Carbon Copy Cloner support, and they were kind enough to supply me with an AppleScript that can be used to kick start a backup task by name. Based on that AppleScript, I wrote a shell script that does pretty much the same thing, and a launchd configuration that can be used to trigger the script. Here is how it works.

1. Create a backup task as you normally would, but instead of setting up a schedule in Carbon Copy Cloner, set it to run manually.

Create Backup Task

2. Download the files here and unzip it. You’ll see two files inside: ccckickstart.sh (the script) and com.tonyswu.ccckickstart.TASKNAME.plist (the launchd configuration file).  Move the ccckickstart.sh script to somewhere system-level and permanent, such as /opt/tonyswu/bin:

$ sudo mkdir /opt/tonyswu/bin
$ sudo mv ~/Downloads/ccckickstart-master/ccckickstart.sh /opt/tonyswu/bin/

Rename the launchd configuration file as you need, open it up with Xcode or a text-only editor, and make changes according to your setup:

• Change label name.
• Change the first ProgramArguments to the path of your ccckickstart.sh script.
• Change the third ProgramArguments to the name of the backup task you setup in step 1.
• Change StartCalendarInterval to what you want. As is it’ll trigger the script at 20 past midnight on the first of every month.

3. Move the launchd configuration file to /Library/LaunchDaemon, change permission, and load it into launchd:

$ sudo mv ~/Downloads/ccckickstart-master/com.tonyswu.ccckickstart.TASKNAME.plist /Library/LaunchDaemon/
$ sudo chown root:wheel /Library/LaunchDaemon/com.tonyswu.ccckickstart.TASKNAME.plist
$ sudo launchctl load /Library/LaunchDaemon/com.tonyswu.ccckickstart.TASKNAME.plist

GitHub page here.

Mac Command Line: How to Add a Wireless Network

You can add a preferred wireless network on Mac by using the command line tool networksetup. To see the full list of flags networksetup takes, please refer to the man page here. We’ll be looking at the -addpreferredwirelessnetworkatindex flag specifically. The flag needs 5 parameters:

[-addpreferredwirelessnetworkatindex hardwareport network index securitytype [password]]

We’ll first need to find out what hardwareport we are using. We can do this using the same command, but with the flag -listallhardwareports:

networksetup -listallhardwareports

$ networksetup -listallhardwareports

Hardware Port: Bluetooth DUN
Device: Bluetooth-Modem
Ethernet Address: N/A

Hardware Port: Ethernet
Device: en0
Ethernet Address: 3c:07:54:70:f7:04

Hardware Port: FireWire
Device: fw0
Ethernet Address: 3c:07:54:ff:fe:b7:71:dc

Hardware Port: Wi-Fi
Device: en1
Ethernet Address: 70:56:81:9e:f1:a4

Hardware Port: Bluetooth PAN
Device: en3
Ethernet Address: N/A

Hardware Port: Thunderbolt 1
Device: en4
Ethernet Address: d2:00:1b:77:1d:c0

Hardware Port: Thunderbolt Bridge
Device: bridge0
Ethernet Address: N/A

Look at the section Hardware Port: Wi-Fi, and the Device value is the one you want to use for hardwareport. Note that this value will be different depending on models of computers. With hardwareport, we can now add the wireless network:

$ networksetup -addpreferredwirelessnetworkatindex en1 WifiName 1 WPA2 "PASSWORD"

In order to build this into a script, we just need to run the -listallhardwareports flag first and do some text manipulation:

#!/bin/bash

portName=`/usr/sbin/networksetup -listallhardwareports | /usr/bin/sed -n '/Wi-Fi/,/Hardware/p' | /usr/bin/grep "Device" | /usr/bin/awk '{print $2}'`
/usr/sbin/networksetup -addpreferredwirelessnetworkatindex "$portName" WifiName 1 WPA2 "PASSWORD"

exit 0

How to Install Munki and Munki Web Admin on Mac OS X 10.8 Mountain Lion Server, Part 2

What is MunkiWebAdmin?
MunkiWebAdmin is a Django web application that incorporates the functionality of the MunkiReport project and also provides the ability to browse catalogs, and browse and edit manifests of an existing Munki repo.

What you’ll need:
1. Working Munki Server with Mac OS X 10.8 Mountain Lion and Server App (Don’t have one? Follow part 1 here)
2. Xcode and command line tools

The following items are needed, but if you followed part 1 here, you should already have them in place:
1. Text editor of your choice (I use TextWrangler)
2. A domain name (I use munkidemo.test.com)
3. A valid SSL Certificate

1. Install Xcode and the Command Line Tools

Open up App Store and install Xcode. Once it’s installed, launch Xcode, go to Xcode -> Preferences…, click on Downloads, then install the Command Line Tools.

Install Xcode and Command Line Tools

2. Install MySQL (version 5.6.15 at the time of writing this guide)

Download MySQL at:

http://dev.mysql.com/downloads/mysql/

Make sure you download the Mac OS X ver. 10.7 (x86, 64-bit), DMG Archive installer. Double click on the DMG file, and you’ll find two .pkg installers and one .prefPane file. Go ahead and install all three.

In my opinion, it is a good idea to separate data from the system in a server environment, so I’ll modify the configuration to save MySQL databases in the Data partition that we use for Munki’s repository.

In System Preferences, make sure MySQL is not running. If it is running, turn it off. Run the following command to move the databases from the default location to the Data partition:

$ sudo mkdir /Volumes/Data/mysql
$ sudo cp -R /usr/local/mysql/data /Volumes/Data/mysql/
$ sudo chown -R _mysql /Volumes/Data/mysql

Open the my.cnf file with your favorite command line text editor:

$ sudo vi /usr/local/mysql/my.cnf

Find the line:

# datadir = .....

and change it to:

datadir = /Volumes/Data/mysql/data

Make sure to remove the leading # symbol, then save the file. Turn on MySQL from System Preferences.

If you are working on a production server, this is also a good time to set the root password for MySQL:

$ /usr/local/mysql/bin/mysqladmin -u root password NEWPASSWORD

3. Create MySQL database and user

Run MySQL from the command line:

$ /usr/local/mysql/bin/mysql -u root -p

Create a database (I use munkiwebadmin as the name of the database):

mysql> CREATE DATABASE munkiwebadmin;

Create an user (I use munkiwebadmin as the user name):

mysql> GRANT ALL ON munkiwebadmin.* TO 'munkiwebadmin'@'localhost' IDENTIFIED BY 'PASSWORD';

Change database characcter set to UTF8:

mysql> ALTER DATABASE munkiwebadmin CHARSET=utf8;

4. Install and Configure Virtual Environment

Usually you can install virtualenv with just sudo easy_install virtualenv, but at the time of writing this guide there was a problem with virtualenv installed by easy_install, so we’ll get around this by installing virtualenv with pip:

$ sudo easy_install pip
$ sudo pip install virtualenv

Create a new virtual environment:

$ cd /usr/local
$ sudo virtualenv munkiwebadmin

Go into the newly created directory and activate the virtual environment:

$ cd /usr/local/munkiwebadmin
$ source bin/activate

Your command prompt should now have (munkiwebadminl) in the front:

(munkiwebadminl)$

Install django and prerequisites:

(munkiwebadminl)$ sudo pip install django==1.5.1
(munkiwebadminl)$ sudo pip install django-wsgiserver==0.8.0beta
(munkiwebadminl)$ export PATH=$PATH:/usr/local/mysql/bin
(munkiwebadminl)$ sudo pip install MySQL-python

Install and configure munkiwebadmin:

(munkiwebadminl)$ sudo git clone https://code.google.com/p/munki.munkiwebadmin/ munkiwebadmin
(munkiwebadminl)$ cd munkiwebadmin

Make a copy of the settings_template.py file, and open it up with your favorite command line text editor:

(munkiwebadminl)$ sudo cp settings_template.py settings.py
(munkiwebadminl)$ sudo vi settings.py

On line 33, edit the administrator’s name and email:

ADMINS = (
  ('Administrator', 'administrator@test.com'),
)

Comment out everything from line 40 to 49:

#DATABASES = {
#   'default': {
#     'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
#     'NAME': os.path.join(PROJECT_DIR, 'munkiwebadmin.db'), # Or path to database file if using sqlite3.
#     'USER': '', # Not used with sqlite3.
#     'PASSWORD': '', # Not used with sqlite3.
#     'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
#     'PORT': '', # Set to empty string for default. Not used with sqlite3.
#   }
#}

Uncomment everything from line 52 to 61, and change the database name, user, and password to what you created in MySQL earlier:

DATABASES = {
  'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME': 'munkiwebadmin',
    'USER': 'munkiwebadmin',
    'PASSWORD': 'PASSWORD',
    'HOST': 'localhost',
    'PORT': '',
  }
}

Under INSTALLED_APPS on line 173, uncomment django_wsgiserver.

On line 216, change MUNKI_REPO_DIR to the location of the Munki repository (/Volumes/Data/munki_repo if you followed part 1):

MUNKI_REPO_DIR = '/Volumes/Data/munki_repo'

Save and close the document.

5. Initialize the Database

Initialize the database with the following command:

(munkiwebadminl)$ python manage.py syncdb

You’ll get this error message:

django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: dlopen(/usr/local/munkiwebadmin/lib/python2.7/site-packages/_mysql.so, 2): Library not loaded: libmysqlclient.18.dylib
Referenced from: /usr/local/munkiwebadmin/lib/python2.7/site-packages/_mysql.so
Reason: image not found

MySQL.so Error

It would seem that the object _mysql.so cannot find the library libmysqlclient.18.dylib. We can use otool to find out why:

$ otool -L /usr/local/munkiwebadmin/lib/python2.7/site-packages/_mysql.so
/usr/local/munkiwebadmin/lib/python2.7/site-packages/_mysql.so:
libmysqlclient.18.dylib (compatibility version 18.0.0, current version 18.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)

otool

It seems _mysql.so is trying to locate the library with empty path. We can use name_install to fix it:

$ sudo install_name_tool -change libmysqlclient.18.dylib /usr/local/mysql/lib/libmysqlclient.18.dylib /usr/local/munkiwebadmin/lib/python2.7/site-packages/_mysql.so

Run otool again to make sure the change was good:

$ otool -L /usr/local/munkiwebadmin/lib/python2.7/site-packages/_mysql.so
/usr/local/munkiwebadmin/lib/python2.7/site-packages/_mysql.so:
/usr/local/mysql/lib/libmysqlclient.18.dylib (compatibility version 18.0.0, current version 18.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)

Fix MySQL.so Error

Let’s try to initialize the database again:

(munkiwebadminl)$ python manage.py syncdb

You’ll be prompted to create a default admin user. Enter yes, and follow the prompt to finish creating a default admin user:

You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (leave blank to use 'administrator'):
Email address: administrator@test.com
Password:
Password (again):
Superuser created successfully.
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)

Initialize Database

Stage the static files (type yes when prompted):

$ sudo python manage.py collectstatic

6. Start the Web Application and Test

You can start the web application by running:

(munkiwebadmin)$ python manage.py runwsgiserver port=8000 host=0.0.0.0

Open your browser of choice and go to http://127.0.0.1:8000. You should now see the login page of MunkiWebAdmin.

You can now exit out of terminal and terminate the virtual environment.

7. Bootstrap MunkiWebAdmin with Apache and Server App

First, let’s change the owner of the munkiwebadmin folder to _www so Apache can access the folder:

$ sudo chown -R _www:_www /usr/local/munkiwebadmin

Download the following 3 files:

com.test.munkiwebadmin.plist
httpd_munkiwebadmin.conf
munkiwebadmin.wsgi

You may have to go through the files and change some of the paths if you decided to install Munki Web Admin elsewhere. Also note that you should change the domain name com.test to your own domain, although this doesn’t really matter.

Move them to the correct location and change the permission:

$ sudo mv ~/Downloads/com.test.munkiwebadmin.plist /Library/Server/Web/Config/apache2/webapps/
$ sudo chown administrator:staff /Library/Server/Web/Config/apache2/webapps/com.test.munkiwebadmin.plist
$ sudo mv ~/Downloads/httpd_munkiwebadmin.conf /Library/Server/Web/Config/apache2/
$ sudo chown administrator:staff /Library/Server/Web/Config/apache2/httpd_munkiwebadmin.conf
$ sudo mv ~/Downloads/munkiwebadmin.wsgi /usr/local/munkiwebadmin/munkiwebadmin/
$ sudo chown _www:_www /usr/local/munkiwebadmin/munkiwebadmin/munkiwebadmin.wsgi

Open up Server App, select the Websites service, and click on the + button to add a site.

Change the domain name, port number, and SSL certificate. Since the domain name is the same, you can use the same SSL certificate that was used to secure your Munki implementation if you followed part 1.

Website Settings

Click on Edit Advanced Settings…, and enable the web applicatiosn MunkiWebAdmin. If you don’t see it, you may have to restart the Website service.

Website Advanced Settings

Open your browser of choise, and go to https://127.0.0.1:8443, you should now see the login page of MunkiWebAdmin again.

If you followed part 1, remember that we had to change the authentication type to Basic instead of the default Digest for our Munki server. We’ll need to take care of that again. Open the Apache configuration file for the secure site with your favorite command line text editor:

$ sudo vi /Library/Server/Web/Config/apache2/sites/0000_any_443_.conf

Find the line AuthType Digest, and change it to AuthType Basic. Save the file, and restart Websites service from Server.app

8. Client Configuration

In the /usr/local/munkiwebadmin/munkiwebadmin/scripts folder, you’ll find the scripts that need to be installed on the client machines:

munkiwebadmin-config
postflight
preflight
report_broken_client

Open munkiwebadmin-config with your favorite command line text editor:

$ sudo vi /usr/local/munkiwebadmin/munkiwebadmin/scripts/munkiwebadmin-config

On line 6, change the MWA_HOST value to what was configured in Server App:

MWA_HOST="https://munkidemo.test.com:8443"

Copy the 4 files to the client machines at /usr/local/munki and modify the permission and owner:

$ sudo cp ~/Downloads/munkiwebadmin-config /usr/local/munki/
$ sudo cp ~/Downloads/postflight /usr/local/munki/
$ sudo cp ~/Downloads/preflight /usr/local/munki/
$ sudo cp ~/Downloads/report_broken_client /usr/local/munki/
$ sudo chown root:wheel /usr/local/munki/munkiwebadmin-config
$ sudo chown root:wheel /usr/local/munki/postflight
$ sudo chown root:wheel /usr/local/munki/preflight
$ sudo chown root:wheel /usr/local/munki/report_broken_client
$ sudo chmod 755 /usr/local/munki/munkiwebadmin-config
$ sudo chmod 755 /usr/local/munki/postflight
$ sudo chmod 755 /usr/local/munki/preflight
$ sudo chmod 755 /usr/local/munki/report_broken_client

Test the connection by running:

$ sudo /usr/local/munki/managedsoftwareupdate --checkonly

You should now see your client listed in MunkiWebAdmin.

MunkiWebAdmin at Work

9. Reference

https://code.google.com/p/munki/wiki/MunkiWebAdminOSXSetup
https://code.google.com/p/munki/wiki/MunkiWebAdminUbuntuSetup
http://fluffyquickness.com/2013/01/mwa-10-8-server/

How to Install Munki and Munki Web Admin on Mac OS X 10.8 Mountain Lion Server, Part 1

What is Munki?
Munki is a set of tools that, used together with a webserver-based repository of packages and package metadata, can be used by OS X administrators to manage software installs (and in many cases removals) on OS X client machines.

What you’ll need:
1. Mac OS X 10.8 Mountain Lion with Server App
2. Munki Tools
3. Text editor of your choice (I use TextWrangler)
4. A domain name (I use munkidemo.test.com)
5. A valid SSL Certificate

1. Setup Munki Repository

I recommend separating Munki repository from the system partition. Mac Mini Server has 2 internal hard drives, so you can use one for system and the other for data. Alternatively, if you have a lot of clients to serve, an external RAID device may be a better idea. In this example I will place the Munki repository in a different volume called “Data”. Let’s create the repository by typing these commands in Terminal:

$ cd /Volumes/Data
$ mkdir munki_repo
$ mkdir munki_repo/catalogs
$ mkdir munki_repo/manifests
$ mkdir munki_repo/pkgs
$ mkdir munki_repo/pkgsinfo

Change the permission:

$ sudo chmod -R a+rX /Volumes/Data/munki_repo

This’ll add read and execute permissions to all categories of the ownership (owner, group, and other).

2. Setup Web Services

Open up Server.app. Turn on Websites, double click on Server Website to edit the settings. Click on the drop down menu Store Site File In, and select the munki_repo folder we created. Click Done to save the configuration.

Repeat the above for Server Website (SSL).

pUuAA-4E-sc1pUuAA-4E-sc2

3. Install and Configure Munki Tools on the Server

Download the latest version of Munki tools here, install and restart your server:

http://code.google.com/p/munki/downloads/list

Add Munki to the search path, it’ll save you a lot of typing:

$ PATH=$PATH\:/usr/local/munki
$ export PATH

Configure Munki with some basic information (this is user account specific, if you switch to a different user account you’ll need to do this again):

$ munkiimport --configure
Path to munki repo (example: /Volumes/repo): /Volumes/Data/munki_repo
Repo fileshare URL (example: afp://munki.example.com/repo):
pkginfo extension (Example: .plist):
pkginfo editor (examples: /usr/bin/vi or TextMate.app): TextWrangler.app
Default catalog to use (example: testing): test

4. Import Software and Create Client Manifest

Let’s start by importing a simple application like Firefox. Download the latest version of Firefox here:

http://www.mozilla.org/en-US/firefox/new/

Type in the following commands in Terminal:

$ munkiimport ~/Downloads/Firefox\ 26.0.dmg

Item name [Firefox]:
Display name: Firefox
Description: Firefox web browser.
Version [26.0]:
Catalogs [test]:

Item name: Firefox
Display name: Firefox
Description: Firefox web browser.
Version: 26.0
Catalogs: test

Import this item? [y/n] y
Upload item to subdirectory path []:
Copying Firefox 26.0.dmg to /Volumes/Data/munki_repo/pkgs/Firefox 26.0.dmg...
Saving pkginfo to /Volumes/Data/munki_repo/pkgsinfo/Firefox-26.0...
Rebuild catalogs? [y/n] y
Rebuilding catalogs at /Volumes/Data/munki_repo...

At this point, the text editor of your choice should pop up with the pkginfo file, and you should notice a few files created under your Munki repository.

Run the following command in Terminal to create a client manifest (I’ll call mine first_client), add the catalog test to the manifest, and add the package Firefox to the manifest:

$ manifestutil

Entering interactive mode... (type "help" for commands)
> new-manifest first_client
> add-catalog test --manifest first_client
Added test to catalogs of manifest first_client.
> add-pkg Firefox --manifest first_client
Added Firefox to section managed_installs of manifest first_client.
> exit

5. Configure Client Installation and Test

Download the latest version of Munki tools from here:

http://code.google.com/p/munki/downloads/list

and install on your client machine. You’ll need to restart after the installation.

Munki client by default stores the configuration in /Library/Preferences/ManagedInstalls.plist. Type in the following command in Terminal to write the server url and client identifier so Munki client knows where to check for software update. Note that ClientIdentifier needs to match the name of the manifest you created in step 4 (first_client):

$ sudo defaults write /Library/Preferences/ManagedInstalls SoftwareRepoURL "http://munkidemo.test.com"
$ sudo defaults write /Library/Preferences/ManagedInstalls ClientIdentifier "first_client"

Confirm the change was written in the file:

$ defaults read /Library/Preferences/ManagedInstalls
{
    ClientIdentifier = "first_client";
    SoftwareRepoURL = "http://munkidemo.test.com";
    ...
}

Launch the application Managed Software Update under the Utilities folder, and you should see Firefox listed as a software update.

pUuAA-4E-sc6

6. Add User Authentication to Munki

You now have a functional Munki server and client environment, but it is a good idea to add user authentication to limit access, even more so if you plan to add licensed software in your Munki repo. It is also a good idea to have multiple accounts for different groups of devices, so that an account can be disabled / changed without affecting others.

We’ll need a directory structure for this. If you already have an Active Directory or Open Directory server, just bind your Munki server to it. If not, we’ll create our own.

In Server.app, turn on Open Directory and select the option Create a new Open Directory domain. Specify a password for diradmin and fill in the Organization Name and Admin Email Address to finish the setup.

In Server.app, select Users, select Local Network Users from the drop down menu, and click on the + button to create new users.

pUuAA-4E-sc3

In Server.app, select Groups, select Local Network Groups from the drop down menu, click on the + button to create a new group. I’ll call mine Munki Users (munki_users). Select the group you just created, click on the gear button, and select Edit Group… In the Members section, click on the + button to include all the user accounts that should have access to your Munki repository, and hit Done.

pUuAA-4E-sc4pUuAA-4E-sc5

In Server.app, select Websites, double click on Server Website, and change Who Can Access to Munki Users. Repeat this step for Server Website (SSL).

pUuAA-4E-sc7

We’ll now add the username and password information in the ManagedInstalls.plist file on the client machine. By default the ManagedInstalls.plist configuration file is placed in /Library/Preferences folder, which all user accounts have read permission to. To prevent the users from being able to read the username and password, we’ll move the configuration file to another location recognized by Munki where permission is more limited (/private/var/root/Library/Preferences/ManagedInstalls.plist):

$ sudo mv /Library/Preferences/ManagedInstalls.plist /private/var/root/Library/Preferences/

Munki uses HTTP basic authentication, and we’ll need to encode the username and password using base64 encoding scheme before adding the information into ManagedInstalls.plist. Run the following commands in Terminal (substitute USERNAME and PASSWORD with one of the users you created above):

$ python -c 'import base64; print "Authorization: Basic %s" % base64.b64encode("USERNAME:PASSWORD")'
Authorization: Basic Y2xpZW50X2E6Y2xpZW50X2E=

Add the result into ManagedInstalls.plist:

$ sudo defaults write /private/var/root/Library/Preferences/ManagedInstalls.plist AdditionalHttpHeaders -array "Authorization: Basic Y2xpZW50X2E6Y2xpZW50X2E="

Confirm the change was written in the file:

$ sudo defaults read /private/var/root/Library/Preferences/ManagedInstalls.plist
{
    AdditionalHttpHeaders = (
        "Authorization: Basic Y2xpZW50X2E6Y2xpZW50X2E="
    );
    ...
}

Run the following command in Terminal on the client machine to verify if it’s functional:

$ sudo /usr/local/munki/managedsoftwareupdate --checkonly

You should see some error messages:

ERROR: Could not retrieve manifest client_manifest from the server: Error 22: The requested URL returned error: 401
ERROR: Could not retrieve managed install primary manifest.

If you take a look at the Error Log (Server Website) on the server, you’ll see why it’s not working:

mod_digest_apple: Client used wrong authentication scheme ‘Basic’ in request for URI /manifests/first_client

Looks like the web server is using Digest authentication while the client is using Basic. Munki only supports Basic authentication, and unfortunately Server.app in OS X 10.7 and above does not give you the option to specify which authentication scheme to use, so we’ll need to change this using command line. Use your favorite command line text editor to open the Apache configuration file:

$ sudo vi /Library/Server/Web/Config/apache2/sites/0000_any_80_.conf

Inside the <Directory “/Volumes/Data/munki_repo”> and <Directory “/Volumes/Data/munki_repo”> clause, find the line AuthType Digest, and change it to AuthType Basic. Save the file, and restart Websites service from Server.app. Now run the command again to verify if client is working:

$ sudo /usr/local/munki/managedsoftwareupdate --checkonly

Everything should be working fine now. Please note that Server.app WILL overwrite your change on the authentication type if you modify and save any website information. I’ve not found a way around it, so just remember that if you change anything in Server.app regarding Websites service, you’ll also need to change the authentication type again.

7. Secure Munki Using SSL Certificate

Since Munki only supports Basic authentication type, which means username / password information is transmitted without encryption, we’ll need to address this security concern with a SSL certificate.

You can use a self-signed certificate, but I would recommend you to get a signed certificate from a 3rd party certificate authority.

Once you have the certificate imported into Server.app, double click on Server Website (SSL) and specify the certificate you want to use.

Also remember we’ll need to change the AuthType in Apache configuration again, similar to what we did in step 6, but for the secure connection. Open the Apache configuration file for the secure site:

$ sudo vi /Library/Server/Web/Config/apache2/sites/0000_any_443_.conf

Find the line AuthType Digest, and change it to AuthType Basic. Save the file, and restart Websites service from Server.app

Now we need to change client configuration to use https rather than http:

$ sudo defaults write /private/var/root/Library/Preferences/ManagedInstalls.plist SoftwareRepoURL "https://munkidemo.test.com"

Verify the modification sticks:

$ sudo defaults read /private/var/root/Library/Preferences/ManagedInstalls.plist
{
    SoftwareRepoURL = "https://munkidemo.test.com";
    ...
}

Verify client is still working:

$ sudo /usr/local/munki/managedsoftwareupdate --checkonly

Note that there is no way (that I know of) to remove the default port 80 Server Website, so you’ll need to limit the access of port 80 somewhere else. Ideally you should have your servers behind firewall. If so, you can achieve this by denying any traffic from port 80 to the Munki server.

References:

https://code.google.com/p/munki/
https://code.google.com/p/munki/wiki/DemonstrationSetup

How to Install OTRS Help Desk on Mac OS X 10.8 Mountain Lion

This is a step-by-step guide to installing OTRS on Mac OS X 10.8 Mountain Lion. While I was attempting this, I found quite a bit of scattered information on the Internet, but no step-by-step guide. It took me a while to get everything together and finally get it to work, so I thought I might share my process and perhaps be able to help someone out.

What you’ll need:

  • Mac OS X 10.8 Mountain Lion (without Server app)
  • MySQL
  • OTRS Help Desk
  • Xcode (and the command line tools)
  • Coffee to keep you awake

The reason I picked 10.8 client over server is because some customizations are needed for Apache, and the server version is already customized by Apple, and I would rather work with something clean.

1. Install Xcode and the Command Line Tools

Open up App Store and install Xcode. Once it’s installed, launch Xcode, go to Xcode -> Preferences…, click on Downloads, then install the Command Line Tools.

Xcode Command Line Tools

2. Install MySQL (version 5.6.12 at the time of writing this guide)

Download MySQL at:

http://dev.mysql.com/downloads/mysql/

Make sure you download the Mac OS X ver. 10.7 (x86, 64-bit), DMG Archive installer. Double click on the DMG file, and you’ll find two .pkg installers and one .prefPane file. Go ahead and install all three.

After installation is finished, we’ll need to modify the configuration slightly. Open the my.cnf file with your favorite command line text editor:

$ sudo vi /usr/local/mysql/my.cnf

Add the following line into the configuration file:

max_allowed_packet=8M

Save the file. If you are working on a production server, this is also a good time to set the root password for MySQL:

$ /usr/local/mysql/bin/mysqladmin -u root password NEWPASSWORD

Turn on MySQL from System Preferences.

3. Install OTRS Help Desk from Source (version 3.2.9 at the time of writing this guide)

Download OTRS Help Desk at:

http://www.otrs.com/en/open-source/get-otrs/software-download/

Make sure you download the tar.gz version under Source Archive. After it’s downloaded, unarchive it by double clicking on it, then move it to the path /opt/otrs:

$ sudo mkdir /opt
$ sudo mv ~/Downloads/otrs-3.2.9 /opt/otrs

Move the configuration files in place:

$ sudo cp /opt/otrs/Kernel/Config.pm.dist /opt/otrs/Kernel/Config.pm
$ sudo cp /opt/otrs/Kernel/Config/GenericAgent.pm.dist /opt/otrs/Kernel/Config/GenericAgent.pm

4. Verify Perl Modules

We’ll run the built-in script to verify what modules are needed by OTRS:

$ perl /opt/otrs/bin/otrs.CheckModules.pl

Most of the modules not installed will say optional, but it is recommended to get them all installed, except the DBD modules. For those, you’ll only need the one that you are going to use. So here are the list of modules we’ll need to install:

  • Crypt::SSLeay
  • DBD::mysql
  • Encode::HanExtra
  • GD
  • GD::Text
  • GD::Graph
  • JSON::XS
  • Mail::IMAPClient
  • Net::SSL
  • PDF::API2
  • Text::CSV_XS
  • YAML::XS

5. Install Perl Module YAML::XS

YAML is the only one listed as required, it’s also a dependency on some other modules, so we’ll start there. Type in the following line in Terminal:

$ sudo perl -MCPAN -e 'install YAML::XS'

If this is your first time using cpan, answer yes to the questions so it automatically configures itself.

6. Install Perl Module Crypt::SSLeay

Type in the following line in Terminal:

$ sudo perl -MCPAN -e 'install Crypt::SSLeay'

It is your choice whether to run the live test or not.

7. Install Perl Module Bundle::DBI

This is not listed, but it’s a dependency for DBD::mysql, so let’s get it installed:

$ sudo perl -MCPAN -e 'install Bundle::DBI'

8. Install Perl Modules DBD::mysql

We’ll install this module manually, because without changing some configurations on the make file the test won’t complete successfully. Let’s start by creating an user for testing purpose:

$/usr/local/mysql/bin/mysql -u root -p
mysql> GRANT ALL ON test.* TO 'test'@'localhost' IDENTIFIED BY 'test';
mysql> exit

Type the following commands in Terminal, and note the return values:

$ /usr/local/mysql/bin/mysql_config --cflags --libs
-I/usr/local/mysql/include -Wno-null-conversion -Os -g -fno-strict-aliasing -arch x86_64
-L/usr/local/mysql/lib -lmysqlclient

Get the module by typing the following line in terminal:

$ sudo perl -MCPAN -e 'get DBD::mysql'

Navigate to the cpan build directory (substitute administrator with the user name you are using, and the version number of the module may vary as well):

$ cd /Users/administrator/.cpan/build/DBD-mysql-4.023-pyyK8K

Type the following commands in Terminal. Use the –cflags and –libs values we got earlier:

$ sudo perl Makefile.pl --cflags="-I/usr/local/mysql/include -Wno-null-conversion -Os -g -fno-strict-aliasing -arch x86_64" --libs="-L/usr/local/mysql/lib -lmysqlclient" --testuser="test" --testpassword="test"

Then type in:

$ sudo make
$ sudo make test

Then you’ll get this error:

# Failed test 'use DBD::mysql;'
# at t/00base.t line 21.
# Tried to use 'DBD::mysql'.
# Error: Can't load '/Users/administrator/.cpan/build/DBD-mysql-4.023-pyyK8K/blib/arch/auto/DBD/mysql/mysql.bundle' for module DBD::mysql: dlopen(/Users/administrator/.cpan/build/DBD-mysql-4.023-pyyK8K/blib/arch/auto/DBD/mysql/mysql.bundle, 2): Library not loaded: libmysqlclient.18.dylib
# Referenced from: /Users/administrator/.cpan/build/DBD-mysql-4.023-pyyK8K/blib/arch/auto/DBD/mysql/mysql.bundle
# Reason: image not found at /System/Library/Perl/5.12/darwin-thread-multi-2level/DynaLoader.pm line 204.
# at (eval 7) line 2
# Compilation failed in require at (eval 7) line 2.
# BEGIN failed--compilation aborted at (eval 7) line 2.
FAILED--Further testing stopped: Unable to load DBD::mysql
make: *** [test_dynamic] Error 255

So it would appear that the mysql.bundle file cannot find the path to the libmysqlclient.18.dylib library. Let’s find out why by using otool:

$ otool -L /Users/administrator/.cpan/build/DBD-mysql-4.023-pyyK8K/blib/arch/auto/DBD/mysql/mysql.bundle

/Users/administrator/.cpan/build/DBD-mysql-4.023-pyyK8K/blib/arch/auto/DBD/mysql/mysql.bundle:
libmysqlclient.18.dylib (compatibility version 18.0.0, current version 18.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)

So it’s looking for the library with no path information. Let’s fix that:

$ sudo install_name_tool -change libmysqlclient.18.dylib /usr/local/mysql/lib/libmysqlclient.18.dylib /Users/administrator/.cpan/build/DBD-mysql-4.023-pyyK8K/blib/arch/auto/DBD/mysql/mysql.bundle

Verify if the change stuck:

$ otool -L /Users/administrator/.cpan/build/DBD-mysql-4.023-pyyK8K/blib/arch/auto/DBD/mysql/mysql.bundle

/Users/administrator/.cpan/build/DBD-mysql-4.023-pyyK8K/blib/arch/auto/DBD/mysql/mysql.bundle:
/usr/local/mysql/lib/libmysqlclient.18.dylib (compatibility version 18.0.0, current version 18.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)

Now let’s test again:

$ sudo make test

This time it should pass. Now we can install it:

$ sudo make install

After it’s installed, we can drop the test user:

$/usr/local/mysql/bin/mysql -u root -p
mysql> DROP USER 'test'@'localhost';
mysql> exit

9. Install Perl Module Encode::HanExtra

Type in the following in command line:

$ sudo perl -MCPAN -e 'install Encode::HanExtra'

10. Install Perl Module GD

We’ll also do this one manually. Download the following dependency libraries and decompress after download is finished:

Install zlib:

$ cd ~/Downloads/zlib-1.2.8
$ ./configure --shared
$ make
$ sudo make install

Install libpng

$ cd ~/Downloads/libpng-1.6.2
$ cp scripts/makefile.darwin Makefile
$ ./configure --prefix=/usr/local
$ make
$ sudo make install

Install JPEG library:

$ cd ~/Downloads/jpeg-9/
$ ./configure --enable-shared
$ make
$ sudo make install

Install FreeType

$ cd ~/Downloads/freetype-2.5.0.1
$ ./configure
$ make
$ sudo make install

Install LibGD

$ cd ~/Downloads/libgd-2.1.0
$ ./configure
$ make
$ sudo make install

Install GD

$ perl -MCPAN -e 'get GD'
$ cd /Users/administrator/.cpan/build/GD-2.50-cs7Ejq
$ perl Makefile.pl
$ make
$ sudo make install

11. install Perl Module GD::Text

$ sudo perl -MCPAN -e 'install GD::Text'

12. install Perl Module GD::Graph

$ sudo perl -MCPAN -e 'install GD::Graph'

13. install Perl Module JSON::XS

$ sudo perl -MCPAN -e 'install JSON::XS'

14. install Perl Module Mail::IMAPClient

$ sudo perl -MCPAN -e 'install Mail::IMAPClient'

15. install Perl Module PDF::API2

$ sudo perl -MCPAN -e 'install PDF::API2'

16. install Perl Module Text::CSV_XS

$ sudo perl -MCPAN -e 'install Text::CSV_XS'

17. Verify Modules Installation and Perl Syntax

Let’s verify t modules again:

$ perl /opt/otrs/bin/otrs.CheckModules.pl

There should only be 3 uninstalled modules for database systems that we will not be using. Run the following three scripts to verify syntax:

$ perl -cw /opt/otrs/bin/cgi-bin/index.pl
$ perl -cw /opt/otrs/bin/cgi-bin/customer.pl
$ perl -cw /opt/otrs/bin/otrs.PostMaster.pl

You should get the return value syntax OK on all three.

18. Configure Apache Web Server

Allow the apache web user to access the OTRS directory:

$ sudo chown -R _www:_www /opt/otrs

Move OTRS’ configuration file in place:

$ sudo cp /opt/otrs/scripts/apache2-httpd.include.conf /etc/apache2/other/otrs.conf

Open up Apache configuration file with your favorite command line text editor:

$ sudo vi /etc/apache2/httpd.conf

Un-comment line 116 and 117:

LoadModule perl_module libexec/apache2/mod_perl.so
LoadModule php5_module libexec/apache2/libphp5.so

Change line 169 to:

DocumentRoot "/opt/otrs/var/httpd/htdocs"

Change line 196 to:

<Directory "/opt/otrs/var/httpd/htdocs">

Change line 209 to:

Options Indexes FollowSymLinks MultiViews Includes ExecCGI

Add the following on line 210:

DirectoryIndex index.html index.pl

Change line 216 to:

AllowOverride all

Un-comment line 397 and add .pl as a file type:

AddHandler cgi-script .cgi .pl

Un-comment line 408 and 409:

AddType text/html .shtml
AddOutputFilter INCLUDES .shtml

Start Apache web server:

$ sudo apachectl start

Configure Apache to start automatically after reboot:

$ sudo defaults write /System/Library/LaunchDaemons/org.apache.httpd Disabled -bool false

19. Manually Create Database for OTRS

The recommended way on the OTRS admin manual for creating the OTRS database is to use the built-in installer at http://localhost/otrs/installer.pl. However, when I tried it, it gave me an error saying Specified key was too long; max key length is 767 bytes. So much for the recommended way. Let’s attempt this manually.

First, let’s create a database and an user:

$ /usr/local/mysql/bin/mysql -u root -p
mysql> CREATE DATABASE otrs;
mysql> GRANT ALL ON otrs.* TO 'otrs'@'localhost' IDENTIFIED BY 'YOUR_PASSWORD';
mysql> exit

Execute the following 3 scripts (they must be executed in this order):

$ /usr/local/mysql/bin/mysql -u otrs -p otrs < /opt/otrs/scripts/database/otrs-schema.mysql.sql
$ /usr/local/mysql/bin/mysql -u otrs -p otrs < /opt/otrs/scripts/database/otrs-initial_insert.mysql.sql
$ /usr/local/mysql/bin/mysql -u otrs -p otrs < /opt/otrs/scripts/database/otrs-schema-post.mysql.sql

Open up Config.pm with your favorite text editor:

$ sudo vi /opt/otrs/Kernel/Config.pm

And fill out the information according to what you did with MySQL:

# The database host
$Self->{DatabaseHost} = 'localhost';

# The database name
$Self->{Database} = 'otrs';

# The database user
$Self->{DatabaseUser} = 'otrs';

# The password of database user. You also can use bin/otrs.CryptPassword.pl
# for crypted passwords
$Self->{DatabasePw} = 'some-pass';

Now go to http://localhost and login:

Username: root@localhost
Password: root

You should see your OTRS Help Desk. This is also a good time to change your root password if your server is in production or faces the Internet in any way.

20. Setup Recurssive Background Task

OTRS uses cron tab to execute recurssive background tasks. However, cron job has been deprecated in Mac OS X, so we’ll attempt to do the same thing using launchd.

There are multiple cron jobs in the folder /opt/otrs/var/cron, and we’ll reproduce the following ones in launchd:

  • cache.dist
  • generic_agent-database.dist
  • pending_jobs.dist
  • postmaster_mailbox.dist
  • postmaster.dist
  • rebuild_ticket_index.dist
  • session.dist
  • unlock.dist

You can save yourself some time and click on the link here to download all the .plist files, or you can use Xcode and create those files yourself following the screenshots below:

com.otrs.cleanup.plist
com.otrs.DeleteCache.plist
com.otrs.DeleteSessionIDs.plist
com.otrs.GenericAgentDatabase.plist
com.otrs.LoaderCache.plist
com.otrs.PendingJobs.plist
com.otrs.PostMasterMailbox.plist
com.otrs.RebuildTicketIndex.plist
com.otrs.UnlockTickets.plist

Once you have all the files ready, move them to the folder /Library/LaunchDaemons and change the permission to match the parent folder:

$ sudo chown root:wheel /Library/LaunchDaemons/com.otrs.*

Load the files into launchd:

$ launchctl load /Library/LaunchDaemons/com.otrs.cleanup.plist /Library/LaunchDaemons/com.otrs.DeleteCache.plist /Library/LaunchDaemons/com.otrs.DeleteSessionIDs.plist /Library/LaunchDaemons/com.otrs.GenericAgentDatabase.plist /Library/LaunchDaemons/com.otrs.LoaderCache.plist /Library/LaunchDaemons/com.otrs.PendingJobs.plist /Library/LaunchDaemons/com.otrs.PostMasterMailbox.plist /Library/LaunchDaemons/com.otrs.RebuildTicketIndex.plist /Library/LaunchDaemons/com.otrs.UnlockTickets.plist

Verify that they are loaded:

$ launchctl list | grep "otrs"

- 0 com.otrs.UnlockTickets
- 0 com.otrs.RebuildTicketIndex
- 0 com.otrs.PostMasterMailbox
- 0 com.otrs.PendingJobs
- 0 com.otrs.LoaderCache
- 0 com.otrs.GenericAgentDatabase
- 0 com.otrs.DeleteSessionIDs
- 0 com.otrs.DeleteCache
- 0 com.otrs.cleanup

References:

Here are some of the good articles I ran across while attempting this installation. PerlMonks in general was an excellent source of information.

http://www.perlmonks.org/index.pl?node_id=1043593
http://stackoverflow.com/questions/6383310/python-mysqldb-library-not-loaded-libmysqlclient-18-dylib
http://sergiobernardino.net/post/12885983651/errors-dbd-mysql-mac-osx
http://jonkemp.com/tips/installing-gd-graphics-library-on-mac-os-x.html
http://www.cgi101.com/book/connect/mac.html

How to Adjust Printer Default to Simplex in Mac

We recently replaced our old Konica copier with a newer model (C754). And I did not know this until we put the printer in use – it is now a federal law that printer drivers come with the default settings to print duplex. Wow. To me that’s not a particularly huge issue, but we do have clients that are required to print more simplex than duplex (lawyers, yeah?). I understand you can have print setting presets in Mac, but that’s not too useful if your users can’t be bothered to use it. Well, here is how you can change the default printer settings by modifying the .ppd file.

* Note: I’ve only done it with this particular model of printer (Konica Minolta C754), however I think for other models or brands of printers it should be pretty similar.

1. Open up Terminal and type in:

cd /etc/cups/ppd
ls -l

You should see a list of .ppd files for all the printers on your computer.

p223_1

2. Type in the following command, substitute the text editor of your liking (I prefer vi) and the last part with the name of the .ppd file you are looking to modify (in my case it’s Konica_Minolta_C754.ppd):

sudo vi /etc/cups/ppd/Konica_Minolta_C754.ppd

3. Search for the phrase “DefaultKMDuplex” (In vi, this would be typing in /DefaultKMDuplex and press enter).

p223_2

4. You’ll now see that the default is set to Double. Change that to Single.

p223_3