Skip to content

Instantly share code, notes, and snippets.

@bogdanscarwash
Created April 14, 2025 15:16
Show Gist options
  • Save bogdanscarwash/bfa7eea483aab7451d545be91346e16c to your computer and use it in GitHub Desktop.
Save bogdanscarwash/bfa7eea483aab7451d545be91346e16c to your computer and use it in GitHub Desktop.
Universal WebDAV Server Setup Script for Debian 12. Works on both standard Debian 12 and WSL environments
#!/bin/bash
# Universal WebDAV Server Setup Script for Debian 12
# Works on both standard Debian 12 and WSL environments
# Exit on any error
set -e
# Configuration variables
WEBDAV_DIR="/var/www/webdav"
WEBDAV_CONF="/etc/apache2/sites-available/webdav.conf"
WEBDAV_USER="webdav_user"
LOCK_DB="/var/lock/apache2/DAVLock"
HTML_INTERFACE=true
# Function to check if running as root
check_root() {
if [ "$(id -u)" -ne 0 ]; then
echo "This script must be run as root. Please use sudo."
exit 1
fi
}
# Function to detect environment (WSL vs standard Debian)
detect_environment() {
if grep -q Microsoft /proc/version || grep -q microsoft /proc/version; then
echo "WSL environment detected. Using service commands."
ENVIRONMENT="wsl"
else
echo "Standard Debian environment detected. Using systemctl."
ENVIRONMENT="standard"
fi
}
# Function to update system
update_system() {
echo "Updating system packages..."
apt update
apt upgrade -y
}
# Function to install Apache2
install_apache() {
echo "Installing Apache2..."
apt install -y apache2
echo "Installing apache2-utils for htpasswd utility..."
apt install -y apache2-utils
echo "Starting Apache2 service..."
if [ "$ENVIRONMENT" = "wsl" ]; then
service apache2 start || true
else
systemctl enable apache2
systemctl start apache2
fi
}
# Function to enable WebDAV modules
enable_webdav_modules() {
echo "Enabling WebDAV modules..."
a2enmod dav
a2enmod dav_fs
a2enmod alias
echo "Restarting Apache2..."
if [ "$ENVIRONMENT" = "wsl" ]; then
service apache2 restart
else
systemctl restart apache2
fi
}
# Function to create and configure WebDAV directory
configure_webdav_directory() {
echo "Creating WebDAV directory at $WEBDAV_DIR..."
mkdir -p $WEBDAV_DIR
echo "Setting ownership to www-data..."
chown -R www-data:www-data $WEBDAV_DIR
echo "Creating lock directory..."
mkdir -p $(dirname $LOCK_DB)
chown -R www-data:www-data $(dirname $LOCK_DB)
# Simple configuration directly in default site
echo "Creating WebDAV configuration in default site..."
cat > /etc/apache2/sites-available/000-default.conf << EOF
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
# WebDAV configuration
Alias /webdav $WEBDAV_DIR
<Directory $WEBDAV_DIR>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
DAV On
AuthType Basic
AuthName "WebDAV Server"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
</Directory>
DavLockDB $LOCK_DB
ErrorLog \${APACHE_LOG_DIR}/error.log
CustomLog \${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
EOF
}
# Function to create user authentication
setup_authentication() {
echo "Creating authentication file with user $WEBDAV_USER..."
htpasswd -c /etc/apache2/.htpasswd $WEBDAV_USER
echo "Reloading Apache2 configuration..."
if [ "$ENVIRONMENT" = "wsl" ]; then
service apache2 reload
else
systemctl reload apache2
fi
}
# Function to create web interface
create_web_interface() {
if [ "$HTML_INTERFACE" = true ]; then
echo "Creating web interface..."
cat > $WEBDAV_DIR/index.html << 'EOF'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebDAV Browser</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 900px;
margin: 0 auto;
background: white;
padding: 20px;
border-radius: 5px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
color: #333;
border-bottom: 1px solid #eee;
padding-bottom: 10px;
}
#file-list {
margin-top: 20px;
}
.file-item {
padding: 10px;
border-bottom: 1px solid #eee;
display: flex;
align-items: center;
}
.file-item:hover {
background: #f9f9f9;
}
.file-icon {
margin-right: 10px;
color: #555;
}
.file-name {
flex-grow: 1;
}
.file-actions {
display: flex;
gap: 10px;
}
.btn {
padding: 6px 12px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
.btn-primary {
background: #4285f4;
color: white;
}
.btn-danger {
background: #ea4335;
color: white;
}
.dropzone {
border: 2px dashed #ccc;
border-radius: 5px;
padding: 25px;
text-align: center;
margin: 20px 0;
background: #f9f9f9;
}
.dropzone.highlight {
border-color: #4285f4;
background: #e8f0fe;
}
</style>
</head>
<body>
<div class="container">
<h1>WebDAV File Browser</h1>
<div class="dropzone" id="drop-area">
<p>Drag & drop files here or</p>
<input type="file" id="file-input" multiple style="display: none;">
<button class="btn btn-primary" onclick="document.getElementById('file-input').click()">Select Files</button>
</div>
<div id="file-list">
<!-- Files will be listed here -->
<p>Loading files...</p>
</div>
</div>
<script>
// Simple WebDAV client using browser's built-in fetch API
const webdavClient = {
baseUrl: window.location.href,
// List files in the current directory
async listFiles() {
try {
const response = await fetch(this.baseUrl, {
method: 'PROPFIND',
headers: {
'Depth': '1',
'Content-Type': 'application/xml'
},
credentials: 'include'
});
if (response.ok) {
const text = await response.text();
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(text, "text/xml");
const responses = xmlDoc.getElementsByTagNameNS("DAV:", "response");
const files = [];
for (let i = 1; i < responses.length; i++) { // Skip first (current directory)
const href = responses[i].getElementsByTagNameNS("DAV:", "href")[0].textContent;
const prop = responses[i].getElementsByTagNameNS("DAV:", "propstat")[0]
.getElementsByTagNameNS("DAV:", "prop")[0];
const isCollection = prop.getElementsByTagNameNS("DAV:", "resourcetype")[0]
.getElementsByTagNameNS("DAV:", "collection").length > 0;
files.push({
href: href,
name: decodeURIComponent(href.split('/').filter(Boolean).pop()),
isDirectory: isCollection
});
}
return files;
} else {
throw new Error(`Failed to list files: ${response.status}`);
}
} catch (error) {
console.error("Error listing files:", error);
return [];
}
},
// Download a file
downloadFile(href) {
window.location.href = href;
},
// Delete a file
async deleteFile(href) {
try {
const response = await fetch(href, {
method: 'DELETE',
credentials: 'include'
});
if (response.ok) {
return true;
} else {
throw new Error(`Failed to delete file: ${response.status}`);
}
} catch (error) {
console.error("Error deleting file:", error);
return false;
}
},
// Upload a file
async uploadFile(file, progressCallback) {
try {
const url = this.baseUrl + encodeURIComponent(file.name);
const response = await fetch(url, {
method: 'PUT',
body: file,
credentials: 'include'
});
if (response.ok) {
return true;
} else {
throw new Error(`Failed to upload file: ${response.status}`);
}
} catch (error) {
console.error("Error uploading file:", error);
return false;
}
},
// Create a directory
async createDirectory(name) {
try {
const url = this.baseUrl + encodeURIComponent(name);
const response = await fetch(url, {
method: 'MKCOL',
credentials: 'include'
});
if (response.ok) {
return true;
} else {
throw new Error(`Failed to create directory: ${response.status}`);
}
} catch (error) {
console.error("Error creating directory:", error);
return false;
}
}
};
// Render file list
async function renderFileList() {
const fileListEl = document.getElementById('file-list');
fileListEl.innerHTML = '<p>Loading files...</p>';
const files = await webdavClient.listFiles();
if (files.length === 0) {
fileListEl.innerHTML = '<p>No files found.</p>';
return;
}
let html = '';
files.forEach(file => {
html += `
<div class="file-item">
<div class="file-icon">${file.isDirectory ? '๐Ÿ“' : '๐Ÿ“„'}</div>
<div class="file-name">${file.name}</div>
<div class="file-actions">
<button class="btn btn-primary" onclick="downloadFile('${file.href}')">Download</button>
<button class="btn btn-danger" onclick="deleteFile('${file.href}', '${file.name}')">Delete</button>
</div>
</div>
`;
});
html += `
<div class="file-item">
<button class="btn btn-primary" onclick="promptCreateDirectory()">Create Folder</button>
</div>
`;
fileListEl.innerHTML = html;
}
// Download file
function downloadFile(href) {
webdavClient.downloadFile(href);
}
// Delete file
async function deleteFile(href, name) {
if (confirm(`Are you sure you want to delete "${name}"?`)) {
const success = await webdavClient.deleteFile(href);
if (success) {
renderFileList();
} else {
alert('Failed to delete file');
}
}
}
// Create directory
function promptCreateDirectory() {
const name = prompt('Enter folder name:');
if (name) {
webdavClient.createDirectory(name).then(success => {
if (success) {
renderFileList();
} else {
alert('Failed to create folder');
}
});
}
}
// File upload handling
const dropArea = document.getElementById('drop-area');
const fileInput = document.getElementById('file-input');
dropArea.addEventListener('dragover', (e) => {
e.preventDefault();
dropArea.classList.add('highlight');
});
dropArea.addEventListener('dragleave', () => {
dropArea.classList.remove('highlight');
});
dropArea.addEventListener('drop', (e) => {
e.preventDefault();
dropArea.classList.remove('highlight');
const files = e.dataTransfer.files;
handleFiles(files);
});
fileInput.addEventListener('change', () => {
const files = fileInput.files;
handleFiles(files);
});
async function handleFiles(files) {
for (const file of files) {
const success = await webdavClient.uploadFile(file);
if (success) {
console.log(`Uploaded: ${file.name}`);
} else {
console.error(`Failed to upload: ${file.name}`);
}
}
renderFileList();
}
// Initialize
document.addEventListener('DOMContentLoaded', () => {
renderFileList();
});
</script>
</body>
</html>
EOF
chown www-data:www-data $WEBDAV_DIR/index.html
echo "Web interface created successfully."
fi
}
# Function to check and display server status
check_server() {
echo "Checking Apache2 status..."
if [ "$ENVIRONMENT" = "wsl" ]; then
service apache2 status || true
else
systemctl status apache2 --no-pager
fi
echo -e "\nWebDAV server setup complete!"
echo "You can access your WebDAV server at: http://localhost/webdav"
echo "Use the username $WEBDAV_USER and the password you provided"
if [ "$ENVIRONMENT" = "wsl" ]; then
echo -e "\nNOTE: Since you're using WSL, you'll need to start Apache manually after system restarts with:"
echo "sudo service apache2 start"
fi
if [ "$HTML_INTERFACE" = true ]; then
echo -e "\nA web-based file browser interface has been installed."
echo "Access it at http://localhost/webdav/"
fi
}
# Main execution
main() {
check_root
detect_environment
update_system
install_apache
enable_webdav_modules
configure_webdav_directory
setup_authentication
create_web_interface
check_server
}
# Run the script
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment