various: add detection and Taildrop for Unraid

Updates tailscale/tailscale#8025

Signed-off-by: Derek Kaser <derek.kaser@gmail.com>
pull/4754/head
Derek Kaser 1 year ago committed by Brad Fitzpatrick
parent d1ce7a9b5e
commit 0d7303b798

@ -66,7 +66,7 @@ func isSystemdSystem() bool {
return false return false
} }
switch distro.Get() { switch distro.Get() {
case distro.QNAP, distro.Gokrazy, distro.Synology: case distro.QNAP, distro.Gokrazy, distro.Synology, distro.Unraid:
return false return false
} }
_, err := exec.LookPath("systemctl") _, err := exec.LookPath("systemctl")

@ -18,7 +18,7 @@ import (
func configureTaildrop(logf logger.Logf, lb *ipnlocal.LocalBackend) { func configureTaildrop(logf logger.Logf, lb *ipnlocal.LocalBackend) {
dg := distro.Get() dg := distro.Get()
switch dg { switch dg {
case distro.Synology, distro.TrueNAS, distro.QNAP: case distro.Synology, distro.TrueNAS, distro.QNAP, distro.Unraid:
// See if they have a "Taildrop" share. // See if they have a "Taildrop" share.
// See https://github.com/tailscale/tailscale/issues/2179#issuecomment-982821319 // See https://github.com/tailscale/tailscale/issues/2179#issuecomment-982821319
path, err := findTaildropDir(dg) path, err := findTaildropDir(dg)
@ -42,6 +42,8 @@ func findTaildropDir(dg distro.Distro) (string, error) {
return findTrueNASTaildropDir(name) return findTrueNASTaildropDir(name)
case distro.QNAP: case distro.QNAP:
return findQnapTaildropDir(name) return findQnapTaildropDir(name)
case distro.Unraid:
return findUnraidTaildropDir(name)
} }
return "", fmt.Errorf("%s is an unsupported distro for Taildrop dir", dg) return "", fmt.Errorf("%s is an unsupported distro for Taildrop dir", dg)
} }
@ -103,3 +105,25 @@ func findQnapTaildropDir(name string) (string, error) {
} }
return "", fmt.Errorf("shared folder %q not found", name) return "", fmt.Errorf("shared folder %q not found", name)
} }
// findUnraidTaildropDir looks for a directory linked at
// /var/lib/tailscale/Taildrop. This is a symlink to the
// path specified by the user in the Unraid Web UI
func findUnraidTaildropDir(name string) (string, error) {
dir := fmt.Sprintf("/var/lib/tailscale/%s", name)
_, err := os.Stat(dir)
if err != nil {
return "", fmt.Errorf("symlink %q not found", name)
}
fullpath, err := filepath.EvalSymlinks(dir)
if err != nil {
return "", fmt.Errorf("symlink %q to shared folder not valid", name)
}
fi, err := os.Stat(fullpath)
if err == nil && fi.IsDir() {
return dir, nil // return the symlink
}
return "", fmt.Errorf("shared folder %q not found", name)
}

@ -95,6 +95,8 @@ func linuxVersionMeta() (meta versionMeta) {
propFile = "/etc.defaults/VERSION" propFile = "/etc.defaults/VERSION"
case distro.OpenWrt: case distro.OpenWrt:
propFile = "/etc/openwrt_release" propFile = "/etc/openwrt_release"
case distro.Unraid:
propFile = "/etc/unraid-version"
case distro.WDMyCloud: case distro.WDMyCloud:
slurp, _ := os.ReadFile("/etc/version") slurp, _ := os.ReadFile("/etc/version")
meta.DistroVersion = string(bytes.TrimSpace(slurp)) meta.DistroVersion = string(bytes.TrimSpace(slurp))
@ -153,6 +155,8 @@ func linuxVersionMeta() (meta versionMeta) {
meta.DistroVersion = m["productversion"] meta.DistroVersion = m["productversion"]
case distro.OpenWrt: case distro.OpenWrt:
meta.DistroVersion = m["DISTRIB_RELEASE"] meta.DistroVersion = m["DISTRIB_RELEASE"]
case distro.Unraid:
meta.DistroVersion = m["version"]
} }
return return
} }

@ -49,6 +49,7 @@ import (
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/util/clientmetric" "tailscale.com/util/clientmetric"
"tailscale.com/util/multierr" "tailscale.com/util/multierr"
"tailscale.com/version/distro"
"tailscale.com/wgengine" "tailscale.com/wgengine"
"tailscale.com/wgengine/filter" "tailscale.com/wgengine/filter"
) )
@ -1090,6 +1091,10 @@ func (h *peerAPIHandler) handlePeerPut(w http.ResponseWriter, r *http.Request) {
http.Error(w, errNoTaildrop.Error(), http.StatusInternalServerError) http.Error(w, errNoTaildrop.Error(), http.StatusInternalServerError)
return return
} }
if distro.Get() == distro.Unraid && !h.ps.directFileMode {
http.Error(w, "Taildrop folder not configured or accessible", http.StatusInternalServerError)
return
}
rawPath := r.URL.EscapedPath() rawPath := r.URL.EscapedPath()
suffix, ok := strings.CutPrefix(rawPath, "/v0/put/") suffix, ok := strings.CutPrefix(rawPath, "/v0/put/")
if !ok { if !ok {

@ -29,6 +29,7 @@ const (
TrueNAS = Distro("truenas") TrueNAS = Distro("truenas")
Gokrazy = Distro("gokrazy") Gokrazy = Distro("gokrazy")
WDMyCloud = Distro("wdmycloud") WDMyCloud = Distro("wdmycloud")
Unraid = Distro("unraid")
) )
var distro lazy.SyncValue[Distro] var distro lazy.SyncValue[Distro]
@ -90,6 +91,8 @@ func linuxDistro() Distro {
return WDMyCloud return WDMyCloud
case have("/usr/sbin/wd_crontab.sh"): // Western Digital MyCloud OS5 case have("/usr/sbin/wd_crontab.sh"): // Western Digital MyCloud OS5
return WDMyCloud return WDMyCloud
case have("/etc/unraid-version"):
return Unraid
} }
return "" return ""
} }

Loading…
Cancel
Save