diff options
| author | cashmere <cashmere@autistici.org> | 2026-09-04 09:05:24 +0200 |
|---|---|---|
| committer | cashmere <cashmere@autistici.org> | 2026-09-04 09:05:24 +0200 |
| commit | 4f49b16079b27d7ce633619e4cddfdf2bffbc952 (patch) | |
| tree | c296c1e7f3c3e2f6859c6d3a1b1b208779b89679 /www/server/macos/service.md | |
| download | relic-4f49b16079b27d7ce633619e4cddfdf2bffbc952.tar.gz | |
Diffstat (limited to 'www/server/macos/service.md')
| -rw-r--r-- | www/server/macos/service.md | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/www/server/macos/service.md b/www/server/macos/service.md new file mode 100644 index 0000000..b1358fa --- /dev/null +++ b/www/server/macos/service.md @@ -0,0 +1,181 @@ +# Serving via launchd on macOS + +[`launchd`][ldhome] is the default service management framework on macOS +[since the release of Tiger in 2005][wpa]. If you want a Fossil server +to launch in the background on a Mac, it’s the way Apple wants you to do +it. `launchd` is to macOS as `systemd` is to most modern Linux desktop +systems. (Indeed, `systemd` arguably reinvented the perfectly good, +pre-existing `launchd` wheel.) + +Unlike in [our `systemd` article](../debian/service.md), we’re not going +to show the per-user method here, because those so-called +[LaunchAgents][la] only start when a user is logged into the GUI, and +they stop when that user logs out. This does not strike us as proper +“server” behavior, so we’ll stick to system-level LaunchDaemons instead. + +However, we will still give two different configurations, just as in the +`systemd` article: one for a standalone HTTP server, and one using +socket activation. + +For more information on `launchd`, the single best resource we’ve found +is [launchd.info](https://launchd.info). The next best is: + + $ man launchd.plist + +[la]: http://www.grivet-tools.com/blog/2014/launchdaemons-vs-launchagents/ +[ldhome]: https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html +[wpa]: https://en.wikipedia.org/wiki/Launchd + + + +## Standalone HTTP Server + +To configure `launchd` to start Fossil as a standalone HTTP server, +write the following as `com.example.dev.FossilHTTP.plist`: + +```xml +<?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>com.example.dev.FossilHTTP</string> + <key>ProgramArguments</key> + <array> + <string>/usr/local/bin/fossil</string> + <string>server</string> + <string>--port</string> + <string>9000</string> + <string>repo.fossil</string> + </array> + <key>WorkingDirectory</key> + <string>/Users/you/museum</string> + <key>KeepAlive</key> + <true/> + <key>RunAtLoad</key> + <true/> + <key>StandardErrorPath</key> + <string>/tmp/fossil-error.log</string> + <key>StandardOutPath</key> + <string>/tmp/fossil-info.log</string> + <key>UserName</key> + <string>you</string> + <key>GroupName</key> + <string>staff</string> + <key>InitGroups</key> + <true/> +</dict> +</plist> +``` + +In this example, we’re assuming your development organization uses the +domain name “`dev.example.org`”, that your short macOS login name is +“`you`”, and that you store your Fossils in “`~/museum`”. Adjust these +elements of the plist file to suit your local situation. + +You might be wondering about the use of `UserName`: isn’t Fossil +supposed to drop privileges and enter [a `chroot(2)` +jail](../../chroot.md) when it’s started as root like this? Why do we +need to give it a user name? Won’t Fossil use the owner of the +repository file to set that? All I can tell you is that in testing here, +if you leave the user and group configuration at the tail end of that +plist file out, Fossil will remain running as root! + +Install that file and set it to start with: + + $ sudo install -o root -g wheel -m 644 com.example.dev.FossilHTTP.plist \ + /Library/LaunchDaemons/ + $ sudo launchctl load -w /Library/LaunchDaemons/com.example.dev.FossilHTTP.plist + +Because we set the `RunAtLoad` key, this will also launch the daemon. + +Stop the daemon with: + + $ sudo launchctl unload -w /Library/LaunchDaemons/com.example.dev.FossilHTTP.plist + + +## Socket Listener + +Another useful method to serve a Fossil repo via `launchd` is by setting +up a socket listener: + +```xml +<?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>com.example.dev.FossilSocket</string> + <key>ProgramArguments</key> + <array> + <string>/usr/local/bin/fossil</string> + <string>http</string> + <string>repo.fossil</string> + </array> + <key>Sockets</key> + <dict> + <key>Listeners</key> + <dict> + <key>SockServiceName</key> + <string>9001</string> + <key>SockType</key> + <string>stream</string> + <key>SockProtocol</key> + <string>TCP</string> + <key>SockFamily</key> + <string>IPv4</string> + </dict> + </dict> + <key>inetdCompatibility</key> + <dict> + <key>Wait</key> + <false/> + </dict> + <key>WorkingDirectory</key> + <string>/Users/you/museum</string> + <key>UserName</key> + <string>you</string> + <key>GroupName</key> + <string>staff</string> + <key>InitGroups</key> + <true/> +</dict> +</plist> +``` + +Save it as “`com.example.dev.FossilSocket.plist`” and install and load +it into `launchd` as above. + +This version differs in several key ways: + +1. We’re calling Fossil as `fossil http` rather than `fossil server` to + make it serve a single request and then shut down immediately. + +2. We’ve told `launchd` to listen on our TCP port number instead of + passing it to `fossil`. + +3. We’re running the daemon in `inetd` compatibility mode of `launchd` + with “wait” mode off, which tells it to attach the connected socket + to the `fossil` process’s stdio handles. + +4. We’ve removed the `Standard*Path` keys because they interfere with + our use of stdio handles for HTTP I/O. You might therefore want to + start with the first method and then switch over to this one only + once you’ve got the daemon launching debugged, since once you tie up + stdio this way, you won’t be able to get logging information from + Fossil via that path. (Fossil does have some internal logging + mechanisms, but you can’t get at them until Fossil is launching!) + +5. We’ve removed the `KeepAlive` and `RunAtLoad` keys because those + options aren’t appropriate to this type of service. + +6. Because we’re running it via a socket listener instead of as a + standalone HTTP server, the Fossil service only takes system + resources when it’s actually handling an HTTP hit. If your Fossil + server is mostly idle, this method will be a bit more efficient than + the first option. + + +*[Return to the top-level Fossil server article.](../)* |
