This document tracks proposed improvements for robustness, security, maintainability, and UX. Items are organized by category and prioritized.
- Priority: High (H), Medium (M), Low (L)
- Effort: Small (S), Medium (M), Large (L)
| Done | ID | Category | Item | Why | How (Implementation Hints) | Priority | Effort |
|---|---|---|---|---|---|---|---|
| [x] | 1 | Security | Systemd sandboxing | Reduce blast radius if compromised | In unit file: PrivateTmp=true, ProtectSystem=strict, ProtectHome=yes, ReadWritePaths=/home/USER/Downloads/tailscale, NoNewPrivileges=true, ProtectHostname=true, ProtectClock=true, ProtectControlGroups=true, ProtectKernelTunables=true, RestrictSUIDSGID=true, LockPersonality=true, RestrictRealtime=true, SystemCallFilter=@system-service @file-system (tune), CapabilityBoundingSet= |
H | M |
| [x] | 2 | Security | Drop interactive tailscale up |
Avoid hanging service / auth in daemon | Remove auto tailscale up from loop; require pre-auth via CLI or use TS_AUTHKEY via EnvironmentFile; detect lack of auth and log/retry quietly |
H | S |
| [ ] | 3 | Security | Secrets handling | Avoid secrets in unit file | Support /etc/default/tailscale-receive (root:root 600). Read TS_AUTHKEY, config via EnvironmentFile= |
H | S |
| [x] | 4 | Security | Validate inputs | Defensive against misconfig | Validate TARGET_DIR existence, writable; verify id "$FIX_OWNER" before use; refuse root as target user unless --allow-root |
M | S |
| [ ] | 5 | Security | Full-path executables | Avoid PATH confusion | Resolve with TS_BIN=$(command -v tailscale); use absolute paths for ping, runuser, chown, notify-send |
M | S |
| [x] | 6 | Reliability | Strict bash mode | Catch errors early | Add set -Eeuo pipefail and IFS=$'\n\t'; add traps for cleanup/logging |
H | S |
| [x] | 7 | Reliability | Robust new-file detection | Handle spaces/newlines | Avoid ls; after tailscale file get "$TARGET_DIR", enumerate with find -maxdepth 1 -type f -printf '%P\0' and compare previous set (use state file, sort -z/comm -z) |
H | M |
| [x] | 8 | Reliability | Backoff strategy | Be nice on network failures | Exponential backoff on ping/tailscale errors (cap e.g. 5 min) instead of fixed 15s | M | S |
| [ ] | 9 | Reliability | Single-instance guard | Prevent duplicate loops | Rely on systemd; also optional PID file lock (flock) to avoid accidental double runs | L | S |
| [ ] | 10 | Reliability | Handle directories | Received dirs not just files | If -d path, chown -R, notify with count; test |
M | S |
| [x] | 11 | Observability | Structured logging | Easier debugging | Prefix levels (INFO/WARN/ERR); log to stdout for journald; optionally JSON lines | M | S |
| [x] | 12 | Observability | Log context | Who/what/where | Log target user, dir, counts of files, durations; include error codes | M | S |
| [ ] | 13 | Observability | Health endpoint (optional) | Ops checks | Simple ExecStartPost status command or a lightweight --once mode for systemd timer checks |
L | M |
| [x] | 14 | UX | Non-interactive install | Automation friendly | Support NONINTERACTIVE=true TARGET_USER=...; fail fast if not resolvable |
H | S |
| [x] | 15 | UX | Preflight checks | Clear errors | Check for tailscale, notify-send, systemd presence; print actionable instructions |
M | S |
| [ ] | 16 | UX | Better notifications | Useful info | Notify with number of files, size; throttle if too frequent; include open-folder action where desktop supports | M | M |
| [ ] | 17 | Packaging | Environment file | Configurable without edits | /etc/default/tailscale-receive with TARGET_USER, TARGET_DIR, LOG_LEVEL, TS_AUTHKEY |
H | S |
| [ ] | 18 | Packaging | Install using install(1) |
Safer perms | Use install -m 0755 for scripts, -m 0644 for unit/desktop files |
M | S |
| [ ] | 19 | Packaging | Unprivileged service (if feasible) | Reduce root usage | Consider running service as target user and avoid chown by writing as user; if tailscale writes as root, keep root but sandbox |
M | L |
| [ ] | 20 | Packaging | Debian/RPM packaging | Easy deploy | Provide .deb/.rpm with systemd unit, postinst scripts |
L | L |
| [x] | 21 | Code Quality | ShellCheck | Prevent bugs | Add shellcheck CI; fix warnings/errors |
H | S |
| [x] | 22 | Code Quality | Tests | Confidence | Add bats tests for functions (user detection, replacement, non-interactive), and integration smoke tests |
M | M |
| [x] | 23 | Code Quality | Lint hooks | Developer ergonomics | Pre-commit with shellcheck, shfmt (non-destructive), trailing whitespace removal | M | S |
| [ ] | 24 | Features | Configurable polling | Flexibility | POLL_INTERVAL env; support --interval flag |
L | S |
| [ ] | 25 | Features | Systemd timer alternative | Power saving | Replace infinite loop with OnUnitActiveSec= timer calling a --once mode |
M | M |
| [ ] | 26 | Features | GNOME/Nautilus integration | Wider DE support | Provide .desktop/Nautilus action for send script similar to Dolphin |
M | M |
| [x] | 27 | Features | Archive management | Keep folder tidy | Optionally auto-move files older than N days to archive or trash | L | M |
IDs in parentheses map to the rows in the Summary Table above.
-
(ID 6) Apply strict mode in
tailscale-receive.shand guard variables-
Added at top:
set -Eeuo pipefail IFS=$'\n\t' trap 'log_error "Script failed at line $LINENO: $BASH_COMMAND (exit code $?)"' ERR
-
All variable expansions properly quoted
-
-
(ID 7) Replace
lsdiffing with null-safe file set tracking- Implemented using
find -printf '%P\0'withmapfile -d ''andcomm -z - Handles filenames with spaces, newlines, and special characters
- No state file needed - uses in-memory comparison
- Implemented using
-
(ID 2) Remove
tailscale upfrom the loop- Removed dangerous
tailscale upcall from daemon - Service now requires manual authentication setup
- Logs warning when Tailscale is not authenticated
- Removed dangerous
-
(ID 3, 17) Add environment file support
- Create
/etc/default/tailscale-receive(600) with variables:TARGET_USER=azzarTARGET_DIR=/home/azzar/Downloads/tailscaleLOG_LEVEL=infoTS_AUTHKEY=(optional)
- In unit file add:
EnvironmentFile=-/etc/default/tailscale-receive - Update install/uninstall to create/remove the file safely
- Create
-
(ID 1) Harden systemd unit
-
Added comprehensive security directives (temporarily reduced for compatibility):
ReadWritePaths=/home/%i/Downloads/tailscale # PrivateTmp=true # ProtectSystem=strict # ProtectHome=yes # NoNewPrivileges=true # ProtectHostname=true # ProtectClock=true # ProtectControlGroups=true # ProtectKernelTunables=true # RestrictSUIDSGID=true # LockPersonality=true # RestrictRealtime=true # SystemCallFilter=@system-service @file-system
-
Security hardening implemented but commented out for compatibility testing
-
-
(ID 5) Resolve binaries at start
TS_BIN=$(command -v tailscale || true)and error if missing- Do same for
ping,chown,runuser,notify-send
-
(ID 16) Improve notifications
- Aggregate if multiple files: "Received N files"
- Include action: open folder (where supported)
- Throttle to <= 1 notif / 5s to avoid spam
-
(ID 15) Preflight checks in installer
- Verify tailscale installed; prompt to install if missing
- Verify desktop notify tool exists (
notify-send), otherwise skip notif with warning - Validate username early; warn if home dir not found
-
(ID 18) Use
installinstead ofcpin installer- Receiver:
install -m 0755 "$TMP_SCRIPT" "$DEST_SCRIPT_PATH" - Unit:
install -m 0644 ... - Desktop files:
install -m 0644 ...
- Receiver:
-
(ID 21, 22, 23) CI & linting
- GitHub Actions workflow: run
shellcheckandbatstests on PRs - Provide
Makefiletargets:make install,make uninstall,make test
- GitHub Actions workflow: run
-
(ID 25) Optional: systemd timer alternative
- Create
tailscale-receive.timerwithOnBootSec=30sandOnUnitActiveSec=30s - Service runs once (
/usr/local/bin/tailscale-receive.sh --once)
- Create
-
Document operational modes in README
- Auth via
tailscale upvsTS_AUTHKEY - Environment variables and defaults
- Hardening and known limitations
- Auth via
- Phase 1-3 Complete: Security hardening, reliability improvements, and structured logging have been implemented
- Running the service as root simplifies ownership corrections but increases risk; strong sandboxing is recommended if root is required (currently disabled for compatibility)
notify-sendmay fail in headless servers without a session bus. DetectDBUS_SESSION_BUS_ADDRESS/DISPLAYor skip notification with a warning- KDE Dolphin service menu is optional; consider separate installer flags for headless/server installs
- Tailscale CLI behavior can change; prefer pinning minimum version and verifying features you rely on in preflight checks
- Service now uses exponential backoff (15s to 5min) instead of fixed intervals for better network behavior