Question
Has anyone successfully been able to start a webapp via a webappctl
configuration which specifies a launchd configuration in their webapp.plist
launchKeys
key?
Background
Specifically, with Server.app installed, one can, in theory, configure custom web applications which would show up in the Server.app GUI under the "Advanced Settings" of a Website configuration.
If you take a look at the ReadMe.txt
in /Library/Server/Web/Config/apache2
there's a section which states:
webapps/
This directory contains the webapp.plist files for all defined webapps.
See the man page for webapp.plist(8) and webappctl(8).
(Server app man pages are present in /Applications/Server.app/Contents/ServerRoot/usr/share/man/.)
Administrators are strongly encouraged to use the webapp mechanism
instead of modifying virtual host config files directly.
In general, you can place Apache configuration directives in an "Include" file,
and create a webapp.plist file that references that Include file.
You can then activate or de-activate that Include file for the default
sites, or for specific custom sites, by using webappctl(8).
You can also read the man entries, as suggested in the ReadMe.txt by these terminal commands:
man -M /Applications/Server.app/Contents/ServerRoot/usr/share/man/ webapp.plist
man -M /Applications/Server.app/Contents/ServerRoot/usr/share/man/ webappctl
There's also a sample webapp configuration /Library/Server/Web/Config/apache2/com.example.mywebapp.plist
which has some comments in it about how this plist could be configured.
Setup
In my case I have added a webapp.plist
to the /Library/Server/Web/Config/apache2/
directory which looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<!-- See man pages for webapp.plist(5) and webappctl(8) for information about webapp.plist -->
<plist version="1.0">
<dict>
<key>includeFiles</key>
<array/> <!-- Include files are activated in virtual host when webapp is started -->
<key>launchKeys</key>
<array> <!-- Launchd plists in /Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons are loaded when webapp is started -->
<string>org.levi.foo</string>
</array>
<key>name</key>
<string>org.apache.tomcat</string>
<key>displayName</key> <!-- Name shown in Server app -->
<string>Tomcat</string>
<key>proxies</key> <!-- ProxyPass/ProxyPassReverse directives are activated when webapp is started -->
<dict/>
<key>requiredModuleNames</key>
<array/>
<key>installationIndicatorFilePath</key> <!-- The presence of this file indicates web app is installed -->
<string>/Library/Tomcat/Home/bin/catalina.sh</string>
<key>sslPolicy</key> <!-- Determines webapp SSL behavior -->
<integer>0</integer> <!-- 0: default, UseSSLWhenEnabled -->
<!-- 1: UseSSLAlways -->
<!-- 2: UseSSLOnlyWhenCertificateIsTrustable -->
<!-- 3: UseSSLNever -->
<!-- 4: UseSSLAndNonSSL -->
</dict>
</plist>
Paying specific attention to:
<key>launchKeys</key>
<array>
<string>org.levi.foo</string>
</array>
which specifies my launchd.plist
which is located at /Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons/org.levi.foo.plist
and looks like:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>org.levi.foo</string>
<key>RunAtLoad</key>
<true/>
<key>Program</key>
<string>/Library/Tomcat/start.sh</string>
</dict>
</plist>
which should simply call the script /Library/Tomcat/start.sh
which is simply:
#!/bin/bash
BASENAME=`basename $0`
LOGGER_B="/usr/bin/logger"
function log {
MESSAGE="$1"
${LOGGER_B} -i -p daemon.notice -t ${BASENAME} ${MESSAGE}
}
log "Here I am!"
Issue
If I use launchctl
to manually load the org.levi.foo.plist
:
$ sudo launchctl load org.levi.foo.plist
I get the expected message in /var/log/system.log
:
Apr 2 16:12:01 host sudo[85791]: levi : TTY=ttys000 ; PWD=/Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons ; USER=root ; COMMAND=/bin/launchctl load org.levi.foo.plist
Apr 2 16:12:01 host start.sh[85795]: Here I am!
However, if I use webappctl
to start my webapp configuration (above):
$ sudo webappctl start org.apache.tomcat
I get an error in /var/log/system.log
:
Apr 2 16:18:46 host sudo[85904]: levi : TTY=ttys000 ; PWD=/Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons ; USER=root ; COMMAND=/Applications/Server.app/Contents/ServerRoot/usr/sbin/webappctl start org.apache.tomcat
Apr 2 16:18:47 host serverctl[85914]: ERROR: The operation couldn’t be completed. Operation not permitted
Apr 2 16:18:49 host serverctl[85915]: ERROR: The operation couldn’t be completed. Operation not permitted
Apr 2 16:18:49 host servermgr_web[85908]: XSWebConfig:ERROR: Failed on second attempt to load /Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons/org.levi.foo.plist
and I don't see my "Here I am!" message.
This seems to indicate that my launchd.plist
is not making it as far as running the script when trying to start via webappctl
, but I have no idea what operation couldn't be completed, or why not. All of the files I've mentioned are owned by root:wheel
with rw-r--r--
permissions, except for the script, which is rwx-r-xr-x
.
So, what magic must be performed to get my webapp to load/unload my launchd configuration on start/stop?
Side note: Obviously these configurations and scripts are simple examples I've used for debugging purposes and to simplify the details here. In reality I'm trying to stand up an instance of Tomcat as a "webapp" to run behind Apache 2 on my server such that I can deploy true web apps through Tomcat and have them served to the web.)
Side note 2:
I know I can install my launchd.plist
in /Library/LaunchDaemons
, and omit the launchKeys
from my webapp.plist
as a workaround, but this does not allow me to start/stop the webapp via Server.app (or the command line equivalent), and, I mean, it should work, right?
Many thanks,
Levi
(crosspost from https://discussions.apple.com/message/27946624 )
webappctl start org.apache.tomcat
just works. Maybe it's some caching problem. Did you try to restart your Mac/empty the caches? Or restart the web server?/var/log/system.log
? To be clear, there's no error fromwebappctl start org.apache.tomcat
(it seems to work), but the error manifests in thesystem.log
as I've documented.sudo launchctl load org.levi.foo.plist
(of course) and also fromsudo webappctl start org.apache.tomcat
. After executing the latter you also get a 3-liner response in your shell which states that org.apache.tomcat is RUNNING now.