krypted.com

Tiny Deathstars of Foulness

Web Services in macOS Server, Linux and most versions of Unix are provided by Apache, an Open Source project that much of the Internet owes its origins to. Apache owes its name to the fact that it’s “a patchy” service. These patches are often mods, or modules. Configuring web services is as easy in macOS Server 5.4, running on High Sierra (10.13), as it has ever been.

To set up the default web portal, simply open the Server app, click on the Websites service and click on the ON button.

After a time, the service will start. Once running, click on the View Server Website link at the bottom of the pane.

Provided the stock macOS Server page loads, you are ready to use macOS Server as a web server.



Before we setup custom sites, there are a few things you should know. The first is, the server is no longer really designed to remove the default website. So if you remove the site, your server will exhibit inconsistent behavior. Also, don’t remove the files that comprise the default site. Instead just add sites, which is covered next. Webmail is gone. You don’t have to spend a ton of time looking for it as it isn’t there. Also, Mountain Lion Server added web apps, which we’ll briefly review later in this article as well, as those continue in Mavericks Server, Yosemite Server, El Capitan Server and ultimately macOS Server 5.2 for Sierra and macOS Server 5.4 for High Sierra.  Finally, enabling PHP and Python on sites is done globally, so this setting applies to all sites hosted on the server.



Now that we’ve got that out of the way, let’s add our first custom site. Do so by clicking on the plus sign. At the New Web Site pane, you’ll be prompted for a number of options. The most important is the name of the site, with other options including the following:
  • Domain Name: The name the site is accessible from. The default sites do not have this option as they are accessible from all names that resolve to the server.
  • IP Address: The IP address the site listens on. Any means the site is available from every IP address the server is configured to use. The default websites do not have this option as they are accessible from all addresses automatically
  • Port: By default, sites without SSL run on port 80 on all network interfaces, and sites with SSL run on port 443 on all network interfaces. Use the Port field to use custom ports (e.g., 8080). The default sites do not have this option as they are configured to use 80 and 443 for default and SSL-based communications respectively.
  • SSL Certificate: Loads a list of SSL certificates installed using Keychain or the SSL Certificate option in the Settings pane of the Server application
  • Store Site Files In: The directory that the files that comprise the website are stored in. These can be placed into the correct directory using file shares or copying using the Finder. Click on the drop-down menu and then select Other to browse to the directory files are stored in.
  • Who Can Access: By default Anyone (all users, including unauthenticated guests) can access the contents of sites. Clicking on Anyone and then Customize… brings up the “Restrict access to the following folders to a chosen group” screen, where you can choose web directories and then define groups of users who can access the contents.
  • Additional Domains: Click on the Edit… button to bring up a simple list of domain names the the site also responds for (e.g. in addition to krypted.com, add www.krypted.com).
  • Redirects: Click on the Edit… button to bring up a list of redirects within the site. This allows configuring redirects to other sites. For example, use /en to load english.krypted.com or /cn to load china.krypted.com).
  • Aliases: Click on the Edit… button to load a list of aliases. This allows configuring redirects to folders within the same server. For example, /en loads /Library/Server/Web/Data/Sites/Default
  • Index Files: Click on the Edit… button to bring up a list of pages that are loaded when a page isn’t directly indicated. For example, when visiting krypted.com, load the wp.php page by default.
  • Advanced Options: The remaining options are available by clicking on the “Edit Advanced Settings…” button.

The Advanced Option include the following:
  • Enable Server Side Includes: Allows administrators to configure leveraging includes in web files, so that pieces of code can be used across multiple pages in sites.
  • Allow overrides using .htaccess files: Using a .htaccess file allows administrators to define who is able to access a given directory, defining custom user names and passwords in the hidden .htaccess file. These aren’t usually required in an OS X Server web environment as local and directory-based accounts can be used for such operations. This setting enables using custom .htaccess files instead of relying on Apple’s stock web permissions.
  • Allow folder listing: Enables folder listings on directories of a site that don’t have an Index File (described in the non-Advanced settings earlier).
  • Allow CGI execution: Enables CGI scripts for the domain being configured.
  • Use custom error page: Allows administrators to define custom error pages, such as those annoying 404 error pages that load when a page can’t be found
  • Make these web apps available on this website: A somewhat advanced setting, loads items into the webapps array, which can be viewed using the following command:  sudo serveradmin settings web:definedWebApps
Once you’ve configured all the appropriate options, click on Done to save your changes. The site should then load. Sites are then listed in the list of Websites.

The Apache service is most easily managed from the Server app, but there are too many options in Apache to really be able to put into a holistic graphical interface. The easiest way to manage the Websites service in OS X Yosemite Server is using the serveradmin command. Apache administrators from other platforms will be tempted to use the apachectl command to restart the Websites service. Instead, use the serveradmin command to do so. To start the service:

sudo serveradmin start web

To stop the service(s):

sudo serveradmin stop web

And to see the status:

sudo serveradmin fullstatus web

Fullstatus returns the following information:
web:health = _empty_dictionary
web:readWriteSettingsVersion = 1
web:apacheVersion = “2.4”
web:servicePortsRestrictionInfo = _empty_array
web:startedTime = “2017-08-26 02:38:57 +0000”
web:apacheState = “RUNNING”
web:statusMessage = “”
web:ApacheMode = 2
web:servicePortsAreRestricted = “NO”
web:state = “RUNNING”
web:setStateVersion = 1

While the health option typically resembles kiosk computers in the Computer Science departments of most major universities, much of the rest of the output can be pretty helpful including the Apache version, whether the service is running, any restrictions on ports and the date/time stamp that the service was started.

To see all of the settings available to the serveradmin command, run it, followed by settings and then web, to indicate the Websites service:

sudo serveradmin settings web

