Configuration

This document describes the configuration options of a WsgiDAV server.

The WsgiDAVApp object is configured by passing a Python dict with distinct options, that define

  • Server options (hostname, port, SSL cert, …)

  • List of share-name / WebDAV provider mappings

  • Optional list of users for authentication

  • Optional custom DAV providers (i.e. other than FilesystemProvider)

  • Optional custom lock manager, property manager and domain controller

  • Advanced debugging options

  • (and more)

This section shows the available options and defaults:

  1# (c) 2009-2024 Martin Wendt and contributors; see WsgiDAV https://github.com/mar10/wsgidav
  2# Original PyFileServer (c) 2005 Ho Chun Wei.
  3# Licensed under the MIT license:
  4# http://www.opensource.org/licenses/mit-license.php
  5r"""
  6::
  7
  8     _      __         _ ___  ___ _   __
  9    | | /| / /__ ___  (_) _ \/ _ | | / /
 10    | |/ |/ (_-</ _ `/ / // / __ | |/ /
 11    |__/|__/___/\_, /_/____/_/ |_|___/
 12               /___/
 13
 14Default configuration.
 15"""
 16
 17# from wsgidav.mw.debug_filter import WsgiDavDebugFilter
 18from wsgidav.dir_browser import WsgiDavDirBrowser
 19from wsgidav.error_printer import ErrorPrinter
 20from wsgidav.http_authenticator import HTTPAuthenticator
 21
 22# from wsgidav.mw.impersonator import Impersonator
 23from wsgidav.mw.cors import Cors
 24from wsgidav.request_resolver import RequestResolver
 25
 26__docformat__ = "reStructuredText"
 27
 28# Use these settings, if config file does not define them (or is totally missing)
 29DEFAULT_VERBOSE = 3
 30DEFAULT_LOGGER_DATE_FORMAT = "%H:%M:%S"
 31DEFAULT_LOGGER_FORMAT = "%(asctime)s.%(msecs)03d - %(levelname)-8s: %(message)s"
 32
 33DEFAULT_CONFIG = {
 34    "server": "cheroot",
 35    "server_args": {},
 36    "host": "localhost",
 37    "port": 8080,
 38    "mount_path": None,  # Application root, e.g. <mount_path>/<share_name>/<res_path>
 39    "provider_mapping": {},
 40    "fs_dav_provider": {
 41        "shadow_map": {},
 42        "follow_symlinks": False,
 43    },
 44    "honor_mtime_header": False,
 45    "add_header_MS_Author_Via": True,
 46    "default_charset": "utf-8",  # e.g. "utf-8"
 47    "hotfixes": {
 48        "emulate_win32_lastmod": False,  # True: support Win32LastModifiedTime
 49        "re_encode_path_info": True,  # (See issue #73)
 50        "unquote_path_info": False,  # (See issue #8, #228)
 51        # "accept_put_without_content_length": True,  # (See issue #10, #282)
 52        # "treat_root_options_as_asterisk": False, # Hotfix for WinXP / Vista: accept 'OPTIONS /' for a 'OPTIONS *'
 53        # "win_accept_anonymous_options": False,
 54        # "winxp_accept_root_share_login": False,
 55    },
 56    "property_manager": None,  # True: use property_manager.PropertyManager
 57    "mutable_live_props": [],
 58    "lock_storage": True,  # True: use LockManager(lock_storage.LockStorageDict)
 59    "middleware_stack": [
 60        # WsgiDavDebugFilter,
 61        Cors,
 62        ErrorPrinter,
 63        HTTPAuthenticator,
 64        # Impersonator,
 65        WsgiDavDirBrowser,  # configured under dir_browser option (see below)
 66        RequestResolver,  # this must be the last middleware item
 67    ],
 68    # HTTP Authentication Options
 69    "http_authenticator": {
 70        # None: dc.simple_dc.SimpleDomainController(user_mapping)
 71        "domain_controller": None,
 72        "accept_basic": True,  # Allow basic authentication, True or False
 73        "accept_digest": True,  # Allow digest authentication, True or False
 74        "default_to_digest": True,  # True (default digest) or False (default basic)
 75        # Name of a header field that will be accepted as authorized user
 76        "trusted_auth_header": None,
 77    },
 78    #: Used by SimpleDomainController only
 79    "simple_dc": {"user_mapping": {}},  # NO anonymous access by default
 80    #: Verbose Output
 81    #: 0 - no output
 82    #: 1 - no output (excepting application exceptions)
 83    #: 2 - show warnings
 84    #: 3 - show single line request summaries (for HTTP logging)
 85    #: 4 - show additional events
 86    #: 5 - show full request/response header info (HTTP Logging)
 87    #:     request body and GET response bodies not shown
 88    "verbose": DEFAULT_VERBOSE,
 89    #: Suppress version info in HTTP response headers and error responses
 90    "suppress_version_info": False,
 91    #: Log options
 92    "logging": {
 93        "enable": None,  # True: activate 'wsgidav' logger (in library mode)
 94        "logger_date_format": DEFAULT_LOGGER_DATE_FORMAT,
 95        "logger_format": DEFAULT_LOGGER_FORMAT,
 96        "enable_loggers": [],
 97        "debug_methods": [],
 98    },
 99    #: Options for `WsgiDavDirBrowser`
100    "dir_browser": {
101        "enable": True,  # Render HTML listing for GET requests on collections
102        # Add a trailing slash to directory URLs (by generating a 301 redirect):
103        "directory_slash": True,
104        # List of fnmatch patterns:
105        "ignore": [
106            ".DS_Store",  # macOS folder meta data
107            "._*",  # macOS hidden data files
108            "Thumbs.db",  # Windows image previews
109        ],
110        "icon": True,
111        "response_trailer": True,  # Raw HTML code, appended as footer (True: use a default)
112        "show_user": True,  # Show authenticated user an realm
113        # Send <dm:mount> response if request URL contains '?davmount' (rfc4709)
114        "davmount": True,
115        # Add 'Mount' link at the top
116        "davmount_links": False,
117        "ms_sharepoint_support": True,  # Invoke MS Office documents for editing using WebDAV
118        "libre_office_support": True,  # Invoke Libre Office documents for editing using WebDAV
119        # The path to the directory that contains template.html and associated assets.
120        # The default is the htdocs directory within the dir_browser directory.
121        "htdocs_path": None,
122    },
123}

