texxasrulez/rounddav

RoundDAV - a SabreDAV-based CalDAV/CardDAV server tailored for Roundcube.

Maintainers

Package info

github.com/texxasrulez/rounddav

Type:project

pkg:composer/texxasrulez/rounddav

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

0.0.1 2025-12-15 21:58 UTC

This package is auto-updated.

Last update: 2026-03-03 02:31:47 UTC


README

Downloads Packagist Downloads Packagist Version Github License GitHub Stars GitHub Issues GitHub Contributors GitHub Forks Donate Paypal

A lightweight CalDAV, CardDAV, and WebDAV storage engine designed for self-hosters who want full control without dragging in a monster stack. RoundDAV powers calendars, contacts, and file storage behind Roundcube - cleanly and predictably.

While this may work like any other sabre based server, this one is tailored for Roundcube specifically.

There are 3 Roundcube plugins to use with this and extend the bridge between the two.

Required for use with Roundcube:

RoundDAV Provision Roundcube Plugin

Recommended Plugins:

RoundDAV Files Roundcube Plugin

RoundDAV Bookmarks Roundcube Plugin

Features

  • CalDAV & CardDAV: Standards-compliant calendars and addressbooks
  • WebDAV Filesystem: Per-user storage rooted at a filesystem path you control
  • Provisioning API: Roundcube can create DAV users automatically
  • SSO-Ready: Includes /public/sso_login.php and /public/sso_logout.php
  • Admin UI: Simple administration panel for principals, calendars, addressbooks
  • Per-User Extras: Extra calendars and addressbooks can be created on first login
  • Clean PHP: No frameworks, minimal dependencies, easy to debug

Directory Layout

Typical layout on disk:

rounddav/
  config/
    config.dist.php
    config.php
  public/
    index.php
    install.php
    admin/
    files/
    api.php
    sso_login.php
    sso_logout.php
  src/
    Provision/
    Dav/
    ...
  • config/ – configuration files
  • public/ – web-exposed entry points (admin UI, files UI, SSO, API)
  • src/ – RoundDAV internals (provisioning, DAV backends, etc.)

Installation

  1. Copy rounddav/ to your server (outside your main vhost if you like).
  2. Point a vhost or alias at rounddav/public/.

Example Nginx snippet:

location /rounddav/ {
    alias /var/www/rounddav/public/;
    index index.php;
}
  1. Run the installer in your browser:
https://your.server/rounddav/public/install.php
  1. Fill in:

    • Database DSN / user / password
    • Files root path (for WebDAV file storage)
    • Admin username + password
  2. Submit. The installer writes config/config.php and initializes the database.

  3. Run composer update in root to install dependencies.

Configuration Overview

config/config.php is generated from config.dist.php and contains (at least):

return [
    'database' => [
        'dsn'      => 'mysql:host=localhost;dbname=rounddav',
        'user'     => 'rounddav',
        'password' => 'secret',
        'options'  => [],
    ],

    'files' => [
        'root'       => '/srv/rounddav/files',
        'public_url' => 'https://your.server/rounddav/public/files/',
    ],

    'admin' => [
        'username'      => 'admin',
        'email'         => 'admin@example.com',
        'password_hash' => '$2y$10$...',
    ],

    'provision' => [
        'shared_secret'    => 'change_me_provision',
        'principal_prefix' => 'principals',
    ],

    'sso' => [
        'enabled' => true,
        'secret'  => 'change_me_sso',
        'ttl'     => 600,
    ],
];

Key points:

  • files.root – base directory for per-user WebDAV storage.
  • files.public_url – where the browser reaches the Files UI.
  • admin.email (or admin.username) – use this to identify the admin user in templates.
  • provision.shared_secret – for API calls if you ever protect them further.
  • sso.secret – must match rounddav_sso_secret in the Roundcube rounddav_provision plugin.
  • security.headers – optional response headers. Leave x_frame_options empty (default) if Files UI must be embedded by Roundcube on a different origin.

Provisioning API

RoundDAV exposes a simple HTTP API for provisioning users:

POST /rounddav/public/api.php?r=provision/user
Content-Type: application/json

Example payload (this is what the Roundcube plugin sends):

{
  "username": "user@example.com",
  "password": "plaintext-or-derived",
  "extra_calendars": [
    {
      "uri": "todo",
      "displayname": "Tasks",
      "mode": "tasks",
      "shared": false
    }
  ],
  "extra_addressbooks": [
    {
      "uri": "work",
      "displayname": "Work Contacts",
      "shared": false
    }
  ]
}