The output is pretty verbose and can be considered in two sections, the first includes global settings across sites as well as the information for the default sites that should not be deleted:
web:defaultSite:documentRoot = “/Library/Server/Web/Data/Sites/Default”
web:defaultSite:serverName = “”
web:defaultSite:realms = _empty_dictionary
web:defaultSite:redirects = _empty_array
web:defaultSite:enableServerSideIncludes = no
web:defaultSite:networkAccesses = _empty_array
web:defaultSite:customLogPath = “"/var/log/apache2/access_log"”
web:defaultSite:webApps = _empty_array
web:defaultSite:sslCertificateIdentifier = “”
web:defaultSite:fullSiteRedirectToOtherSite = “https://%{SERVER_NAME}”
web:defaultSite:allowFolderListing = no
web:defaultSite:serverAliases = _empty_array
web:defaultSite:errorLogPath = “"/var/log/apache2/error_log"”
web:defaultSite:fileName = “/Library/Server/Web/Config/apache2/sites/0000_127.0.0.1_34580_.conf”
web:defaultSite:aliases = _empty_array
web:defaultSite:directoryIndexes:_array_index:0 = “index.html”
web:defaultSite:directoryIndexes:_array_index:1 = “index.php”
web:defaultSite:directoryIndexes:_array_index:2 = “default.html”
web:defaultSite:allowAllOverrides = no
web:defaultSite:identifier = “67127006”
web:defaultSite:port = 34580
web:defaultSite:allowCGIExecution = no
web:defaultSite:serverAddress = “127.0.0.1”
web:defaultSite:requiresSSL = no
web:defaultSite:proxies = _empty_dictionary
web:defaultSite:errorDocuments = _empty_dictionary
The second section is per-site settings, with an array entry for each site:
web:customSites:_array_index:0:documentRoot =
“/Library/Server/Web/Data/Sites/blog.krypted.com” web:customSites:_array_index:0:serverName = “blog.krypted.com”
web:customSites:_array_index:0:realms = _empty_dictionary
web:customSites:_array_index:0:redirects = _empty_array
web:customSites:_array_index:0:enableServerSideIncludes = no
web:customSites:_array_index:0:networkAccesses = _empty_array
web:customSites:_array_index:0:customLogPath = “/var/log/apache2/access_log”
web:customSites:_array_index:0:webApps = _empty_array
web:customSites:_array_index:0:sslCertificateIdentifier = “”
web:customSites:_array_index:0:fullSiteRedirectToOtherSite = “”
web:customSites:_array_index:0:allowFolderListing = no
web:customSites:_array_index:0:serverAliases = _empty_array
web:customSites:_array_index:0:errorLogPath = “/var/log/apache2/error_log”
web:customSites:_array_index:0:fileName = “/Library/Server/Web/Config/apache2/sites/0000_127.0.0.1_34580_blog.krypted.com.conf”
web:customSites:_array_index:0:aliases = _empty_array
web:customSites:_array_index:0:directoryIndexes:_array_index:0 = “index.html”
web:customSites:_array_index:0:directoryIndexes:_array_index:1 = “index.php”
web:customSites:_array_index:0:directoryIndexes:_array_index:2 = “default.html”
web:customSites:_array_index:0:allowAllOverrides = no
web:customSites:_array_index:0:identifier = “67127002”
web:customSites:_array_index:0:port = 34580
web:customSites:_array_index:0:allowCGIExecution = no
web:customSites:_array_index:0:serverAddress = “127.0.0.1”
web:customSites:_array_index:0:requiresSSL = no
web:customSites:_array_index:0:proxies = _empty_dictionary
web:customSites:_array_index:0:errorDocuments = _empty_dictionary
web:dataLocation = “/Library/Server/Web/Data”
The next section (the largest by far) includes array entries for each defined web app. The following shows the entry for a Hello World Python app
web:definedWebApps:_array_index:0:requiredWebAppNames = _empty_array
web:definedWebApps:_array_index:0:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_ACSServer.conf”
web:definedWebApps:_array_index:0:requiredModuleNames:_array_index:0 = “mod_rewrite.so”
web:definedWebApps:_array_index:0:startCommand = “”
web:definedWebApps:_array_index:0:sslPolicy = 1
web:definedWebApps:_array_index:0:requiresSSL = no
web:definedWebApps:_array_index:0:requiredByWebAppNames = _empty_array
web:definedWebApps:_array_index:0:launchKeys:_array_index:0 = “com.apple.AccountsConfigService”
web:definedWebApps:_array_index:0:proxies:/AccountsConfigService/api/:path = “/AccountsConfigService/api/”
web:definedWebApps:_array_index:0:proxies:/AccountsConfigService/api/:urls:_array_index:0 = “http://localhost:31415/AccountsConfigService/api”
web:definedWebApps:_array_index:0:preflightCommand = “”
web:definedWebApps:_array_index:0:stopCommand = “”
web:definedWebApps:_array_index:0:name = “com.apple.webapp.ACSServer”
web:definedWebApps:_array_index:0:displayName = “”
web:definedWebApps:_array_index:1:requiredWebAppNames:_array_index:0 = “com.apple.webapp.collabd”
web:definedWebApps:_array_index:1:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_corecollaboration_webauth.conf”
web:definedWebApps:_array_index:1:requiredModuleNames:_array_index:0 = “proxy_module”
web:definedWebApps:_array_index:1:requiredModuleNames:_array_index:1 = “headers_module”
web:definedWebApps:_array_index:1:startCommand = “”
web:definedWebApps:_array_index:1:sslPolicy = 4
web:definedWebApps:_array_index:1:requiresSSL = no
web:definedWebApps:_array_index:1:requiredByWebAppNames = _empty_array
web:definedWebApps:_array_index:1:launchKeys = _empty_array
web:definedWebApps:_array_index:1:proxies:/auth:path = “/auth”
web:definedWebApps:_array_index:1:proxies:/auth:urls:_array_index:0 = “http://localhost:4444/auth”
web:definedWebApps:_array_index:1:preflightCommand = “”
web:definedWebApps:_array_index:1:stopCommand = “”
web:definedWebApps:_array_index:1:name = “com.apple.webapp.auth”
web:definedWebApps:_array_index:1:displayName = “”
web:definedWebApps:_array_index:2:requiredWebAppNames:_array_index:0 = “com.apple.webapp.auth”
web:definedWebApps:_array_index:2:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_corecollaboration_webcalssl.conf”
web:definedWebApps:_array_index:2:requiredModuleNames:_array_index:0 = “proxy_module”
web:definedWebApps:_array_index:2:requiredModuleNames:_array_index:1 = “headers_module”
web:definedWebApps:_array_index:2:startCommand = “”
web:definedWebApps:_array_index:2:sslPolicy = 1
web:definedWebApps:_array_index:2:requiresSSL = no
web:definedWebApps:_array_index:2:requiredByWebAppNames = _empty_array
web:definedWebApps:_array_index:2:launchKeys = _empty_array
web:definedWebApps:_array_index:2:proxies = _empty_dictionary
web:definedWebApps:_array_index:2:preflightCommand = “”
web:definedWebApps:_array_index:2:stopCommand = “”
web:definedWebApps:_array_index:2:name = “com.apple.webapp.calendar”
web:definedWebApps:_array_index:2:displayName = “”
web:definedWebApps:_array_index:3:requiredWebAppNames:_array_index:0 = “com.apple.webapp.auth”
web:definedWebApps:_array_index:3:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_corecollaboration_changepassword.conf”
web:definedWebApps:_array_index:3:requiredModuleNames:_array_index:0 = “proxy_module”
web:definedWebApps:_array_index:3:requiredModuleNames:_array_index:1 = “headers_module”
web:definedWebApps:_array_index:3:startCommand = “”
web:definedWebApps:_array_index:3:sslPolicy = 4
web:definedWebApps:_array_index:3:requiresSSL = no
web:definedWebApps:_array_index:3:requiredByWebAppNames = _empty_array
web:definedWebApps:_array_index:3:launchKeys = _empty_array
web:definedWebApps:_array_index:3:proxies:/changepassword:path = “/changepassword”
web:definedWebApps:_array_index:3:proxies:/changepassword:urls:_array_index:0 = “http://localhost:4444/changepassword”
web:definedWebApps:_array_index:3:preflightCommand = “”
web:definedWebApps:_array_index:3:stopCommand = “”
web:definedWebApps:_array_index:3:name = “com.apple.webapp.changepassword”
web:definedWebApps:_array_index:3:displayName = “”
web:definedWebApps:_array_index:4:requiredWebAppNames = _empty_array
web:definedWebApps:_array_index:4:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_corecollaboration_shared.conf”
web:definedWebApps:_array_index:4:requiredModuleNames:_array_index:0 = “proxy_module”
web:definedWebApps:_array_index:4:requiredModuleNames:_array_index:1 = “xsendfile_module”
web:definedWebApps:_array_index:4:requiredModuleNames:_array_index:2 = “headers_module”
web:definedWebApps:_array_index:4:requiredModuleNames:_array_index:3 = “expires_module”
web:definedWebApps:_array_index:4:requiredModuleNames:_array_index:4 = “deflate_module”
web:definedWebApps:_array_index:4:startCommand = “”
web:definedWebApps:_array_index:4:sslPolicy = 0
web:definedWebApps:_array_index:4:requiresSSL = no
web:definedWebApps:_array_index:4:requiredByWebAppNames = _empty_array
web:definedWebApps:_array_index:4:launchKeys:_array_index:0 = “com.apple.collabd.expire”
web:definedWebApps:_array_index:4:launchKeys:_array_index:1 = “com.apple.collabd.notifications”
web:definedWebApps:_array_index:4:proxies:/collabdproxy:path = “/collabdproxy”
web:definedWebApps:_array_index:4:proxies:/collabdproxy:urls:_array_index:0 = “http://localhost:4444/svc”
web:definedWebApps:_array_index:4:proxies:/__collabd/streams/activity:path = “/__collabd/streams/activity”
web:definedWebApps:_array_index:4:proxies:/__collabd/streams/activity:urls:_array_index:0 = “http://localhost:4444/streams/activity”
web:definedWebApps:_array_index:4:preflightCommand = “”
web:definedWebApps:_array_index:4:stopCommand = “”
web:definedWebApps:_array_index:4:name = “com.apple.webapp.collabd”
web:definedWebApps:_array_index:4:displayName = “”
web:definedWebApps:_array_index:5:requiredWebAppNames:_array_index:0 = “com.apple.webapp.auth”
web:definedWebApps:_array_index:5:includeFiles = _empty_array
web:definedWebApps:_array_index:5:requiredModuleNames = _empty_array
web:definedWebApps:_array_index:5:startCommand = “”
web:definedWebApps:_array_index:5:sslPolicy = 0
web:definedWebApps:_array_index:5:requiresSSL = no
web:definedWebApps:_array_index:5:requiredByWebAppNames = _empty_array
web:definedWebApps:_array_index:5:launchKeys:_array_index:0 = “com.apple.DeviceManagement.dmrunnerd”
web:definedWebApps:_array_index:5:launchKeys:_array_index:1 = “com.apple.DeviceManagement.php-fpm”
web:definedWebApps:_array_index:5:proxies = _empty_dictionary
web:definedWebApps:_array_index:5:preflightCommand = “”
web:definedWebApps:_array_index:5:stopCommand = “”
web:definedWebApps:_array_index:5:name = “com.apple.webapp.devicemgr”
web:definedWebApps:_array_index:5:displayName = “”
web:definedWebApps:_array_index:6:requiredWebAppNames = _empty_array
web:definedWebApps:_array_index:6:includeFiles = _empty_array
web:definedWebApps:_array_index:6:requiredModuleNames:_array_index:0 = “php5_module”
web:definedWebApps:_array_index:6:startCommand = “”
web:definedWebApps:_array_index:6:sslPolicy = 0
web:definedWebApps:_array_index:6:requiresSSL = no
web:definedWebApps:_array_index:6:requiredByWebAppNames = _empty_array
web:definedWebApps:_array_index:6:launchKeys = _empty_array
web:definedWebApps:_array_index:6:proxies = _empty_dictionary
web:definedWebApps:_array_index:6:preflightCommand = “”
web:definedWebApps:_array_index:6:stopCommand = “”
web:definedWebApps:_array_index:6:name = “com.apple.webapp.php”
web:definedWebApps:_array_index:6:displayName = “”
web:definedWebApps:_array_index:7:requiredWebAppNames = _empty_array
web:definedWebApps:_array_index:7:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_webdavsharing.conf”
web:definedWebApps:_array_index:7:requiredModuleNames:_array_index:0 = “rewrite_module”
web:definedWebApps:_array_index:7:requiredModuleNames:_array_index:1 = “bonjour_module”
web:definedWebApps:_array_index:7:startCommand = “”
web:definedWebApps:_array_index:7:sslPolicy = 0
web:definedWebApps:_array_index:7:requiresSSL = no
web:definedWebApps:_array_index:7:requiredByWebAppNames = _empty_array
web:definedWebApps:_array_index:7:launchKeys = _empty_array
web:definedWebApps:_array_index:7:proxies = _empty_dictionary
web:definedWebApps:_array_index:7:preflightCommand = “”
web:definedWebApps:_array_index:7:stopCommand = “”
web:definedWebApps:_array_index:7:name = “com.apple.webapp.webdavsharing”
web:definedWebApps:_array_index:7:displayName = “”
web:definedWebApps:_array_index:8:requiredWebAppNames:_array_index:0 = “com.apple.webapp.collabd”
web:definedWebApps:_array_index:8:requiredWebAppNames:_array_index:1 = “com.apple.webapp.auth”
web:definedWebApps:_array_index:8:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_corecollaboration_wiki.conf”
web:definedWebApps:_array_index:8:requiredModuleNames:_array_index:0 = “proxy_module”
web:definedWebApps:_array_index:8:requiredModuleNames:_array_index:1 = “headers_module”
web:definedWebApps:_array_index:8:startCommand = “”
web:definedWebApps:_array_index:8:sslPolicy = 0
web:definedWebApps:_array_index:8:requiresSSL = no
web:definedWebApps:_array_index:8:requiredByWebAppNames = _empty_array
web:definedWebApps:_array_index:8:launchKeys:_array_index:0 = “com.apple.collabd.preview”
web:definedWebApps:_array_index:8:launchKeys:_array_index:1 = “com.apple.collabd.quicklook”
web:definedWebApps:_array_index:8:proxies:/__collabd/preview:path = “/__collabd/preview”
web:definedWebApps:_array_index:8:proxies:/__collabd/preview:urls:_array_index:0 = “http://localhost:4444/preview”
web:definedWebApps:_array_index:8:proxies:/wiki/files/upload:path = “/wiki/files/upload”
web:definedWebApps:_array_index:8:proxies:/wiki/files/upload:urls:_array_index:0 = “http://localhost:4444/upload_file”
web:definedWebApps:_array_index:8:proxies:/wiki/files/download:path = “/wiki/files/download”
web:definedWebApps:_array_index:8:proxies:/wiki/files/download:urls:_array_index:0 = “http://localhost:4444/files”
web:definedWebApps:_array_index:8:proxies:/wiki/ipad:path = “/wiki/ipad”
web:definedWebApps:_array_index:8:proxies:/wiki/ipad:urls = _empty_array
web:definedWebApps:_array_index:8:proxies:/wiki:path = “/wiki”
web:definedWebApps:_array_index:8:proxies:/wiki:urls:_array_index:0 = “http://localhost:4444/app-context/wiki”
web:definedWebApps:_array_index:8:preflightCommand = “”
web:definedWebApps:_array_index:8:stopCommand = “”
web:definedWebApps:_array_index:8:name = “com.apple.webapp.wiki”
web:definedWebApps:_array_index:8:displayName = “”
web:definedWebApps:_array_index:9:requiredWebAppNames = _empty_array
web:definedWebApps:_array_index:9:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_wsgi.conf”
web:definedWebApps:_array_index:9:requiredModuleNames:_array_index:0 = “wsgi_module”
web:definedWebApps:_array_index:9:startCommand = “”
web:definedWebApps:_array_index:9:sslPolicy = 0
web:definedWebApps:_array_index:9:requiresSSL = no
web:definedWebApps:_array_index:9:requiredByWebAppNames = _empty_array
web:definedWebApps:_array_index:9:launchKeys = _empty_array
web:definedWebApps:_array_index:9:proxies = _empty_dictionary
web:definedWebApps:_array_index:9:preflightCommand = “”
web:definedWebApps:_array_index:9:stopCommand = “”
web:definedWebApps:_array_index:9:name = “com.apple.webapp.wsgi”
web:definedWebApps:_array_index:9:displayName = “Python "Hello World" app at /wsgi”
web:definedWebApps:_array_index:10:requiredWebAppNames = _empty_array
web:definedWebApps:_array_index:10:includeFiles:_array_index:0 = “/Library/Developer/XcodeServer/CurrentXcodeSymlink/Contents/Developer/usr/share/xcs/httpd_xcs.conf”
web:definedWebApps:_array_index:10:requiredModuleNames = _empty_array
web:definedWebApps:_array_index:10:startCommand = “”
web:definedWebApps:_array_index:10:sslPolicy = 4
web:definedWebApps:_array_index:10:requiresSSL = no
web:definedWebApps:_array_index:10:requiredByWebAppNames = _empty_array
web:definedWebApps:_array_index:10:launchKeys = _empty_array
web:definedWebApps:_array_index:10:proxies = _empty_dictionary
web:definedWebApps:_array_index:10:preflightCommand = “”
web:definedWebApps:_array_index:10:stopCommand = “”
web:definedWebApps:_array_index:10:name = “com.apple.webapp.xcode”
web:definedWebApps:_array_index:10:displayName = “”
web:definedWebApps:_array_index:11:requiredWebAppNames:_array_index:0 = “com.example.webapp.myotherwebapp”
web:definedWebApps:_array_index:11:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_myinclude.conf”
web:definedWebApps:_array_index:11:requiredModuleNames:_array_index:0 = “mystuff_module”
web:definedWebApps:_array_index:11:startCommand = “/usr/local/bin/startmywebapp”
web:definedWebApps:_array_index:11:sslPolicy = 0
web:definedWebApps:_array_index:11:requiresSSL = no
web:definedWebApps:_array_index:11:requiredByWebAppNames = _empty_array
web:definedWebApps:_array_index:11:launchKeys:_array_index:0 = “com.example.mywebapp”
web:definedWebApps:_array_index:11:proxies:/mywebapp:path = “/mywebapp”
web:definedWebApps:_array_index:11:proxies:/mywebapp:urls:_array_index:0 = “http://localhost:3000”
web:definedWebApps:_array_index:11:proxies:/mywebapp:urls:_array_index:1 = “http://localhost:3001”
web:definedWebApps:_array_index:11:preflightCommand = “/usr/local/bin/preflightmywebapp”
web:definedWebApps:_array_index:11:stopCommand = “/usr/local/bin/stopmywebapp”
web:definedWebApps:_array_index:11:name = “com.example.mywebapp”
web:definedWebApps:_array_index:11:displayName = “MyWebApp”
The final section defines the settings used for the default sites as well as a couple of host based settings:
web:defaultSecureSite:documentRoot = “/Library/Server/Web/Data/Sites/Default”
web:defaultSecureSite:serverName = “”
web:defaultSecureSite:realms = _empty_dictionary
web:defaultSecureSite:redirects = _empty_array
web:defaultSecureSite:enableServerSideIncludes = no
web:defaultSecureSite:networkAccesses = _empty_array
web:defaultSecureSite:customLogPath = “"/var/log/apache2/access_log"”
web:defaultSecureSite:webApps = _empty_array
web:defaultSecureSite:sslCertificateIdentifier = “odr.krypted.com.32A9706448BDB45B120A91470FA866A5C61BD342”
web:defaultSecureSite:fullSiteRedirectToOtherSite = “”
web:defaultSecureSite:allowFolderListing = no
web:defaultSecureSite:serverAliases = _empty_array
web:defaultSecureSite:errorLogPath = “"/var/log/apache2/error_log"”
web:defaultSecureSite:fileName = “/Library/Server/Web/Config/apache2/sites/0000_127.0.0.1_34543_.conf”
web:defaultSecureSite:aliases = _empty_array
web:defaultSecureSite:directoryIndexes:_array_index:0 = “index.html”
web:defaultSecureSite:directoryIndexes:_array_index:1 = “index.php”
web:defaultSecureSite:directoryIndexes:_array_index:2 = “default.html”
web:defaultSecureSite:allowAllOverrides = no
web:defaultSecureSite:identifier = “67127004”
web:defaultSecureSite:port = 34543
web:defaultSecureSite:allowCGIExecution = no
web:defaultSecureSite:serverAddress = “127.0.0.1”
web:defaultSecureSite:requiresSSL = yes
web:defaultSecureSite:proxies = _empty_dictionary
web:defaultSecureSite:errorDocuments = _empty_dictionary
web:mainHost:keepAliveTimeout = 15.000000
web:mainHost:maxClients = “256”
Each site has its own configuration file defined in the array for each section. By default these are stored in the /Library/Server/Web/Config/apache2/sites directory, with /Library/Server/Web/Config/apache2/sites/0000_any_80_blog.krypted.com.conf being the file for the custom site we created previously. As you can see, many of the options available in the Server app are also available in these files:
ServerName www2.krypted.com ServerAdmin admin@example.com DocumentRoot "/Library/Server/Web/Data/Sites/blog.krypted.com" DirectoryIndex index.html index.php /wiki/ default.html CustomLog /var/log/apache2/access_log combinedvhost ErrorLog /var/log/apache2/error_log
SSLEngine Off
SSLCipherSuite “ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM”
SSLProtocol -ALL +SSLv3 +TLSv1
SSLProxyEngine On
SSLProxyProtocol -ALL +SSLv3 +TLSv1
Options All -Indexes -ExecCGI -Includes +MultiViews
AllowOverride None
DAV Off
Deny from all
ErrorDocument 403 /customerror/websitesoff403.html
The serveradmin command can also be used to run commands. For example, to reset the service to factory defaults, delete the configuration files for each site and then run the following command:

sudo serveradmin command web:command=restoreFactorySettings

The final tip I’m going to give in this article is when to make changes with each app. I strongly recommend making all of your changes in the Server app when possible. When it isn’t, use serveradmin and when you can’t make changes in serveradmin, only then alter the configuration files that come with the operating system by default. For example, in this article I look at overriding some ports for some virtual sites that might conflict with other sites on your systems. I also recommend keeping backups of all configuration files that are altered and a log of what was altered in each, in order to help piece the server back together should it become unconfigured miraculously when a softwareupdate -all is run next.

September 27th, 2017

Posted In: Mac OS X Server

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