When a Python dict is passed to the WsgiDAVApp constructor, its values will override the defaults from above:

root_path = gettempdir()
provider = FilesystemProvider(root_path, readonly=False, fs_opts={})

config = {
    "host": "0.0.0.0",
    "port": 8080,
    "provider_mapping": {"/": provider},
    "verbose": 1,
    }
app = WsgiDAVApp(config)

Use a Configuration File

When running from the CLI (command line interface), some settings may be passed as arguments, e.g.:

$ wsgidav --host=0.0.0.0 --port=8080 --root=/tmp --auth=anonymous

Serving on http://0.0.0.0:8080 ...

Much more options are available when a configuration file is used. By default wsgidav.yaml and wsgidav.json are searched in the local directory. An alternative file name can be specified like so:

$ wsgidav --config=my_config.yaml

To prevent the use of a local default configuration file, use this option:

$ wsgidav --no-config

The options described below can be defined for the CLI either

  • in YAML syntax inside a wsgidav.yaml file

  • or JSON syntax inside a wsgidav.json file

Note

The two supported file formats are just different ways for the CLI to generate a Python dict that is then passed to the WsgiDAVApp constructor.

The YAML format is recommended.

For a start, copy YAML Sample Configuration and edit it to your needs. (Alternatively use JSON Sample Configuration.)

Verbosity Level

The verbosity level can have a value from 0 to 5 (default: 3):

Verbosity

Option

Log level

Remarks

0

-qqq

CRITICAL

quiet

1

-qq

ERROR

no output (excepting application exceptions)

2

-q

WARN

warnings and errors only

3

INFO

show single line request summaries (for HTTP logging)

4

-v

DEBUG

show additional events

5

-vv

DEBUG

show full request/response header info (HTTP Logging) request body and GET response bodies not shown

Middleware Stack

WsgiDAV is built as WSGI application (WsgiDAVApp) that is extended by a list of middleware components which implement additional functionality.

This stack is defined as a list of WSGI compliant application instances, e.g.:

from wsgidav.mw.debug_filter import WsgiDavDebugFilter

debug_filter = WsgiDavDebugFilter(wsgidav_app, next_app, config)

conf = {
    ...
    "middleware_stack": [
        debug_filter,
        ...
        ],
    ...
    }

If the middleware class constructor has a common signature, it is sufficient to pass the class instead of the instantiated object. The built-in middleware derives from BaseMiddleware, so we can simplify as:

from wsgidav.dir_browser import WsgiDavDirBrowser
from wsgidav.mw.debug_filter import WsgiDavDebugFilter
from wsgidav.error_printer import ErrorPrinter
from wsgidav.http_authenticator import HTTPAuthenticator
from wsgidav.request_resolver import RequestResolver

