Skip to content

WebDAV Backup Destination

ZestSSH can back up encrypted .zest files to any standards-compliant WebDAV server. This provides a self-hosted backup option that you fully control.

The WebDAV implementation uses a minimal subset of the protocol and is compatible with:

  • Nextcloud (see also Nextcloud-specific setup)
  • ownCloud
  • Synology WebDAV Server
  • Apache mod_dav
  • Nginx with ngx_http_dav_module
  • Any standards-compliant WebDAV endpoint

ZestSSH uses five WebDAV/HTTP methods:

MethodPurpose
PUTUpload a backup file
GETDownload a backup file
PROPFINDList directory contents (Depth: 0 for auth check, Depth: 1 for file listing)
DELETERemove a backup file
MKCOLCreate the remote backup directory

No other WebDAV extensions (LOCK, COPY, MOVE, PROPPATCH) are required.

WebDAV uses HTTP Basic Authentication. Credentials are sent as a Base64-encoded username:password pair in the Authorization header with every request.

No OAuth flow is required — you provide your username and password during setup, and they are stored in the destination configuration.

FieldDescriptionExample
Server URLBase URL of the WebDAV serverhttps://cloud.example.com/remote.php/dav/files/username
UsernameWebDAV usernamejohn
PasswordWebDAV password or app passwordapp-specific-password-here
FieldDefaultDescription
Remote Path/ZestSSH/backups/Directory on the server where backups are stored
LabelWebDAVDisplay name in the backup destination list

The remote path is automatically normalized:

  • A leading / is added if missing.
  • A trailing / is added if missing.
  • Example: ZestSSH/backups becomes /ZestSSH/backups/.
  1. Go to Settings > Backup & Restore > Backup Destinations.
  2. Tap Add Destination > WebDAV.
  3. Enter the server URL, username, and password.
  4. Optionally customize the remote path and label.
  5. ZestSSH tests the connection with a PROPFIND (Depth: 0) request.
  6. If the remote directory does not exist, it is created with MKCOL.

If the remote path does not exist, ZestSSH creates it recursively. For a path like /ZestSSH/backups/:

  1. MKCOL /ZestSSH/
  2. MKCOL /ZestSSH/backups/

Status codes 201 (created) and 405 (already exists) are both treated as success.

  1. The directory is ensured to exist (MKCOL if needed).
  2. The .zest file is uploaded via PUT with Content-Type: application/octet-stream.
  3. Status codes 201 (created) or 204 (no content) indicate success.
  1. PROPFIND with Depth: 1 on the backup directory.
  2. The XML response is parsed to extract .zest files with their:
    • Filename (from <d:href>)
    • File size (from <d:getcontentlength>)
    • Last modified date (from <d:getlastmodified>, RFC 2822 format)
  3. Results are sorted newest-first.

The XML parsing uses regex-based extraction rather than a full XML parser, handling both lowercase (<d:response>) and uppercase (<D:response>) namespace prefixes that vary by server.

  1. GET request to the file URL.
  2. The response body is written to a local file.
  1. DELETE request to the file URL.
  2. Status codes 200 or 204 indicate success.

WebDAV backups survive app uninstall because they are stored on an external server. This makes WebDAV a better long-term backup destination compared to local storage.

The isAuthenticated() method sends a lightweight PROPFIND (Depth: 0) to verify that:

  • The server is reachable.
  • Credentials are valid.
  • The remote path exists (or can be created).

A 207 (Multi-Status) or 200 response indicates success. This check runs before each backup operation.

  • Credentials are stored in the destination configuration JSON. Use app-specific passwords (not your main account password) when available.
  • Always use HTTPS URLs to prevent credential interception.
  • The backup files themselves are encrypted with AES-256-GCM regardless of the transport security — even if someone gains access to your WebDAV server, they cannot read the backup contents without the backup password.