Web Services in macOS Server, Linux and most versions of Unix are provided by Apache, an Open Source project that much of the Internet owes its origins to. Apache owes its name to the fact that it’s “a patchy” service. These patches are often mods, or modules. Configuring web services is as easy in macOS Server 5.2, running on Sierra (10.12), as it has ever been. To set up the default web portal, simply open the Server app, click on the Websites service and click on the ON button. screen-shot-2016-09-29-at-10-53-42-pm After a time, the service will start. Once running, click on the View Server Website link at the bottom of the pane. screen-shot-2016-09-29-at-10-54-07-pm Provided the stock macOS Server page loads, you are ready to use macOS Server as a web server. screen-shot-2016-09-29-at-10-54-49-pm Before we setup custom sites, there are a few things you should know. The first is, the server is no longer really designed to remove the default website. So if you remove the site, your server will exhibit inconsistent behavior. Also, don’t remove the files that comprise the default site. Instead just add sites, which is covered next. Webmail is gone. You don’t have to spend a ton of time looking for it as it isn’t there. Also, Mountain Lion Server added web apps, which we’ll briefly review later in this article as well, as those continue in Mavericks Server, Yosemite Server, El Capitan Server and ultimately macOS Server 5.2 for Sierra.  Finally, enabling PHP and Python on sites is done globally, so this setting applies to all sites hosted on the server. screen-shot-2016-09-29-at-10-56-17-pm Now that we’ve got that out of the way, let’s add our first custom site. Do so by clicking on the plus sign. At the New Web Site pane, you’ll be prompted for a number of options. The most important is the name of the site, with other options including the following:
  • Domain Name: The name the site is accessible from. The default sites do not have this option as they are accessible from all names that resolve to the server.
  • IP Address: The IP address the site listens on. Any means the site is available from every IP address the server is configured to use. The default websites do not have this option as they are accessible from all addresses automatically
  • Port: By default, sites without SSL run on port 80 on all network interfaces, and sites with SSL run on port 443 on all network interfaces. Use the Port field to use custom ports (e.g., 8080). The default sites do not have this option as they are configured to use 80 and 443 for default and SSL-based communications respectively.
  • SSL Certificate: Loads a list of SSL certificates installed using Keychain or the SSL Certificate option in the Settings pane of the Server application
  • Store Site Files In: The directory that the files that comprise the website are stored in. These can be placed into the correct directory using file shares or copying using the Finder. Click on the drop-down menu and then select Other to browse to the directory files are stored in.
  • Who Can Access: By default Anyone (all users, including unauthenticated guests) can access the contents of sites. Clicking on Anyone and then Customize… brings up the “Restrict access to the following folders to a chosen group” screen, where you can choose web directories and then define groups of users who can access the contents.
  • Additional Domains: Click on the Edit… button to bring up a simple list of domain names the the site also responds for (e.g. in addition to krypted.com, add www.krypted.com).
  • Redirects: Click on the Edit… button to bring up a list of redirects within the site. This allows configuring redirects to other sites. For example, use /en to load english.krypted.com or /cn to load china.krypted.com).
  • Aliases: Click on the Edit… button to load a list of aliases. This allows configuring redirects to folders within the same server. For example, /en loads /Library/Server/Web/Data/Sites/Default
  • Index Files: Click on the Edit… button to bring up a list of pages that are loaded when a page isn’t directly indicated. For example, when visiting krypted.com, load the wp.php page by default.
  • Advanced Options: The remaining options are available by clicking on the “Edit Advanced Settings…” button.
screen-shot-2016-09-29-at-10-56-43-pm The Advanced Option include the following:
  • Enable Server Side Includes: Allows administrators to configure leveraging includes in web files, so that pieces of code can be used across multiple pages in sites.
  • Allow overrides using .htaccess files: Using a .htaccess file allows administrators to define who is able to access a given directory, defining custom user names and passwords in the hidden .htaccess file. These aren’t usually required in an OS X Server web environment as local and directory-based accounts can be used for such operations. This setting enables using custom .htaccess files instead of relying on Apple’s stock web permissions.
  • Allow folder listing: Enables folder listings on directories of a site that don’t have an Index File (described in the non-Advanced settings earlier).
  • Allow CGI execution: Enables CGI scripts for the domain being configured.
  • Use custom error page: Allows administrators to define custom error pages, such as those annoying 404 error pages that load when a page can’t be found
  • Make these web apps available on this website: A somewhat advanced setting, loads items into the webapps array, which can be viewed using the following command:  sudo serveradmin settings web:definedWebApps
Once you’ve configured all the appropriate options, click on Done to save your changes. The site should then load. Sites are then listed in the list of Websites. The Apache service is most easily managed from the Server app, but there are too many options in Apache to really be able to put into a holistic graphical interface. The easiest way to manage the Websites service in OS X Yosemite Server is using the serveradmin command. Apache administrators from other platforms will be tempted to use the apachectl command to restart the Websites service. Instead, use the serveradmin command to do so. To start the service: sudo serveradmin start web To stop the service(s): sudo serveradmin stop web And to see the status: sudo serveradmin fullstatus web Fullstatus returns the following information:
web:health = _empty_dictionary web:readWriteSettingsVersion = 1 web:apacheVersion = “2.2” web:servicePortsRestrictionInfo = _empty_array web:startedTime = “2016-09-26 02:38:57 +0000” web:apacheState = “RUNNING” web:statusMessage = “” web:ApacheMode = 2 web:servicePortsAreRestricted = “NO” web:state = “RUNNING” web:setStateVersion = 1
While the health option typically resembles kiosk computers in the Computer Science departments of most major universities, much of the rest of the output can be pretty helpful including the Apache version, whether the service is running, any restrictions on ports and the date/time stamp that the service was started. To see all of the settings available to the serveradmin command, run it, followed by settings and then web, to indicate the Websites service: sudo serveradmin settings web The output is pretty verbose and can be considered in two sections, the first includes global settings across sites as well as the information for the default sites that should not be deleted:
web:defaultSite:documentRoot = “/Library/Server/Web/Data/Sites/Default” web:defaultSite:serverName = “” web:defaultSite:realms = _empty_dictionary web:defaultSite:redirects = _empty_array web:defaultSite:enableServerSideIncludes = no web:defaultSite:networkAccesses = _empty_array web:defaultSite:customLogPath = “"/var/log/apache2/access_log"” web:defaultSite:webApps = _empty_array web:defaultSite:sslCertificateIdentifier = “” web:defaultSite:fullSiteRedirectToOtherSite = “https://%{SERVER_NAME}” web:defaultSite:allowFolderListing = no web:defaultSite:serverAliases = _empty_array web:defaultSite:errorLogPath = “"/var/log/apache2/error_log"” web:defaultSite:fileName = “/Library/Server/Web/Config/apache2/sites/0000_127.0.0.1_34580_.conf” web:defaultSite:aliases = _empty_array web:defaultSite:directoryIndexes:_array_index:0 = “index.html” web:defaultSite:directoryIndexes:_array_index:1 = “index.php” web:defaultSite:directoryIndexes:_array_index:2 = “default.html” web:defaultSite:allowAllOverrides = no web:defaultSite:identifier = “67127006” web:defaultSite:port = 34580 web:defaultSite:allowCGIExecution = no web:defaultSite:serverAddress = “127.0.0.1” web:defaultSite:requiresSSL = no web:defaultSite:proxies = _empty_dictionary web:defaultSite:errorDocuments = _empty_dictionary
The second section is per-site settings, with an array entry for each site:
web:customSites:_array_index:0:documentRoot = “/Library/Server/Web/Data/Sites/blog.krypted.com” web:customSites:_array_index:0:serverName = “blog.krypted.com” web:customSites:_array_index:0:realms = _empty_dictionary web:customSites:_array_index:0:redirects = _empty_array web:customSites:_array_index:0:enableServerSideIncludes = no web:customSites:_array_index:0:networkAccesses = _empty_array web:customSites:_array_index:0:customLogPath = “/var/log/apache2/access_log” web:customSites:_array_index:0:webApps = _empty_array web:customSites:_array_index:0:sslCertificateIdentifier = “” web:customSites:_array_index:0:fullSiteRedirectToOtherSite = “” web:customSites:_array_index:0:allowFolderListing = no web:customSites:_array_index:0:serverAliases = _empty_array web:customSites:_array_index:0:errorLogPath = “/var/log/apache2/error_log” web:customSites:_array_index:0:fileName = “/Library/Server/Web/Config/apache2/sites/0000_127.0.0.1_34580_blog.krypted.com.conf” web:customSites:_array_index:0:aliases = _empty_array web:customSites:_array_index:0:directoryIndexes:_array_index:0 = “index.html” web:customSites:_array_index:0:directoryIndexes:_array_index:1 = “index.php” web:customSites:_array_index:0:directoryIndexes:_array_index:2 = “default.html” web:customSites:_array_index:0:allowAllOverrides = no web:customSites:_array_index:0:identifier = “67127002” web:customSites:_array_index:0:port = 34580 web:customSites:_array_index:0:allowCGIExecution = no web:customSites:_array_index:0:serverAddress = “127.0.0.1” web:customSites:_array_index:0:requiresSSL = no web:customSites:_array_index:0:proxies = _empty_dictionary web:customSites:_array_index:0:errorDocuments = _empty_dictionary web:dataLocation = “/Library/Server/Web/Data”
The next section (the largest by far) includes array entries for each defined web app. The following shows the entry for a Hello World Python app:
web:definedWebApps:_array_index:0:requiredWebAppNames = _empty_array web:definedWebApps:_array_index:0:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_ACSServer.conf” web:definedWebApps:_array_index:0:requiredModuleNames:_array_index:0 = “mod_rewrite.so” web:definedWebApps:_array_index:0:startCommand = “” web:definedWebApps:_array_index:0:sslPolicy = 1 web:definedWebApps:_array_index:0:requiresSSL = no web:definedWebApps:_array_index:0:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:0:launchKeys:_array_index:0 = “com.apple.AccountsConfigService” web:definedWebApps:_array_index:0:proxies:/AccountsConfigService/api/:path = “/AccountsConfigService/api/” web:definedWebApps:_array_index:0:proxies:/AccountsConfigService/api/:urls:_array_index:0 = “http://localhost:31415/AccountsConfigService/api” web:definedWebApps:_array_index:0:preflightCommand = “” web:definedWebApps:_array_index:0:stopCommand = “” web:definedWebApps:_array_index:0:name = “com.apple.webapp.ACSServer” web:definedWebApps:_array_index:0:displayName = “” web:definedWebApps:_array_index:1:requiredWebAppNames:_array_index:0 = “com.apple.webapp.collabd” web:definedWebApps:_array_index:1:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_corecollaboration_webauth.conf” web:definedWebApps:_array_index:1:requiredModuleNames:_array_index:0 = “proxy_module” web:definedWebApps:_array_index:1:requiredModuleNames:_array_index:1 = “headers_module” web:definedWebApps:_array_index:1:startCommand = “” web:definedWebApps:_array_index:1:sslPolicy = 4 web:definedWebApps:_array_index:1:requiresSSL = no web:definedWebApps:_array_index:1:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:1:launchKeys = _empty_array web:definedWebApps:_array_index:1:proxies:/auth:path = “/auth” web:definedWebApps:_array_index:1:proxies:/auth:urls:_array_index:0 = “http://localhost:4444/auth” web:definedWebApps:_array_index:1:preflightCommand = “” web:definedWebApps:_array_index:1:stopCommand = “” web:definedWebApps:_array_index:1:name = “com.apple.webapp.auth” web:definedWebApps:_array_index:1:displayName = “” web:definedWebApps:_array_index:2:requiredWebAppNames:_array_index:0 = “com.apple.webapp.auth” web:definedWebApps:_array_index:2:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_corecollaboration_webcalssl.conf” web:definedWebApps:_array_index:2:requiredModuleNames:_array_index:0 = “proxy_module” web:definedWebApps:_array_index:2:requiredModuleNames:_array_index:1 = “headers_module” web:definedWebApps:_array_index:2:startCommand = “” web:definedWebApps:_array_index:2:sslPolicy = 1 web:definedWebApps:_array_index:2:requiresSSL = no web:definedWebApps:_array_index:2:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:2:launchKeys = _empty_array web:definedWebApps:_array_index:2:proxies = _empty_dictionary web:definedWebApps:_array_index:2:preflightCommand = “” web:definedWebApps:_array_index:2:stopCommand = “” web:definedWebApps:_array_index:2:name = “com.apple.webapp.calendar” web:definedWebApps:_array_index:2:displayName = “” web:definedWebApps:_array_index:3:requiredWebAppNames:_array_index:0 = “com.apple.webapp.auth” web:definedWebApps:_array_index:3:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_corecollaboration_changepassword.conf” web:definedWebApps:_array_index:3:requiredModuleNames:_array_index:0 = “proxy_module” web:definedWebApps:_array_index:3:requiredModuleNames:_array_index:1 = “headers_module” web:definedWebApps:_array_index:3:startCommand = “” web:definedWebApps:_array_index:3:sslPolicy = 4 web:definedWebApps:_array_index:3:requiresSSL = no web:definedWebApps:_array_index:3:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:3:launchKeys = _empty_array web:definedWebApps:_array_index:3:proxies:/changepassword:path = “/changepassword” web:definedWebApps:_array_index:3:proxies:/changepassword:urls:_array_index:0 = “http://localhost:4444/changepassword” web:definedWebApps:_array_index:3:preflightCommand = “” web:definedWebApps:_array_index:3:stopCommand = “” web:definedWebApps:_array_index:3:name = “com.apple.webapp.changepassword” web:definedWebApps:_array_index:3:displayName = “” web:definedWebApps:_array_index:4:requiredWebAppNames = _empty_array web:definedWebApps:_array_index:4:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_corecollaboration_shared.conf” web:definedWebApps:_array_index:4:requiredModuleNames:_array_index:0 = “proxy_module” web:definedWebApps:_array_index:4:requiredModuleNames:_array_index:1 = “xsendfile_module” web:definedWebApps:_array_index:4:requiredModuleNames:_array_index:2 = “headers_module” web:definedWebApps:_array_index:4:requiredModuleNames:_array_index:3 = “expires_module” web:definedWebApps:_array_index:4:requiredModuleNames:_array_index:4 = “deflate_module” web:definedWebApps:_array_index:4:startCommand = “” web:definedWebApps:_array_index:4:sslPolicy = 0 web:definedWebApps:_array_index:4:requiresSSL = no web:definedWebApps:_array_index:4:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:4:launchKeys:_array_index:0 = “com.apple.collabd.expire” web:definedWebApps:_array_index:4:launchKeys:_array_index:1 = “com.apple.collabd.notifications” web:definedWebApps:_array_index:4:proxies:/collabdproxy:path = “/collabdproxy” web:definedWebApps:_array_index:4:proxies:/collabdproxy:urls:_array_index:0 = “http://localhost:4444/svc” web:definedWebApps:_array_index:4:proxies:/__collabd/streams/activity:path = “/__collabd/streams/activity” web:definedWebApps:_array_index:4:proxies:/__collabd/streams/activity:urls:_array_index:0 = “http://localhost:4444/streams/activity” web:definedWebApps:_array_index:4:preflightCommand = “” web:definedWebApps:_array_index:4:stopCommand = “” web:definedWebApps:_array_index:4:name = “com.apple.webapp.collabd” web:definedWebApps:_array_index:4:displayName = “” web:definedWebApps:_array_index:5:requiredWebAppNames:_array_index:0 = “com.apple.webapp.auth” web:definedWebApps:_array_index:5:includeFiles = _empty_array web:definedWebApps:_array_index:5:requiredModuleNames = _empty_array web:definedWebApps:_array_index:5:startCommand = “” web:definedWebApps:_array_index:5:sslPolicy = 0 web:definedWebApps:_array_index:5:requiresSSL = no web:definedWebApps:_array_index:5:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:5:launchKeys:_array_index:0 = “com.apple.DeviceManagement.dmrunnerd” web:definedWebApps:_array_index:5:launchKeys:_array_index:1 = “com.apple.DeviceManagement.php-fpm” web:definedWebApps:_array_index:5:proxies = _empty_dictionary web:definedWebApps:_array_index:5:preflightCommand = “” web:definedWebApps:_array_index:5:stopCommand = “” web:definedWebApps:_array_index:5:name = “com.apple.webapp.devicemgr” web:definedWebApps:_array_index:5:displayName = “” web:definedWebApps:_array_index:6:requiredWebAppNames = _empty_array web:definedWebApps:_array_index:6:includeFiles = _empty_array web:definedWebApps:_array_index:6:requiredModuleNames:_array_index:0 = “php5_module” web:definedWebApps:_array_index:6:startCommand = “” web:definedWebApps:_array_index:6:sslPolicy = 0 web:definedWebApps:_array_index:6:requiresSSL = no web:definedWebApps:_array_index:6:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:6:launchKeys = _empty_array web:definedWebApps:_array_index:6:proxies = _empty_dictionary web:definedWebApps:_array_index:6:preflightCommand = “” web:definedWebApps:_array_index:6:stopCommand = “” web:definedWebApps:_array_index:6:name = “com.apple.webapp.php” web:definedWebApps:_array_index:6:displayName = “” web:definedWebApps:_array_index:7:requiredWebAppNames = _empty_array web:definedWebApps:_array_index:7:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_webdavsharing.conf” web:definedWebApps:_array_index:7:requiredModuleNames:_array_index:0 = “rewrite_module” web:definedWebApps:_array_index:7:requiredModuleNames:_array_index:1 = “bonjour_module” web:definedWebApps:_array_index:7:startCommand = “” web:definedWebApps:_array_index:7:sslPolicy = 0 web:definedWebApps:_array_index:7:requiresSSL = no web:definedWebApps:_array_index:7:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:7:launchKeys = _empty_array web:definedWebApps:_array_index:7:proxies = _empty_dictionary web:definedWebApps:_array_index:7:preflightCommand = “” web:definedWebApps:_array_index:7:stopCommand = “” web:definedWebApps:_array_index:7:name = “com.apple.webapp.webdavsharing” web:definedWebApps:_array_index:7:displayName = “” web:definedWebApps:_array_index:8:requiredWebAppNames:_array_index:0 = “com.apple.webapp.collabd” web:definedWebApps:_array_index:8:requiredWebAppNames:_array_index:1 = “com.apple.webapp.auth” web:definedWebApps:_array_index:8:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_corecollaboration_wiki.conf” web:definedWebApps:_array_index:8:requiredModuleNames:_array_index:0 = “proxy_module” web:definedWebApps:_array_index:8:requiredModuleNames:_array_index:1 = “headers_module” web:definedWebApps:_array_index:8:startCommand = “” web:definedWebApps:_array_index:8:sslPolicy = 0 web:definedWebApps:_array_index:8:requiresSSL = no web:definedWebApps:_array_index:8:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:8:launchKeys:_array_index:0 = “com.apple.collabd.preview” web:definedWebApps:_array_index:8:launchKeys:_array_index:1 = “com.apple.collabd.quicklook” web:definedWebApps:_array_index:8:proxies:/__collabd/preview:path = “/__collabd/preview” web:definedWebApps:_array_index:8:proxies:/__collabd/preview:urls:_array_index:0 = “http://localhost:4444/preview” web:definedWebApps:_array_index:8:proxies:/wiki/files/upload:path = “/wiki/files/upload” web:definedWebApps:_array_index:8:proxies:/wiki/files/upload:urls:_array_index:0 = “http://localhost:4444/upload_file” web:definedWebApps:_array_index:8:proxies:/wiki/files/download:path = “/wiki/files/download” web:definedWebApps:_array_index:8:proxies:/wiki/files/download:urls:_array_index:0 = “http://localhost:4444/files” web:definedWebApps:_array_index:8:proxies:/wiki/ipad:path = “/wiki/ipad” web:definedWebApps:_array_index:8:proxies:/wiki/ipad:urls = _empty_array web:definedWebApps:_array_index:8:proxies:/wiki:path = “/wiki” web:definedWebApps:_array_index:8:proxies:/wiki:urls:_array_index:0 = “http://localhost:4444/app-context/wiki” web:definedWebApps:_array_index:8:preflightCommand = “” web:definedWebApps:_array_index:8:stopCommand = “” web:definedWebApps:_array_index:8:name = “com.apple.webapp.wiki” web:definedWebApps:_array_index:8:displayName = “” web:definedWebApps:_array_index:9:requiredWebAppNames = _empty_array web:definedWebApps:_array_index:9:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_wsgi.conf” web:definedWebApps:_array_index:9:requiredModuleNames:_array_index:0 = “wsgi_module” web:definedWebApps:_array_index:9:startCommand = “” web:definedWebApps:_array_index:9:sslPolicy = 0 web:definedWebApps:_array_index:9:requiresSSL = no web:definedWebApps:_array_index:9:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:9:launchKeys = _empty_array web:definedWebApps:_array_index:9:proxies = _empty_dictionary web:definedWebApps:_array_index:9:preflightCommand = “” web:definedWebApps:_array_index:9:stopCommand = “” web:definedWebApps:_array_index:9:name = “com.apple.webapp.wsgi” web:definedWebApps:_array_index:9:displayName = “Python "Hello World" app at /wsgi” web:definedWebApps:_array_index:10:requiredWebAppNames = _empty_array web:definedWebApps:_array_index:10:includeFiles:_array_index:0 = “/Library/Developer/XcodeServer/CurrentXcodeSymlink/Contents/Developer/usr/share/xcs/httpd_xcs.conf” web:definedWebApps:_array_index:10:requiredModuleNames = _empty_array web:definedWebApps:_array_index:10:startCommand = “” web:definedWebApps:_array_index:10:sslPolicy = 4 web:definedWebApps:_array_index:10:requiresSSL = no web:definedWebApps:_array_index:10:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:10:launchKeys = _empty_array web:definedWebApps:_array_index:10:proxies = _empty_dictionary web:definedWebApps:_array_index:10:preflightCommand = “” web:definedWebApps:_array_index:10:stopCommand = “” web:definedWebApps:_array_index:10:name = “com.apple.webapp.xcode” web:definedWebApps:_array_index:10:displayName = “” web:definedWebApps:_array_index:11:requiredWebAppNames:_array_index:0 = “com.example.webapp.myotherwebapp” web:definedWebApps:_array_index:11:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_myinclude.conf” web:definedWebApps:_array_index:11:requiredModuleNames:_array_index:0 = “mystuff_module” web:definedWebApps:_array_index:11:startCommand = “/usr/local/bin/startmywebapp” web:definedWebApps:_array_index:11:sslPolicy = 0 web:definedWebApps:_array_index:11:requiresSSL = no web:definedWebApps:_array_index:11:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:11:launchKeys:_array_index:0 = “com.example.mywebapp” web:definedWebApps:_array_index:11:proxies:/mywebapp:path = “/mywebapp” web:definedWebApps:_array_index:11:proxies:/mywebapp:urls:_array_index:0 = “http://localhost:3000” web:definedWebApps:_array_index:11:proxies:/mywebapp:urls:_array_index:1 = “http://localhost:3001” web:definedWebApps:_array_index:11:preflightCommand = “/usr/local/bin/preflightmywebapp” web:definedWebApps:_array_index:11:stopCommand = “/usr/local/bin/stopmywebapp” web:definedWebApps:_array_index:11:name = “com.example.mywebapp” web:definedWebApps:_array_index:11:displayName = “MyWebApp”
The final section defines the settings used for the default sites as well as a couple of host based settings:
web:defaultSecureSite:documentRoot = “/Library/Server/Web/Data/Sites/Default” web:defaultSecureSite:serverName = “” web:defaultSecureSite:realms = _empty_dictionary web:defaultSecureSite:redirects = _empty_array web:defaultSecureSite:enableServerSideIncludes = no web:defaultSecureSite:networkAccesses = _empty_array web:defaultSecureSite:customLogPath = “"/var/log/apache2/access_log"” web:defaultSecureSite:webApps = _empty_array web:defaultSecureSite:sslCertificateIdentifier = “odr.krypted.com.32A9706448BDB45B120A91470FA866A5C61BD342” web:defaultSecureSite:fullSiteRedirectToOtherSite = “” web:defaultSecureSite:allowFolderListing = no web:defaultSecureSite:serverAliases = _empty_array web:defaultSecureSite:errorLogPath = “"/var/log/apache2/error_log"” web:defaultSecureSite:fileName = “/Library/Server/Web/Config/apache2/sites/0000_127.0.0.1_34543_.conf” web:defaultSecureSite:aliases = _empty_array web:defaultSecureSite:directoryIndexes:_array_index:0 = “index.html” web:defaultSecureSite:directoryIndexes:_array_index:1 = “index.php” web:defaultSecureSite:directoryIndexes:_array_index:2 = “default.html” web:defaultSecureSite:allowAllOverrides = no web:defaultSecureSite:identifier = “67127004” web:defaultSecureSite:port = 34543 web:defaultSecureSite:allowCGIExecution = no web:defaultSecureSite:serverAddress = “127.0.0.1” web:defaultSecureSite:requiresSSL = yes web:defaultSecureSite:proxies = _empty_dictionary web:defaultSecureSite:errorDocuments = _empty_dictionary web:mainHost:keepAliveTimeout = 15.000000 web:mainHost:maxClients = “256”
Each site has its own configuration file defined in the array for each section. By default these are stored in the /Library/Server/Web/Config/apache2/sites directory, with /Library/Server/Web/Config/apache2/sites/0000_any_80_blog.krypted.com.conf being the file for the custom site we created previously. As you can see, many of the options available in the Server app are also available in these files:
ServerName www2.krypted.com
ServerAdmin admin@example.com
DocumentRoot "/Library/Server/Web/Data/Sites/blog.krypted.com"
DirectoryIndex index.html index.php /wiki/ default.html
CustomLog /var/log/apache2/access_log combinedvhost
ErrorLog /var/log/apache2/error_log SSLEngine Off SSLCipherSuite “ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM” SSLProtocol -ALL +SSLv3 +TLSv1 SSLProxyEngine On SSLProxyProtocol -ALL +SSLv3 +TLSv1 Options All -Indexes -ExecCGI -Includes +MultiViews AllowOverride None DAV Off Deny from all ErrorDocument 403 /customerror/websitesoff403.html
The serveradmin command can also be used to run commands. For example, to reset the service to factory defaults, delete the configuration files for each site and then run the following command: sudo serveradmin command web:command=restoreFactorySettings The final tip I’m going to give in this article is when to make changes with each app. I strongly recommend making all of your changes in the Server app when possible. When it isn’t, use serveradmin and when you can’t make changes in serveradmin, only then alter the configuration files that come with the operating system by default. For example, in this article I look at overriding some ports for some virtual sites that might conflict with other sites on your systems. I also recommend keeping backups of all configuration files that are altered and a log of what was altered in each, in order to help piece the server back together should it become unconfigured miraculously when a softwareupdate -all is run next.