The server will:

  • Ensure the principal and credentials exist
  • Ensure the default calendar + addressbook exist
  • Ensure any additional calendars/addressbooks defined in the request exist

The endpoint replies with JSON, e.g.:

{
  "status": "ok",
  "message": "Provisioning OK for user@example.com",
  "principal_uri": "principals/user@example.com",
  "principal_id": 6
}

SSO Endpoints

These are used by Roundcube (rounddav_provision + rounddav_files) to log users into the web UI without a second login.

Login

GET /rounddav/public/sso_login.php?user=<user>&ts=<unix>&sig=<hmac>
  • user – principal identifier (usually the email / Roundcube username)
  • ts – Unix timestamp when the token was issued
  • sighash_hmac('sha256', "$user|$ts", $config['sso']['secret'])

If valid:

  • Sets $_SESSION['rounddav_files_user'] = $user
  • Redirects the browser to files.public_url or ./files/

Logout

GET /rounddav/public/sso_logout.php?user=<user>&ts=<unix>&sig=<hmac>
  • Signature is based on "$user|$ts|logout"

If valid:

  • Destroys the PHP session
  • Leaves no visible output

Roundcube’s logout hook fires a tiny new Image().src = ".../sso_logout.php?..."; call to trigger this.

Admin UI

Accessible under:

https://your.server/rounddav/public/admin/

You can:

  • View and manage principals
  • Create/delete calendars and addressbooks for each principal
  • Edit calendar/addressbook properties (URI, displayname, flags)
  • Toggle options like “tasks only” vs “events only” vs both

The Admin UI is intentionally minimal, built for admins who already know what DAV is.

Admin README.md

Config Backup, Restore, and Embed-Safe Security Settings

The Admin UI (/public/admin/?action=config) now includes config snapshot and backup tools for config/config.php.

Backup and restore workflow

In Config Snapshot:

  • Create backup now writes a timestamped config-YYYYmmdd-HHMMSS-xxxxxxxx.php file under var/config_backups/
  • Download exports a single backup file
  • Restore replaces the live config.php with the selected backup
  • Download all as ZIP streams all backups as one archive for off-host storage

RoundDAV also creates a backup automatically before config writes/imports/restores.

Retention policy

Retention is configurable in the same card:

  • Keep newest backups (backups.config.keep_last)
  • Delete backups older than days (backups.config.max_age_days, 0 disables age pruning)
  • Auto-prune after config writes/restores/backups (backups.config.auto_prune)

Defaults in config/config.dist.php:

'backups' => [
    'config' => [
        'keep_last' => 30,
        'max_age_days' => 0,
        'auto_prune' => true,
    ],
],

Recommended settings for Roundcube iframe embedding

If rounddav_files is shown inside Roundcube via iframe (especially cross-origin):

  • Keep security.headers.enabled = true
  • Keep security.headers.x_content_type_options = true
  • Keep security.headers.referrer_policy = strict-origin-when-cross-origin
  • Keep security.headers.x_frame_options = '' (empty; do not set SAMEORIGIN/DENY for cross-origin embeds)
  • If CSP is enabled, ensure frame-ancestors includes your Roundcube origin (for example https://mail.example.com)

Use Verify Current Headers in the Security diagnostics panel to confirm live responses from Admin/Files endpoints match expected values.

Files UI

Accessible under:

https://your.server/rounddav/public/files/

This is the generic Files interface that rounddav_files embeds in an iframe inside Roundcube. It:

  • Shows per-user directories under your configured files.root
  • Allows uploads, downloads, deletions (depending on your implementation)
  • Is styled to roughly match Roundcube skins when embedded

Philosophy

RoundDAV is meant to be:

  • Small enough to understand
  • Strong enough to be useful
  • Quiet enough to disappear behind Roundcube

If you know Roundcube and a bit of PHP, you should be able to debug or extend this without fighting it.

Enjoy!

💰 Donations 💰

If you use this plugin and would like to show your appreciation by buying me a cup of coffee, I surely would appreciate it. A regular cup of Joe is sufficient, but a Starbucks Coffee would be better ...
Zelle (Zelle is integrated within many major banks Mobile Apps by default) - Just send to texxasrulez at yahoo dot com
No Zelle in your banks mobile app, no problem, just click Paypal and I can make a Starbucks run ...

I appreciate the interest in this plugin and hope all the best ...