A collection of ready-to-use configurations for common deployment scenarios.
Expose a single folder publicly with read-only access. No credentials required.
# docker-compose.yml
services:
webdav:
image: ghcr.io/vaggeliskls/webdav-server:latest
ports:
- "80:8080"
environment:
SERVER_NAME: localhost
FOLDER_PERMISSIONS: "/files:public:ro"
AUTO_CREATE_FOLDERS: "true"All users share the same credentials file. Any authenticated user can access /files with full read-write.
# docker-compose.yml
services:
webdav:
image: ghcr.io/vaggeliskls/webdav-server:latest
ports:
- "80:8080"
volumes:
- ./data:/var/lib/dav/data
environment:
SERVER_NAME: localhost
FOLDER_PERMISSIONS: "/files:*:rw"
AUTO_CREATE_FOLDERS: "true"
BASIC_AUTH_ENABLED: "true"
BASIC_USERS: "alice:alice123 bob:bob123"Access the server:
# Basic authentication (curl's default)
curl -u alice:alice123 http://localhost/files/
# Upload a file
curl -u alice:alice123 -T myfile.txt http://localhost/files/myfile.txt
# Create a directory
curl -u alice:alice123 -X MKCOL http://localhost/files/newfolder/Use Digest authentication for improved security. Passwords are never sent in plain text over the network.
# docker-compose.yml
services:
webdav:
image: ghcr.io/vaggeliskls/webdav-server:latest
ports:
- "80:8080"
volumes:
- ./data:/var/lib/dav/data
environment:
SERVER_NAME: localhost
FOLDER_PERMISSIONS: "/files:*:rw"
AUTO_CREATE_FOLDERS: "true"
DIGEST_AUTH_ENABLED: "true"
BASIC_USERS: "alice:alice123 bob:bob123"Access the server with Digest authentication:
# Force Digest authentication
curl -u alice:alice123 --digest http://localhost/files/
# Upload a file
curl -u alice:alice123 --digest -T myfile.txt http://localhost/files/myfile.txt
# Auto-negotiate (curl will choose Digest automatically)
curl -u alice:alice123 --anyauth http://localhost/files/Apache's file-based Basic and Digest auth use incompatible password file formats and cannot run simultaneously on the same resource. You must enable one or the other.
Use Basic (recommended when behind HTTPS — simpler, universally supported):
environment:
BASIC_AUTH_ENABLED: "true"
DIGEST_AUTH_ENABLED: "false"
BASIC_USERS: "alice:alice123 bob:bob123"curl -u alice:alice123 http://localhost/files/Use Digest (credentials never sent in plaintext — useful without HTTPS):
environment:
BASIC_AUTH_ENABLED: "false"
DIGEST_AUTH_ENABLED: "true"
BASIC_USERS: "alice:alice123 bob:bob123"curl --digest -u alice:alice123 http://localhost/files/Note: If both
BASIC_AUTH_ENABLEDandDIGEST_AUTH_ENABLEDare set totrue, Basic takes precedence.
A public read-only area alongside a private read-write folder restricted to specific users.
# docker-compose.yml
services:
webdav:
image: ghcr.io/vaggeliskls/webdav-server:latest
ports:
- "80:8080"
volumes:
- ./data:/var/lib/dav/data
environment:
SERVER_NAME: localhost
FOLDER_PERMISSIONS: "/public:public:ro,/private:alice:rw"
AUTO_CREATE_FOLDERS: "true"
BASIC_AUTH_ENABLED: "true"
BASIC_USERS: "alice:alice123"GET http://localhost/public/→ accessible without credentialsGET http://localhost/private/→ requiresalice:alice123PUT http://localhost/private/file.txt→ allowed for alice (rw)PUT http://localhost/public/file.txt→ blocked (ro)
Each user gets their own private folder. A shared area is available to all authenticated users.
# docker-compose.yml
services:
webdav:
image: ghcr.io/vaggeliskls/webdav-server:latest
ports:
- "80:8080"
volumes:
- ./data:/var/lib/dav/data
environment:
SERVER_NAME: localhost
FOLDER_PERMISSIONS: "/shared:*:ro,/alice:alice:rw,/bob:bob:rw"
AUTO_CREATE_FOLDERS: "true"
BASIC_AUTH_ENABLED: "true"
BASIC_USERS: "alice:alice123 bob:bob123"/shared— read-only for any authenticated user/alice— read-write foraliceonly/bob— read-write forbobonly
Allow all authenticated users to access a folder except one or more explicitly blocked users.
# docker-compose.yml
services:
webdav:
image: ghcr.io/vaggeliskls/webdav-server:latest
ports:
- "80:8080"
volumes:
- ./data:/var/lib/dav/data
environment:
SERVER_NAME: localhost
FOLDER_PERMISSIONS: "/shared:* !charlie:ro,/private:alice bob:rw"
AUTO_CREATE_FOLDERS: "true"
BASIC_AUTH_ENABLED: "true"
BASIC_USERS: "alice:alice123 bob:bob123 charlie:charlie123"GET http://localhost/shared/withaliceorbob→ allowedGET http://localhost/shared/withcharlie→403 Forbidden- Multiple exclusions:
"* !charlie !dave"
Authenticate users against an LDAP/Active Directory server. All authenticated users can access /files.
# docker-compose.yml
services:
webdav:
image: ghcr.io/vaggeliskls/webdav-server:latest
ports:
- "80:8080"
volumes:
- ./data:/var/lib/dav/data
environment:
SERVER_NAME: mydomain.local
FOLDER_PERMISSIONS: "/files:*:rw"
AUTO_CREATE_FOLDERS: "true"
LDAP_ENABLED: "true"
LDAP_URL: "ldaps://ldap.mydomain.local"
LDAP_ATTRIBUTE: "uid"
LDAP_BASE_DN: "ou=users,dc=mydomain,dc=local"
LDAP_BIND_DN: "uid=searchuser,ou=users,dc=mydomain,dc=local"
LDAP_BIND_PASSWORD: "securepassword"Apache tries LDAP first. If LDAP is unreachable or the user is not found, it falls back to the local password file.
# docker-compose.yml
services:
webdav:
image: ghcr.io/vaggeliskls/webdav-server:latest
ports:
- "80:8080"
volumes:
- ./data:/var/lib/dav/data
environment:
SERVER_NAME: mydomain.local
FOLDER_PERMISSIONS: "/files:*:rw"
AUTO_CREATE_FOLDERS: "true"
LDAP_ENABLED: "true"
LDAP_URL: "ldaps://ldap.mydomain.local"
LDAP_ATTRIBUTE: "uid"
LDAP_BASE_DN: "ou=users,dc=mydomain,dc=local"
LDAP_BIND_DN: "uid=searchuser,ou=users,dc=mydomain,dc=local"
LDAP_BIND_PASSWORD: "securepassword"
BASIC_AUTH_ENABLED: "true"
BASIC_USERS: "localadmin:adminpass"Expose the server via Traefik with rate limiting. The webdav container is not directly port-exposed.
# docker-compose.yml
services:
webdav:
image: ghcr.io/vaggeliskls/webdav-server:latest
volumes:
- ./data:/var/lib/dav/data
networks:
- proxy
environment:
SERVER_NAME: files.mydomain.com
FOLDER_PERMISSIONS: "/files:*:rw"
AUTO_CREATE_FOLDERS: "true"
BASIC_AUTH_ENABLED: "true"
BASIC_USERS: "alice:alice123"
labels:
- "traefik.enable=true"
- "traefik.http.routers.webdav.rule=Host(`files.mydomain.com`)"
- "traefik.http.routers.webdav.entrypoints=web"
- "traefik.http.services.webdav.loadbalancer.server.port=8080"
# --- Rate limiting + connection cap (per client IP) ------------------
- "traefik.http.middlewares.webdav-ratelimit.ratelimit.average=20"
- "traefik.http.middlewares.webdav-ratelimit.ratelimit.burst=40"
- "traefik.http.middlewares.webdav-ratelimit.ratelimit.period=1s"
- "traefik.http.middlewares.webdav-inflight.inflightreq.amount=50"
- "traefik.http.routers.webdav.middlewares=webdav-ratelimit,webdav-inflight"
traefik:
image: traefik:v3.6.9
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
volumes:
# Read-only: Traefik only needs to read the Docker API, never write it.
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- proxy
networks:
proxy:
driver: bridgeTuning:
average/burst/periodthrottle the request rate per client IP;inflightreq.amountcaps simultaneous in-flight requests. The limit is keyed on the direct client IP by default — only add anipstrategy.depthif a CDN/proxy sits in front of Traefik, otherwise a spoofedX-Forwarded-Forcan bypass it.
Enable CORS for web clients and expose a health check endpoint for uptime monitoring.
# docker-compose.yml
services:
webdav:
image: ghcr.io/vaggeliskls/webdav-server:latest
ports:
- "80:8080"
volumes:
- ./data:/var/lib/dav/data
environment:
SERVER_NAME: localhost
FOLDER_PERMISSIONS: "/files:*:rw"
AUTO_CREATE_FOLDERS: "true"
BASIC_AUTH_ENABLED: "true"
BASIC_USERS: "alice:alice123"
CORS_ENABLED: "true"
CORS_ORIGIN: "https://myapp.example.com"
HEALTH_CHECK_ENABLED: "true"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/_health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s# Health check
curl http://localhost/_health # → 200 OKFor any example above you can extract environment variables into an .env file and reference it with env_file:
# .env
SERVER_NAME=localhost
FOLDER_PERMISSIONS=/public:public:ro,/private:alice:rw
AUTO_CREATE_FOLDERS=true
BASIC_AUTH_ENABLED=true
BASIC_USERS=alice:alice123 bob:bob123
CORS_ENABLED=false
HEALTH_CHECK_ENABLED=false# docker-compose.yml
services:
webdav:
image: ghcr.io/vaggeliskls/webdav-server:latest
ports:
- "80:8080"
volumes:
- ./data:/var/lib/dav/data
env_file:
- .env