October 18th, 2016

Posted In: Mac OS X Server

Tags: , , , , ,

The serveradmin command can also be used to run commands. For example, to reset the service to factory defaults, backup then delete the configuration files for each site and then run the following command: sudo serveradmin command web:command=restoreFactorySettings This is pretty timely as I’ve seen a very high rate of pretty messed up configurations from the Server 4 to Server 5 upgrades. Basically, what seems to happen is that older servers, that were running let’s say Server 2 and Server 3 and Server 4 and now Server 5 will have a little cruft. Sites with older configurations that are incompatible with the latest proxy-based config. And finding the specific problem vs the time it takes to just reset and rebuild any specific settings is rarely worth it. So, there ya’ go. If you get errors like “Websites are turned off. An administrator can turn them on using the Server application.”  when you try to view any page other than the index.html page of a custom site, then you can probably just trash the config and go from there. Enjoy.

May 7th, 2016

Posted In: Mac OS X Server

Tags: , , , , ,

OS X has a built-in web server called Apache. It’s been there for a long, long time. Once upon a time, you could enable web sharing using System Preferences. This is no longer a feature in the Sharing System Preference pane, but you can actually enable it quicker than you could before. To do so, we’ll use apachectl: /usr/sbin/apachectl start To then stop the web server: /usr/sbin/apachectl stop To see the apache status: /usr/sbin/apachectl status Or: /usr/sbin/apachectl fullstatus The default site is stored in /Library/WebServer/Documents. You can then edit this there, or replace the index.html.en file with a file/hierarchy that you wish to have. Screen Shot 2015-12-08 at 10.12.25 AM Enjoy.

December 22nd, 2015

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

Tags: , , , , ,

Web Services in Mac OS X, Mac OS X Server, Linux and most versions of Unix are provided by Apache, an Open Source project that much of the Internet owes its origins to. Apache owes its name to the fact that it’s “a patchy” service. These patches are often mods, or modules. Configuring web services is as easy in OS X Server, running on Yosemite and El Capitan, as it has ever been. To set up the default web portal, simply open the Server app, click on the Websites service and click on the ON button. Screen Shot 2015-09-25 at 9.31.32 PM After a time, the service will start. Once running, click on the View Server Website link at the bottom of the pane. Screen Shot 2015-09-25 at 9.32.00 PM Provided the stock OS X Server page loads, you are ready to use OS X Server as a web server. Screen Shot 2015-09-25 at 9.32.27 PM Before we setup custom sites, there are a few things you should know. The first is, the server is no longer really designed to remove the default website. So if you remove the site, your server will exhibit inconsistent behavior. Also, don’t remove the files that comprise the default site. Instead just add sites, which is covered next. Webmail is gone. You don’t have to spend a ton of time looking for it as it isn’t there. Also, Mountain Lion Server added web apps, which we’ll briefly review later in this article as well, as those continue in Mavericks Server, Yosemite Server, and ultimately in OS X Server 5 for El Capitan.  Finally, enabling PHP and Python on sites is done globally, so this setting applies to all sites hosted on the server. Screen Shot 2015-09-25 at 9.38.10 PM Now that we’ve got that out of the way, let’s add our first custom site. Do so by clicking on the plus sign. At the New Web Site pane, you’ll be prompted for a number of options. The most important is the name of the site, with other options including the following:
  • Domain Name: The name the site is accessible from. The default sites do not have this option as they are accessible from all names that resolve to the server.
  • IP Address: The IP address the site listens on. Any means the site is available from every IP address the server is configured to use. The default websites do not have this option as they are accessible from all addresses automatically
  • Port: By default, sites without SSL run on port 80 on all network interfaces, and sites with SSL run on port 443 on all network interfaces. Use the Port field to use custom ports (e.g., 8080). The default sites do not have this option as they are configured to use 80 and 443 for default and SSL-based communications respectively.
  • SSL Certificate: Loads a list of SSL certificates installed using Keychain or the SSL Certificate option in the Settings pane of the Server application
  • Store Site Files In: The directory that the files that comprise the website are stored in. These can be placed into the correct directory using file shares or copying using the Finder. Click on the drop-down menu and then select Other to browse to the directory files are stored in.
  • Who Can Access: By default Anyone (all users, including unauthenticated guests) can access the contents of sites. Clicking on Anyone and then Customize… brings up the “Restrict access to the following folders to a chosen group” screen, where you can choose web directories and then define groups of users who can access the contents.
  • Additional Domains: Click on the Edit… button to bring up a simple list of domain names the the site also responds for (e.g. in addition to krypted.com, add www.krypted.com).
  • Redirects: Click on the Edit… button to bring up a list of redirects within the site. This allows configuring redirects to other sites. For example, use /en to load english.krypted.com or /cn to load china.krypted.com).
  • Aliases: Click on the Edit… button to load a list of aliases. This allows configuring redirects to folders within the same server. For example, /en loads /Library/Server/Web/Data/Sites/Default
  • Index Files: Click on the Edit… button to bring up a list of pages that are loaded when a page isn’t directly indicated. For example, when visiting krypted.com, load the wp.php page by default.
  • Advanced Options: The remaining options are available by clicking on the “Edit Advanced Settings…” button.
