Skip to content

Add support for Taildrive - #509

Closed
ananthb wants to merge 11 commits into
hassio-addons:mainfrom
ananthb:taildrive
Closed

Add support for Taildrive#509
ananthb wants to merge 11 commits into
hassio-addons:mainfrom
ananthb:taildrive

Conversation

@ananthb

@ananthb ananthb commented May 31, 2025

Copy link
Copy Markdown
Contributor

Proposed Changes

Share homeassistant directories to your Tailnet using Taildrive.

Summary by CodeRabbit

  • New Features

    • Added Taildrive sharing toggles for additional Home Assistant directories (homeassistant_config, addon_configs, ssl, addons, backup, media, all_addon_configs) with per-directory options defaulting to false.
    • Added a one-shot startup task that syncs configured Taildrive shares, creating or removing shares to match configuration and reporting availability errors.
  • Documentation

    • Updated English translations and docs with the Taildrive option, descriptions, and knowledge-base link.

@coderabbitai

coderabbitai Bot commented May 31, 2025

Copy link
Copy Markdown

Walkthrough

Adds Taildrive support: config/schema extended with taildrive boolean options and new share map entries; docs and English translations updated; an s6 oneshot service (run/type/up) added to reconcile configured Taildrive shares with /opt/tailscale drive list at startup.

Changes

Cohort / File(s) Summary
Configuration
tailscale/config.yaml
Added Taildrive map entries (addons:rw, all_addon_configs:rw, backup:rw, homeassistant_config:rw, media:rw, share:rw, ssl:rw) and options.taildrive / schema.taildrive boolean fields for each share type.
Service scripts
tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/...
.../run, .../type, .../up
Added s6 oneshot service: type = oneshot, up references run, and a new executable run script that reads add-on config (bashio/jq), checks Taildrive capability via /opt/tailscale status, lists active drives, creates symlink /homeassistant/config, and issues /opt/tailscale drive share or drive unshare to reconcile configured vs active shares (skips unsharing drives not managed by the add-on).
Localization
tailscale/translations/en.yaml
Added taildrive translation entries (name and description) under configuration and tags explaining Taildrive shares and that options are disabled by default.
Documentation
tailscale/DOCS.md
Inserted taildrive option in sample config, added explanatory option and tags sections, and added a Taildrive reference anchor/link in the docs.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Config as Add‑on Config
    participant Run as taildrive run (oneshot)
    participant TSCli as /opt/tailscale CLI
    participant FS as Filesystem

    Config->>Run: provide `options.taildrive` and configured share list
    Run->>TSCli: /opt/tailscale status (check Taildrive capability)
    alt Taildrive unavailable & shares configured
        Run-->>Config: log error and exit non‑zero
    else Taildrive available
        Run->>TSCli: /opt/tailscale drive list
        TSCli-->>Run: active drives JSON
        Run->>FS: create symlink /homeassistant -> /config
        loop each possible share
            alt configured & not active
                Run->>TSCli: /opt/tailscale drive share "<name>" "/<name>"
            else active & not configured & managed_by_addon
                Run->>TSCli: /opt/tailscale drive unshare "<name>"
            else active & not managed_by_addon
                Run-->>Config: log skip (do not unshare)
            end
        end
    end
    Run-->>Config: exit (success)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

maintenance

Poem

I nibble configs with a twitchy nose,
I map the shares where moonlit folder grows.
One oneshot hop, the drives align and sing,
symlinks snug, and Tailscale does its thing. 🥕🐇

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add support for Taildrive' is clear, concise, and directly reflects the main change in the pull request, which implements Taildrive sharing functionality across configuration, service scripts, and documentation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
tailscale/translations/en.yaml (1)

93-98: Fix typo in the description.

The translation content is good and informative, but there's a small typo that should be corrected.

Apply this diff to fix the typo:

   taildrive:
     name: Taildrive Shares
     description: >-
-      This option allows you to specify which Homeassistant directories you
+      This option allows you to specify which Home Assistant directories you
       want to share with other Tailscale nodes using Taildrive.
       The listed values are the only allowed values.
tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run (1)

20-20: Consider improving array comparison logic.

The string-based array comparison using [[ ! " ${array[*]} " =~ " ${item} " ]] works but could be more robust for edge cases with special characters in directory names.

Consider using a more robust comparison approach:

# Function to check if array contains element
contains_element() {
    local element="$1"
    shift
    local array=("$@")
    for item in "${array[@]}"; do
        [[ "$item" == "$element" ]] && return 0
    done
    return 1
}