conf = {
    ...
    "middleware_stack": [
        WsgiDavDebugFilter,
        ErrorPrinter,
        HTTPAuthenticator,
        WsgiDavDirBrowser,
        RequestResolver,  # this must be the last middleware item
        ],
    ...
    }

The middleware stack can be configured and extended. The following example removes the directory browser, and adds a third-party debugging tool:

import dozer

# from wsgidav.dir_browser import WsgiDavDirBrowser
from wsgidav.mw.debug_filter import WsgiDavDebugFilter
from wsgidav.error_printer import ErrorPrinter
from wsgidav.http_authenticator import HTTPAuthenticator
from wsgidav.request_resolver import RequestResolver

# Enable online profiling and GC inspection. See https://github.com/mgedmin/dozer
# (Requires `pip install Dozer`):
dozer_app = dozer.Dozer(wsgidav_app)
dozer_profiler = dozer.Profiler(dozer_app, None, "/tmp")

conf = {
    ...
    "middleware_stack": [
        dozer_app,
        dozer_profiler,
        WsgiDavDebugFilter,
        ErrorPrinter,
        HTTPAuthenticator,
        # WsgiDavDirBrowser,
        RequestResolver,  # this must be the last middleware item
        ],
    ...
    }

The stack can also be defined in text files, for example YAML. Again, we can pass an import path for a WSGI compliant class if the signature is known. For third-party middleware however, the constructor’s positional arguments should be explicitly listed:

...
middleware_stack:
    - class: dozer.Dozer
      args:
        - "${application}"
    - class: dozer.Profiler
      args:
        - "${application}"
        - null  # global_conf
        - /tmp  # profile_path
    - wsgidav.mw.debug_filter.WsgiDavDebugFilter
    - wsgidav.error_printer.ErrorPrinter
    - wsgidav.http_authenticator.HTTPAuthenticator
    - wsgidav.dir_browser.WsgiDavDirBrowser
    - wsgidav.request_resolver.RequestResolver

It is also possible to pass options as named args (i.e. ‘kwargs’):

...
middleware_stack:
    ...
    - class: dozer.Profiler
      kwargs:
        app: "${application}"
        profile_path: /tmp
    ...

Note that the external middleware must be available, for example by calling pip install Doze, so this will not be possible if WsgiDAV is running from the MSI installer.

DAVProvider

A DAVProvider handles read and write requests for all URLs that start with a given share path.

WsgiDAV comes bundled with FilesystemProvider, a DAVProvider that serves DAV requests by reading and writing to the server’s file system.
However, custom DAVProviders may be implemented and used, that publish a database backend, cloud drive, or any virtual data structure.

The provider_mapping configuration routes share paths to specific DAVProvider instances.

By default a writable FilesystemProvider is assumed, but can be forced to read-only. Note that a DomainController may still restrict access completely or prevent editing depending on authentication.

Three syntax variants are supported:

  1. <share_path>: <folder_path>: use FilesystemProvider(folder_path)

  2. <share_path>: { "root": <folder_path>, "readonly": <bool> }: use FilesystemProvider(folder_path, readonly)

  3. <share_path>: { "class": <class_path>, args: [arg, ...], kwargs: {"arg1": val1, "arg2": val2, ... }} Instantiate a custom class (derived from DAVProvider) using named kwargs.

For example:

provider_mapping:
    "/": "/path/to/share1"
    "/home": "~"
    "/pub":
        root: "/path/to/share2"
        readonly: true
    "/share3":
        class: path.to.CustomDAVProviderClass
        args:
            - pos_arg1
            - pos_arg2
        kwargs:
            path: '/path/to/share3'
            another_arg: 42

Property Manager

