├── LICENSE ├── README.md └── macOS Server Migration Notes.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Steve Smith 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | macOS-Open-Source-Server 2 | ======================== 3 | 4 | # macOS Open Source Server: Open Source macOS Server Services 5 | 6 | An open source version of several useful [macOS 7 | Server](https://apps.apple.com/us/app/macos-server/id883878097?mt=12) 8 | services that are no longer supported. This [README.md](README.md) has 9 | instructions for installing and configuring these services using 10 | [MacPorts](https://www.macports.org). See the [macOS Server Migration 11 | Notes](macOS Server Migration Notes.md) for detailed notes on 12 | migrating macOS Server.app v. 5.7 High Sierra to Server.app v. 5.8 13 | Mojave. 14 | 15 | 16 | Table of Contents 17 | ================= 18 | * [DNS](#dns) 19 | * [Mail](#mail) 20 | * [Calendar and Contacts](#calendar-and-contacts) 21 | * [VPN](#vpn) 22 | * [OpenVPN](#openvpn) 23 | 24 | 25 | ## DNS 26 | 27 | Configure DNS with a "split horizon," so that the domain is bound to 28 | an external IP address on the open internet by the DNS provider of 29 | your choice, and an internal LAN IP address by the [DNS service](#dns) 30 | on the server. 31 | 32 | ```bash 33 | sudo port install dns-server 34 | port notes dns-server 35 | sudo port load bind9 36 | ``` 37 | 38 | It is necessary to reconfigure the installation for your own network 39 | specifics and preferences by editing the files: 40 | 41 | * `/opt/local/etc/named.conf` 42 | * `/opt/local/var/named/db.*` 43 | 44 | Refer to the `*.macports` template files and `man named` for details. 45 | 46 | 47 | ## Mail 48 | 49 | MacPorts provides a basic, working, configurable mail server: 50 | ```bash 51 | sudo port install mail-server 52 | port notes mail-server 53 | sudo port load mail-server 54 | ``` 55 | 56 | This mail server uses [postfix](http://www.postfix.org/documentation.html) for the MTA, 57 | [dovecot](https://www.dovecot.org) for the MDA, [solr](http://lucene.apache.org/solr/guide/) for fast search, 58 | [Rspamd](https://www.rspamd.com) for a milter, and [clamav](https://www.clamav.net) for email virus scanning. 59 | Surrogate TLS and DKIM configurations are created during the installation; these must be changed prior to 60 | deployment. The configuration files in this port are a combination of macOS Server version 5.7's Mail server 61 | setup, with many newer capabilities added. See the individual projects for configuration details, as well as 62 | online guides, e.g. [mail-server-guide](https://www.c0ffee.net/blog/mail-server-guide/), and the MacPorts 63 | `mail-server` [Portfile](https://github.com/macports/macports-ports/blob/master/mail/mail-server/Portfile) itself: 64 | ```bash 65 | port notes mail-server 66 | less `port file mail-server` 67 | port contents mail-server 68 | ``` 69 | 70 | Users must reconfigure the mail-server installation for their own system, network, and security model specifics 71 | by editing all necessary files and checking file permissions. Full deployment also requires a working DNS 72 | configuration on both the LAN and the internet (pre-installed with `mail-server`), including SPF, DMARC, and DKIM 73 | records, trusted TLS certificates, port forwarding, possibly a mail relay, and more. 74 | 75 | 76 | ## Calendar and Contacts 77 | 78 | ```bash 79 | sudo port install calendar-contacts-server 80 | port notes calendar-contacts-server 81 | sudo port load calendar-contacts-server 82 | ``` 83 | 84 | 85 | ## VPN 86 | 87 | Configure macOS's native VPN (L2TP-IPSec-PSK) Server. This 88 | configuration is based upon macOS Server.app's prior VPN server. 89 | 90 | ```bash 91 | sudo port install macos-vpn-server 92 | port notes macos-vpn-server 93 | sudo port load macos-vpn-server 94 | ``` 95 | 96 | It is necessary to reconfigure the installation for your own network 97 | specifics by editing the file: 98 | * `/Library/Preferences/SystemConfiguration/com.apple.RemoteAccessServers.plist` 99 | See `man 5 vpnd` for details. 100 | 101 | 102 | ## OpenVPN 103 | 104 | See the repo [macOS OpenVPN Server](https://github.com/essandess/macos-openvpn-server). 105 | -------------------------------------------------------------------------------- /macOS Server Migration Notes.md: -------------------------------------------------------------------------------- 1 | # macOS-Open-Source-Server 2 | macOS Open Source Server: An Open Source Version of macOS Server Services 3 | 4 | This [README.md](README.md) has notes on migrating macOS Server.app v. 5.7 High Sierra to Server.app v. 5.8 Mojave, 5 | which has deprecated all server services except for **Profile Manager** and **Open Directory**. This roughly follows 6 | the [macOS Server Service Migration Guide](https://developer.apple.com/support/macos-server/macOS-Server-Service-Migration-Guide.pdf), 7 | but adds important details or omissions of that documentation. The outcome will be a macOS-based server that hosts open source 8 | versions of services traditionally included in the old Server.app, but with a user-configurable and upgradable configuration. 9 | 10 | The general approach here will be to migrate Server.app v. 5.7 configurations into either open source services, or native 11 | macOS services if such exist. I will use Server.app v. 5.8's Open Directory for authentication, but this is not necessary. 12 | 13 | These notes use [MacPorts](https://www.macports.org). It is also easy to use [Homebrew](https://brew.sh), like this [repo](../../../../taniguti/Services_on_macOS). 14 | 15 | Table of Contents 16 | ================= 17 | * [Hardware](#hardware) 18 | * [Server.app v. 5.7 Backup](#serverapp-v-57-backup) 19 | * [SSH](#ssh) 20 | * [Macports migration](#macports-migration) 21 | * [Logrotate](#logrotate) 22 | * [Server.app](#server-app) 23 | * [Domain Name](#domain-name) 24 | * [Domain Name Registration](#domain-name-registration) 25 | * [Domain Name DNS Configuration](#domain-name-dns-configuration) 26 | * [SPF](#spf) 27 | * [DKIM](#dkim) 28 | * [DNS](#dns) 29 | * [Network Configuration](#network-configuration) 30 | * [Web](#web) 31 | * [`apachectl`-based](#apachectl-based) 32 | * [Server.app-based](#server-app-based) 33 | * [`VirtualHost` Method](#virtualhost-method) 34 | * [`AliasMatch` Method](#aliasmatch-method) 35 | * [Apache2 log file rotatation](#apache2-log-file-rotatation) 36 | * [VPN (macOS `vpnd`, L2TP-IPSec-PSK)](#vpn-macos-vpnd-l2tp-ipsec-psk) 37 | * [OpenVPN](#openvpn) 38 | * [Mail](#mail) 39 | * [Calendar and Contacts](#calendar-and-contacts) 40 | 41 | 42 | ## Hardware 43 | 44 | This is done on a Mac Mini (2018) which, when configured with a 6-core i&, is small, quiet, and very, very performant. 45 | I added 64 GB of memory purchased from OWC, which is a straighforward process so long as you take the time to keep the screws 46 | organized from each of the disassembly stages. See these [instructional](https://eshop.macsales.com/installvideos/mac-mini-2018-memory/) 47 | [videos](https://www.youtube.com/watch?v=gQq4hLKv1Cc). 48 | 49 | These services will run well on any old Mac desktop configured with a suffient processor and memory, including my old 50 | 2012 Mac Mini server model. 51 | 52 | Like those old Mac servers, I'll call the base hard drive in these notes `Server HD` (not `Macintosh HD`). 53 | 54 | 55 | ## Server.app v. 5.7 Backup 56 | 57 | Save Server.app v. 5.7's service configurations in `/Library/Server` in `/Library/Server_v57` on the new server. Save all other Server.app-related files in `/Library/Server_v57/Server\ HD`, which correspond to `/` in the old server's file system. 58 | 59 | Create these directions and make a copy of the entire Server.app: 60 | 61 | New server: 62 | ``` 63 | sudo mkdir -p /Library/Server_v57/Server\ HD/Applications 64 | sudo rsync -a -e 'ssh -l admin' admin@old-server:/Applications/Server.app /Library/Server_v57/Server\ HD/Applications/ 65 | ``` 66 | 67 | 68 | ## SSH 69 | 70 | Lock down ssh with key logins only, only allow specific users and groups. 71 | 72 | New server: 73 | ``` 74 | ssh-keygen -t ed25519 -a 256 -C admin@new-server 75 | sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.orig 76 | sudo vi /etc/ssh/sshd_config 77 | diff /etc/ssh/sshd_config.orig /etc/ssh/sshd_config 78 | ``` 79 | 80 | ``` 81 | 57a58 82 | > PasswordAuthentication no 83 | 61a63 84 | > ChallengeResponseAuthentication no 85 | 119a122,127 86 | > 87 | > # Allow ssh authentication for only these users; also set in 88 | > # System Preferences>Sharing>Remote Login. 89 | > # See Directory Utility or `sudo dscl /Local/Default -read /Groups/admin` 90 | > AllowUsers admin 91 | > AllowGroups admin 92 | ``` 93 | 94 | Copy `~/.ssh/id_ed25519.pub` to `~/.ssh/authorized_keys` on other hosts. 95 | 96 | 97 | ## Macports migration 98 | 99 | Follow this [Macports migration procedure](https://trac.macports.org/wiki/Migration) to migrate Macports to the new server. 100 | 101 | Avoid server rot by updating Macports binaries regularly: 102 | ``` 103 | sudo bash -c 'port selfupdate ; port -puN upgrade outdated ; port uninstall inactive' 104 | ``` 105 | 106 | 107 | ## Logrotate 108 | 109 | Use `logrotate` for services that don't have built-in log rotataion capabilities 110 | ``` 111 | sudo port install logrotate 112 | sudo cp -p /opt/local/etc/logrotate.conf /opt/local/etc/logrotate.conf.orig 113 | sudo vi /opt/local/etc/logrotate.conf 114 | diff /opt/local/etc/logrotate.conf.orig /opt/local/etc/logrotate.conf 115 | ``` 116 | 117 | Use `bzip2` for compression: 118 | ``` 119 | > # use bzip2 for log file compression 120 | > compresscmd /usr/bin/bzip2 121 | > uncompresscmd /usr/bin/bunzip2 122 | > compressoptions -9 123 | > compressext .bz2 124 | > 125 | ``` 126 | 127 | 128 | ## Server.app 129 | 130 | Install and turn on **Profile Manager** and **Open Directory**. 131 | 132 | 133 | ## Domain Name 134 | 135 | ### Domain Name Registration 136 | 137 | Purchase a domain name from your favorite registrar. Personally, I 138 | really like [NameCheap](https://www.namecheap.com). These notes will 139 | configure this domain with a "split horizon," so that the domain is 140 | bound to an external IP address on the open internet by the DNS 141 | provider of your choice, and an internal LAN IP address by the [DNS 142 | service](#dns) on the server. That way, devices will connect with the 143 | server via rouer port forwarding while on the outside internet, and 144 | directly and securely over the LAN while at home or through a VPN 145 | tunnel. 146 | 147 | ### Domain Name DNS Configuration 148 | 149 | Choose a DNS service, either from the Domain Name Registrar you used, or a separate provider. There are [security considerations](https://arstechnica.com/information-technology/2014/02/how-to-run-your-own-e-mail-server-with-your-own-domain-part-1/) for using the domain name registrar as the domain's DNS provider. Personally, I like 150 | [DNS Made Easy](https://dnsmadeeasy.com), and use their [Mail Server Forwarding Service](https://dnsmadeeasy.com/services/mailservices/) for a dynamic IP address. Later, configure `ddclient` to detect and 151 | automatically update server IP address changes with the DNS provider. 152 | 153 | Check your domain for proper configuration (`A` records, `MX` records) and its appearance on any blacklists using tools like 154 | [MXToolbox](http://mxtoolbox.com/) for things like [blacklist lookup](http://mxtoolbox.com/blacklists.aspx), 155 | [SPF lookup](https://mxtoolbox.com/spf.aspx), and [DKIM lookup](https://mxtoolbox.com/dkim.aspx), useful for checking the 156 | [SPF record](#spf) and [DKIM record](#dkim) you're about to enter. 157 | 158 | #### SPF 159 | 160 | Add an SPF `TXT` record to your DNS configuration that tells email MTA's the valid domains that may send email from your domain. Personally, I use an ISP Mail Relay, so my SPF records look like: 161 | ``` 162 | dig @8.8.4.4 domainname.com any 163 | ``` 164 | > `v=spf1 a mx +include:comcast.net -all` 165 | 166 | There is an SPF `TXT` record added for each email domain that has a DNS `A` and `MX` record. 167 | 168 | #### DKIM 169 | 170 | 171 | ## DNS 172 | 173 | ### Copy the previous Server.app's DNS configuration 174 | 175 | Follow krypted's [Export DNS Records from macOS Server](http://krypted.com/mac-os-x-server/export-dns-records-macos-server/) 176 | to export DNS records from the existing server. 177 | 178 | Copy the previous Server.app's `named` configuration to the new server: 179 | ``` 180 | sudo mkdir /Library/Server_v57 181 | sudo rsync -a -e 'ssh -l admin' --exclude rndc.key admin@old-server:/Library/Server/named /Library/Server_v57 182 | ``` 183 | 184 | Keep a copy of the old server's `serveradmin` DNS settings: 185 | 186 | Old server: 187 | ``` 188 | sudo serveradmin -x set dns > serveradmin_v57_dns.plist 189 | sudo chown admin:admin serveradmin_v57_dns.plist 190 | rsync serveradmin_v57_dns.plist admin@new-server:~/Downloads 191 | ``` 192 | 193 | ### Install `bind9` with the latest Python version 194 | 195 | ``` 196 | sudo port -pN install python37 197 | sudo port select --set python3 python37 198 | sudo port -pN install bind9 nmap 199 | ``` 200 | 201 | ### Configure `named` 202 | 203 | New server: 204 | ``` 205 | port notes bind9 206 | sudo rsync -a /Library/Server_v57/named/ /opt/local/var/named 207 | sudo mkdir /opt/local/var/log/named 208 | sudo chown named:named /opt/local/var/named/* /opt/local/var/log/named 209 | sudo rndc-confgen -A hmac-sha512 -a -c /opt/local/var/named/rndc.key -u named 210 | sudo cp /Library/Server_v57/named/named.conf /opt/local/etc 211 | ``` 212 | 213 | ``` 214 | sudo vi /opt/local/etc/named.conf 215 | diff /Library/Server_v57/named/named.conf /opt/local/etc/named.conf 216 | ``` 217 | 218 | Edit in Macports-specific file locatons, use a secure hash for `controls` (not the deprecated `hmac-md5` algorithm used in 219 | Server.app v5.7), specify a `named` pid file, enable log file rotation, and restrict queries to the acl 220 | `com.apple.ServerAdmin.DNS.public` (acl names unchanged from Server.app). 221 | 222 | ``` 223 | 1c1 224 | < include "/Library/Server/named/rndc.key"; 225 | --- 226 | > include "/opt/local/var/named/rndc.key"; 227 | 3c3 228 | < directory "/Library/Server/named"; 229 | --- 230 | > directory "/opt/local/var/named"; 231 | 6a7,9 232 | > allow-query { 233 | > com.apple.ServerAdmin.DNS.public; 234 | > }; 235 | 16a20 236 | > pid-file "/opt/local/var/run/named/named.pid"; 237 | 32c36 238 | < file "/Library/Logs/named.log"; 239 | --- 240 | > file "/opt/local/var/log/named/named.log" versions 10 size 2m; 241 | ``` 242 | 243 | ### Load and test `named` 244 | 245 | ``` 246 | sudo port load bind9 247 | sudo ps -ef | grep named | grep -v grep 248 | sudo lsof -i ':53' 249 | nmap -p 53 new-server 250 | nslookup github.com 127.0.0.1 251 | host github.com 127.0.0.1 252 | dig @new-server github.com 253 | ``` 254 | 255 | This provides a solid name server for the LAN. It can also be modified for fancier options like 256 | [Hidden Master](https://www.c0ffee.net/blog/dns-hidden-master/) DNS with DNSSEC, and even a vanity 257 | name server. 258 | 259 | 260 | ## Network Configuration 261 | 262 | Assign `new-server` a fixed IP address on the LAN with a router DHCP reservation, e.g. `10.0.1.3`. 263 | * System Preferences.app>Network>Interface>Advanced…>TCP/IP>Configure IPv4: `Manually`, IPv4 Address: `10.0.1.3` 264 | * System Preferences.app>Network>Interface>Advanced…>DNS>DNS Servers: + `127.0.0.1` 265 | * System Preferences.app>Network>Interface>Advanced…>DNS>Search Domains: + `new-server.tld` (assuming that your DNS has this zone) 266 | * Ultimately, configure the router to use DNS server `10.0.1.3` so that any device on the LAN uses `new-server` as its DNS server. 267 | 268 | 269 | Make sure that hostname lookups [FQDN] and reverse lookups for `new-server` point to each other: 270 | ``` 271 | host new-server.domainname.tld 272 | host 10.0.1.3 273 | ``` 274 | 275 | Server.app on `new-server`:
276 | Server.app>Open Directory> Toggle OD off & on and verify that the OD Master is running properly with the new localhost DNS server. 277 | 278 | ## Web 279 | 280 | Follow the 281 | [macOS Server Service Migration Guide](https://developer.apple.com/support/macos-server/macOS-Server-Service-Migration-Guide.pdf) to create a localhost macOS Web server that works with the new Server.app's **Profile Manager**. The challenge: 282 | 283 | First, stop all services that want to bind to `http` port 80 and `https` post 443: 284 | ``` 285 | sudo apachectl stop 286 | sudo /Applications/Server.app/Contents/ServerRoot/usr/sbin/serveradmin stop devicemgr 287 | ``` 288 | 289 | Confirm the following breakage by browsing to http://localhost and https://new-server.domainname.tld/mydevices. 290 | 291 | These commands launch the macOS web server, but break Profile Manager 292 | ``` 293 | sudo apachectl start 294 | sudo /Applications/Server.app/Contents/ServerRoot/usr/sbin/serveradmin start devicemgr 295 | ``` 296 | 297 | These commands launch Profile Manager, but break the macOS web server: 298 | ``` 299 | sudo /Applications/Server.app/Contents/ServerRoot/usr/sbin/serveradmin start devicemgr 300 | sudo apachectl start 301 | ``` 302 | 303 | Break this issue into four steps: 304 | * Step 0: `Host` a basic native macOS web page using the default `apachectl` settings 305 | * Step 1: `VirtualHost` a native macOS web page in a specific, non-`Default` `/Library/WebServer/Sites` directory 306 | * Step 2: Copy Server.app v.5.7's Configuration and Website Data per the [macOS Server Service Migration Guide](https://developer.apple.com/support/macos-server/macOS-Server-Service-Migration-Guide.pdf) 307 | * Step 3: Modify Server.app v.5.8's `/Library/Server/Web/Config/Proxy/apache_serviceproxy.conf` or `/Library/Server/Web/Config/apache2/httpd_devicemanagement.conf` to host a web page the same page on port 80 (the first of these methods will also work for https port 443) 308 | 309 | ### `apachectl`-based 310 | 311 | #### Step 0: `Host` a basic native macOS web page using the default `apachectl` settings 312 | ``` 313 | sudo apachectl start 314 | open -a Safari http://localhost 315 | ``` 316 | 317 | #### Step 1: `VirtualHost` a native macOS web page in `/Library/WebServer/Sites/proxy.domainname.tld` 318 | ``` 319 | sudo mkdir /etc/apache2/sites 320 | sudo vi /etc/apache2/httpd.conf 321 | ``` 322 | >`Include /private/etc/apache2/sites/*.conf` 323 | 324 | If you've configured `named` to create the zone and domain `proxy.domainname.private`, this configuration file serve pages from http://proxy.domainname.private, e.g. http://proxy.domainname.private/proxy.pac. This `.conf` file is from Step 2 below. 325 | 326 | `/etc/apache2/sites/0000_127.0.0.1_80_proxy.domainname.private.conf` 327 | ``` 328 | 329 | ServerName proxy.domainname.private 330 | ServerAdmin admin@domainname.tld 331 | DocumentRoot "/Library/WebServer/Sites/proxy.domainname.private" 332 | 333 | DirectoryIndex index.html 334 | 335 | CustomLog /var/log/apache2/access_log combinedvhost 336 | ErrorLog /var/log/apache2/error_log 337 | 338 | MSTEngine Off 339 | MSTCipherSuite HIGH, MEDIUM 340 | MSTProtocolRange TLSv1.2 TLSv1.2 341 | MSTProxyEngine On 342 | MSTProxyProtocolRange TLSv1.2 TLSv1.2 343 | 344 | 345 | Options All -Indexes -ExecCGI -Includes +MultiViews 346 | AllowOverride None 347 | Require all granted 348 | 349 | 350 | DAV Off 351 | 352 | # 353 | # Require all denied 354 | # ErrorDocument 403 /customerror/websitesoff403.html 355 | # 356 | 357 | 358 | ``` 359 | 360 | To avoid caching issues, restart the web server using `apachectl stop`/`start`: 361 | ``` 362 | sudo apachectl configtest ; sudo apachectl stop ; sudo apachectl start ; sleep 1 ; nmap -p 80 localhost 363 | ``` 364 | 365 | #### Step 2: Copy Server.app v.5.7's Configuration and Website Data 366 | 367 | This almost works up to (probably) TLS configuration details. It's a good exercise to run through to understand what may be required in Step 3. Put this configuration in the directory `/etc/apache2/Server_v57` and promote it if it's ever working and useful. 368 | 369 | New server: 370 | ``` 371 | sudo rsync -a -e 'ssh -l admin' admin@old-server:/Library/Server/Web /Library/Server_v57 372 | ``` 373 | 374 | Follow the detailed instructions in [macOS Server Service Migration Guide](https://developer.apple.com/support/macos-server/macOS-Server-Service-Migration-Guide.pdf): 375 | ``` 376 | sudo rsync -a /Library/Server_v57/Web/Data/Sites /Library/WebServer/ 377 | find /Library/WebServer/Sites -type l -name 'default.html.*' -exec ls -l {} ';' 378 | find /Library/WebServer/Sites -type l -name 'default.html.*' -exec sudo rm {} ';' 379 | sudo cp -p /Library/WebServer/Documents/index.html.en /Library/WebServer/Sites/Default 380 | sudo mkdir /etc/apache2/Server_v57 381 | sudo cp -p /Library/Server_v57/Web/Config/apache2/httpd_server_app.conf /etc/apache2/Server_v57 382 | sudo mkdir /etc/apache2/Server_v57/sites 383 | sudo rsync -a /Library/Server_v57/Web/Config/apache2/sites/*.conf /etc/apache2/Server_v57/sites 384 | find /etc/apache2/Server_v57/sites -name '*.conf' -exec sudo sed -i '' 's/DocumentRoot "\/Library\/Server\/Web\/Data\/Sites\/Default"/DocumentRoot "\/Library\/WebServer\/Sites\/Default"/' {} ';' 385 | find /etc/apache2/Server_v57/sites -name '*.conf' -exec sudo sed -i '' 's/Directory "\/Library\/Server\/Web\/Data\/Sites\/Default"/Directory "\/Library\/WebServer\/Sites\/Default"/' {} ';' 386 | find /etc/apache2/Server_v57/sites -name '*.conf' -exec sudo sed -i '' 's///' {} ';' 387 | sudo sed -E -i '' 's/Listen[[:space:]]127.0.0.1:34543/Listen *:443/' /etc/apache2/Server_v57/sites/virtual_host_global.conf 388 | sudo sed -E -i '' 's/Listen[[:space:]]127.0.0.1:34580/Listen *:80/' /etc/apache2/Server_v57/sites/virtual_host_global.conf 389 | sudo mv /etc/apache2/Server_v57/sites/0000_127.0.0.1_34543_.conf /etc/apache2/Server_v57/sites/0000_127.0.0.1_443_.conf 390 | sudo mv /etc/apache2/Server_v57/sites/0000_127.0.0.1_34580_.conf /etc/apache2/Server_v57/sites/0000_127.0.0.1_80_.conf 391 | find /etc/apache2/Server_v57 -name '*.conf' -exec sudo sed -E -i '' 's/Include[[:space:]]+\/Library\/Server\/Web\/Config\/apache2\/sites\//Include \/etc\/apache2\/Server_v57\/sites\//' {} ';' 392 | ``` 393 | 394 | Now edit these `.conf` files line-by-line, following the `diff`'s in the [macOS Server Service Migration Guide](https://developer.apple.com/support/macos-server/macOS-Server-Service-Migration-Guide.pdf), and create a symbolic link from `apachectl`'s `httpd.conf` to `httpd_server_app.conf`. 395 | ``` 396 | sudo vi /etc/apache2/Server_v57/sites/0000_127.0.0.1_443_.conf 397 | sudo vi /etc/apache2/Server_v57/sites/0000_127.0.0.1_80_.conf 398 | sudo vi /etc/apache2/Server_v57/httpd_server_app.conf 399 | sudo mv /etc/apache2/httpd.conf /etc/apache2/httpd.conf.orig 400 | sudo ln -s /etc/apache2/Server_v57/httpd_server_app.conf /etc/apache2/httpd.conf 401 | ``` 402 | 403 | Note that the recommended `mod_authnz_od_apple` module to enable should read: 404 | ``` 405 | LoadModule authnz_od_apple_module /usr/libexec/apache2/mod_authnz_od_apple.so 406 | ``` 407 | 408 | A few helpful debugging commands: 409 | ``` 410 | egrep -e '^LoadModule.+SERVER_INSTALL_PATH_PREFIX' /Library/Server_v57/Web/Config/apache2/httpd_server_app.conf 411 | sudo apachectl configtest 412 | sudo less /private/var/log/apache2/error_log 413 | sudo apachectl configtest ; sudo apachectl stop ; sudo apachectl start ; sleep 1 ; nmap -p 80 localhost 414 | ``` 415 | 416 | ### Server.app-based 417 | 418 | #### Step 3: Modify Server.app v.5.8's Apache Configuration to host `proxy.domainname.tld` 419 | 420 | These Server.app Apache configuration files must be re-edited after every Server.app upgrade. 421 | 422 | #### `VirtualHost` Method 423 | 424 | ``` 425 | sudo cp -p /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf.orig 426 | sudo mkdir /Library/Server/Web/Config/Proxy/sites 427 | sudo cp -p /etc/apache2/sites/0000_127.0.0.1_80_proxy.domainname.private.conf /Library/Server/Web/Config/Proxy/sites 428 | ``` 429 | 430 | Add this virtual host to the file `apache_serviceproxy.conf` [before](https://httpd.apache.org/docs/2.4/vhosts/examples.html) 431 | the other `VirtualHost` declarations in this `.conf` file. 432 | ``` 433 | sudo vi /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf 434 | diff /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf.orig /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf 435 | ``` 436 | 437 | ``` 438 | > # Host other virtual hosts; this line must appear first 439 | > Include /Library/Server/Web/Config/Proxy/sites/*.conf 440 | > 441 | ``` 442 | 443 | #### `AliasMatch` Method 444 | 445 | Use a simple `AliasMatch` to serve `*.pac` files over HTTP (whether at http://domainname.tld/proxy.pac or http://proxy.domainname.private/proxy.pac). Note that a router forwarding port 80 to the server will also serve these PAC files to the open internet with this configuration. Rather, only forward port 443 and leave port 80 for the LAN only. 446 | 447 | ``` 448 | sudo cp /Library/Server/Web/Config/apache2/httpd_devicemanagement.conf /Library/Server/Web/Config/apache2/httpd_devicemanagement.conf.orig 449 | sudo vi /Library/Server/Web/Config/apache2/httpd_devicemanagement.conf 450 | diff /Library/Server/Web/Config/apache2/httpd_devicemanagement.conf.orig /Library/Server/Web/Config/apache2/httpd_devicemanagement.conf 451 | ``` 452 | 453 | ``` 454 | 79a80,83 455 | > # Serve *.pac at http://domainname.tld/proxy.pac or http://proxy.domainname.private/proxy.pac 456 | > #AliasMatch ^/([^/]+\.pac)$ /Library/WebServer/Sites/proxy.domainname.private/$1 457 | > 458 | > # See /Library/Server/Web/Config/Proxy/apache_serviceproxy.conf 459 | ``` 460 | 461 | Debug server.app's `.conf`: 462 | ``` 463 | sudo /Applications/Server.app/Contents/ServerRoot/usr/sbin/httpd-server-wrapper -t 464 | sudo less /private/var/log/apache2/service_proxy_error.log 465 | ``` 466 | 467 | ### Apache2 log file rotatation 468 | 469 | This `logrotate` script will rotate the logs generated by the `Profile Manager`-based web server configuration above. It can 470 | easily be modified to an `apachectl`-based configuration. Note that the current Macports port file of `logrotate` appears to 471 | have a broken default launch daemon loader, so `sudo port load logrotate` doesn't work. Per `port notes logrotate`, do this 472 | step by hand: 473 | ``` 474 | sudo vi /opt/local/etc/logrotate.d/serveradmin_web 475 | sudo cp /opt/local/share/logrotate/org.macports.logrotate.plist.example /Library/LaunchDaemons/org.macports.logrotate.plist 476 | sudo launchctl load -w /Library/LaunchDaemons/org.macports.logrotate.plist 477 | ``` 478 | 479 | > `/opt/local/etc/logrotate.d/serveradmin_web` 480 | ``` 481 | /var/log/apache2/access_log /var/log/apache2/error_log /var/log/apache2/*.log { 482 | weekly 483 | missingok 484 | # rotate 52 485 | compress 486 | delaycompress 487 | notifempty 488 | create 640 root admin 489 | sharedscripts 490 | postrotate 491 | ( serveradmin stop devicemgr ; serveradmin start devicemgr ) > /dev/null 2>&1 492 | endscript 493 | } 494 | ``` 495 | 496 | 497 | ## VPN (macOS `vpnd`, L2TP-IPSec-PSK) 498 | 499 | First off, L2TP-IPSec-PSK is [only as strong as the PSK](https://discussions.apple.com/thread/4167809). Certificate-based VPN, 500 | like this [OpenVPN configuration](https://github.com/essandess/macos-openvpn-server) is strongly preferred. I'm including this 501 | migration because: 502 | * It's simple and robust and works with native macOS's `vpnd` 503 | * A strong PSK is easy to generate and use 504 | * If this ever breaks with native macOS tools, it will be easy to modify to work with racoon 505 | * I'm hopeful that someday someone figures out how to modify this approach to certificate-based IPSec, which appears possible just by looking at the defaults in 506 | > `/Applications/Server.app/Contents/ServerRoot/usr/share/servermgrd/bundles/servermgr_vpn.bundle/Contents/Resources/com.apple.RemoteAccessServers.defaults.plist`. 507 | 508 | Apple’s [Server.app migration guide](https://developer.apple.com/support/macos-server/macOS-Server-Service-Migration-Guide.pdf), doesn’t actually cover this VPN migration, in spite of this assertion: 509 | > After migration you’ll have:
510 | > • vpnd as your VPN service
511 | > • The identical configuration as the macOS Server VPN service
512 | > • A launchd job that starts the service after computer restarts 513 | 514 | These steps provide a working `vpnd`-based L2TP-IPSec-PSK VPN service on new Macs. This is based in part on these threads: 515 | * http://unixnme.blogspot.com/2016/05/how-to-setup-l2tp-vpn-server-on-mac-os.html 516 | * https://discussions.apple.com/thread/1229769 517 | 518 | Old server Server.app v.5.7: 519 | ``` 520 | Server.app v5.7>Users>Local Network Users, View: Show System Accounts 521 | Highlight "VPN MPPE Key Access User" 522 | Gear icon on bottom>Export Users… 523 | Save As: ~/Downloads/vpn_0123456789ab.txt 524 | ``` 525 | 526 | ``` 527 | scp -p ~/Downloads/vpn_0123456789ab.txt admin@new-server:~/Downloads 528 | ``` 529 | 530 | New server Server.app v.5.8: 531 | 532 | ``` 533 | Server.app v5.8>Users>Local Network Users, View: Show System Accounts 534 | Gear icon on bottom>Import Users…> Local Network Directory 535 | System Preferences>Sharing>Remote Login> Allow access for: Remove account "VPN MPPE Key Access User" 536 | ``` 537 | 538 | ``` 539 | sudo security add-generic-password -a vpn_0123456789ab -s com.apple.ras -p "vpn_0123456789ab's password" /Library/Keychains/System.keychain 540 | sudo security add-generic-password -a com.apple.ppp.l2tp -s com.apple.net.racoon -T /usr/sbin/racoon -p "SHARED-SECRET-PHRASE" /Library/Keychains/System.keychain 541 | ``` 542 | 543 | **Important:** ***Change this template password and PSK for these accounts using Keychain Access.app in the next step.*** 544 | 545 | New server Keychain Access.app: 546 | ``` 547 | Keychain Access.app>Keychains: System, Category: All Items, Search for "com.apple.ras", double-click, check "Show password" 548 | Add a new, strong password to the account vpn_0123456789ab (not the initial template from above) 549 | Keychain Access.app>Keychains: System, Category: All Items, Search for "com.apple.net.racoon", double-click, check "Show password" 550 | Add a new, very, very strong random PSK to the account com.apple.ppp.l2tp (not the initial template from above) 551 | ``` 552 | 553 | New server Server.app v.5.8: 554 | ``` 555 | Server.app v5.8>Users>Local Network Users, View: Show System Accounts 556 | Highlight "VPN MPPE Key Access User" 557 | Gear icon on bottom>Change Password… 558 | Use the exact same strong password as entered into the Keychain Access.app for account vpn_0123456789ab above. 559 | ``` 560 | 561 | New server: 562 | ``` 563 | sudo mkdir -p /Library/Server_v57/Server\ HD/Library/Preferences/SystemConfiguration 564 | sudo rsync -a -e 'ssh -l admin' admin@old-server:/Library/Preferences/SystemConfiguration/com.apple.RemoteAccessServers.plist /Library/Server_v57/Server\ HD/Library/Preferences/SystemConfiguration 565 | sudo cp -p /Library/Server_v57/Server\ HD/Library/Preferences/SystemConfiguration/com.apple.RemoteAccessServers.plist /Library/Preferences/SystemConfiguration 566 | sudo cp -p /Library/Server_v57/Server\ HD/Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons/com.apple.ppp.l2tp.plist /Library/LaunchDaemons 567 | sudo vi /Library/Preferences/SystemConfiguration/com.apple.RemoteAccessServers.plist # change `VPNHost` hostname, any config changes 568 | sudo launchctl load -w /Library/LaunchDaemons/com.apple.ppp.l2tp.plist 569 | ``` 570 | 571 | Note: This uses Open Directory for authentication. I'd make a beer- or whiskey-based wager that it will work without Open 572 | Directory if the account `vpn_0123456789ab` is added to the `/Local/Default` node in Directory Utility, along with the 573 | appropriate edits to `PSKeyAccounts` in `/Library/Preferences/SystemConfiguration/com.apple.RemoteAccessServers.plist`. 574 | 575 | Debugging: 576 | ``` 577 | sudo -u admin dscl localhost list /LDAPv3/127.0.0.1/Users 578 | sudo -u admin dscl localhost -read /LDAPv3/127.0.0.1/Users/vpn_0123456789ab 579 | ``` 580 | 581 | ## OpenVPN 582 | 583 | See the repo [macOS OpenVPN Server](https://github.com/essandess/macos-openvpn-server). 584 | 585 | 586 | ## Mail 587 | 588 | Build a modern BSD-based mail server for macOS using a postfix+dovecot+solr+rspamd stack. This will integrate modern BSD 589 | tools, PAM authentication on macOS, with the option of using Apple's latest Server.app with **Open Directory** certificate 590 | creation/management, the ability to deploy credentials using the **Profile Manager** MDM, and using, for as long as it or this 591 | Apple service lives, an old macOS Server.app v.5.7 to 592 | [generate APNS Mail/Calendar/Address APNS certificates](https://github.com/st3fan/dovecot-xaps-daemon/issues/46) for push 593 | notifications on mobile devices. Except for APNS, there are good, viable alternatives to all these tools. 594 | 595 | This section roughly follows these BSD- and Linux-based notes: 596 | * *The Book of Postfix*, http://www.postfix.org/documentation.html 597 | * https://wiki.dovecot.org 598 | * https://www.rspamd.com/doc/index.html 599 | * https://www.c0ffee.net/blog/mail-server-guide/ 600 | * https://rspamd.com/doc/quickstart.html 601 | * https://thomas-leister.de/en/mailserver-debian-stretch/ 602 | * https://arstechnica.com/information-technology/2014/02/how-to-run-your-own-e-mail-server-with-your-own-domain-part-1/ 603 | * http://www.purplehat.org/?page_id=4 604 | 605 | ### Copy the previous Server.app's Mail configuration 606 | 607 | Old server: 608 | ``` 609 | ( cd /Library/Server ; sudo tar cfpj ~/Downloads/Mail_Config.tbz ./Mail/Config ) 610 | scp ~/Downloads/Mail_Config.tbz admin@new-server:~/Downloads 611 | ``` 612 | 613 | New server: 614 | ``` 615 | ( cd /Library/Server_v57 ; sudo tar xfpj ~/Downloads/Mail_Config.tbz ) 616 | ``` 617 | 618 | Keep a copy of the old server's `serveradmin` Mail settings (compressed and encrypted): 619 | 620 | Old server: 621 | ``` 622 | sudo serveradmin -x set mail | bzip2 -c > ~/Downloads/serveradmin_v57_mail.plist.bz2 623 | gpg -ac ~/Downloads/serveradmin_v57_mail.plist.bz2 624 | sudo chown admin:admin ~/Downloads/serveradmin_v57_mail.plist.bz2.asc 625 | sudo chmod 640 ~/Downloads/serveradmin_v57_mail.plist.bz2.asc 626 | scp -p ~/Downloads/serveradmin_v57_mail.plist.bz2.asc admin@new-server:~/Downloads 627 | rm ~/Downloads/serveradmin_v57_mail.plist.bz2 ~/Downloads/serveradmin_v57_mail.plist.bz2.asc 628 | ``` 629 | 630 | ### Mail server installation steps 631 | 632 | #### `postfix` 633 | 634 | ##### Install `postfix` 635 | 636 | ``` 637 | port search postfix 638 | port variants postfix 639 | sudo port -pN install postfix +dovecot_sasl +ldap +pcre +postgresql96 +sasl +smtputf8 +tls 640 | port notes postfix 641 | ``` 642 | 643 | Turn of macOS's native `postfix` MTA, if it's running. Leave its 644 | `com.apple.postfix.master` (`man 8 master`) and `com.apple.postfix.newaliases` (`man newaliases`) daemons running, which in any event to turn off would require an 645 | unnecessary cycle of `scrutil disable`, `scrutil enable` in Recovery Mode to handle the SIP protections on these plists: 646 | ``` 647 | sudo launchctl list | grep postfix 648 | # Don't do this, which SIP will prevent anyway: 649 | # sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.postfix.master.plist 650 | ``` 651 | 652 | ##### Configure `postfix` 653 | 654 | Configure `postfix` with an amalgam of modern BSD mail capabilities that also uses the latest Server.app's certificates and 655 | **Open Directory** LDAP authentication. Also configure the web-based configuration and monitoring tools to us 656 | **Profile Manager**'s Apache web server as decribed above in the [Web](#web) section. 657 | 658 | Postfix configuration, though powerful and comprehensive, is also Byzantine and error-prone. The best approach is to build the 659 | foundations step-by-step, changing up to three parameters each time, and reloading to make sure that everything is running 660 | correctly. 661 | 662 | At the end of this section, a sucecssful `postfix` configuration will be able to send email using a simple `sendmail` test. 663 | 664 | ``` 665 | sudo cp -p /opt/local/etc/postfix/main.cf /opt/local/etc/postfix/main.cf.orig 666 | sudo vi /opt/local/etc/postfix/main.cf 667 | sudo port load postfix 668 | # Make sure that PATH points to Macports `/opt/local/sbin/postfix`, not the native macOS `postfix` binary 669 | which postfix 670 | ``` 671 | 672 | Create these directories and files, with appropriate permissions: 673 | ``` 674 | # Logging 675 | sudo mkdir /opt/local/var/log/mail 676 | sudo chmod go-rwx /opt/local/var/log/mail 677 | 678 | # Aliases 679 | sudo newaliases 680 | 681 | # Create your own Diffie-Hellman parameters for TLS Forward Secrecy 682 | sudo -u _postfix openssl dhparam -out /opt/local/var/lib/postfix/dh2048.pem 2048 683 | 684 | # TLS authentication of mail relays (using Comcast as ISP example) 685 | openssl s_client -showcerts -servername smtp.comcast.net -connect smtp.comcast.net:587 -starttls smtp < /dev/null > smtp_comcast_net.pem 686 | # For smtp_tls_CAfile: 687 | vi smtp_comcast_net.pem # delete non-certificate outputs before 1st --- and after last --- 688 | # For smtp_tls_CApath: 689 | # break into three (or the necessary trust chain #) of .crt files delineated by 690 | # '-----BEGIN CERTIFICATE-----' 691 | sudo mkdir -p /opt/local/etc/postfix/etc/certificates 692 | sudo cp smtp_comcast_net.pem [*.crt] /opt/local/etc/postfix/etc/certificates 693 | sudo chgrp -R _postfix /opt/local/etc/postfix/etc 694 | 695 | # SASL authentication for mail relays 696 | sudo mkdir /opt/local/etc/postfix/sasl 697 | sudo vi /opt/local/etc/postfix/sasl/passwd 698 | sudo chgrp -R _postfix /opt/local/etc/postfix/sasl 699 | sudo chmod -R o-rwx /opt/local/etc/postfix/sasl 700 | sudo postmap /opt/local/etc/postfix/sasl/passwd 701 | ``` 702 | 703 | Checking and debugging after every few parameter changes. 704 | ``` 705 | man 5 postconf 706 | sudo vi /opt/local/etc/postfix/main.cf 707 | sudo bash -c 'postfix reload ; sleep 1 ; nmap -p 25 localhost ; lsof -i ":25" ; postfix status ; postfix check' 708 | sendmail -t < ~/mail.txt 709 | sudo less /opt/local/var/log/mail/postfix.log 710 | mailq 711 | # For `sendmail -v` without dovecot set up: 712 | sudo postsuper -d ALL 713 | ``` 714 | 715 | `mail.txt` 716 | ``` 717 | To: me@isp.net 718 | Subject: postfix configuration test 719 | From: admin@domain.tld 720 | 721 | My first SMTP email test. 722 | ``` 723 | 724 | Run postfix in chroot and re-test. 725 | 726 | Site-specific configuration details will appear in the `/opt/local/etc/postfix` directory. 727 | 728 | Add `rspamd` as a milter. 729 | 730 | #### `dovecot` 731 | 732 | ##### Install `dovecot` 733 | ``` 734 | sudo port -pN install dovecot2 +ldap +lucene +solr +postgresql92 735 | sudo port -pN install dovecot2-antispam dovecot2-sieve 736 | sudo port -pN install apache-solr8 737 | ``` 738 | 739 | Note the inconsistency of PostgreSQL versions with `postfix` above. I'm adding the SQL variant "just in case" I need to use 740 | such a database, and will go back and fix later if this necessity arises. 741 | 742 | ##### Configure `dovecot` 743 | 744 | Site-specific configuration details will appear in the `/opt/local/etc/dovecot/conf.d` directory. 745 | * PAM, Kerberos, automated full-text search via Solr, automated spam.ham junkmail training. 746 | 747 | #### `clamav` 748 | 749 | Install and configure `clamav` using the [macOS-clamAV](../macOS-clamAV) repo. 750 | 751 | #### `rspamd` 752 | ##### Install `rspamd` 753 | ``` 754 | sudo port -pN install rspamd dcc 755 | ``` 756 | 757 | ##### Configure `rspamd` 758 | 759 | Site-specific configuration details will appear in the `/opt/local/etc/rspamd/local.d` directory. 760 | * Redis, ClamAV, postfix milter (within chroot) 761 | 762 | #### Configure DKIM in postfix and the DNS records 763 | 764 | ``` 765 | sudo mkdir /opt/local/var/lib/rspamd/dkim 766 | sudo chown _rspamd:_rspamd /opt/local/var/lib/rspamd/dkim 767 | sudo chmod 0750 /opt/local/var/lib/rspamd/dkim 768 | sudo -u _rspamd rspamadm dkim_keygen -k /opt/local/var/lib/rspamd/dkim/domain.tld.dkim.key -s dkim -t ed25519 -d domain.tld 769 | ``` 770 | 771 | #### Test DKIM, DMARC, SPF 772 | 773 | #### Create user-specific sieve scripts 774 | 775 | #### Install APNS configuration using Server.app v5.7 certs 776 | 777 | #### Install mailman 778 | 779 | #### Make sure that this configuration works with Notes 780 | 781 | #### Create S/MIME certs 782 | 783 | 784 | ## Calendar and Contacts 785 | 786 | This process will build an Apple Calendar and Contacts server on macOS **independent** of any prior Server.app installation. References: 787 | * CalendarServer's [QuickStart](https://www.calendarserver.org/QuickStart.html) for a working example. 788 | * [macOS Server Service Migration Guide v1.2](https://developer.apple.com/support/macos-server/macOS-Server-Service-Migration-Guide.pdf) 789 | * https://github.com/apple/ccs-calendarserver/issues/535#issuecomment-489647731 790 | * https://gist.github.com/essandess/3136597a587edc9045d8ae7d75e59e0a 791 | 792 | ### Create the `calendarserver` account, password, install directories 793 | 794 | ``` 795 | # choose a free uid < 500; uid 350 is used here 796 | dscl . -list /Users UniqueID | sort -n -k2 797 | 798 | sudo bash < ~/.profile 852 | 853 | git clone https://github.com/apple/ccs-calendarserver.git 854 | # git clone -b release/CalendarServer-9.3 https://github.com/apple/ccs-calendarserver.git 855 | 856 | cd ccs-calendarserver 857 | 858 | # /opt/local is deprecated, but included for openssl, virtualenv 859 | sh -x < ~/ccs-calendarserver.log 2>&1 870 | ) 871 | PACKAGE_CALENDARSERVER 872 | ``` 873 | 874 | ### Create site-specific directories, configurations, set permissions 875 | 876 | As `calendarserver`: 877 | ``` 878 | # Configuration 879 | mkdir -p /var/calendarserver/Library/CalendarServer/Config 880 | chgrp _calendar /var/calendarserver/Library/CalendarServer/Config 881 | chmod 0750 /var/calendarserver/Library/CalendarServer/Config 882 | 883 | # Logs 884 | mkdir -p /var/calendarserver/Library/CalendarServer/logs 885 | chgrp _calendar /var/calendarserver/Library/CalendarServer/logs 886 | chmod 0750 /var/calendarserver/Library/CalendarServer/logs 887 | 888 | # PostgreSQL 889 | mkdir -p /var/calendarserver/Library/CalendarServer/Data/Database 890 | chgrp -R _calendar /var/calendarserver/Library/CalendarServer/Data 891 | chmod -R 0700 /var/calendarserver/Library/CalendarServer/Data 892 | 893 | # calendarserver config file 894 | vi /var/calendarserver/Library/CalendarServer/Config/calendarserver.plist 895 | 896 | # nginx reverse proxy configuration 897 | mkdir -p /var/calendarserver/Library/CalendarServer/etc 898 | vi /var/calendarserver/Library/CalendarServer/etc/nginx.conf 899 | mkdir -p /var/calendarserver/Library/CalendarServer/etc/nginx_root 900 | vi /var/calendarserver/Library/CalendarServer/etc/nginx_root/default.html # unused, but nginx root is here 901 | openssl dhparam -out /var/calendarserver/Library/CalendarServer/etc/dhparam.pem 4096 902 | 903 | # Launch daemons 904 | mkdir -p /var/calendarserver/Library/CalendarServer/Config/LaunchDaemons 905 | vi /var/calendarserver/Library/CalendarServer/Config/LaunchDaemons/org.calendarserver.calendarserver.plist 906 | vi /var/calendarserver/Library/CalendarServer/Config/LaunchDaemons/org.calendarserver.nginx_proxy.plist 907 | 908 | # ccs-calendarserver's postgres code points to `PSQL = "../postgresql/_root/bin/psql"` 909 | mkdir -p /var/calendarserver/Library/CalendarServer/postgresql 910 | ln -s /opt/local /var/calendarserver/Library/CalendarServer/postgresql/_root 911 | ``` 912 | 913 | As sudoer: 914 | ``` 915 | sudo sh -x <