# Usage:
if ! contains_element "$dir" "${shared_dirs[@]}"; then
    # Share the directory
fi

Also applies to: 28-28

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7150d95 and 2aaf637.

📒 Files selected for processing (5)
  • tailscale/config.yaml (2 hunks)
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run (1 hunks)
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/type (1 hunks)
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/up (1 hunks)
  • tailscale/translations/en.yaml (1 hunks)
🔇 Additional comments (6)
tailscale/config.yaml (1)

27-34: LGTM: Comprehensive directory mappings added.

The new directory mappings provide good coverage of Home Assistant directories for Taildrive sharing. The read-write permissions are appropriate for the use case.

tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/up (1)

1-1: Clarify the purpose and content of this file.

This file appears to only contain a file path reference. If this is meant to be an s6 service script, it should contain executable commands or be properly configured as a symlink/reference to the actual run script.

Please verify if this file should:

  1. Be empty (if it's just a placeholder)
  2. Contain actual service startup commands
  3. Be a symlink to the main run script
tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/type (1)

1-1: LGTM: Correct service type configuration.

The oneshot service type is appropriate for the Taildrive synchronization script that needs to run and complete its task rather than staying as a daemon.

tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run (3)

1-7: LGTM: Proper script header and documentation.

The script header with shebang, shellcheck directive, and descriptive comments is well-structured and follows good practices.


8-9: LGTM: Configuration reading implementation.

The use of bashio::config with mapfile to read the configured directories into an array is correct and follows the add-on patterns.


18-24: Verify command path consistency and add error handling.

The script uses /opt/tailscale drive share here but used just taildrive earlier. The path should be consistent throughout.

Apply this diff to add error handling:

 for dir in "${configured_dirs[@]}"; do
     if [[ ! " ${shared_dirs[*]} " =~ " ${dir} " ]]; then
         # Share the directory
-        /opt/tailscale drive share "${dir}" "/${dir}"
+        if ! /opt/tailscale drive share "${dir}" "/${dir}" 2>/dev/null; then
+            bashio::log.error "Failed to share directory: ${dir}"
+        else
+            bashio::log.info "Successfully shared directory: ${dir}"
+        fi
     fi
 done

Also verify that the directory paths are correct - should they be /config, /media, etc. or the actual mounted paths?

Comment thread tailscale/config.yaml Outdated
Comment thread tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run Outdated
Comment thread tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run Outdated
@ananthb
ananthb force-pushed the taildrive branch 2 times, most recently from d9d88c5 to a64cf18 Compare May 31, 2025 14:38

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run (2)

26-32: ⚠️ Potential issue

Fix command path error and inverted logic.

This segment has two critical issues: incorrect command path and inverted conditional logic.

Apply this diff to fix both issues:

 for dir in "${shared_dirs[@]}"; do
-    if printf '%s\0' "${configured_dirs[@]}" | grep -Fxqz -- "${dir}"; then
+    if ! printf '%s\0' "${configured_dirs[@]}" | grep -Fxqz -- "${dir}"; then
         # Unshare the directory
-        /opt/taildrive drive unshare "${dir}"
+        if ! /opt/tailscale drive unshare "${dir}" 2>/dev/null; then
+            bashio::log.error "Failed to unshare directory: ${dir}"
+        else
+            bashio::log.info "Successfully unshared directory: ${dir}"
+        fi
     fi
 done

The command path should be /opt/tailscale drive unshare not /opt/taildrive drive unshare, and the logic should unshare directories that are NOT in the configured list.


11-16: 🛠️ Refactor suggestion

Add error handling for command execution.

While the command path appears correct, the script should handle cases where the tailscale drive list command fails.

Add error handling:

-mapfile -t shared_dirs < <(/opt/tailscale drive list | tail -n +3 | awk '{print $1}')
+if ! mapfile -t shared_dirs < <(/opt/tailscale drive list 2>/dev/null | tail -n +3 | awk '{print $1}'); then
+    bashio::log.warning "Failed to retrieve current Taildrive shares"
+    shared_dirs=()
+fi
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2aaf637 and a64cf18.

📒 Files selected for processing (2)
  • tailscale/config.yaml (2 hunks)
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tailscale/config.yaml
🔇 Additional comments (2)
tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run (2)

1-7: LGTM - Well-structured script header.

The shebang and header comments are properly formatted and provide clear context about the script's purpose.


8-9: LGTM - Configuration reading looks correct.

The script properly reads the configured directories from the add-on configuration using bashio.

Comment thread tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run Outdated
@lmagyar

lmagyar commented Jun 10, 2025

Copy link
Copy Markdown
Collaborator

I've made several fixes to this PR, pushed it to ananthb's repo:

  • you don't need map: \ - addon_config:rw, this is for this add-on only, you want to share all_addon_configs, so the config option addon_config is also renamed to addon_configs
  • renamed config option homeassistant_config to config, there were a loooong discussion when it was changed, and eg. the Samba add-on goes with the "config" option, and adds a symlink /config -> /homeassistant
  • you need a "?" to the end of the match() schema entry, because that makes it optional, without this and not adding an options: tag to the config.yaml, all instalations would break because of the missing mandatory config option
    • I've tried "list(addons|addon_configs|backup|config|media|share|ssl)?", but the config editor UI is so broken, can't handle this (though works in yaml editor mode, no problem to save)
    • finally I went with multiple bool config options, mandatory, no "?", but added default values under the opions: tag
    • this really differs from the current "all options are optional" situation, but due to another UI bug, it is impossible to make a configuration yaml dictionary optional, even when all entries are eg bool?, ie. there must be a taildrive: tag in the configuration yaml, but if Update documentation about UI bug in configuration editor - or make all the config options mandatory #463 is resolved, this will be just another mandatory config option
  • you must add the new service to the S6 "user" bundle service, or it will never be started
  • I've added a check for the drive:share ACL setting
  • your original process substitutions mapfile -t active_share_names < <(/opt/tailscale drive list ...... will never fail, without ACL settings TS fails with Access denied, but the taildrive S6 service starts up, I've changed it to variable assignment and command substitution, that preserves the exit code, and also makes the result ready for grep
  • typo: /opt/taildrive doesn't exists
  • added a check, that only the shares created by this add-on can be unshared by it, because I'm a bit afraid it would interfere with some user settings (we had similar implementation logic for serve/funnel at the beginning, and there were issues)
  • extended the DOCS

@ananthb

ananthb commented Jun 10, 2025

Copy link
Copy Markdown
Contributor Author

@lmagyar I'm not seeing it in my repo yet. Feel free to push your changes to the taildrive branch on my repo.

@lmagyar

lmagyar commented Jun 10, 2025

Copy link
Copy Markdown
Collaborator

This should be the PR: https://github.com/ananthb/addon-tailscale/pull/1

@github-actions

Copy link
Copy Markdown

There hasn't been any activity on this pull request recently. This pull request has been automatically marked as stale because of that and will be closed if no further activity occurs within 7 days. Thank you for your contributions.

@github-actions github-actions Bot added the stale There has not been activity on this issue or PR for quite some time. label Jul 11, 2025
@lmagyar

lmagyar commented Jul 11, 2025

Copy link
Copy Markdown
Collaborator

not stale

@github-actions github-actions Bot removed the stale There has not been activity on this issue or PR for quite some time. label Jul 12, 2025
@lmagyar

lmagyar commented Jul 27, 2025

Copy link
Copy Markdown
Collaborator

@ananthb I've fixed a bug that broke startup, please see PR in your repo.

@github-actions

Copy link
Copy Markdown

There hasn't been any activity on this pull request recently. This pull request has been automatically marked as stale because of that and will be closed if no further activity occurs within 7 days. Thank you for your contributions.

@github-actions github-actions Bot added the stale There has not been activity on this issue or PR for quite some time. label Aug 28, 2025
@ananthb

ananthb commented Aug 28, 2025

Copy link
Copy Markdown
Contributor Author

Not stale

@github-actions github-actions Bot removed the stale There has not been activity on this issue or PR for quite some time. label Aug 29, 2025
@frenck frenck added the new-feature New features or options. label Sep 4, 2025

@frenck frenck left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a merge conflict.

@ananthb

ananthb commented Sep 5, 2025

Copy link
Copy Markdown
Contributor Author

Sure let me fix it

@lmagyar

lmagyar commented Sep 5, 2025

Copy link
Copy Markdown
Collaborator

Just a note on the conflict, you don't need the funnel section in the docs, and the end of the docs should look like this:

[tailscale_info_tags]: https://tailscale.com/kb/1068/tags
[tailscale_info_taildrive]: https://tailscale.com/kb/1369/taildrive
[tailscale_info_taildrop]: https://tailscale.com/kb/1106/taildrop
[tailscale_info_userspace_networking]: https://tailscale.com/kb/1112/userspace-networking

@ananthb
ananthb force-pushed the taildrive branch 2 times, most recently from 822b079 to 8bceec6 Compare September 6, 2025 08:00
@ananthb
ananthb requested a review from frenck September 6, 2025 08:00
@ananthb
ananthb force-pushed the taildrive branch 2 times, most recently from ad01f3d to ad24eb4 Compare September 6, 2025 08:01

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
tailscale/config.yaml (2)

27-34: Security check: confirm intent to ship writable backup and all_addon_configs mounts.

  • Exposing /backup and /all_addon_configs over Taildrive could leak sensitive data (system backups, secrets from other add-ons).
  • If inclusion is intentional, call this out in DOCS and translations, and consider a strong warning.
  • If not, drop the mounts or keep them unmapped until UI/ACL guidance is finalized.

I can generate a minimal doc snippet and warnings for these two entries if you confirm the desired behavior.


53-54: Schema looks aligned; decide on all_addon_configs allowance and optionality.

  • The validator matches: homeassistant_config|addon_config|ssl|addons|backup|share|media. This intentionally excludes all_addon_configs (mapped above). If you want to allow it, add it to the regex; if not, document why.
  • Confirm whether taildrive should be considered optional. Current pattern follows how advertise_routes is modeled (property optional; items validated when present), which is OK.

Possible update if you decide to allow it:

-    - "match(^(?i:(homeassistant_config|addon_config|ssl|addons|backup|share|media))$)"
+    - "match(^(?i:(homeassistant_config|addon_config|ssl|addons|backup|share|media|all_addon_configs))$)"
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9a3e1ac and ad24eb4.

📒 Files selected for processing (6)
  • tailscale/DOCS.md (1 hunks)
  • tailscale/config.yaml (2 hunks)
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run (1 hunks)
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/type (1 hunks)
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/up (1 hunks)
  • tailscale/translations/en.yaml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/type
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/up
  • tailscale/translations/en.yaml
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2024-11-15T17:38:56.576Z
Learnt from: lmagyar
PR: hassio-addons/addon-tailscale#419
File: tailscale/rootfs/command/with-contenv-merge:8-12
Timestamp: 2024-11-15T17:38:56.576Z
Learning: The script `with-contenv-merge` in `tailscale/rootfs/command/` is directly copied from s6 and should not be modified.

Applied to files:

  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run
📚 Learning: 2024-10-09T10:32:14.110Z
Learnt from: mikz
PR: hassio-addons/addon-tailscale#407
File: tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-nginx/run:24-29
Timestamp: 2024-10-09T10:32:14.110Z
Learning: In the Tailscale add-on for Home Assistant, the `tailscale/rootfs` directory is copied into the container's root directory via the Dockerfile, ensuring that files like `/etc/nginx/templates/homeassistant.gtpl` are present at runtime.

Applied to files:

  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run
🪛 markdownlint-cli2 (0.17.2)
tailscale/DOCS.md

440-440: Link and image reference definitions should be needed
Unused link or image reference definition: "tailscale_info_taildrive"

(MD053, link-image-reference-definitions)


441-441: Link and image reference definitions should be needed
Duplicate link or image reference definition: "tailscale_info_taildrop"

(MD053, link-image-reference-definitions)

Comment thread tailscale/DOCS.md
Comment thread tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

♻️ Duplicate comments (1)
tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run (1)

36-46: Incorrect unshare path and same canonicalization bug

  • Uses /opt/taildrive instead of /opt/tailscale.
  • Same normalization issue as above.
  • Add error handling.
-# If a directory is shared but not configured, unshare it.
-for share_name in "${active_share_names[@]}"; do
-    if ! printf '%s\0' "${configured_share_names[@]}" | grep -Fxqz -- "${share_name}"; then
-        # Rewrite homeasstant_config to config
-        if [[ "${share_name}" == "homeassistant_config" ]]; then
-            share_name="config"
-        fi
-
-        # Unshare the directory
-        /opt/taildrive drive unshare "${share_name}"
-    fi
-done
+# If a directory is shared but not configured, unshare it.
+for name in "${active_canon[@]}"; do
+    if ! printf '%s\0' "${configured_canon[@]}" | grep -Fxqz -- "${name}"; then
+        if ! /opt/tailscale drive unshare "${name}" 2>/dev/null; then
+            bashio::log.error "Failed to unshare: ${name}"
+        else
+            bashio::log.info "Unshared: ${name}"
+        fi
+    fi
+done

Note: If your environment requires drive share unshare subcommand form, switch the unshare line accordingly. Please verify with the installed Tailscale CLI.

🧹 Nitpick comments (2)
tailscale/DOCS.md (1)

440-441: Fix unused and duplicate link refs

  • 440: tailscale_info_taildrive is defined but never used.
  • 441: Duplicate tailscale_info_taildrop definition.

Either use the Taildrive ref in a short “Option: taildrive” section or drop the unused/duplicate refs. Minimal fix below removes the duplicate and keeps Taildrive available for future use.

 [tailscale_info_userspace_networking]: https://tailscale.com/kb/1112/userspace-networking
 [tailscale_info_taildrive]: https://tailscale.com/kb/1369/taildrive
-[tailscale_info_taildrop]: https://tailscale.com/kb/1106/taildrop

Optionally, add a small section describing the new taildrive option and link it to [tailscale_info_taildrive]. I can draft that if you want.

tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run (1)

1-1: Ensure the s6 service is in the user bundle

Add taildrive to the user bundle; otherwise this oneshot won’t run.

+# /etc/s6-overlay/s6-rc.d/user/contents.d/taildrive
+taildrive
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9a3e1ac and ad24eb4.

📒 Files selected for processing (6)
  • tailscale/DOCS.md (1 hunks)
  • tailscale/config.yaml (2 hunks)
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run (1 hunks)
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/type (1 hunks)
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/up (1 hunks)
  • tailscale/translations/en.yaml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/type
  • tailscale/translations/en.yaml
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/up
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2024-11-15T17:38:56.576Z
Learnt from: lmagyar
PR: hassio-addons/addon-tailscale#419
File: tailscale/rootfs/command/with-contenv-merge:8-12
Timestamp: 2024-11-15T17:38:56.576Z
Learning: The script `with-contenv-merge` in `tailscale/rootfs/command/` is directly copied from s6 and should not be modified.

Applied to files:

  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run
📚 Learning: 2024-10-09T10:32:14.110Z
Learnt from: mikz
PR: hassio-addons/addon-tailscale#407
File: tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-nginx/run:24-29
Timestamp: 2024-10-09T10:32:14.110Z
Learning: In the Tailscale add-on for Home Assistant, the `tailscale/rootfs` directory is copied into the container's root directory via the Dockerfile, ensuring that files like `/etc/nginx/templates/homeassistant.gtpl` are present at runtime.

Applied to files:

  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run
🪛 markdownlint-cli2 (0.17.2)
tailscale/DOCS.md

440-440: Link and image reference definitions should be needed
Unused link or image reference definition: "tailscale_info_taildrive"

(MD053, link-image-reference-definitions)


441-441: Link and image reference definitions should be needed
Duplicate link or image reference definition: "tailscale_info_taildrop"

(MD053, link-image-reference-definitions)

🔇 Additional comments (1)
tailscale/config.yaml (1)

53-55: Make taildrive optional and include all_addon_configs

Update the schema entry in tailscale/config.yaml to mark taildrive optional and support all_addon_configs:

- taildrive:
-   - "match(^(?i:(homeassistant_config|addon_config|ssl|addons|backup|share|media))$)"
+ taildrive:
+   - "match(^(?i:(homeassistant_config|addon_config|all_addon_configs|ssl|addons|backup|share|media))$)?"

Comment thread tailscale/config.yaml Outdated
Comment thread tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run Outdated
Comment thread tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run Outdated
Comment thread tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run Outdated
Comment thread tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run Outdated
@lmagyar

lmagyar commented Sep 6, 2025

Copy link
Copy Markdown
Collaborator

This became a total mess. The only 2 merge conflict resolution were needed were the 2 thing I mentioned above.

This version got back to your first version, that has a lot of issues. See my comment: #509 (comment)

You should have rebased your branch, instead you cherry picked your first commit, and lost all other commits.

@lmagyar lmagyar added the no-stale This issue or PR is exempted from the stable bot. label Oct 22, 2025
@lmagyar

lmagyar commented Nov 6, 2025

Copy link
Copy Markdown
Collaborator

The last commit (adding export LOG_FD to each bashio script 8b59a55), can be reverted after hassio-addons/bashio#174 is published in a new base image.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run (3)

28-28: Consider using string non-emptiness check instead of word count.

Using wc -w on a newline-separated list works but is less semantically clear. A simpler check would be:

-  if (( 0 < $(wc -w <<< ${configured_share_names}) )); then
+  if [[ -n "${configured_share_names}" ]]; then

This directly checks if any shares are configured without relying on word-counting behavior.


43-51: Add error handling for share operations.

The share command could fail (e.g., permission denied, network issues) without clear indication to the user.

Apply this diff to add error handling:

   for share_name in ${configured_share_names}; do
     if ! grep -Fxq -- "${share_name}" <<< "${active_share_names}"; then
       bashio::log.info "Taildrive: sharing /${share_name}"
-      /opt/tailscale drive share "${share_name}" "/${share_name}"
+      if ! /opt/tailscale drive share "${share_name}" "/${share_name}"; then
+        bashio::log.error "Failed to share /${share_name}"
+      fi
     else
       bashio::log.info "Taildrive: /${share_name} is already shared"
     fi
   done

53-63: Add error handling for unshare operations.

Similar to the share loop, the unshare command could fail without clear user notification.

Apply this diff to add error handling:

   for share_name in ${active_share_names}; do
     if ! grep -Fxq -- "${share_name}" <<< "${configured_share_names}"; then
       if grep -Fxq -- "${share_name}" <<< "${all_share_names}"; then
         bashio::log.info "Taildrive: unsharing /${share_name}"
-        /opt/tailscale drive unshare "${share_name}"
+        if ! /opt/tailscale drive unshare "${share_name}"; then
+          bashio::log.error "Failed to unshare /${share_name}"
+        fi
       else
         bashio::log.info "Taildrive: skipping to unshare '${share_name}'"
       fi
     fi
   done
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0e70fbd and 8b59a55.

📒 Files selected for processing (1)
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: mikz
Repo: hassio-addons/addon-tailscale PR: 407
File: tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-nginx/run:24-29
Timestamp: 2024-10-09T10:32:14.110Z
Learning: In the Tailscale add-on for Home Assistant, the `tailscale/rootfs` directory is copied into the container's root directory via the Dockerfile, ensuring that files like `/etc/nginx/templates/homeassistant.gtpl` are present at runtime.
📚 Learning: 2024-10-09T10:32:14.110Z
Learnt from: mikz
Repo: hassio-addons/addon-tailscale PR: 407
File: tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-nginx/run:24-29
Timestamp: 2024-10-09T10:32:14.110Z
Learning: In the Tailscale add-on for Home Assistant, the `tailscale/rootfs` directory is copied into the container's root directory via the Dockerfile, ensuring that files like `/etc/nginx/templates/homeassistant.gtpl` are present at runtime.

Applied to files:

  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run
📚 Learning: 2024-11-15T17:38:56.576Z
Learnt from: lmagyar
Repo: hassio-addons/addon-tailscale PR: 419
File: tailscale/rootfs/command/with-contenv-merge:8-12
Timestamp: 2024-11-15T17:38:56.576Z
Learning: The script `with-contenv-merge` in `tailscale/rootfs/command/` is directly copied from s6 and should not be modified.

Applied to files:

  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run
📚 Learning: 2025-10-29T20:47:02.818Z
Learnt from: lmagyar
Repo: hassio-addons/addon-tailscale PR: 562
File: tailscale/rootfs/etc/s6-overlay/s6-rc.d/post-tailscaled/run:120-128
Timestamp: 2025-10-29T20:47:02.818Z
Learning: In the hassio-addons/addon-tailscale project, when checking for IPv6 addresses in bash scripts, use the regex format `if [[ "${variable}" =~ .*:.* ]]; then` for consistency with other IPv6 tests in the codebase.

Applied to files:

  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run
📚 Learning: 2025-09-17T23:53:19.467Z
Learnt from: lmagyar
Repo: hassio-addons/addon-tailscale PR: 509
File: tailscale/config.yaml:0-0
Timestamp: 2025-09-17T23:53:19.467Z
Learning: In the Tailscale add-on config.yaml, there is an intentional naming mismatch between map entries and schema field names: map entries use actual Home Assistant directory names (like `homeassistant_config`, `all_addon_configs`) while schema fields use user-friendly names (like `config`, `addon_configs`). This allows correct directory mapping while presenting cleaner option names in the UI.

Applied to files:

  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run

Comment thread tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run (1)

28-28: Quote configured_share_names in the wc test for robustness

Line 28 currently relies on unquoted expansion:

if (( 0 < $(wc -w <<< ${configured_share_names}) )); then

Safer and more idiomatic:

if (( 0 < $(wc -w <<< "${configured_share_names}") )); then

This avoids any future surprises from word splitting or globbing if keys ever change.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8b59a55 and a30e43c.

📒 Files selected for processing (6)
  • tailscale/DOCS.md (3 hunks)
  • tailscale/config.yaml (2 hunks)
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run (1 hunks)
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/type (1 hunks)
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/up (1 hunks)
  • tailscale/translations/en.yaml (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/type
🚧 Files skipped from review as they are similar to previous changes (3)
  • tailscale/translations/en.yaml
  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/up
  • tailscale/config.yaml
🧰 Additional context used
🧠 Learnings (7)
📚 Learning: 2024-10-09T10:32:14.110Z
Learnt from: mikz
Repo: hassio-addons/addon-tailscale PR: 407
File: tailscale/rootfs/etc/s6-overlay/s6-rc.d/init-nginx/run:24-29
Timestamp: 2024-10-09T10:32:14.110Z
Learning: In the Tailscale add-on for Home Assistant, the `tailscale/rootfs` directory is copied into the container's root directory via the Dockerfile, ensuring that files like `/etc/nginx/templates/homeassistant.gtpl` are present at runtime.

Applied to files:

  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run
  • tailscale/DOCS.md
📚 Learning: 2024-11-15T17:38:56.576Z
Learnt from: lmagyar
Repo: hassio-addons/addon-tailscale PR: 419
File: tailscale/rootfs/command/with-contenv-merge:8-12
Timestamp: 2024-11-15T17:38:56.576Z
Learning: The script `with-contenv-merge` in `tailscale/rootfs/command/` is directly copied from s6 and should not be modified.

Applied to files:

  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run
📚 Learning: 2025-11-06T10:55:55.062Z
Learnt from: lmagyar
Repo: hassio-addons/addon-tailscale PR: 566
File: tailscale/rootfs/usr/bin/subnet-routes:1-2
Timestamp: 2025-11-06T10:55:55.062Z
Learning: In the hassio-addons/addon-tailscale project, utility scripts in `/usr/bin/` (like `subnet-routes`, `protect-subnet-routes`, `unprotect-subnet-routes`) are invoked from s6-overlay service scripts or NetworkManager dispatchers that already use `#!/command/with-contenv bashio`. These utilities inherit the environment from their parent processes and therefore use `#!/usr/bin/env bashio` rather than `#!/command/with-contenv bashio`.

Applied to files:

  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run
📚 Learning: 2025-10-29T20:47:02.818Z
Learnt from: lmagyar
Repo: hassio-addons/addon-tailscale PR: 562
File: tailscale/rootfs/etc/s6-overlay/s6-rc.d/post-tailscaled/run:120-128
Timestamp: 2025-10-29T20:47:02.818Z
Learning: In the hassio-addons/addon-tailscale project, when checking for IPv6 addresses in bash scripts, use the regex format `if [[ "${variable}" =~ .*:.* ]]; then` for consistency with other IPv6 tests in the codebase.

Applied to files:

  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run
📚 Learning: 2025-09-17T23:53:19.467Z
Learnt from: lmagyar
Repo: hassio-addons/addon-tailscale PR: 509
File: tailscale/config.yaml:0-0
Timestamp: 2025-09-17T23:53:19.467Z
Learning: In the Tailscale add-on config.yaml, there is an intentional naming mismatch between map entries and schema field names: map entries use actual Home Assistant directory names (like `homeassistant_config`, `all_addon_configs`) while schema fields use user-friendly names (like `config`, `addon_configs`). This allows correct directory mapping while presenting cleaner option names in the UI.

Applied to files:

  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run
  • tailscale/DOCS.md
📚 Learning: 2025-11-06T11:15:56.108Z
Learnt from: lmagyar
Repo: hassio-addons/addon-tailscale PR: 509
File: tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run:41-41
Timestamp: 2025-11-06T11:15:56.108Z
Learning: In Home Assistant Docker add-ons, runtime changes to the container filesystem (such as symlinks, created files, or directory modifications) are not persisted between container restarts. The filesystem starts fresh on each run, so operations like `ln -s` don't need idempotent checks for pre-existing targets.

Applied to files:

  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run
📚 Learning: 2025-09-15T22:13:04.962Z
Learnt from: lmagyar
Repo: hassio-addons/addon-tailscale PR: 455
File: tailscale/rootfs/etc/s6-overlay/s6-rc.d/tailscaled/run:54-54
Timestamp: 2025-09-15T22:13:04.962Z
Learning: In Home Assistant Docker add-ons, files like `/etc/resolv.dnsmasq.conf` are ephemeral and get deleted/recreated on container restart, so using `mv` instead of `cp` for one-time startup operations is appropriate since the source file will be regenerated on the next restart.

Applied to files:

  • tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: workflows / Lint Add-on
🔇 Additional comments (4)
tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run (2)

16-39: Taildrive capability and config parsing look correct

Reading taildrive via jq and gating on .Self.CapMap["drive:share"] before calling drive list is coherent with the schema and avoids hitting Taildrive when the capability is absent. The error paths and bashio::exit.nok usage are also appropriate for a oneshot sync service.


41-67: Share/unshare logic correctly limits scope to add-on–managed shares

The loops over configured_share_names and active_share_names correctly:

  • Share configured-but-inactive names, and
  • Unshare active-but-unconfigured names only when present in all_share_names,

so user-created Taildrive shares are preserved while add-on-managed ones are reconciled. Logging is clear and should make behavior easy to debug.

tailscale/DOCS.md (2)

77-84: Config snippet for taildrive matches implementation

The new taildrive block in the sample configuration uses the same keys the run script and schema expect and defaults everything to false, which is a sensible, non-surprising default.


331-339: Taildrive option section and link are clear and consistent

The Option: \taildrive`section succinctly explains the feature, and the new[tailscale_info_taildrive]` reference correctly points to the upstream docs and is actually used, so markdownlint should be happy. Structure is consistent with the other option sections.

Also applies to: 482-482

@lmagyar

lmagyar commented Nov 23, 2025

Copy link
Copy Markdown
Collaborator
if (( 0 < $(wc -w <<< ${configured_share_names}) )); then

Safer and more idiomatic:

if (( 0 < $(wc -w <<< "${configured_share_names}") )); then

This avoids any future surprises from word splitting or globbing if keys ever change.

This doesn't protect against word splitting here, wc doesn't care, but it is OK for 0 < ....

But this is a typo in the for loops, already fixed in the last commit.

@lmagyar

lmagyar commented Jan 14, 2026

Copy link
Copy Markdown
Collaborator

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jan 14, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Taildrive support to the Tailscale addon, enabling users to share Home Assistant directories with other devices on their Tailnet. However, there are critical naming inconsistencies between the configuration schema and directory mappings that will prevent the feature from working correctly.

Changes:

  • Added Taildrive configuration options for seven directories (addons, addon_configs, backup, config, media, share, ssl) with per-directory boolean toggles defaulting to false
  • Added a new oneshot s6-overlay service that synchronizes Taildrive shares on startup by creating or removing shares to match configuration
  • Updated documentation and translations to describe the new Taildrive feature

Reviewed changes

Copilot reviewed 6 out of 8 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
tailscale/config.yaml Adds directory mappings, configuration options, and schema for Taildrive shares - contains critical naming mismatches
tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run Shell script that manages Taildrive share creation/removal - attempts to work around naming issues with a symlink
tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/type Defines the service as a oneshot
tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/up Points to the run script
tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/dependencies.d/post-tailscaled Ensures Tailscale is running before configuring Taildrive
tailscale/rootfs/etc/s6-overlay/s6-rc.d/user/contents.d/taildrive Marker file to enable the service
tailscale/translations/en.yaml Adds English translation for Taildrive configuration description
tailscale/DOCS.md Adds documentation for the Taildrive feature and configuration options

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run
Comment thread tailscale/config.yaml
Comment thread tailscale/DOCS.md
Comment thread tailscale/DOCS.md
Comment thread tailscale/config.yaml
Comment thread tailscale/config.yaml
Comment thread tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run Outdated
Comment thread tailscale/config.yaml
Comment thread tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run
Comment thread tailscale/rootfs/etc/s6-overlay/s6-rc.d/taildrive/run Outdated
@sim-san

sim-san commented Feb 2, 2026

Copy link
Copy Markdown

@lmagyar
Is there a possibility to test the version of the addon ?

@lmagyar

lmagyar commented Feb 3, 2026

Copy link
Copy Markdown
Collaborator

It's not merged here, so can't be tested even on the edge channel.

But you can "replace" this add-on with my fork. There is a script that will install the fork and copy this add-on's state to the fork and start that up. In theory you won't notice the change, but all the unmerged PR's are available there. See the beginning of the readme: https://github.com/lmagyar/homeassistant-addon-tailscale

@lmagyar lmagyar mentioned this pull request Feb 3, 2026
@lmagyar

lmagyar commented Feb 3, 2026

Copy link
Copy Markdown
Collaborator

Closing in favor of #617, GH started to refuse my updates to this PR.

@lmagyar lmagyar closed this Feb 3, 2026
@github-actions github-actions Bot locked and limited conversation to collaborators Feb 5, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

new-feature New features or options. no-stale This issue or PR is exempted from the stable bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants