# nginx reverse proxy for CalendarServer # run command: # sudo nginx -g "daemon off;" -p @CALENDARSERVERDIR@/Library/CalendarServer/logs -c @CALENDARSERVERDIR@/Library/CalendarServer/etc/nginx.conf user @CALENDARSERVERUSER@ _calendar; worker_processes auto; error_log ../logs/nginx_error.log; #error_log ../logs/error.log notice; #error_log ../logs/error.log info; pid ../run/nginx.pid; events { worker_connections 1024; } # To use macOS Server v5.10 generated certificates: # # 0. Identify the file that looks like @host@.@domain@.@tld@.@CERTIFICATE_SHA1@.cert.pem # and verify its issue date and issuer "* Intermediate CA" with: # # $ ls /etc/certificates # $ openssl x509 -inform pem -in /etc/certificates/@host@.@domain@.@tld@.@CERTIFICATE_SHA1@.cert.pem -text -noout # $ openssl x509 -noout -fingerprint -sha1 -inform pem -in openssl x509 -noout -fingerprint -sha1 -inform pem -in /etc/certificates/@host@.@domain@.@tld@.@CERTIFICATE_SHA1@.cert.pem | tr -d ':' | sed -e 's|^SHA1 Fingerprint=||' | tr -d ':' | sed -e 's|^SHA1 Fingerprint=||' # # Use this SHA1 to obtain the passphraphse for this certificate's private key from: # # Keychain Access.app> System> Search for this SHA1> # Double-click "Mac OS X Server certificate management"> Show password # # 1. Create a secure storage for this passphrase and desctrypted key: # # $ sudo mkdir -p @PREFIX@/etc/certificates/private # $ sudo chmod 0700 @PREFIX@/etc/certificates/private # $ sudo vi @PREFIX@/etc/certificates/private/@host@.@domain@.@tld@.@CERTIFICATE_SHA1@.key.pem.passphrase /etc/certificates/private # $ sudo chmod -R go-rwx @PREFIX@/etc/certificates/private # # `ssl_key_password` wasn't working on my install, so put the decrypted key in @PREFIX@/etc/certificates/private # # $ sudo openssl rsa -in /etc/certificates/@host@.@domain@.@tld@.@CERTIFICATE_SHA1@.key.pem -out @PREFIX@/etc/certificates/private/@host@.@domain@.@tld@.@CERTIFICATE_SHA1@.key.pem.decrypted -passin file:@PREFIX@/etc/certificates/private/@host@.@domain@.@tld@.@CERTIFICATE_SHA1@.key.pem.passphrase # $ sudo chmod -R go-rwx @PREFIX@/etc/certificates/private # # 2. Link to the existing TLS chain. # # $ sudo ln -s /etc/certificates/@host@.@domain@.@tld@.@CERTIFICATE_SHA1@.cert.pem @PREFIX@/etc/certificates # $ sudo ln -s /etc/certificates/@host@.@domain@.@tld@.@CERTIFICATE_SHA1@.key.pem @PREFIX@/etc/certificates # $ sudo ln -s /etc/certificates/@host@.@domain@.@tld@.@CERTIFICATE_SHA1@.chain.pem @PREFIX@/etc/certificates # $ sudo ln -s /etc/certificates/@host@.@domain@.@tld@.@CERTIFICATE_SHA1@.concat.pem @PREFIX@/etc/certificates # # 3. Confirm restricted permissions: # # $ ls -l @PREFIX@/etc/certificates # $ sudo ls -l @PREFIX@/etc/certificates/private # # 4. Finally, reconfigure dovecot's conf.d/10-ssl.conf, postfix's master.cf, # and, if installed, calendar-contacts-server's proxy nginx.conf: # # $ sudo vi @PREFIX@/etc/dovecot/conf.d/10-ssl.conf # $ sudo vi @PREFIX@/etc/postfix/main.cf # $ sudo vi @PREFIX@/var/calendarserver/Library/CalendarServer/etc/nginx.conf http { include @PREFIX@/etc/nginx/mime.types; default_type application/octet-stream; server_tokens off; #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; access_log ../logs/nginx_access.log; client_max_body_size 20M; upstream caldavd_secured { server unix:@CALENDARSERVERDIR@/Library/CalendarServer/run/caldavd_requests/secured.sock; } upstream caldavd_unsecured { server unix:@CALENDARSERVERDIR@/Library/CalendarServer/run/caldavd_requests/unsecured.sock; } # Reverse proxy for CalendarServer server { root nginx_root; # empty except for (unused) default.html # TLS listen @host@.@domain@.@tld@:8443 ssl; # calDAV listen @host@.@domain@.@tld@:8843 ssl; # cardDAV server_name @host@.@domain@.@tld@; # ssl_certificate must contain the cert:intermed[:root CA] chain ssl_certificate @PREFIX@/etc/certificates/@TLS_CERTIFICATE_NAME@.chain.pem; ssl_certificate_key @PREFIX@/etc/certificates/private/@TLS_CERTIFICATE_NAME@.key.pem.decrypted; # use modern crypto # https://wiki.mozilla.org/Security/Server_Side_TLS # https://cipherli.st ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256; ssl_prefer_server_ciphers on; ssl_dhparam dhparam.pem; ssl_ecdh_curve secp384r1; ssl_session_timeout 10m; ssl_session_cache shared:SSL:10m; ssl_session_tickets off; # nginx: [warn] "ssl_stapling" ignored, no OCSP responder URL in the certificate # ssl_stapling on; # ssl_stapling_verify on; location / { proxy_pass http://caldavd_secured; # proxy_pass https://localhost:8443; # caldav issues "Bad Request 404" without turning off "Connection: close" header and setting HTTP/1.1 proxy_set_header Connection ""; proxy_http_version 1.1; # proxy_set_header Host $host; # the proxy is a unix socket proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2; proxy_ssl_ciphers HIGH:!aNULL:!MD5; # proxy_ssl_certificate @CALENDARSERVERDIR@/Source/github/apple/ccs-calendarserver.build/twistedcaldav/test/data/cert.pem; # proxy_ssl_certificate_key @CALENDARSERVERDIR@/Source/github/apple/ccs-calendarserver.build/twistedcaldav/test/data/server.pem; # proxy_ssl_trusted_certificate @CALENDARSERVERDIR@/Source/github/apple/ccs-calendarserver.build/twistedcaldav/test/data/cert.pem; proxy_ssl_server_name on; # proxy_ssl_verify on; # turn this off for expired test certificate proxy_ssl_verify off; proxy_ssl_verify_depth 2; proxy_ssl_session_reuse on; } } server { root nginx_root; # empty except for (unused) default.html # HTTP listen @host@.@domain@.@tld@:8008; # calDAV listen @host@.@domain@.@tld@:8800; # cardDAV server_name @host@.@domain@.@tld@; # quick alternate test # ncat -vlk 8800 -c 'ncat -U /path/to/unix_socket.sock' location / { proxy_pass http://caldavd_unsecured; # proxy_pass http://localhost:8008; # caldav issues "Bad Request 404" without turning off "Connection: close" header and setting HTTP/1.1 proxy_set_header Connection ""; proxy_http_version 1.1; # proxy_set_header Host $host; } } }