WebDAV Server
Overview
WebDAV Server delivers hacdias/webdav, a fast, simple, self-hosted WebDAV server written as a single static Go binary. WebDAV lets you mount and manage a remote directory as if it were a local drive from Windows Explorer, macOS Finder, Linux file managers and any WebDAV client. It works as a drop-in remote file share, backup target or document store that you run and own inside your own Azure subscription.
This SecureAnyCloud image installs the official webdav binary at /usr/local/bin/webdav, running as the webdav service. It serves a directory at /var/lib/webdav/data on the OS disk over HTTPS on port 443, with configurable per-user permissions for create, read, update and delete. A webdav-firstboot.service oneshot creates the credentials on first boot.
WebDAV is a protocol, not a web application, so there is no web UI to sign in to. You drive it with any WebDAV client (Windows Explorer, macOS Finder, Linux davfs2, Cyberduck, WinSCP, or a mobile app) or with curl. This guide uses curl to demonstrate the server and shows how to connect the common desktop clients.
What you get:
- WebDAV Server (verified at 5.14.0) as the official single static Go binary
webdav.serviceserving HTTPS on:443- Secure by default, with no default login. Upstream webdav can run with plaintext or no authentication, but this image never ships that. The server always runs over HTTPS with HTTP Basic Auth enforced, and the password is stored only as a bcrypt hash.
- A per-VM self-signed TLS certificate generated on first boot
webdav-firstboot.service, a oneshot that generates a unique username and password and a TLS certificate on each VM's first boot. It stores the password only as a bcrypt hash in the server configuration, writes the plaintext credential to a root-only0600file, resolves the instance URL, refreshes the binary, and then disables itself. No two VMs share a credential, and none is baked into the image.- Fail-secure startup. A bootstrap gate (
ConditionPathExists) clears only after first boot has written the per-VM credential and certificate, so the server cannot start until they exist. If first boot were interrupted, the server would not serve, rather than coming up open or unencrypted. - Always current. On first boot, the appliance downloads the newest webdav release binary and falls back to the baked version if the network is unavailable. Every launch runs current software rather than the version frozen at build time.
- An Ubuntu 24.04 LTS base, patched at build time
- 24/7 SecureAnyCloud support with a 24-hour response SLA
Prerequisites
You need an active Azure subscription, an SSH key pair, and a VNet with a subnet.
WebDAV is light on CPU. Performance is dominated by disk and network throughput. The recommended VM size is Standard_B2s (2 vCPU, 4 GB RAM) for evaluation and small teams. For busy file shares, choose a larger size with a bigger data disk.
The served directory lives on the OS disk by default. Expand the disk, or attach a dedicated data disk (see the sizing section), before you store large amounts of data.
Deploy from the Azure Portal
Search the Marketplace for WebDAV Server on Ubuntu 24.04 and choose your VM size. Attach a network security group (NSG) that allows TCP 22 (SSH) from your management network and TCP 443 (HTTPS WebDAV) from the clients that will use the share.
Basic Auth and TLS are enforced, so the server is safe to expose to your clients. Still, restrict the source ranges to networks you control.
Deploy from the Azure CLI
RG="webdav-prod"; LOCATION="eastus"; VM_NAME="webdav-01" IMAGE_URN="sac1647283583153:webdav-server-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION" az network vnet create -g "$RG" --name wd-vnet --address-prefix 10.90.0.0/16 --subnet-name wd-subnet --subnet-prefix 10.90.1.0/24 az network nsg create -g "$RG" --name wd-nsg az network nsg rule create -g "$RG" --nsg-name wd-nsg --name allow-ssh --priority 100 \
--source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 22 --access Allow --protocol Tcp az network nsg rule create -g "$RG" --nsg-name wd-nsg --name allow-webdav --priority 110 \
--source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 443 --access Allow --protocol Tcp
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:webdav-server-ubuntu-24-04:default:latest
az vm create -g "$RG" --name "$VM_NAME" --image "$IMAGE_URN" \
--size Standard_B2s --storage-sku StandardSSD_LRS \
--admin-username azureuser --ssh-key-values "$SSH_KEY" \
--vnet-name wd-vnet --subnet wd-subnet --nsg wd-nsg --public-ip-sku StandardConnect via SSH
ssh azureuser@<vm-ip>Verify the service and listener
WebDAV Server serves HTTPS on :443. Every request requires authentication, so an unauthenticated call returns 401.
sudo systemctl start webdav 2>/dev/null || true
sudo systemctl is-active webdav ss -tln | grep ':443' echo "unauthenticated / -> HTTP $(curl -sk -o /dev/null -w '%{http_code}' https://127.0.0.1/)"The output shows the service active, the listening socket on :443, and HTTP 401 from the unauthenticated call. The 401 confirms that authentication is enforced.
Read your per-VM credentials
The image generated a username and password on this VM's first boot and stored them in a root-only file. The server configuration keeps the password only as a bcrypt hash. Read the credentials and keep them secret. Then confirm that the per-VM credential authenticates and that an unauthenticated request does not.
sudo cat /root/webdav-info.txt
U=$(sudo grep '^WEBDAV_USER=' /root/webdav-info.txt | cut -d= -f2-)
P=$(sudo grep '^WEBDAV_PASSWORD=' /root/webdav-info.txt | cut -d= -f2-)
echo "unauthenticated -> HTTP $(curl -sk -o /dev/null -w '%{http_code}' https://127.0.0.1/)"
echo "authenticated -> HTTP $(curl -sk -o /dev/null -w '%{http_code}' -u "$U:$P" https://127.0.0.1/)"The info note holds WEBDAV_USER, WEBDAV_PASSWORD and the WebDAV URL. It is owned by root:root with mode 0600. The server returns 401 without the credential and 2xx with it. The per-VM TLS certificate at /etc/webdav/tls/cert.pem encrypts the transport.
Store and fetch a file (WebDAV round trip)
Upload a file with an authenticated PUT. Fetch it straight back and confirm that it matches byte for byte. Then list the directory with PROPFIND. A WebDAV client does exactly this under the hood.
U=$(sudo grep '^WEBDAV_USER=' /root/webdav-info.txt | cut -d= -f2-)
P=$(sudo grep '^WEBDAV_PASSWORD=' /root/webdav-info.txt | cut -d= -f2-) BLOB="hello from WebDAV Server at $(date -u +%FT%TZ)" printf '%s' "$BLOB" | curl -sk -u "$U:$P" -T - "https://127.0.0.1/demo.txt" -o /dev/null -w 'PUT /demo.txt -> HTTP %{http_code}\n'
GOT=$(curl -sk -u "$U:$P" "https://127.0.0.1/demo.txt") [ "$GOT" = "$BLOB" ] && echo "GET /demo.txt -> byte for byte match" || echo "GET /demo.txt -> MISMATCH" echo "PROPFIND / -> HTTP $(curl -sk -o /dev/null -w '%{http_code}' -u "$U:$P" -X PROPFIND -H 'Depth: 1' https://127.0.0.1/)" echo "unauthenticated GET /demo.txt -> HTTP $(curl -sk -o /dev/null -w '%{http_code}' https://127.0.0.1/demo.txt)" curl -sk -u "$U:$P" -X DELETE "https://127.0.0.1/demo.txt" -o /dev/nullThe PUT returns 201. The authenticated GET returns the identical file. PROPFIND returns 207 Multi-Status, which is the directory listing. An unauthenticated GET of the same path returns 401, so content is never served without the credential.
Connect a WebDAV client
Use the username and password from Step 5 and the server address https://<vm-ip>/. The certificate is self-signed, so clients prompt you to trust it on first connect. See Step 8 to install a trusted certificate.
Windows (File Explorer): open File Explorer, right-click This PC, choose Map network drive, and enter https://<vm-ip>/ as the folder. Windows prompts for the username and password. You can also use the command line:
net use * https://<vm-ip>/ /user:<webdav-username> <webdav-password>macOS (Finder): in Finder, choose Go -> Connect to Server (Command-K) and enter https://<vm-ip>/. Supply the username and password when prompted.
Linux (davfs2): install davfs2 and mount the share:
sudo apt-get install -y davfs2
sudo mount -t davfs https://<vm-ip>/ /mnt/webdavcurl (any platform): upload, download and list from scripts:
curl -u <webdav-username>:<webdav-password> -T ./report.pdf https://<vm-ip>/report.pdf
curl -u <webdav-username>:<webdav-password> https://<vm-ip>/report.pdf -o report.pdf
curl -u <webdav-username>:<webdav-password> -X PROPFIND -H 'Depth: 1' https://<vm-ip>/Trusting or replacing the certificate
The server ships with a per-VM self-signed certificate. It encrypts traffic, but clients do not trust it out of the box, so they prompt on first connect. For a smoother experience, either distribute the self-signed certificate to your clients as a trusted root, or replace it with a certificate from a public CA.
To use a real certificate from Let's Encrypt, you need a public DNS name that points at the VM and TCP 80 reachable. Install certbot, obtain a certificate for <your-domain>, point the config at it, and restart the service:
sudo apt-get install -y certbot
sudo certbot certonly --standalone -d <your-domain> --agree-tos -m <your-email> -n sudo sed -i "s#^cert:.*#cert: /etc/letsencrypt/live/<your-domain>/fullchain.pem#" /etc/webdav/config.yml
sudo sed -i "s#^key:.*#key: /etc/letsencrypt/live/<your-domain>/privkey.pem#" /etc/webdav/config.yml
sudo systemctl restart webdavClients then connect to https://<your-domain>/ without a certificate warning.
Permissions, users and sizing
The server configuration lives at /etc/webdav/config.yml. It defines the listening address and port, the served directory, the TLS certificate, and the users with their permissions. Permissions combine the letters C (create), R (read), U (update) and D (delete). The per-VM admin user is granted CRUD.
To add a read-only user or a second full-access user, generate a bcrypt hash and add a users entry, then restart the service. Never store a plaintext password in the config:
# generate a bcrypt hash for a new password (never store plaintext in the config) htpasswd -nbBC 10 reader "<new-password>"
# add a users: entry to /etc/webdav/config.yml with permissions: R for read only, then:
sudo systemctl restart webdavThe served directory lives on the OS disk under /var/lib/webdav/data. Inspect it and its disk usage:
ls -ld /var/lib/webdav/data du -sh /var/lib/webdav/data 2>/dev/null df -h /var/lib/webdavTo grow capacity, attach a dedicated data disk and mount it at /var/lib/webdav/data, preserving webdav ownership. The served content then lives on the larger volume.
Persistence, first boot and updates
The served directory lives on the OS disk under /var/lib/webdav/data. The first-boot service generates the per-VM username, password and TLS certificate. It refreshes the webdav binary to the latest release and writes the fail-secure bootstrap marker. It then disables itself, so subsequent reboots are unaffected. The OS is patched at build time and ships with unattended security upgrades enabled.
sudo /usr/local/bin/webdav version 2>/dev/null | head -1 systemctl is-enabled webdav-firstboot.service webdav.service ls -ld /var/lib/webdav/data export DEBIAN_FRONTEND=noninteractive;
sudo apt-get update -y >/dev/null 2>&1 echo "held packages: $(apt-mark showhold | tr '\n' ' ')[none]"Support
Every SecureAnyCloud deployment includes 24/7 support with a 24-hour response SLA. Contact sales@secureanycloud.com for help with deployment, configuration or scaling.
This is a repackaged open-source software product with additional charges for SecureAnyCloud support services. WebDAV Server (hacdias/webdav) is open source under the MIT license. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.
Deploy on Azure
Launch WebDAV Server on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
WebDAV Server delivers hacdias/webdav, a fast, simple, self-hosted WebDAV server written as a single static Go binary. WebDAV lets you mount and manage a remote directory as if it were a local drive from Windows Explorer, macOS Finder, Linux file managers and any WebDAV client. It works as a drop-in remote file share, backup target or document store that you run and own inside your own AWS account.
This SecureAnyCloud image installs the official webdav binary at /usr/local/bin/webdav, running as the webdav service. It serves a directory at /var/lib/webdav/data over HTTPS on port 443, with configurable per-user permissions for create, read, update and delete. A webdav-firstboot.service oneshot creates the credentials on first boot.
WebDAV is a protocol, not a web application, so there is no web UI to sign in to. You drive it with any WebDAV client (Windows Explorer, macOS Finder, Linux davfs2, Cyberduck, WinSCP, or a mobile app) or with curl. This guide uses curl to demonstrate the server and shows how to connect the common desktop clients.
What you get:
- WebDAV Server (verified at 5.14.0) as the official single static Go binary
webdav.serviceserving HTTPS on:443- Secure by default, with no default login. Upstream webdav can run with plaintext or no authentication, but this image never ships that. The server always runs over HTTPS with HTTP Basic Auth enforced, and the password is stored only as a bcrypt hash.
- A per-instance self-signed TLS certificate generated on first boot
webdav-firstboot.service, a oneshot that generates a unique username and password and a TLS certificate on each instance's first boot. It stores the password only as a bcrypt hash in the server configuration, writes the plaintext credential to a root-only0600file, resolves the instance URL via EC2 instance metadata, refreshes the binary, and then disables itself. No two instances share a credential, and none is baked into the image.- Fail-secure startup. A bootstrap gate (
ConditionPathExists) clears only after first boot has written the per-instance credential and certificate, so the server cannot start until they exist. If first boot were interrupted, the server would not serve, rather than coming up open or unencrypted. - Always current. On first boot, the appliance downloads the newest webdav release binary and falls back to the baked version if the network is unavailable. Every launch runs current software rather than the version frozen at build time.
- An Ubuntu 24.04 LTS base, fully patched
- 24/7 SecureAnyCloud support with a 24-hour response SLA
Connecting to your instance
Connect over SSH as the default login user for your instance's operating system variant, using the key pair you selected at launch.
OS variant SSH login user Example
Ubuntu 24.04 LTS ubuntu ssh -i your-key.pem ubuntu@<public-ip>
Prerequisites
You need an AWS account, an EC2 key pair in your target region, and a VPC with a public subnet.
WebDAV is light on CPU. Performance is dominated by disk and network throughput. The recommended instance type is m5.large (2 vCPU, 8 GB RAM) for evaluation and small teams. For busy file shares, choose a larger type with a bigger EBS volume.
The served directory lives on the root EBS volume by default. Expand the volume, or attach a dedicated data volume (see the sizing section), before you store large amounts of data.
Launch the Instance from the AWS Marketplace
In the AWS Marketplace, search for WebDAV Server by SecureAnyCloud. Choose Continue to Subscribe, then Continue to Configuration and Continue to Launch. Select your instance type (m5.large is a good default), your VPC and subnet, and your key pair. Attach a security group that allows:
- TCP 22 (SSH) from your management network only
- TCP 443 (HTTPS WebDAV) from the clients that will use the share
Basic Auth and TLS are enforced, so the server is safe to expose to your clients. Still, restrict the source ranges to networks you control.
Launch the Instance from the AWS CLI
AMI_ID="<ami-id>"
# the WebDAV Server AMI id for your region KEY_NAME="<your-key-pair>" SUBNET_ID="<subnet-id>"
# a public subnet REGION="us-east-1"
# Security group: SSH from your management CIDR, WebDAV (443) from your clients
SG_ID=$(aws ec2 create-security-group --region "$REGION" \
--group-name webdav-sg --description "WebDAV Server" \
--vpc-id <vpc-id> --query GroupId --output text)
aws ec2 authorize-security-group-ingress --region "$REGION" --group-id "$SG_ID" \
--protocol tcp --port 22 --cidr <your-mgmt-cidr>
aws ec2 authorize-security-group-ingress --region "$REGION" --group-id "$SG_ID" \
--protocol tcp --port 443 --cidr <your-clients-cidr>
aws ec2 run-instances --region "$REGION" \
--image-id "$AMI_ID" --instance-type m5.large \
--key-name "$KEY_NAME" --subnet-id "$SUBNET_ID" \
--security-group-ids "$SG_ID" \
--metadata-options "HttpTokens=required" \
--associate-public-ip-address \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=webdav-01}]'The instance uses IMDSv2 (HttpTokens=required). The first-boot service reads the instance metadata with a token to resolve the server URL.
Connect via SSH
ssh -i your-key.pem ubuntu@<public-ip>Verify the service and listener
WebDAV Server serves HTTPS on :443. Every request requires authentication, so an unauthenticated call returns 401.
sudo systemctl is-active webdav
sudo ss -tln | grep ':443' /usr/local/bin/webdav version echo "unauthenticated / -> HTTP $(curl -sk -o /dev/null -w '%{http_code}' https://127.0.0.1/)"The output shows the service active, the listening socket on :443, the webdav version, and HTTP 401 from the unauthenticated call. The 401 confirms that authentication is enforced.
Read your per-instance credentials
The image generated a username and password on this instance's first boot and stored them in a root-only file. The server configuration keeps the password only as a bcrypt hash. Read the credentials and keep them secret. Then confirm that the per-instance credential authenticates and that an unauthenticated request does not.
sudo cat /root/webdav-info.txt
U=$(sudo grep '^WEBDAV_USER=' /root/webdav-info.txt | cut -d= -f2-)
P=$(sudo grep '^WEBDAV_PASSWORD=' /root/webdav-info.txt | cut -d= -f2-)
echo "unauthenticated -> HTTP $(curl -sk -o /dev/null -w '%{http_code}' https://127.0.0.1/)"
echo "authenticated -> HTTP $(curl -sk -o /dev/null -w '%{http_code}' -u "$U:$P" https://127.0.0.1/)"The info note holds WEBDAV_USER, WEBDAV_PASSWORD and the WebDAV URL. It is owned by root:root with mode 0600. The server returns 401 without the credential and 2xx with it. The per-instance TLS certificate at /etc/webdav/tls/cert.pem encrypts the transport.
Store and fetch a file (WebDAV round trip)
Upload a file with an authenticated PUT. Fetch it straight back and confirm that it matches byte for byte. Then list the directory with PROPFIND. A WebDAV client does exactly this under the hood.
U=$(sudo grep '^WEBDAV_USER=' /root/webdav-info.txt | cut -d= -f2-)
P=$(sudo grep '^WEBDAV_PASSWORD=' /root/webdav-info.txt | cut -d= -f2-) BLOB="hello from WebDAV Server at $(date -u +%FT%TZ)" printf '%s' "$BLOB" | curl -sk -u "$U:$P" -T - "https://127.0.0.1/demo.txt" -o /dev/null -w 'PUT /demo.txt -> HTTP %{http_code}\n'
GOT=$(curl -sk -u "$U:$P" "https://127.0.0.1/demo.txt") [ "$GOT" = "$BLOB" ] && echo "GET /demo.txt -> byte for byte match" || echo "GET /demo.txt -> MISMATCH" echo "PROPFIND / -> HTTP $(curl -sk -o /dev/null -w '%{http_code}' -u "$U:$P" -X PROPFIND -H 'Depth: 1' https://127.0.0.1/)" echo "unauthenticated GET /demo.txt -> HTTP $(curl -sk -o /dev/null -w '%{http_code}' https://127.0.0.1/demo.txt)" curl -sk -u "$U:$P" -X DELETE "https://127.0.0.1/demo.txt" -o /dev/nullThe PUT returns 201. The authenticated GET returns the identical file. PROPFIND returns 207 Multi-Status, which is the directory listing. An unauthenticated GET of the same path returns 401, so content is never served without the credential.
Connect a WebDAV client
Use the username and password from Step 5 and the server address https://<public-ip>/. The certificate is self-signed, so clients prompt you to trust it on first connect. See Step 8 to install a trusted certificate.
Windows (File Explorer): open File Explorer, right-click This PC, choose Map network drive, and enter https://<public-ip>/ as the folder. Windows prompts for the username and password. You can also use the command line:
net use * https://<public-ip>/ /user:<webdav-username> <webdav-password>macOS (Finder): in Finder, choose Go -> Connect to Server (Command-K) and enter https://<public-ip>/. Supply the username and password when prompted.
Linux (davfs2): install davfs2 and mount the share:
sudo apt-get install -y davfs2
sudo mount -t davfs https://<public-ip>/ /mnt/webdavcurl (any platform): upload, download and list from scripts:
curl -u <webdav-username>:<webdav-password> -T ./report.pdf https://<public-ip>/report.pdf
curl -u <webdav-username>:<webdav-password> https://<public-ip>/report.pdf -o report.pdf
curl -u <webdav-username>:<webdav-password> -X PROPFIND -H 'Depth: 1' https://<public-ip>/Trusting or replacing the certificate
The server ships with a per-instance self-signed certificate. It encrypts traffic, but clients do not trust it out of the box, so they prompt on first connect. For a smoother experience, either distribute the self-signed certificate to your clients as a trusted root, or replace it with a certificate from a public CA.
To use a real certificate from Let's Encrypt, you need a public DNS name that points at the instance and TCP 80 reachable. Install certbot, obtain a certificate for your-domain, point the config at it, and restart the service:
sudo apt-get install -y certbot
sudo certbot certonly --standalone -d your-domain --agree-tos -m your-email -n sudo sed -i "s#^cert:.*#cert: /etc/letsencrypt/live/your-domain/fullchain.pem#" /etc/webdav/config.yml
sudo sed -i "s#^key:.*#key: /etc/letsencrypt/live/your-domain/privkey.pem#" /etc/webdav/config.yml
sudo systemctl restart webdavClients then connect to https://your-domain/ without a certificate warning.
Permissions, users and sizing
The server configuration lives at /etc/webdav/config.yml. It defines the listening address and port, the served directory, the TLS certificate, and the users with their permissions. Permissions combine the letters C (create), R (read), U (update) and D (delete). The per-instance admin user is granted CRUD.
To add a read-only user or a second full-access user, generate a bcrypt hash and add a users entry, then restart the service. Never store a plaintext password in the config:
# generate a bcrypt hash for a new password (never store plaintext in the config) htpasswd -nbBC 10 reader "<new-password>"
# add a users: entry to /etc/webdav/config.yml with permissions: R for read only, then:
sudo systemctl restart webdavThe served directory lives on the root EBS volume under /var/lib/webdav/data. Inspect it and its disk usage:
ls -ld /var/lib/webdav/data du -sh /var/lib/webdav/data 2>/dev/null df -h /var/lib/webdavTo grow capacity, attach a dedicated EBS volume and mount it at /var/lib/webdav/data, preserving webdav ownership. The served content then lives on the larger, independently resizable volume.
Persistence, first boot and updates
The served directory lives on the root EBS volume under /var/lib/webdav/data. The first-boot service generates the per-instance username, password and TLS certificate. It refreshes the webdav binary to the latest release and writes the fail-secure bootstrap marker. It then disables itself, so subsequent reboots are unaffected. The OS ships fully patched with unattended security upgrades enabled.
sudo /usr/local/bin/webdav version 2>/dev/null | head -1 systemctl is-enabled webdav-firstboot.service webdav.service ls -ld /var/lib/webdav/data export DEBIAN_FRONTEND=noninteractive;
sudo apt-get update -y >/dev/null 2>&1 echo "held packages: $(apt-mark showhold | tr '\n' ' ')[none]"Support
Every SecureAnyCloud deployment includes 24/7 support with a 24-hour response SLA. Contact sales@secureanycloud.com for help with deployment, configuration or scaling.
This is a repackaged open-source software product with additional charges for SecureAnyCloud support services. WebDAV Server (hacdias/webdav) is open source under the MIT license. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.
Deploy on AWS
Launch WebDAV Server on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com