Screen Shot 2015-09-25 at 9.38.35 PM The Advanced Option include the following:
  • Enable Server Side Includes: Allows administrators to configure leveraging includes in web files, so that pieces of code can be used across multiple pages in sites.
  • Allow overrides using .htaccess files: Using a .htaccess file allows administrators to define who is able to access a given directory, defining custom user names and passwords in the hidden .htaccess file. These aren’t usually required in an OS X Server web environment as local and directory-based accounts can be used for such operations. This setting enables using custom .htaccess files instead of relying on Apple’s stock web permissions.
  • Allow folder listing: Enables folder listings on directories of a site that don’t have an Index File (described in the non-Advanced settings earlier).
  • Allow CGI execution: Enables CGI scripts for the domain being configured.
  • Use custom error page: Allows administrators to define custom error pages, such as those annoying 404 error pages that load when a page can’t be found
  • Make these web apps available on this website: A somewhat advanced setting, loads items into the webapps array, which can be viewed using the following command:  sudo serveradmin settings web:definedWebApps
Once you’ve configured all the appropriate options, click on Done to save your changes. The site should then load. Sites are then listed in the list of Websites. The Apache service is most easily managed from the Server app, but there are too many options in Apache to really be able to put into a holistic graphical interface. The easiest way to manage the Websites service in OS X Yosemite Server is using the serveradmin command. Apache administrators from other platforms will be tempted to use the apachectl command to restart the Websites service. Instead, use the serveradmin command to do so. To start the service: sudo serveradmin start web To stop the service(s): sudo serveradmin stop web And to see the status: sudo serveradmin fullstatus web Fullstatus returns the following information:
web:health = _empty_dictionary web:readWriteSettingsVersion = 1 web:apacheVersion = “2.2” web:servicePortsRestrictionInfo = _empty_array web:startedTime = “2015-09-26 02:38:57 +0000” web:apacheState = “RUNNING” web:statusMessage = “” web:ApacheMode = 2 web:servicePortsAreRestricted = “NO” web:state = “RUNNING” web:setStateVersion = 1
While the health option typically resembles kiosk computers in the Computer Science departments of most major universities, much of the rest of the output can be pretty helpful including the Apache version, whether the service is running, any restrictions on ports and the date/time stamp that the service was started. To see all of the settings available to the serveradmin command, run it, followed by settings and then web, to indicate the Websites service: sudo serveradmin settings web The output is pretty verbose and can be considered in two sections, the first includes global settings across sites as well as the information for the default sites that should not be deleted:
web:defaultSite:documentRoot = “/Library/Server/Web/Data/Sites/Default” web:defaultSite:serverName = “” web:defaultSite:realms = _empty_dictionary web:defaultSite:redirects = _empty_array web:defaultSite:enableServerSideIncludes = no web:defaultSite:networkAccesses = _empty_array web:defaultSite:customLogPath = “"/var/log/apache2/access_log"” web:defaultSite:webApps = _empty_array web:defaultSite:sslCertificateIdentifier = “” web:defaultSite:fullSiteRedirectToOtherSite = “https://%{SERVER_NAME}” web:defaultSite:allowFolderListing = no web:defaultSite:serverAliases = _empty_array web:defaultSite:errorLogPath = “"/var/log/apache2/error_log"” web:defaultSite:fileName = “/Library/Server/Web/Config/apache2/sites/0000_127.0.0.1_34580_.conf” web:defaultSite:aliases = _empty_array web:defaultSite:directoryIndexes:_array_index:0 = “index.html” web:defaultSite:directoryIndexes:_array_index:1 = “index.php” web:defaultSite:directoryIndexes:_array_index:2 = “default.html” web:defaultSite:allowAllOverrides = no web:defaultSite:identifier = “67127006” web:defaultSite:port = 34580 web:defaultSite:allowCGIExecution = no web:defaultSite:serverAddress = “127.0.0.1” web:defaultSite:requiresSSL = no web:defaultSite:proxies = _empty_dictionary web:defaultSite:errorDocuments = _empty_dictionary
The second section is per-site settings, with an array entry for each site:
web:customSites:_array_index:0:documentRoot = “/Library/Server/Web/Data/Sites/blog.krypted.com” web:customSites:_array_index:0:serverName = “blog.krypted.com” web:customSites:_array_index:0:realms = _empty_dictionary web:customSites:_array_index:0:redirects = _empty_array web:customSites:_array_index:0:enableServerSideIncludes = no web:customSites:_array_index:0:networkAccesses = _empty_array web:customSites:_array_index:0:customLogPath = “/var/log/apache2/access_log” web:customSites:_array_index:0:webApps = _empty_array web:customSites:_array_index:0:sslCertificateIdentifier = “” web:customSites:_array_index:0:fullSiteRedirectToOtherSite = “” web:customSites:_array_index:0:allowFolderListing = no web:customSites:_array_index:0:serverAliases = _empty_array web:customSites:_array_index:0:errorLogPath = “/var/log/apache2/error_log” web:customSites:_array_index:0:fileName = “/Library/Server/Web/Config/apache2/sites/0000_127.0.0.1_34580_blog.krypted.com.conf” web:customSites:_array_index:0:aliases = _empty_array web:customSites:_array_index:0:directoryIndexes:_array_index:0 = “index.html” web:customSites:_array_index:0:directoryIndexes:_array_index:1 = “index.php” web:customSites:_array_index:0:directoryIndexes:_array_index:2 = “default.html” web:customSites:_array_index:0:allowAllOverrides = no web:customSites:_array_index:0:identifier = “67127002” web:customSites:_array_index:0:port = 34580 web:customSites:_array_index:0:allowCGIExecution = no web:customSites:_array_index:0:serverAddress = “127.0.0.1” web:customSites:_array_index:0:requiresSSL = no web:customSites:_array_index:0:proxies = _empty_dictionary web:customSites:_array_index:0:errorDocuments = _empty_dictionary web:dataLocation = “/Library/Server/Web/Data”
The next section (the largest by far) includes array entries for each defined web app. The following shows the entry for a Hello World Python app:
web:definedWebApps:_array_index:0:requiredWebAppNames = _empty_array web:definedWebApps:_array_index:0:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_ACSServer.conf” web:definedWebApps:_array_index:0:requiredModuleNames:_array_index:0 = “mod_rewrite.so” web:definedWebApps:_array_index:0:startCommand = “” web:definedWebApps:_array_index:0:sslPolicy = 1 web:definedWebApps:_array_index:0:requiresSSL = no web:definedWebApps:_array_index:0:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:0:launchKeys:_array_index:0 = “com.apple.AccountsConfigService” web:definedWebApps:_array_index:0:proxies:/AccountsConfigService/api/:path = “/AccountsConfigService/api/” web:definedWebApps:_array_index:0:proxies:/AccountsConfigService/api/:urls:_array_index:0 = “http://localhost:31415/AccountsConfigService/api” web:definedWebApps:_array_index:0:preflightCommand = “” web:definedWebApps:_array_index:0:stopCommand = “” web:definedWebApps:_array_index:0:name = “com.apple.webapp.ACSServer” web:definedWebApps:_array_index:0:displayName = “” web:definedWebApps:_array_index:1:requiredWebAppNames:_array_index:0 = “com.apple.webapp.collabd” web:definedWebApps:_array_index:1:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_corecollaboration_webauth.conf” web:definedWebApps:_array_index:1:requiredModuleNames:_array_index:0 = “proxy_module” web:definedWebApps:_array_index:1:requiredModuleNames:_array_index:1 = “headers_module” web:definedWebApps:_array_index:1:startCommand = “” web:definedWebApps:_array_index:1:sslPolicy = 4 web:definedWebApps:_array_index:1:requiresSSL = no web:definedWebApps:_array_index:1:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:1:launchKeys = _empty_array web:definedWebApps:_array_index:1:proxies:/auth:path = “/auth” web:definedWebApps:_array_index:1:proxies:/auth:urls:_array_index:0 = “http://localhost:4444/auth” web:definedWebApps:_array_index:1:preflightCommand = “” web:definedWebApps:_array_index:1:stopCommand = “” web:definedWebApps:_array_index:1:name = “com.apple.webapp.auth” web:definedWebApps:_array_index:1:displayName = “” web:definedWebApps:_array_index:2:requiredWebAppNames:_array_index:0 = “com.apple.webapp.auth” web:definedWebApps:_array_index:2:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_corecollaboration_webcalssl.conf” web:definedWebApps:_array_index:2:requiredModuleNames:_array_index:0 = “proxy_module” web:definedWebApps:_array_index:2:requiredModuleNames:_array_index:1 = “headers_module” web:definedWebApps:_array_index:2:startCommand = “” web:definedWebApps:_array_index:2:sslPolicy = 1 web:definedWebApps:_array_index:2:requiresSSL = no web:definedWebApps:_array_index:2:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:2:launchKeys = _empty_array web:definedWebApps:_array_index:2:proxies = _empty_dictionary web:definedWebApps:_array_index:2:preflightCommand = “” web:definedWebApps:_array_index:2:stopCommand = “” web:definedWebApps:_array_index:2:name = “com.apple.webapp.calendar” web:definedWebApps:_array_index:2:displayName = “” web:definedWebApps:_array_index:3:requiredWebAppNames:_array_index:0 = “com.apple.webapp.auth” web:definedWebApps:_array_index:3:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_corecollaboration_changepassword.conf” web:definedWebApps:_array_index:3:requiredModuleNames:_array_index:0 = “proxy_module” web:definedWebApps:_array_index:3:requiredModuleNames:_array_index:1 = “headers_module” web:definedWebApps:_array_index:3:startCommand = “” web:definedWebApps:_array_index:3:sslPolicy = 4 web:definedWebApps:_array_index:3:requiresSSL = no web:definedWebApps:_array_index:3:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:3:launchKeys = _empty_array web:definedWebApps:_array_index:3:proxies:/changepassword:path = “/changepassword” web:definedWebApps:_array_index:3:proxies:/changepassword:urls:_array_index:0 = “http://localhost:4444/changepassword” web:definedWebApps:_array_index:3:preflightCommand = “” web:definedWebApps:_array_index:3:stopCommand = “” web:definedWebApps:_array_index:3:name = “com.apple.webapp.changepassword” web:definedWebApps:_array_index:3:displayName = “” web:definedWebApps:_array_index:4:requiredWebAppNames = _empty_array web:definedWebApps:_array_index:4:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_corecollaboration_shared.conf” web:definedWebApps:_array_index:4:requiredModuleNames:_array_index:0 = “proxy_module” web:definedWebApps:_array_index:4:requiredModuleNames:_array_index:1 = “xsendfile_module” web:definedWebApps:_array_index:4:requiredModuleNames:_array_index:2 = “headers_module” web:definedWebApps:_array_index:4:requiredModuleNames:_array_index:3 = “expires_module” web:definedWebApps:_array_index:4:requiredModuleNames:_array_index:4 = “deflate_module” web:definedWebApps:_array_index:4:startCommand = “” web:definedWebApps:_array_index:4:sslPolicy = 0 web:definedWebApps:_array_index:4:requiresSSL = no web:definedWebApps:_array_index:4:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:4:launchKeys:_array_index:0 = “com.apple.collabd.expire” web:definedWebApps:_array_index:4:launchKeys:_array_index:1 = “com.apple.collabd.notifications” web:definedWebApps:_array_index:4:proxies:/collabdproxy:path = “/collabdproxy” web:definedWebApps:_array_index:4:proxies:/collabdproxy:urls:_array_index:0 = “http://localhost:4444/svc” web:definedWebApps:_array_index:4:proxies:/__collabd/streams/activity:path = “/__collabd/streams/activity” web:definedWebApps:_array_index:4:proxies:/__collabd/streams/activity:urls:_array_index:0 = “http://localhost:4444/streams/activity” web:definedWebApps:_array_index:4:preflightCommand = “” web:definedWebApps:_array_index:4:stopCommand = “” web:definedWebApps:_array_index:4:name = “com.apple.webapp.collabd” web:definedWebApps:_array_index:4:displayName = “” web:definedWebApps:_array_index:5:requiredWebAppNames:_array_index:0 = “com.apple.webapp.auth” web:definedWebApps:_array_index:5:includeFiles = _empty_array web:definedWebApps:_array_index:5:requiredModuleNames = _empty_array web:definedWebApps:_array_index:5:startCommand = “” web:definedWebApps:_array_index:5:sslPolicy = 0 web:definedWebApps:_array_index:5:requiresSSL = no web:definedWebApps:_array_index:5:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:5:launchKeys:_array_index:0 = “com.apple.DeviceManagement.dmrunnerd” web:definedWebApps:_array_index:5:launchKeys:_array_index:1 = “com.apple.DeviceManagement.php-fpm” web:definedWebApps:_array_index:5:proxies = _empty_dictionary web:definedWebApps:_array_index:5:preflightCommand = “” web:definedWebApps:_array_index:5:stopCommand = “” web:definedWebApps:_array_index:5:name = “com.apple.webapp.devicemgr” web:definedWebApps:_array_index:5:displayName = “” web:definedWebApps:_array_index:6:requiredWebAppNames = _empty_array web:definedWebApps:_array_index:6:includeFiles = _empty_array web:definedWebApps:_array_index:6:requiredModuleNames:_array_index:0 = “php5_module” web:definedWebApps:_array_index:6:startCommand = “” web:definedWebApps:_array_index:6:sslPolicy = 0 web:definedWebApps:_array_index:6:requiresSSL = no web:definedWebApps:_array_index:6:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:6:launchKeys = _empty_array web:definedWebApps:_array_index:6:proxies = _empty_dictionary web:definedWebApps:_array_index:6:preflightCommand = “” web:definedWebApps:_array_index:6:stopCommand = “” web:definedWebApps:_array_index:6:name = “com.apple.webapp.php” web:definedWebApps:_array_index:6:displayName = “” web:definedWebApps:_array_index:7:requiredWebAppNames = _empty_array web:definedWebApps:_array_index:7:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_webdavsharing.conf” web:definedWebApps:_array_index:7:requiredModuleNames:_array_index:0 = “rewrite_module” web:definedWebApps:_array_index:7:requiredModuleNames:_array_index:1 = “bonjour_module” web:definedWebApps:_array_index:7:startCommand = “” web:definedWebApps:_array_index:7:sslPolicy = 0 web:definedWebApps:_array_index:7:requiresSSL = no web:definedWebApps:_array_index:7:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:7:launchKeys = _empty_array web:definedWebApps:_array_index:7:proxies = _empty_dictionary web:definedWebApps:_array_index:7:preflightCommand = “” web:definedWebApps:_array_index:7:stopCommand = “” web:definedWebApps:_array_index:7:name = “com.apple.webapp.webdavsharing” web:definedWebApps:_array_index:7:displayName = “” web:definedWebApps:_array_index:8:requiredWebAppNames:_array_index:0 = “com.apple.webapp.collabd” web:definedWebApps:_array_index:8:requiredWebAppNames:_array_index:1 = “com.apple.webapp.auth” web:definedWebApps:_array_index:8:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_corecollaboration_wiki.conf” web:definedWebApps:_array_index:8:requiredModuleNames:_array_index:0 = “proxy_module” web:definedWebApps:_array_index:8:requiredModuleNames:_array_index:1 = “headers_module” web:definedWebApps:_array_index:8:startCommand = “” web:definedWebApps:_array_index:8:sslPolicy = 0 web:definedWebApps:_array_index:8:requiresSSL = no web:definedWebApps:_array_index:8:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:8:launchKeys:_array_index:0 = “com.apple.collabd.preview” web:definedWebApps:_array_index:8:launchKeys:_array_index:1 = “com.apple.collabd.quicklook” web:definedWebApps:_array_index:8:proxies:/__collabd/preview:path = “/__collabd/preview” web:definedWebApps:_array_index:8:proxies:/__collabd/preview:urls:_array_index:0 = “http://localhost:4444/preview” web:definedWebApps:_array_index:8:proxies:/wiki/files/upload:path = “/wiki/files/upload” web:definedWebApps:_array_index:8:proxies:/wiki/files/upload:urls:_array_index:0 = “http://localhost:4444/upload_file” web:definedWebApps:_array_index:8:proxies:/wiki/files/download:path = “/wiki/files/download” web:definedWebApps:_array_index:8:proxies:/wiki/files/download:urls:_array_index:0 = “http://localhost:4444/files” web:definedWebApps:_array_index:8:proxies:/wiki/ipad:path = “/wiki/ipad” web:definedWebApps:_array_index:8:proxies:/wiki/ipad:urls = _empty_array web:definedWebApps:_array_index:8:proxies:/wiki:path = “/wiki” web:definedWebApps:_array_index:8:proxies:/wiki:urls:_array_index:0 = “http://localhost:4444/app-context/wiki” web:definedWebApps:_array_index:8:preflightCommand = “” web:definedWebApps:_array_index:8:stopCommand = “” web:definedWebApps:_array_index:8:name = “com.apple.webapp.wiki” web:definedWebApps:_array_index:8:displayName = “” web:definedWebApps:_array_index:9:requiredWebAppNames = _empty_array web:definedWebApps:_array_index:9:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_wsgi.conf” web:definedWebApps:_array_index:9:requiredModuleNames:_array_index:0 = “wsgi_module” web:definedWebApps:_array_index:9:startCommand = “” web:definedWebApps:_array_index:9:sslPolicy = 0 web:definedWebApps:_array_index:9:requiresSSL = no web:definedWebApps:_array_index:9:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:9:launchKeys = _empty_array web:definedWebApps:_array_index:9:proxies = _empty_dictionary web:definedWebApps:_array_index:9:preflightCommand = “” web:definedWebApps:_array_index:9:stopCommand = “” web:definedWebApps:_array_index:9:name = “com.apple.webapp.wsgi” web:definedWebApps:_array_index:9:displayName = “Python "Hello World" app at /wsgi” web:definedWebApps:_array_index:10:requiredWebAppNames = _empty_array web:definedWebApps:_array_index:10:includeFiles:_array_index:0 = “/Library/Developer/XcodeServer/CurrentXcodeSymlink/Contents/Developer/usr/share/xcs/httpd_xcs.conf” web:definedWebApps:_array_index:10:requiredModuleNames = _empty_array web:definedWebApps:_array_index:10:startCommand = “” web:definedWebApps:_array_index:10:sslPolicy = 4 web:definedWebApps:_array_index:10:requiresSSL = no web:definedWebApps:_array_index:10:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:10:launchKeys = _empty_array web:definedWebApps:_array_index:10:proxies = _empty_dictionary web:definedWebApps:_array_index:10:preflightCommand = “” web:definedWebApps:_array_index:10:stopCommand = “” web:definedWebApps:_array_index:10:name = “com.apple.webapp.xcode” web:definedWebApps:_array_index:10:displayName = “” web:definedWebApps:_array_index:11:requiredWebAppNames:_array_index:0 = “com.example.webapp.myotherwebapp” web:definedWebApps:_array_index:11:includeFiles:_array_index:0 = “/Library/Server/Web/Config/apache2/httpd_myinclude.conf” web:definedWebApps:_array_index:11:requiredModuleNames:_array_index:0 = “mystuff_module” web:definedWebApps:_array_index:11:startCommand = “/usr/local/bin/startmywebapp” web:definedWebApps:_array_index:11:sslPolicy = 0 web:definedWebApps:_array_index:11:requiresSSL = no web:definedWebApps:_array_index:11:requiredByWebAppNames = _empty_array web:definedWebApps:_array_index:11:launchKeys:_array_index:0 = “com.example.mywebapp” web:definedWebApps:_array_index:11:proxies:/mywebapp:path = “/mywebapp” web:definedWebApps:_array_index:11:proxies:/mywebapp:urls:_array_index:0 = “http://localhost:3000” web:definedWebApps:_array_index:11:proxies:/mywebapp:urls:_array_index:1 = “http://localhost:3001” web:definedWebApps:_array_index:11:preflightCommand = “/usr/local/bin/preflightmywebapp” web:definedWebApps:_array_index:11:stopCommand = “/usr/local/bin/stopmywebapp” web:definedWebApps:_array_index:11:name = “com.example.mywebapp” web:definedWebApps:_array_index:11:displayName = “MyWebApp”
The final section defines the settings used for the default sites as well as a couple of host based settings:
web:defaultSecureSite:documentRoot = “/Library/Server/Web/Data/Sites/Default” web:defaultSecureSite:serverName = “” web:defaultSecureSite:realms = _empty_dictionary web:defaultSecureSite:redirects = _empty_array web:defaultSecureSite:enableServerSideIncludes = no web:defaultSecureSite:networkAccesses = _empty_array web:defaultSecureSite:customLogPath = “"/var/log/apache2/access_log"” web:defaultSecureSite:webApps = _empty_array web:defaultSecureSite:sslCertificateIdentifier = “odr.krypted.com.32A9706448BDB45B120A91470FA866A5C61BD342” web:defaultSecureSite:fullSiteRedirectToOtherSite = “” web:defaultSecureSite:allowFolderListing = no web:defaultSecureSite:serverAliases = _empty_array web:defaultSecureSite:errorLogPath = “"/var/log/apache2/error_log"” web:defaultSecureSite:fileName = “/Library/Server/Web/Config/apache2/sites/0000_127.0.0.1_34543_.conf” web:defaultSecureSite:aliases = _empty_array web:defaultSecureSite:directoryIndexes:_array_index:0 = “index.html” web:defaultSecureSite:directoryIndexes:_array_index:1 = “index.php” web:defaultSecureSite:directoryIndexes:_array_index:2 = “default.html” web:defaultSecureSite:allowAllOverrides = no web:defaultSecureSite:identifier = “67127004” web:defaultSecureSite:port = 34543 web:defaultSecureSite:allowCGIExecution = no web:defaultSecureSite:serverAddress = “127.0.0.1” web:defaultSecureSite:requiresSSL = yes web:defaultSecureSite:proxies = _empty_dictionary web:defaultSecureSite:errorDocuments = _empty_dictionary web:mainHost:keepAliveTimeout = 15.000000 web:mainHost:maxClients = “256”
Each site has its own configuration file defined in the array for each section. By default these are stored in the /Library/Server/Web/Config/apache2/sites directory, with /Library/Server/Web/Config/apache2/sites/0000_any_80_blog.krypted.com.conf being the file for the custom site we created previously. As you can see, many of the options available in the Server app are also available in these files:
ServerName www2.krypted.com
ServerAdmin admin@example.com
DocumentRoot "/Library/Server/Web/Data/Sites/blog.krypted.com"
DirectoryIndex index.html index.php /wiki/ default.html
CustomLog /var/log/apache2/access_log combinedvhost
ErrorLog /var/log/apache2/error_log SSLEngine Off SSLCipherSuite “ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM” SSLProtocol -ALL +SSLv3 +TLSv1 SSLProxyEngine On SSLProxyProtocol -ALL +SSLv3 +TLSv1 Options All -Indexes -ExecCGI -Includes +MultiViews AllowOverride None DAV Off Deny from all ErrorDocument 403 /customerror/websitesoff403.html
The serveradmin command can also be used to run commands. For example, to reset the service to factory defaults, delete the configuration files for each site and then run the following command: sudo serveradmin command web:command=restoreFactorySettings The final tip I’m going to give in this article is when to make changes with each app. I strongly recommend making all of your changes in the Server app when possible. When it isn’t, use serveradmin and when you can’t make changes in serveradmin, only then alter the configuration files that come with the operating system by default. For example, in this article I look at overriding some ports for some virtual sites that might conflict with other sites on your systems. I also recommend keeping backups of all configuration files that are altered and a log of what was altered in each, in order to help piece the server back together should it become unconfigured miraculously when a softwareupdate -all is run next.

