n3xt0r / laravel-webdav-server
A WebDAV server implementation for Laravel based on SabreDAV, with support for Laravel filesystem disks.
Fund package maintenance!
Requires
- php: ^8.4|^8.5
- illuminate/contracts: ^12.0|^13.0
- sabre/dav: ~4.6.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- brianium/paratest: ^7.20
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^10.0.0||^9.0.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
This package is auto-updated.
Last update: 2026-04-12 20:01:12 UTC
README
A WebDAV server for Laravel powered by SabreDAV, exposing any configured Flysystem disk through the WebDAV protocol.
Warning
This package is currently under active development and not yet production-ready. APIs, configuration keys, and behaviour may change without notice between releases. Use in production at your own risk.
Overview
Laravel WebDAV Server provides a native WebDAV server implementation for Laravel applications, built on top of SabreDAV.
The primary goal of this package is to bridge the gap between:
- the WebDAV protocol (via SabreDAV)
- and Laravel's filesystem abstraction (Flysystem)
Instead of working with local filesystem paths directly, this package maps WebDAV nodes to Laravel disks, making it possible to expose any configured storage (local, S3, etc.) through a WebDAV interface.
Features
- WebDAV server powered by SabreDAV
- Native integration with Laravel filesystem disks
- User-based storage mapping via pluggable resolvers
- Pluggable authentication layer (no coupling to Laravel auth)
- Clean separation between transport (WebDAV) and domain logic
- Fully extensible architecture (custom storage, auth, authorization)
Requirements
- PHP 8.4+
- Laravel 12+
Installation
composer require n3xt0r/laravel-webdav-server
php artisan vendor:publish --tag="laravel-webdav-server-config"
php artisan migrate
Architecture
Configuration
// config/webdav-server.php – accessed at runtime as webdav.* return [ 'base_uri' => '/webdav/', 'storage' => [ 'disk' => 'local', // any disk from config/filesystems.php 'prefix' => 'webdav', // each user's root: {prefix}/{principal_id} ], 'auth' => [ 'model' => null, // required: App\Models\WebDavAccount::class 'username_column' => 'username', 'password_column' => 'password_encrypted', 'enabled_column' => 'enabled', // set to '' to skip the check 'user_id_column' => 'user_id', 'display_name_column' => 'username', ], ];
Route
Route::any('/webdav/{path?}', \N3XT0R\LaravelWebdavServer\Http\Controllers\WebDavController::class) ->where('path', '.*');
Extension Points
All default bindings use bindIf() – bind your own implementation in AppServiceProvider::register() and it takes
precedence automatically.
| Contract | Default | Override to… |
|---|---|---|
CredentialValidatorInterface |
DatabaseCredentialValidator |
Custom auth (LDAP, tokens, …) |
WebDavAccountRepositoryInterface |
EloquentWebDavAccountRepository |
Non-Eloquent user stores |
SpaceResolverInterface |
DefaultSpaceResolver |
Per-user disk / path routing |
PathAuthorizationInterface |
GatePathAuthorization |
Replace Gate with ACL, RBAC, … |
Default storage mapping: webdav.storage.prefix/{principal.id} on webdav.storage.disk.
Authorization / Policies
The default GatePathAuthorization calls Gate::forUser($principal->user)->inspect($ability, $resource) before every
filesystem operation. The resource passed to the policy is always WebDavPathResourceDto with two public properties:
disk and path.
The five policy abilities:
| Ability | When |
|---|---|
read |
PROPFIND, GET, file metadata |
write |
PUT (overwrite) |
delete |
DELETE (recursively checked on every node) |
createDirectory |
MKCOL |
createFile |
PUT (new file) |
The service provider auto-registers
App\Policies\WebDavPathPolicy– you must create this class in your application. A ready-to-use reference implementation is shipped insrc/Policies/WebDavPathPolicy.php.
To use a different policy class:
// AppServiceProvider::boot() Gate::policy( \N3XT0R\LaravelWebdavServer\DTO\Auth\WebDavPathResourceDto::class, \App\Policies\MyCustomPolicy::class, );
To bypass Gate entirely, bind your own PathAuthorizationInterface implementation.
Throw Sabre\DAV\Exception\Forbidden on denial – never a Laravel HTTP exception.
Supported WebDAV Operations
PROPFIND · GET · PUT · DELETE · MKCOL
Developer Commands
composer run test # Pest test suite (random order) composer run lint # auto-fix code style (Laravel Pint) composer run test:lint # dry-run style check composer run serve # workbench app → http://0.0.0.0:8000
License / Copyright
Copyright (c) 2026 Ilya Beliaev This project includes code licensed under MIT.
The MIT License (MIT). See LICENSE.md for details.
