Skip to content

audstanley/david

 
 

Repository files navigation

david - The simple WebDAV server... extended.

A new fork of dave

Introduction

david is a simple WebDAV server that provides the following features:

  • Single binary that runs under Windows, Linux and OSX.
  • Authentication via HTTP-Basic.
  • CRUD operation permissions
  • TLS support - if needed.
  • A simple user management which allows user-directory-jails as well as full admin access to all subdirectories.
  • Live config reload to allow editing of users without downtime.
  • A CLI tool to generate password hashes (bcrypt, argon2, scrypt)

It perfectly fits if you would like to give some people the possibility to upload, download or share files with common tools like the OSX Finder, Windows Explorer or Nautilus under Linux (or many other tools).

The project david is an extension from the project dave

Table of Contents

Installation

Build from sources

Setup

  1. Make sure to have Golang installed
  2. Clone the repository (or your fork)
git clone https://github.com/audstanley/david
  1. Build and install the binaries
cd cmd/david && go build . && mv ./david ~/go/bin/david
cd ../dcrypt && go build . && mv dcrypt ~/go/bin/dcrypt && cd ../..

Alternatively, use mage to build:

mage Build

This will create binaries in the dist/ directory.

Command Line Usage

The david CLI now uses Cobra with subcommands for better structure and help:

# Start the server (default command)
david server --config config.yaml

# Start server with overrides
david server --host 127.0.0.1 --port 9000 --debug

# Get help
david --help
david server --help
david completion --help

Available Commands:

  • server - Start the WebDAV server
  • help - Help about any command
  • completion - Generate autocompletion script

Server Flags:

  • -c, --config string - Path to configuration file
  • -H, --host string - Override host address
  • -p, --port string - Override port
  • -d, --debug - Enable debug logging
  • --production - Enable production (JSON) logging

Configuration

The configuration is done in form of a yaml file. david will scan the following locations for the presence of a config.yaml in the following order:

  • The directory ./config
  • The directory $HOME/.swd (swd was the initial project name of david)
  • The directory $HOME/.david
  • The current working directory .

Alternatively, the path to a configuration file can be specified on the command-line:

david server --config /path/to/config.yaml

You can also override configuration settings directly from command-line flags:

david server --config config.yaml --host 0.0.0.0 --port 8080 --debug

Priority: CLI flags override config file settings.

First steps

Here an example of a very simple but functional configuration:

address: "127.0.0.1"        # the bind address
port: "8000"                # the listening port
dir: "/home/myuser/webdav"  # the provided base dir
prefix: "/webdav"           # the url-prefix of the original url
users:
  user:                     # with password 'foo' and jailed access to '/home/myuser/webdav/user'
    password: "$2a$10$yITzSSNJZAdDZs8iVBQzkuZCzZ49PyjTiPIrmBUKUpB0pwX7eySvW"
    subdir: "/user"
    permissions: "r"        # read only
  admin:                    # with password 'foo' and access to '/home/myuser/webdav'
    password: "$2a$10$DaWhagZaxWnWAOXY0a55.eaYccgtMOL3lGlqI3spqIBGyM0MD.EN6"
    permissions: "crud"

With this configuration you'll grant access for two users and the WebDAV server is available under http://127.0.0.1:8000/webdav.

TLS

