mholt / caddy-webdav Goto Github PK
View Code? Open in Web Editor NEWWebDAV handler module for Caddy
License: Apache License 2.0
WebDAV handler module for Caddy
License: Apache License 2.0
Based on the documents and my test, it seems like WebDAV has to be served in a different path with directory listing, one cannot have them both functioning under the same path, is that correct?
As an Apache & Nginx user, I felt quite surprised, as it is an expected behaviour to have them working in the same path.
Cheers,
Jayden
Hello,
I can not build / install the Webdav plugin for Docker.
I've tried numerous times.
I've tried to update my GO version with this tutorial:
https://go.dev/doc/install
This is the error message:
18.94 go: github.com/mholt/[email protected] requires go >= 1.22.0 (running go 1.21.10; GOTOOLCHAIN=local) 18.94 2024/05/22 02:58:06 [FATAL] exit status 1
go version:
go version go1.22.3 linux/amd64
Please help.
I'm having some trouble setting this up. I want:
How can I do this?
I tried this, but it didn't work:
drive.example.com {
webdav /dav/* {
root /srv/files
prefix /dav
}
}
It gives me a blank screen when I navigate to drive.example.com/dav.
I am trying to setup a multi-user WebDAV configuration.
I have things configured in the Caddyfile as follows:
*.example.com {
...
@storage host storage.example.com
handle @storage {
basicauth {
username1 <hashed_pw>
username2 <hashed_pw>
}
root * /path/to/webdav/{http.auth.user.id}
webdav
}
...
}
Which is working, but the individual users see the root of the webdav path when they connect (i.e. /path/to/webdav/
, not /path/to/webdav/user1
as expected.)
It appears someone else ran into the same issue, as posted here:
https://caddy.community/t/multiple-users-with-different-roots-in-webdav/19502
But they never replied to the debugging suggestions.
As suggested, I turned on debugging and tried the custom X-Auth header. From that, I can see the username from {http.auth.user.id}
as expected in the response.
Other than that, there don't appear to be any debug messages indicating a problem.
I'm not hugely familiar with go, but I also took a look at the Caddyfile parsing code for this module, and it all looks pretty straightforward and boiler-platey, so it doesn't seem likely the issue would be there.
Any ideas?
Hello,
I tired using caddy webdav plugin as backend for the excellent rclone project, and indeed was working somewhat fine for small files, however i discovered that there is a problem related to the RANGE request and downloads failing for big files and having to-download that lead me to rclone issue #4459 comment by @ncw, it seems there is problem related to the range requests in webdav plugin causing the multipart download files to not send correct range the file real size is 875607573 or 836M. As far as i know single request downloads works fine.
2022/12/04 13:03:39 DEBUG : rclone: Version "v1.60.0" starting with parameters ["rclone" "copy" "caddy:/files/test.mp4" "." "-P" "-vvv"]
2022/12/04 13:03:39 DEBUG : Creating backend with remote "caddy:/files/test.mp4"
2022/12/04 13:03:39 DEBUG : Using config file from "/home/user/.config/rclone/rclone.conf"
2022/12/04 13:03:39 DEBUG : found headers:
2022/12/04 13:03:40 DEBUG : fs cache: adding new entry for parent of "caddy:/files/test.mp4", "caddy:files"
2022/12/04 13:03:40 DEBUG : Creating backend with remote "."
2022/12/04 13:03:40 DEBUG : fs cache: renaming cache item "." to be canonical "/home/user/tests"
2022-12-04 13:03:40 DEBUG : test.mp4: Need to transfer - File not found at Destination
2022-12-04 13:03:40 DEBUG : test.mp4: Starting multi-thread copy with 3 parts of size 278.375Mi
2022-12-04 13:03:40 DEBUG : test.mp4: multi-thread copy: stream 3/3 (583794688-875607573) size 278.294Mi starting
2022-12-04 13:03:40 DEBUG : test.mp4: multi-thread copy: stream 2/3 (291897344-583794688) size 278.375Mi starting
2022-12-04 13:03:40 DEBUG : test.mp4: multi-thread copy: stream 1/3 (0-291897344) size 278.375Mi starting
2022-12-04 13:04:00 DEBUG : test.mp4: multi-thread copy: stream 1/3 (0-291897344) size 278.375Mi finished
2022-12-04 13:04:00 DEBUG : test.mp4: multi-thread copy: stream 2/3 (291897344-583794688) size 278.375Mi finished
2022-12-04 13:04:17 DEBUG : test.mp4: multi-thread copy: stream 3/3 failed: multipart copy: wrote 875607573 bytes but expected to write 291812885
2022-12-04 13:04:17 ERROR : test.mp4: Failed to copy: multipart copy: wrote 875607573 bytes but expected to write 291812885
2022-12-04 13:04:17 ERROR : Attempt 1/3 failed with 1 errors and: multipart copy: wrote 875607573 bytes but expected to write 291812885
2022-12-04 13:04:18 DEBUG : test.mp4: Sizes differ (src 875607573 vs dst 1459402261)
2022-12-04 13:04:18 DEBUG : test.mp4: Starting multi-thread copy with 3 parts of size 278.375Mi
2022-12-04 13:04:18 DEBUG : test.mp4: multi-thread copy: stream 3/3 (583794688-875607573) size 278.294Mi starting
2022-12-04 13:04:18 DEBUG : test.mp4: multi-thread copy: stream 1/3 (0-291897344) size 278.375Mi starting
2022-12-04 13:04:18 DEBUG : test.mp4: multi-thread copy: stream 2/3 (291897344-583794688) size 278.375Mi starting
2022-12-04 13:04:33 DEBUG : test.mp4: multi-thread copy: stream 2/3 (291897344-583794688) size 278.375Mi finished
2022-12-04 13:04:33 DEBUG : test.mp4: multi-thread copy: stream 3/3 (583794688-875607573) size 278.294Mi finished
2022-12-04 13:04:33 DEBUG : test.mp4: multi-thread copy: stream 1/3 (0-291897344) size 278.375Mi finished
2022-12-04 13:04:33 DEBUG : test.mp4: Finished multi-thread copy with 3 parts of size 278.375Mi
2022-12-04 13:04:33 INFO : test.mp4: Multi-thread Copied (replaced existing)
2022-12-04 13:04:33 ERROR : Attempt 2/3 succeeded
Transferred: 2.175 GiB / 2.175 GiB, 100%, 47.549 MiB/s, ETA 0s
Transferred: 1 / 1, 100%
Elapsed time: 53.3s
2022/12/04 13:04:33 INFO :
Transferred: 2.175 GiB / 2.175 GiB, 100%, 47.549 MiB/s, ETA 0s
Transferred: 1 / 1, 100%
Elapsed time: 53.3s
2022/12/04 13:04:33 DEBUG : 4 go routines active
v2.6.2 h1:wKoFIxpmOJLGl3QXoo6PNbYvGW4xLEgo32GPBEjWL8o=
$ caddy list-modules
admin.api.load
admin.api.metrics
admin.api.pki
admin.api.reverse_proxy
caddy.adapters.caddyfile
caddy.config_loaders.http
caddy.listeners.http_redirect
caddy.listeners.tls
caddy.logging.encoders.console
caddy.logging.encoders.filter
caddy.logging.encoders.filter.cookie
caddy.logging.encoders.filter.delete
caddy.logging.encoders.filter.hash
caddy.logging.encoders.filter.ip_mask
caddy.logging.encoders.filter.query
caddy.logging.encoders.filter.regexp
caddy.logging.encoders.filter.rename
caddy.logging.encoders.filter.replace
caddy.logging.encoders.json
caddy.logging.writers.discard
caddy.logging.writers.file
caddy.logging.writers.net
caddy.logging.writers.stderr
caddy.logging.writers.stdout
caddy.storage.file_system
events
http
http.authentication.hashes.bcrypt
http.authentication.hashes.scrypt
http.authentication.providers.http_basic
http.encoders.gzip
http.encoders.zstd
http.handlers.acme_server
http.handlers.authentication
http.handlers.copy_response
http.handlers.copy_response_headers
http.handlers.encode
http.handlers.error
http.handlers.file_server
http.handlers.headers
http.handlers.map
http.handlers.metrics
http.handlers.push
http.handlers.request_body
http.handlers.reverse_proxy
http.handlers.rewrite
http.handlers.static_response
http.handlers.subroute
http.handlers.templates
http.handlers.tracing
http.handlers.vars
http.matchers.expression
http.matchers.file
http.matchers.header
http.matchers.header_regexp
http.matchers.host
http.matchers.method
http.matchers.not
http.matchers.path
http.matchers.path_regexp
http.matchers.protocol
http.matchers.query
http.matchers.remote_ip
http.matchers.vars
http.matchers.vars_regexp
http.precompressed.br
http.precompressed.gzip
http.precompressed.zstd
http.reverse_proxy.selection_policies.cookie
http.reverse_proxy.selection_policies.first
http.reverse_proxy.selection_policies.header
http.reverse_proxy.selection_policies.ip_hash
http.reverse_proxy.selection_policies.least_conn
http.reverse_proxy.selection_policies.random
http.reverse_proxy.selection_policies.random_choose
http.reverse_proxy.selection_policies.round_robin
http.reverse_proxy.selection_policies.uri_hash
http.reverse_proxy.transport.fastcgi
http.reverse_proxy.transport.http
http.reverse_proxy.upstreams.a
http.reverse_proxy.upstreams.multi
http.reverse_proxy.upstreams.srv
pki
tls
tls.certificates.automate
tls.certificates.load_files
tls.certificates.load_folders
tls.certificates.load_pem
tls.certificates.load_storage
tls.client_auth.leaf
tls.get_certificate.http
tls.get_certificate.tailscale
tls.handshake_match.remote_ip
tls.handshake_match.sni
tls.issuance.acme
tls.issuance.internal
tls.issuance.zerossl
tls.stek.distributed
tls.stek.standard
Standard modules: 99
caddy.logging.encoders.formatted
caddy.logging.encoders.transform
dns.providers.cloudflare
http.handlers.webdav
layer4
layer4.handlers.echo
layer4.handlers.proxy
layer4.handlers.proxy_protocol
layer4.handlers.socks5
layer4.handlers.subroute
layer4.handlers.tee
layer4.handlers.throttle
layer4.handlers.tls
layer4.matchers.http
layer4.matchers.ip
layer4.matchers.proxy_protocol
layer4.matchers.socks4
layer4.matchers.socks5
layer4.matchers.ssh
layer4.matchers.tls
layer4.matchers.xmpp
layer4.proxy.selection_policies.first
layer4.proxy.selection_policies.ip_hash
layer4.proxy.selection_policies.least_conn
layer4.proxy.selection_policies.random
layer4.proxy.selection_policies.random_choose
layer4.proxy.selection_policies.round_robin
tls.handshake_match.alpn
Non-standard modules: 28
Unknown modules: 0
Hi,
Thanks for the awesome work. There is an issue trouble me when I use this module. Large file can not be upload to the webdav server even caddy
and caddy-webdav
start normally. However, small file can be uploaded and deleted, and large file can alse be deleted. And all is well if basicauth
is not set, similar to the issue mentioned here. Here is my detailed info:
v2.4.6 h1:HGkGICFGvyrodcqOOclHKfvJC0qTU7vny/7FhYp9hNw=
Caddyfile
{
email [email protected]
order webdav before file_server
}
dav.mydomain.com {
log {
output file /var/log/caddy/caddy.log
}
header {
Access-Control-Allow-Origin *
Access-Control-Allow-Credentials true
Access-Control-Allow-Methods "GET, HEAD, POST, PUT, OPTIONS, MOVE, DELETE, COPY, LOCK, UNLOCK, PROPFIND, MKCOL"
Access-Control-Allow-Headers "Authorization,DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Accept-Charset,X-Accept,origin,accept,if-match,destination,overwrite,X-CustomHeader"
Access-Control-Expose-Headers "ETag"
Access-Control-Max-Age 1728000
}
file_server
webdav {
root /data/webdav
}
basicauth {
username JDJhJDE0JGxYYWhxUVd6a1RRd01PS2xtNnBkNHUzUllqenFaSGFib1Zid1BFaGNRSmpOLktXNXBJbGhH
}
}
file1
is 5 bytes, file2
is 18.6 MB and file3
is 18.6 MB.{"level":"error","ts":1649603015.3900425,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_addr":"my_ip:16834","proto":"HTTP/1.1","method":"PUT","host":"dav.mydomain","uri":"/zotero/file1","headers":{"Content-Type":["application/octet-stream"],"Content-Length":["5"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"","proto_mutual":true,"server_name":"dav.mydomain"}},"common_log":"my_ip - - [10/Apr/2022:15:03:35 +0000] \"PUT /zotero/file1 HTTP/1.1\" 401 0","user_id":"","duration":0.000256805,"size":0,"status":401,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Expose-Headers":["ETag"],"Access-Control-Max-Age":["1728000"],"Access-Control-Allow-Credentials":["true"],"Www-Authenticate":["Basic realm=\"restricted\""],"Server":["Caddy"],"Access-Control-Allow-Headers":["Authorization,DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Accept-Charset,X-Accept,origin,accept,if-match,destination,overwrite,X-CustomHeader"],"Access-Control-Allow-Methods":["GET, HEAD, POST, PUT, OPTIONS, MOVE, DELETE, COPY, LOCK, UNLOCK, PROPFIND, MKCOL"]}}
{"level":"info","ts":1649603017.5407305,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_addr":"my_ip:16834","proto":"HTTP/1.1","method":"PUT","host":"dav.mydomain","uri":"/zotero/file1","headers":{"Authorization":["Basic bHloNDU4OkxZSDEyMzQ1Njc5"],"Content-Type":["application/octet-stream"],"Content-Length":["5"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"","proto_mutual":true,"server_name":"dav.mydomain"}},"common_log":"my_ip - username [10/Apr/2022:15:03:37 +0000] \"PUT /zotero/file1 HTTP/1.1\" 201 7","user_id":"username","duration":1.982221712,"size":7,"status":201,"resp_headers":{"Access-Control-Allow-Methods":["GET, HEAD, POST, PUT, OPTIONS, MOVE, DELETE, COPY, LOCK, UNLOCK, PROPFIND, MKCOL"],"Access-Control-Allow-Origin":["*"],"Access-Control-Expose-Headers":["ETag"],"Access-Control-Max-Age":["1728000"],"Etag":["\"16e4913458b93d2d5\""],"Server":["Caddy"],"Access-Control-Allow-Credentials":["true"],"Access-Control-Allow-Headers":["Authorization,DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Accept-Charset,X-Accept,origin,accept,if-match,destination,overwrite,X-CustomHeader"]}}
{"level":"error","ts":1649603055.6700094,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_addr":"my_ip:16834","proto":"HTTP/1.1","method":"PUT","host":"dav.mydomain","uri":"/zotero/file3","headers":{"Content-Type":["application/octet-stream"],"Content-Length":["18633601"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"","proto_mutual":true,"server_name":"dav.mydomain"}},"common_log":"my_ip - - [10/Apr/2022:15:04:15 +0000] \"PUT /zotero/file3 HTTP/1.1\" 401 0","user_id":"","duration":0.000145973,"size":0,"status":401,"resp_headers":{"Www-Authenticate":["Basic realm=\"restricted\""],"Server":["Caddy"],"Access-Control-Expose-Headers":["ETag"],"Access-Control-Max-Age":["1728000"],"Access-Control-Allow-Credentials":["true"],"Access-Control-Allow-Headers":["Authorization,DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Accept-Charset,X-Accept,origin,accept,if-match,destination,overwrite,X-CustomHeader"],"Access-Control-Allow-Methods":["GET, HEAD, POST, PUT, OPTIONS, MOVE, DELETE, COPY, LOCK, UNLOCK, PROPFIND, MKCOL"],"Access-Control-Allow-Origin":["*"]}}
{"level":"error","ts":1649603058.8734984,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_addr":"my_ip:17028","proto":"HTTP/1.1","method":"PUT","host":"dav.mydomain","uri":"/zotero/file3","headers":{"Content-Type":["application/octet-stream"],"Content-Length":["18633601"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"","proto_mutual":true,"server_name":"dav.mydomain"}},"common_log":"my_ip - - [10/Apr/2022:15:04:18 +0000] \"PUT /zotero/file3 HTTP/1.1\" 401 0","user_id":"","duration":0.000120796,"size":0,"status":401,"resp_headers":{"Access-Control-Max-Age":["1728000"],"Access-Control-Allow-Credentials":["true"],"Www-Authenticate":["Basic realm=\"restricted\""],"Server":["Caddy"],"Access-Control-Allow-Headers":["Authorization,DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Accept-Charset,X-Accept,origin,accept,if-match,destination,overwrite,X-CustomHeader"],"Access-Control-Allow-Methods":["GET, HEAD, POST, PUT, OPTIONS, MOVE, DELETE, COPY, LOCK, UNLOCK, PROPFIND, MKCOL"],"Access-Control-Allow-Origin":["*"],"Access-Control-Expose-Headers":["ETag"]}}
{"level":"error","ts":1649603061.5329177,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_addr":"my_ip:17056","proto":"HTTP/1.1","method":"PUT","host":"dav.mydomain","uri":"/zotero/file3","headers":{"Content-Type":["application/octet-stream"],"Content-Length":["18633601"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"","proto_mutual":true,"server_name":"dav.mydomain"}},"common_log":"my_ip - - [10/Apr/2022:15:04:21 +0000] \"PUT /zotero/file3 HTTP/1.1\" 401 0","user_id":"","duration":0.000104573,"size":0,"status":401,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Expose-Headers":["ETag"],"Access-Control-Max-Age":["1728000"],"Www-Authenticate":["Basic realm=\"restricted\""],"Server":["Caddy"],"Access-Control-Allow-Credentials":["true"],"Access-Control-Allow-Headers":["Authorization,DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Accept-Charset,X-Accept,origin,accept,if-match,destination,overwrite,X-CustomHeader"],"Access-Control-Allow-Methods":["GET, HEAD, POST, PUT, OPTIONS, MOVE, DELETE, COPY, LOCK, UNLOCK, PROPFIND, MKCOL"]}}
{"level":"error","ts":1649603064.0896423,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_addr":"my_ip:17080","proto":"HTTP/1.1","method":"PUT","host":"dav.mydomain","uri":"/zotero/file3","headers":{"Content-Length":["18633601"],"Content-Type":["application/octet-stream"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"","proto_mutual":true,"server_name":"dav.mydomain"}},"common_log":"my_ip - - [10/Apr/2022:15:04:24 +0000] \"PUT /zotero/file3 HTTP/1.1\" 401 0","user_id":"","duration":0.000129379,"size":0,"status":401,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Expose-Headers":["ETag"],"Access-Control-Max-Age":["1728000"],"Www-Authenticate":["Basic realm=\"restricted\""],"Server":["Caddy"],"Access-Control-Allow-Credentials":["true"],"Access-Control-Allow-Headers":["Authorization,DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Accept-Charset,X-Accept,origin,accept,if-match,destination,overwrite,X-CustomHeader"],"Access-Control-Allow-Methods":["GET, HEAD, POST, PUT, OPTIONS, MOVE, DELETE, COPY, LOCK, UNLOCK, PROPFIND, MKCOL"]}}
{"level":"error","ts":1649603067.0620177,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_addr":"my_ip:17116","proto":"HTTP/1.1","method":"PROPFIND","host":"dav.mydomain","uri":"/zotero/","headers":{"Depth":["1"],"Traceparent":["00-95bcf341ff0e0f898331c275b059a2aa-d1700fca3284ce5e-00"],"Content-Type":["application/xml; charset=utf-8"],"Content-Length":["96"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"","proto_mutual":true,"server_name":"dav.mydomain"}},"common_log":"my_ip - - [10/Apr/2022:15:04:27 +0000] \"PROPFIND /zotero/ HTTP/1.1\" 401 0","user_id":"","duration":0.000231393,"size":0,"status":401,"resp_headers":{"Access-Control-Max-Age":["1728000"],"Access-Control-Allow-Credentials":["true"],"Access-Control-Allow-Headers":["Authorization,DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Accept-Charset,X-Accept,origin,accept,if-match,destination,overwrite,X-CustomHeader"],"Www-Authenticate":["Basic realm=\"restricted\""],"Server":["Caddy"],"Access-Control-Allow-Methods":["GET, HEAD, POST, PUT, OPTIONS, MOVE, DELETE, COPY, LOCK, UNLOCK, PROPFIND, MKCOL"],"Access-Control-Allow-Origin":["*"],"Access-Control-Expose-Headers":["ETag"]}}
{"level":"info","ts":1649603067.272328,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_addr":"my_ip:17116","proto":"HTTP/1.1","method":"PROPFIND","host":"dav.mydomain","uri":"/zotero/","headers":{"Depth":["1"],"Traceparent":["00-95bcf341ff0e0f898331c275b059a2aa-d1700fca3284ce5e-00"],"Authorization":["Basic bHloNDU4OkxZSDEyMzQ1Njc5"],"Content-Type":["application/xml; charset=utf-8"],"Content-Length":["96"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"","proto_mutual":true,"server_name":"dav.mydomain"}},"common_log":"my_ip - username [10/Apr/2022:15:04:27 +0000] \"PROPFIND /zotero/ HTTP/1.1\" 207 1674","user_id":"username","duration":0.008953879,"size":1674,"status":207,"resp_headers":{"Access-Control-Allow-Origin":["*"],"Access-Control-Expose-Headers":["ETag"],"Access-Control-Max-Age":["1728000"],"Content-Type":["text/xml; charset=utf-8"],"Server":["Caddy"],"Access-Control-Allow-Credentials":["true"],"Access-Control-Allow-Headers":["Authorization,DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Accept-Charset,X-Accept,origin,accept,if-match,destination,overwrite,X-CustomHeader"],"Access-Control-Allow-Methods":["GET, HEAD, POST, PUT, OPTIONS, MOVE, DELETE, COPY, LOCK, UNLOCK, PROPFIND, MKCOL"]}}
{"level":"error","ts":1649603067.4928412,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_addr":"my_ip:17116","proto":"HTTP/1.1","method":"PROPFIND","host":"dav.mydomain","uri":"/","headers":{"Depth":["1"],"Traceparent":["00-95bcf341ff0e0f898331c275b059a2aa-cde040a9d5b79e46-00"],"Content-Type":["application/xml; charset=utf-8"],"Content-Length":["96"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"","proto_mutual":true,"server_name":"dav.mydomain"}},"common_log":"my_ip - - [10/Apr/2022:15:04:27 +0000] \"PROPFIND / HTTP/1.1\" 401 0","user_id":"","duration":0.000132876,"size":0,"status":401,"resp_headers":{"Access-Control-Allow-Headers":["Authorization,DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Accept-Charset,X-Accept,origin,accept,if-match,destination,overwrite,X-CustomHeader"],"Access-Control-Allow-Methods":["GET, HEAD, POST, PUT, OPTIONS, MOVE, DELETE, COPY, LOCK, UNLOCK, PROPFIND, MKCOL"],"Access-Control-Allow-Origin":["*"],"Access-Control-Expose-Headers":["ETag"],"Www-Authenticate":["Basic realm=\"restricted\""],"Server":["Caddy"],"Access-Control-Max-Age":["1728000"],"Access-Control-Allow-Credentials":["true"]}}
{"level":"info","ts":1649603067.6733172,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_addr":"my_ip:17116","proto":"HTTP/1.1","method":"PROPFIND","host":"dav.mydomain","uri":"/","headers":{"Traceparent":["00-95bcf341ff0e0f898331c275b059a2aa-cde040a9d5b79e46-00"],"Authorization":["Basic bHloNDU4OkxZSDEyMzQ1Njc5"],"Content-Type":["application/xml; charset=utf-8"],"Content-Length":["96"],"Depth":["1"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"","proto_mutual":true,"server_name":"dav.mydomain"}},"common_log":"my_ip - username [10/Apr/2022:15:04:27 +0000] \"PROPFIND / HTTP/1.1\" 207 969","user_id":"username","duration":0.000882937,"size":969,"status":207,"resp_headers":{"Content-Type":["text/xml; charset=utf-8"],"Server":["Caddy"],"Access-Control-Allow-Credentials":["true"],"Access-Control-Allow-Headers":["Authorization,DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Accept-Charset,X-Accept,origin,accept,if-match,destination,overwrite,X-CustomHeader"],"Access-Control-Allow-Methods":["GET, HEAD, POST, PUT, OPTIONS, MOVE, DELETE, COPY, LOCK, UNLOCK, PROPFIND, MKCOL"],"Access-Control-Allow-Origin":["*"],"Access-Control-Expose-Headers":["ETag"],"Access-Control-Max-Age":["1728000"]}}
Thanks in advance.
When receiving a PROPFIND request for a file that does not exist, the plugin is logging an internal handler error, instead of responding appropriately, which I imagine would be with a 404.
{
"level": "error",
"ts": 1595606346.000593,
"logger": "http.handlers.webdav",
"msg": "internal handler error",
"error": "stat /var/www/.../image.png: no such file or directory",
"request": {
"method": "PROPFIND",
"uri": "/webdav/.../image.png",
"proto": "HTTP/1.1",
"remote_addr": "...",
"host": "example.com",
"headers": {
"Connection": [
"close"
],
"Content-Length": [
"0"
],
"Accept": [
"text/plain"
],
"Depth": [
"0"
],
"Authorization": [
"Basic ..."
],
"User-Agent": [
"axios/0.18.0"
]
},
"tls": {
"resumed": true,
"version": 771,
"ciphersuite": 52393,
"proto": "",
"proto_mutual": true,
"server_name": "example.com"
}
}
}
I use xcaddy build caddy 2.4.3 with webdav, it is failed.
root@debian:~# /root/go/bin/xcaddy build v2.4.3 --with github.com/mholt/caddy-webdav
2021/07/07 10:15:03 [INFO] Temporary folder: /tmp/buildenv_2021-07-07-1015.138554826
2021/07/07 10:15:03 [INFO] Writing main module: /tmp/buildenv_2021-07-07-1015.138554826/main.go
2021/07/07 10:15:03 [INFO] Initializing Go module
2021/07/07 10:15:03 [INFO] exec (timeout=10s): /usr/bin/go mod init caddy
go: creating new go.mod: module caddy
2021/07/07 10:15:03 [INFO] Pinning versions
2021/07/07 10:15:03 [INFO] exec (timeout=0s): /usr/bin/go get -d -v github.com/caddyserver/caddy/[email protected]
2021/07/07 10:15:23 [INFO] exec (timeout=0s): /usr/bin/go get -d -v github.com/mholt/caddy-webdav
go: github.com/mholt/caddy-webdav upgrade => v0.0.0-20200916200058-c949b3226234
go: downloading google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c
go: downloading github.com/smallstep/certificates v0.15.15
2021/07/07 10:15:29 [INFO] Build environment ready
2021/07/07 10:15:29 [INFO] Building Caddy
2021/07/07 10:15:29 [INFO] exec (timeout=0s): /usr/bin/go mod tidy
go: downloading google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c
go: downloading github.com/smallstep/certificates v0.15.15
go: downloading github.com/klauspost/compress v1.13.0
caddy imports
github.com/caddyserver/caddy/v2/modules/standard imports
github.com/caddyserver/caddy/v2/modules/caddypki imports
github.com/smallstep/certificates/authority: github.com/smallstep/[email protected]: reading https://proxy.golang.org/github.com/smallstep/certificates/@v/v0.15.15.zip: 403 Forbidden
caddy imports
github.com/caddyserver/caddy/v2/modules/standard imports
github.com/caddyserver/caddy/v2/modules/caddypki imports
github.com/smallstep/certificates/db: github.com/smallstep/[email protected]: reading https://proxy.golang.org/github.com/smallstep/certificates/@v/v0.15.15.zip: 403 Forbidden
caddy imports
github.com/caddyserver/caddy/v2/modules/standard imports
github.com/caddyserver/caddy/v2/modules/caddypki/acmeserver imports
github.com/smallstep/certificates/acme: github.com/smallstep/[email protected]: reading https://proxy.golang.org/github.com/smallstep/certificates/@v/v0.15.15.zip: 403 Forbidden
caddy imports
github.com/caddyserver/caddy/v2/modules/standard imports
github.com/caddyserver/caddy/v2/modules/caddypki/acmeserver imports
github.com/smallstep/certificates/acme/api: github.com/smallstep/[email protected]: reading https://proxy.golang.org/github.com/smallstep/certificates/@v/v0.15.15.zip: 403 Forbidden
caddy imports
github.com/caddyserver/caddy/v2/modules/standard imports
github.com/caddyserver/caddy/v2/modules/caddypki/acmeserver imports
github.com/smallstep/certificates/acme/db/nosql: github.com/smallstep/[email protected]: reading https://proxy.golang.org/github.com/smallstep/certificates/@v/v0.15.15.zip: 403 Forbidden
caddy imports
github.com/caddyserver/caddy/v2/modules/standard imports
github.com/caddyserver/caddy/v2/modules/caddypki/acmeserver imports
github.com/smallstep/certificates/authority/provisioner: github.com/smallstep/[email protected]: reading https://proxy.golang.org/github.com/smallstep/certificates/@v/v0.15.15.zip: 403 Forbidden
caddy imports
github.com/mholt/caddy-webdav imports
github.com/caddyserver/caddy/v2/modules/caddyhttp imports
google.golang.org/genproto/googleapis/api/expr/v1alpha1: google.golang.org/[email protected]: reading https://proxy.golang.org/google.golang.org/genproto/@v/v0.0.0-20210602131652-f16073e35f0c.zip: 403 Forbidden
caddy imports
github.com/caddyserver/caddy/v2/modules/standard imports
github.com/caddyserver/caddy/v2/modules/caddyhttp/standard imports
github.com/caddyserver/caddy/v2/modules/caddyhttp/encode/gzip imports
github.com/klauspost/compress/gzip: github.com/klauspost/[email protected]: reading https://proxy.golang.org/github.com/klauspost/compress/@v/v1.13.0.zip: 403 Forbidden
caddy imports
github.com/caddyserver/caddy/v2/modules/standard imports
github.com/caddyserver/caddy/v2/modules/caddyhttp/standard imports
github.com/caddyserver/caddy/v2/modules/caddyhttp/encode/zstd imports
github.com/klauspost/compress/zstd: github.com/klauspost/[email protected]: reading https://proxy.golang.org/github.com/klauspost/compress/@v/v1.13.0.zip: 403 Forbidden
2021/07/07 10:15:32 [INFO] Cleaning up temporary folder: /tmp/buildenv_2021-07-07-1015.138554826
2021/07/07 10:15:32 [FATAL] exit status 1
{
order webdav last
}
:8001 {
webdav /share/* {
root ./share
}
}
not working.
Hello,
Are there plans to expose features available in https://github.com/hacdias/caddy-webdav, such as blocking dot files, allowing modifications for files/folders per user, or allowing/denying user access to resources, for Caddy 2?
I am currently using Caddy v1.
I think this is a bug or limitation in the upstream webdav library, but I noticed that when listing the contents of a directory, the whole request returns an error if just one of the files has a permissions error. Instead, that file should not be in the list, and the request should still succeed, listing the rest of the files in the directory.
Caddy server is windows 10. The phone uses photosync+webdav to synchronize photos, and an error will be reported every time a photo is synchronized.
Error message: Cannot create a file when that file already exists
Tip: The error log will be output, but it does not affect the use
Caddyfile:
{
order webdav before file_server
}
:7001 {
webdav {
root D:/_data
prefix /
}
}
error.log:
{"level":"error","ts":1627832105.3054144,"logger":"http.handlers.webdav","msg":"internal handler error","error":"mkdir D:\\_data\\手机相册\\Screenshots\\2020: Cannot create a file when that file already exists.
Scopes as provided by the webdav "predecessor" addon in caddy 1.0.4 is not available in caddy 2 (2.2.1)
I used the following config in caddy 1.0.4 which worked just as wanted. Couldn't get similar mult user access functionality in caddy 2 and the new webdav addon.
webdav.somedomain.duckdns.org {
basicauth / super userpwd
basicauth / user2 userpwd
basicauth / user3 userpwd
basicauth / user4 userpwd
webdav {
super:
scope /home/DATA/webdav
user2:
scope /home/DATA/webdav/.user2
user3:
scope /home/DATA/webdav/.user3
user4:
scope /home/DATA/webdav/.user3
}
log /etc/caddy/access-webdav.log
}
The readme doesn't document the prefix option at the moment, which is required whenever a matcher is used on the directive.
I spent an hour or two of confusion before finding the option in the code, documenting it might save the next person some time. :D
Can we get some support added for chunked uploads / setting max body size ?
I'm trying to use this behind cloudflare proxy and it always fails on large files.
add "..%2F" to url can get the parent of root path
i would love to hide a folder on webdav listening. something like the hide
option in file_server.
Clean download (from https://caddyserver.com/download) and installation of Caddy2+webdav on Mac OS Catalina.
Browser gets status code 405 and shows Method not allowed for https://localhost/dav, with Caddyfile extracted from Readme as below,
localhost
root * /srv
route {
rewrite /dav /dav/
webdav /dav/* {
prefix /dav
}
file_server
}
<<<
If replaced it with below (basically remove rewrite and prefix), everything works with http://localhost URL.
localhost
root * /srv
route {
webdav {
}
file_server
}
<<<
Cannot find any clues anywhere :(... please kindly share any advices. Thanks.
Hello, I'm using caddy1 + webdav and would like to migrate, but this version of the webdav plugin gives me empty responses, except on the root path where I get the xml right.
Thanks,
Response (on any request except / )
HTTP/1.1 200 OK
Server: Caddy
Date: Fri, 22 May 2020 23:04:21 GMT
Content-Length: 0
Caddyfile
{
order webdav last
}
:2015 {
webdav / {
root ./
}
}
Hi,
first of all, thanks a lot for the webdav-module. :) I had some trouble getting things to run smoothly and thought it might be a good idea to share the solutions.
Background: I wanted to use webdav to store and share notes with my wife. I encountered the following problems while installing, which my have occurred to others.
My system: Debian Buster running caddy v2.3.0 h1
with a systemd service (I swapped the executable in /usr/bin/
with the one including the webdav module).
Things that were not clear for me from the webdav module readme:
1. get the root right:
The readme example does not work with the systemd service.
Read-me example:
webdav /some/path/match/* {
root /path
prefix /some/path/match
}
I had to change it to:
webdav /webdav/* {
root /usr/share/caddy/webdav
prefix /webdav
}
In my case the webserver root in the caddyfile is root * /usr/share/caddy
, which means that the path structure of the example is different.
2. Fix permissions while using a systemd service:
Although caddy had all the necessary permissions to the webdav directory it still complained about permissions:
Feb 18 23:18:48 vps caddy[12627]: {"level":"error","ts":1613686728.1413567,"logger":"http.handlers.webdav","msg":"internal handler error","error":"open /usr/share/caddy/webdav/silentnotes_repository.silentnotes: read-only file system","request":{"remote_addr":"x.x.x.x:123","proto":"HTTP/1.1","method":"PUT","host":"x.x.com","uri":"/webdav/silentnotes_repository.silentnotes","headers":{"Content-Length":["832"],"Authorization":["Basic c3xlZmAuOlYySXIxZg=="],"Accept-Encoding":["gzip, deflate"]},"tls":{"resumed":false,"version":771,"cipher_suite":49200,"proto":"","proto_mutual":true,"server_name":"x.x.com"}}}
Fix: Follow https://caddy.community/t/problem-with-filemanager-plugin-and-systemd/3900/3 and add a ReadWriteDirectories directive to the systemd file, as ProtectSystem=full
prevents this.
In my case this results in:
User=caddy
Group=caddy
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE
ReadWriteDirectories=/usr/share/caddy/webdav
If you find these notes useful, please add them to the module read-me page. Thanks!
Hi,
I have these settings as default in webdav:
danobe.dev {
# Set this path to your site's directory.
#root * /usr/share/caddy
# Enable the static file server.
#file_server
# Another common task is to set up a reverse proxy:
reverse_proxy localhost:5000
# Or serve a PHP site through php-fpm:
# php_fastcgi localhost:9000
}
I tried by know all different choices with webdav and tutorials in the internet, but I can't get it to work.
This are the fields I have to enter in the image.
I'm not really familiar with webdav, it seems to be the only convinient way to deploy my application.
I have a linux server with the path /var/www/personalWebsite into which I would like to deploy my application.
It works via scp and rsync but it looks like I'm to dumb to get it to work with debdav.
Could you provide a clear explanation on how I have to change the caddy configuration file?
Like I've said I tried all possible combinations but I couldn't get it to work...
And how do I restrict the access, is this like a public ftp where everyone can deploy files?
I've read this here, and here it get's shown I have to create a password hash, but I don't know if this is necessary?
https://marko.euptera.com/posts/caddy-webdav.html
That would be very kind of you,
kind regards
greets from Italy,
Daniel
The caddy and webdav module is downloaded today from the homepage.
Caddyfile :
{
admin off
auto_https off
local_certs
order webdav before file_server
}
:9999 {
encode gzip
root * /data
file_server browse
tls /root/caddy/server.cert /root/caddy/server.key
webdav /webdav/* {
root /data
prefix /webdav
}
}
Generate some text files as the snapshot, then refresh the webdav directory, no any text file is shown.
Then, just rename the text file to another filetype as the snapshot, and refresh the webdav directory again, one of them appeared.
Let's continue. This time i just rename the filename, did not change the filetype. Here is the snapshot.
Not only text files is filtered strangely, other filetype is the same. Here is another test.
This is my webdav client conf:
I dont know why and how to resolve it. Thanks.
Hi,
This webdav module is working extremely well with a few lines of configuration, congratulations for the awesome job 🏆
One issue I'm facing now is that file manipulations done via webdav are done with the permissions of the user Caddy runs as (which is root
when using Docker).
I'd love to be able to configure another user to perform file manipulations as, probably following the user[:group]
or uid[:gid]
format like this:
webdav.{$BASE_URL} {
webdav {
root /share/
user mike:mike
}
}
Using Docker or Docker Compose, it would even be configurable like this:
webdav.{$BASE_URL} {
webdav {
root /share/
user {$UID}:{$GID}
}
}
Do you think that might be considered?
Or should I gosu
/su-exec
the whole Caddy server instead?
Or do you recomment another solution?
Thanks a lot in advance 🙏
Hi there, really liking caddy and learning a bunch, while trying to contribute a bit! To the forum.
I was wondering if you see this plugin evolving so that it can support class 1 or class 2 WebDAV.
My current need does not involve anything fancy but it would be nice to stay with caddy if the need for a lock, for instance, arises.
Thanks for your effort!
I have Caddy with this module configured and it is working fine for iPhone KeePassium.
For MacOS, I am using KeePassXC, which does not support webdav directly, so I have to mount the directory with MacOS Finder.
It lists the files, but I cannot create or rename files, so KeepassXC cannot save the database. I also tried create and rename directly in the Finder and it does not work.
After some investigation, it looks like MacOS requires the webdav server to support "Level 2 locking". Apache can do that and Nginx with some workarounds, but looks like this module does not.
I tried various configs, including the standard:
webdav /dav/* {
root /dav/
prefix /dav
}
For example, user 1 has read, write, edit and delete permission, while user 2 has only read permission.
Separately publish executable files for caddy with webdav plugin.
https://github.com/mholt/caddy-webdav/releases
Since webdav requires higher performance than static files and reverse proxy, I think webdav should be run as a separate process, and then it would be better for caddy gateway service to do reverse proxy for webdav.
It is better to separate the gateway service and webdav service into separate processes.
Compiling caddy with plug-ins still has some costs. Wouldn't it be better to publish it as an executable file?
In this way, you can get a webdav server out of the box.
HEAD requests to folders return HTTP 405 Method Not Allowed.
I believe this is an issue because, according to RFC 4918§9.4, HEAD should be valid also on collections.
The current behaviour makes it impossible to use this extension with some WebDAV clients/libraries (e.g., java's Sardine).
# Caddyfile
:8080
log
root * /var/www
route {
webdav
}
# Content of the webroot
$ ls -lah /var/www
total 12K
drwxr-xr-x 3 root root 4.0K Jan 02 15:04 .
drwxr-xr-x 14 root root 4.0K Jan 02 15:04 ..
-rw-r--r-- 1 root root 11 Jan 02 15:04 a-file
drwxr-xr-x 2 root root 4.0K Jan 02 15:04 a-folder
GET requests work for both file and folder:
$ curl -X GET http://localhost:8080/a-file
I'm a file
$ curl -X GET http://localhost:8080/a-folder
<?xml version="1.0" encoding="UTF-8"?><D:multistatus xmlns:D="DAV:"><D:response><D:href>/a-folder/</D:href><D:propstat><D:prop><D:getlastmodified>Mon, 02 Jan 2006 15:04:05 MST</D:getlastmodified><D:resourcetype><D:collection xmlns:D="DAV:"/></D:resourcetype><D:displayname>a-folder</D:displayname><D:supportedlock><D:lockentry xmlns:D="DAV:"><D:lockscope><D:exclusive/></D:lockscope><D:locktype><D:write/></D:locktype></D:lockentry></D:supportedlock></D:prop><D:status>HTTP/1.1 200 OK</D:status></D:propstat></D:response></D:multistatus>
HEAD requests to a-file
work, but to a-folder
fail:
$ curl --head http://localhost:8080/a-file
HTTP/1.1 200 OK
[...]
$ curl --head http://localhost:8080/a-folder
HTTP/1.1 405 Method Not Allowed
Server: Caddy
Date: Mon, 02 Jan 2006 15:04:05 MST
Note: This would close #19, where the workarounds proposed so far don't work.
Hi there, apologies, this is completely off topic.
Have you ever been able to access a webdav server via caddy with TLS 1.2?
I have tried cadaver
, davx
, thunar
(the file manager) but they all seem to send a TLS 1.0 Client Hello and that fails with the current Caddy.
Thank you, just wondering because I am going a bit nuts :D
I want use webdav with caddy v2, but can not work.
caddy version: 2.1.1
My website root: /home/website, webdav root: /home/webdav
Caddyfile:
{
http_port 8080
order webdav last
}
http:// {
root * /home/website
log {
output stdout
}
file_server
webdav /webdav/* {
root /home/
}
}
When file_server is normal, the website can be accessed, but WebDAV cannot work.
The comment file_server, WebDAV works normally and the website cannot be accessed.
Hello! Friend.
I use this caddy. https://hub.docker.com/_/caddy?tab=description
But webdav can not work.
Can you help me ?
Thank you very much.
I wanted to see if you could clarify something in my Caddyfile, or maybe build. I cannot get /webdav to work with a docker build of Caddy. When I browse to the docker box, I get my test page. When I go to http://dockerip/static to redirect to /static/ and does the browse plugin. So those are working. When I go to http://dockerip/webdav I'm getting 404.
Is the root element of webdav relative to the site blocks root? or is it a full file path?
My Caddyfile:
{
order webdav last
}
(global) {
encode gzip zstd
log {
output file /data/logs/caddy_access.log
}
handle_errors /data/logs/caddy_errors.log
php_fastcgi phpfpm:9000
}
:80 {
root * /usr/share/caddy/html
file_server
file_server /static/* browse
import global
redir /static /static/
webdav /webdav {
root /usr/share/caddy/webdav
}
}
The Dockerfile builder:
FROM caddy:2.0.0-builder AS builder
RUN caddy-builder \
github.com/mholt/caddy-webdav
FROM caddy:2.0.0
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
Relevant docker-compose.yml:
version: '3.4'
services:
# Caddy web server, doing reverse proxy
caddy:
image: "caddy:2.0.0-custom"
container_name: "caddy"
ports:
- "80:80"
- "443:443"
volumes:
- /srv/caddy/Caddyfile:/etc/caddy/Caddyfile:ro
- /srv/caddy/www:/usr/share/caddy:rw
- /srv/caddy/data:/data:rw
restart: always
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.