KDAV with Nginx?
-
Wondering if the experts here can throw in some advice for me.
I have a Traefik 2.3 Reverse Proxy in front of my Kopano Core installation including KDAV.
The Traefik reverse proxy rewrites anything with .well_known/{card,cal}dav to the KDAV server.php which is hosted via Nginx and PHP-FPM.
I can visit via my own web browser to
dav.example.com
being met with basic authentication to where I am able to enter my Kopano username and password with success being presented with the SabreDAV interface.Where things go sideways is trying to connect a client to the KDAV installation - Whether I use automatic configuration (based on trying to get information via
.well-known
hints) or manual where I am requestinghttps://dav.example.com/calendars/username/Calendar
it fails. Looking at the web server logs the client issues aPROPFIND
request to the server and then responds with a200 OK
response, with no details to give any more hints.Request: <d:propfind xmlns:d="DAV:"><d:prop><d:current-user-principal /></d:prop></d:propfind> Response: <?xml version="1.0" encoding="utf-8" ?> <D:multistatus xmlns:D="DAV:"> <D:response> <D:href>/</D:href> <D:propstat> <D:prop> </D:prop> <D:status>HTTP/1.1 200 OK</D:status> </D:propstat> </D:response> </D:multistatus>
I’m willing to bet that there’s something to do with my Nginx configuration here, so figured I’d let others see how I have configured it to see if anything jumps out as wrong, or if there is a better way to do this.
site.conf
server { server_name dav.example.com; listen 80; root /usr/share/kdav; index server.php; dav_methods PUT DELETE MKCOL COPY MOVE; dav_ext_methods PROPFIND OPTIONS; create_full_put_path on; dav_access user:rw group:rw all:r; location /server.php { access_log /logs/nginx/kdav-access.log; error_log /logs/nginx/kdav-error.log; try_files $uri $uri/ /?$args; location ~ \.php(/|$) { include /etc/nginx/nginx.conf.d/php-fpm.conf; fastcgi_split_path_info ^(.+?\.php)(/.+)$; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_index server.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } } }
Alternatively, here’s how it looks with curl.
curl -Lv -X PROPFIND --header "Depth: 0" -u "username:password" https://dav.example.com/.well-known/carddav * Trying 111.222.111.222:443... * Connected to dav.example.com (111.222.111.222) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/ssl/certs/ca-certificates.crt CApath: none * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 * ALPN, server accepted to use h2 * Server certificate: * subject: CN=dav.example.com * start date: Oct 9 15:26:22 2020 GMT * expire date: Jan 7 15:26:22 2021 GMT * subjectAltName: host "dav.example.com" matched cert's "dav.example.com" * issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3 * SSL certificate verify ok. * Using HTTP2, server supports multi-use * Connection state changed (HTTP/2 confirmed) * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 * Server auth using Basic with user 'username' * Using Stream ID: 1 (easy handle 0x559b6e11aa70) > PROPFIND /.well-known/carddav HTTP/2 > Host: dav.example.com > authorization: Basic ZGF2ZWNvbnJveTpUaXJlZG9mSVRcITIwMTk= > user-agent: curl/7.72.0 > accept: */* > depth: 0 > * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): * Connection state changed (MAX_CONCURRENT_STREAMS == 250)! < HTTP/2 308 < location: https://dav.example.com/ < vary: Accept-Encoding < content-type: text/plain; charset=utf-8 < content-length: 18 < date: Fri, 09 Oct 2020 20:32:10 GMT < * Ignoring the response-body * Connection #0 to host dav.example.com left intact * Issue another request to this URL: 'https://dav.example.com/' * Found bundle for host dav.example.com: 0x559b6e114760 [can multiplex] * Re-using existing connection! (#0) with host dav.example.com * Connected to dav.example.com (111.222.111.222) port 443 (#0) * Server auth using Basic with user 'username' * Using Stream ID: 3 (easy handle 0x559b6e11aa70) > PROPFIND / HTTP/2 > Host: dav.example.com > authorization: Basic ZGF2ZWNvbnJveTpUaXJlZG9mSVRcITIwMTk= > user-agent: curl/7.72.0 > accept: */* > depth: 0 > < HTTP/2 207 < content-type: text/xml; charset=utf-8 < date: Fri, 09 Oct 2020 20:32:10 GMT < server: nginx/1.19.2 < vary: Accept-Encoding < content-length: 424 < <?xml version="1.0" encoding="utf-8" ?> <D:multistatus xmlns:D="DAV:"> <D:response> <D:href>/</D:href> <D:propstat> <D:prop> <D:displayname>/</D:displayname> <D:getlastmodified>Fri, 09 Oct 2020 20:09:04 GMT</D:getlastmodified> <D:resourcetype><D:collection/></D:resourcetype> <D:lockdiscovery/> <D:supportedlock> </D:supportedlock> </D:prop> <D:status>HTTP/1.1 200 OK</D:status> </D:propstat> </D:response> </D:multistatus> * Connection #0 to host dav.example.com left intact
Even trying to go directly to the calendar as recommended in another thread:
URL: https://dav.example.com/calendars/username/calendar/ (PROPFIND) Request: <d:propfind xmlns:d="DAV:"><d:prop><d:current-user-principal /></d:prop></d:propfind> Response: <?xml version="1.0" encoding="utf-8" ?> <D:multistatus xmlns:D="DAV:"> <D:response> <D:href>/</D:href> <D:propstat> <D:prop> </D:prop> <D:status>HTTP/1.1 200 OK</D:status> </D:propstat> </D:response> </D:multistatus>
KDAV
config.php
<?php define('MAPI_SERVER', 'file:///var/run/kopano/server.sock'); define('SABRE_AUTH_REALM', 'DAV'); define('DAV_ROOT_URI', '/'); define('SYNC_DB', 'sqlite:/data/kdav/syncstate.db'); define('MAX_SYNC_ITEMS', 1000); define('DEVELOPER_MODE', TRUE);
When setting
DEVELOPER_MODE
toFalse
I get the following in my logs and on screen when visiting https://dav.example.com thru a browser.( ! ) Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in /usr/share/kdav/vendor/sabre/dav/lib/CalDAV/ICSExportPlugin.php on line 321 Call Stack # Time Memory Function Location 1 0.0013 395768 {main}( ) .../server.php:0 2 0.1763 1101416 spl_autoload_call ( ) .../server.php:92 3 0.1763 1101472 Composer\Autoload\ClassLoader->loadClass( ) .../server.php:92 4 0.1763 1101584 Composer\Autoload\includeFile( ) .../ClassLoader.php:322 3.2.2 Sabre\DAV\Exception\NotImplemented There was no plugin in the system that was willing to handle this GET method. Enable the Browser plugin to get a better result here.
KDAV:
master
| Nginx1.19.3
| PHP7.3.20
| Traefik2.3.1
Any help would be appreciated!