├── .gitignore ├── logo.png ├── commitlint.config.js ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── config.yml │ └── bug_report.yml ├── workflows │ ├── pr-label.yml │ ├── translate.yml │ ├── release-drafter.yml │ ├── stale.yml │ ├── translate-download.yml │ ├── lint.yml │ ├── release.yml │ └── update-tailscale.yml └── release-drafter.yml ├── composer ├── src ├── usr │ └── local │ │ ├── emhttp │ │ └── plugins │ │ │ └── tailscale │ │ │ ├── event │ │ │ └── README │ │ │ ├── tailscale.png │ │ │ ├── README.md │ │ │ ├── restart.sh │ │ │ ├── enhanced-log.json │ │ │ ├── tailscale-watcher.php │ │ │ ├── include │ │ │ ├── Pages │ │ │ │ ├── Error.php │ │ │ │ ├── Lock.php │ │ │ │ ├── Info.php │ │ │ │ ├── Dashboard.php │ │ │ │ ├── Status.php │ │ │ │ └── Tailscale.php │ │ │ ├── common.php │ │ │ ├── tailscale-lock │ │ │ │ ├── disabled.php │ │ │ │ ├── locked.php │ │ │ │ ├── signed.php │ │ │ │ └── signing.php │ │ │ ├── page.php │ │ │ └── data │ │ │ │ ├── Lock.php │ │ │ │ └── Status.php │ │ │ ├── style.css │ │ │ ├── erase.sh │ │ │ ├── approve-nodes.php │ │ │ ├── Tailscale-3-Lock.page │ │ │ ├── Tailscale-4-Info.page │ │ │ ├── Tailscale.page │ │ │ ├── Tailscale-2-Status.page │ │ │ ├── Tailscale-1-Settings.page │ │ │ ├── Tailscale_dashboard.page │ │ │ ├── settings.json │ │ │ ├── lib │ │ │ └── select2 │ │ │ │ └── LICENSE.md │ │ │ ├── diagnostics.json │ │ │ └── locales │ │ │ ├── zh_CN.json │ │ │ ├── ja_JP.json │ │ │ ├── ko_KR.json │ │ │ ├── en_US.json │ │ │ ├── no_NO.json │ │ │ ├── sv_SE.json │ │ │ ├── pl_PL.json │ │ │ ├── uk_UA.json │ │ │ ├── pt_BR.json │ │ │ └── pt_PT.json │ │ ├── php │ │ └── unraid-tailscale-utils │ │ │ ├── daily.sh │ │ │ ├── log.sh │ │ │ ├── composer.json │ │ │ ├── unraid-tailscale-utils │ │ │ ├── LockInfo.php │ │ │ ├── DashboardInfo.php │ │ │ ├── Warning.php │ │ │ ├── StatusInfo.php │ │ │ ├── ConnectionInfo.php │ │ │ ├── PeerStatus.php │ │ │ ├── ServeConfig.php │ │ │ ├── Config.php │ │ │ ├── Watcher.php │ │ │ ├── LocalAPI.php │ │ │ └── Utils.php │ │ │ ├── daily.php │ │ │ └── pre-startup.php │ │ └── etc │ │ └── rc.d │ │ └── rc.tailscale ├── etc │ └── logrotate.d │ │ └── tailscale └── install │ ├── slack-desc │ └── doinst.sh ├── phpstan.neon ├── crowdin.yml ├── .coderabbit.yaml ├── plugin ├── plugin.json ├── tailscale.plg ├── tailscale-preview.plg └── plugin.j2 ├── README.md ├── CONTRIBUTING.md └── .php-cs-fixer.dist.php /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | ._.DS_Store 3 | .php-cs-fixer.cache 4 | vendor -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unraid/unraid-tailscale/HEAD/logo.png -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { extends: ["@commitlint/config-conventional"] }; -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: dkaser 4 | -------------------------------------------------------------------------------- /composer: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | composer --working-dir src/usr/local/php/unraid-tailscale-utils/ "$@" -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/event/README: -------------------------------------------------------------------------------- 1 | This folder is used by the package installation script. -------------------------------------------------------------------------------- /src/usr/local/php/unraid-tailscale-utils/daily.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | /usr/local/php/unraid-tailscale-utils/daily.php 1>/dev/null 2>&1 4 | -------------------------------------------------------------------------------- /phpstan.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | level: 9 3 | fileExtensions: 4 | - php 5 | - page 6 | paths: 7 | - src 8 | excludePaths: 9 | - */vendor/* -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/tailscale.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unraid/unraid-tailscale/HEAD/src/usr/local/emhttp/plugins/tailscale/tailscale.png -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/README.md: -------------------------------------------------------------------------------- 1 | **Tailscale** 2 | 3 | Tailscale is a VPN service that makes the devices and applications you own accessible anywhere in the world, securely and effortlessly. 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Support 4 | url: https://forums.unraid.net/topic/136889-plugin-tailscale/ 5 | about: Support thread on Unraid forums -------------------------------------------------------------------------------- /src/usr/local/php/unraid-tailscale-utils/log.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | log() { 4 | LOG_TIME=`date '+%Y/%m/%d %H:%M:%S'` 5 | CALLER=`basename "$0"` 6 | echo "$LOG_TIME $CALLER: $1" >> /var/log/tailscale-utils.log 7 | } -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/restart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . /usr/local/php/unraid-tailscale-utils/log.sh 4 | 5 | log "Restarting Tailscale in 5 seconds" 6 | echo "sleep 5 ; /etc/rc.d/rc.tailscale restart" | at now 2>/dev/null 7 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/enhanced-log.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "/var/log/tailscale.log", 4 | "/var/log/tailscale.log.*", 5 | "/var/log/tailscale-utils.log", 6 | "/var/log/tailscale-utils.log.*" 7 | ] 8 | } -------------------------------------------------------------------------------- /src/etc/logrotate.d/tailscale: -------------------------------------------------------------------------------- 1 | /var/log/tailscale.log { 2 | compress 3 | daily 4 | rotate 4 5 | notifempty 6 | missingok 7 | copytruncate 8 | } 9 | 10 | /var/log/tailscale-utils.log { 11 | compress 12 | daily 13 | rotate 4 14 | notifempty 15 | missingok 16 | copytruncate 17 | } 18 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/tailscale-watcher.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | run(); 11 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/include/Pages/Error.php: -------------------------------------------------------------------------------- 1 |

Oops!

2 |

Something unexpected has occurred, and this page cannot be loaded.

3 |

Please report the following error on the plugin support thread:

4 |

-------------------------------------------------------------------------------- /crowdin.yml: -------------------------------------------------------------------------------- 1 | project_id_env: CROWDIN_PROJECT_ID 2 | api_token_env: CROWDIN_PERSONAL_TOKEN 3 | 4 | preserve_hierarchy: true 5 | 6 | files: 7 | - source: /src/usr/local/emhttp/plugins/tailscale/locales/en_US.json 8 | dest: /unraid-tailscale-utils/en_US.json 9 | translation: /src/usr/local/emhttp/plugins/tailscale/locales/%locale_with_underscore%.json 10 | -------------------------------------------------------------------------------- /.coderabbit.yaml: -------------------------------------------------------------------------------- 1 | language: en-US 2 | early_access: true 3 | enable_free_tier: true 4 | reviews: 5 | profile: chill 6 | poem: false 7 | pre_merge_checks: 8 | docstrings: 9 | mode: off 10 | finishing_touches: 11 | docstrings: 12 | enabled: false 13 | tools: 14 | phpstan: 15 | enabled: false 16 | issue_enrichment: 17 | auto_enrich: 18 | enabled: false 19 | -------------------------------------------------------------------------------- /plugin/plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tailscale", 3 | "package_name": "unraid-tailscale-utils", 4 | "author": "Derek Kaser", 5 | "min": "7.0.0", 6 | "support": "https://forums.unraid.net/topic/136889-plugin-tailscale/", 7 | "launch": "Settings/Tailscale", 8 | "tailscaleVersion": "tailscale_1.92.3_amd64", 9 | "tailscaleSHA256": "5f51b7e3819286cb3f18e7999c51e37a967610011e88b6c25ff65c49ab0908dc" 10 | } 11 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/style.css: -------------------------------------------------------------------------------- 1 | .tablesorter .filtered { 2 | display: none; 3 | } 4 | .tablesorter-filter.disabled { 5 | display: none; 6 | } 7 | .fileTree { 8 | width: 300px; 9 | max-height: 150px; 10 | overflow-y: scroll; 11 | overflow-x: hidden; 12 | position: absolute; 13 | z-index: 100; 14 | display: none 15 | } 16 | 17 | li.select2-results__option { 18 | color: black; 19 | } -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/erase.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . /usr/local/emhttp/plugins/tailscale/log.sh 4 | 5 | log "Stopping Tailscale" 6 | /etc/rc.d/rc.tailscale stop 7 | 8 | log "Erasing Configuration" 9 | rm -f /boot/config/plugins/tailscale/tailscale.cfg 10 | rm -rf /boot/config/plugins/tailscale/state/ 11 | 12 | log "Restarting Tailscale" 13 | echo "sleep 5 ; /usr/local/emhttp/plugins/tailscale/update-settings.sh" | at now 2>/dev/null -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/approve-nodes.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | $value) { 14 | $utils->logmsg("Tailnet lock: signing {$value}"); 15 | $localAPI->postTkaSign($value); 16 | } 17 | -------------------------------------------------------------------------------- /.github/workflows/pr-label.yml: -------------------------------------------------------------------------------- 1 | name: PR Conventional Commit Validation 2 | 3 | on: 4 | pull_request: 5 | types: [opened, synchronize, reopened, edited] 6 | 7 | jobs: 8 | validate-pr-title: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: PR Conventional Commit Validation 12 | uses: ytanikin/pr-conventional-commits@b72758283dcbee706975950e96bc4bf323a8d8c0 13 | with: 14 | task_types: '["feat","fix","docs","test","ci","refactor","perf","chore","revert"]' 15 | -------------------------------------------------------------------------------- /src/install/slack-desc: -------------------------------------------------------------------------------- 1 | |-----handy-ruler------------------------------------------------------| 2 | unraid-tailscale-utils: tailscale-utils (utilites for running Tailscale on Unraid) 3 | unraid-tailscale-utils: 4 | unraid-tailscale-utils: This package provides the scripts and configuration pages to 5 | unraid-tailscale-utils: run Tailscale directly on the Unraid OS. 6 | unraid-tailscale-utils: 7 | unraid-tailscale-utils: https://github.com/unraid/unraid-tailscale-utils 8 | unraid-tailscale-utils: 9 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/Tailscale-3-Lock.page: -------------------------------------------------------------------------------- 1 | Menu="Tailscale" 2 | Icon="tailscale.png" 3 | Title="Lock" 4 | Type="xmenu" 5 | Tag="lock" 6 | Markdown="false" 7 | --- 8 | " . print_r($e, true) . ""; 16 | } 17 | 18 | ?> -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/Tailscale-4-Info.page: -------------------------------------------------------------------------------- 1 | Menu="Tailscale" 2 | Icon="tailscale.png" 3 | Title="Info" 4 | Tag="info" 5 | Type="xmenu" 6 | Markdown="false" 7 | --- 8 | " . print_r($e, true) . ""; 16 | } 17 | 18 | ?> -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/Tailscale.page: -------------------------------------------------------------------------------- 1 | Menu="NetworkServices" 2 | Icon="tailscale.png" 3 | Title="Tailscale" 4 | Type="xmenu" 5 | Tabs="true" 6 | Markdown="false" 7 | --- 8 | " . print_r($e, true) . ""; 16 | } 17 | 18 | ?> -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/Tailscale-2-Status.page: -------------------------------------------------------------------------------- 1 | Menu="Tailscale" 2 | Icon="tailscale.png" 3 | Title="Status" 4 | Tag="server" 5 | Type="xmenu" 6 | Markdown="false" 7 | --- 8 | " . print_r($e, true) . ""; 16 | } 17 | 18 | ?> 19 | -------------------------------------------------------------------------------- /.github/workflows/translate.yml: -------------------------------------------------------------------------------- 1 | name: Upload for translation 2 | 3 | on: 4 | push: 5 | branches: 6 | - "trunk" 7 | 8 | jobs: 9 | synchronize-with-crowdin: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v4 15 | 16 | - name: crowdin action 17 | uses: crowdin/github-action@v2 18 | with: 19 | upload_sources: true 20 | env: 21 | CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} 22 | CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} 23 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/Tailscale-1-Settings.page: -------------------------------------------------------------------------------- 1 | Menu="Tailscale" 2 | Icon="tailscale.png" 3 | Title="Settings" 4 | Type="xmenu" 5 | Tag="gears" 6 | Markdown="false" 7 | --- 8 | $var ?? null, "display" => $display ?? null)); 14 | } catch (Throwable $e) { 15 | echo "An error occurred:
" . print_r($e, true) . "
"; 16 | } 17 | 18 | ?> -------------------------------------------------------------------------------- /src/install/doinst.sh: -------------------------------------------------------------------------------- 1 | ( cd etc/cron.daily ; rm -rf tailscale-daily ) 2 | ( cd etc/cron.daily ; rm -rf check-tailscale-key ) 3 | ( cd etc/cron.daily ; ln -sf /usr/local/php/unraid-tailscale-utils/daily.sh tailscale-daily ) 4 | ( cd usr/local/emhttp/plugins/tailscale/event ; rm -rf array_started ) 5 | ( cd usr/local/emhttp/plugins/tailscale/event ; ln -sf ../restart.sh array_started ) 6 | ( cd usr/local/emhttp/plugins/tailscale/event ; rm -rf stopped ) 7 | ( cd usr/local/emhttp/plugins/tailscale/event ; ln -sf ../restart.sh stopped ) 8 | 9 | chmod 0644 /etc/logrotate.d/tailscale 10 | chown root:root /etc/logrotate.d/tailscale -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/Tailscale_dashboard.page: -------------------------------------------------------------------------------- 1 | Cond="version_compare(parse_ini_file('/etc/unraid-version')['version'],'6.11.9','>')" 2 | Menu="Dashboard:0" 3 | --- 4 | An error occurred loading the Tailscale dashboard widget.'; 13 | } 14 | 15 | ?> -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | categories: 2 | - title: "🚀 Features" 3 | labels: 4 | - "feat" 5 | - title: "🐛 Bug Fixes" 6 | labels: 7 | - "fix" 8 | - title: "🧰 Maintenance" 9 | labels: 10 | - "chore" 11 | - "refactor" 12 | change-template: "- $TITLE ([#$NUMBER]($URL))" 13 | category-template: "### $TITLE" 14 | change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. 15 | template: | 16 | $CHANGES 17 | prerelease: "true" 18 | include-pre-releases: "true" 19 | latest: "false" 20 | exclude-labels: 21 | - "docs" 22 | - "test" 23 | - "ci" 24 | - "perf" 25 | - "refactor" 26 | - "translation" 27 | replacers: 28 | - search: '/^(feat|fix|chore|refactor)(\(.+\))?: /' 29 | replace: "" 30 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name: Release Drafter 2 | 3 | on: 4 | push: 5 | branches: 6 | - trunk 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | update_release_draft: 13 | permissions: 14 | contents: write 15 | pull-requests: read 16 | runs-on: ubuntu-latest 17 | steps: 18 | # Calculate version string in format YYYY.MM.DD.HHMM 19 | - name: Set version string 20 | id: set_version 21 | run: TZ=UTC date +'%Y.%m.%d.%H%M' | xargs -I{} echo "version={}" >> $GITHUB_ENV 22 | 23 | - uses: dkaser/release-drafter@8bc802e5816eff4cc92ae7ce2a6f5f09c284bf0d 24 | with: 25 | version: ${{ env.version }} 26 | name: ${{ env.version }} 27 | tag: ${{ env.version }} 28 | env: 29 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 30 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Close inactive issues 2 | on: 3 | schedule: 4 | - cron: "30 2 * * *" 5 | 6 | jobs: 7 | close-issues: 8 | runs-on: ubuntu-latest 9 | permissions: 10 | issues: write 11 | pull-requests: write 12 | steps: 13 | - uses: actions/stale@v5 14 | with: 15 | days-before-issue-stale: 30 16 | days-before-issue-close: 7 17 | stale-issue-label: "stale" 18 | stale-issue-message: "This issue is stale because it has been open for 30 days with no activity." 19 | close-issue-message: "This issue was closed because it has been inactive for 7 days since being marked as stale." 20 | days-before-pr-stale: -1 21 | days-before-pr-close: -1 22 | exempt-issue-labels: enhancement 23 | repo-token: ${{ secrets.GITHUB_TOKEN }} 24 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "INCLUDE_INTERFACE": { 3 | "default": "1", 4 | "description": "Adds tailscale interface to Unraid services" 5 | }, 6 | "USAGE": { 7 | "default": "1", 8 | "description": "Allow collection of usage data" 9 | }, 10 | "ACCEPT_DNS": { 11 | "default": "0", 12 | "description": "Use MagicDNS" 13 | }, 14 | "ACCEPT_ROUTES": { 15 | "default": "0", 16 | "description": "Use routes from the tailnet" 17 | }, 18 | "SYSCTL_IP_FORWARD": { 19 | "default": "1", 20 | "description": "Enable IP forwarding in sysctl" 21 | }, 22 | "ENABLE_TAILSCALE": { 23 | "default": "1", 24 | "description": "Tailscale enabled" 25 | }, 26 | "WG_PORT": { 27 | "default": "0", 28 | "description": "Port for Wireguard connections" 29 | }, 30 | "TAILDROP_DIR": { 31 | "default": "", 32 | "description": "Destination for Taildrop files" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/usr/local/php/unraid-tailscale-utils/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dkaser/unraid-tailscale-utils", 3 | "description": "Tailscale configuration", 4 | "type": "library", 5 | "license": "GPL-3.0-or-later", 6 | "autoload": { 7 | "psr-4": { 8 | "Tailscale\\": "unraid-tailscale-utils/" 9 | } 10 | }, 11 | "authors": [ 12 | { 13 | "name": "Derek Kaser" 14 | } 15 | ], 16 | "require-dev": { 17 | "friendsofphp/php-cs-fixer": "^3.64", 18 | "phpstan/phpstan": "^2.1" 19 | }, 20 | "config": { 21 | "sort-packages": true, 22 | "bin-dir": "../../../../../vendor/bin/" 23 | }, 24 | "repositories": [ 25 | { 26 | "type": "vcs", 27 | "url": "https://github.com/dkaser/unraid-utils.git" 28 | } 29 | ], 30 | "require": { 31 | "edacerton/plugin-utils": "^1.0", 32 | "rlanvin/php-ip": "^3.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.github/workflows/translate-download.yml: -------------------------------------------------------------------------------- 1 | name: Download translations 2 | 3 | on: 4 | schedule: 5 | - cron: "30 2 * * *" 6 | workflow_dispatch: 7 | 8 | jobs: 9 | synchronize-with-crowdin: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: write 13 | pull-requests: write 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v4 17 | 18 | - name: crowdin action 19 | uses: crowdin/github-action@v2 20 | with: 21 | upload_sources: false 22 | download_translations: true 23 | push_translations: true 24 | commit_message: "chore: update translations from Crowdin" 25 | create_pull_request: true 26 | pull_request_title: "chore: update translations from Crowdin" 27 | pull_request_labels: "translation" 28 | env: 29 | CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} 30 | CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} 31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 32 | -------------------------------------------------------------------------------- /src/usr/local/php/unraid-tailscale-utils/unraid-tailscale-utils/LockInfo.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | class LockInfo 23 | { 24 | public string $LockSigned = ""; 25 | public string $LockSigning = ""; 26 | public string $PubKey = ""; 27 | public string $NodeKey = ""; 28 | } 29 | -------------------------------------------------------------------------------- /src/usr/local/php/unraid-tailscale-utils/unraid-tailscale-utils/DashboardInfo.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | class DashboardInfo 23 | { 24 | /** @var array $TailscaleIPs */ 25 | public array $TailscaleIPs = array(); 26 | 27 | public string $HostName = ""; 28 | public string $DNSName = ""; 29 | public string $Online = ""; 30 | } 31 | -------------------------------------------------------------------------------- /src/usr/local/php/unraid-tailscale-utils/unraid-tailscale-utils/Warning.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | class Warning 23 | { 24 | public string $Message; 25 | public string $Priority; 26 | 27 | public function __construct(string $message = "", string $priority = "system") 28 | { 29 | $this->Message = $message; 30 | $this->Priority = $priority; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/include/common.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | define(__NAMESPACE__ . "\PLUGIN_ROOT", dirname(dirname(__FILE__))); 23 | define(__NAMESPACE__ . "\PLUGIN_NAME", "tailscale-utils"); 24 | 25 | // @phpstan-ignore requireOnce.fileNotFound 26 | require_once "/usr/local/php/unraid-tailscale-utils/vendor/autoload.php"; 27 | 28 | $utils = new Utils(PLUGIN_NAME); 29 | $utils->setPHPDebug(); 30 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/include/tailscale-lock/disabled.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | use EDACerton\PluginUtils\Translator; 23 | 24 | if ( ! defined(__NAMESPACE__ . '\PLUGIN_ROOT') || ! defined(__NAMESPACE__ . '\PLUGIN_NAME')) { 25 | throw new \RuntimeException("Common file not loaded."); 26 | } 27 | 28 | $tr = $tr ?? new Translator(PLUGIN_ROOT); 29 | ?> 30 |

tr("tailscale_lock"); ?>

31 | 32 |

tr("lock.disabled"); ?>

-------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/lib/select2/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2012-2017 Kevin Brown, Igor Vaynberg, and Select2 contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/usr/local/php/unraid-tailscale-utils/unraid-tailscale-utils/StatusInfo.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | class StatusInfo 23 | { 24 | public ?LockInfo $LockInfo = null; 25 | public string $TsVersion = ""; 26 | public string $KeyExpiration = ""; 27 | public string $Online = ""; 28 | public string $InNetMap = ""; 29 | public string $Tags = ""; 30 | public string $LoggedIn = ""; 31 | public string $TsHealth = ""; 32 | public string $LockEnabled = ""; 33 | } 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: Report a problem with the plugin 3 | title: '[Bug]: ' 4 | labels: ['bug'] 5 | body: 6 | - type: textarea 7 | id: what-happened 8 | attributes: 9 | label: Description 10 | description: What happened? 11 | validations: 12 | required: true 13 | - type: input 14 | id: plugin-version 15 | attributes: 16 | label: Plugin Version 17 | description: Which version of the plugin were you using? 18 | validations: 19 | required: true 20 | - type: input 21 | id: unraid-version 22 | attributes: 23 | label: Unraid Version 24 | description: Which version of Unraid were you using? 25 | validations: 26 | required: true 27 | - type: textarea 28 | attributes: 29 | label: Steps To Reproduce 30 | description: How can be behavior be recreated? 31 | placeholder: | 32 | 1. Go to '...' 33 | 2. Click on '....' 34 | 3. Scroll down to '....' 35 | 4. See error 36 | validations: 37 | required: false 38 | - type: textarea 39 | attributes: 40 | label: Anything else? 41 | description: | 42 | Tip: You can attach screenshots by clicking this area to highlight it and then dragging files in. 43 | validations: 44 | required: false -------------------------------------------------------------------------------- /src/usr/local/php/unraid-tailscale-utils/daily.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | . 19 | */ 20 | 21 | namespace Tailscale; 22 | 23 | $docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp'; 24 | 25 | require_once "{$docroot}/plugins/tailscale/include/common.php"; 26 | if ( ! defined(__NAMESPACE__ . '\PLUGIN_ROOT') || ! defined(__NAMESPACE__ . '\PLUGIN_NAME')) { 27 | throw new \RuntimeException("Common file not loaded."); 28 | } 29 | $utils = new Utils(PLUGIN_NAME); 30 | 31 | $tailscaleConfig = $tailscaleConfig ?? new Config(); 32 | 33 | $utils->run_task('Tailscale\System::notifyOnKeyExpiration'); 34 | $utils->run_task('Tailscale\System::refreshWebGuiCert'); 35 | -------------------------------------------------------------------------------- /src/usr/local/php/unraid-tailscale-utils/unraid-tailscale-utils/ConnectionInfo.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | class ConnectionInfo 23 | { 24 | public string $HostName = ""; 25 | public string $DNSName = ""; 26 | public string $TailscaleIPs = ""; 27 | public string $MagicDNSSuffix = ""; 28 | public string $AdvertisedRoutes = ""; 29 | public string $AcceptRoutes = ""; 30 | public string $AcceptDNS = ""; 31 | public string $RunSSH = ""; 32 | public string $ExitNodeLocal = ""; 33 | public string $AdvertiseExitNode = ""; 34 | public string $UseExitNode = ""; 35 | public string $AutoUpdate = ""; 36 | } 37 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/include/tailscale-lock/locked.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | use EDACerton\PluginUtils\Translator; 23 | 24 | if ( ! defined(__NAMESPACE__ . '\PLUGIN_ROOT') || ! defined(__NAMESPACE__ . '\PLUGIN_NAME')) { 25 | throw new \RuntimeException("Common file not loaded."); 26 | } 27 | 28 | $tr = $tr ?? new Translator(PLUGIN_ROOT); 29 | ?> 30 |

tr("tailscale_lock"); ?>

31 | 32 |

33 | tr('lock.unsigned'); ?>. 34 |

35 | 36 |

tr('lock.unsigned_instructions'); ?>

37 | 38 | 44 | 45 |
getTailscaleLockNodekey(); ?>
-------------------------------------------------------------------------------- /src/usr/local/php/unraid-tailscale-utils/unraid-tailscale-utils/PeerStatus.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | class PeerStatus 23 | { 24 | public string $Name = ""; 25 | public string $LoginName = ""; 26 | public bool $SharedUser = false; 27 | 28 | /** @var string[] */ 29 | public array $IP = array(); 30 | 31 | public string $Address = ""; 32 | 33 | public bool $Online = false; 34 | public bool $Active = false; 35 | public bool $Relayed = false; 36 | 37 | public bool $Traffic = false; 38 | public int $TxBytes = 0; 39 | public int $RxBytes = 0; 40 | 41 | public bool $ExitNodeActive = false; 42 | public bool $ExitNodeAvailable = false; 43 | public bool $Mullvad = false; 44 | } 45 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/include/tailscale-lock/signed.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | use EDACerton\PluginUtils\Translator; 23 | 24 | if ( ! defined(__NAMESPACE__ . '\PLUGIN_ROOT') || ! defined(__NAMESPACE__ . '\PLUGIN_NAME')) { 25 | throw new \RuntimeException("Common file not loaded."); 26 | } 27 | 28 | $tr = $tr ?? new Translator(PLUGIN_ROOT); 29 | ?> 30 |

tr("tailscale_lock"); ?>

31 | 32 |

33 | tr('lock.signed_node'); ?> 34 |

35 | 36 |

37 | tr('lock.make_signing'); ?> 38 |

39 | 40 | 46 | 47 |
getTailscaleLockPubkey(); ?>
48 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Commit Quality 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | jobs: 10 | php-cs-fixer: 11 | name: PHP-CS-Fixer 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | - name: PHP-CS-Fixer 16 | uses: docker://oskarstark/php-cs-fixer-ga 17 | with: 18 | args: --diff --dry-run 19 | 20 | phpstan: 21 | name: PHPStan Analysis 22 | runs-on: ubuntu-latest 23 | 24 | steps: 25 | - uses: actions/checkout@v4 26 | - uses: php-actions/composer@v6 27 | with: 28 | working_dir: "src/usr/local/php/unraid-tailscale-utils" 29 | php_extensions: gmp 30 | - run: "vendor/bin/phpstan" 31 | 32 | commitlint: 33 | name: Commitlint 34 | runs-on: ubuntu-22.04 35 | steps: 36 | - uses: actions/setup-node@v4 37 | with: 38 | node-version: 18 39 | 40 | - name: Install commitlint 41 | run: | 42 | npm install -g commitlint 43 | npm install -g "@commitlint/config-conventional" 44 | 45 | - uses: actions/checkout@v4 46 | with: 47 | fetch-depth: 0 48 | 49 | - name: Validate current commit (last commit) with commitlint 50 | if: github.event_name == 'push' 51 | run: npx commitlint --from HEAD~1 --to HEAD --verbose 52 | 53 | - name: Validate PR commits with commitlint 54 | if: github.event_name == 'pull_request' 55 | run: npx commitlint --from ${{ github.event.pull_request.head.sha }}~${{ github.event.pull_request.commits }} --to ${{ github.event.pull_request.head.sha }} --verbose 56 | -------------------------------------------------------------------------------- /src/usr/local/etc/rc.d/rc.tailscale: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # /etc/rc.d/rc.tailscaled - start/stop the tailscaled daemon 3 | 4 | . /usr/local/php/unraid-tailscale-utils/log.sh 5 | 6 | start_tailscaled() { 7 | if ! /usr/bin/pgrep --ns $$ --euid root -f "^/usr/local/sbin/tailscaled" 1> /dev/null 2> /dev/null ; then 8 | 9 | /usr/local/php/unraid-tailscale-utils/pre-startup.php 10 | if [ $? -ne 0 ]; then 11 | log "Tailscale is disabled in settings, not starting tailscaled." 12 | return 13 | fi 14 | 15 | if [ -f /usr/local/emhttp/plugins/tailscale/custom-params.sh ]; then 16 | . /usr/local/emhttp/plugins/tailscale/custom-params.sh 17 | else 18 | TAILSCALE_CUSTOM_PARAMS="" 19 | fi 20 | 21 | TAILSCALE_START_CMD="/usr/local/sbin/tailscaled -statedir /boot/config/plugins/tailscale/state -tun tailscale1 $TAILSCALE_CUSTOM_PARAMS" 22 | log "Starting tailscaled: $TAILSCALE_START_CMD" 23 | mkdir -p /boot/config/plugins/tailscale/state 24 | $TAILSCALE_START_CMD 2>&1 | grep -vF "monitor: [unexpected]" >> /var/log/tailscale.log & 25 | nohup /usr/local/emhttp/plugins/tailscale/tailscale-watcher.php 1>/dev/null 2>&1 & 26 | fi 27 | } 28 | 29 | stop_tailscaled() { 30 | log "Stopping tailscaled." 31 | killall --ns $$ --wait tailscale-watcher.php 2> /dev/null 32 | killall --ns $$ --wait tailscaled 2> /dev/null 33 | } 34 | 35 | restart_tailscaled() { 36 | stop_tailscaled 37 | sleep 1 38 | start_tailscaled 39 | } 40 | 41 | case "$1" in 42 | 'start') 43 | start_tailscaled 44 | ;; 45 | 'stop') 46 | stop_tailscaled 47 | ;; 48 | 'restart') 49 | restart_tailscaled 50 | ;; 51 | *) 52 | echo "usage $0 start|stop|restart" 53 | esac 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # unraid-tailscale 2 | 3 | [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](LICENSE) 4 | [![GitHub Releases](https://img.shields.io/github/v/release/unraid/unraid-tailscale)](https://github.com/unraid/unraid-tailscale/releases) 5 | [![Last Commit](https://img.shields.io/github/last-commit/unraid/unraid-tailscale)](https://github.com/unraid/unraid-tailscale/commits/trunk/) 6 | [![Code Style: PHP-CS-Fixer](https://img.shields.io/badge/code%20style-php--cs--fixer-brightgreen.svg)](https://github.com/FriendsOfPHP/PHP-CS-Fixer) 7 | ![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/unraid/unraid-tailscale/total) 8 | ![GitHub Downloads (all assets, latest release)](https://img.shields.io/github/downloads/unraid/unraid-tailscale/latest/total) 9 | ## Features 10 | - Easy Tailscale installation and management on Unraid 11 | - Helper scripts for authentication and status 12 | - Example configurations for common use cases 13 | 14 | ## Development 15 | 16 | ### Requirements 17 | 18 | - [Composer](https://getcomposer.org/) for dependency management 19 | 20 | ### Testing 21 | 22 | 1. Clone the repository. 23 | 2. Run `./composer install` to install dependencies. 24 | 3. For local testing, copy the contents of `src/` (except for the `install` directory) to the root of the Unraid test system. 25 | 26 | ### Contributing 27 | Pull requests and issues are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines, including code checks, commit message conventions, and licensing. You can also open an issue to discuss your idea. 28 | 29 | ## License 30 | This project is licensed under the GNU General Public License v3.0 or later. See [LICENSE](LICENSE) for details. 31 | -------------------------------------------------------------------------------- /src/usr/local/php/unraid-tailscale-utils/pre-startup.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | . 19 | */ 20 | 21 | namespace Tailscale; 22 | 23 | $docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp'; 24 | require_once "{$docroot}/plugins/tailscale/include/common.php"; 25 | 26 | if ( ! defined(__NAMESPACE__ . '\PLUGIN_ROOT') || ! defined(__NAMESPACE__ . '\PLUGIN_NAME')) { 27 | throw new \RuntimeException("Common file not loaded."); 28 | } 29 | $utils = new Utils(PLUGIN_NAME); 30 | 31 | $tailscaleConfig = $tailscaleConfig ?? new Config(); 32 | 33 | $utils->run_task('Tailscale\System::createTailscaledParamsFile', array($tailscaleConfig)); 34 | $utils->run_task('Tailscale\System::applyGRO'); 35 | $utils->run_task('Tailscale\System::setExtraInterface', array($tailscaleConfig)); 36 | $utils->run_task('Tailscale\System::enableIPForwarding', array($tailscaleConfig)); 37 | $utils->run_task('Tailscale\System::createTaildropLink', array($tailscaleConfig)); 38 | 39 | if ($tailscaleConfig->Enable) { 40 | exit(0); 41 | } else { 42 | exit(1); 43 | } 44 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to unraid-tailscale-utils 2 | 3 | Thank you for your interest in contributing to **unraid-tailscale-utils**! 4 | 5 | ## How to Contribute 6 | 7 | - **Bug Reports & Feature Requests:** 8 | Please open an issue describing your bug or feature request with as much detail as possible. 9 | 10 | - **Pull Requests:** 11 | 1. Fork the repository and create your branch from `main`. 12 | 2. Make your changes, following the existing code style. 13 | 3. Add or update tests as appropriate. 14 | 4. Ensure your code passes all checks (see below). 15 | 5. Submit a pull request with a clear description of your changes. 16 | 17 | ## Localization 18 | 19 | New strings should be added to `src/usr/local/emhttp/plugins/tailscale/locales/en_US.json`. 20 | 21 | Translations are managed via Crowdin (https://translate.edac.dev/) 22 | 23 | ## Code Quality & Checks 24 | 25 | This repository uses automated code checks via GitHub Actions ([.github/workflows/lint.yml](.github/workflows/lint.yml)): 26 | 27 | - **Static Analysis:** 28 | Run `vendor/bin/phpstan` after running `./composer install` in the repository root. 29 | 30 | - **Code Formatting:** 31 | Run `vendor/bin/php-cs-fixer fix` to automatically apply formatting rules. 32 | 33 | - **Commit Message Linting:** 34 | All commits must follow the [Conventional Commits](https://www.conventionalcommits.org/) specification. 35 | Example: 36 | ``` 37 | feat: add advanced log filtering 38 | fix: resolve colorization bug in syslog view 39 | ``` 40 | 41 | These checks are run automatically on every push and pull request. Please ensure your code passes locally before submitting. 42 | 43 | ## License 44 | 45 | By contributing to this repository, you agree that your contributions will be licensed under the [GNU General Public License v3.0 or later](LICENSE). 46 | -------------------------------------------------------------------------------- /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | files() 5 | ->in(__DIR__) 6 | ->name('*.php') 7 | ->name('*.page') 8 | ->exclude(['vendor']) 9 | ; 10 | 11 | $config = new PhpCsFixer\Config(); 12 | return $config 13 | ->setRiskyAllowed(true) 14 | ->setRules([ 15 | '@PSR12' => true, 16 | 'no_empty_comment' => true, 17 | 'multiline_comment_opening_closing' => true, 18 | 'single_line_comment_spacing' => true, 19 | 'single_line_comment_style' => true, 20 | 'heredoc_indentation' => true, 21 | 'include' => true, 22 | 'no_alternative_syntax' => true, 23 | 'single_space_around_construct' => true, 24 | 'binary_operator_spaces' => ['default' => 'align_single_space_minimal'], 25 | 'concat_space' => ['spacing' => 'one'], 26 | 'linebreak_after_opening_tag' => true, 27 | 'increment_style' => ['style' => 'post'], 28 | 'logical_operators' => true, 29 | 'no_useless_concat_operator' => ['juggle_simple_strings' => true], 30 | 'not_operator_with_space' => true, 31 | 'object_operator_without_whitespace' => true, 32 | 'standardize_increment' => true, 33 | 'standardize_not_equals' => true, 34 | 'no_useless_return' => true, 35 | 'no_empty_statement' => true, 36 | 'semicolon_after_instruction' => true, 37 | 'explicit_string_variable' => true, 38 | 'simple_to_complex_string_variable' => true, 39 | 'method_chaining_indentation' => true, 40 | 'no_extra_blank_lines' => ['tokens' => ['attribute', 'break', 'case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'return', 'square_brace_block', 'switch', 'throw', 'use']], 41 | ]) 42 | ->setIndent(' ') 43 | ->setLineEnding("\n") 44 | ->setFinder($finder) 45 | ; 46 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/include/page.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | /** 23 | * @param array $params 24 | */ 25 | function getPage(string $filename, bool $niceError = true, array $params = array()): string 26 | { 27 | try { 28 | require_once dirname(__FILE__) . "/common.php"; 29 | return includePage(dirname(__FILE__) . "/Pages/{$filename}.php", $params); 30 | } catch (\Throwable $e) { 31 | if ($niceError) { 32 | file_put_contents("/var/log/tailscale-error.log", print_r($e, true) . PHP_EOL, FILE_APPEND); 33 | return includePage(dirname(__FILE__) . "/Pages/Error.php", array("e" => $e)); 34 | } else { 35 | throw $e; 36 | } 37 | } 38 | } 39 | 40 | /** 41 | * @param array $params 42 | */ 43 | function includePage(string $filename, array $params = array()): string 44 | { 45 | extract($params); 46 | 47 | if (is_file($filename)) { 48 | ob_start(); 49 | try { 50 | include $filename; 51 | return ob_get_clean() ?: ""; 52 | } catch (\Throwable $e) { 53 | ob_end_clean(); 54 | throw $e; 55 | } 56 | } 57 | return ""; 58 | } 59 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/include/Pages/Lock.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | use EDACerton\PluginUtils\Translator; 23 | 24 | if ( ! defined(__NAMESPACE__ . '\PLUGIN_ROOT') || ! defined(__NAMESPACE__ . '\PLUGIN_NAME')) { 25 | throw new \RuntimeException("Common file not loaded."); 26 | } 27 | 28 | $tr = $tr ?? new Translator(PLUGIN_ROOT); 29 | 30 | $tailscaleConfig = $tailscaleConfig ?? new Config(); 31 | 32 | if ( ! $tailscaleConfig->Enable) { 33 | echo($tr->tr("tailscale_disabled")); 34 | return; 35 | } 36 | 37 | if ( ! defined(__NAMESPACE__ . "\PLUGIN_ROOT")) { 38 | throw new \RuntimeException("PLUGIN_ROOT not defined"); 39 | } 40 | 41 | $signingNode = false; 42 | 43 | $tailscaleInfo = $tailscaleInfo ?? new Info($tr); 44 | 45 | switch (true) { 46 | case $tailscaleInfo->getTailscaleLockSigning(): 47 | require PLUGIN_ROOT . "/include/tailscale-lock/signing.php"; 48 | break; 49 | case $tailscaleInfo->getTailscaleLockSigned(): 50 | require PLUGIN_ROOT . "/include/tailscale-lock/signed.php"; 51 | break; 52 | case $tailscaleInfo->getTailscaleLockEnabled(): 53 | require PLUGIN_ROOT . "/include/tailscale-lock/locked.php"; 54 | break; 55 | default: 56 | require PLUGIN_ROOT . "/include/tailscale-lock/disabled.php"; 57 | break; 58 | } 59 | -------------------------------------------------------------------------------- /src/usr/local/php/unraid-tailscale-utils/unraid-tailscale-utils/ServeConfig.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | class ServeConfig 23 | { 24 | private \stdClass $config; 25 | 26 | public function __construct(string $hostname, string $port, string $target) 27 | { 28 | // Validate the hostname 29 | if ( ! filter_var($hostname, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)) { 30 | throw new \InvalidArgumentException("Invalid hostname: {$hostname}"); 31 | } 32 | 33 | // Validate the port 34 | if ( ! is_numeric($port) || (int)$port < 1 || (int)$port > 65535) { 35 | throw new \InvalidArgumentException("Invalid port: {$port}"); 36 | } 37 | 38 | $hostAndPort = "{$hostname}:{$port}"; 39 | 40 | $this->config = new \stdClass(); 41 | 42 | $this->config->TCP = new \stdClass(); 43 | $this->config->TCP->{$port} = new \stdClass(); 44 | $this->config->TCP->{$port}->HTTPS = true; 45 | 46 | $this->config->Web = new \stdClass(); 47 | $this->config->Web->{$hostAndPort} = new \stdClass(); 48 | $this->config->Web->{$hostAndPort}->Handlers = new \stdClass(); 49 | $this->config->Web->{$hostAndPort}->Handlers->{'/'} = new \stdClass(); 50 | $this->config->Web->{$hostAndPort}->Handlers->{'/'}->Proxy = $target; 51 | 52 | $this->config->AllowFunnel = new \stdClass(); 53 | $this->config->AllowFunnel->{$hostAndPort} = true; 54 | } 55 | 56 | public function getConfig(): \stdClass 57 | { 58 | return $this->config; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/diagnostics.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Tailscale", 3 | "filters": [ 4 | "s/\\.[^\\.]*\\.myunraid\\.net/\\.hash\\.myunraid\\.net/g", 5 | "s/\\.[^\\.]*\\.ts\\.net/\\.magicdns\\.ts\\.net/g" 6 | ], 7 | "commands": [ 8 | { 9 | "command": "tailscale status", 10 | "file": "tailscale-status.txt", 11 | "filters": [ 12 | "s/^(\\S*[ ]*\\S*[ ]*\\S)\\S*/\\1zzz/g", 13 | "s/^(\\S*[ ]*\\S)\\S*/\\1zzz/g", 14 | "s/ */ /g" 15 | ] 16 | }, 17 | { 18 | "command": "tailscale debug prefs | jq 'del(.Config)'", 19 | "file": "tailscale-debug-prefs.txt" 20 | }, 21 | { 22 | "command": "tailscale lock status", 23 | "file": "tailscale-lock-status.txt" 24 | }, 25 | { 26 | "command": "ls -Rl /usr/local/emhttp/plugins/tailscale/", 27 | "file": "plugin-files.txt" 28 | }, 29 | { 30 | "command": "ls -l /boot/config/plugins/tailscale/", 31 | "file": "config-files.txt" 32 | }, 33 | { 34 | "command": "iptables -L -n -v", 35 | "file": "iptables.txt" 36 | }, 37 | { 38 | "command": "ip link", 39 | "file": "ip-link.txt" 40 | }, 41 | { 42 | "command": "ip address", 43 | "file": "ip-address.txt" 44 | }, 45 | { 46 | "command": "docker network inspect host", 47 | "file": "docker-network-host.txt" 48 | }, 49 | { 50 | "command": "ip rule", 51 | "file": "ip-rule.txt" 52 | }, 53 | { 54 | "command": "ip route list table 52", 55 | "file": "ip-route-tailscale.txt" 56 | }, 57 | { 58 | "command": "ip route list table all", 59 | "file": "ip-route-all.txt" 60 | }, 61 | { 62 | "command": "netstat -4nl", 63 | "file": "ipv4-listening.txt" 64 | } 65 | ], 66 | "files": [ 67 | "/boot/config/plugins/tailscale/tailscale.cfg", 68 | "/etc/resolv.conf", 69 | "/etc/ssh/sshd_config", 70 | "/etc/nginx/conf.d/servers.conf", 71 | "/etc/samba/smb-names.conf", 72 | "/var/log/tailscale*" 73 | ], 74 | "system_diagnostics": true, 75 | "upload": "https://plugin-diagnostics.edacerton.win/" 76 | } -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | release: 5 | types: 6 | - prereleased 7 | - released 8 | - published 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | permissions: 14 | contents: write 15 | steps: 16 | - uses: dkaser/unraid-plugin-release-action@v1 17 | id: release_action 18 | with: 19 | github_token: ${{ secrets.GITHUB_TOKEN }} 20 | plg_branch: trunk 21 | build_prereleases: true 22 | ssh_key: ${{ secrets.DEPLOY_KEY }} 23 | composer_dir: src/usr/local/php/unraid-tailscale-utils/ 24 | 25 | # Print out the commit SHA 26 | - name: Print commit SHA 27 | run: echo "Commit SHA ${{ steps.release_action.outputs.commit_long_sha }}" 28 | 29 | # Update preview tag using git 30 | - name: Update preview tag 31 | run: | 32 | cd ${{ github.workspace }}/main 33 | git tag -f preview ${{ steps.release_action.outputs.commit_long_sha }} 34 | git push origin preview --force 35 | 36 | # Update main tag if not a prerelease 37 | - name: Update main tag 38 | if: github.event.release.prerelease == false 39 | run: | 40 | cd ${{ github.workspace }}/main 41 | git tag -f main ${{ steps.release_action.outputs.commit_long_sha }} 42 | git push origin main --force 43 | 44 | - name: Notify Discord 45 | uses: dkaser/discord-webhook-notify@tailscale 46 | with: 47 | webhookUrl: ${{ secrets.TAILSCALE_DISCORD_WEBHOOK }} 48 | username: Tailscale Bot 49 | avatarUrl: https://raw.githubusercontent.com/unraid/unraid-tailscale/trunk/logo.png 50 | thumbnailUrl: https://raw.githubusercontent.com/unraid/unraid-tailscale/trunk/logo.png 51 | severity: info 52 | color: ${{ github.event.release.prerelease && '#ffff00' || '#00ff00' }} 53 | title: New Update Available 54 | description: | 55 | ## Tailscale Plugin Update : ${{ github.event.release.name }} 56 | 57 | ${{ github.event.release.body }} 58 | fields: | 59 | [ 60 | {"name": "Channel", "value": ${{ toJson(github.event.release.prerelease && 'Preview :test_tube:' || 'Release') }}, "inline": true}, 61 | {"name": "Tag", "value": ${{ toJson(github.event.release.tag_name) }}, "inline": true}, 62 | {"name": "Github Release", "value": ${{ toJson(format('[Link]({0})', github.event.release.html_url)) }}, "inline": true} 63 | ] 64 | -------------------------------------------------------------------------------- /src/usr/local/php/unraid-tailscale-utils/unraid-tailscale-utils/Config.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | class Config 23 | { 24 | public bool $IncludeInterface; 25 | public bool $Usage; 26 | public bool $IPForward; 27 | public bool $Enable; 28 | public bool $SSH; 29 | public bool $AllowDNS; 30 | public bool $AllowRoutes; 31 | public bool $AllowFunnel; 32 | public bool $AddPeersToHosts; 33 | public bool $NoLogsNoSupport; 34 | public bool $UseTPM; 35 | 36 | public int $WgPort; 37 | public string $TaildropDir; 38 | 39 | public function __construct() 40 | { 41 | $config_file = '/boot/config/plugins/tailscale/tailscale.cfg'; 42 | 43 | // Load configuration file 44 | if (file_exists($config_file)) { 45 | $saved_config = parse_ini_file($config_file) ?: array(); 46 | } else { 47 | $saved_config = array(); 48 | } 49 | 50 | $this->IncludeInterface = boolval($saved_config["INCLUDE_INTERFACE"] ?? "1"); 51 | $this->Usage = boolval($saved_config["USAGE"] ?? "1"); 52 | $this->IPForward = boolval($saved_config["SYSCTL_IP_FORWARD"] ?? "1"); 53 | $this->Enable = boolval($saved_config["ENABLE_TAILSCALE"] ?? "1"); 54 | $this->SSH = boolval($saved_config["SSH"] ?? "0"); 55 | $this->AllowDNS = boolval($saved_config["ACCEPT_DNS"] ?? "0"); 56 | $this->AllowRoutes = boolval($saved_config["ACCEPT_ROUTES"] ?? "0"); 57 | $this->AllowFunnel = boolval($saved_config["ALLOW_FUNNEL"] ?? "0"); 58 | $this->AddPeersToHosts = boolval($saved_config["ADD_PEERS_TO_HOSTS"] ?? "0"); 59 | $this->NoLogsNoSupport = boolval($saved_config["NO_LOGS_NO_SUPPORT"] ?? "0"); 60 | $this->UseTPM = boolval($saved_config["USE_TPM"] ?? "0"); 61 | 62 | $this->WgPort = intval($saved_config["WG_PORT"] ?? "0"); 63 | 64 | $this->TaildropDir = $saved_config["TAILDROP_DIR"] ?? ""; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/include/data/Lock.php: -------------------------------------------------------------------------------- 1 | . 20 | */ 21 | 22 | use EDACerton\PluginUtils\Translator; 23 | 24 | try { 25 | require_once dirname(dirname(__FILE__)) . "/common.php"; 26 | 27 | if ( ! defined(__NAMESPACE__ . '\PLUGIN_ROOT') || ! defined(__NAMESPACE__ . '\PLUGIN_NAME')) { 28 | throw new \RuntimeException("Common file not loaded."); 29 | } 30 | 31 | $tr = $tr ?? new Translator(PLUGIN_ROOT); 32 | 33 | $tailscaleConfig = $tailscaleConfig ?? new Config(); 34 | 35 | if ( ! $tailscaleConfig->Enable) { 36 | echo("{}"); 37 | return; 38 | } 39 | 40 | switch ($_POST['action']) { 41 | case 'get': 42 | $tailscaleInfo = $tailscaleInfo ?? new Info($tr); 43 | $rows = ""; 44 | 45 | $mullvad = filter_var($_POST['mullvad'] ?? false, FILTER_VALIDATE_BOOLEAN); 46 | 47 | foreach ($tailscaleInfo->getTailscaleLockPending() as $lockHost => $lockKey) { 48 | if ( ! $mullvad && str_contains($lockHost, 'mullvad.ts.net')) { 49 | continue; 50 | } 51 | 52 | $rows .= "{$lockHost}{$lockKey}"; 53 | } 54 | 55 | $output = << 57 | 58 | 59 |   60 | Name 61 | Key 62 | 63 | 64 | 65 | {$rows} 66 | 67 | 68 | EOT; 69 | 70 | $rtn = array(); 71 | $rtn['html'] = $output; 72 | echo json_encode($rtn); 73 | break; 74 | } 75 | } catch (\Throwable $e) { 76 | file_put_contents("/var/log/tailscale-error.log", print_r($e, true) . PHP_EOL, FILE_APPEND); 77 | echo "{}"; 78 | } 79 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/include/tailscale-lock/signing.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | use EDACerton\PluginUtils\Translator; 23 | 24 | if ( ! defined(__NAMESPACE__ . '\PLUGIN_ROOT') || ! defined(__NAMESPACE__ . '\PLUGIN_NAME')) { 25 | throw new \RuntimeException("Common file not loaded."); 26 | } 27 | 28 | $tr = $tr ?? new Translator(PLUGIN_ROOT); 29 | ?> 30 |

tr("tailscale_lock"); ?>

31 |

tr("lock.sign"); ?>

32 |

33 | tr("lock.signing_node"); ?> 34 |

35 |

36 | tr("lock.signing_instructions"); ?> 37 |

38 | 44 | 45 | 73 | 74 |
75 | 76 |
 

77 | 78 | 79 | Display unsigned Mullvad nodes 80 |
81 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/include/Pages/Info.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | use EDACerton\PluginUtils\Translator; 23 | 24 | if ( ! defined(__NAMESPACE__ . '\PLUGIN_ROOT') || ! defined(__NAMESPACE__ . '\PLUGIN_NAME')) { 25 | throw new \RuntimeException("Common file not loaded."); 26 | } 27 | 28 | $tr = $tr ?? new Translator(PLUGIN_ROOT); 29 | 30 | $tailscaleConfig = $tailscaleConfig ?? new Config(); 31 | 32 | if ( ! $tailscaleConfig->Enable) { 33 | echo($tr->tr("tailscale_disabled")); 34 | return; 35 | } 36 | 37 | $tailscaleInfo = $tailscaleInfo ?? new Info($tr); 38 | $tailscaleStatusInfo = $tailscaleInfo->getStatusInfo(); 39 | ?> 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | tr("tailscale_lock"); 50 | 51 | echo Utils::printRow($tr->tr("info.version"), $tailscaleStatusInfo->TsVersion); 52 | echo Utils::printRow($tr->tr("info.health"), $tailscaleStatusInfo->TsHealth); 53 | echo Utils::printRow($tr->tr("info.login"), $tailscaleStatusInfo->LoggedIn); 54 | echo Utils::printRow($tr->tr("info.netmap"), $tailscaleStatusInfo->InNetMap); 55 | echo Utils::printRow($tr->tr("info.online"), $tailscaleStatusInfo->Online); 56 | echo Utils::printRow($tr->tr("info.key_expire"), $tailscaleStatusInfo->KeyExpiration); 57 | echo Utils::printRow($tr->tr("info.tags"), $tailscaleStatusInfo->Tags); 58 | echo Utils::printRow("{$lockTranslate}: " . $tr->tr("enabled"), $tailscaleStatusInfo->LockEnabled); 59 | echo Utils::printRow($tr->tr("info.connected_via"), $tailscaleInfo->connectedViaTS() ? $tr->tr("yes") : $tr->tr("no")); 60 | 61 | if ($tailscaleStatusInfo->LockInfo != null) { 62 | echo Utils::printRow("{$lockTranslate}: " . $tr->tr("info.lock.signed"), $tailscaleStatusInfo->LockInfo->LockSigned); 63 | echo Utils::printRow("{$lockTranslate}: " . $tr->tr("info.lock.signing"), $tailscaleStatusInfo->LockInfo->LockSigning); 64 | echo Utils::printRow("{$lockTranslate}: " . $tr->tr("info.lock.node_key"), $tailscaleStatusInfo->LockInfo->NodeKey); 65 | echo Utils::printRow("{$lockTranslate}: " . $tr->tr("info.lock.public_key"), $tailscaleStatusInfo->LockInfo->PubKey); 66 | } 67 | ?> 68 | 69 |
tr('status'); ?> 
70 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/include/Pages/Dashboard.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | use EDACerton\PluginUtils\Translator; 23 | 24 | if ( ! defined(__NAMESPACE__ . '\PLUGIN_ROOT') || ! defined(__NAMESPACE__ . '\PLUGIN_NAME')) { 25 | throw new \RuntimeException("Common file not loaded."); 26 | } 27 | 28 | $tr = $tr ?? new Translator(PLUGIN_ROOT); 29 | 30 | $tailscaleConfig = $tailscaleConfig ?? new Config(); 31 | 32 | $tailscale_dashboard = "" . $tr->tr("tailscale_disabled") . ""; 33 | 34 | if ($tailscaleConfig->Enable) { 35 | $tailscaleInfo = $tailscaleInfo ?? new Info($tr); 36 | $tailscaleDashInfo = $tailscaleInfo->getDashboardInfo(); 37 | 38 | $tailscale_dashboard = Utils::printDash($tr->tr("info.online"), $tailscaleDashInfo->Online); 39 | $tailscale_dashboard .= Utils::printDash($tr->tr("info.hostname"), $tailscaleDashInfo->HostName); 40 | $tailscale_dashboard .= Utils::printDash($tr->tr("info.dns"), $tailscaleDashInfo->DNSName); 41 | $tailscale_dashboard .= Utils::printDash($tr->tr("info.ip"), implode("
 ", $tailscaleDashInfo->TailscaleIPs)); 42 | } 43 | 44 | echo << 46 | 47 | 48 |
49 |
50 | Tailscale 51 |
52 |

Tailscale

53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | 61 | 62 | 63 | {$tailscale_dashboard} 64 | 65 | EOT; 66 | 67 | $isResponsiveWebgui = version_compare(parse_ini_file('/etc/unraid-version')['version'] ?? "", '7.2', '>='); 68 | if ( ! $isResponsiveWebgui) { 69 | echo << 71 | $(function() { 72 | $('#tailscale-dashboard-title').replaceWith(function() { 73 | return $(this).text() + "
"; 74 | }); 75 | $('#tailscale-settings-button').prependTo('#tailscale-dashboard-card'); 76 | }); 77 | 78 | EOT; 79 | } 80 | -------------------------------------------------------------------------------- /.github/workflows/update-tailscale.yml: -------------------------------------------------------------------------------- 1 | name: Tailscale updater 2 | 3 | on: 4 | schedule: 5 | - cron: "0 6 * * *" 6 | workflow_dispatch: 7 | 8 | permissions: 9 | contents: write 10 | pull-requests: write 11 | 12 | jobs: 13 | update-tailscale: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v6 17 | with: 18 | ref: trunk 19 | 20 | - name: Determine versions 21 | id: compare 22 | run: | 23 | latest_tarball="$(curl -fsSL https://pkgs.tailscale.com/stable/?mode=json | jq -r '.TarballsVersion')" 24 | if [ -z "$latest_tarball" ]; then 25 | echo "Error: Failed to fetch latest Tailscale version" >&2 26 | exit 1 27 | fi 28 | current_full="$(jq -r '.tailscaleVersion' plugin/plugin.json)" 29 | current_tarball="${current_full#tailscale_}" 30 | current_tarball="${current_tarball%_amd64}" 31 | echo "latest=${latest_tarball}" >> "$GITHUB_OUTPUT" 32 | echo "current=${current_tarball}" >> "$GITHUB_OUTPUT" 33 | if [ "$latest_tarball" != "$current_tarball" ]; then 34 | echo "update=true" >> "$GITHUB_OUTPUT" 35 | else 36 | echo "update=false" >> "$GITHUB_OUTPUT" 37 | fi 38 | 39 | - name: Stop when up to date 40 | if: steps.compare.outputs.update != 'true' 41 | run: echo "Tailscale is already up to date." 42 | 43 | - name: Update plugin metadata 44 | if: steps.compare.outputs.update == 'true' 45 | id: plugin 46 | run: | 47 | new_full="tailscale_${{ steps.compare.outputs.latest }}_amd64" 48 | sha_url="https://pkgs.tailscale.com/stable/tailscale_${{ steps.compare.outputs.latest }}_amd64.tgz.sha256" 49 | new_sha="$(curl -fsSL "$sha_url" | cut -d' ' -f1)" 50 | tmp="$(mktemp)" 51 | jq --arg version "$new_full" --arg sha "$new_sha" \ 52 | '.tailscaleVersion=$version | .tailscaleSHA256=$sha' \ 53 | plugin/plugin.json > "$tmp" 54 | mv "$tmp" plugin/plugin.json 55 | echo "full_version=$new_full" >> "$GITHUB_OUTPUT" 56 | echo "sha=$new_sha" >> "$GITHUB_OUTPUT" 57 | 58 | - name: Commit and push branch 59 | if: steps.compare.outputs.update == 'true' 60 | run: | 61 | git config user.name "github-actions[bot]" 62 | git config user.email "github-actions[bot]@users.noreply.github.com" 63 | git checkout -B chore/tailscale-update 64 | git add plugin/plugin.json 65 | if git commit -m "chore: update Tailscale to ${{ steps.compare.outputs.latest }}"; then 66 | git push --force origin chore/tailscale-update 67 | echo "commit_made=true" >> $GITHUB_ENV 68 | else 69 | echo "No changes to commit." 70 | echo "commit_made=false" >> $GITHUB_ENV 71 | fi 72 | 73 | - name: Create or update PR 74 | if: steps.compare.outputs.update == 'true' && env.commit_made == 'true' 75 | env: 76 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 77 | run: | 78 | gh pr create \ 79 | --title "chore: update Tailscale to ${{ steps.compare.outputs.latest }}" \ 80 | --body "Automated update via workflow." \ 81 | --head chore/tailscale-update \ 82 | --base trunk \ 83 | --label chore \ 84 | || gh pr edit chore/tailscale-update \ 85 | --title "chore: update Tailscale to ${{ steps.compare.outputs.latest }}" \ 86 | --body "Automated update via workflow." 87 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/include/Pages/Status.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | use EDACerton\PluginUtils\Translator; 23 | 24 | if ( ! defined(__NAMESPACE__ . '\PLUGIN_ROOT') || ! defined(__NAMESPACE__ . '\PLUGIN_NAME')) { 25 | throw new \RuntimeException("Common file not loaded."); 26 | } 27 | 28 | $tr = $tr ?? new Translator(PLUGIN_ROOT); 29 | 30 | $tailscaleConfig = $tailscaleConfig ?? new Config(); 31 | 32 | if ( ! $tailscaleConfig->Enable) { 33 | echo($tr->tr("tailscale_disabled")); 34 | return; 35 | } 36 | ?> 37 | 38 | 39 | 40 | 81 | 82 |

83 | 84 | 85 | 91 | 92 | 93 |
86 | 87 | 88 | Display inactive Mullvad nodes 89 | Display inactive shared-in nodes 90 |
-------------------------------------------------------------------------------- /src/usr/local/php/unraid-tailscale-utils/unraid-tailscale-utils/Watcher.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | class Watcher 23 | { 24 | private Config $config; 25 | 26 | public function __construct() 27 | { 28 | $this->config = new Config(); 29 | } 30 | 31 | public function run(): void 32 | { 33 | $timer = 15; 34 | $need_ip = true; 35 | $allow_check_restart = false; 36 | 37 | $tsName = ''; 38 | 39 | if ( ! defined(__NAMESPACE__ . '\PLUGIN_ROOT') || ! defined(__NAMESPACE__ . '\PLUGIN_NAME')) { 40 | throw new \RuntimeException("Common file not loaded."); 41 | } 42 | $utils = new Utils(PLUGIN_NAME); 43 | 44 | $utils->logmsg("Starting tailscale-watcher"); 45 | 46 | while ( ! file_exists('/var/local/emhttp/var.ini')) { 47 | $utils->logmsg("Waiting for system to finish booting"); 48 | sleep(10); 49 | } 50 | 51 | // @phpstan-ignore while.alwaysTrue 52 | while (true) { 53 | unset($tailscale_ipv4); 54 | 55 | $interfaces = net_get_interfaces(); 56 | 57 | if (isset($interfaces["tailscale1"]["unicast"])) { 58 | foreach ($interfaces["tailscale1"]["unicast"] as $interface) { 59 | if (isset($interface["address"])) { 60 | if ($interface["family"] == 2) { 61 | $tailscale_ipv4 = $interface["address"]; 62 | $timer = 60; 63 | } 64 | } 65 | } 66 | } 67 | 68 | if (isset($tailscale_ipv4)) { 69 | if ($need_ip) { 70 | $utils->logmsg("Tailscale IP detected, applying configuration"); 71 | $need_ip = false; 72 | 73 | $localAPI = new LocalAPI(); 74 | $status = $localAPI->getStatus(); 75 | $tsName = $status->Self->DNSName; 76 | 77 | $utils->run_task('Tailscale\System::applyTailscaleConfig', array($this->config)); 78 | $utils->run_task('Tailscale\System::applyGRO'); 79 | $utils->run_task('Tailscale\System::restartSystemServices', array($this->config)); 80 | if ($this->config->AddPeersToHosts) { 81 | $utils->run_task('Tailscale\System::addToHostFile', array($status)); 82 | } 83 | } 84 | 85 | $allow_check_restart = $utils->run_task('Tailscale\System::checkWebgui', array($this->config, $tailscale_ipv4, $allow_check_restart)); 86 | $utils->run_task('Tailscale\System::checkServeConfig'); 87 | $utils->run_task('Tailscale\System::fixLocalSubnetRoutes'); 88 | 89 | // Watch for changes to the DNS name (e.g., if someone changes the tailnet name or the Tailscale name of the server via the admin console) 90 | // If a change happens, refresh the Tailscale WebGUI certificate 91 | $localAPI = new LocalAPI(); 92 | $status = $localAPI->getStatus(); 93 | $newTsName = $status->Self->DNSName; 94 | 95 | if ($newTsName != $tsName) { 96 | $utils->logmsg("Detected DNS name change"); 97 | $tsName = $newTsName; 98 | 99 | $utils->run_task('Tailscale\System::refreshWebGuiCert'); 100 | } 101 | } else { 102 | $utils->logmsg("Waiting for Tailscale IP"); 103 | } 104 | 105 | sleep($timer); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/usr/local/php/unraid-tailscale-utils/unraid-tailscale-utils/LocalAPI.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | enum APIMethods 23 | { 24 | case GET; 25 | case POST; 26 | case PATCH; 27 | } 28 | 29 | class LocalAPI 30 | { 31 | private const tailscaleSocket = '/var/run/tailscale/tailscaled.sock'; 32 | private Utils $utils; 33 | 34 | public function __construct() 35 | { 36 | if ( ! defined(__NAMESPACE__ . "\PLUGIN_ROOT") || ! defined(__NAMESPACE__ . "\PLUGIN_NAME")) { 37 | throw new \RuntimeException("Common file not loaded."); 38 | } 39 | $this->utils = new Utils(PLUGIN_NAME); 40 | } 41 | 42 | private function tailscaleLocalAPI(string $url, APIMethods $method = APIMethods::GET, object $body = new \stdClass()): string 43 | { 44 | if (empty($url)) { 45 | throw new \InvalidArgumentException("URL cannot be empty"); 46 | } 47 | 48 | $body_encoded = json_encode($body, JSON_UNESCAPED_SLASHES); 49 | 50 | if ( ! $body_encoded) { 51 | throw new \InvalidArgumentException("Failed to encode JSON"); 52 | } 53 | 54 | $ch = curl_init(); 55 | 56 | $headers = []; 57 | 58 | curl_setopt($ch, CURLOPT_TIMEOUT, 5); 59 | curl_setopt($ch, CURLOPT_UNIX_SOCKET_PATH, $this::tailscaleSocket); 60 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 61 | curl_setopt($ch, CURLOPT_URL, "http://local-tailscaled.sock/localapi/{$url}"); 62 | 63 | if ($method == APIMethods::POST) { 64 | curl_setopt($ch, CURLOPT_POST, true); 65 | curl_setopt($ch, CURLOPT_POSTFIELDS, $body_encoded); 66 | $this->utils->logmsg("Tailscale Local API: {$url} POST " . $body_encoded); 67 | $headers[] = "Content-Type: application/json"; 68 | } 69 | 70 | if ($method == APIMethods::PATCH) { 71 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PATCH'); 72 | curl_setopt($ch, CURLOPT_POSTFIELDS, $body_encoded); 73 | $this->utils->logmsg("Tailscale Local API: {$url} PATCH " . $body_encoded); 74 | $headers[] = "Content-Type: application/json"; 75 | } 76 | 77 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 78 | 79 | $out = curl_exec($ch) ?: false; 80 | curl_close($ch); 81 | return strval($out); 82 | } 83 | 84 | public function getStatus(): \stdClass 85 | { 86 | return (object) json_decode($this->tailscaleLocalAPI('v0/status')); 87 | } 88 | 89 | public function getPrefs(): \stdClass 90 | { 91 | return (object) json_decode($this->tailscaleLocalAPI('v0/prefs')); 92 | } 93 | 94 | public function getTkaStatus(): \stdClass 95 | { 96 | return (object) json_decode($this->tailscaleLocalAPI('v0/tka/status')); 97 | } 98 | 99 | public function getServeConfig(): \stdClass 100 | { 101 | return (object) json_decode($this->tailscaleLocalAPI('v0/serve-config')); 102 | } 103 | 104 | public function getPacketFilterRules(): \stdClass 105 | { 106 | return (object) json_decode($this->tailscaleLocalAPI('v0/debug-packet-filter-rules')); 107 | } 108 | 109 | public function resetServeConfig(): void 110 | { 111 | $this->tailscaleLocalAPI("v0/serve-config", APIMethods::POST, new \stdClass()); 112 | } 113 | 114 | public function setServeConfig(ServeConfig $serveConfig): void 115 | { 116 | $this->tailscaleLocalAPI("v0/serve-config", APIMethods::POST, $serveConfig->getConfig()); 117 | } 118 | 119 | public function postLoginInteractive(): void 120 | { 121 | $this->tailscaleLocalAPI('v0/login-interactive', APIMethods::POST); 122 | } 123 | 124 | public function patchPref(string $key, mixed $value): void 125 | { 126 | $body = []; 127 | $body[$key] = $value; 128 | $body["{$key}Set"] = true; 129 | 130 | $this->tailscaleLocalAPI('v0/prefs', APIMethods::PATCH, (object) $body); 131 | } 132 | 133 | public function postTkaSign(string $key): void 134 | { 135 | $body = ["NodeKey" => $key]; 136 | $this->tailscaleLocalAPI("v0/tka/sign", APIMethods::POST, (object) $body); 137 | } 138 | 139 | public function expireKey(): void 140 | { 141 | $this->tailscaleLocalAPI('v0/set-expiry-sooner?expiry=0', APIMethods::POST); 142 | } 143 | 144 | public function setAutoUpdate(bool $enabled): void 145 | { 146 | $body = []; 147 | $body["AutoUpdate"] = ["Apply" => $enabled, "Check" => $enabled]; 148 | $body["AutoUpdateSet"] = ["ApplySet" => true, "CheckSet" => true]; 149 | 150 | $this->tailscaleLocalAPI("v0/prefs", APIMethods::PATCH, (object) $body); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/include/data/Status.php: -------------------------------------------------------------------------------- 1 | . 20 | */ 21 | 22 | use EDACerton\PluginUtils\Translator; 23 | 24 | try { 25 | require_once dirname(dirname(__FILE__)) . "/common.php"; 26 | 27 | if ( ! defined(__NAMESPACE__ . '\PLUGIN_ROOT') || ! defined(__NAMESPACE__ . '\PLUGIN_NAME')) { 28 | throw new \RuntimeException("Common file not loaded."); 29 | } 30 | 31 | $tr = $tr ?? new Translator(PLUGIN_ROOT); 32 | $utils = $utils ?? new Utils(PLUGIN_NAME); 33 | 34 | $tailscaleConfig = $tailscaleConfig ?? new Config(); 35 | 36 | if ( ! $tailscaleConfig->Enable) { 37 | echo("{}"); 38 | return; 39 | } 40 | 41 | switch ($_POST['action']) { 42 | case 'get': 43 | $tailscaleInfo = $tailscaleInfo ?? new Info($tr); 44 | $rows = ""; 45 | 46 | $mullvad = filter_var($_POST['mullvad'] ?? false, FILTER_VALIDATE_BOOLEAN); 47 | $shared = filter_var($_POST['shared'] ?? false, FILTER_VALIDATE_BOOLEAN); 48 | 49 | foreach ($tailscaleInfo->getPeerStatus() as $peer) { 50 | if ($peer->Mullvad && ! $mullvad && ! $peer->Active) { 51 | continue; 52 | } 53 | if ($peer->SharedUser && ! $shared && ! $peer->Active) { 54 | continue; 55 | } 56 | 57 | $user = $peer->SharedUser ? $tr->tr('status_page.shared') : $peer->Name; 58 | $online = $peer->Online ? ($peer->Active ? $tr->tr('status_page.active') : $tr->tr('status_page.idle')) : $tr->tr('status_page.offline'); 59 | $exitNode = $peer->ExitNodeActive ? $tr->tr('status_page.exit_active') : ($peer->ExitNodeAvailable ? ($peer->Mullvad ? "Mullvad" : $tr->tr('status_page.exit_available')) : ""); 60 | $connection = $peer->Active ? ($peer->Relayed ? $tr->tr('status_page.relay') : $tr->tr('status_page.direct')) : ""; 61 | $active = $peer->Active ? $peer->Address : ""; 62 | $txBytes = $peer->Traffic ? $peer->TxBytes : ""; 63 | $rxBytes = $peer->Traffic ? $peer->RxBytes : ""; 64 | $pingHost = ($peer->SharedUser || $peer->Active || ! $peer->Online || $peer->Mullvad) ? "" : ""; 65 | $ips = implode("
", $peer->IP); 66 | 67 | $rows .= << 69 | {$user} 70 | {$ips} 71 | {$peer->LoginName} 72 | {$online} 73 | {$exitNode} 74 | {$connection} 75 | {$active} 76 | {$txBytes} 77 | {$rxBytes} 78 | {$pingHost} 79 | 80 | EOT; 81 | } 82 | 83 | $output = << 85 | 86 | 87 | {$tr->tr('info.dns')} 88 | {$tr->tr('info.ip')} 89 | {$tr->tr('status_page.login_name')} 90 | {$tr->tr('status')} 91 | {$tr->tr('status_page.exit_node')} 92 | {$tr->tr('status_page.connection_type')} 93 | {$tr->tr('status_page.connection_addr')} 94 | {$tr->tr('status_page.tx_bytes')} 95 | {$tr->tr('status_page.rx_bytes')} 96 | {$tr->tr('status_page.action')} 97 | 98 | 99 | 100 | {$rows} 101 | 102 | 103 | EOT; 104 | 105 | $rtn = array(); 106 | $rtn['html'] = $output; 107 | echo json_encode($rtn); 108 | break; 109 | case 'ping': 110 | $tailscaleInfo = $tailscaleInfo ?? new Info($tr); 111 | $out = "Could not find host."; 112 | 113 | foreach ($tailscaleInfo->getPeerStatus() as $peer) { 114 | if ($peer->Name == $_POST['host']) { 115 | $peerIP = escapeshellarg($peer->IP[0]); 116 | $out = implode("
", $utils->run_command("tailscale ping {$peerIP}")); 117 | break; 118 | } 119 | } 120 | 121 | echo $out; 122 | break; 123 | } 124 | } catch (\Throwable $e) { 125 | file_put_contents("/var/log/tailscale-error.log", print_r($e, true) . PHP_EOL, FILE_APPEND); 126 | echo "{}"; 127 | } 128 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/locales/zh_CN.json: -------------------------------------------------------------------------------- 1 | { 2 | "yes": "是", 3 | "no": "否", 4 | "ignore": "忽略", 5 | "erase": "清除", 6 | "confirm": "确认", 7 | "download": "下载", 8 | "restart": "重新启动", 9 | "apply": "应用", 10 | "back": "返回", 11 | "status": "状态", 12 | "connection": "连接", 13 | "unknown": "未知的", 14 | "none": "无", 15 | "disabled": "已禁用", 16 | "enabled": "已启用", 17 | "disable": "禁用", 18 | "enable": "启用", 19 | "cancel": "取消", 20 | "accept": "接受", 21 | "sign": "登录", 22 | "login": "登录", 23 | "add": "添加", 24 | "remove": "移除", 25 | "tailnet": "Tailnet", 26 | "configuration": "配置", 27 | "needs_login": "此设备需要登录 Tailscale。登录后请刷新此页面以查看状态。", 28 | "tailscale_disabled": "Tailscale 当前已禁用。可以通过“设置选项卡”启用。", 29 | "tailscale_lock": "Tailscale 锁", 30 | "warning": "警告", 31 | "save": "保存", 32 | "settings": { 33 | "basic": "基本视图", 34 | "advanced": "高级视图", 35 | "system_settings": "系统设置", 36 | "enable_tailscale": "启用 Tailscale", 37 | "unraid_listen": "Unraid 服务监听 Tailscale IP", 38 | "ip_forward": "启用 IP 转发", 39 | "taildrop": "Taildrop 位置", 40 | "services": "Tailscale 服务", 41 | "wireguard": "Wireguard 端口", 42 | "outbound_network": "高级网络选项", 43 | "subnets": "允许 Tailscale 子网", 44 | "dns": "允许 Tailscale DNS 设置", 45 | "save": "保存设置", 46 | "restart": "重启 Tailscale", 47 | "erase": "清除 Tailscale 配置", 48 | "diagnostics": "插件诊断", 49 | "reauthenticate": "重新认证", 50 | "funnel": "允许 Tailscale Funnel", 51 | "hosts": "将对等端添加到 /etc/hosts 文件中。", 52 | "no_logs_no_support": "无日志 无支持", 53 | "tpm": "允许 TPM 加密节点密钥", 54 | "context": { 55 | "tpm": "启用受信任平台模块(TPM)以安全存储 Tailscale 节点密钥。这提高了安全性,防止节点密钥被轻易提取,确保只有授权的硬件可以访问。启用此选项需要 TPM 2.0。如果系统没有兼容的 TPM,则此选项无效。", 56 | "unraid_listen": "将Unraid服务(如SSH、WebGUI、SMB等)配置为Tailscale监听地址", 57 | "ip_forward": "在 sysctl 中将 net.ipv4.ip_forward 和 net.ipv6.conf.all.forwarding 设置为 1。启用后,此更改会立即发生。", 58 | "taildrop": "指定传入 Taildrop 文件的路径。", 59 | "dns": "允许通过 CLI 或 WebGUI 启用 Tailscale DNS。如果禁用,当 Tailscale 启动时,Tailscale DNS 也将被禁用。", 60 | "subnets": "允许通过 CLI 或 WebGUI 启用 Tailscale 路由。如果禁用,当 Tailscale 启动时,Tailscale 路由也将被禁用。", 61 | "wireguard": "更改用于 Wireguard 连接的端口。这项通常不需要更改。", 62 | "erase": "注销 Tailscale 并重置所有设置为默认值", 63 | "restart": "重新启动 Tailscale 守护程序并重新应用设置。", 64 | "diagnostics": "下载诊断记录(这可能需要一些时间才能完成)", 65 | "save": "应用更改时,Tailscale 将重新启动", 66 | "reauthenticate": "强制进行 Tailscale 重新认证。", 67 | "funnel": "允许通过 WebGUI 启用 Tailscale Funnel。如果禁用,Tailscale Funnel 将被禁用。", 68 | "hosts": "将 Tailscale 对等端添加到 /etc/hosts 用于名称解析。如果您希望在不启用服务器上的 Tailscale DNS 的情况下使用 Tailnet DNS 名称,这将非常有用。", 69 | "no_logs_no_support": "将禁用 Tailscale 的遥测功能,并使您无法获得需要此类遥测用于调试的 Tailscale 支持。" 70 | } 71 | }, 72 | "info": { 73 | "online": "在线", 74 | "version": "Tailscale 版本", 75 | "health": "Tailscale 健康状态", 76 | "login": "已登录", 77 | "netmap": "在网络图中", 78 | "key_expire": "密钥过期", 79 | "tags": "标签", 80 | "hostname": "主机名", 81 | "dns": "DNS 名称", 82 | "ip": "Tailscale IP 地址", 83 | "magicdns": "MagicDNS 后缀", 84 | "routes": "广告路由", 85 | "accept_routes": "接受路由", 86 | "accept_dns": "接受 DNS", 87 | "run_ssh": "Tailscale SSH", 88 | "advertise_exit_node": "作为出口节点运行", 89 | "use_exit_node": "使用出口节点", 90 | "exit_node_local": "使用出口节点时允许 LAN 访问", 91 | "unapproved": "需要在管理控制台批准", 92 | "connected_via": "通过 Tailscale 连接", 93 | "funnel_port": "WebGUI 的 Funnel 端口", 94 | "port_in_use": "端口正在使用", 95 | "peer_relay": "对等中继端口", 96 | "auto_update": "自动更新", 97 | "lock": { 98 | "node_key": "节点密钥", 99 | "public_key": "公开密钥", 100 | "signed": "节点密钥签名", 101 | "signing": "正在签署节点" 102 | } 103 | }, 104 | "warnings": { 105 | "key_expiration": "Tailscale 密钥将在 %s 天内在 %s 过期。", 106 | "netbios": "NetBIOS 在 SMB 设置中启用 - 这可以阻止通过 Tailscale 访问共享内容。", 107 | "lock": "尾网(tailnet)已启用锁定,但该节点尚未签名。 它将无法与尾网通信。", 108 | "funnel": "为 Unraid WebGUI 启用 Tailscale Funnel 会使您的服务器暴露在 Internet 上,极大增加未经授权访问和潜在攻击的风险。只有在您充分理解安全影响的情况下才应启用此功能。建议和安全的远程访问方式是,在您计划用于访问 WebGUI 的设备上安装 Tailscale,而不是启用 Funnel。", 109 | "subnet": "在您的 Unraid 服务器上接受 Tailscale 子网会在某些网络配置下破坏本地网络连接。作为子网路由器或出口节点,您的 Unraid 服务器并不需要接受路由。只有当您的 Unraid 服务器需要连接其他设备所发布的远程子网时,才应启用该选项。", 110 | "dns": "在服务器上启用 Tailscale MagicDNS 可能会干扰 Docker 容器中的名称解析,可能导致应用程序连通性问题。您无需在服务器上启用 MagicDNS,也能从其他设备使用 MagicDNS 名称(如 'unraid.tailnet.ts.net')访问您的 Unraid 服务器。启用“将对等端添加到 /etc/hosts”是一种更安全的替代方案,可以让服务器上使用 Tailscale 名称。", 111 | "caution": "请谨慎操作,并确保在继续前已了解此更改的影响。", 112 | "more_info": "详细信息:", 113 | "peer_relay_no_acl": "未在 Tailnet 策略(访问控制)中配置。", 114 | "tpm": "启用 TPM 会将 Tailscale 节点密钥锁定到此设备的特定硬件。如果之后禁用 TPM,Tailscale 节点密钥将失效,设备需要重新通过 Tailscale 进行身份验证。TPM 也可能会发生锁定,从而中断 Tailscale 连接,并要求重新进行身份验证。" 115 | }, 116 | "lock": { 117 | "sign": "为节点签名", 118 | "signing_node": "这是尾网的签名节点。", 119 | "signing_instructions": "以下节点当前被锁定在尾网之外。 选中您要添加的任何节点的复选框,然后点击“签名”按钮,将该节点添加到尾网。", 120 | "signed_node": "您的尾网已启用锁定,且当前节点已签名。 该节点可与尾网通信。", 121 | "make_signing": "如您希望将其设为签名节点,则需信任以下来自签名节点的密钥:", 122 | "unsigned": "您的尾网已启用锁定,且当前节点未签名。 该节点无法与尾网通信。", 123 | "unsigned_instructions": "要允许该节点通信,您需要信任以下来自签名节点的密钥", 124 | "disabled": "您的 tailnet 未启用锁定。" 125 | }, 126 | "status_page": { 127 | "exit_node": "出口节点", 128 | "connection_type": "连接类型", 129 | "connection_addr": "连接", 130 | "tx_bytes": "发送字节 (Tx Bytes)", 131 | "rx_bytes": "接收字节 (Rx Bytes)", 132 | "relay": "中继", 133 | "direct": "直连", 134 | "exit_active": "已激活", 135 | "exit_available": "可用", 136 | "idle": "空闲", 137 | "offline": "离线", 138 | "active": "活动", 139 | "login_name": "登录名", 140 | "shared": "共享用户", 141 | "action": "操作" 142 | } 143 | } -------------------------------------------------------------------------------- /src/usr/local/php/unraid-tailscale-utils/unraid-tailscale-utils/Utils.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | use PhpIP\IPBlock; 23 | 24 | class Utils extends \EDACerton\PluginUtils\Utils 25 | { 26 | public function setPHPDebug(): void 27 | { 28 | $debug = file_exists("/boot/config/plugins/tailscale/debug"); 29 | 30 | if ($debug && ! defined("PLUGIN_DEBUG")) { 31 | error_reporting(E_ALL); 32 | define("PLUGIN_DEBUG", true); 33 | } 34 | } 35 | 36 | public static function printRow(string $title, string $value): string 37 | { 38 | return "{$title}{$value}" . PHP_EOL; 39 | } 40 | 41 | public static function printDash(string $title, string $value): string 42 | { 43 | return "{$title}{$value}" . PHP_EOL; 44 | } 45 | 46 | public static function formatWarning(?Warning $warning): string 47 | { 48 | if ($warning == null) { 49 | return ""; 50 | } 51 | 52 | return "" . $warning->Message . ""; 53 | } 54 | 55 | public static function ip4_in_network(string $ip, string $network): bool 56 | { 57 | if (strpos($network, '/') === false) { 58 | return false; 59 | } 60 | 61 | list($subnet, $mask) = explode('/', $network, 2); 62 | $ip_bin_string = sprintf("%032b", ip2long($ip)); 63 | $net_bin_string = sprintf("%032b", ip2long($subnet)); 64 | 65 | return (substr_compare($ip_bin_string, $net_bin_string, 0, intval($mask)) === 0); 66 | } 67 | 68 | public static function logwrap(string $message, bool $debug = false, bool $rateLimit = false): void 69 | { 70 | if ( ! defined(__NAMESPACE__ . "\PLUGIN_NAME")) { 71 | throw new \RuntimeException("PLUGIN_NAME is not defined."); 72 | } 73 | $utils = new Utils(PLUGIN_NAME); 74 | $utils->logmsg($message, $debug, $rateLimit); 75 | } 76 | 77 | /** 78 | * @return array 79 | */ 80 | public static function runwrap(string $command, bool $alwaysShow = false, bool $show = true): array 81 | { 82 | if ( ! defined(__NAMESPACE__ . "\PLUGIN_NAME")) { 83 | throw new \RuntimeException("PLUGIN_NAME is not defined."); 84 | } 85 | $utils = new Utils(PLUGIN_NAME); 86 | return $utils->run_command($command, $alwaysShow, $show); 87 | } 88 | 89 | public static function validateCidr(string $cidr): bool 90 | { 91 | try { 92 | $block = IPBlock::create($cidr); 93 | 94 | // Check that the IP address is the network address (host bits are zero) 95 | return $block->getNetworkAddress()->humanReadable() . '/' . $block->getPrefixLength() === $cidr; 96 | } catch (\Exception $e) { 97 | return false; 98 | } 99 | } 100 | 101 | /** 102 | * @return array 103 | */ 104 | public static function getExitRoutes(): array 105 | { 106 | return ["0.0.0.0/0", "::/0"]; 107 | } 108 | 109 | public static function isFunnelAllowed(): bool 110 | { 111 | $directives = ["allow 127.0.0.1;", "allow ::1;"]; 112 | 113 | $nginxConfig = file_get_contents('/etc/nginx/nginx.conf'); 114 | if ($nginxConfig === false) { 115 | return false; // Unable to read the nginx configuration file 116 | } 117 | 118 | // Search $nginxConfig for the allow directives. 119 | foreach ($directives as $directive) { 120 | if (strpos($nginxConfig, $directive) !== false) { 121 | return false; // Directive found, funnel not safe to use 122 | } 123 | } 124 | 125 | return true; 126 | } 127 | 128 | /** 129 | * Get a list of ports that are currently assigned to services. 130 | * This is a best-effort approach, especially since docker might not be running during configuration. 131 | * 132 | * @return array 133 | */ 134 | public function get_assigned_ports(): array 135 | { 136 | $ports = array(); 137 | $identCfg = parse_ini_file("/boot/config/ident.cfg", false, INI_SCANNER_RAW) ?: array(); 138 | if (isset($identCfg['PORT'])) { 139 | $ports[] = intval($identCfg['PORT']); 140 | } 141 | if (isset($identCfg['PORTSSL']) && isset($identCfg['USE_SSL']) && $identCfg['USE_SSL'] === 'yes') { 142 | $ports[] = intval($identCfg['PORTSSL']); 143 | } 144 | if (isset($identCfg['PORTTELNET']) && isset($identCfg['USE_TELNET']) && $identCfg['USE_TELNET'] === 'yes') { 145 | $ports[] = intval($identCfg['PORTTELNET']); 146 | } 147 | if (isset($identCfg['PORTSSH']) && isset($identCfg['USE_SSH']) && $identCfg['USE_SSH'] === 'yes') { 148 | $ports[] = intval($identCfg['PORTSSH']); 149 | } 150 | 151 | // Get any open TCP ports from the system 152 | $netstatOutput = shell_exec("netstat -tuln | grep LISTEN"); 153 | if ($netstatOutput) { 154 | $lines = explode("\n", trim($netstatOutput)); 155 | foreach ($lines as $line) { 156 | if (preg_match('/:(\d+)\s+/', $line, $matches)) { 157 | $port = intval($matches[1]); 158 | if ($port > 0 && $port < 65536) { 159 | $ports[] = $port; 160 | } 161 | } 162 | } 163 | } 164 | 165 | return array_unique($ports); 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /plugin/tailscale.plg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 17 | 45 | 46 | 47 | 48 | 49 | 76 | 77 | 78 | 79 | 80 | https://pkgs.tailscale.com/stable/tailscale_1.92.1_amd64.tgz 81 | d1750da42d983b9875fe71c29bf937c59ace3ab00e87c24ca0ae614a09508b11 82 | 83 | 84 | 85 | https://github.com/unraid/unraid-tailscale/releases/download/2025.12.11.0321/unraid-tailscale-utils-2025.12.11.0321-noarch-1.txz 86 | fcfed3a080cf4b20148d92b4a4b212fef0befcae0f9f7c5bc3e39b7b2191d68f 87 | 88 | 89 | 92 | 93 | 94 | /boot/config/plugins/tailscale/.gitignore 110 | 111 | ln -s /usr/local/emhttp/plugins/tailscale/bin/tailscale /usr/local/sbin/tailscale 112 | ln -s /usr/local/emhttp/plugins/tailscale/bin/tailscaled /usr/local/sbin/tailscaled 113 | 114 | # remove other branches (e.g., if switching from main to preview) 115 | rm -f /boot/config/plugins/tailscale-preview.plg 116 | rm -f /var/log/plugins/tailscale-preview.plg 117 | rm -f /boot/config/plugins/tailscale-trunk.plg 118 | rm -f /var/log/plugins/tailscale-trunk.plg 119 | 120 | 121 | 122 | 123 | # start tailscaled 124 | /usr/local/emhttp/plugins/tailscale/restart.sh 125 | 126 | # Bash completion 127 | tailscale completion bash > /etc/bash_completion.d/tailscale 128 | 129 | # cleanup old versions 130 | rm -f $(ls /boot/config/plugins/tailscale/unraid-tailscale-utils-*.txz 2>/dev/null | grep -v '2025.12.11.0321') 131 | rm -f $(ls /boot/config/plugins/tailscale/*.tgz 2>/dev/null | grep -v 'tailscale_1.92.1_amd64') 132 | 133 | # check to see if the state file has been backed up to Unraid Connect 134 | if [ -d "/boot/.git" ]; then 135 | if git --git-dir /boot/.git log --all --name-only --diff-filter=A -- config/plugins/tailscale/state/tailscaled.state | grep -q . ; then 136 | echo "******************************" 137 | echo "* WARNING *" 138 | echo "******************************" 139 | echo " " 140 | echo "The Tailscale state file has been backed up to Unraid Connect via Flash backup." 141 | echo " " 142 | echo "To remove this backup, please perform the following steps:" 143 | echo "1. Go to Settings -> Management Access". 144 | echo "2. Under Unraid Connect, deactivate flash backup. Select the option to also delete cloud backup." 145 | echo "3. Reactivate flash backup." 146 | 147 | /usr/local/emhttp/webGui/scripts/notify -l '/Settings/ManagementAccess' -i 'alert' -e 'Tailscale State' -s 'Tailscale state backed up to Unraid connect.' -d 'The Tailscale state file has been backed up to Unraid connect. This is a potential security risk. From the Management Settings page, deactivate flash backup and delete cloud backups, then reactivate flash backup.' 148 | fi 149 | fi 150 | 151 | echo "" 152 | echo "----------------------------------------------------" 153 | echo " tailscale has been installed." 154 | echo " Version: 2025.12.11.0321" 155 | echo "----------------------------------------------------" 156 | echo "" 157 | ]]> 158 | 159 | 160 | 161 | 164 | 165 | 166 | /dev/null 169 | 170 | rm /usr/local/sbin/tailscale 171 | rm /usr/local/sbin/tailscaled 172 | 173 | removepkg unraid-tailscale-utils 174 | 175 | rm -rf /usr/local/emhttp/plugins/tailscale 176 | rm -f /boot/config/plugins/tailscale/*.tgz 177 | rm -f /boot/config/plugins/tailscale/*.txz 178 | ]]> 179 | 180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/locales/ja_JP.json: -------------------------------------------------------------------------------- 1 | { 2 | "yes": "はい", 3 | "no": "いいえ", 4 | "ignore": "無視", 5 | "erase": "消去", 6 | "confirm": "確認", 7 | "download": "ダウンロード", 8 | "restart": "再起動", 9 | "apply": "適用", 10 | "back": "戻る", 11 | "status": "ステータス", 12 | "connection": "接続", 13 | "unknown": "不明", 14 | "none": "なし", 15 | "disabled": "無効", 16 | "enabled": "有効", 17 | "disable": "無効にする", 18 | "enable": "有効にする", 19 | "cancel": "キャンセル", 20 | "accept": "承認", 21 | "sign": "署名", 22 | "login": "ログイン", 23 | "add": "追加", 24 | "remove": "削除", 25 | "tailnet": "tailnet", 26 | "configuration": "構成", 27 | "needs_login": "このデバイスはTailscaleへのログインが必要です。ログイン完了後、このページをリロードしてステータスを確認してください。", 28 | "tailscale_disabled": "Tailscaleは現在無効です。設定タブから有効化できます。", 29 | "tailscale_lock": "Tailscaleロック", 30 | "warning": "警告", 31 | "save": "保存する", 32 | "settings": { 33 | "basic": "基本表示", 34 | "advanced": "詳細表示", 35 | "system_settings": "システム設定", 36 | "enable_tailscale": "Tailscaleを有効にする", 37 | "unraid_listen": "UnraidサービスがTailscale IPでリッスンする", 38 | "ip_forward": "IPフォワーディングを有効にする", 39 | "taildrop": "Taildropの保存先", 40 | "services": "Tailscaleサービス", 41 | "wireguard": "Wireguardポート", 42 | "outbound_network": "高度なネットワークオプション", 43 | "subnets": "Tailscaleサブネット許可", 44 | "dns": "Tailscale DNS設定を許可", 45 | "save": "設定を保存", 46 | "restart": "Tailscaleを再起動", 47 | "erase": "Tailscale構成を消去", 48 | "diagnostics": "プラグイン診断情報", 49 | "reauthenticate": "再認証", 50 | "funnel": "Tailscale Funnel を許可", 51 | "hosts": "/etc/hosts にピアを追加する (Add Peers)", 52 | "no_logs_no_support": "ログを無効にすると、サポートは受けられません", 53 | "tpm": "TPM を使用してノードキーを暗号化する", 54 | "context": { 55 | "tpm": "TPM(Trusted Platform Module)を使用して Tailscale ノードキーを安全に保存できるようにします。これにより、ノードキーが容易に抽出されるのを防ぎ、認証されたハードウェアのみがアクセス可能になるため、セキュリティが強化されます。このオプションを有効にするには、TPM 2.0 が必要です。システムに互換性のある TPM が存在しない場合、この設定は影響しません。", 56 | "unraid_listen": "Unraidサービス(SSH、WebGUI、SMBなど)がTailscaleアドレスでリッスンするように設定します。", 57 | "ip_forward": "net.ipv4.ip_forwardおよびnet.ipv6.conf.all.forwardingをsysctlで1に設定します。この変更は有効化時にすぐに適用されます。", 58 | "taildrop": "Taildropから受信するファイルのパスを指定します。", 59 | "dns": "CLIまたはWebGUIからTailscale DNSの有効化が可能です。無効の場合、Tailscale起動時にTailscale DNSが無効になります。", 60 | "subnets": "CLIまたはWebGUIからTailscaleルートの有効化が可能です。無効の場合、Tailscale起動時にTailscaleルートが無効になります。", 61 | "wireguard": "Wireguard接続で使用するポートを変更します。通常この設定を変更する必要はありません。", 62 | "erase": "Tailscaleからログアウトし、すべての設定をデフォルトにリセットします", 63 | "restart": "Tailscaleデーモンを再起動し、設定を再適用します。", 64 | "diagnostics": "診断情報をダウンロードします(完了までに時間がかかる場合があります)", 65 | "save": "設定を適用するとTailscaleが再起動します", 66 | "reauthenticate": "Tailscale の再認証を強制します。", 67 | "funnel": "WebGUI から Tailscale Funnel を有効化できます。無効にすると、Tailscale Funnel は無効になります。", 68 | "hosts": "Tailscale のピアを名前解決のために /etc/hosts に追加します。これは、サーバーで Tailscale DNS を有効にすると発生する可能性のある複雑さを避けつつ、Tailnet の DNS 名を使用したい場合に便利です。", 69 | "no_logs_no_support": "Tailscale のテレメトリを無効にし、問題のデバッグにテレメトリが必要となる Tailscale からのサポートを受けることを拒否します。" 70 | } 71 | }, 72 | "info": { 73 | "online": "オンライン", 74 | "version": "Tailscaleバージョン", 75 | "health": "Tailscaleヘルス", 76 | "login": "ログイン済み", 77 | "netmap": "ネットワークマップ内", 78 | "key_expire": "キー有効期限", 79 | "tags": "タグ", 80 | "hostname": "ホスト名", 81 | "dns": "DNS名", 82 | "ip": "Tailscale IPアドレス", 83 | "magicdns": "MagicDNSサフィックス", 84 | "routes": "広告されたルート", 85 | "accept_routes": "ルートを受け入れる", 86 | "accept_dns": "DNSを受け入れる", 87 | "run_ssh": "Tailscale SSH", 88 | "advertise_exit_node": "エグジットノードとして動作", 89 | "use_exit_node": "エグジットノードを使用", 90 | "exit_node_local": "エグジットノード使用中にLANアクセスを許可", 91 | "unapproved": "管理コンソールでの承認が必要です", 92 | "connected_via": "Tailscale経由で接続済み", 93 | "funnel_port": "WebGUI 用 Funnel ポート", 94 | "port_in_use": "使用中のポート", 95 | "peer_relay": "ピアリレイポート", 96 | "auto_update": "自動更新", 97 | "lock": { 98 | "node_key": "ノードキー", 99 | "public_key": "公開鍵", 100 | "signed": "ノードキー署名済み", 101 | "signing": "署名ノードである" 102 | } 103 | }, 104 | "warnings": { 105 | "key_expiration": "Tailscaleキーは%s日後(%s)に期限切れとなります。", 106 | "netbios": "SMB設定でNetBIOSが有効になっています - これによりTailscale経由で共有へアクセスできなくなる場合があります。", 107 | "lock": "tailnetでロックが有効ですが、このノードは署名されていません。tailnetと通信できません。", 108 | "funnel": "Unraid WebGUI で Tailscale Funnel を有効にすると、サーバーがインターネットに公開され、認可されていないアクセスや攻撃のリスクが大幅に増加します。この機能は、セキュリティへの影響を十分に理解している場合のみ有効にしてください。リモートアクセスの推奨/安全な方法は、Funnel を有効にせず、WebGUI にアクセスする予定の端末すべてに Tailscale をインストールすることです。", 109 | "subnet": "Unraid サーバーで Tailscale サブネットの許可を有効にすると、特定のネットワーク構成においてローカルネットワーク接続が障害される可能性があります。Unraid サーバーをサブネットルーターや出口ノードとして機能させるためにルートの許可は必要ありません。他の端末から通知されたリモートサブネットに Unraid サーバーが接続する必要がある場合のみ、このオプションを有効にしてください。", 110 | "dns": "サーバー上で Tailscale MagicDNS を有効にすると、Docker コンテナ内で名前解決が妨げられ、アプリケーションの接続に問題が発生する可能性があります。他の端末から MagicDNS 名(例: \"unraid.tailnet.ts.net\")を使って Unraid サーバーへアクセスする場合、サーバー上で MagicDNS を有効にする必要はありません。「/etc/hosts にピアを追加する (Add Peers)」を有効にする方が安全な選択肢であり、サーバー上で Tailscale 名を使用できます。", 111 | "caution": "十分に注意して進め、この変更の影響を理解したうえで続行してください。", 112 | "more_info": "詳細はこちら:", 113 | "peer_relay_no_acl": "Tailnetポリシー(アクセス制御)で設定されていません。", 114 | "tpm": "TPM を有効にすると、Tailscale ノードキーがこのデバイスの特定のハードウェアに固定されます。後で TPM を無効にすると、Tailscale ノードキーは無効になり、再度 Tailscale に対して認証する必要があります。また、TPM がロックアウトされることがあり、これにより Tailscale の接続が中断され、再認証が必要になる可能性があります。" 115 | }, 116 | "lock": { 117 | "sign": "ノードに署名", 118 | "signing_node": "これはtailnetの署名ノードです。", 119 | "signing_instructions": "以下のノードは現在tailnetからロックアウトされています。追加したいノードのチェックボックスを選択し、「署名」ボタンをクリックしてtailnetに追加してください。", 120 | "signed_node": "お使いのtailnetでロックが有効になっており、現在のノードは署名済みです。このノードはtailnetと通信可能です。", 121 | "make_signing": "このノードを署名ノードにする場合は、以下の署名ノードのキーを信頼する必要があります。", 122 | "unsigned": "お使いのtailnetでロックが有効になっており、現在のノードは署名されていません。このノードはtailnetと通信できません。", 123 | "unsigned_instructions": "このノードが通信できるようにするには、以下の署名ノードのキーを信頼する必要があります。", 124 | "disabled": "お使いのtailnetではロックが有効になっていません。" 125 | }, 126 | "status_page": { 127 | "exit_node": "エグジットノード", 128 | "connection_type": "接続タイプ", 129 | "connection_addr": "接続", 130 | "tx_bytes": "送信バイト数", 131 | "rx_bytes": "受信バイト数", 132 | "relay": "リレー", 133 | "direct": "ダイレクト", 134 | "exit_active": "アクティブ", 135 | "exit_available": "利用可能", 136 | "idle": "アイドル", 137 | "offline": "オフライン", 138 | "active": "アクティブ", 139 | "login_name": "ログイン名", 140 | "shared": "共有ユーザー", 141 | "action": "操作" 142 | } 143 | } -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/locales/ko_KR.json: -------------------------------------------------------------------------------- 1 | { 2 | "yes": "예", 3 | "no": "아니오", 4 | "ignore": "무시", 5 | "erase": "지우기", 6 | "confirm": "확인", 7 | "download": "다운로드", 8 | "restart": "다시 시작", 9 | "apply": "적용", 10 | "back": "뒤로", 11 | "status": "상태", 12 | "connection": "연결", 13 | "unknown": "알 수 없음", 14 | "none": "없음", 15 | "disabled": "비활성화됨", 16 | "enabled": "활성화됨", 17 | "disable": "비활성화", 18 | "enable": "활성화", 19 | "cancel": "취소", 20 | "accept": "수락", 21 | "sign": "서명", 22 | "login": "로그인", 23 | "add": "추가", 24 | "remove": "제거", 25 | "tailnet": "Tailnet", 26 | "configuration": "구성", 27 | "needs_login": "이 장치는 Tailscale에 로그인해야 합니다. 로그인 후 이 페이지를 새로고침하여 상태를 확인하세요.", 28 | "tailscale_disabled": "Tailscale이(가) 현재 비활성화되어 있습니다. 설정 탭에서 활성화할 수 있습니다.", 29 | "tailscale_lock": "Tailscale 잠금", 30 | "warning": "경고", 31 | "save": "저장하기", 32 | "settings": { 33 | "basic": "기본 보기", 34 | "advanced": "고급 보기", 35 | "system_settings": "시스템 설정", 36 | "enable_tailscale": "Tailscale 활성화", 37 | "unraid_listen": "Unraid 서비스가 Tailscale IP로 수신 대기", 38 | "ip_forward": "IP 포워딩 활성화", 39 | "taildrop": "Taildrop 위치", 40 | "services": "Tailscale 서비스", 41 | "wireguard": "Wireguard 포트", 42 | "outbound_network": "고급 네트워크 옵션", 43 | "subnets": "Tailscale 서브넷 허용", 44 | "dns": "Tailscale DNS 설정 허용", 45 | "save": "설정 저장", 46 | "restart": "Tailscale 다시 시작", 47 | "erase": "Tailscale 구성 삭제", 48 | "diagnostics": "플러그인 진단", 49 | "reauthenticate": "다시 인증", 50 | "funnel": "Tailscale Funnel 허용", 51 | "hosts": "/etc/hosts에 피어 추가하기​​.", 52 | "no_logs_no_support": "로그 비활성화 시 지원 불가", 53 | "tpm": "TPM을 사용하여 노드 키 암호화 허용", 54 | "context": { 55 | "tpm": "TPM(신뢰 플랫폼 모듈)을 사용하여 Tailscale 노드 키를 안전하게 저장할 수 있습니다. 이 기능을 사용하면 노드 키가 쉽게 추출되지 않도록 보호되어, 권한이 있는 하드웨어에서만 접근할 수 있도록 보안이 향상됩니다. 이 옵션을 활성화하려면 TPM 2.0이 필요합니다. 시스템에 호환되는 TPM이 없으면 아무런 효과가 없습니다.", 56 | "unraid_listen": "Unraid 서비스(SSH, WebGUI, SMB 등)가 Tailscale 주소에서 수신 대기하도록 구성합니다.", 57 | "ip_forward": "sysctl에서 net.ipv4.ip_forward 및 net.ipv6.conf.all.forwarding을 1로 설정합니다. 이 설정은 활성화 시 즉시 적용됩니다.", 58 | "taildrop": "수신되는 Taildrop 파일의 경로를 지정하세요.", 59 | "dns": "CLI 또는 WebGUI를 통해 Tailscale DNS를 활성화할 수 있습니다. 비활성화하면 Tailscale 시작 시 Tailscale DNS가 비활성화됩니다.", 60 | "subnets": "CLI 또는 WebGUI를 통해 Tailscale 라우트를 활성화할 수 있습니다. 비활성화하면 Tailscale 시작 시 Tailscale 라우트가 비활성화됩니다.", 61 | "wireguard": "Wireguard 연결에 사용할 포트를 변경합니다. 일반적으로 이 설정을 변경할 필요는 없습니다.", 62 | "erase": "Tailscale에서 로그아웃하고 모든 설정을 기본값으로 초기화합니다.", 63 | "restart": "Tailscale 데몬을 다시 시작하고 설정을 재적용합니다.", 64 | "diagnostics": "진단을 다운로드합니다(완료까지 시간이 걸릴 수 있습니다).", 65 | "save": "변경 사항이 적용되면 Tailscale이 다시 시작됩니다.", 66 | "reauthenticate": "Tailscale 재인증을 강제합니다.", 67 | "funnel": "WebGUI를 통해 Tailscale funnel을 활성화할 수 있습니다. 비활성화하면 Tailscale funnel이 비활성화됩니다.", 68 | "hosts": "Tailscale 피어를 이름 해석을 위해 /etc/hosts에 추가합니다. 이는 서버에서 Tailscale DNS를 활성화하여 발생할 수 있는 잠재적인 복잡함 없이 Tailnet DNS 이름을 사용하고 싶을 때 유용합니다.", 69 | "no_logs_no_support": "Tailscale의 원격 측정이 비활성화되어 디버깅에 해당 원격 측정이 필요한 Tailscale의 지원을 받을 수 없습니다." 70 | } 71 | }, 72 | "info": { 73 | "online": "온라인", 74 | "version": "Tailscale 버전", 75 | "health": "Tailscale 상태", 76 | "login": "로그인됨", 77 | "netmap": "네트워크 맵에 포함됨", 78 | "key_expire": "키 만료", 79 | "tags": "태그", 80 | "hostname": "호스트 이름", 81 | "dns": "DNS 이름", 82 | "ip": "Tailscale IP", 83 | "magicdns": "MagicDNS 접미사", 84 | "routes": "광고된 라우트", 85 | "accept_routes": "라우트 수락", 86 | "accept_dns": "DNS 수락", 87 | "run_ssh": "Tailscale SSH", 88 | "advertise_exit_node": "Exit Node로 실행", 89 | "use_exit_node": "Exit Node 사용", 90 | "exit_node_local": "Exit Node 사용 중 LAN 접근 허용", 91 | "unapproved": "관리 콘솔에서 승인이 필요합니다.", 92 | "connected_via": "Tailscale을 통해 연결됨", 93 | "funnel_port": "WebGUI용 Funnel 포트", 94 | "port_in_use": "사용 중인 포트", 95 | "peer_relay": "피어 릴레이 포트", 96 | "auto_update": "자동 업데이트", 97 | "lock": { 98 | "node_key": "노드 키", 99 | "public_key": "공개 키", 100 | "signed": "노드 키 서명됨", 101 | "signing": "서명 노드 여부" 102 | } 103 | }, 104 | "warnings": { 105 | "key_expiration": "Tailscale 키가 %s일 뒤 %s에 만료됩니다.", 106 | "netbios": "SMB 설정에서 NetBIOS가 활성화되어 있습니다 - 이로 인해 공유를 Tailscale을 통해 액세스할 수 없을 수 있습니다.", 107 | "lock": "Tailnet에 잠금이 활성화되었지만, 이 노드는 서명되지 않았습니다. Tailnet과 통신할 수 없습니다.", 108 | "funnel": "Unraid WebGUI에 대해 Tailscale Funnel을 활성화하면 서버가 인터넷에 노출되어 무단 액세스 및 잠재적인 공격의 위험이 크게 증가합니다. 이 기능은 보안상의 영향을 완전히 이해하는 경우에만 활성화해야 합니다. 원격 액세스를 위한 권장/안전한 방법은 Funnel을 활성화하는 대신 WebGUI에 액세스할 장치에 Tailscale을 설치하는 것입니다.", 109 | "subnet": "Unraid 서버에서 Tailscale 서브넷을 수락하면 일부 네트워크 구성에서 로컬 네트워크 연결이 방해받을 수 있습니다. Unraid 서버가 서브넷 라우터 또는 종료 노드로 동작하기 위해 라우트 수락은 필요하지 않습니다. Unraid 서버에서 다른 장치가 광고하는 원격 서브넷에 연결해야 할 때만 이 옵션을 활성화하세요.", 110 | "dns": "서버에서 Tailscale MagicDNS를 활성화하면 Docker 컨테이너 내의 이름 해석이 방해받아 애플리케이션 연결 문제가 발생할 수 있습니다. MagicDNS는 다른 장치에서 'unraid.tailnet.ts.net' 같은 MagicDNS 이름으로 Unraid 서버에 접근하기 위해 서버에서 활성화할 필요가 없습니다. '피어를 /etc/hosts에 추가하기'를 활성화하면 서버에서 Tailscale 이름을 사용할 수 있어 더욱 안전한 대안이 됩니다.", 111 | "caution": "신중하게 진행하시고 계속하기 전에 이 변경의 영향을 충분히 이해했는지 확인하세요.", 112 | "more_info": "자세한 정보:", 113 | "peer_relay_no_acl": "Tailnet 정책(액세스 제어)에서 구성되지 않았습니다.", 114 | "tpm": "TPM을 활성화하면 Tailscale 노드 키가 이 장치의 특정 하드웨어에 고정됩니다. 이후 TPM이 비활성화되면 Tailscale 노드 키가 무효화되어 장치를 다시 Tailscale에 인증해야 합니다. 또한 TPM이 잠기면 Tailscale 연결이 중단되어 다시 인증해야 할 수 있습니다." 115 | }, 116 | "lock": { 117 | "sign": "노드 서명", 118 | "signing_node": "이 노드는 Tailnet의 서명 노드입니다.", 119 | "signing_instructions": "다음 노드들이 현재 Tailnet에서 잠겨져 있습니다. 추가할 노드를 선택한 후, 서명 버튼을 클릭하여 Tailnet에 노드를 추가하세요.", 120 | "signed_node": "Tailnet에 잠금이 활성화되어 있고 현재 노드는 서명되었습니다. 이 노드는 Tailnet과 통신할 수 있습니다.", 121 | "make_signing": "이 노드를 서명 노드로 만들려면 서명 노드에서 다음 키를 신뢰해야 합니다:", 122 | "unsigned": "Tailnet에 잠금이 활성화되어 있고 현재 노드는 서명되지 않았습니다. 이 노드는 Tailnet과 통신할 수 없습니다.", 123 | "unsigned_instructions": "이 노드가 통신할 수 있도록 하려면 서명 노드에서 다음 키를 신뢰해야 합니다.", 124 | "disabled": "Tailnet에 잠금이 활성화되어 있지 않습니다." 125 | }, 126 | "status_page": { 127 | "exit_node": "종료 노드", 128 | "connection_type": "연결 유형", 129 | "connection_addr": "연결", 130 | "tx_bytes": "Tx 바이트", 131 | "rx_bytes": "Rx 바이트", 132 | "relay": "릴레이", 133 | "direct": "직접 연결", 134 | "exit_active": "활성화됨", 135 | "exit_available": "사용 가능", 136 | "idle": "유휴", 137 | "offline": "오프라인", 138 | "active": "활성화됨", 139 | "login_name": "로그인 이름", 140 | "shared": "공유된 사용자", 141 | "action": "동작" 142 | } 143 | } -------------------------------------------------------------------------------- /plugin/tailscale-preview.plg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 17 | 45 | 46 | 47 | 48 | 49 | 76 | 77 | 78 | 79 | 80 | https://pkgs.tailscale.com/stable/tailscale_1.92.3_amd64.tgz 81 | 5f51b7e3819286cb3f18e7999c51e37a967610011e88b6c25ff65c49ab0908dc 82 | 83 | 84 | 85 | https://github.com/unraid/unraid-tailscale/releases/download/2025.12.17.0420/unraid-tailscale-utils-2025.12.17.0420-noarch-1.txz 86 | 5473e0ccbc471ad8188d9a4d88ed4d35c534234db677118ad5b61c356d8ab2ab 87 | 88 | 89 | 92 | 93 | 94 | /boot/config/plugins/tailscale/.gitignore 110 | 111 | ln -s /usr/local/emhttp/plugins/tailscale/bin/tailscale /usr/local/sbin/tailscale 112 | ln -s /usr/local/emhttp/plugins/tailscale/bin/tailscaled /usr/local/sbin/tailscaled 113 | 114 | # remove other branches (e.g., if switching from main to preview) 115 | rm -f /boot/config/plugins/tailscale.plg 116 | rm -f /var/log/plugins/tailscale.plg 117 | rm -f /boot/config/plugins/tailscale-trunk.plg 118 | rm -f /var/log/plugins/tailscale-trunk.plg 119 | 120 | 121 | # Update plugin name for non-main branches 122 | sed -i "s/Tailscale\*\*/Tailscale (Preview)**/" /usr/local/emhttp/plugins/tailscale/README.md 123 | 124 | 125 | # start tailscaled 126 | /usr/local/emhttp/plugins/tailscale/restart.sh 127 | 128 | # Bash completion 129 | tailscale completion bash > /etc/bash_completion.d/tailscale 130 | 131 | # cleanup old versions 132 | rm -f $(ls /boot/config/plugins/tailscale/unraid-tailscale-utils-*.txz 2>/dev/null | grep -v '2025.12.17.0420') 133 | rm -f $(ls /boot/config/plugins/tailscale/*.tgz 2>/dev/null | grep -v 'tailscale_1.92.3_amd64') 134 | 135 | # check to see if the state file has been backed up to Unraid Connect 136 | if [ -d "/boot/.git" ]; then 137 | if git --git-dir /boot/.git log --all --name-only --diff-filter=A -- config/plugins/tailscale/state/tailscaled.state | grep -q . ; then 138 | echo "******************************" 139 | echo "* WARNING *" 140 | echo "******************************" 141 | echo " " 142 | echo "The Tailscale state file has been backed up to Unraid Connect via Flash backup." 143 | echo " " 144 | echo "To remove this backup, please perform the following steps:" 145 | echo "1. Go to Settings -> Management Access". 146 | echo "2. Under Unraid Connect, deactivate flash backup. Select the option to also delete cloud backup." 147 | echo "3. Reactivate flash backup." 148 | 149 | /usr/local/emhttp/webGui/scripts/notify -l '/Settings/ManagementAccess' -i 'alert' -e 'Tailscale State' -s 'Tailscale state backed up to Unraid connect.' -d 'The Tailscale state file has been backed up to Unraid connect. This is a potential security risk. From the Management Settings page, deactivate flash backup and delete cloud backups, then reactivate flash backup.' 150 | fi 151 | fi 152 | 153 | echo "" 154 | echo "----------------------------------------------------" 155 | echo " tailscale has been installed." 156 | echo " Version: 2025.12.17.0420" 157 | echo "----------------------------------------------------" 158 | echo "" 159 | ]]> 160 | 161 | 162 | 163 | 166 | 167 | 168 | /dev/null 171 | 172 | rm /usr/local/sbin/tailscale 173 | rm /usr/local/sbin/tailscaled 174 | 175 | removepkg unraid-tailscale-utils 176 | 177 | rm -rf /usr/local/emhttp/plugins/tailscale 178 | rm -f /boot/config/plugins/tailscale/*.tgz 179 | rm -f /boot/config/plugins/tailscale/*.txz 180 | ]]> 181 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /plugin/plugin.j2: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% set pluginDirectory = "/usr/local/emhttp/plugins/tailscale" -%} 5 | {% set configDirectory = "/boot/config/plugins/tailscale" -%} 6 | {% set version = env['PLUGIN_VERSION'] -%} 7 | {% if env['PLUGIN_RELEASE'] == "-preview" -%} 8 | {% set branch = "preview" -%} 9 | {% else -%} 10 | {% set branch = "main" -%} 11 | {% endif -%} 12 | 13 | 24 | 25 | 26 | 31 | 32 | 33 | 34 | 35 | 62 | 63 | 64 | 65 | 66 | https://pkgs.tailscale.com/stable/{{ tailscaleVersion }}.tgz 67 | {{ tailscaleSHA256 }} 68 | 69 | 70 | 71 | https://github.com/{{ env['GITHUB_REPOSITORY'] }}/releases/download/{{ env['PLUGIN_VERSION'] }}/{{ package_name }}-{{ env['PLUGIN_VERSION'] }}-noarch-1.txz 72 | {{ env['PLUGIN_CHECKSUM'] }} 73 | 74 | 75 | 78 | 79 | 80 | {{ configDirectory }}/.gitignore 96 | 97 | ln -s {{ pluginDirectory }}/bin/tailscale /usr/local/sbin/tailscale 98 | ln -s {{ pluginDirectory }}/bin/tailscaled /usr/local/sbin/tailscaled 99 | 100 | # remove other branches (e.g., if switching from main to preview) 101 | {% if branch != 'main' -%} 102 | rm -f /boot/config/plugins/tailscale.plg 103 | rm -f /var/log/plugins/tailscale.plg 104 | {% endif -%} 105 | {% if branch != 'preview' -%} 106 | rm -f /boot/config/plugins/tailscale-preview.plg 107 | rm -f /var/log/plugins/tailscale-preview.plg 108 | {% endif -%} 109 | {% if branch != 'trunk' -%} 110 | rm -f /boot/config/plugins/tailscale-trunk.plg 111 | rm -f /var/log/plugins/tailscale-trunk.plg 112 | {% endif %} 113 | 114 | {% if branch != 'main' -%} 115 | # Update plugin name for non-main branches 116 | sed -i "s/Tailscale\*\*/Tailscale ({{ branch.capitalize() }})**/" {{ pluginDirectory }}/README.md 117 | {% endif %} 118 | 119 | # start tailscaled 120 | {{ pluginDirectory }}/restart.sh 121 | 122 | # Bash completion 123 | tailscale completion bash > /etc/bash_completion.d/tailscale 124 | 125 | # cleanup old versions 126 | rm -f $(ls /boot/config/plugins/{{ name }}/{{ package_name }}-*.txz 2>/dev/null | grep -v '{{ env['PLUGIN_VERSION'] }}') 127 | rm -f $(ls /boot/config/plugins/{{ name }}/*.tgz 2>/dev/null | grep -v '{{ tailscaleVersion }}') 128 | 129 | # check to see if the state file has been backed up to Unraid Connect 130 | if [ -d "/boot/.git" ]; then 131 | if git --git-dir /boot/.git log --all --name-only --diff-filter=A -- config/plugins/tailscale/state/tailscaled.state | grep -q . ; then 132 | echo "******************************" 133 | echo "* WARNING *" 134 | echo "******************************" 135 | echo " " 136 | echo "The Tailscale state file has been backed up to Unraid Connect via Flash backup." 137 | echo " " 138 | echo "To remove this backup, please perform the following steps:" 139 | echo "1. Go to Settings -> Management Access". 140 | echo "2. Under Unraid Connect, deactivate flash backup. Select the option to also delete cloud backup." 141 | echo "3. Reactivate flash backup." 142 | 143 | /usr/local/emhttp/webGui/scripts/notify -l '/Settings/ManagementAccess' -i 'alert' -e 'Tailscale State' -s 'Tailscale state backed up to Unraid connect.' -d 'The Tailscale state file has been backed up to Unraid connect. This is a potential security risk. From the Management Settings page, deactivate flash backup and delete cloud backups, then reactivate flash backup.' 144 | fi 145 | fi 146 | 147 | echo "" 148 | echo "----------------------------------------------------" 149 | echo " {{ name }} has been installed." 150 | echo " Version: {{ env['PLUGIN_VERSION'] }}" 151 | echo "----------------------------------------------------" 152 | echo "" 153 | ]]> 154 | 155 | 156 | 157 | 160 | 161 | 162 | /dev/null 165 | 166 | rm /usr/local/sbin/tailscale 167 | rm /usr/local/sbin/tailscaled 168 | 169 | removepkg unraid-tailscale-utils 170 | 171 | rm -rf {{ pluginDirectory }} 172 | rm -f {{ configDirectory }}/*.tgz 173 | rm -f {{ configDirectory }}/*.txz 174 | ]]> 175 | 176 | 177 | 178 | 179 | -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/include/Pages/Tailscale.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | namespace Tailscale; 21 | 22 | use EDACerton\PluginUtils\Translator; 23 | 24 | $docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp'; 25 | require_once "{$docroot}/plugins/tailscale/include/common.php"; 26 | 27 | if ( ! defined(__NAMESPACE__ . '\PLUGIN_ROOT') || ! defined(__NAMESPACE__ . '\PLUGIN_NAME')) { 28 | throw new \RuntimeException("Common file not loaded."); 29 | } 30 | 31 | $tr = $tr ?? new Translator(PLUGIN_ROOT); 32 | 33 | $tailscaleConfig = $tailscaleConfig ?? new Config(); 34 | 35 | if ( ! $tailscaleConfig->Enable) { 36 | echo($tr->tr("tailscale_disabled")); 37 | return; 38 | } 39 | 40 | $tailscaleInfo = $tailscaleInfo ?? new Info($tr); 41 | ?> 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 55 | 56 | 198 | 199 | 200 | getTailscaleLockWarning()); ?> 201 | getTailscaleNetbiosWarning()); ?> 202 | getKeyExpirationWarning()); ?> 203 | 204 |

205 |

206 |

207 | 208 | 209 | 212 | 213 |
210 | 211 |
-------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/locales/en_US.json: -------------------------------------------------------------------------------- 1 | { 2 | "yes": "Yes", 3 | "no": "No", 4 | "ignore": "Ignore", 5 | "erase": "Erase", 6 | "confirm": "Confirm", 7 | "download": "Download", 8 | "restart": "Restart", 9 | "apply": "Apply", 10 | "back": "Back", 11 | "status": "Status", 12 | "connection": "Connection", 13 | "unknown": "Unknown", 14 | "none": "None", 15 | "disabled": "Disabled", 16 | "enabled": "Enabled", 17 | "disable": "Disable", 18 | "enable": "Enable", 19 | "cancel": "Cancel", 20 | "accept": "Accept", 21 | "sign": "Sign", 22 | "login": "Login", 23 | "add": "Add", 24 | "remove": "Remove", 25 | "tailnet": "Tailnet", 26 | "configuration": "Configuration", 27 | "needs_login": "This device needs to be logged in to Tailscale. Refresh this page after logging in to view the status.", 28 | "tailscale_disabled": "Tailscale is currently disabled. It can be enabled via the Settings tab.", 29 | "tailscale_lock": "Tailscale Lock", 30 | "warning": "Warning", 31 | "save": "Save", 32 | "settings": { 33 | "basic": "Basic View", 34 | "advanced": "Advanced View", 35 | "system_settings": "System Settings", 36 | "enable_tailscale": "Enable Tailscale", 37 | "unraid_listen": "Unraid services listen on Tailscale IP", 38 | "ip_forward": "Enable IP Forwarding", 39 | "taildrop": "Taildrop Location", 40 | "services": "Tailscale Services", 41 | "wireguard": "Wireguard Port", 42 | "outbound_network": "Advanced Network Options", 43 | "subnets": "Allow Tailscale Subnets", 44 | "dns": "Allow Tailscale DNS settings", 45 | "save": "Save Settings", 46 | "restart": "Restart Tailscale", 47 | "erase": "Erase Tailscale Configuration", 48 | "diagnostics": "Plugin Diagnostics", 49 | "reauthenticate": "Reauthenticate", 50 | "funnel": "Allow Tailscale Funnel", 51 | "hosts": "Add Peers to /etc/hosts", 52 | "no_logs_no_support": "No Logs No Support", 53 | "tpm": "Allow TPM to Encrypt Node Key", 54 | "context": { 55 | "tpm": "Enables the use of a TPM (Trusted Platform Module) for secure storage of the Tailscale node key. This enhances security by protecting the node key from being easily extracted, ensuring that only authorized hardware can access it. Enabling this option requires TPM 2.0. It has no effect if the system does not have a compatible TPM.", 56 | "unraid_listen": "Configures Unraid services (SSH, WebGUI, SMB, etc.) to listen on Tailscale addresses.", 57 | "ip_forward": "Sets net.ipv4.ip_forward and net.ipv6.conf.all.forwarding to 1 in sysctl. This change occurs immediately when being enabled.", 58 | "taildrop": "Specify the path for incoming Taildrop files.", 59 | "dns": "Allows Tailscale DNS to be enabled via the CLI or WebGUI. If disabled, Tailscale DNS will be disabled when Tailscale starts.", 60 | "subnets": "Allows Tailscale routes to be enabled via the CLI or WebGUI. If disabled, Tailscale routes will be disabled when Tailscale starts.", 61 | "wireguard": "Change the port used for Wireguard conections. This usually does not need to be changed.", 62 | "erase": "Logs out of Tailscale and resets all settings to defaults", 63 | "restart": "Restart the Tailscale daemon and reapply settings.", 64 | "diagnostics": "Download diagnostics (this may take some time to complete)", 65 | "save": "Tailscale will be restarted when changes are applied", 66 | "reauthenticate": "Force a Tailscale reauthentication.", 67 | "funnel": "Allows Tailscale funnel to be enabled via the WebGUI. If disabled, Tailscale funnel will be disabled.", 68 | "hosts": "Adds Tailscale peers to /etc/hosts for name resolution. This is useful if you want to use Tailnet DNS names, without the potential complications of enabling Tailscale DNS on the server.", 69 | "no_logs_no_support": "Disables Tailscale's telemetry and opts you out of getting support from Tailscale that would require such telemetry for debugging." 70 | } 71 | }, 72 | "info": { 73 | "online": "Online", 74 | "version": "Tailscale Version", 75 | "health": "Tailscale Health", 76 | "login": "Logged In", 77 | "netmap": "In Network Map", 78 | "key_expire": "Key Expiration", 79 | "tags": "Tags", 80 | "hostname": "Hostname", 81 | "dns": "DNS Name", 82 | "ip": "Tailscale IPs", 83 | "magicdns": "MagicDNS Suffix", 84 | "routes": "Advertised Routes", 85 | "accept_routes": "Accept Routes", 86 | "accept_dns": "Accept DNS", 87 | "run_ssh": "Tailscale SSH", 88 | "advertise_exit_node": "Run as Exit Node", 89 | "use_exit_node": "Use Exit Node", 90 | "exit_node_local": "Allow LAN Access while using Exit Node", 91 | "unapproved": "Needs approval in admin console", 92 | "connected_via": "Connected via Tailscale", 93 | "funnel_port": "Funnel Port for WebGUI", 94 | "port_in_use": "Port in Use", 95 | "peer_relay": "Peer Relay Port", 96 | "auto_update": "Auto Update", 97 | "lock": { 98 | "node_key": "Node Key", 99 | "public_key": "Public Key", 100 | "signed": "Node Key Signed", 101 | "signing": "Is Signing Node" 102 | } 103 | }, 104 | "warnings": { 105 | "key_expiration": "The Tailscale key will expire in %s days on %s.", 106 | "netbios": "NetBIOS is enabled in SMB settings - this can prevent shares from being accessed via Tailscale.", 107 | "lock": "The tailnet has lock enabled, but this node has not been signed. It will not be able to communicate with the tailnet.", 108 | "funnel": "Enabling Tailscale Funnel for the Unraid WebGUI exposes your server to the internet, significantly increasing the risk of unauthorized access and potential attacks. This feature should only be enabled if you fully understand the security impact. The recommended/secure approach for remote access is to install Tailscale on the devices you plan to use to access the WebGUI instead of enabling Funnel.", 109 | "subnet": "Accepting Tailscale subnets on your Unraid server can disrupt local network connectivity in certain network configurations. Accepting routes is not required for your Unraid server to function as a subnet router or exit node. Only enable this option if your Unraid server needs to connect to remote subnets advertised by other devices.", 110 | "dns": "Enabling Tailscale MagicDNS on your server can disrupt name resolution inside Docker containers, potentially causing connectivity issues for applications. MagicDNS does not need to be enabled on the server for you to access your Unraid server using MagicDNS names (e.g., 'unraid.tailnet.ts.net') from other devices. Enabling 'Add Peers to /etc/hosts' is a safer alternative that allows Tailscale names to be used on the server.", 111 | "caution": "Proceed with caution and ensure you understand the implications of this change before continuing.", 112 | "more_info": "For more information:", 113 | "peer_relay_no_acl": "Not configured in Tailnet policy (access controls).", 114 | "tpm": "Enabling the TPM locks the Tailscale node key to the specific hardware of this device. If the TPM is later disabled, the Tailscale node key will become invalid and the device will need to be reauthenticated to Tailscale. It is also possible for TPMs to lock out, which can disrupt Tailscale connectivity and require reauthentication." 115 | }, 116 | "lock": { 117 | "sign": "Sign Nodes", 118 | "signing_node": "This is a signing node for the tailnet.", 119 | "signing_instructions": "The following nodes are currently locked out of the tailnet. Check the box for any nodes you wish to add, then click the Sign button, to add the node to the tailnet.", 120 | "signed_node": "Your tailnet has lock enabled and the current node is signed. This node can communicate with the tailnet.", 121 | "make_signing": "If you wish to make this a signing node, you will need to trust the following key from a signing node:", 122 | "unsigned": "Your tailnet has lock enabled and the current node is not signed. This node cannot communicate with the tailnet.", 123 | "unsigned_instructions": "To allow this node to communicate, you will need to trust the following key from a signing node", 124 | "disabled": "Your tailnet does not have lock enabled." 125 | }, 126 | "status_page": { 127 | "exit_node": "Exit Node", 128 | "connection_type": "Connection Type", 129 | "connection_addr": "Connection", 130 | "tx_bytes": "Tx Bytes", 131 | "rx_bytes": "Rx Bytes", 132 | "relay": "Relay", 133 | "direct": "Direct", 134 | "exit_active": "Active", 135 | "exit_available": "Available", 136 | "idle": "Idle", 137 | "offline": "Offline", 138 | "active": "Active", 139 | "login_name": "Login Name", 140 | "shared": "Shared-In User", 141 | "action": "Action" 142 | } 143 | } -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/locales/no_NO.json: -------------------------------------------------------------------------------- 1 | { 2 | "yes": "Ja", 3 | "no": "Nei", 4 | "ignore": "Ignorer", 5 | "erase": "Slett", 6 | "confirm": "Bekreft", 7 | "download": "Last ned", 8 | "restart": "Start på nytt", 9 | "apply": "Bruk", 10 | "back": "Tilbake", 11 | "status": "Status", 12 | "connection": "Tilkobling", 13 | "unknown": "Ukjent", 14 | "none": "Ingen", 15 | "disabled": "Deaktivert", 16 | "enabled": "Aktivert", 17 | "disable": "Deaktiver", 18 | "enable": "Aktiver", 19 | "cancel": "Avbryt", 20 | "accept": "Godta", 21 | "sign": "Signer", 22 | "login": "Innlogging", 23 | "add": "Legg til", 24 | "remove": "Fjern", 25 | "tailnet": "Tailnet", 26 | "configuration": "Konfigurasjon", 27 | "needs_login": "Denne enheten må logges inn på Tailscale. Oppdater denne siden etter innlogging for å se status.", 28 | "tailscale_disabled": "Tailscale er for øyeblikket deaktivert. Det kan aktiveres via fanen Innstillinger.", 29 | "tailscale_lock": "Tailscale-lås", 30 | "warning": "Advarsel", 31 | "save": "Lagre", 32 | "settings": { 33 | "basic": "Grunnleggende visning", 34 | "advanced": "Avansert visning", 35 | "system_settings": "Systeminnstillinger", 36 | "enable_tailscale": "Aktiver Tailscale", 37 | "unraid_listen": "Unraid-tjenester lytter på Tailscale-IP", 38 | "ip_forward": "Aktiver IP-videresending", 39 | "taildrop": "Taildrop-plassering", 40 | "services": "Tailscale-tjenester", 41 | "wireguard": "Wireguard-port", 42 | "outbound_network": "Avanserte nettverksalternativer", 43 | "subnets": "Tillat Tailscale-subnett", 44 | "dns": "Tillat Tailscale DNS-innstillinger", 45 | "save": "Lagre innstillinger", 46 | "restart": "Start Tailscale på nytt", 47 | "erase": "Slett Tailscale-konfigurasjon", 48 | "diagnostics": "Plugin-diagnostikk", 49 | "reauthenticate": "Reautentiser", 50 | "funnel": "Tillat Tailscale Funnel", 51 | "hosts": "Legg til Peers i /etc/hosts", 52 | "no_logs_no_support": "Ingen logger, ingen støtte", 53 | "tpm": "Tillat TPM å kryptere node-nøkkel", 54 | "context": { 55 | "tpm": "Aktiverer bruk av TPM (Trusted Platform Module) for sikker lagring av Tailscale-node-nøkkelen. Dette forbedrer sikkerheten ved å beskytte node-nøkkelen mot enkel utvinning, og sikrer at kun autorisert maskinvare kan få tilgang. Aktivering av dette alternativet krever TPM 2.0. Det har ingen effekt dersom systemet ikke har en kompatibel TPM.", 56 | "unraid_listen": "Konfigurerer Unraid-tjenester (SSH, WebGUI, SMB, osv.) til å lytte på Tailscale-adresser.", 57 | "ip_forward": "Setter net.ipv4.ip_forward og net.ipv6.conf.all.forwarding til 1 i sysctl. Denne endringen skjer umiddelbart når den aktiveres.", 58 | "taildrop": "Angi stien for innkommende Taildrop-filer.", 59 | "dns": "Tillater at Tailscale DNS kan aktiveres via CLI eller WebGUI. Hvis deaktivert, deaktiveres Tailscale DNS når Tailscale starter.", 60 | "subnets": "Tillater at Tailscale-ruter kan aktiveres via CLI eller WebGUI. Hvis deaktivert, deaktiveres Tailscale-ruter når Tailscale starter.", 61 | "wireguard": "Endre porten som brukes for Wireguard-tilkoblinger. Dette trenger vanligvis ikke endres.", 62 | "erase": "Logger ut av Tailscale og tilbakestiller alle innstillinger til standard.", 63 | "restart": "Starter Tailscale-daemonen på nytt og bruker innstillingene på nytt.", 64 | "diagnostics": "Last ned diagnostikk (dette kan ta litt tid å fullføre)", 65 | "save": "Tailscale vil bli startet på nytt når endringer brukes", 66 | "reauthenticate": "Tving en Tailscale-reauthentisering.", 67 | "funnel": "Tillater at Tailscale Funnel kan aktiveres via WebGUI. Hvis deaktivert, vil Tailscale Funnel være deaktivert.", 68 | "hosts": "Legger til Tailscale-peers i /etc/hosts for navneoppløsning. Dette er nyttig hvis du vil kunne bruke Tailnet DNS-navn uten de potensielle komplikasjonene ved å aktivere Tailscale DNS på serveren.", 69 | "no_logs_no_support": "Deaktiverer Tailscale sin telemetri og gjør at du ikke kan få støtte fra Tailscale som krever slik telemetri for feilsøking." 70 | } 71 | }, 72 | "info": { 73 | "online": "Online", 74 | "version": "Tailscale-versjon", 75 | "health": "Tailscale-helse", 76 | "login": "Innlogget", 77 | "netmap": "I nettverkskart", 78 | "key_expire": "Nøkkelutløp", 79 | "tags": "Tagger", 80 | "hostname": "Vertsnavn", 81 | "dns": "DNS-navn", 82 | "ip": "Tailscale-IP-er", 83 | "magicdns": "MagicDNS-suffiks", 84 | "routes": "Annonserte ruter", 85 | "accept_routes": "Godta ruter", 86 | "accept_dns": "Godta DNS", 87 | "run_ssh": "Tailscale SSH", 88 | "advertise_exit_node": "Kjør som exit node", 89 | "use_exit_node": "Bruk exit node", 90 | "exit_node_local": "Tillat LAN-tilgang ved bruk av exit node", 91 | "unapproved": "Trenger godkjenning i administrasjonskonsollen", 92 | "connected_via": "Tilkoblet via Tailscale", 93 | "funnel_port": "Funnel-port for WebGUI", 94 | "port_in_use": "Port i bruk", 95 | "peer_relay": "Peer-reléport", 96 | "auto_update": "Automatisk oppdatering", 97 | "lock": { 98 | "node_key": "Node-nøkkel", 99 | "public_key": "Offentlig nøkkel", 100 | "signed": "Node-nøkkel signert", 101 | "signing": "Er signernode" 102 | } 103 | }, 104 | "warnings": { 105 | "key_expiration": "Tailscale-nøkkelen utløper om %s dager, den %s.", 106 | "netbios": "NetBIOS er aktivert i SMB-innstillinger - dette kan forhindre tilgang til delinger via Tailscale.", 107 | "lock": "Tailnettet har lås aktivert, men denne noden er ikke signert. Den vil ikke kunne kommunisere med tailnettet.", 108 | "funnel": "Hvis du aktiverer Tailscale Funnel for Unraid WebGUI, eksponeres serveren din mot internett, noe som øker risikoen for uautorisert tilgang og potensielle angrep betydelig. Denne funksjonen bør kun aktiveres hvis du fullt ut forstår sikkerhetskonsekvensene. Den anbefalte/sikre metoden for ekstern tilgang er å installere Tailscale på enhetene du bruker til å få tilgang til WebGUI i stedet for å aktivere Funnel.", 109 | "subnet": "Å godta Tailscale-subnett på Unraid-serveren din kan forstyrre lokal nettverkstilkobling i visse nettverkskonfigurasjoner. Å godta ruter er ikke nødvendig for at Unraid-serveren din skal fungere som en subnettruter eller exit node. Aktiver kun dette alternativet hvis Unraid-serveren din må koble til eksterne subnett annonsert av andre enheter.", 110 | "dns": "Å aktivere Tailscale MagicDNS på serveren din kan forstyrre navneoppløsning inne i Docker-containere, noe som potensielt kan føre til tilkoblingsproblemer for applikasjoner. MagicDNS trenger ikke å være aktivert på serveren for at du skal kunne få tilgang til Unraid-serveren ved å bruke MagicDNS-navn (for eksempel \"unraid.tailnet.ts.net\") fra andre enheter. Å aktivere «Legg til Peers i /etc/hosts» er et tryggere alternativ som lar deg bruke Tailscale-navn på serveren.", 111 | "caution": "Fortsett med forsiktighet og sørg for at du forstår konsekvensene av denne endringen før du går videre.", 112 | "more_info": "For mer informasjon:", 113 | "peer_relay_no_acl": "Ikke konfigurert i Tailnet-policyen (tilgangskontroller).", 114 | "tpm": "Når TPM aktiveres, låses Tailscale-node-nøkkelen til maskinvaren på denne enheten. Hvis TPM senere deaktiveres, vil Tailscale-node-nøkkelen bli ugyldig, og enheten må autentiseres på nytt med Tailscale. Det er også mulig at TPM kan låses ute, noe som kan forstyrre Tailscale-tilkoblingen og kreve ny autentisering." 115 | }, 116 | "lock": { 117 | "sign": "Signer noder", 118 | "signing_node": "Dette er en signernode for tailnettet.", 119 | "signing_instructions": "Følgende noder er for øyeblikket låst ute fra tailnettet. Huk av for de nodene du ønsker å legge til, og klikk deretter på Signer-knappen for å legge noden til tailnettet.", 120 | "signed_node": "Tailnettet ditt har lås aktivert, og denne noden er signert. Denne noden kan kommunisere med tailnettet.", 121 | "make_signing": "Hvis du ønsker å gjøre dette til en signernode, må du stole på følgende nøkkel fra en signernode:", 122 | "unsigned": "Tailnettet ditt har lås aktivert, og denne noden er ikke signert. Denne noden kan ikke kommunisere med tailnettet.", 123 | "unsigned_instructions": "For å tillate at denne noden kommuniserer, må du stole på følgende nøkkel fra en signernode", 124 | "disabled": "Tailnettet ditt har ikke lås aktivert." 125 | }, 126 | "status_page": { 127 | "exit_node": "Utgangspunkt", 128 | "connection_type": "Tilkoblingstype", 129 | "connection_addr": "Tilkobling", 130 | "tx_bytes": "Tx-bytes", 131 | "rx_bytes": "Rx-bytes", 132 | "relay": "Relé", 133 | "direct": "Direkte", 134 | "exit_active": "Aktiv", 135 | "exit_available": "Tilgjengelig", 136 | "idle": "Tomgang", 137 | "offline": "Frakoblet", 138 | "active": "Aktiv", 139 | "login_name": "Innloggingsnavn", 140 | "shared": "Delt bruker", 141 | "action": "Handling" 142 | } 143 | } -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/locales/sv_SE.json: -------------------------------------------------------------------------------- 1 | { 2 | "yes": "Ja", 3 | "no": "Nej", 4 | "ignore": "Ignorera", 5 | "erase": "Radera", 6 | "confirm": "Bekräfta", 7 | "download": "Ladda ner", 8 | "restart": "Starta om", 9 | "apply": "Tillämpa", 10 | "back": "Tillbaka", 11 | "status": "Status", 12 | "connection": "Anslutning", 13 | "unknown": "Okänd", 14 | "none": "Ingen", 15 | "disabled": "Inaktiverad", 16 | "enabled": "Aktiverad", 17 | "disable": "Inaktivera", 18 | "enable": "Aktivera", 19 | "cancel": "Avbryt", 20 | "accept": "Acceptera", 21 | "sign": "Signera", 22 | "login": "Inloggning", 23 | "add": "Lägg till", 24 | "remove": "Ta bort", 25 | "tailnet": "Tailnet", 26 | "configuration": "Konfiguration", 27 | "needs_login": "Den här enheten måste vara inloggad i Tailscale. Uppdatera denna sidan efter inloggning för att visa status.", 28 | "tailscale_disabled": "Tailscale är för närvarande inaktiverat. Det kan aktiveras via fliken Inställningar.", 29 | "tailscale_lock": "Tailscale-lås", 30 | "warning": "Varning", 31 | "save": "Spara", 32 | "settings": { 33 | "basic": "Grundvy", 34 | "advanced": "Avancerad vy", 35 | "system_settings": "Systeminställningar", 36 | "enable_tailscale": "Aktivera Tailscale", 37 | "unraid_listen": "Unraid-tjänster lyssnar på Tailscale IP", 38 | "ip_forward": "Aktivera IP-vidarebefordran", 39 | "taildrop": "Taildrop-plats", 40 | "services": "Tailscale-tjänster", 41 | "wireguard": "Wireguard-port", 42 | "outbound_network": "Avancerade nätverksalternativ", 43 | "subnets": "Tillåt Tailscale-subnät", 44 | "dns": "Tillåt Tailscale DNS-inställningar", 45 | "save": "Spara inställningar", 46 | "restart": "Starta om Tailscale", 47 | "erase": "Radera Tailscale-konfiguration", 48 | "diagnostics": "Plugin-diagnostik", 49 | "reauthenticate": "Tvinga Tailscale att autentisera om.", 50 | "funnel": "Tillåt Tailscale Funnel", 51 | "hosts": "Lägg till Peers i /etc/hosts.", 52 | "no_logs_no_support": "Inga loggar, inget stöd", 53 | "tpm": "Tillåt TPM att kryptera nodnyckel", 54 | "context": { 55 | "tpm": "Aktiverar användning av en TPM (Trusted Platform Module) för säker lagring av Tailscale-nodnyckeln. Detta förbättrar säkerheten genom att skydda nodnyckeln från att enkelt kunna extraheras, vilket säkerställer att endast auktoriserad hårdvara kan komma åt den. Aktivering av detta alternativ kräver TPM 2.0. Det har ingen effekt om systemet inte har en kompatibel TPM.", 56 | "unraid_listen": "Konfigurerar Unraid-tjänster (SSH, WebGUI, SMB, etc.) att lyssna på Tailscale-adresser.", 57 | "ip_forward": "Ställer in net.ipv4.ip_forward och net.ipv6.conf.all.forwarding till 1 i sysctl. Denna ändring sker omedelbart när den aktiveras.", 58 | "taildrop": "Ange sökvägen för inkommande Taildrop-filer.", 59 | "dns": "Tillåter att Tailscale DNS kan aktiveras via CLI eller WebGUI. Om det är inaktiverat kommer Tailscale DNS att inaktiveras när Tailscale startar.", 60 | "subnets": "Tillåter att Tailscale-rutter kan aktiveras via CLI eller WebGUI. Om det är inaktiverat kommer Tailscale-rutter att inaktiveras när Tailscale startar.", 61 | "wireguard": "Ändra porten som används för Wireguard-anslutningar. Detta behöver vanligtvis inte ändras.", 62 | "erase": "Loggar ut från Tailscale och återställer alla inställningar till standardvärdena", 63 | "restart": "Starta om Tailscale-daemonen och tillämpa inställningar på nytt.", 64 | "diagnostics": "Ladda ner diagnostik (detta kan ta en stund att slutföra)", 65 | "save": "Tailscale kommer att startas om när ändringar tillämpas", 66 | "reauthenticate": "Tvinga en Tailscale-omautentisering.", 67 | "funnel": "Tillåter att Tailscale Funnel kan aktiveras via WebGUI. Om det är inaktiverat kommer Tailscale Funnel att inaktiveras.", 68 | "hosts": "Lägger till Tailscale-peers i /etc/hosts för namnuppslagning. Detta är användbart om du vill använda Tailnet DNS-namn utan de potentiella komplikationerna med att aktivera Tailscale DNS på servern.", 69 | "no_logs_no_support": "Inaktiverar Tailscales telemetri och utesluter dig från att få support från Tailscale som kräver sådan telemetri för felsökning." 70 | } 71 | }, 72 | "info": { 73 | "online": "Online", 74 | "version": "Tailscale-version", 75 | "health": "Tailscale-status", 76 | "login": "Inloggad", 77 | "netmap": "I nätverkskartan", 78 | "key_expire": "Nyckelutgång", 79 | "tags": "Taggar", 80 | "hostname": "Värdnamn", 81 | "dns": "DNS-namn", 82 | "ip": "Tailscale-IP:er", 83 | "magicdns": "MagicDNS-suffix", 84 | "routes": "Annonserade rutter", 85 | "accept_routes": "Acceptera rutter", 86 | "accept_dns": "Acceptera DNS", 87 | "run_ssh": "Tailscale SSH", 88 | "advertise_exit_node": "Kör som exit-nod", 89 | "use_exit_node": "Använd exit-nod", 90 | "exit_node_local": "Tillåt LAN-åtkomst när exit-nod används", 91 | "unapproved": "Behöver godkännande i admin-konsolen", 92 | "connected_via": "Ansluten via Tailscale", 93 | "funnel_port": "Funnel-port för WebGUI", 94 | "port_in_use": "Port används", 95 | "peer_relay": "Peer-reläport", 96 | "auto_update": "Automatisk uppdatering", 97 | "lock": { 98 | "node_key": "Nodnyckel", 99 | "public_key": "Publik nyckel", 100 | "signed": "Nodnyckel signerad", 101 | "signing": "Är signeringsnod" 102 | } 103 | }, 104 | "warnings": { 105 | "key_expiration": "Tailscale-nyckeln kommer att utgå om %s dagar den %s.", 106 | "netbios": "NetBIOS är aktiverat i SMB-inställningar - detta kan förhindra åtkomst till delade mappar via Tailscale.", 107 | "lock": "Tailnet har lås aktiverat, men denna nod är inte signerad. Den kommer inte kunna kommunicera med tailnet.", 108 | "funnel": "Att aktivera Tailscale Funnel för Unraid WebGUI exponerar din server mot internet och ökar avsevärt risken för obehörig åtkomst och potentiella attacker. Denna funktion bör endast aktiveras om du fullt ut förstår säkerhetsriskerna. Det rekommenderade/säkra sättet för fjärråtkomst är att installera Tailscale på de enheter du planerar att använda för att komma åt WebGUI, istället för att aktivera Funnel.", 109 | "subnet": "Att acceptera Tailscale-subnät på din Unraid-server kan störa den lokala nätverksanslutningen i vissa nätverkskonfigurationer. Att acceptera rutter krävs inte för att din Unraid-server ska fungera som en subnätsrouter eller exitnod. Aktivera endast detta alternativ om din Unraid-server behöver ansluta till fjärrsubnät som annonseras av andra enheter.", 110 | "dns": "Att aktivera Tailscale MagicDNS på din server kan störa namnuppslagning i Docker-containrar och potentiellt orsaka anslutningsproblem för applikationer. MagicDNS behöver inte vara aktiverat på servern för att du ska kunna nå din Unraid-server med MagicDNS-namn (t.ex. \"unraid.tailnet.ts.net\") från andra enheter. Att aktivera \"Lägg till Peers i /etc/hosts\" är ett säkrare alternativ som gör det möjligt att använda Tailscale-namn på servern.", 111 | "caution": "Fortsätt med försiktighet och säkerställ att du förstår konsekvenserna av denna ändring innan du fortsätter.", 112 | "more_info": "Mer information:", 113 | "peer_relay_no_acl": "Inte konfigurerad i Tailnet-policy (åtkomstkontroller).", 114 | "tpm": "När TPM aktiveras låses Tailscale-nodnyckeln till den specifika hårdvaran på denna enhet. Om TPM senare inaktiveras kommer Tailscale-nodnyckeln att bli ogiltig och enheten måste återautentiseras mot Tailscale. Det är också möjligt att TPM kan låsas, vilket kan störa Tailscale-anslutningen och kräva återautentisering." 115 | }, 116 | "lock": { 117 | "sign": "Signera noder", 118 | "signing_node": "Detta är en signeringsnod för tailnet.", 119 | "signing_instructions": "Följande noder är för närvarande utestängda från tailnet. Markera kryssrutan för de noder du vill lägga till, och klicka sedan på Signera för att lägga till noden i tailnet.", 120 | "signed_node": "Ditt tailnet har lås aktiverat och den aktuella noden är signerad. Denna nod kan kommunicera med tailnet.", 121 | "make_signing": "Om du vill göra denna till en signeringsnod måste du lita på följande nyckel från en signeringsnod:", 122 | "unsigned": "Ditt tailnet har lås aktiverat och den aktuella noden är inte signerad. Denna nod kan inte kommunicera med tailnet.", 123 | "unsigned_instructions": "För att tillåta denna nod att kommunicera måste du lita på följande nyckel från en signeringsnod", 124 | "disabled": "Ditt tailnet har inte lås aktiverat." 125 | }, 126 | "status_page": { 127 | "exit_node": "Exit-nod", 128 | "connection_type": "Anslutningstyp", 129 | "connection_addr": "Anslutning", 130 | "tx_bytes": "Tx-bytes", 131 | "rx_bytes": "Rx-bytes", 132 | "relay": "Relä", 133 | "direct": "Direkt", 134 | "exit_active": "Aktiv", 135 | "exit_available": "Tillgänglig", 136 | "idle": "Vilande", 137 | "offline": "Offline", 138 | "active": "Aktiv", 139 | "login_name": "Inloggningsnamn", 140 | "shared": "Delad användare", 141 | "action": "Åtgärd" 142 | } 143 | } -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/locales/pl_PL.json: -------------------------------------------------------------------------------- 1 | { 2 | "yes": "Tak", 3 | "no": "Nie", 4 | "ignore": "Ignoruj", 5 | "erase": "Usuń", 6 | "confirm": "Potwierdź", 7 | "download": "Pobierz", 8 | "restart": "Uruchom ponownie", 9 | "apply": "Zastosuj", 10 | "back": "Wstecz", 11 | "status": "Status", 12 | "connection": "Połączenie", 13 | "unknown": "Nieznane", 14 | "none": "Brak", 15 | "disabled": "Wyłączone", 16 | "enabled": "Włączone", 17 | "disable": "Wyłącz", 18 | "enable": "Włącz", 19 | "cancel": "Anuluj", 20 | "accept": "Akceptuj", 21 | "sign": "Podpisz", 22 | "login": "Zaloguj", 23 | "add": "Dodaj", 24 | "remove": "Usuń", 25 | "tailnet": "Tailnet", 26 | "configuration": "Konfiguracja", 27 | "needs_login": "To urządzenie musi być zalogowane do Tailscale. Odśwież tę stronę po zalogowaniu, aby zobaczyć status.", 28 | "tailscale_disabled": "Tailscale jest obecnie wyłączony. Można go włączyć w zakładce Ustawienia.", 29 | "tailscale_lock": "Blokada Tailscale", 30 | "warning": "Ostrzeżenie", 31 | "save": "Zapisz", 32 | "settings": { 33 | "basic": "Widok podstawowy", 34 | "advanced": "Widok zaawansowany", 35 | "system_settings": "Ustawienia systemowe", 36 | "enable_tailscale": "Włącz Tailscale", 37 | "unraid_listen": "Usługi Unraid nasłuchują na adresie IP Tailscale", 38 | "ip_forward": "Włącz przekazywanie IP", 39 | "taildrop": "Lokalizacja Taildrop", 40 | "services": "Usługi Tailscale", 41 | "wireguard": "Port Wireguard", 42 | "outbound_network": "Zaawansowane opcje sieciowe", 43 | "subnets": "Zezwól na podsieci Tailscale", 44 | "dns": "Zezwól na ustawienia DNS Tailscale", 45 | "save": "Zapisz ustawienia", 46 | "restart": "Restartuj Tailscale", 47 | "erase": "Usuń konfigurację Tailscale", 48 | "diagnostics": "Diagnostyka wtyczki", 49 | "reauthenticate": "Ponowna autoryzacja", 50 | "funnel": "Zezwól na Tailscale Funnel", 51 | "hosts": "Dodaj peerów do /etc/hosts", 52 | "no_logs_no_support": "Brak dzienników, brak wsparcia", 53 | "tpm": "Zezwól TPM na szyfrowanie klucza węzła", 54 | "context": { 55 | "tpm": "Umożliwia użycie TPM (Trusted Platform Module) do bezpiecznego przechowywania klucza węzła Tailscale. Zwiększa to bezpieczeństwo, chroniąc klucz węzła przed łatwym wydobyciem i zapewniając, że tylko autoryzowany sprzęt może mieć do niego dostęp. Włączenie tej opcji wymaga TPM 2.0. Jeśli system nie posiada kompatybilnego TPM, opcja ta nie ma wpływu.", 56 | "unraid_listen": "Konfiguruje usługi Unraid (SSH, WebGUI, SMB itd.), aby nasłuchiwały na adresach Tailscale.", 57 | "ip_forward": "Ustawia net.ipv4.ip_forward oraz net.ipv6.conf.all.forwarding na 1 w sysctl. Ta zmiana następuje natychmiast po włączeniu.", 58 | "taildrop": "Określ ścieżkę dla przychodzących plików Taildrop.", 59 | "dns": "Pozwala na włączenie DNS Tailscale przez CLI lub WebGUI. Po wyłączeniu, DNS Tailscale będzie wyłączony po uruchomieniu Tailscale.", 60 | "subnets": "Pozwala na włączenie tras Tailscale przez CLI lub WebGUI. Po wyłączeniu, trasy Tailscale będą wyłączone po uruchomieniu Tailscale.", 61 | "wireguard": "Zmień port używany do połączeń Wireguard. Zazwyczaj nie ma potrzeby go zmieniać.", 62 | "erase": "Wylogowuje z Tailscale i przywraca wszystkie ustawienia do domyślnych", 63 | "restart": "Restartuje demona Tailscale i ponownie stosuje ustawienia.", 64 | "diagnostics": "Pobierz diagnostykę (to może chwilę potrwać)", 65 | "save": "Tailscale zostanie zrestartowany po zastosowaniu zmian", 66 | "reauthenticate": "Wymuś ponowną autoryzację Tailscale.", 67 | "funnel": "Pozwala na włączenie Tailscale Funnel przez WebGUI. Po wyłączeniu, Tailscale Funnel zostanie wyłączony.", 68 | "hosts": "Dodaje peerów Tailscale do /etc/hosts w celu rozwiązywania nazw. Jest to przydatne, jeśli chcesz używać nazw DNS Tailnet, bez potencjalnych komplikacji wynikających z włączenia DNS Tailscale na serwerze.", 69 | "no_logs_no_support": "Wyłącza telemetrię Tailscale i rezygnujesz tym samym z otrzymania wsparcia od Tailscale, które wymagałoby tej telemetrii do debugowania." 70 | } 71 | }, 72 | "info": { 73 | "online": "Online", 74 | "version": "Wersja Tailscale", 75 | "health": "Stan Tailscale", 76 | "login": "Zalogowano", 77 | "netmap": "W mapie sieci", 78 | "key_expire": "Wygaśnięcie klucza", 79 | "tags": "Tagi", 80 | "hostname": "Nazwa hosta", 81 | "dns": "Nazwa DNS", 82 | "ip": "Adresy IP Tailscale", 83 | "magicdns": "Sufiks MagicDNS", 84 | "routes": "Reklamowane trasy", 85 | "accept_routes": "Akceptuj trasy", 86 | "accept_dns": "Akceptuj DNS", 87 | "run_ssh": "Tailscale SSH", 88 | "advertise_exit_node": "Działaj jako węzeł wyjściowy", 89 | "use_exit_node": "Użyj węzła wyjściowego", 90 | "exit_node_local": "Zezwól na dostęp do LAN podczas korzystania z węzła wyjściowego", 91 | "unapproved": "Wymaga zatwierdzenia w konsoli administracyjnej", 92 | "connected_via": "Połączono przez Tailscale", 93 | "funnel_port": "Port Tailscale Funnel dla WebGUI", 94 | "port_in_use": "Port w użyciu", 95 | "peer_relay": "Port przekaźnika peer", 96 | "auto_update": "Automatyczna aktualizacja", 97 | "lock": { 98 | "node_key": "Klucz węzła", 99 | "public_key": "Klucz publiczny", 100 | "signed": "Klucz węzła podpisany", 101 | "signing": "Czy jest to węzeł podpisujący" 102 | } 103 | }, 104 | "warnings": { 105 | "key_expiration": "Klucz Tailscale wygaśnie za %s dni, dnia %s.", 106 | "netbios": "NetBIOS jest włączony w ustawieniach SMB - może to uniemożliwić dostęp do udziałów przez Tailscale.", 107 | "lock": "Sieć tailnet ma włączoną blokadę, ale ten węzeł nie został podpisany. Nie będzie mógł komunikować się z tailnetem.", 108 | "funnel": "Włączenie Tailscale Funnel dla WebGUI Unraid wystawia Twój serwer na internet, znacząco zwiększając ryzyko nieautoryzowanego dostępu oraz potencjalnych ataków. Funkcję tę należy włączać jedynie, jeśli w pełni rozumiesz jej wpływ na bezpieczeństwo. Zalecaną i bezpieczniejszą metodą zdalnego dostępu jest instalacja Tailscale na urządzeniach, z których planujesz korzystać z WebGUI, zamiast włączać Tailscale Funnel.", 109 | "subnet": "Akceptowanie podsieci Tailscale na Twoim serwerze Unraid może zakłócić łączność w sieci lokalnej w niektórych konfiguracjach. Akceptacja tras nie jest wymagana, aby Unraid działał jako router podsieci lub węzeł wyjściowy. Włącz tę opcję tylko wtedy, gdy Twój serwer Unraid potrzebuje połączyć się z podsieciami reklamowanymi przez inne urządzenia.", 110 | "dns": "Włączenie MagicDNS Tailscale na serwerze może zakłócić rozwiązywanie nazw w kontenerach Docker, co może powodować problemy z łącznością aplikacji. Nie musisz włączać MagicDNS na serwerze, aby uzyskiwać dostęp do serwera Unraid przy użyciu nazw MagicDNS (np. \"unraid.tailnet.ts.net\") z innych urządzeń. Włączenie opcji \"Dodaj peerów do /etc/hosts\" to bezpieczniejsza alternatywa, która pozwala na używanie nazw Tailscale na serwerze.", 111 | "caution": "Zachowaj ostrożność i upewnij się, że rozumiesz konsekwencje tej zmiany przed kontynuacją.", 112 | "more_info": "Więcej informacji:", 113 | "peer_relay_no_acl": "Niezkonfigurowane w polityce Tailnet (kontrola dostępu).", 114 | "tpm": "Włączenie TPM przypisuje klucz węzła Tailscale do konkretnego sprzętu tego urządzenia. Jeśli TPM zostanie później wyłączony, klucz węzła Tailscale stanie się nieprawidłowy i urządzenie będzie wymagać ponownej autoryzacji w Tailscale. Istnieje również możliwość zablokowania TPM, co może zakłócić łączność Tailscale i wymagać ponownej autoryzacji." 115 | }, 116 | "lock": { 117 | "sign": "Podpisz węzły", 118 | "signing_node": "To jest węzeł podpisujący dla tailnet.", 119 | "signing_instructions": "Następujące węzły są aktualnie zablokowane w tailnet. Zaznacz dowolne węzły, które chcesz dodać, a następnie kliknij przycisk Podpisz, aby dodać węzeł do tailnet.", 120 | "signed_node": "Twój tailnet ma włączoną blokadę i bieżący węzeł jest podpisany. Ten węzeł może komunikować się z tailnet.", 121 | "make_signing": "Jeśli chcesz uczynić ten węzeł podpisującym, musisz zaufać następującemu kluczowi z węzła podpisującego:", 122 | "unsigned": "Twój tailnet ma włączoną blokadę i bieżący węzeł nie jest podpisany. Ten węzeł nie może komunikować się z tailnet.", 123 | "unsigned_instructions": "Aby ten węzeł mógł się komunikować, musisz zaufać następującemu kluczowi z węzła podpisującego", 124 | "disabled": "Twój tailnet nie ma włączonej blokady." 125 | }, 126 | "status_page": { 127 | "exit_node": "Węzeł wyjściowy", 128 | "connection_type": "Typ połączenia", 129 | "connection_addr": "Połączenie", 130 | "tx_bytes": "Bajty Tx", 131 | "rx_bytes": "Bajty Rx", 132 | "relay": "Przekaźnik", 133 | "direct": "Bezpośrednio", 134 | "exit_active": "Aktywny", 135 | "exit_available": "Dostępny", 136 | "idle": "Bezczynny", 137 | "offline": "Offline", 138 | "active": "Aktywny", 139 | "login_name": "Nazwa logowania", 140 | "shared": "Użytkownik z udostępnionym dostępem", 141 | "action": "Akcja" 142 | } 143 | } -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/locales/uk_UA.json: -------------------------------------------------------------------------------- 1 | { 2 | "yes": "Так", 3 | "no": "Ні", 4 | "ignore": "Ігнорувати", 5 | "erase": "Стерти", 6 | "confirm": "Підтвердити", 7 | "download": "Завантажити", 8 | "restart": "Перезапустити", 9 | "apply": "Застосувати", 10 | "back": "Назад", 11 | "status": "Статус", 12 | "connection": "З'єднання", 13 | "unknown": "Невідомо", 14 | "none": "Відсутньо", 15 | "disabled": "Вимкнено", 16 | "enabled": "Увімкнено", 17 | "disable": "Вимкнути", 18 | "enable": "Увімкнути", 19 | "cancel": "Скасувати", 20 | "accept": "Прийняти", 21 | "sign": "Підписати", 22 | "login": "Вхід", 23 | "add": "Додати", 24 | "remove": "Видалити", 25 | "tailnet": "Tailnet", 26 | "configuration": "Конфігурація", 27 | "needs_login": "Цьому пристрою потрібно увійти в Tailscale. Оновіть цю сторінку після входу для перегляду статусу.", 28 | "tailscale_disabled": "Tailscale наразі вимкнений. Його можна увімкнути через вкладку Налаштування.", 29 | "tailscale_lock": "Блокування Tailscale", 30 | "warning": "Попередження", 31 | "save": "Зберегти", 32 | "settings": { 33 | "basic": "Базовий вигляд", 34 | "advanced": "Розширений вигляд", 35 | "system_settings": "Системні налаштування", 36 | "enable_tailscale": "Увімкнути Tailscale", 37 | "unraid_listen": "Служби Unraid слухають на IP Tailscale", 38 | "ip_forward": "Увімкнути проброс IP", 39 | "taildrop": "Розташування Taildrop", 40 | "services": "Служби Tailscale", 41 | "wireguard": "Порт Wireguard", 42 | "outbound_network": "Розширені мережеві параметри", 43 | "subnets": "Дозволити підмережі Tailscale", 44 | "dns": "Дозволити налаштування DNS Tailscale", 45 | "save": "Зберегти налаштування", 46 | "restart": "Перезапустити Tailscale", 47 | "erase": "Стерти конфігурацію Tailscale", 48 | "diagnostics": "Діагностика плагіна", 49 | "reauthenticate": "Перевірити автентифікацію ще раз", 50 | "funnel": "Дозволити Tailscale Funnel", 51 | "hosts": "Додати вузли до /etc/hosts Tailscale", 52 | "no_logs_no_support": "Без журналів — без підтримки", 53 | "tpm": "Дозволити TPM шифрувати ключ вузла", 54 | "context": { 55 | "tpm": "Увімкнення використання TPM (модуля надійної платформи) для захищеного зберігання ключа вузла Tailscale. Це підвищує безпеку, захищаючи ключ вузла від легкого вилучення та забезпечуючи доступ до нього лише на авторизованому обладнанні. Увімкнення цієї опції потребує TPM 2.0. Якщо система не має сумісного TPM, ця функція не діє.", 56 | "unraid_listen": "Налаштовує служби Unraid (SSH, WebGUI, SMB тощо) для прослуховування на адресах Tailscale.", 57 | "ip_forward": "Встановлює net.ipv4.ip_forward та net.ipv6.conf.all.forwarding у 1 в sysctl. Зміни застосовуються негайно після увімкнення.", 58 | "taildrop": "Укажіть шлях для вхідних файлів Taildrop.", 59 | "dns": "Дозволяє включити DNS Tailscale через CLI або WebGUI. Якщо вимкнено, DNS Tailscale буде вимкнено при старті Tailscale.", 60 | "subnets": "Дозволяє включити маршрути Tailscale через CLI або WebGUI. Якщо вимкнено, маршрути Tailscale будуть вимкнені при старті Tailscale.", 61 | "wireguard": "Змініть порт, який використовується для з'єднань Wireguard. Зазвичай цю опцію змінювати не потрібно.", 62 | "erase": "Вихід з Tailscale і скидання всіх налаштувань за замовчуванням", 63 | "restart": "Перезапустіть демон Tailscale і повторно застосуйте налаштування.", 64 | "diagnostics": "Завантажити діагностичну інформацію (це може зайняти певний час)", 65 | "save": "Tailscale буде перезапущено під час застосування змін", 66 | "reauthenticate": "Примусово виконати повторну автентифікацію Tailscale.", 67 | "funnel": "Дозволяє увімкнути Tailscale Funnel через WebGUI. Якщо вимкнено, Tailscale Funnel буде вимкнено.", 68 | "hosts": "Додає вузли Tailscale до /etc/hosts для вирішення імен. Це корисно, якщо ви хочете використовувати DNS-імена Tailnet, без можливих ускладнень від увімкнення DNS Tailscale на сервері.", 69 | "no_logs_no_support": "Вимикає телеметрію Tailscale і скасовує вашу участь у отриманні підтримки від Tailscale, яка потребує такої телеметрії для налагодження." 70 | } 71 | }, 72 | "info": { 73 | "online": "Онлайн", 74 | "version": "Версія Tailscale", 75 | "health": "Стан Tailscale", 76 | "login": "Увійшов у систему", 77 | "netmap": "У мережевій карті", 78 | "key_expire": "Термін дії ключа", 79 | "tags": "Теги", 80 | "hostname": "Ім'я хоста", 81 | "dns": "DNS-ім'я", 82 | "ip": "IP-адреси Tailscale", 83 | "magicdns": "Суфікс MagicDNS", 84 | "routes": "Рекламовані маршрути", 85 | "accept_routes": "Приймати маршрути", 86 | "accept_dns": "Приймати DNS", 87 | "run_ssh": "Tailscale SSH", 88 | "advertise_exit_node": "Використовувати як вихідний вузол", 89 | "use_exit_node": "Використовувати вихідний вузол", 90 | "exit_node_local": "Дозволити LAN-доступ під час використання вихідного вузла", 91 | "unapproved": "Потрібне підтвердження в адмін-консолі", 92 | "connected_via": "Підключено через Tailscale", 93 | "funnel_port": "Порт Funnel для WebGUI", 94 | "port_in_use": "Порт використовується", 95 | "peer_relay": "Порт ретрансляції пірів", 96 | "auto_update": "Автоматичне оновлення", 97 | "lock": { 98 | "node_key": "Ключ вузла", 99 | "public_key": "Публічний ключ", 100 | "signed": "Ключ вузла підписаний", 101 | "signing": "Підписуючий вузол" 102 | } 103 | }, 104 | "warnings": { 105 | "key_expiration": "Ключ Tailscale закінчиться через %s днiв %s.", 106 | "netbios": "NetBIOS увімкнений у налаштуваннях SMB – це може завадити доступу до спільних папок через Tailscale.", 107 | "lock": "У tailnet увімкнено блокування, але цей вузол не підписано. Він не зможе спілкуватися з tailnet.", 108 | "funnel": "Увімкнення Tailscale Funnel для WebGUI Unraid відкриває ваш сервер для доступу з Інтернету, що суттєво підвищує ризик несанкціонованого доступу та можливих атак. Увімкніть цю функцію лише в тому разі, якщо ви повністю розумієте наслідки для безпеки. Рекомендований/безпечний підхід до віддаленого доступу — встановити Tailscale на пристрої, за допомогою яких ви плануєте отримувати доступ до WebGUI, замість увімкнення Funnel.", 109 | "subnet": "Прийняття підмереж Tailscale на вашому сервері Unraid може порушити локальну мережеву підключуваність у певних мережевих конфігураціях. Приймати маршрути необовʼязково для роботи вашого сервера Unraid як маршрутизатора підмережі чи вузла виходу. Увімкніть цю опцію лише якщо ваш сервер Unraid має підключатися до віддалених підмереж, що рекламуються іншими пристроями.", 110 | "dns": "Увімкнення MagicDNS Tailscale на вашому сервері може порушити вирішення імен у контейнерах Docker, що потенційно може спричинити проблеми з підключенням для застосунків. MagicDNS не потрібно вмикати на сервері, щоб отримати доступ до вашого сервера Unraid за іменами MagicDNS (наприклад, 'unraid.tailnet.ts.net') з інших пристроїв. Увімкнення \"Додати вузли до /etc/hosts\" є безпечнішою альтернативою, яка дозволяє використовувати імена Tailscale на сервері.", 111 | "caution": "Дійте обережно і переконайтесь, що ви розумієте наслідки цієї зміни перед тим, як продовжити.", 112 | "more_info": "Детальніше:", 113 | "peer_relay_no_acl": "Не налаштовано в політиці Tailnet (контролі доступу).", 114 | "tpm": "Увімкнення TPM прив’язує ключ вузла Tailscale до конкретного обладнання цього пристрою. Якщо TPM буде згодом вимкнено, ключ вузла Tailscale стане недійсним, і пристрій потрібно буде повторно автентифікувати в Tailscale. Також можливе блокування TPM, що може призвести до порушення підключення Tailscale і вимагатиме повторної автентифікації." 115 | }, 116 | "lock": { 117 | "sign": "Підписати вузли", 118 | "signing_node": "Це підписуючий вузол для tailnet.", 119 | "signing_instructions": "Наступні вузли наразі заблоковані від tailnet. Відмітьте будь-який вузол, який хочете додати, а потім натисніть кнопку \"Підписати\", щоб додати цей вузол до tailnet.", 120 | "signed_node": "У вашому tailnet увімкнено блокування, і поточний вузол підписано. Цей вузол може спілкуватися з tailnet.", 121 | "make_signing": "Щоб зробити це підписуючим вузлом, потрібно засвідчити наступний ключ з підписуючого вузла:", 122 | "unsigned": "У вашому tailnet увімкнено блокування, а поточний вузол не підписано. Цей вузол не може спілкуватися з tailnet.", 123 | "unsigned_instructions": "Щоб дозволити цьому вузлу спілкуватися, потрібно засвідчити наступний ключ з підписуючого вузла", 124 | "disabled": "У вашому tailnet блокування не увімкнено." 125 | }, 126 | "status_page": { 127 | "exit_node": "Вихідний вузол", 128 | "connection_type": "Тип з'єднання", 129 | "connection_addr": "З'єднання", 130 | "tx_bytes": "Передано байтів", 131 | "rx_bytes": "Прийнято байтів", 132 | "relay": "Ретранслятор", 133 | "direct": "Прямий", 134 | "exit_active": "Активно", 135 | "exit_available": "Доступно", 136 | "idle": "Бездіяльний", 137 | "offline": "Офлайн", 138 | "active": "Активний", 139 | "login_name": "Ім'я для входу", 140 | "shared": "Користувач із спільним доступом", 141 | "action": "Дія" 142 | } 143 | } -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/locales/pt_BR.json: -------------------------------------------------------------------------------- 1 | { 2 | "yes": "Sim", 3 | "no": "Não", 4 | "ignore": "Ignorar", 5 | "erase": "Apagar", 6 | "confirm": "Confirmar", 7 | "download": "Baixar", 8 | "restart": "Reiniciar", 9 | "apply": "Aplicar", 10 | "back": "Voltar", 11 | "status": "Status", 12 | "connection": "Conexão", 13 | "unknown": "Desconhecido", 14 | "none": "Nenhum", 15 | "disabled": "Desativado", 16 | "enabled": "Ativado", 17 | "disable": "Desativar", 18 | "enable": "Ativar", 19 | "cancel": "Cancelar", 20 | "accept": "Aceitar", 21 | "sign": "Assinar", 22 | "login": "Login", 23 | "add": "Adicionar", 24 | "remove": "Remover", 25 | "tailnet": "Tailnet", 26 | "configuration": "Configuração", 27 | "needs_login": "Este dispositivo precisa estar logado no Tailscale. Recarregue esta página após o login para ver o status.", 28 | "tailscale_disabled": "Tailscale está atualmente desativado. Pode ser ativado através da aba Configurações.", 29 | "tailscale_lock": "Bloqueio do Tailscale", 30 | "warning": "Aviso", 31 | "save": "Salvar", 32 | "settings": { 33 | "basic": "Visualização Básica", 34 | "advanced": "Visualização Avançada", 35 | "system_settings": "Configurações do Sistema", 36 | "enable_tailscale": "Ativar Tailscale", 37 | "unraid_listen": "Serviços Unraid escutam no IP do Tailscale", 38 | "ip_forward": "Ativar Encaminhamento de IP", 39 | "taildrop": "Localização do Taildrop", 40 | "services": "Serviços do Tailscale", 41 | "wireguard": "Porta do Wireguard", 42 | "outbound_network": "Opções Avançadas de Rede", 43 | "subnets": "Permitir Sub-redes do Tailscale", 44 | "dns": "Permitir configurações de DNS do Tailscale", 45 | "save": "Salvar Configurações", 46 | "restart": "Reiniciar Tailscale", 47 | "erase": "Apagar Configuração do Tailscale", 48 | "diagnostics": "Diagnóstico do Plugin", 49 | "reauthenticate": "Reautenticar", 50 | "funnel": "Permitir Funnel do Tailscale", 51 | "hosts": "Adicionar pares ao /etc/hosts", 52 | "no_logs_no_support": "Sem Registros Sem Suporte", 53 | "tpm": "Permitir que o TPM criptografe a chave do nó", 54 | "context": { 55 | "tpm": "Ativa o uso de um TPM (Trusted Platform Module) para armazenamento seguro da chave do nó do Tailscale. Isso melhora a segurança ao proteger a chave do nó contra extração fácil, garantindo que apenas o hardware autorizado possa acessá-la. Ativar esta opção requer TPM 2.0. Não tem efeito se o sistema não tiver um TPM compatível.", 56 | "unraid_listen": "Configura os serviços Unraid (SSH, WebGUI, SMB, etc.) para escutarem nos endereços do Tailscale.", 57 | "ip_forward": "Define net.ipv4.ip_forward e net.ipv6.conf.all.forwarding como 1 no sysctl. Esta alteração ocorre imediatamente ao ser ativada.", 58 | "taildrop": "Especifique o caminho para os arquivos recebidos do Taildrop.", 59 | "dns": "Permite ativar o DNS do Tailscale via CLI ou WebGUI. Se desativado, o DNS do Tailscale será desativado ao iniciar o Tailscale.", 60 | "subnets": "Permite ativar rotas do Tailscale via CLI ou WebGUI. Se desativado, as rotas do Tailscale serão desativadas ao iniciar o Tailscale.", 61 | "wireguard": "Altera a porta usada para conexões Wireguard. Normalmente não é necessário alterar.", 62 | "erase": "Faz logout do Tailscale e redefine todas as configurações para o padrão", 63 | "restart": "Reinicia o daemon do Tailscale e reaplica as configurações.", 64 | "diagnostics": "Baixar diagnóstico (isso pode levar algum tempo para completar)", 65 | "save": "O Tailscale será reiniciado ao aplicar as alterações", 66 | "reauthenticate": "Forçar uma reautenticação do Tailscale.", 67 | "funnel": "Permite que o Funnel do Tailscale seja ativado pela WebGUI. Se desativado, o Funnel do Tailscale será desativado.", 68 | "hosts": "Adiciona os pares do Tailscale ao /etc/hosts para resolução de nomes. Isso é útil se você quiser usar nomes DNS do Tailnet, sem as possíveis complicações de ativar o DNS do Tailscale no servidor.", 69 | "no_logs_no_support": "Desativa a telemetria do Tailscale e impede que você receba suporte do Tailscale que exija essa telemetria para depuração." 70 | } 71 | }, 72 | "info": { 73 | "online": "Online", 74 | "version": "Versão do Tailscale", 75 | "health": "Estado do Tailscale", 76 | "login": "Logado", 77 | "netmap": "No Mapa de Rede", 78 | "key_expire": "Expiração da Chave", 79 | "tags": "Tags", 80 | "hostname": "Nome do Host", 81 | "dns": "Nome DNS", 82 | "ip": "IPs do Tailscale", 83 | "magicdns": "Sufixo MagicDNS", 84 | "routes": "Rotas Anunciadas", 85 | "accept_routes": "Aceitar Rotas", 86 | "accept_dns": "Aceitar DNS", 87 | "run_ssh": "Tailscale SSH", 88 | "advertise_exit_node": "Atuar como Nó de Saída", 89 | "use_exit_node": "Usar Nó de Saída", 90 | "exit_node_local": "Permitir acesso à LAN ao usar Nó de Saída", 91 | "unapproved": "Precisa de aprovação no console de administração", 92 | "connected_via": "Conectado via Tailscale", 93 | "funnel_port": "Porta do Funnel para WebGUI", 94 | "port_in_use": "Porta em uso", 95 | "peer_relay": "Porta de retransmissão de peer", 96 | "auto_update": "Atualização Automática", 97 | "lock": { 98 | "node_key": "Chave do Nó", 99 | "public_key": "Chave Pública", 100 | "signed": "Chave do Nó Assinada", 101 | "signing": "É Nó de Assinatura" 102 | } 103 | }, 104 | "warnings": { 105 | "key_expiration": "A chave do Tailscale irá expirar em %s dias em %s.", 106 | "netbios": "O NetBIOS está ativado em Configurações SMB - isto pode impedir o acesso a compartilhamentos via Tailscale.", 107 | "lock": "O tailnet possui bloqueio ativado, mas este nó não foi assinado. Ele não poderá se comunicar com o tailnet.", 108 | "funnel": "Ativar o Funnel do Tailscale na WebGUI do Unraid expõe seu servidor à internet, aumentando significativamente o risco de acesso não autorizado e possíveis ataques. Esse recurso só deve ser ativado se você compreender totalmente o impacto na segurança. A abordagem recomendada/segura para acesso remoto é instalar o Tailscale nos dispositivos que você pretende usar para acessar a WebGUI, em vez de ativar o Funnel.", 109 | "subnet": "Aceitar sub-redes do Tailscale no seu servidor Unraid pode afetar a conectividade da rede local em determinadas configurações. Aceitar rotas não é necessário para que seu servidor Unraid funcione como um roteador de sub-rede ou nó de saída. Só ative esta opção se seu servidor Unraid precisar se conectar a sub-redes remotas anunciadas por outros dispositivos.", 110 | "dns": "Ativar o MagicDNS do Tailscale no seu servidor pode prejudicar a resolução de nomes dentro dos containers Docker, causando possíveis problemas de conectividade para aplicativos. Não é necessário ativar o MagicDNS no servidor para acessar o seu servidor Unraid usando nomes MagicDNS (por exemplo, 'unraid.tailnet.ts.net') a partir de outros dispositivos. Ativar a opção 'Adicionar pares ao /etc/hosts' é uma alternativa mais segura que permite o uso dos nomes do Tailscale no servidor.", 111 | "caution": "Proceda com cautela e certifique-se de que você entende as implicações desta alteração antes de continuar.", 112 | "more_info": "Para mais informações:", 113 | "peer_relay_no_acl": "Não configurado na política do Tailnet (controles de acesso).", 114 | "tpm": "Ativar o TPM vincula a chave do nó do Tailscale ao hardware específico deste dispositivo. Se o TPM for posteriormente desativado, a chave do nó do Tailscale se tornará inválida e o dispositivo precisará ser reautenticado no Tailscale. Também é possível que o TPM seja bloqueado, o que pode interromper a conectividade com o Tailscale e exigir nova autenticação." 115 | }, 116 | "lock": { 117 | "sign": "Assinar Nós", 118 | "signing_node": "Este é um nó de assinatura para o tailnet.", 119 | "signing_instructions": "Os seguintes nós estão atualmente bloqueados fora do tailnet. Marque a caixa dos nós que você deseja adicionar e clique no botão Assinar para adicionar o nó ao tailnet.", 120 | "signed_node": "Seu tailnet possui bloqueio ativado e o nó atual está assinado. Este nó pode se comunicar com o tailnet.", 121 | "make_signing": "Se desejar tornar este um nó de assinatura, será necessário confiar na chave abaixo de um nó de assinatura:", 122 | "unsigned": "Seu tailnet possui bloqueio ativado e o nó atual não está assinado. Este nó não pode se comunicar com o tailnet.", 123 | "unsigned_instructions": "Para permitir que este nó se comunique, você precisará confiar na chave abaixo de um nó de assinatura", 124 | "disabled": "Seu tailnet não possui bloqueio ativado." 125 | }, 126 | "status_page": { 127 | "exit_node": "Nó de Saída", 128 | "connection_type": "Tipo de Conexão", 129 | "connection_addr": "Conexão", 130 | "tx_bytes": "Bytes de Envio (Tx)", 131 | "rx_bytes": "Bytes de Recepção (Rx)", 132 | "relay": "Relé", 133 | "direct": "Direto", 134 | "exit_active": "Ativo", 135 | "exit_available": "Disponível", 136 | "idle": "Ocioso", 137 | "offline": "Offline", 138 | "active": "Ativo", 139 | "login_name": "Nome de Login", 140 | "shared": "Usuário Compartilhado", 141 | "action": "Ação" 142 | } 143 | } -------------------------------------------------------------------------------- /src/usr/local/emhttp/plugins/tailscale/locales/pt_PT.json: -------------------------------------------------------------------------------- 1 | { 2 | "yes": "Sim", 3 | "no": "Não", 4 | "ignore": "Ignorar", 5 | "erase": "Apagar", 6 | "confirm": "Confirmar", 7 | "download": "Baixar", 8 | "restart": "Reiniciar", 9 | "apply": "Aplicar", 10 | "back": "Voltar", 11 | "status": "Status", 12 | "connection": "Conexão", 13 | "unknown": "Desconhecido", 14 | "none": "Nenhum", 15 | "disabled": "Desativado", 16 | "enabled": "Ativado", 17 | "disable": "Desativar", 18 | "enable": "Ativar", 19 | "cancel": "Cancelar", 20 | "accept": "Aceitar", 21 | "sign": "Assinar", 22 | "login": "Login", 23 | "add": "Adicionar", 24 | "remove": "Remover", 25 | "tailnet": "Tailnet", 26 | "configuration": "Configuração", 27 | "needs_login": "Este dispositivo precisa estar logado no Tailscale. Atualize esta página após o login para ver o status.", 28 | "tailscale_disabled": "Tailscale está atualmente desativado. Ele pode ser ativado pela guia Configurações.", 29 | "tailscale_lock": "Bloqueio do Tailscale", 30 | "warning": "Aviso", 31 | "save": "Salvar", 32 | "settings": { 33 | "basic": "Visualização Básica", 34 | "advanced": "Visualização Avançada", 35 | "system_settings": "Configurações do Sistema", 36 | "enable_tailscale": "Ativar Tailscale", 37 | "unraid_listen": "Serviços Unraid ouvem no IP do Tailscale", 38 | "ip_forward": "Ativar Reencaminhamento de IP", 39 | "taildrop": "Localização do Taildrop", 40 | "services": "Serviços do Tailscale", 41 | "wireguard": "Porta Wireguard", 42 | "outbound_network": "Opções avançadas de rede", 43 | "subnets": "Permitir Sub-redes do Tailscale", 44 | "dns": "Permitir configurações de DNS do Tailscale", 45 | "save": "Salvar Configurações", 46 | "restart": "Reiniciar Tailscale", 47 | "erase": "Apagar Configuração do Tailscale", 48 | "diagnostics": "Diagnóstico do Plugin", 49 | "reauthenticate": "Reautenticar", 50 | "funnel": "Permitir Funnel do Tailscale", 51 | "hosts": "Adicionar peers ao /etc/hosts", 52 | "no_logs_no_support": "Sem logs, sem suporte", 53 | "tpm": "Permitir que o TPM criptografe a chave de nó", 54 | "context": { 55 | "tpm": "Ativa o uso de um TPM (Módulo de Plataforma Confiável) para armazenamento seguro da chave de nó do Tailscale. Isso aumenta a segurança ao proteger a chave de nó contra extração fácil, garantindo que apenas hardware autorizado possa acessá-la. Ativar esta opção requer TPM 2.0. Não terá efeito se o sistema não possuir um TPM compatível.", 56 | "unraid_listen": "Configura serviços do Unraid (SSH, WebGUI, SMB, etc.) para ouvir nos endereços do Tailscale.", 57 | "ip_forward": "Define net.ipv4.ip_forward e net.ipv6.conf.all.forwarding como 1 no sysctl. Essa alteração ocorre imediatamente ao ser ativada.", 58 | "taildrop": "Especifique o caminho para arquivos recebidos do Taildrop.", 59 | "dns": "Permite que o DNS do Tailscale seja ativado via CLI ou WebGUI. Se desativado, o DNS do Tailscale estará desativado quando o Tailscale iniciar.", 60 | "subnets": "Permite que rotas do Tailscale sejam ativadas via CLI ou WebGUI. Se desativado, rotas do Tailscale serão desativadas quando iniciar.", 61 | "wireguard": "Altere a porta usada para conexões Wireguard. Normalmente isso não precisa ser alterado.", 62 | "erase": "Faz logout do Tailscale e restaura todas as configurações para os padrões", 63 | "restart": "Reinicia o daemon do Tailscale e reaplica as configurações.", 64 | "diagnostics": "Baixar diagnósticos (isso pode demorar um pouco para concluir)", 65 | "save": "O Tailscale será reiniciado quando as alterações forem aplicadas", 66 | "reauthenticate": "Forçar uma nova autenticação do Tailscale.", 67 | "funnel": "Permite que o Funnel do Tailscale seja ativado através da WebGUI. Se desativado, o Funnel do Tailscale será desativado.", 68 | "hosts": "Adiciona peers do Tailscale ao /etc/hosts para resolução de nomes. Isto é útil se você quiser usar nomes DNS do Tailnet, sem as possíveis complicações de habilitar o DNS do Tailscale no servidor.", 69 | "no_logs_no_support": "Desativa a telemetria do Tailscale e impede que você receba suporte do Tailscale que exija essa telemetria para depuração." 70 | } 71 | }, 72 | "info": { 73 | "online": "Online", 74 | "version": "Versão do Tailscale", 75 | "health": "Status do Tailscale", 76 | "login": "Logado", 77 | "netmap": "No Mapa de Rede", 78 | "key_expire": "Expiração da Chave", 79 | "tags": "Tags", 80 | "hostname": "Nome do Host", 81 | "dns": "Nome DNS", 82 | "ip": "IPs do Tailscale", 83 | "magicdns": "Sufixo MagicDNS", 84 | "routes": "Rotas Anunciadas", 85 | "accept_routes": "Aceitar Rotas", 86 | "accept_dns": "Aceitar DNS", 87 | "run_ssh": "Tailscale SSH", 88 | "advertise_exit_node": "Anunciar como Exit Node", 89 | "use_exit_node": "Usar Exit Node", 90 | "exit_node_local": "Permitir acesso LAN ao usar Exit Node", 91 | "unapproved": "Necessita aprovação no painel de administração", 92 | "connected_via": "Conectado via Tailscale", 93 | "funnel_port": "Porta do Funnel para WebGUI", 94 | "port_in_use": "Porta em Uso", 95 | "peer_relay": "Porta de retransmissão do peer", 96 | "auto_update": "Atualização automática", 97 | "lock": { 98 | "node_key": "Chave do Nó", 99 | "public_key": "Chave Pública", 100 | "signed": "Chave do Nó Assinada", 101 | "signing": "É Nó de Assinatura" 102 | } 103 | }, 104 | "warnings": { 105 | "key_expiration": "A chave do Tailscale irá expirar em %s dias, em %s.", 106 | "netbios": "O NetBIOS está ativado em configurações SMB - isso pode impedir acesso às compartilhamentos através do Tailscale.", 107 | "lock": "O tailnet está com bloqueio ativado, mas este nó não foi assinado. Ele não poderá se comunicar com o tailnet.", 108 | "funnel": "Ativar o Funnel do Tailscale para o WebGUI do Unraid expõe seu servidor à Internet, aumentando significativamente o risco de acesso não autorizado e potenciais ataques. Este recurso só deve ser ativado se você compreender totalmente o impacto na segurança. A abordagem recomendada/segura para acesso remoto é instalar o Tailscale nos dispositivos que você pretende usar para acessar o WebGUI, em vez de ativar o Funnel.", 109 | "subnet": "Aceitar sub-redes do Tailscale no seu servidor Unraid pode interromper a conectividade da rede local em certas configurações de rede. Aceitar rotas não é necessário para que seu Unraid funcione como roteador de sub-rede ou nó de saída. Ative esta opção apenas se seu Unraid precisar se conectar a sub-redes remotas anunciadas por outros dispositivos.", 110 | "dns": "Ativar o MagicDNS do Tailscale no seu servidor pode causar interrupções na resolução de nomes dentro de containers Docker, causando possivelmente problemas de conectividade para aplicações. O MagicDNS não precisa estar ativado no servidor para que você acesse seu Unraid usando nomes MagicDNS (exemplo: 'unraid.tailnet.ts.net') de outros dispositivos. Ativar \"Adicionar peers ao /etc/hosts\" é uma alternativa mais segura, pois permite que nomes do Tailscale sejam usados no servidor.", 111 | "caution": "Prossiga com cautela e certifique-se de entender as implicações desta alteração antes de continuar.", 112 | "more_info": "Para mais informações:", 113 | "peer_relay_no_acl": "Não configurado na política do Tailnet (controles de acesso).", 114 | "tpm": "Ativar o TPM vincula a chave de nó do Tailscale ao hardware específico deste dispositivo. Se o TPM for posteriormente desativado, a chave de nó do Tailscale se tornará inválida e o dispositivo precisará ser reautenticado no Tailscale. Também é possível que TPMs fiquem bloqueados, o que pode interromper a conectividade do Tailscale e exigir nova autenticação." 115 | }, 116 | "lock": { 117 | "sign": "Assinar Nós", 118 | "signing_node": "Este é um nó de assinatura para a tailnet.", 119 | "signing_instructions": "Os seguintes nós estão atualmente bloqueados fora do tailnet. Marque a caixa dos nós que deseja adicionar e clique no botão Assinar para adicioná-lo à tailnet.", 120 | "signed_node": "Seu tailnet está com bloqueio ativado e o nó atual está assinado. Este nó pode se comunicar com o tailnet.", 121 | "make_signing": "Se deseja tornar este um nó de assinatura, você deverá confiar na seguinte chave a partir de um nó de assinatura:", 122 | "unsigned": "Seu tailnet está com bloqueio ativado e o nó atual não está assinado. Este nó não pode se comunicar com o tailnet.", 123 | "unsigned_instructions": "Para permitir que este nó se comunique, você deverá confiar na seguinte chave a partir de um nó de assinatura", 124 | "disabled": "Seu tailnet não possui bloqueio ativado." 125 | }, 126 | "status_page": { 127 | "exit_node": "Exit Node", 128 | "connection_type": "Tipo de Conexão", 129 | "connection_addr": "Conexão", 130 | "tx_bytes": "Bytes Tx", 131 | "rx_bytes": "Bytes Rx", 132 | "relay": "Relé", 133 | "direct": "Direto", 134 | "exit_active": "Ativo", 135 | "exit_available": "Disponível", 136 | "idle": "Inativo", 137 | "offline": "Offline", 138 | "active": "Ativo", 139 | "login_name": "Nome de Login", 140 | "shared": "Usuário Compartilhado", 141 | "action": "Ação" 142 | } 143 | } --------------------------------------------------------------------------------