October 10th, 2015

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

Tags: , , , , , , ,

OS X Server 5 dropped last week. It’s the first time I’ve seen an OS X Server version drop before an OS release. I’m guessing there was an impetus to get it out the door before OS X 10.11 ships, so that caching and software update servers can facilitate quicker adoption and tools like Profile Manager will work on 0-day. But, there are some funny issues that are popping up. One of these is OS X Server usurping some ports that would otherwise potentially be used by other tools. Notably for Casper administrators, this includes port 8443. So here are some issues I’ve seen with Apache in the latest OS X Server. Ports are in use that shouldn’t be This is of particular interest to people running Tomcat sites (e.g. Casper admins). If you have a 3rd party service that isn’t loading, you may find that a port is already in use. For example, let’s say that you’re trying to start a JSS on port 8443. Well, let’s say you run stroke and you see this (when the JSS is stopped): /System/Library/CoreServices/Applications/Network\ Utility.app/Contents/Resources/stroke 127.0.0.1 8443 8443 And let’s say you get this response (again, with the JSS stopped): Open TCP Port:      8443      pcsync-https Well, that means that the server has probably just totally ganked port 8443 for that funky new proxy thing. In /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf there are a few new funny things due to proxy services (that whole proxy folder is new btw). One of which is the fact that the server listens on some ports you might not mean for it to listen on, by default including 80, 443, 8008, 8800, 8443, and 8843. The server always had a default site listening on ports 80 and 443, but now Caldav response is using 8443 for a Virtual Host for the CalendarServer that redirects to /webcal on port 443. Arg. There are a few things you can do to correct this. One would be to comment out one of the lines for the listeners. For this, find the line that reads:
listen 8443
And replace it with:
#listen 8443
This would likely spawn some errors in your apache logs when the virtual hosts that also use 8443 try and load. So you’ll likely also want to comment out the virtual host section of the file. For this, look for <VirtualHost *:8443> to that virtual hosts </VirtualHost> and comment out the whole section. Another option, if you do actually want to use the server as a calendar server as well, might be to replace the asterisk in the definition with an IP address or hostname, which would bind that port to a specific IP address or hostname. This would be true if you have something using 8008, 8800 (think Kerio), etc. Also, consider that there’s a /Library/Server/Web/Config/Proxy/apache_serviceproxy_customsites*.conf entry. For 5.03 and 5.04, this isn’t an issue, but any time you see an include like that, you could be loading up multiple includes in the future. Which could introduce additional tasks. Also, keep in mind that you’ll want to keep a backup of this file handy. It’s in a place in your system where Apple can change things in the file without any concern around customizations you previously made in the file. Therefore, in a subsequent software update, you may need to restore that file. You don’t get prompted that there’s a new version of OS X Server When you install OS X Server 5, the next time you open the Server app, you should get prompted that the Server app has been replaced and then go through a little assistant. If you don’t, reboot, throw the Server.app in the trash, redownload and reopen the app. That should take care of that issue. Certificates don’t get migrated The /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf file will have a number of certificates. These include SSLCertificateFile, SSLCertificateKeyFile, and SSLCertificateChainFile. In /etc/certificates, you’ll have some certificates. For example, on my server, I have: 4A94D0AE-7DD6-4D8D-A721-D62DE2AAE092.C174963A4CB567837EE8B5FD7EC8DCBE03143CCB.cert.pem 4A94D0AE-7DD6-4D8D-A721-D62DE2AAE092.C174963A4CB567837EE8B5FD7EC8DCBE03143CCB.chain.pem 4A94D0AE-7DD6-4D8D-A721-D62DE2AAE092.C174963A4CB567837EE8B5FD7EC8DCBE03143CCB.concat.pem Server Fallback SSL Certificate.AD80FE0DDF4D16419A158AAA901594FF15D48A2A.cert.pem Server Fallback SSL Certificate.AD80FE0DDF4D16419A158AAA901594FF15D48A2A.chain.pem Server Fallback SSL Certificate.AD80FE0DDF4D16419A158AAA901594FF15D48A2A.concat.pem Server Fallback SSL Certificate.AD80FE0DDF4D16419A158AAA901594FF15D48A2A.key.pem odr.krypted.com.00EA9C581A8C85D48D295807946C0703DAF88F67.cert.pem odr.krypted.com.00EA9C581A8C85D48D295807946C0703DAF88F67.chain.pem odr.krypted.com.00EA9C581A8C85D48D295807946C0703DAF88F67.concat.pem odr.krypted.com.00EA9C581A8C85D48D295807946C0703DAF88F67.key.pem One is built based on the promotion of OD, another is a fallback, and the one with the funny GUID in front of it is usually the one that you’d use when defining these fields. If OS X Server doesn’t see the correct pem files that it’s expecting it will just create new ones. The old ones are still there. So, if a service like Profile Manager is totally busted, you can backup the /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf and edit the path to the certificates in the file to correct them. Reboot and see if Profile Manager fires up. On one machine, I also had to trash the Server app again and install it again, but just pointing the paths to the correct location worked for the most part (also, note that I had to use the full path of a file rather than just the name of the file). Oh, don’t forget, this would need to be done for each virtual host with an offending certificate chain.   Apache binds ports to all IPs A final issue I’ll point out is that servers that I’d customized the IP that Apache listens on needed to be reconfigured. This is done in the see /Library/Server/Web/Config/Apache2/httpd_server_app.conf configuration file. Here, look for a line for Listen. It will be commented out as so:
#Listen 12.34.56.78:80
If you want to only have a given port listen on a given IP, use that section of that file to customize how the listener should operate. For example, if you have an IP on your machine of 10.0.0.100 and you only want port 80 listening on that port, use the following
Listen 10.0.0.100:80
Conclusion Overall, I would say that if you haven’t upgraded to Server 5 on a Yosemite system, that I’d hold off. There are some funny kinks that need to be worked out and I’d hate to be the one figuring some of this out if I wasn’t planning on a funky upgrade session (e.g. if I had a limited downtime window).