At first, use your favorite toolchain to obtain a SSL certificate and keyfile (if you don't already have some).

Here an example with openssl:

# Generate a keypair
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365
# Remove the passphrase from the key file
openssl rsa -in key.pem -out clean_key.pem

Now you can reference your keypair in the configuration via:

address: "127.0.0.1"    # the bind address
port: "8000"            # the listening port
dir: "/home/myuser/webdav"     # the provided base directory
tls:
  keyFile: clean_key.pem
  certFile: cert.pem
users:
  ...

The presence of the tls section is completely enough to let the server start with a TLS secured HTTPS connection.

In the current release version you must take care, that the private key doesn't need a passphrase. Otherwise starting the server will fail.

Cross Origin Resource Sharing (CORS)

In case you intend to operate this server from a web browser based application, you might need to allow CORS access. To achieve that, you can configure the host you want to grant access to:

cors:
  origin: "*"        # the origin to allow, or '*' for all
  credentials: true  # whether to allow credentials via CORS

Note however that this has security implications, so be careful in production environments.

Behind a proxy

david will also work behind a reverse proxy. Here is an example configuration with apache2 httpd's mod_proxy:

<Location /webdav>
  ProxyPass           https://webdav-host:8000/
  ProxyPassReverse    https://webdav-host:8000/
</Location>

Here is an example of david using a json caddyfile for a reverse proxy:

{
    "admin": {
      "disabled": false,
      "listen": "0.0.0.0:2019",
      "enforce_origin": false,
      "origins": [
        "127.0.0.1"
      ],
      "config": {
        "persist": false
      }
    },
    "apps": {
      "http": {
        "servers": {
          "MyServers": {
            "listen": [
              ":443"
            ],
            "routes": [
              {
                "match": [
                  {
                    "host": [
                      "files.example.com"
                    ]
                  }
                ],
                "handle": [
                  {
                    "handler": "reverse_proxy",
                    "upstreams": [
                      {
                        "dial": ":8000"
                      }
                    ]
                  }
                ]
              }
            ]
          }
        }
      }
    }
  }

User management

User management in david is very simple, but optional. You don't have to add users if it's not necessary for your use case. But if you do, each user in the config.yaml must have a password and can have a subdirectory.

The password must be in form of a hashed password. You can generate one calling the shipped CLI tool dcrypt passwd. David supports multiple hashing algorithms for flexibility and performance:

Supported Algorithms:

  • bcrypt - Battle-tested, widely compatible (default)
  • argon2 - Modern, memory-hard, Argon2id winner (2015 password hashing contest)
  • scrypt - Memory-hard, resistant to GPU/ASIC attacks

Generate with dcrypt passwd:

# Default: bcrypt
dcrypt passwd --password "your-password"

# Specify algorithm and cost
dcrypt passwd --password "your-password" --algorithm bcrypt --cost 12
dcrypt passwd --password "your-password" --algorithm argon2
dcrypt passwd --password "your-password" --algorithm scrypt

# Interactive mode
dcrypt passwd
Enter password: ******
Hashed Password (bcrypt): $2a$10$...

BCPT CLI Options:

  • -p, --password string - Password to hash (required)
  • --algorithm string - Hash algorithm: bcrypt, argon2, scrypt (default: bcrypt)
  • -c, --cost int - Hash cost factor (default: 10 for bcrypt)

David Server Configuration:

Configure the hash algorithm in your config.yaml:

hash:
  algorithm: bcrypt  # bcrypt, argon2, or scrypt
  params:
    bcrypt_cost: 10
    # argon2 (uses fixed parameters):
    # memory: 64
    # iterations: 3
    # parallelism: 4
    # scrypt:
    # scrypt_n: 16384
    # scrypt_r: 8
    # scrypt_p: 1

Or override from CLI:

david server --config config.yaml --hash-algorithm argon2

Security Comparison (benchmarks on this system):

Algorithm Security Memory Speed (Hash Gen) Speed (Verify) Best For
bcrypt High Low (~4KB) 66.93 ms 63.08 ms General use, maximum compatibility
argon2 Highest High (~64MB) 81.06 ms <1 µs Modern applications, recommended
scrypt High High (~128MB) 81.64 ms 81.66 ms GPU resistance

Note: Benchmarks measured on Linux with Go 1.23, 100 iterations. Run dcrypt benchmark to measure on your system.

About SHA: We do not support SHA-256/SHA-512 for password hashing. These algorithms are designed for general-purpose hashing and are intentionally fast, making them unsuitable for passwords (see issue #2). For security, we recommend memory-hard algorithms like argon2 or bcrypt.

Notes:

  • All three algorithms are memory-hard, providing resistance against GPU/ASIC attacks
  • Argon2 is the current recommended algorithm (winner of the 2015 Password Hashing Competition)
  • Bcrypt remains the safest choice for maximum compatibility and battle-testing
  • David automatically detects the hash algorithm from the hash prefix, so switching algorithms won't break existing users

If a subdirectory is configured for a user, the user is jailed within it and can't see anything that exists outside of this directory. If no subdirectory is configured for an user, the user can see and modify all files within the base directory.

Logging

You can enable / disable logging for the following operations:

  • Creation of files or directories
  • Reading of files or directories
  • Updating of files or directories
  • Deletion of files or directories

You can also enable or disable the error log.

All file-operation logs are disabled per default until you will turn it on via the following config entries:

log:
  production: false
  debug: true
  error: true
  create: true
  read: true
  update: true
  delete: true
...

Log Formats:

  • Text Mode (production: false): Human-readable format with timestamps
  • JSON Mode (production: true): Structured JSON format for log aggregation tools

Control via CLI:

Enable debug or production mode from command line:

david server --debug           # Enable debug logging
david server --production      # Enable JSON log format

Priority: CLI flags override config file settings.

Log Examples:

Attached TTY (text format):

INFO[0000] Server is starting and listening              address=0.0.0.0 port=8000 security=none

Detached TTY (timestamp format):

time="2018-04-14T20:46:00+02:00" level=info msg="Server is starting and listening" address=0.0.0.0 port=8000 security=none

Production mode (JSON format):

{"level":"info","msg":"Server is starting and listening","address":"0.0.0.0","port":"8000","security":"none"}

Live reload

There is no need to restart the server itself, if you're editing the user or log section of the configuration. The config file will be re-read and the application will update it's own configuration silently in background.

Connecting

You could simply connect to the WebDAV server with an HTTP(S) connection and a tool that allows the WebDAV protocol.

For example: Under OSX you can use the default file management tool Finder. Press CMD+K, enter the server address (e.g. http://localhost:8000) and choose connect.

CLI Reference

david

The WebDAV server with subcommand structure:

david [flags]
david [command]

Available Commands:

  • server - Start the WebDAV server
  • help - Help about any command
  • completion - Generate autocompletion script

Global Flags:

  • -h, --help - Help for david

Server Command:

david server [flags]

Flags:

  • -c, --config string - Path to configuration file
  • -H, --host string - Override host address
  • -p, --port string - Override port
  • -d, --debug - Enable debug logging
  • --production - Enable production (JSON) logging
  • --hash-algorithm string - Hash algorithm: bcrypt, argon2, scrypt (default: from config)

dcrypt

Password hash generator supporting multiple algorithms:

dcrypt [command]

Available Commands:

  • passwd - Generate a password hash (bcrypt, argon2, or scrypt)
  • help - Help about any command

Passwd Command:

dcrypt passwd [flags]

Flags:

  • -p, --password string - Password to hash (required)
  • --algorithm string - Hash algorithm: bcrypt, argon2, scrypt (default: bcrypt)
  • -c, --cost int - Hash cost factor (default: 10 for bcrypt)
  • -h, --help - Help for passwd

Examples:

# Generate bcrypt hash (default)
dcrypt passwd --password "mysecretpassword"
Hashed Password (bcrypt): $2a$10$...

# Generate with specific algorithm and cost
dcrypt passwd --password "secret" --algorithm bcrypt --cost 12

# Generate argon2 hash with custom parameters
dcrypt passwd --password "secret" --algorithm argon2 \
  --argon2-memory 65536 --argon2-iterations 3 --argon2-parallelism 4

# Generate scrypt hash with custom parameters
dcrypt passwd --password "secret" --algorithm scrypt \
  --scrypt-n 16384 --scrypt-r 8 --scrypt-p 1

# Generate interactively
dcrypt passwd
Enter password: ******
Hashed Password (bcrypt): $2a$10$...

Issues on Windows?

Windows 11 is not going to let you map the network drive with a self signed certificate or no running david with no certificate (at all). Consider using Caddy, or use Cyberduck - which will let you connect with a self signed certificate. There might be a way around this by editing a windows register, but I don't recommend that. Just use Cyberduck, or try out Cybermount. The easiest option is a reverse proxy running Caddy, in my honest opinion. Caddy v2 will sign the certificate, and you can run david with no TLS needed since Caddy is handling the encryption over the internet.

License

Please be aware of the licenses of the components we use in this project. Everything else that has been developed by the contributions to this project is under the Apache 2 License.

About

A totally simple and very easy to configure stand alone webdav server... extended.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • Go 99.4%
  • Other 0.6%