The built-in PropertyManager`.

Possible options are:

  • Disable locking, by passing property_manager: null.

  • Enable default storage, which is implemented using a memory-based, not persistent storage, by passing property_manager: true. (This is an alias for property_manager: wsgidav.prop_man.property_manager.PropertyManager)

  • Enable an installed or custom storage

Example: Use a persistent shelve based property storage:

property_manager:
    class: wsgidav.prop_man.property_manager.ShelvePropertyManager
    storage_path: /path/to/wsgidav_locks.shelve

Lock Manager and Storage

The built-in LockManager requires a LockStorageDict instance.

Possible options are:

  • Disable locking, by passing lock_storage: null.

  • Enable default locking, which is implemented using a memory-based, not persistent storage, by passing lock_storage: true. (This is an alias for lock_storage: wsgidav.lock_man.lock_storage.LockStorageDict)

  • Enable an installed lock storage

A persistent, shelve based LockStorageShelve is also available:

lock_storage:
    class: wsgidav.lock_man.lock_storage.LockStorageShelve
    kwargs:
        storage_path: /path/to/wsgidav_locks.shelve

Domain Controller

The HTTP authentication middleware relies on a domain controller. Currently three variants are supported.

SimpleDomainController

The wsgidav.dc.simple_dc.SimpleDomainController allows to authenticate against a plain mapping of shares and user names.

The pseudo-share "*" maps all URLs that are not explicitly listed.

A value of true can be used to enable anonymous access.

Example YAML configuration:

http_authenticator:
    domain_controller: null  # Same as wsgidav.dc.simple_dc.SimpleDomainController
    accept_basic: true  # Pass false to prevent sending clear text passwords
    accept_digest: true
    default_to_digest: true

simple_dc:
    user_mapping:
        "*":
            "user1":
                password: "abc123"
            "user2":
                password: "qwerty"
        "/pub": true

An optional roles list will be passed in environ[“wsgidav.auth.roles”] to downstream middleware. This is currently not used by the provided middleware, but may be handy for custom handlers:

simple_dc:
    user_mapping:
        "*":
            "user1":
                password: "abc123"
                roles: ["editor", "admin"]
            "user2":
                password: "abc123"
                roles: []

If no config file is used, anonymous authentication can be enabled on the command line like:

$ wsgidav ... --auth=anonymous

which simply defines this setting:

simple_dc:
    user_mapping:
        "*": true

NTDomainController

Allows users to authenticate against a Windows NT domain or a local computer.

The wsgidav.dc.nt_dc.NTDomainController requires basic authentication and therefore should use SSL.

Example YAML configuration:

ssl_certificate: wsgidav/server/sample_bogo_server.crt
ssl_private_key: wsgidav/server/sample_bogo_server.key
ssl_certificate_chain: None

http_authenticator:
    domain_controller: wsgidav.dc.nt_dc.NTDomainController
    accept_basic: true
    accept_digest: false
    default_to_digest: false

nt_dc:
    preset_domain: null
    preset_server: null

If no config file is used, NT authentication can be enabled on the command line like:

$ wsgidav ... --auth=nt

PAMDomainController

Allows users to authenticate against a PAM (Pluggable Authentication Modules), that are at the core of user authentication in any modern linux distribution and macOS.

The wsgidav.dc.pam_dc.PAMDomainController requires basic authentication and therefore should use SSL.

Example YAML configuration that authenticates users against the server’s known user accounts:

ssl_certificate: wsgidav/server/sample_bogo_server.crt
ssl_private_key: wsgidav/server/sample_bogo_server.key
ssl_certificate_chain: None

http_authenticator:
    domain_controller: wsgidav.dc.pam_dc.PAMDomainController
    accept_basic: true
    accept_digest: false
    default_to_digest: false

pam_dc:
    service: "login"
    allow_users: "all"
    #: or "current" for the current user, or a list of user names like deny_users
    # deny_users:
    #   - "root"
    #   - "daemon"

If no config file is used, PAM authentication can be enabled on the command line like:

$ wsgidav ... --auth=pam-login

Custom Domain Controllers

A custom domain controller can be used like so:

http_authenticator:
    domain_controller: path.to.CustomDomainController

The constructor must accept two arguments:

def __init__(self, wsgidav_app, config)

Note that this allows the custom controller to read the configuration dict and look for a custom section there.

Cors Middleware

The wsgidav.mw.cors.Cors Respond to CORS preflight OPTIONS request and inject CORS headers. This middleware is available by default, but needs configuration to be enabled. A minimal (yet ):

cors:
    #: List of allowed Origins or '*'
    #: Default: false, i.e. prevent CORS
    # allow_origin: null
    allow_origin: '*'

This may be too unspecific though. See Cross-Origin Resource Sharing (CORS) .

Annotated YAML configuration:

cors:
    #: List of allowed Origins or '*'
    #: Default: false, i.e. prevent CORS
    allow_origin: null
    # allow_origin: '*'
    # allow_origin:
    #   - 'https://example.com'
    #   - 'https://localhost:8081'

    #: List or comma-separated string of allowed methods (returned as
    #: response to preflight request)
    allow_methods:
    # allow_methods: POST,HEAD
    #: List or comma-separated string of allowed header names (returned as
    #: response to preflight request)
    allow_headers:
    #   - X-PINGOTHER
    #: List or comma-separated string of allowed headers that JavaScript in
    #: browsers is allowed to access.
    expose_headers:
    #: Set to true to allow responses on requests with credentials flag set
    allow_credentials: false
    #: Time in seconds for how long the response to the preflight request can
    #: be cached (default: 5)
    max_age: 600
    #: Add custom response headers (dict of header-name -> header-value items)
    #: (This is not related to CORS or required to implement CORS functionality)
    add_always:
    #    'X-Foo-Header: 'qux'

Sample wsgidav.yaml

The YAML syntax is the recommended format to define configuration:

Download Sample Configuration.

  1# WsgiDAV configuration file
  2#
  3# 1. Rename this file to `wsgidav.yaml`.
  4# 2. Adjust settings as appropriate.
  5# 3. Run `wsgidav` from the same directory or pass file path with `--config` option.
  6#
  7# See https://wsgidav.readthedocs.io/en/latest/user_guide_configure.html
  8#
  9# ============================================================================
 10# SERVER OPTIONS
 11
 12#: Run WsgiDAV inside this  WSGI server.
 13#: Supported servers:
 14#:     cheroot, ext-wsgiutils, gevent, gunicorn, paste, uvicorn, wsgiref
 15#: 'wsgiref' and 'ext_wsgiutils' are simple builtin servers that should *not* be
 16#: used in production.
 17#: All other servers must have been installed before, e.g. `pip install cheroot`.
 18#: (The binary MSI distribution already includes 'cheroot'.)
 19#: NOTE: Using 'gunicorn' with more than 1 worker can cause problems with the
 20#: in-memory and shelve-based lock storage as both are not safe for concurrent
 21#: access. (see issue #332) Instead, you can use 'gunicorn' with multiple `threads`
 22#: or try the 'redis' based lock storage (#186).
 23#: Default: 'cheroot', use the `--server` command line option to change this.
 24
 25server: cheroot
 26
 27#: Server specific arguments, passed to the server. For example cheroot:
 28#:   https://cheroot.cherrypy.dev/en/latest/pkg/cheroot.wsgi.html#cheroot.wsgi.Server
 29# server_args:
 30#     max: -1
 31#     numthreads: 10
 32#     request_queue_size: 5
 33#     shutdown_timeout: 5
 34#     timeout: 10
 35
 36# Server hostname (default: localhost, use --host on command line)
 37host: 0.0.0.0
 38
 39# Server port (default: 8080, use --port on command line)
 40port: 8080
 41
 42# Transfer block size in bytes
 43block_size: 8192
 44
 45#: Add the MS-Author-Via Response Header to OPTIONS command to allow editing
 46#: with Microsoft Office (default: true)
 47add_header_MS_Author_Via: true
 48
 49#: Default encoding for text files. #: If null (default), use system default encoding.
 50#: Otherwise specify a string like "utf-8". Pass None to prevent '; charset=' header.
 51default_charset: 'utf-8'
 52
 53hotfixes:
 54    #: Handle Microsoft's Win32LastModifiedTime property.
 55    #: This is useful only in the case when you copy files from a Windows
 56    #: client into a WebDAV share. Windows sends the "last modified" time of
 57    #: the file in a Microsoft extended property called "Win32LastModifiedTime"
 58    #: instead of the standard WebDAV property "getlastmodified". So without
 59    #: this config option set to "True", the "last modified" time of the copied
 60    #: file will be "now" instead of its original value.
 61    #: The proper solution for dealing with the Windows WebDAV client is to use
 62    #: a persistent property manager. This setting is merely a work-around.
 63    #: NOTE: Works with Win10, can't work with Win7. Other versions untested.
 64    emulate_win32_lastmod: false
 65    #: Re-encode PATH_INFO using UTF-8 (falling back to ISO-8859-1).
 66    #: This seems to be wrong, since per PEP 3333 PATH_INFO is always ISO-8859-1
 67    #: encoded (see https://www.python.org/dev/peps/pep-3333/#unicode-issues).
 68    #: However it also seems to resolve errors when accessing resources with
 69    #: Chinese characters, for example (see issue #73).
 70    re_encode_path_info: true
 71    #: Force unquoting of PATH_INFO. This should already be done by the WSGI
 72    #: Framework, so this setting should only be used to fix unexpected problems
 73    #: there (false fixes issue #8, true fixes issue #228).
 74    unquote_path_info: false
 75    #: Hotfix for WinXP / Vista: accept 'OPTIONS /' for a 'OPTIONS *'
 76    #: (default: false)
 77    treat_root_options_as_asterisk: false
 78
 79
 80# ----------------------------------------------------------------------------
 81# SSL Support
 82
 83#: The certificate should match the servers hostname, so the bogus certs will
 84#: not work in all scenarios.
 85#: (Paths can be absolute or relative to this config file.)
 86
 87# ssl_certificate: 'wsgidav/server/sample_bogo_server.crt'
 88# ssl_private_key: 'wsgidav/server/sample_bogo_server.key'
 89# ssl_certificate_chain: null
 90
 91#: Cheroot server supports 'builtin' and 'pyopenssl' (default: 'builtin')
 92# ssl_adapter: 'pyopenssl'
 93
 94# ----------------------------------------------------------------------------
 95
 96#: Modify to customize the WSGI application stack.
 97#: See here for an example how to add custom middlewares:
 98#:   https://wsgidav.readthedocs.io/en/latest/user_guide_configure.html#middleware-stack
 99middleware_stack:
100    - wsgidav.mw.cors.Cors
101    # - wsgidav.mw.debug_filter.WsgiDavDebugFilter
102    - wsgidav.error_printer.ErrorPrinter
103    - wsgidav.http_authenticator.HTTPAuthenticator
104    # - wsgidav.mw.impersonator.Impersonator
105    - wsgidav.dir_browser.WsgiDavDirBrowser
106    - wsgidav.request_resolver.RequestResolver  # this must be the last middleware item
107
108# ==============================================================================
109# SHARES
110
111#: Application root, applied before provider mapping shares, e.g. 
112#:   <mount_path>/<share_name>/<res_path>
113#: Set this to the mount point (aka location) when WsgiDAV is running behind a 
114#: reverse proxy.
115#: If set, the mount path must have a leading (but not trailing) slash.
116mount_path: null
117
118#: Route share paths to DAVProvider instances
119#: By default a writable `FilesystemProvider` is assumed, but can be forced
120#: to read-only.
121#: Note that a DomainController may still restrict access completely or prevent
122#: editing depending on authentication.
123#:
124#: The following syntax variants are supported to use FilesystemProvider:
125#:     <share_path>: <folder_path>
126#: or
127#:     <share_path>: { 'root': <folder_path>, 'readonly': <bool> }
128#:
129#: or instantiate an arbitrary custom class:
130#:
131#:     <share_path>: { 'class': <class_path>, args: [<arg>, ...], kwargs: {<arg>: <val>, ...} }
132
133provider_mapping:
134    '/': '/path/to/share1'
135    '/pub':
136        root: '/path/to/share2'
137        readonly: true
138    '/share3':
139        class: path.to.CustomDAVProviderClass
140        args:
141            - foo
142            - 42
143        kwargs:
144            path: '/path/to/share3'
145            another_arg: 42
146
147#: Additional configuration passed to `FilesystemProvider(..., fs_opts)`
148fs_dav_provider:
149    #: Mapping from request URL to physical file location, e.g.
150    #: make sure that a `/favicon.ico` URL is resolved, even if a `*.html`
151    #: or `*.txt` resource file was opened using the DirBrowser
152    # shadow_map:
153    #     '/favicon.ico': 'file_path/to/favicon.ico'
154    
155    #: Serve symbolic link files and folders (default: false)
156    follow_symlinks: false
157
158#: Set last modification based on timestamp provided by `X-OC-Mtime` header
159honor_mtime_header: false
160
161# ==============================================================================
162# AUTHENTICATION
163http_authenticator:
164    #: Allow basic authentication
165    accept_basic: true
166    #: Allow digest authentication
167    accept_digest: true
168    #: true (default digest) or false (default basic)
169    default_to_digest: true
170    #: Header field that will be accepted as authorized user.
171    #: Including quotes, for example: trusted_auth_header = 'REMOTE_USER'
172    trusted_auth_header: null
173    #: Domain controller that is used to resolve realms and authorization.
174    #: Default null: which uses SimpleDomainController and the
175    #: `simple_dc.user_mapping` option below.
176    #: (See http://wsgidav.readthedocs.io/en/latest/user_guide_configure.html
177    #: for details.)
178    domain_controller: null
179    # domain_controller: wsgidav.dc.simple_dc.SimpleDomainController
180    # domain_controller: wsgidav.dc.pam_dc.PAMDomainController
181    # domain_controller: wsgidav.dc.nt_dc.NTDomainController
182    # domain_controller: wsgidav.dc.htpasswd_dc.HtpasswdDomainController
183    # domain_controller: wsgidav.dc.htdigest_dc.HtdigestDomainController
184
185
186# Additional options for SimpleDomainController only:
187simple_dc:
188    # Access control per share.
189    # These routes must match the provider mapping.
190    # NOTE: Provider routes without a matching entry here, are inaccessible.
191    user_mapping:
192        '*':  # default (used for all shares that are not explicitly listed)
193            'user1':
194                password: 'abc123'
195                # Optional: passed to downstream middleware as environ["wsgidav.auth.roles"]
196                roles: ['editor']
197            'user2':
198                password: 'def456'
199                password: 'qwerty'
200        '/pub': true  # Pass true to allow anonymous access
201
202# Additional options for NTDomainController only:
203nt_dc:
204    preset_domain: null
205    preset_server: null
206
207# Additional options for PAMDomainController only:
208pam_dc:
209    service: 'login'
210    encoding: 'utf-8'
211    resetcreds: true
212
213# Additional options for HtpasswdDomainController only:
214htpasswd_dc:
215    htpasswd_file: '/path/to/wsgidav.htpasswd'
216
217# Additional options for HtdigestDomainController only:
218htdigest_dc:
219    htdigest_file: '/path/to/wsgidav.htdigest'
220
221
222# ----------------------------------------------------------------------------
223# User/Group Impersonating
224# (Requires `wsgidav.mw.impersonator.Impersonator`, which is disabled by default.)
225impersonator:
226    # enabling impersonating
227    enable: false
228
229    # custom map WebDAV (HTTP) usernames to Unix usernames
230    # custom_user_mapping:
231    #     leonlee: leo
232    #     jenifer: jenny
233
234    # or, use WebDAV (HTTP) usernames as is
235    custom_user_mapping: null
236
237
238# ----------------------------------------------------------------------------
239# CORS
240# (Requires `wsgidav.mw.cors.Cors`, which is enabled by default.)
241cors:
242    #: List of allowed Origins or '*'
243    #: Default: false, i.e. prevent CORS
244    allow_origin: null
245    # allow_origin: '*'
246    # allow_origin:
247    #   - 'https://example.com'
248    #   - 'https://localhost:8081'
249
250    #: List or comma-separated string of allowed methods (returned as
251    #: response to preflight request)
252    allow_methods:
253    # allow_methods: POST,HEAD
254    #: List or comma-separated string of allowed header names (returned as
255    #: response to preflight request)
256    allow_headers:
257    #   - X-PINGOTHER
258    #: List or comma-separated string of allowed headers that JavaScript in
259    #: browsers is allowed to access.
260    expose_headers:
261    #: Set to true to allow responses on requests with credentials flag set
262    allow_credentials: false
263    #: Time in seconds for how long the response to the preflight request can
264    #: be cached (default: 5)
265    max_age: 600
266    #: Add custom response headers (dict of header-name -> header-value items)
267    #: (This is not related to CORS or required to implement CORS functionality)
268    add_always:
269    #    'X-Foo-Header: 'qux'
270
271# ----------------------------------------------------------------------------
272# Property Manager
273# null: (default) no support for dead properties
274# true: Use wsgidav.prop_man.property_manager.PropertyManager
275#       which is an in-memory property manager (NOT persistent)
276#
277# Example: Use persistent shelve based property manager
278#     property_manager:
279#        class: wsgidav.prop_man.property_manager.ShelvePropertyManager
280#        kwargs:
281#            storage_path: 'wsgidav-props.shelve'
282
283property_manager: null
284
285#: Optional additional live property modification
286#: Note: by default live properties like file size and last-modified time are
287#: read-only, but that can be overridden here if the underlying DAV provider
288#: supports it. For now only the FileSystemProvider supports it and only namely
289#: changes to the last-modified timestamp. Enable it with the mutable_live_props
290#: list as below to allow clients to use the utime system call or e.g. the
291#: touch or cp / rsync commands with the preserve-timestamp flags on a mounted
292#: DAV share.
293#: Please note that the timestamp is set on the actual file or directory, so it
294#: is persistent even for in-memory property managers. It should also be noted
295#: that mutable last-modified may not be compliant with the RFC 4918.
296mutable_live_props:
297    # Enable to allow clients to use e.g. the touch or cp / rsync commands with the
298    # preserve-timestamp flags in a mounted DAV share (may be RFC4918 incompliant)
299    - '{DAV:}getlastmodified'
300
301
302# ----------------------------------------------------------------------------
303# Lock Manager Storage
304#
305# null: No lock support
306# true: (default) shortcut for
307#     lock_storage: wsgidav.lock_man.lock_storage.LockStorageDict
308#
309# Note that the default LockStorageDict works in-memory, so it is
310# NOT persistent.
311#
312# Example: Use persistent shelve based lock storage:
313#     lock_storage:
314#         class: wsgidav.lock_man.lock_storage.LockStorageShelve
315#         kwargs:
316#             storage_path: /path/to/wsgidav_locks.shelve
317#
318# Check the documentation on how to develop custom lock storage.
319
320lock_storage: true
321
322
323# ==============================================================================
324# DEBUGGING
325
326#: Set verbosity level (can be overridden by -v or -q arguments)
327verbose: 3
328
329#: Suppress version info in HTTP response headers and error responses
330suppress_version_info: false
331
332logging:
333    #: Enable logging when using wsgidav in library mode (always on, when running as CLI)
334    enable: null
335    #: Set logging output format
336    #: (see https://docs.python.org/3/library/logging.html#logging.Formatter)
337    logger_date_format: '%H:%M:%S'
338    logger_format: '%(asctime)s.%(msecs)03d - %(levelname)-8s: %(message)s'
339    # Example: Add date,thread id, and logger name:
340    # logger_date_format: '%Y-%m-%d %H:%M:%S'
341    # logger_format: '%(asctime)s.%(msecs)03d - <%(thread)05d> %(name)-27s %(levelname)-8s: %(message)s'
342
343    #: Enable specific module loggers
344    #: E.g. ['lock_manager', 'property_manager', 'http_authenticator', ...]
345    # enable_loggers: ['http_authenticator', ]
346
347    # Enable max. logging for certain http methods
348    # E.g. ['COPY', 'DELETE', 'GET', 'HEAD', 'LOCK', 'MOVE', 'OPTIONS', 'PROPFIND', 'PROPPATCH', 'PUT', 'UNLOCK']
349    debug_methods: []
350
351    # Enable max. logging during  litmus suite tests that contain certain strings
352    # E.g. ['lock_excl', 'notowner_modify', 'fail_cond_put_unlocked', ...]
353    debug_litmus: []
354
355
356# ----------------------------------------------------------------------------
357# WsgiDavDirBrowser
358
359dir_browser:
360    enable: true
361    #: List of fnmatch patterns that will be hidden in the directory listing
362    ignore:
363        - '.DS_Store'  # macOS folder meta data
364        - 'Thumbs.db'  # Windows image previews
365        - '._*'  # macOS hidden data files
366    #: Add a trailing slash to directory URLs (by generating a 301 redirect)
367    directory_slash: true
368    #: Display WsgiDAV icon in header
369    icon: true
370    #: Raw HTML code, appended as footer (true: use a default trailer)
371    response_trailer: true
372    #: Display the name and realm of the authenticated user (or 'anomymous')
373    show_user: true
374    show_logout: true
375    #: Send <dm:mount> response if request URL contains '?davmount'
376    #: (See https://tools.ietf.org/html/rfc4709)
377    davmount: true
378    #: Add a 'Mount' link at the top of the listing
379    davmount_links: false
380    #: Invoke MS Office documents for editing using WebDAV by adding a JavaScript
381    #: click handler.
382    #: - For IE 11 and below invokes the SharePoint ActiveXObject("SharePoint.OpenDocuments")
383    #: - If the custom legacy Firefox plugin is available, it will be used
384    #:   https://docs.microsoft.com/en-us/previous-versions/office/developer/sharepoint-2010/ff407576(v%3Doffice.14)
385    #: - Otherwise the Office URL prefix is used (e.g. 'ms-word:ofe|u|http://server/path/file.docx')
386    ms_sharepoint_support: true
387    #: Invoke Libre Office documents for editing using WebDAV
388    libre_office_support: true
389    #: The path to the directory that contains template.html and associated
390    #: assets.
391    #: The default is the htdocs directory within the dir_browser directory.
392    htdocs_path: null

Sample wsgidav.json

We can also use a JSON file for configuration. The structure is identical to the YAML format.

See the ./sample_wsgidav.json example. (Note that the parser allows JavaScript-style comments)

Configuration Tips

Running Behind a Reverse Proxy

If WsgiDAV is running behind a reverse proxy, …

For example, when nginx is used to expose the local WsgiDAV share http://127.0.0.1:8080/public_drive as http://example.com/drive, the configuration files may look like this:

wsgidav.yaml

host: 127.0.0.1
port: 8080
mount_path: "/drive"
provider_mapping:
    "/public_drive":  # Exposed as http://HOST/drive by nginx reverse proxy
        root: "fixtures/share"

nginx.conf:

http {
    ...
    server {
        listen       80;
        server_name  example.com;
        ...
        location /drive/ {
            proxy_pass http://127.0.0.1:8080/public_drive/;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header X-Forwarded-Host $host;
        }
        # If dir browser is enabled for WsgiDAV:
        location /drive/:dir_browser/ {
            proxy_pass http://127.0.0.1:8080/:dir_browser/;
        }

See the nginx docs for details.