September 22nd, 2015

Posted In: JAMF, Java, Mac OS X, Mac OS X Server, Mac Security

Tags: , , , , , , , , ,

The swupd.plist file used to daisy chain multiple servers so they act as a cascade of software update servers. The new path for the property list is /Library/Server/Software Update/Config/swupd.plist. Here, the metaIndexURL key is sill the location that points to an internal Software Update Server that the server you are editing should look to for updates. The default server is http://swscan.apple.com/content/meta/mirror-config-1.plist. To set a server to look at another internal server for software updates, edit the metaIndexURL key in the /Library/Server/Software Update/Config/swupd.plist file to include the path to the new server. The path should always have /content/meta/mirror-config-1.plist after the FQDN of the host name. So if your internal software update server was called daneel.foundation.lan the command to set that as the upstream software update server would be: defaults write /Library/Server/Software\ Update/Config/swupd metaiIndexURL “http://daneel.foundation.lan/content/meta/mirror-config-1.plist” This is a minor change, but one that might be frustrating if you were still trying to cascade updates the old way. If you’re new to cascading updates, this is a pretty straight forward configuration change, run from a Terminal command. It’s also worth noting that there are a few other settings in this file that could come in handy. You can limit bandwidth using the limitBandwidth key, purge any old updates using the PurgeUnused key, set a max download speed using the maxDownloadSpeed key, configure the Software Update Server TCP port using the portToUse key (automatically set to 8088), change the path to the updates (e.g. if you mv them and then want to repoint to the new location without downloading them all again) using the updatesDocRoot key, etc. Overall, the settings align with the old settings, but just in a new place. Note: The keys above correspond to settings found in the following command: sudo serveradmin settings swupdate The list of settings is as follows: swupdate:checkError = no
swupdate:limitBandwidth = no
swupdate:PurgeUnused = yes
swupdate:portToUse = 8088
swupdate:autoEnable = yes
swupdate:valueBandwidth = 0
swupdate:syncStatus = "Initializing"
swupdate:autoMirror = yes
swupdate:syncBandwidth = 0
swupdate:updatesDocRoot = "/Library/Server/Software Update/Data/"
swupdate:autoMirrorOnlyNew = no

October 31st, 2014

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

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

OS X Yosemite running the Server app has a lot of scripts used for enabling services, setting states, changing hostnames and the like. Once upon a time there was a script for OS X Server called server setup. It was a beautiful but too simplistic kind of script. Today, much of that logic has been moved out into more granular scripts, kept in /Applications/Server.app/Contents/ServerRoot/System/Library/ServerSetup, used by the server to perform all kinds of tasks. These scripts are, like a lot of other things in Yosemite Server. Some of these include the configuration of amavisd, docecot and alerts. These scripts can also be used for migrating services and data. Sometimes the scripts are in bash, sometimes ruby, sometimes perl and other times even python. And the scripts tend to change year over year/release over release. One of the things that can can be useful about the scripts scattered throughout the Server app is to learn how the developers of OS X Server intend for certain tasks to occur. Looking At Services This is also where I learned that Apple had put an Open Directory backup script in /Applications/Server.app/Contents/ServerRoot/usr/libexec/server_backup/opendirectorybackup (that still requires a password). But what I haven’t seen in all of these logs is bumping up the logging level for services before performing tasks, so that you can see a verbose output of what’s going on. To do this, it looks like we’re going service-by-service. So let’s look alphabetically, starting with Address Book: sudo serveradmin settings addressbook:DefaultLogLevel = “warn” This by defualt logs to /var/log/caldavd/error.log, which is built based on the following, which sets the base: sudo serveradmin settings addressbook:LogRoot=/var/log/caldavd And the following, which sets the file name in that directory: sudo serveradmin settings addressbook:ErrorLogFile=error.log You can change either by changing what comes after the = sign. Next is afp. This service logs output to two places. The first is with errors to the service, using /Library/Logs/AppleFileService/AppleFileServiceError.log, the path designated in the following: sudo serveradmin settings afp:errorLogPath = “/Library/Logs/AppleFileService/AppleFileServiceError.log” The second location logs activities (open file, delete file, etc) rather than errors and is /Library/Logs/AppleFileService/AppleFileServiceAccess.log, defined using: sudo serveradmin settings afp:activityLogPath = “/Library/Logs/AppleFileService/AppleFileServiceAccess.log” The activity log is disabled by default and enabled using the command: sudo serveradmin settings afp:activityLog = yes The events that trigger log entries are in the afp:loggingAttributes array and are all enabled by default. There are no further controls for the verbosity of the afp logs. The next service is calendar. Similar to address book, the caldav server uses DefaultLogLevel to set how much data gets placed into logs: sudo serveradmin settings calendar:DefaultLogLevel = “warn” This by defualt logs to /var/log/caldavd/error.log, which is built based on the following, which sets the base: sudo serveradmin settings calendar:LogRoot=/var/log/caldavd And the following, which sets the file name in that directory: sudo serveradmin settings calendar:ErrorLogFile=error.log You can changing either by changing what comes after the = sign. Profile Manager is called devicemgr in the serveradmin interface and I’ve found no way to augment the logging levels. Nor does its migration script ( /Applications/Server.app/Contents/ServerRoot/System/Library/ServerSetup/MigrationExtras/80-devicemgrmigration.sh ) point to any increased logging during migration. The dirserv (aka Open Directory) uses the slapconfig back-end, so I use slapconfig to increase logging: sudo slapconfig -enableslapdlog The DNS service uses named.conf, located in /etc to set log levels and has no serveradmin settings for doing so. Here, use the logging section and look for both the file setting (by default /Library/Logs/named.log) for where the log is stored as well as the severity setting, which can set the logging levels higher or lower. By default Messages, or iChat Server, logs a lot. See the following for what is logged: sudo serveradmin settings jabber:logLevel = “ALL” Adding the -D option to the LaunchDaemon that invokes jabber will increase the logs. Logging long-term is handled in each of the xml files that make up the features of jabber. See the Logconfiguration section of the c2s file via: cat /Applications/Server.app/Contents/ServerRoot/private/etc/jabberd/c2s.xml The mail service has a number of options for logging, much of which has to do with the fact that it’s a patchy solution made up of postfix, etc. Global log locations are controlled using the mail:global:service_data_path key, which indicates a path that logs are stored in (as usual many of these are in /Library/Server): sudo serveradmin settings mail:global:service_data_path = "/Library/Server/Mail" To see the virus database logging levels (which should usually be set to warn): sudo serveradmin settings mail:postfix:virus_db_log_level To see the spamassassin logging levels: sudo serveradmin settings mail:postfix:spam_log_level To see the actual postfix logging level: sudo serveradmin settings mail:postfix:log_level To enable timestamps on logs: sudo serveradmin settings mail:imap:logtimestamps = yes To set the dovecot logging to info: sudo serveradmin settings mail:imap:log_level = “info” To set increased logging per function that dovecot performs, see the config files in /Applications/Server.app/Contents/ServerRoot/private/etc/dovecot/default/conf.d, each of which has a logging section to do so. The NetBoot service is simple to configure logging for, simply set the netboot:logging_level to HIGH (by default it’s MEDIUM): sudo serveradmin settings netboot:logging_level = “HIGH” The Postgres service uses a log directory, configured with postgres:log_directory: sudo serveradmin settings postgres:log_directory = “/Library/Logs/PostgreSQL” The /private/etc/raddb/radiusd.conf has a section (log {}) dedicated to configuring how the radius service logs output. The Xsan service logs output per volume to both the System Log and volume-based log files, stored in /Library/Preferences/Xsan/data. The smb service has a file /Library/Preferences/SystemConfiguration/com.apple.smb.server.plist with a key for log level that can be used for more verbose output of the service. The PPTP VPN service logs output to the file specified in vpn:Servers, configured with these: sudo serveradmin settings vpn:Servers:com.apple.ppp.pptp:Server:LogFile = “/var/log/ppp/vpnd.log”
sudo serveradmin settings vpn:Servers:com.apple.ppp.pptp:PPP:LogFile = “/var/log/ppp/vpnd.log”
sudo serveradmin settings vpn:Servers:com.apple.ppp.l2tp:Server:LogFile = “/var/log/ppp/vpnd.log”
sudo serveradmin settings vpn:Servers:com.apple.ppp.l2tp:PPP:LogFile = “/var/log/ppp/vpnd.log” By default, verbose logging is enabled, which you can see with: sudo serveradmin settings vpn:Servers:com.apple.ppp.pptp:Server:VerboseLogging
sudo serveradmin settings vpn:Servers:com.apple.ppp.pptp:PPP:VerboseLogging
sudo serveradmin settings vpn:Servers:com.apple.ppp.l2tp:Server:VerboseLogging
sudo serveradmin settings vpn:Servers:com.apple.ppp.l2tp:PPP:VerboseLogging The last service is web (Apache). The default access logs are per-site, with a key called customLogPath existing for each. The defaultSite uses the following for its logs: sudo serveradmin settings web:defaultSite:customLogPath Swap out the defaultSite with another site to see its log paths. There’s also a key for errorLogPath that shows errors. These are per-site so that administrators can provide access to logs for the owners of each site and not fear them having access to logs for other users. Global error logs are stored in /private/var/log/apache2/error_log as defined in /private/etc/apache2/httpd.conf. Find LogLevel in this file and set it to configure how in depth the logs will be, using debug for the most verbose and info, notice, warn, error, crit, alert, and emerg to get incrementally less information. Additionally the log formats can be set in /private/etc/apache2/httpd.conf, allowing administrators to configure Yosemite Server’s built-in web service to conform to the standards of most modern web log analyzers. Conclusion Overall, there’s a lot of information in these logs and administrators can spend as much time reviewing logs as they want. But other than standard system logs, the output is typically configured on a service-by-service basis. Some services offer a lot of options and others offering only a few. Some services also offer options within the serveradmin environment while others use their traditional locations in their configuration files. I’ll end this with a warning. There can also be a lot of output in these logs. Therefore, if you set the logging facilities high, make sure to keep a watchful eye on the capacity of the location you’re writing logs out to. The reason I looked at paths to logs where applicable was because you might want to consider redirecting logs to an external volume when debugging so as not to fill up a boot volume and cause even more problems than what you’re likely parsing through logs looking to fix…

October 28th, 2014

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

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

