|
#!/bin/bash |
|
# Setup Tailscale + Taildrive on a Linux machine |
|
# Installs Tailscale if missing, shares root drive, mounts WebDAV |
|
# Run as root or with sudo |
|
# |
|
# Usage: curl -sL <gist-url>/raw | sudo bash |
|
|
|
set -e |
|
|
|
MOUNT_POINT="/mnt/taildrive" |
|
WEBDAV_URL="http://100.100.100.100:8080/" |
|
SECRETS_FILE="/etc/davfs2/secrets" |
|
DAVFS2_CONF="/etc/davfs2/davfs2.conf" |
|
|
|
echo "=== Taildrive Setup ===" |
|
echo "" |
|
|
|
# --- 1. Install Tailscale if needed --- |
|
if ! command -v tailscale &>/dev/null; then |
|
echo "[1/4] Installing Tailscale..." |
|
curl -fsSL https://tailscale.com/install.sh | sh |
|
echo "Tailscale installed." |
|
else |
|
echo "[1/4] Tailscale already installed: $(tailscale version | head -1)" |
|
fi |
|
|
|
# Start and enable tailscaled |
|
if command -v systemctl &>/dev/null; then |
|
systemctl enable --now tailscaled 2>/dev/null || true |
|
fi |
|
|
|
# Check if connected to tailnet |
|
if ! tailscale status &>/dev/null; then |
|
echo "" |
|
echo "Tailscale is not connected. Running 'tailscale up'..." |
|
echo "You may need to authenticate via the URL below:" |
|
echo "" |
|
tailscale up |
|
echo "" |
|
fi |
|
|
|
echo "Tailscale status: $(tailscale status --self --json 2>/dev/null | grep -o '"Online":true' && echo 'connected' || echo 'check manually')" |
|
|
|
# --- 2. Share root drive --- |
|
echo "" |
|
HOSTNAME=$(tailscale status --self --json 2>/dev/null | grep -o '"HostName":"[^"]*"' | cut -d'"' -f4) |
|
HOSTNAME=${HOSTNAME:-$(hostname)} |
|
|
|
CURRENT_USER=$(logname 2>/dev/null || echo "${SUDO_USER:-root}") |
|
|
|
echo "[2/4] Sharing drives..." |
|
|
|
# Share root filesystem |
|
if tailscale drive list 2>/dev/null | grep -q "^root"; then |
|
echo " Root already shared." |
|
else |
|
echo " Sharing / as 'root'..." |
|
tailscale drive share root / --as="$CURRENT_USER" 2>/dev/null || \ |
|
tailscale drive share root / 2>/dev/null || \ |
|
echo " WARNING: Could not share root drive. Check drive:share node attribute." |
|
fi |
|
|
|
# Share all mounted storage devices (skip virtual/system filesystems) |
|
# Only share real block device filesystems (ext4, xfs, btrfs, ntfs, vfat, exfat, zfs, etc.) |
|
REAL_FS="ext[234]|xfs|btrfs|ntfs|vfat|exfat|zfs|f2fs|jfs|reiserfs|hfsplus|apfs|fuseblk" |
|
while IFS= read -r line; do |
|
dev=$(echo "$line" | awk '{print $1}') |
|
mnt=$(echo "$line" | awk '{print $2}') |
|
fstype=$(echo "$line" | awk '{print $3}') |
|
|
|
# Skip root (already shared) |
|
[ "$mnt" = "/" ] && continue |
|
# Skip boot partitions |
|
echo "$mnt" | grep -q "^/boot" && continue |
|
# Skip snap mounts |
|
echo "$mnt" | grep -q "^/snap" && continue |
|
# Only include real filesystems |
|
echo "$fstype" | grep -qE "^($REAL_FS)$" || continue |
|
|
|
# Generate a share name from the mount point (e.g. /mnt/data -> mnt-data) |
|
sharename=$(echo "$mnt" | sed 's|^/||; s|/|-|g; s|[^a-z0-9_() -]||g' | tr '[:upper:]' '[:lower:]') |
|
[ -z "$sharename" ] && continue |
|
|
|
if tailscale drive list 2>/dev/null | grep -q "^${sharename}"; then |
|
echo " $mnt already shared as '$sharename'." |
|
else |
|
echo " Sharing $mnt as '$sharename'..." |
|
tailscale drive share "$sharename" "$mnt" --as="$CURRENT_USER" 2>/dev/null || \ |
|
tailscale drive share "$sharename" "$mnt" 2>/dev/null || \ |
|
echo " WARNING: Could not share $mnt" |
|
fi |
|
done < <(findmnt -rn -o SOURCE,TARGET,FSTYPE 2>/dev/null) |
|
|
|
echo "" |
|
echo "Current shares:" |
|
tailscale drive list 2>/dev/null || echo " (none)" |
|
|
|
# --- 3. Install davfs2 --- |
|
echo "" |
|
if ! command -v mount.davfs &>/dev/null; then |
|
echo "[3/4] Installing davfs2..." |
|
if command -v apt-get &>/dev/null; then |
|
apt-get update -qq && apt-get install -y -qq davfs2 |
|
elif command -v dnf &>/dev/null; then |
|
dnf install -y -q davfs2 |
|
elif command -v pacman &>/dev/null; then |
|
pacman -S --noconfirm davfs2 |
|
elif command -v apk &>/dev/null; then |
|
apk add davfs2 |
|
else |
|
echo "ERROR: Could not detect package manager. Install davfs2 manually." |
|
exit 1 |
|
fi |
|
else |
|
echo "[3/4] davfs2 already installed." |
|
fi |
|
|
|
# --- 4. Configure and mount WebDAV --- |
|
echo "" |
|
echo "[4/4] Configuring WebDAV mount..." |
|
|
|
mkdir -p "$MOUNT_POINT" |
|
|
|
# Empty credentials (Taildrive handles auth via tailnet identity) |
|
if ! grep -q "100.100.100.100:8080" "$SECRETS_FILE" 2>/dev/null; then |
|
echo "$WEBDAV_URL \"\" \"\"" >> "$SECRETS_FILE" |
|
chmod 600 "$SECRETS_FILE" |
|
echo " Added WebDAV credentials." |
|
fi |
|
|
|
# Disable locks (Taildrive doesn't support them) |
|
if ! grep -q "use_locks 0" "$DAVFS2_CONF" 2>/dev/null; then |
|
echo "use_locks 0" >> "$DAVFS2_CONF" |
|
echo " Disabled WebDAV locks." |
|
fi |
|
|
|
# fstab entry |
|
if ! grep -q "100.100.100.100:8080" /etc/fstab 2>/dev/null; then |
|
echo "$WEBDAV_URL $MOUNT_POINT davfs rw,auto,_netdev 0 0" >> /etc/fstab |
|
echo " Added fstab entry." |
|
fi |
|
|
|
# Mount |
|
if mountpoint -q "$MOUNT_POINT" 2>/dev/null; then |
|
echo " Already mounted." |
|
else |
|
mount "$MOUNT_POINT" 2>/dev/null && echo " Mounted at $MOUNT_POINT" || echo " WARNING: Mount failed. May need a reboot or manual mount." |
|
fi |
|
|
|
# --- Done --- |
|
echo "" |
|
echo "=== Setup Complete ===" |
|
echo " Host: $HOSTNAME" |
|
echo " Shares: $(tailscale drive list 2>/dev/null | grep -c '^[a-z]') drive(s) shared" |
|
echo " Mount: $MOUNT_POINT" |
|
echo " Browse: ls $MOUNT_POINT/brad.cozine@gmail.com/" |
|
echo "" |