The software patching configuration built into most operating systems is configured so all that a user has to do is open a box at home, join the network and start using the computer right away. As environments grow from homes to small offices and then small offices grow into enterprises, at some point software updates and patches need to be managed centrally. Yosemite Server (OS X Server 3), as with its OS X Server predecessors has a Software Update service. The service in the Server app is known as Software Update and from the command line is known as swupdate. The Software Update service, by default, stores each update in the /var/db/swupd directory. The Software Update servie is actually comprised of three components. The first is an Apache server, invoked by the /Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons/com.apple.swupdate.host.plist LaunchDaemon. This LaunchDaemon invokes a httpd process and clients access updates from the server based on a manifest of updates available in the sucatalog. These are synchronized with Apple Software Updates via /Applications/Server.app/Contents/ServerRoot/usr/sbin/swupd_syncd, the LaunchDaemon for swupdate at /Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons/com.apple.swupdate.sync.plist. The Apache version is now Apache/2.2.22. Clients can be pointed at the server then via a Profile or using the defaults command to edit the /Library/Preferences/com.apple.SoftwareUpdate.plist file. The contents of this file can be read using the following command: defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist To point a client to a server via the command line, use a command such as the following: sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate CatalogURL http://yosemitesamserver.pretendco.lan:8088/index.sucatalog But first, you’ll need to configure and start the Software Update service. Lucky you, it’s quick (although quick in a hurry up and wait kind of way). To get started, open the Server app and then click on the Software Update service. SoftwareUpdate1 By default, updates are set to simply mirror the Apple servers, by default, enabling each update that Apple publishes, effectively proxying updates. You can use the Manual button if you would like to configure updates to either manually be approved and manually synchronized or just manually approved but automatically copied from Apple. Otherwise click on the ON button and wait for the updates to cache to simply mirror the Apple servers. If you would like to manually configure updates, click on the Manual option and then click on the Updates tab. The first item in the Updates tab is the “Automatically download new updates” checkbox. This option downloads all of the updates but does not enable them. The Updates tab also displays all available updates. click on one and then click on the cog-wheel icon towards the bottom of the screen to configure its behavior (Download, Enable, Disable, Remove and View Update). Note: The only option for updates in an Automatic configuration environment is disable. The service can be managed using serveradmin. To start Software Update, use the start option, followed by the swupdate service identifier: sudo serveradmin start swupdate To stop the service, replace start with stop: sudo serveradmin stop swupdate To see the status of the service, including the location of updates, the paths to log files, when the service was started and the number of updates running, use the fullstatus option: sudo serveradmin fullstatus swupdate The output of which appears as follows: swupdate:state = "RUNNING"
swupdate:lastChecktime = 2014-10-07 01:25:05 +0000
swupdate:syncStatus = "INPROGRESS"
swupdate:syncServiceState = "RUNNING"
swupdate:setStateVersion = 1
swupdate:lastProductsUpdate = 2013-10-06 04:02:16 +0000
swupdate:logPaths:swupdateAccessLog = "/var/log/swupd/swupd_access_log"
swupdate:logPaths:swupdateErrorLog = "/var/log/swupd/swupd_error_log"
swupdate:logPaths:swupdateServiceLog = "/var/log/swupd/swupd_syncd_log"
swupdate:readWriteSettingsVersion = 1
swupdate:pluginVers = "10.10.99 (99)"
swupdate:checkError = no swupdate:updatesDocRoot = "/Library/Server/Software Update/Data/"
swupdate:hostServiceState = "RUNNING"
swupdate:autoMirror = no
swupdate:numOfEnabledPkg = 0
swupdate:servicePortsAreRestricted = "NO"
swupdate:numOfMirroredPkg = 0
swupdate:autoMirrorOnlyNew = no
swupdate:startTime = 2013-10-07 01:25:05 +0000
swupdate:autoEnable = no There are also a number of options available using the serveradmin settings that aren’t exposed to the Server app. These include a feature I used to use a lot in the beginning of deployments with poor bandwidth, only mirroring new updates, which is available to swupdate via the autoMirrorOnlyNew option. To configure: sudo serveradmin settings swupdate:autoMirrorOnlyNew = yes Also, the service can throttle bandwidth for clients. To use this option, run the following command: sudo serveradmin settings swupdate:limitBandwidth = yes And configure bandwidth using the syncBandwidth option, as follows: sudo serveradmin settings swupdate:syncBandwidth = 10 To automatically sync updates but not enable them (as the checkboxes allow for in the Server app, use the following command: sudo serveradmin settings swupdate:autoEnable = no The port (by default 8088) can be managed using the portToUse option, here being used to set it to 80 (clients need this in their catalog URL from here on out): sudo serveradmin settings swupdate:portToUse = 80 Finally, administrators can purge old packages that are no longer needed using the PurgeUnused option: sudo serveradmin swupdate:PurgeUnused = yes One of the biggest drawbacks of the Software Update service in OS X Yosemite Server in my opinion is the fact that it does not allow for serving 3rd party packages, from vendors such as Microsoft or Adobe. To provide those vendors with a manifest file and a quick little path option to add those manifest files, a nice middle ground could be found between the Mac App Store and the built in software update options in OS X. But then, we wouldn’t want to make it too easy. Another issue many have had is that users need administrative passwords to run updates and don’t have them (technically this isn’t a problem with the OS X Server part of the stack, but it’s related). While many options have come up for this, one is to just run the softwareupdate command for clients via ARD or a similar tool. Many environments have used these issues to look at tools such as Reposado or third party patch management tools such as JAMF Software’s the Casper Suite (JAMF also makes a reposado-based VM that mimics the swupdate options), FileWave, Absolute Manage and others. Overall, the update service in Yosemite Server is easily configured, easily managed and easily deployed to clients. It is what it needs to be for a large percentage of OS X Yosemite (10.10) Server administrators. This makes it a very viable option and if you’ve already got a Mountain Lion computer sitting around with clients not yet using a centralized update server, well worth enabling.

October 17th, 2014

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

Tags: , , , , , , , ,

Web Services in Mac OS X, Mac OS X Server, Linux and most versions of Unix are provided by Apache, an Open Source project that much of the Internet owes its origins to. Apache owes its name to the fact that it’s “a patchy” service. These patches are often mods, or modules. Configuring web services is as easy in OS X Mavericks Server (10.9) as it has ever been. To set up the default web portal, simply open the Server app, click on the Websites service and click on the ON button. webserver1 After a time, the service will start. Once running, click on the View Server Website link at the bottom of the pane. webserver2 Provided the stock OS X Server page loads, you are ready to use OS X Server as a web server. Before we setup custom sites, there are a few things you should know. The first is, the server is no longer really designed to remove the default website. So if you remove the site, your server will exhibit inconsistent behavior. Also, don’t remove the files that comprise the default site. Instead just add sites, which is covered next. Webmail is gone. You don’t have to spend a ton of time looking for it as it isn’t there. Also, Mountain Lion Server added web apps, which we’ll briefly review later in this article as well, as those continue in Mavericks Server and subsequently in Yosemite Server.  Finally, enabling PHP and Python on sites is done globally, so this setting applies to all sites hosted on the server. webserver3 Now that we’ve got that out of the way, let’s add our first custom site. Do so by clicking on the plus sign. At the New Web Site pane, you’ll be prompted for a number of options. The most important is the name of the site, with other options including the following:
  • Domain Name: The name the site is accessible from. The default sites do not have this option as they are accessible from all names that resolve to the server.
  • IP Address: The IP address the site listens on. Any means the site is available from every IP address the server is configured to use. The default websites do not have this option as they are accessible from all addresses automatically
  • Port: By default, sites without SSL run on port 80 on all network interfaces, and sites with SSL run on port 443 on all network interfaces. Use the Port field to use custom ports (e.g., 8080). The default sites do not have this option as they are configured to use 80 and 443 for default and SSL-based communications respectively.
  • SSL Certificate: Loads a list of SSL certificates installed using Keychain or the SSL Certificate option in the Settings pane of the Server application
  • Store Site Files In: The directory that the files that comprise the website are stored in. These can be placed into the correct directory using file shares or copying using the Finder. Click on the drop-down menu and then select Other to browse to the directory files are stored in.
  • Who Can Access: By default Anyone (all users, including unauthenticated guests) can access the contents of sites. Clicking on Anyone and then Customize… brings up the “Restrict access to the following folders to a chosen group” screen, where you can choose web directories and then define groups of users who can access the contents.
  • Additional Domains: Click on the Edit… button to bring up a simple list of domain names the the site also responds for (e.g. in addition to krypted.com, add www.krypted.com).
  • Redirects: Click on the Edit… button to bring up a list of redirects within the site. This allows configuring redirects to other sites. For example, use /en to load english.krypted.com or /cn to load china.krypted.com).
  • Aliases: Click on the Edit… button to load a list of aliases. This allows configuring redirects to folders within the same server. For example, /en loads /Library/Server/Web/Data/Sites/Default
  • Index Files: Click on the Edit… button to bring up a list of pages that are loaded when a page isn’t directly indicated. For example, when visiting krypted.com, load the wp.php page by default.
  • Advanced Options: The remaining options are available by clicking on the “Edit Advanced Settings…” button.
The Advanced Option include the following:
  • Enable Server Side Includes: Allows administrators to configure leveraging includes in web files, so that pieces of code can be used across multiple pages in sites.
  • Allow overrides using .htaccess files: Using a .htaccess file allows administrators to define who is able to access a given directory, defining custom user names and passwords in the hidden .htaccess file. These aren’t usually required in an OS X Server web environment as local and directory-based accounts can be used for such operations. This setting enables using custom .htaccess files instead of relying on Apple’s stock web permissions.
  • Allow folder listing: Enables folder listings on directories of a site that don’t have an Index File (described in the non-Advanced settings earlier).
  • Allow CGI execution: Enables CGI scripts for the domain being configured.
  • Use custom error page: Allows administrators to define custom error pages, such as those annoying 404 error pages that load when a page can’t be found
  • Make these web apps available on this website: A somewhat advanced setting, loads items into the webapps array, which can be viewed using the following command:  sudo serveradmin settings web:definedWebApps
Once you’ve configured all the appropriate options, click on Done to save your changes. The site should then load. Sites are then listed in the list of Websites. The Apache service is most easily managed from the Server app, but there are too many options in Apache to really be able to put into a holistic graphical interface. The easiest way to manage the Websites service in OS X Yosemite Server is using the serveradmin command. Apache administrators from other platforms will be tempted to use the apachectl command to restart the Websites service. Instead, use the serveradmin command to do so. To start the service: sudo serveradmin start web To stop the service(s): sudo serveradmin stop web And to see the status: sudo serveradmin fullstatus web Fullstatus returns the following information: web:health = _empty_dictionary
web:readWriteSettingsVersion = 1
web:apacheVersion = "2.2"
web:servicePortsRestrictionInfo = _empty_array
web:startedTime = "2013-10-08 01:05:32 +0000"
web:apacheState = "RUNNING"
web:statusMessage = ""
web:ApacheMode = 2
web:servicePortsAreRestricted = "NO"
web:state = "RUNNING"
web:setStateVersion = 1 While the health option typically resembles kiosk computers in the Computer Science departments of most major universities, much of the rest of the output can be pretty helpful including the Apache version, whether the service is running, any restrictions on ports and the date/time stamp that the service was started. To see all of the settings available to the serveradmin command, run it, followed by settings and then web, to indicate the Websites service: sudo serveradmin settings web The output is pretty verbose and can be considered in two sections, the first includes global settings across sites as well as the information for the default sites that should not be deleted: web:defaultSite:documentRoot = "/Library/Server/Web/Data/Sites/Default"
web:defaultSite:serverName = ""
web:defaultSite:realms = _empty_dictionary
web:defaultSite:redirects = _empty_array
web:defaultSite:enableServerSideIncludes = no
web:defaultSite:customLogPath = ""/var/log/apache2/access_log""
web:defaultSite:webApps = _empty_array
web:defaultSite:sslCertificateIdentifier = ""
web:defaultSite:fullSiteRedirectToOtherSite = ""
web:defaultSite:allowFolderListing = no
web:defaultSite:serverAliases = _empty_array
web:defaultSite:errorLogPath = ""/var/log/apache2/error_log""
web:defaultSite:fileName = "/Library/Server/Web/Config/apache2/sites/0000_any_80_.conf"
web:defaultSite:aliases = _empty_array
web:defaultSite:directoryIndexes:_array_index:0 = "index.html"
web:defaultSite:directoryIndexes:_array_index:1 = "index.php"
web:defaultSite:directoryIndexes:_array_index:2 = "/wiki/"
web:defaultSite:directoryIndexes:_array_index:3 = "default.html"
web:defaultSite:allowAllOverrides = no
web:defaultSite:identifier = "37502141"
web:defaultSite:port = 80
web:defaultSite:allowCGIExecution = no
web:defaultSite:serverAddress = "*"
web:defaultSite:requiresSSL = no
web:defaultSite:proxies = _empty_dictionary
web:defaultSite:errorDocuments = _empty_dictionary
web:defaultSecureSite:documentRoot = "/Library/Server/Web/Data/Sites/Default"
web:defaultSecureSite:serverName = ""
web:defaultSecureSite:realms = _empty_dictionary
web:defaultSecureSite:redirects = _empty_array
web:defaultSecureSite:enableServerSideIncludes = no
web:defaultSecureSite:customLogPath = ""/var/log/apache2/access_log""
web:defaultSecureSite:webApps = _empty_array
web:defaultSecureSite:sslCertificateIdentifier = "com.apple.systemdefault.9912650B09DE94ED160146A3996A45EB3E39275B"
web:defaultSecureSite:fullSiteRedirectToOtherSite = ""
web:defaultSecureSite:allowFolderListing = no
web:defaultSecureSite:serverAliases = _empty_array
web:defaultSecureSite:errorLogPath = ""/var/log/apache2/error_log""
web:defaultSecureSite:fileName = "/Library/Server/Web/Config/apache2/sites/0000_any_443_.conf"
web:defaultSecureSite:aliases = _empty_array
web:defaultSecureSite:directoryIndexes:_array_index:0 = "index.html"
web:defaultSecureSite:directoryIndexes:_array_index:1 = "index.php"
web:defaultSecureSite:directoryIndexes:_array_index:2 = "/wiki/"
web:defaultSecureSite:directoryIndexes:_array_index:3 = "default.html"
web:defaultSecureSite:allowAllOverrides = no
web:defaultSecureSite:identifier = "37502140"
web:defaultSecureSite:port = 443
web:defaultSecureSite:allowCGIExecution = no
web:defaultSecureSite:serverAddress = "*"
web:defaultSecureSite:requiresSSL = yes
web:defaultSecureSite:proxies = _empty_dictionary
web:defaultSecureSite:errorDocuments = _empty_dictionary
web:dataLocation = "/Library/Server/Web/Data"
web:mainHost:keepAliveTimeout = 15.000000
web:mainHost:maxClients = "50%" The second section is per-site settings, with an array entry for each site: web:customSites:_array_index:0:documentRoot = "/Library/Server/Web/Data/Sites/www2.krypted.com"
web:customSites:_array_index:0:serverName = "www2.krypted.com"
web:customSites:_array_index:0:realms = _empty_dictionary
web:customSites:_array_index:0:redirects = _empty_array
web:customSites:_array_index:0:enableServerSideIncludes = no
web:customSites:_array_index:0:customLogPath = "/var/log/apache2/access_log"
web:customSites:_array_index:0:webApps = _empty_array
web:customSites:_array_index:0:sslCertificateIdentifier = ""
web:customSites:_array_index:0:fullSiteRedirectToOtherSite = ""
web:customSites:_array_index:0:allowFolderListing = no
web:customSites:_array_index:0:serverAliases = _empty_array
web:customSites:_array_index:0:errorLogPath = "/var/log/apache2/error_log"
web:customSites:_array_index:0:fileName = "/Library/Server/Web/Config/apache2/sites/0000_any_80_www2.krypted.com.conf"
web:customSites:_array_index:0:aliases = _empty_array
web:customSites:_array_index:0:directoryIndexes:_array_index:0 = "index.html"
web:customSites:_array_index:0:directoryIndexes:_array_index:1 = "index.php"
web:customSites:_array_index:0:directoryIndexes:_array_index:2 = "/wiki/"
web:customSites:_array_index:0:directoryIndexes:_array_index:3 = "default.html"
web:customSites:_array_index:0:allowAllOverrides = no
web:customSites:_array_index:0:identifier = "41179886"
web:customSites:_array_index:0:port = 80
web:customSites:_array_index:0:allowCGIExecution = no
web:customSites:_array_index:0:serverAddress = "*"
web:customSites:_array_index:0:requiresSSL = no
web:customSites:_array_index:0:proxies = _empty_dictionary
web:customSites:_array_index:0:errorDocuments = _empty_dictionary The final section (the largest by far) includes array entries for each defined web app. The following shows the entry for a Hello World Python app: web:definedWebApps:_array_index:20:requiredWebAppNames = _empty_array
web:definedWebApps:_array_index:20:includeFiles = _empty_array
web:definedWebApps:_array_index:20:requiredModuleNames = _empty_array
web:definedWebApps:_array_index:20:startCommand = ""
web:definedWebApps:_array_index:20:sslPolicy = 0
web:definedWebApps:_array_index:20:requiresSSL = no
web:definedWebApps:_array_index:20:requiredByWebAppNames = _empty_array
web:definedWebApps:_array_index:20:launchKeys:_array_index:0 = "org.postgresql.postgres"
web:definedWebApps:_array_index:20:proxies = _empty_dictionary
web:definedWebApps:_array_index:20:preflightCommand = ""
web:definedWebApps:_array_index:20:stopCommand = ""
web:definedWebApps:_array_index:20:name = "org.postgresql.postgres"
web:definedWebApps:_array_index:20:displayName = "" Each site has its own configuration file defined in the array for each section. By default these are stored in the /Library/Server/Web/Config/apache2/sites directory, with /Library/Server/Web/Config/apache2/sites/0000_any_80_www2.krypted.com.conf being the file for the custom site we created previously. As you can see, many of the options available in the Server app are also available in these files: ServerName www2.krypted.com
ServerAdmin admin@example.com
DocumentRoot "/Library/Server/Web/Data/Sites/www2.krypted.com"
DirectoryIndex index.html index.php /wiki/ default.html
CustomLog /var/log/apache2/access_log combinedvhost
ErrorLog /var/log/apache2/error_log SSLEngine Off SSLCipherSuite “ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM” SSLProtocol -ALL +SSLv3 +TLSv1 SSLProxyEngine On SSLProxyProtocol -ALL +SSLv3 +TLSv1 Options All -Indexes -ExecCGI -Includes +MultiViews AllowOverride None DAV Off Deny from all ErrorDocument 403 /customerror/websitesoff403.html The serveradmin command can also be used to run commands. For example, to reset the service to factory defaults, delete the configuration files for each site and then run the following command: sudo serveradmin command web:command=restoreFactorySettings The final tip I’m going to give in this article is when to make changes with each app. I strongly recommend making all of your changes in the Server app when possible. When it isn’t, use serveradmin and when you can’t make changes in serveradmin, only then alter the configuration files that come with the operating system by default. I also recommend keeping backups of all configuration files that are altered and a log of what was altered in each, in order to help piece the server back together should it become unconfigured miraculously when a softwareupdate -all is run next.

October 16th, 2014

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

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

Next Page »