mirror of
https://github.com/Mo3he/Axis_Cam_Tailscale.git
synced 2026-10-01 03:55:40 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dce8beaa1b | ||
|
|
b70d664f91 | ||
|
|
9ea88ccd0d | ||
|
|
f79f631d95 | ||
|
|
835ccff82f | ||
|
|
92262bd16c | ||
|
|
948c201ea3 | ||
|
|
3730609abe | ||
|
|
b06dbc0059 | ||
|
|
7d32827567 | ||
|
|
970055051d | ||
|
|
216ae1ebf9 | ||
|
|
e2daee6519 | ||
|
|
2a8dccfc05 | ||
|
|
02dda93272 | ||
|
|
0331f8d8c5 | ||
|
|
f3d649aa92 | ||
|
|
bddcdf7de8 |
+102
@@ -0,0 +1,102 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 120
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
ReflowComments: true
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
...
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
DEFAULT_BRANCH=origin/main
|
||||
LINTER_RULES_PATH=/
|
||||
VALIDATE_ALL_CODEBASE=true
|
||||
IGNORE_GITIGNORED_FILES=true
|
||||
YAML_CONFIG_FILE=.yamllint.yaml
|
||||
MARKDOWN_CONFIG_FILE=.markdownlint.yaml
|
||||
VALIDATE_DOCKERFILE_HADOLINT=true
|
||||
VALIDATE_JSON=true
|
||||
VALIDATE_MARKDOWN=true
|
||||
VALIDATE_SHELL_SHFMT=true
|
||||
VALIDATE_YAML=true
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
name: Lint
|
||||
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
Build:
|
||||
name: Lint code base
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Environment
|
||||
run: cat .github/super-linter.env >> "$GITHUB_ENV"
|
||||
|
||||
- name: Lint code base
|
||||
uses: super-linter/super-linter/slim@v8
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
# Enforce error-level Dockerfile correctness. Warnings/info are advisory: the
|
||||
# ACAP cross-compile Dockerfiles use accepted patterns (cd in RUN, ARG-templated
|
||||
# FROM tags hadolint cannot resolve, optional pipefail).
|
||||
failure-threshold: error
|
||||
ignored:
|
||||
# Pin versions in 'apt-get install' - the SDK base image is already pinned.
|
||||
- DL3008
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
# Line length (disabled: long lines in tables, URLs and prose are acceptable)
|
||||
MD013: false
|
||||
# Allow inline HTML (e.g. <img> logos and badges in READMEs)
|
||||
MD033: false
|
||||
# Allow blank lines inside blockquotes
|
||||
MD028: false
|
||||
# First line in a file should be a top-level heading
|
||||
MD041: false
|
||||
# Table column style (disabled; the previous "padded" value was invalid)
|
||||
MD060: false
|
||||
@@ -0,0 +1,2 @@
|
||||
rules:
|
||||
line-length: disable
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project are documented here. Each version
|
||||
links to its full release notes on GitHub.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
||||
|
||||
## [1.98.9-Signed] - 2026-07-21 - Tailscale VPN 1.98.9 (Signed)
|
||||
|
||||
- Packages are now signed with the Axis ACAP signing service and install
|
||||
normally on AXIS OS 12.10 and later.
|
||||
- Vendor updated to `moshe@mohome.net` with the registered vendor ID.
|
||||
- `root` and `acap3` variants remain unsigned (manifest schema v1.x).
|
||||
- Upgrading from an earlier unsigned version can fail with "Couldn't
|
||||
install: app" (device log: "Vendor ID in manifest does not match the
|
||||
vendor ID of the previous version"). Back up your config, uninstall the
|
||||
old version, then install this one.
|
||||
|
||||
## [1.98.8-2] - 2026-07-03 - Tailscale VPN 1.98.8-2
|
||||
|
||||
## [1.98.8-subnet-routing] - 2026-07-01 - Tailscale VPN 1.98.8 - Subnet Routing
|
||||
|
||||
## [1.98.8] - 2026-06-30 - Tailscale VPN 1.98.8
|
||||
|
||||
## [1.98.4-statusfix] - 2026-06-16
|
||||
|
||||
## [1.98.4-dns-routes] - 2026-06-10 - Tailscale VPN v1.98.4 - Accept DNS & Routes toggles
|
||||
|
||||
## [1.98.4] - 2026-06-02 - Tailscale VPN 1.98.4
|
||||
|
||||
## [1.98.3] - 2026-05-22 - Tailscale VPN 1.98.3
|
||||
|
||||
## [1.98.2] - 2026-05-19 - Tailscale VPN 1.98.2
|
||||
|
||||
## [1.96.4-dns-routes] - 2026-05-12 - Tailscale VPN v1.96.4 - Accept DNS & Routes toggles
|
||||
|
||||
## [1.96.4-r3] - 2026-04-17 - Tailscale VPN v1.96.4-r3
|
||||
|
||||
## [1.96.4-r2] - 2026-04-17
|
||||
|
||||
## [1.96.4-proxy] - 2026-04-14 - Tailscale VPN 1.96.4 - Proxy Support
|
||||
|
||||
## [1.96.4] - 2026-03-28 - Tailscale VPN 1.96.4
|
||||
|
||||
## [1.96.2] - 2026-03-19 - Tailscale VPN 1.96.2
|
||||
|
||||
## [1.94.2] - 2026-02-26 - Tailscale VPN 1.94.2
|
||||
|
||||
## [1.94.1] - 2026-01-28 - Tailscale VPN 1.94.1
|
||||
|
||||
## [1.92.5] - 2026-01-07 - Tailscale VPN 1.92.5
|
||||
|
||||
## [1.92.3] - 2025-12-17 - Tailscale VPN 1.92.3
|
||||
|
||||
## [1.92.1] - 2025-12-15 - Tailscale VPN 1.92.1
|
||||
|
||||
## [1.90.9] - 2025-11-26 - Tailscale VPN 1.90.9
|
||||
|
||||
## [1.90.8] - 2025-11-20 - Tailscale VPN 1.90.8
|
||||
|
||||
## [1.90.6] - 2025-11-03 - Tailscale VPN 1.90.6
|
||||
|
||||
## [1.90.3] - 2025-10-28 - Tailscale VPN 1.90.3
|
||||
|
||||
## [1.90.2] - 2025-10-27 - Tailscale VPN 1.90.2
|
||||
|
||||
## [1.90.1] - 2025-10-23 - Tailscale VPN 1.90.1
|
||||
|
||||
## [1.88.3] - 2025-09-29 - Tailscale VPN 1.88.3
|
||||
|
||||
## [1.88.1] - 2025-09-15 - Tailscale VPN 1.88.1
|
||||
|
||||
## [1.86.2] - 2025-08-27 - Tailscale VPN 1.86.2
|
||||
|
||||
## [1.84.0] - 2025-05-26
|
||||
|
||||
## [1.82.0] - 2025-04-11
|
||||
|
||||
## [1.80.3] - 2025-03-24
|
||||
|
||||
## [1.78.1] - 2025-01-13
|
||||
|
||||
## [1.76.1] - 2024-10-24
|
||||
|
||||
## [1.72.1] - 2024-08-26
|
||||
|
||||
## [1.68.1] - 2024-06-27
|
||||
|
||||
## [1.62.0] - 2024-03-23
|
||||
|
||||
## [1.60.0] - 2024-02-21
|
||||
|
||||
## [1.56.1] - 2024-01-17
|
||||
|
||||
## [1.54.0] - 2023-11-28
|
||||
|
||||
## [1.52.0] - 2023-11-01
|
||||
|
||||
## [1.50.1] - 2023-10-16
|
||||
|
||||
## [148.2] - 2023-09-13 - Version 1.48.2
|
||||
|
||||
## [1.44.0] - 2023-07-04
|
||||
|
||||
## [138.4] - 2023-04-17 - V1.38.4
|
||||
|
||||
## [1.34.0] - 2022-12-19
|
||||
|
||||
[1.98.8-2]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.98.8-2
|
||||
[1.98.8-subnet-routing]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.98.8-subnet-routing
|
||||
[1.98.8]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.98.8
|
||||
[1.98.4-statusfix]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.98.4-statusfix
|
||||
[1.98.4-dns-routes]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.98.4-dns-routes
|
||||
[1.98.4]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.98.4
|
||||
[1.98.3]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.98.3
|
||||
[1.98.2]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.98.2
|
||||
[1.96.4-dns-routes]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.96.4-dns-routes
|
||||
[1.96.4-r3]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.96.4-r3
|
||||
[1.96.4-r2]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.96.4-r2
|
||||
[1.96.4-proxy]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.96.4-proxy
|
||||
[1.96.4]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.96.4
|
||||
[1.96.2]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.96.2
|
||||
[1.94.2]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.94.2
|
||||
[1.94.1]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.94.1
|
||||
[1.92.5]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.92.5
|
||||
[1.92.3]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.92.3
|
||||
[1.92.1]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.92.1
|
||||
[1.90.9]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.90.9
|
||||
[1.90.8]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.90.8
|
||||
[1.90.6]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.90.6
|
||||
[1.90.3]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.90.3
|
||||
[1.90.2]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.90.2
|
||||
[1.90.1]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.90.1
|
||||
[1.88.3]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.88.3
|
||||
[1.88.1]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.88.1
|
||||
[1.86.2]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.86.2
|
||||
[1.84.0]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v.1.84.0
|
||||
[1.82.0]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v.1.82.0
|
||||
[1.80.3]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v.1.80.3
|
||||
[1.78.1]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v.1.78.1
|
||||
[1.76.1]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v.1.76.1
|
||||
[1.72.1]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v.1.72.1
|
||||
[1.68.1]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.68.1
|
||||
[1.62.0]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v.1.62.0
|
||||
[1.60.0]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v.1.60.0
|
||||
[1.56.1]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.56.1
|
||||
[1.54.0]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v.1.54.0
|
||||
[1.52.0]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v.1.52.0
|
||||
[1.50.1]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.50.1
|
||||
[148.2]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v.148.2
|
||||
[1.44.0]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v.1.44.0
|
||||
[138.4]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v.138.4
|
||||
[1.34.0]: https://github.com/Mo3he/Axis_Cam_Tailscale/releases/tag/v1.34.0
|
||||
+14
-14
@@ -13,13 +13,13 @@ All types of contributions are encouraged and valued. See the [Table of contents
|
||||
|
||||
- [I have a question](#i-have-a-question)
|
||||
- [I want to contribute](#i-want-to-contribute)
|
||||
- [Reporting bugs](#reporting-bugs)
|
||||
- [Before submitting a bug report](#before-submitting-a-bug-report)
|
||||
- [How do I submit a good bug report?](#how-do-i-submit-a-good-bug-report)
|
||||
- [Suggesting enhancements](#suggesting-enhancements)
|
||||
- [Before Submitting an Enhancement](#before-submitting-an-enhancement)
|
||||
- [How do I submit a good enhancement suggestion?](#how-do-i-submit-a-good-enhancement-suggestion)
|
||||
- [Your first code contribution](#your-first-code-contribution)
|
||||
- [Reporting bugs](#reporting-bugs)
|
||||
- [Before submitting a bug report](#before-submitting-a-bug-report)
|
||||
- [How do I submit a good bug report?](#how-do-i-submit-a-good-bug-report)
|
||||
- [Suggesting enhancements](#suggesting-enhancements)
|
||||
- [Before Submitting an Enhancement](#before-submitting-an-enhancement)
|
||||
- [How do I submit a good enhancement suggestion?](#how-do-i-submit-a-good-enhancement-suggestion)
|
||||
- [Your first code contribution](#your-first-code-contribution)
|
||||
|
||||
## I have a question
|
||||
|
||||
@@ -46,13 +46,13 @@ A good bug report shouldn't leave others needing to chase you up for more inform
|
||||
- To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the [bug tracker][issues_bugs].
|
||||
- Also make sure to search the internet to see if users outside of the GitHub community have discussed the issue.
|
||||
- Collect information about the bug:
|
||||
- Axis device model
|
||||
- Axis device firmware version
|
||||
- Stack trace
|
||||
- OS and version (Windows, Linux, macOS, x86, ARM)
|
||||
- Version of the interpreter, compiler, SDK, runtime environment, package manager, depending on what seems relevant
|
||||
- Possibly your input and the output
|
||||
- Can you reliably reproduce the issue? And can you also reproduce it with older versions?
|
||||
- Axis device model
|
||||
- Axis device firmware version
|
||||
- Stack trace
|
||||
- OS and version (Windows, Linux, macOS, x86, ARM)
|
||||
- Version of the interpreter, compiler, SDK, runtime environment, package manager, depending on what seems relevant
|
||||
- Possibly your input and the output
|
||||
- Can you reliably reproduce the issue? And can you also reproduce it with older versions?
|
||||
|
||||
#### How do I submit a good bug report?
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2020 Tailscale & AUTHORS.
|
||||
Copyright (c) 2022 Weston Blieden (ACAP packaging and wrapper code)
|
||||
All rights reserved.
|
||||
Copyright (c) 2022, Weston Blieden
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
@@ -27,4 +25,4 @@ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
@@ -1,73 +1,114 @@
|
||||
# Tailscale ACAP for Axis Cameras
|
||||
|
||||
[](https://github.com/Mo3he/Axis_Cam_Tailscale/releases)
|
||||
[](LICENSE)
|
||||
[](https://github.com/Mo3he/Axis_Cam_Tailscale/releases)
|
||||
[](https://github.com/Mo3he/Axis_Cam_Tailscale/actions/workflows/build.yml)
|
||||
[](https://github.com/Mo3he/Axis_Cam_Tailscale/actions/workflows/super-linter.yml)
|
||||
[](https://github.com/sponsors/Mo3he)
|
||||
[](https://www.buymeacoffee.com/mo3he)
|
||||
|
||||
This repository provides an **ACAP package** that installs the
|
||||
[Tailscale VPN client](https://tailscale.com/) on Axis cameras, for secure remote
|
||||
access without extra hardware or complex network configuration.
|
||||
|
||||
**[Visit the Homepage](https://mo3he.github.io/Axis_Cam_Tailscale/)**
|
||||
|
||||
This repository provides an **ACAP package** that installs the [Tailscale VPN client](https://tailscale.com/) on Axis cameras.
|
||||
> **Disclaimer:** Independent, community-developed ACAP package. Not an official
|
||||
> Axis product and not affiliated with, endorsed by, or supported by Axis
|
||||
> Communications AB or Tailscale Inc. Use at your own risk.
|
||||
|
||||
- Secure remote access to cameras
|
||||
- Easy to install via EAP package
|
||||
- Works on **Axis OS 10.12+** (non-root version, verified across 10.12–12.10)
|
||||
- Works on **legacy Axis OS 9.x / 10.x** via the ACAP 3 variant
|
||||
- Based on **WireGuard VPN** technology
|
||||
|
||||
[](https://github.com/Mo3he/Axis_Cam_Tailscale/releases)
|
||||
[](LICENSE)
|
||||

|
||||
[](https://github.com/sponsors/Mo3he)
|
||||
[](https://www.buymeacoffee.com/mo3he)
|
||||
|
||||
> **Disclaimer:** This is an independent, community-developed ACAP package and is not an official Axis Communications product. It is not affiliated with, endorsed by, or supported by Axis Communications AB. Use it at your own risk. For official Axis software, visit axis.com
|
||||
|
||||
> **Tailscale Notice:** Tailscale is a product of Tailscale Inc. This package independently redistributes the Tailscale binaries under the [BSD 3-Clause License](LICENSE) and is not affiliated with, endorsed by, or supported by Tailscale Inc. For the official Tailscale client, visit [tailscale.com](https://tailscale.com).
|
||||
---
|
||||
> **Tailscale Notice:** Tailscale is a product of Tailscale Inc. This package
|
||||
> independently redistributes the Tailscale binaries under the
|
||||
> [BSD 3-Clause License](LICENSE) and is not affiliated with, endorsed by, or
|
||||
> supported by Tailscale Inc. For the official Tailscale client, visit
|
||||
> [tailscale.com](https://tailscale.com).
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Installation](#installation)
|
||||
- [Usage](#usage)
|
||||
- [Settings](#settings)
|
||||
- [Proxy Support](#proxy-support)
|
||||
- [Accessing Tailnet Services from the Camera](#accessing-tailnet-services-from-the-camera)
|
||||
- [Updating Tailscale](#updating-tailscale)
|
||||
- [Purpose](#purpose)
|
||||
- [Useful Links](#useful-links)
|
||||
- [Compatibility](#compatibility)
|
||||
- [Roadmap](#roadmap)
|
||||
- [Star History](#star-history)
|
||||
- [Support](#support)
|
||||
- [Overview](#overview)
|
||||
- [Compatibility](#compatibility)
|
||||
- [Installation](#installation)
|
||||
- [Configuration](#configuration)
|
||||
- [Ports & security](#ports--security)
|
||||
- [Accessing Tailnet services from the camera](#accessing-tailnet-services-from-the-camera)
|
||||
- [Updating Tailscale](#updating-tailscale)
|
||||
- [Build from source](#build-from-source)
|
||||
- [Roadmap](#roadmap)
|
||||
- [Links](#links)
|
||||
- [License](#license)
|
||||
|
||||
---
|
||||
## Overview
|
||||
|
||||
Adding a VPN client directly to the camera enables secure remote access without
|
||||
additional hardware or complex network configuration, through Tailscale's
|
||||
lightweight WireGuard-based tunnel.
|
||||
|
||||
- Secure remote access to cameras.
|
||||
- Easy to install via EAP package.
|
||||
- Works on **AXIS OS 10.12+** (non-root version, verified across 10.12–13).
|
||||
- Works on **legacy AXIS OS 9.x / 10.x** via the ACAP 3 variant.
|
||||
- Based on **WireGuard VPN** technology.
|
||||
|
||||
Tailscale ACAP runs **without root privileges** in userspace networking mode,
|
||||
making it compatible with AXIS OS 10.12+. For **full kernel networking**, use the
|
||||
**ROOT** version (AXIS OS 10.12–11.x only; AXIS OS 12 and later removed root
|
||||
access for third-party applications). Learn more:
|
||||
[How Tailscale Works](https://tailscale.com/blog/how-tailscale-works/).
|
||||
|
||||
## Compatibility
|
||||
|
||||
| Build | AXIS OS | Architecture | Notes |
|
||||
|---|---|---|---|
|
||||
| ACAP 4 (native SDK) | 10.12 – 13 | aarch64 | Standard, userspace networking |
|
||||
| ACAP 4 (native SDK) | 10.12 – 13 | armv7hf | Standard, userspace networking |
|
||||
| ACAP 4 root | 10.12 – 11.x | aarch64 | Full kernel networking (not on OS 12+) |
|
||||
| ACAP 4 root | 10.12 – 11.x | armv7hf | Full kernel networking (not on OS 12+) |
|
||||
| ACAP 3 (legacy SDK) | 9.x – 10.x | armv7hf | Legacy cameras |
|
||||
|
||||
> Most cameras use the standard **ACAP 4** build. The **root** builds add
|
||||
> kernel-level networking but only run on AXIS OS 10.12–11.x (AXIS OS 12+ removed
|
||||
> root access for ACAPs). Use the **ACAP 3** build only on legacy cameras that
|
||||
> don't support ACAP 4 (AXIS OS 9–10).
|
||||
|
||||
**Verified on AXIS OS 13** (13.0.0, aarch64).
|
||||
|
||||
## Installation
|
||||
|
||||
Get the **prebuilt `.eap` file** from the [Releases page](https://github.com/Mo3he/Axis_Cam_Tailscale/releases).
|
||||
> **Signed packages:** Release `.eap` files are signed with the Axis ACAP
|
||||
> signing service and install normally on AXIS OS 12.10 and later.
|
||||
>
|
||||
> **Upgrading from an earlier version?** The signing vendor changed, so
|
||||
> installing over a previously installed unsigned build can fail with
|
||||
> **"Couldn't install: app"** (device log: *"Vendor ID in manifest does not
|
||||
> match the vendor ID of the previous version"*). To upgrade: back up your app
|
||||
> configuration, **uninstall** the old version, then install the signed one.
|
||||
|
||||
1. Log into your Axis camera.
|
||||
2. Go to **Apps → Add App**.
|
||||
3. Upload the `.eap` file.
|
||||
Get the **prebuilt `.eap` file** from the
|
||||
[Releases page](https://github.com/Mo3he/Axis_Cam_Tailscale/releases).
|
||||
|
||||
1. Log into your Axis camera.
|
||||
2. Go to **Apps -> Add App**.
|
||||
3. Upload the `.eap` file.
|
||||
|
||||
Once installed:
|
||||
- Start the app.
|
||||
- Click **Open** to view logs and get your Tailscale authentication URL.
|
||||
- On uninstall, all changes/files are removed.
|
||||
|
||||
- Start the app.
|
||||
- Click **Open** to view logs and get your Tailscale authentication URL.
|
||||
- On uninstall, all changes/files are removed.
|
||||
|
||||
> You'll need a [Tailscale account](https://tailscale.com/) to authenticate.
|
||||
|
||||
---
|
||||
## Configuration
|
||||
|
||||
## Usage
|
||||
The app runs a C-based parameter bridge that reads settings from the ACAP
|
||||
parameter store and launches Tailscale. View logs and connection status via the
|
||||
**Open** button in the app, and authenticate using the provided URL or by
|
||||
pre-entering an auth key in **Settings**. Parameter changes (ports, server URL,
|
||||
auth key) are applied automatically without reinstalling the app.
|
||||
|
||||
- Runs a C-based parameter bridge (compiled via ACAP SDK 1.15.1) that reads settings from the ACAP parameter store and launches Tailscale.
|
||||
- View logs and connection status via the **Open** button in the app.
|
||||
- Authenticate using the provided URL, or pre-enter an auth key in **Settings**.
|
||||
- Change the **Custom Server URL** in Settings to use a self-hosted [Headscale](https://headscale.net/) control server.
|
||||
- Parameter changes (ports, server URL, auth key) are applied automatically without needing to reinstall the app.
|
||||
|
||||
---
|
||||
|
||||
## Settings
|
||||
|
||||
All parameters are configurable via the web UI (**Open → Settings** card) and take effect immediately without reinstalling:
|
||||
All parameters are configurable via the web UI (**Open -> Settings** card) and
|
||||
take effect immediately:
|
||||
|
||||
| Parameter | Default | Description |
|
||||
|---|---|---|
|
||||
@@ -75,179 +116,140 @@ All parameters are configurable via the web UI (**Open → Settings** card) and
|
||||
| Auth Key | *(empty)* | Pre-authentication key (`tskey-auth-...`). Cleared automatically after first successful connection. Leave blank to authenticate via browser. |
|
||||
| HTTP Proxy Port | `8080` | Port for the outbound HTTP/HTTPS proxy. |
|
||||
| SOCKS5 Proxy Port | `1080` | Port for the outbound SOCKS5 proxy. |
|
||||
| Accept DNS | `off` | Passes `--accept-dns=true` to `tailscale up`. Allows the tailnet to push DNS settings to the camera. Off by default to avoid overriding the camera's DNS configuration. Not available on `armv7hf_acap3`. |
|
||||
| Accept Routes | `off` | Passes `--accept-routes=true` to `tailscale up`. Allows the camera to use subnet routes advertised by other nodes in the tailnet. Not available on `armv7hf_acap3`. |
|
||||
| Accept DNS | `off` | Passes `--accept-dns=true` to `tailscale up`. Allows the tailnet to push DNS settings to the camera. Not available on `armv7hf_acap3`. |
|
||||
| Accept Routes | `off` | Passes `--accept-routes=true` to `tailscale up`. Allows the camera to use subnet routes advertised by other nodes. Not available on `armv7hf_acap3`. |
|
||||
| Advertise Routes (Subnet Router) | *(empty)* | Comma-separated CIDRs (e.g. `192.168.1.0/24,10.0.0.0/8`) this camera will route for the tailnet, turning it into a subnet router. Approve the routes in the Tailscale admin console after saving. Leave blank to disable. |
|
||||
|
||||
---
|
||||
## Ports & security
|
||||
|
||||
All non-ROOT variants expose two local proxy endpoints that route outbound
|
||||
traffic through the Tailscale tunnel. The ports are configurable via **Settings
|
||||
-> HTTP Proxy Port / SOCKS5 Proxy Port**.
|
||||
|
||||
All non-ROOT variants expose two local proxy endpoints that route outbound traffic through the Tailscale tunnel. The ports are configurable via **Settings → HTTP Proxy Port / SOCKS5 Proxy Port** in the web UI.
|
||||
|
||||
### HTTP CONNECT Proxy — `http://127.0.0.1:8080` (default)
|
||||
|
||||
Routes HTTP and HTTPS traffic. Set this wherever an HTTP/HTTPS proxy field is available on the camera:
|
||||
|
||||
| Location | Field | Value |
|
||||
| Proxy | Default address | Routes |
|
||||
|---|---|---|
|
||||
| System → Network → Global proxies | HTTP proxy | `http://127.0.0.1:<port>` |
|
||||
| System → Network → Global proxies | HTTPS proxy | `http://127.0.0.1:<port>` |
|
||||
| System → MQTT → Broker | HTTP proxy | `http://127.0.0.1:<port>` |
|
||||
| System → MQTT → Broker | HTTPS proxy | `http://127.0.0.1:<port>` |
|
||||
| HTTP CONNECT | `http://127.0.0.1:8080` | HTTP and HTTPS traffic |
|
||||
| SOCKS5 | `127.0.0.1:1080` | Any SOCKS5-aware app or service |
|
||||
|
||||
### SOCKS5 Proxy — `127.0.0.1:1080` (default)
|
||||
Set the HTTP CONNECT proxy wherever an HTTP/HTTPS proxy field is available on the
|
||||
camera (System -> Network -> Global proxies; System -> MQTT -> Broker). For
|
||||
SOCKS5-aware apps, set their proxy to `127.0.0.1:<port>`.
|
||||
|
||||
For ACAP apps or services that support SOCKS5, set their proxy to `127.0.0.1:<port>`.
|
||||
> **Security:** the proxies bind to **loopback only** (`127.0.0.1`), so they are
|
||||
> not exposed on the camera's network interface, the least-exposed of the VPN
|
||||
> ACAPs. The active proxy addresses are shown in the **Proxy Configuration** card
|
||||
> of the web UI. If you change a port that is already in use, the app logs an
|
||||
> error and exits rather than silently falling back.
|
||||
|
||||
> The active proxy addresses are always shown in the **Proxy Configuration** card of the web UI.
|
||||
## Accessing Tailnet services from the camera
|
||||
|
||||
> If you change a port that is already in use by another process, the app will log an error and exit rather than silently falling back to a different port.
|
||||
|
||||
---
|
||||
|
||||
## Accessing Tailnet Services from the Camera
|
||||
|
||||
There is an important asymmetry to understand. Making the camera **reachable from** the tailnet (browsing to it, VAPIX, SSH from another tailnet node) works on every build. The harder direction is the camera **reaching out to** a tailnet peer, for example mounting an SMB/CIFS network share hosted on another node. How well this works depends on which build you use.
|
||||
|
||||
### Why the build matters
|
||||
There is an important asymmetry. Making the camera **reachable from** the tailnet
|
||||
(browsing to it, VAPIX, SSH from another tailnet node) works on every build. The
|
||||
harder direction is the camera **reaching out to** a tailnet peer, for example
|
||||
mounting an SMB/CIFS share hosted on another node. How well this works depends on
|
||||
the build:
|
||||
|
||||
| Build | Networking mode | Camera-initiated access to tailnet peers |
|
||||
|---|---|---|
|
||||
| Non-root (`aarch64`, `armv7hf`) and `armv7hf_acap3` | `--tun=userspace-networking` (no kernel `tailscale0` interface) | Only through the local **SOCKS5 / HTTP proxies**, and only for **proxy-aware** apps. Firmware system services (the SMB share client, NTP, etc.) are proxy-unaware, so they **cannot** reach a peer's `100.x` Tailscale IP directly. |
|
||||
| Non-root (`aarch64`, `armv7hf`) and `armv7hf_acap3` | `--tun=userspace-networking` (no kernel `tailscale0`) | Only through the local **SOCKS5 / HTTP proxies**, and only for **proxy-aware** apps. Firmware system services (SMB client, NTP, etc.) are proxy-unaware and **cannot** reach a peer's `100.x` IP directly. |
|
||||
| **ROOT** (`aarch64_root`, `armv7hf_root`) | Kernel networking with a real `tailscale0` interface | Peer `100.x` IPs are routable at the OS level, so firmware services **can** connect directly. Enable **Accept Routes** to also reach subnets behind other nodes. |
|
||||
|
||||
In short: on non-root builds the proxies cover apps that know how to use a proxy, but a system feature like "add network share" opens a raw socket that never touches the tunnel. The ROOT build is the clean way to let the camera *consume* tailnet services.
|
||||
|
||||
### Plan B: reverse-SSH tunnel
|
||||
> **Requires root on the camera.** Port 445 is privileged, so binding it needs a root-capable build (e.g. developer certificates installed).
|
||||
|
||||
If you cannot use the ROOT build but still need the camera to mount a share on a machine that is on your tailnet, you can make the remote share appear **local** to the camera with a reverse SSH tunnel. Because the destination becomes `127.0.0.1`, the proxy-unaware SMB client never has to route over the tailnet.
|
||||
> **Requires root on the camera.** Port 445 is privileged, so binding it needs a
|
||||
> root-capable build (e.g. developer certificates installed).
|
||||
|
||||
From a computer that has both the share and tailnet access to the camera:
|
||||
If you cannot use the ROOT build but still need the camera to mount a share on a
|
||||
machine that is on your tailnet, make the remote share appear **local** to the
|
||||
camera with a reverse SSH tunnel. Because the destination becomes `127.0.0.1`, the
|
||||
proxy-unaware SMB client never has to route over the tailnet.
|
||||
|
||||
```bash
|
||||
# Forward the camera's local port 445 back to the SMB share on this machine
|
||||
ssh -R 445:localhost:445 root@<camera-tailscale-ip>
|
||||
```
|
||||
|
||||
Then, in the camera's **System → Storage → Add network share** dialog, use `127.0.0.1` as the share host and connect.
|
||||
|
||||
---
|
||||
Then, in **System -> Storage -> Add network share**, use `127.0.0.1` as the share
|
||||
host and connect.
|
||||
|
||||
## Updating Tailscale
|
||||
|
||||
- New `.eap` files are auto-built and released **weekly** (if a new Tailscale version is available).
|
||||
- To update, simply install the new `.eap` over the existing one.
|
||||
- New `.eap` files are auto-built and released **weekly** (if a new Tailscale
|
||||
version is available).
|
||||
- To update, simply install the new `.eap` over the existing one.
|
||||
|
||||
### Manual update (advanced)
|
||||
|
||||
Replace the binaries in `common/app/lib/` (shared by `aarch64`, `armv7hf`, and their ROOT variants) or `arm_acap3/app/lib/` (legacy variant, kept separate):
|
||||
Replace the binaries in `common/app/lib/` (shared by `aarch64`, `armv7hf`, and
|
||||
their ROOT variants) or `arm_acap3/app/lib/` (legacy variant, kept separate):
|
||||
|
||||
- `tailscale`
|
||||
- `tailscaled`
|
||||
|
||||
Download the latest versions: [Tailscale static builds](https://pkgs.tailscale.com/stable/#static)
|
||||
Download the latest versions:
|
||||
[Tailscale static builds](https://pkgs.tailscale.com/stable/#static).
|
||||
|
||||
#### Build locally
|
||||
## Build from source
|
||||
|
||||
The Tailscale binaries are not stored in git, so first download them (see [Manual update](#manual-update-advanced) above) and place them in `common/app/lib/` — or `arm_acap3/app/lib/` for the legacy variant.
|
||||
The Tailscale binaries are not stored in git, so first download them (see
|
||||
[Manual update](#manual-update-advanced)) and place them in `common/app/lib/`, or
|
||||
`arm_acap3/app/lib/` for the legacy variant.
|
||||
|
||||
All variants build from the **repository root**, pointing at the variant's own `Dockerfile`:
|
||||
All variants build from the **repository root**, pointing at the variant's own
|
||||
`Dockerfile`:
|
||||
|
||||
```bash
|
||||
docker build -f aarch64/Dockerfile --tag <package_name> .
|
||||
docker cp $(docker create <package_name>):/opt/app ./build
|
||||
```
|
||||
|
||||
(Same for the others — just swap in `arm/Dockerfile`, `aarch64_ROOT/Dockerfile`, `arm_ROOT/Dockerfile`, or `arm_acap3/Dockerfile`.)
|
||||
|
||||
---
|
||||
|
||||
## Good News
|
||||
|
||||
Tailscale ACAP can now run **without root privileges**, making it compatible with **Axis OS 10.12+** — verified working across Axis OS 10.12, 11.11, and 12.10.
|
||||
|
||||
- Runs in **user space networking mode**.
|
||||
|
||||
For **full kernel networking**, use the **ROOT** version. Note: ROOT mode requires Axis OS 10.12–11.x — Axis OS 12 and later removed root access for third-party applications.
|
||||
|
||||
### Legacy camera support (Axis OS 9.x / 10.x)
|
||||
|
||||
An **ACAP 3** variant (`armv7hf_acap3`) is available for older cameras that do not support ACAP 4 / Axis OS 11+. It uses the same userspace networking mode and web UI, built against the ACAP SDK 3.5 toolchain.
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
Adding a VPN client directly to the camera enables:
|
||||
- Secure remote access without additional hardware or complex network configuration.
|
||||
- Easy setup through Tailscale’s lightweight WireGuard-based tunnel.
|
||||
|
||||
Learn more: [How Tailscale Works](https://tailscale.com/blog/how-tailscale-works/)
|
||||
|
||||
---
|
||||
|
||||
## Useful Links
|
||||
|
||||
- [Tailscale](https://tailscale.com/)
|
||||
- [Tailscale GitHub](https://github.com/tailscale/tailscale)
|
||||
- [WireGuard](https://www.wireguard.com/)
|
||||
- [Axis Communications](https://www.axis.com/)
|
||||
|
||||
---
|
||||
|
||||
## Compatibility
|
||||
|
||||
The Tailscale ACAP is compatible with Axis cameras with **ARM** and **AARCH64**-based SoCs.
|
||||
|
||||
| Variant | Architecture | Axis OS | Notes |
|
||||
|---|---|---|---|
|
||||
| `aarch64` | AArch64 | 10.12 – 13 (ACAP 4) | Standard, userspace networking, configurable proxy ports |
|
||||
| `armv7hf` | ARMv7 | 10.12 – 13 (ACAP 4) | Standard, userspace networking, configurable proxy ports |
|
||||
| `aarch64_root` | AArch64 | 10.12 – 11.x (ACAP 4) | Full kernel networking (root) — not supported on OS 12+ |
|
||||
| `armv7hf_root` | ARMv7 | 10.12 – 11.x (ACAP 4) | Full kernel networking (root) — not supported on OS 12+ |
|
||||
| `armv7hf_acap3` | ARMv7 | **9.x – 10.x** | Legacy cameras, ACAP SDK 3 |
|
||||
|
||||
> Not sure which variant to use? Check **System → Properties → Firmware version** on your camera. Axis OS 12+ → use the standard variant (`aarch64` or `armv7hf`). Axis OS 10.12–11.x → standard variant works too, or ROOT if you need kernel networking. Axis OS 9.x → use `armv7hf_acap3`.
|
||||
>
|
||||
> The standard variant's floor was verified by live-testing the same build on Axis OS 10.12.300, 11.11.212, and 12.10.68 — it is not limited to 11.11+ as earlier releases implied. The ROOT variant was also verified on Axis OS 10.12.300 with genuine kernel networking confirmed over SSH (processes running as `root`, a real `tailscale0` kernel interface present, and `ip_forward` correctly toggling on when subnet routes are advertised) — Axis OS 10.x ran third-party apps as root by default, before the privilege sandboxing introduced later, so ROOT was never actually limited to 11.11+.
|
||||
|
||||
You can verify your device details using the following command:
|
||||
|
||||
```bash
|
||||
curl --anyauth "*" -u <username>:<password> <device_ip>/axis-cgi/basicdeviceinfo.cgi --data '{"apiVersion":"1.0","context":"Client defined request ID","method":"getAllProperties"}'
|
||||
```
|
||||
|
||||
> Replace `<device_ip>`, `<username>`, and `<password>` with your device credentials.
|
||||
> Enclose your password in quotes `' '` if it contains special characters.
|
||||
|
||||
---
|
||||
(Same for the others: just swap in `arm/Dockerfile`, `aarch64_ROOT/Dockerfile`,
|
||||
`arm_ROOT/Dockerfile`, or `arm_acap3/Dockerfile`.)
|
||||
|
||||
## Roadmap
|
||||
|
||||
### AXIS OS 13 Preparation
|
||||
|
||||
AXIS OS 13 (scheduled for September 2026) introduces several breaking changes that affect all ACAP applications. The following items are required to maintain compatibility. See the full [AXIS OS 13 breaking changes](https://www.axis.com/for-developers/news/AXIS-OS-13-breaking-changes) announcement for details.
|
||||
AXIS OS 13 (scheduled for September 2026) introduces several breaking changes that
|
||||
affect all ACAP applications. See the full
|
||||
[AXIS OS 13 breaking changes](https://www.axis.com/for-developers/news/AXIS-OS-13-breaking-changes)
|
||||
announcement for details.
|
||||
|
||||
- [x] **Recompile for 64-bit time (Y2038)** - AXIS OS 13 switches to a 64-bit time interface. All ACAP apps must be recompiled against the updated SDK. Cameras with incompatible apps installed will roll back the OS upgrade rather than proceed. Done for the standard `aarch64`/`armv7hf` builds (now built against ACAP Native SDK 12.10.0); the ROOT variants intentionally stay on the older SDK since Axis OS 12+ never supports root third-party apps, so they can never reach OS 13 regardless.
|
||||
- [x] **Migrate to Manifest Schema v2** - The `manifest.json` must use Manifest Schema v2, including an explicit declaration of compatible AXIS OS versions, to satisfy the new signing and compatibility requirements. Done for `aarch64`/`armv7hf` (schema 2.0.0, `compatibleOsVersions` declared); verified this does not break installability on older firmware (OS 10.12–12.10 all tested and working) before promoting it as the standard build.
|
||||
- [x] **Audit for executable stack usage** - Any ACAP compiled with an executable stack must be recompiled to comply with the new security restrictions in AXIS OS 13. Checked all compiled binaries (`param_bridge` for `aarch64`/`armv7hf`, both standard and ROOT, plus the bundled `tailscale`/`tailscaled` Go binaries) via `objdump`'s `GNU_STACK` program header — all report `flags rw-` (no executable stack) on every architecture and variant.
|
||||
- [x] **Verify web UI works over HTTPS** - AXIS OS 13 enforces HTTPS-only connections by default. The bundled web UI must be tested to confirm it functions correctly under this constraint. Verified live: the page and every endpoint it calls (`param.cgi` GET/update, the `reverseProxy` settings API GET/POST, `applications/list.cgi`, `systemlog.cgi`, the restart trigger) all work correctly over HTTPS. The UI only ever issues relative-path requests (no hardcoded `http://` fetch targets), so it inherits the page's own protocol with no mixed-content risk.
|
||||
- [ ] **Sign the ACAP via the Axis ACAP Portal** - AXIS OS 13 removes the ability to install unsigned applications in production environments. The app must be submitted and signed through the official Axis ACAP Portal to remain installable. Deferred for now — the manifest's `vendorId` is a placeholder value, not yet a portal-registered one.
|
||||
- [x] **Recompile for 64-bit time (Y2038)** - Done for the standard
|
||||
`aarch64`/`armv7hf` builds (now built against ACAP Native SDK 12.10.0); the
|
||||
ROOT variants intentionally stay on the older SDK since AXIS OS 12+ never
|
||||
supports root third-party apps.
|
||||
- [x] **Migrate to Manifest Schema v2** - Done for `aarch64`/`armv7hf` (schema
|
||||
2.0.0, `compatibleOsVersions` declared); verified installability on OS
|
||||
10.12–13.
|
||||
- [x] **Audit for executable stack usage** - All compiled binaries report
|
||||
`flags rw-` (no executable stack) on every architecture and variant.
|
||||
- [x] **Verify web UI works over HTTPS** - Verified live; the UI only issues
|
||||
relative-path requests, so it inherits the page's protocol with no
|
||||
mixed-content risk.
|
||||
- [x] **Sign the ACAP via the Axis ACAP Portal** - Done; `aarch64`/`armv7hf`
|
||||
packages are signed with the Axis ACAP signing service. The `root` and
|
||||
`acap3` variants use manifest schema v1.x and are distributed unsigned.
|
||||
|
||||
### General Improvements
|
||||
|
||||
- [x] **Accept DNS from tailnet toggle** - Add an opt-in setting to the settings page that passes `--accept-dns=true` to `tailscale up`. Defaults to off to prevent Tailscale from overriding `resolv.conf` on cameras that don't need MagicDNS.
|
||||
- [x] **Accept routes toggle** - Add an opt-in setting that passes `--accept-routes=true` to `tailscale up`, allowing the camera to use subnet routes advertised by other nodes in the tailnet.
|
||||
- [ ] **Switch to tiny-tailscale binaries** - Evaluate replacing the bundled `tailscale` and `tailscaled` binaries with [tiny-tailscale](https://github.com/iamromulan/tiny-tailscale) builds. These combine both into a single binary, strip unused features, and are significantly smaller (~43% reduction), reducing install size and memory footprint across all architectures.
|
||||
- [x] **Accept DNS from tailnet toggle** - Opt-in setting passing
|
||||
`--accept-dns=true` to `tailscale up` (defaults off).
|
||||
- [x] **Accept routes toggle** - Opt-in setting passing `--accept-routes=true`.
|
||||
- [ ] **Switch to tiny-tailscale binaries** - Evaluate replacing the bundled
|
||||
`tailscale`/`tailscaled` with [tiny-tailscale](https://github.com/iamromulan/tiny-tailscale)
|
||||
builds (single binary, ~43% smaller).
|
||||
|
||||
---
|
||||
## Links
|
||||
|
||||
## Star History
|
||||
- [Tailscale](https://tailscale.com/)
|
||||
- [Tailscale GitHub](https://github.com/tailscale/tailscale)
|
||||
- [WireGuard](https://www.wireguard.com/)
|
||||
- [Axis Communications](https://www.axis.com/)
|
||||
|
||||
[](https://www.star-history.com/#Mo3he/Axis_Cam_Tailscale&Date)
|
||||
## License
|
||||
|
||||
---
|
||||
|
||||
## Support
|
||||
|
||||
If you like this project and want to support my work:
|
||||
[Sponsor Me](https://github.com/sponsors/Mo3he)
|
||||
The packaging code in this repository is licensed under BSD 3-Clause (see
|
||||
[LICENSE](LICENSE)); this also covers the redistributed Tailscale binaries
|
||||
(upstream Tailscale is BSD 3-Clause). Bundled upstream components are listed in
|
||||
[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
# Security Policy
|
||||
|
||||
This is an independent, community-developed ACAP package, provided on a
|
||||
best-effort basis. It is not an official Axis Communications product.
|
||||
|
||||
## Reporting a vulnerability
|
||||
|
||||
Please report security issues privately rather than in a public issue:
|
||||
|
||||
- Use GitHub's "Report a vulnerability" (Security > Advisories) to open a
|
||||
private advisory, or
|
||||
- email <moshe@mohome.net>.
|
||||
|
||||
Include the affected version (or `.eap` filename), camera model / Axis OS
|
||||
version, a description and its impact, and reproduction steps if available. You
|
||||
can expect an acknowledgement within a reasonable time; please avoid public
|
||||
disclosure until a fix is released.
|
||||
|
||||
## Scope
|
||||
|
||||
Reports about this ACAP's own wrapper code, configuration handling, and default
|
||||
settings are in scope. Vulnerabilities in bundled upstream projects should also
|
||||
be reported to their respective upstream projects.
|
||||
@@ -0,0 +1,42 @@
|
||||
# Third-Party Notices
|
||||
|
||||
This ACAP package redistributes the Tailscale client. The ACAP's own wrapper
|
||||
code is licensed separately (see `LICENSE`, BSD 3-Clause).
|
||||
|
||||
## Tailscale
|
||||
|
||||
- Copyright (c) 2020 Tailscale & AUTHORS
|
||||
- Project: <https://github.com/tailscale/tailscale>
|
||||
- License: BSD 3-Clause
|
||||
|
||||
Tailscale is a product of Tailscale Inc. This package independently
|
||||
redistributes the Tailscale binaries and is not affiliated with, endorsed by, or
|
||||
supported by Tailscale Inc. For the official Tailscale client, visit
|
||||
<https://tailscale.com>.
|
||||
|
||||
```text
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
```
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
To build, from main directory
|
||||
|
||||
docker build --tag aarch64 .
|
||||
docker build --tag aarch64 .
|
||||
|
||||
docker cp $(docker create aarch64):/opt/app ./build
|
||||
docker cp $(docker create aarch64):/opt/app ./build
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
"setup": {
|
||||
"appName": "Tailscale_VPN",
|
||||
"friendlyName": "Tailscale VPN",
|
||||
"vendor": "Mo3he",
|
||||
"vendorId": "5741c1fb91",
|
||||
"vendor": "moshe@mohome.net",
|
||||
"vendorId": "70ee172dd9",
|
||||
"vendorUrl": "https://github.com/Mo3he/Axis_Cam_Tailscale",
|
||||
"version": "1.98.8",
|
||||
"version": "1.98.10",
|
||||
"architecture": "aarch64",
|
||||
"runMode": "respawn",
|
||||
"compatibleOsVersions": [
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
To build, from main directory
|
||||
|
||||
docker build --tag aarch64 .
|
||||
docker build --tag aarch64 .
|
||||
|
||||
docker cp $(docker create aarch64):/opt/app ./build
|
||||
docker cp $(docker create aarch64):/opt/app ./build
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
},
|
||||
"vendorUrl": "https://github.com/Mo3he/Axis_Cam_Tailscale",
|
||||
"runMode": "respawn",
|
||||
"version": "1.98.8",
|
||||
"version": "1.98.10",
|
||||
"architecture": "aarch64"
|
||||
},
|
||||
"configuration": {
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
To build from main directory
|
||||
|
||||
docker build --tag arm .
|
||||
docker build --tag arm .
|
||||
|
||||
docker cp $(docker create arm):/opt/app ./build
|
||||
docker cp $(docker create arm):/opt/app ./build
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
"setup": {
|
||||
"appName": "Tailscale_VPN",
|
||||
"friendlyName": "Tailscale VPN",
|
||||
"vendor": "Mo3he",
|
||||
"vendorId": "5741c1fb91",
|
||||
"vendor": "moshe@mohome.net",
|
||||
"vendorId": "70ee172dd9",
|
||||
"vendorUrl": "https://github.com/Mo3he/Axis_Cam_Tailscale",
|
||||
"version": "1.98.8",
|
||||
"version": "1.98.10",
|
||||
"architecture": "armv7hf",
|
||||
"runMode": "respawn",
|
||||
"compatibleOsVersions": [
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
To build from main directory
|
||||
|
||||
docker build --tag arm .
|
||||
docker build --tag arm .
|
||||
|
||||
docker cp $(docker create arm):/opt/app ./build
|
||||
docker cp $(docker create arm):/opt/app ./build
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
},
|
||||
"vendorUrl": "https://github.com/Mo3he/Axis_Cam_Tailscale",
|
||||
"runMode": "respawn",
|
||||
"version": "1.98.8",
|
||||
"version": "1.98.10",
|
||||
"architecture": "armv7hf"
|
||||
},
|
||||
"configuration": {
|
||||
|
||||
+23
-23
@@ -16,19 +16,19 @@ logger -t "Tailscale_VPN" "Starting tailscaled daemon"
|
||||
# Log to file (not piped through logger) -- avoids extra logger process holding
|
||||
# tailscaled stdout open, which prevents our wait loop from detecting exit
|
||||
"$APP_DIR/lib/tailscaled" \
|
||||
--state="$STATE_DIR/tailscaled.state" \
|
||||
--socket="$STATE_DIR/tailscaled.sock" \
|
||||
--socks5-server=localhost:1055 \
|
||||
--outbound-http-proxy-listen=localhost:8080 \
|
||||
--tun=userspace-networking \
|
||||
>> "$STATE_DIR/tailscaled.log" 2>&1 &
|
||||
--state="$STATE_DIR/tailscaled.state" \
|
||||
--socket="$STATE_DIR/tailscaled.sock" \
|
||||
--socks5-server=localhost:1055 \
|
||||
--outbound-http-proxy-listen=localhost:8080 \
|
||||
--tun=userspace-networking \
|
||||
>>"$STATE_DIR/tailscaled.log" 2>&1 &
|
||||
TAILSCALED_PID=$!
|
||||
|
||||
# Wait for socket to appear (up to 15 seconds)
|
||||
i=0
|
||||
while [ $i -lt 15 ] && [ ! -S "$STATE_DIR/tailscaled.sock" ]; do
|
||||
sleep 1
|
||||
i=$((i + 1))
|
||||
sleep 1
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
logger -t "Tailscale_VPN" "Connecting to Tailscale network"
|
||||
@@ -37,9 +37,9 @@ logger -t "Tailscale_VPN" "Connecting to Tailscale network"
|
||||
# cameras with limited RAM (e.g. 222 MB).
|
||||
# Capture output so we can extract auth URL and log it to syslog for the web UI.
|
||||
UP_OUT=$("$APP_DIR/lib/tailscale" \
|
||||
--socket="$STATE_DIR/tailscaled.sock" \
|
||||
up --hostname="$(hostname)" --timeout=10s 2>&1) || true
|
||||
echo "$UP_OUT" >> "$STATE_DIR/tailscaled.log"
|
||||
--socket="$STATE_DIR/tailscaled.sock" \
|
||||
up --hostname="$(hostname)" --timeout=10s 2>&1) || true
|
||||
echo "$UP_OUT" >>"$STATE_DIR/tailscaled.log"
|
||||
|
||||
# If an auth URL was returned, log it so the web UI can show it
|
||||
AUTH_URL=$(echo "$UP_OUT" | grep -o 'https://login\.tailscale\.com/[^ ]*' | head -1)
|
||||
@@ -48,7 +48,7 @@ AUTH_URL=$(echo "$UP_OUT" | grep -o 'https://login\.tailscale\.com/[^ ]*' | head
|
||||
# Log IP and version into syslog so the web UI details panel can populate
|
||||
TS_IP=$("$APP_DIR/lib/tailscale" --socket="$STATE_DIR/tailscaled.sock" ip -4 2>/dev/null | head -1)
|
||||
TS_VER=$("$APP_DIR/lib/tailscale" --socket="$STATE_DIR/tailscaled.sock" version 2>/dev/null | head -1)
|
||||
[ -n "$TS_IP" ] && logger -t "Tailscale_VPN" "Tailscale IP: $TS_IP"
|
||||
[ -n "$TS_IP" ] && logger -t "Tailscale_VPN" "Tailscale IP: $TS_IP"
|
||||
[ -n "$TS_VER" ] && logger -t "Tailscale_VPN" "Tailscale version: $TS_VER"
|
||||
|
||||
logger -t "Tailscale_VPN" "Tailscale VPN is running"
|
||||
@@ -63,19 +63,19 @@ logger -t "Tailscale_VPN" "SOCKS5 proxy: 127.0.0.1:1055"
|
||||
STATUS_FILE="$STATE_DIR/status.json"
|
||||
|
||||
publish_status() {
|
||||
if "$APP_DIR/lib/tailscale" --socket="$STATE_DIR/tailscaled.sock" status --json > "$STATUS_FILE.tmp" 2>/dev/null; then
|
||||
mv "$STATUS_FILE.tmp" "$STATUS_FILE" 2>/dev/null
|
||||
chmod 644 "$STATUS_FILE" 2>/dev/null
|
||||
else
|
||||
rm -f "$STATUS_FILE.tmp" 2>/dev/null
|
||||
fi
|
||||
if "$APP_DIR/lib/tailscale" --socket="$STATE_DIR/tailscaled.sock" status --json >"$STATUS_FILE.tmp" 2>/dev/null; then
|
||||
mv "$STATUS_FILE.tmp" "$STATUS_FILE" 2>/dev/null
|
||||
chmod 644 "$STATUS_FILE" 2>/dev/null
|
||||
else
|
||||
rm -f "$STATUS_FILE.tmp" 2>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
# Remove stale status on stop so the UI does not show a connected node after exit.
|
||||
cleanup() {
|
||||
rm -f "$STATUS_FILE" 2>/dev/null
|
||||
[ -n "$TAILSCALED_PID" ] && kill "$TAILSCALED_PID" 2>/dev/null
|
||||
exit 0
|
||||
rm -f "$STATUS_FILE" 2>/dev/null
|
||||
[ -n "$TAILSCALED_PID" ] && kill "$TAILSCALED_PID" 2>/dev/null
|
||||
exit 0
|
||||
}
|
||||
trap cleanup TERM INT
|
||||
|
||||
@@ -83,8 +83,8 @@ trap cleanup TERM INT
|
||||
# status fresh. This keeps the parent Tailscale_VPN (C launcher) in the process
|
||||
# table so pidof finds it and the camera web UI shows "Running" instead of "Stopped".
|
||||
while kill -0 "$TAILSCALED_PID" 2>/dev/null; do
|
||||
publish_status
|
||||
sleep 5
|
||||
publish_status
|
||||
sleep 5
|
||||
done
|
||||
|
||||
rm -f "$STATUS_FILE" 2>/dev/null
|
||||
|
||||
@@ -3,7 +3,7 @@ MENUNAME="Tailscale VPN"
|
||||
VENDOR="Mo3he"
|
||||
APPMAJORVERSION=1
|
||||
APPMINORVERSION=98
|
||||
APPMICROVERSION=8
|
||||
APPMICROVERSION=10
|
||||
APPTYPE=armv7hf
|
||||
APPNAME=Tailscale_VPN
|
||||
APPOPTS=""
|
||||
|
||||
@@ -27,48 +27,48 @@ ACCEPT_ROUTES="false"
|
||||
ADVERTISE_ROUTES=""
|
||||
|
||||
if [ -f "$STATE_DIR/params.conf" ]; then
|
||||
. "$STATE_DIR/params.conf"
|
||||
. "$STATE_DIR/params.conf"
|
||||
fi
|
||||
|
||||
if [ "$VARIANT" = "root" ]; then
|
||||
logger -t "Tailscale_VPN" "Starting (root mode): custom_server=${CUSTOM_SERVER:-(default)}"
|
||||
logger -t "Tailscale_VPN" "Starting (root mode): custom_server=${CUSTOM_SERVER:-(default)}"
|
||||
else
|
||||
logger -t "Tailscale_VPN" "Starting: http_port=$CONF_HTTP socks_port=$CONF_SOCKS custom_server=${CUSTOM_SERVER:-(default)}"
|
||||
logger -t "Tailscale_VPN" "Starting: http_port=$CONF_HTTP socks_port=$CONF_SOCKS custom_server=${CUSTOM_SERVER:-(default)}"
|
||||
|
||||
# Check whether a TCP port is already bound
|
||||
is_port_in_use() {
|
||||
local port=$1
|
||||
local hex_port
|
||||
hex_port=$(printf '%04X' "$port")
|
||||
grep -q ":${hex_port} " /proc/net/tcp 2>/dev/null && return 0
|
||||
grep -q ":${hex_port} " /proc/net/tcp6 2>/dev/null && return 0
|
||||
return 1
|
||||
}
|
||||
# Check whether a TCP port is already bound
|
||||
is_port_in_use() {
|
||||
local port=$1
|
||||
local hex_port
|
||||
hex_port=$(printf '%04X' "$port")
|
||||
grep -q ":${hex_port} " /proc/net/tcp 2>/dev/null && return 0
|
||||
grep -q ":${hex_port} " /proc/net/tcp6 2>/dev/null && return 0
|
||||
return 1
|
||||
}
|
||||
|
||||
if is_port_in_use "$CONF_HTTP"; then
|
||||
logger -t "Tailscale_VPN" "ERROR: HTTP proxy port $CONF_HTTP is already in use. Change it in Settings."
|
||||
exit 1
|
||||
fi
|
||||
if is_port_in_use "$CONF_SOCKS"; then
|
||||
logger -t "Tailscale_VPN" "ERROR: SOCKS5 port $CONF_SOCKS is already in use. Change it in Settings."
|
||||
exit 1
|
||||
fi
|
||||
if is_port_in_use "$CONF_HTTP"; then
|
||||
logger -t "Tailscale_VPN" "ERROR: HTTP proxy port $CONF_HTTP is already in use. Change it in Settings."
|
||||
exit 1
|
||||
fi
|
||||
if is_port_in_use "$CONF_SOCKS"; then
|
||||
logger -t "Tailscale_VPN" "ERROR: SOCKS5 port $CONF_SOCKS is already in use. Change it in Settings."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
logger -t "Tailscale_VPN" "Starting tailscaled daemon"
|
||||
if [ "$VARIANT" = "root" ]; then
|
||||
$TAILSCALED_PATH \
|
||||
--state="$STATE_DIR/tailscaled.state" \
|
||||
--socket=$SOCKET_PATH \
|
||||
>/dev/null 2>&1 &
|
||||
$TAILSCALED_PATH \
|
||||
--state="$STATE_DIR/tailscaled.state" \
|
||||
--socket=$SOCKET_PATH \
|
||||
>/dev/null 2>&1 &
|
||||
else
|
||||
$TAILSCALED_PATH \
|
||||
--state="$STATE_DIR/tailscaled.state" \
|
||||
--socket=$SOCKET_PATH \
|
||||
--socks5-server=localhost:$CONF_SOCKS \
|
||||
--outbound-http-proxy-listen=localhost:$CONF_HTTP \
|
||||
--tun=userspace-networking \
|
||||
>/dev/null 2>&1 &
|
||||
$TAILSCALED_PATH \
|
||||
--state="$STATE_DIR/tailscaled.state" \
|
||||
--socket=$SOCKET_PATH \
|
||||
--socks5-server=localhost:$CONF_SOCKS \
|
||||
--outbound-http-proxy-listen=localhost:$CONF_HTTP \
|
||||
--tun=userspace-networking \
|
||||
>/dev/null 2>&1 &
|
||||
fi
|
||||
TAILSCALED_PID=$!
|
||||
|
||||
@@ -77,19 +77,19 @@ sleep 2
|
||||
TAILSCALE_CMD="$TAILSCALE_PATH --socket=$SOCKET_PATH up --reset --hostname=$(hostname)"
|
||||
|
||||
if [ -n "$CUSTOM_SERVER" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --login-server $CUSTOM_SERVER"
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --login-server $CUSTOM_SERVER"
|
||||
fi
|
||||
|
||||
if [ -n "$AUTH_KEY" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --authkey $AUTH_KEY"
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --authkey $AUTH_KEY"
|
||||
fi
|
||||
|
||||
if [ "$ACCEPT_DNS" = "true" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --accept-dns=true"
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --accept-dns=true"
|
||||
fi
|
||||
|
||||
if [ "$ACCEPT_ROUTES" = "true" ]; then
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --accept-routes=true"
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --accept-routes=true"
|
||||
fi
|
||||
|
||||
# Advertise LAN subnets so this camera acts as a subnet router. Comma-separated
|
||||
@@ -99,11 +99,11 @@ fi
|
||||
# forward packets between the tailnet and the LAN, so enable IP forwarding.
|
||||
# Routes must still be approved in the Tailscale admin console either way.
|
||||
if [ -n "$ADVERTISE_ROUTES" ]; then
|
||||
if [ "$VARIANT" = "root" ]; then
|
||||
echo 1 > /proc/sys/net/ipv4/ip_forward 2>/dev/null || true
|
||||
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding 2>/dev/null || true
|
||||
fi
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --advertise-routes=$ADVERTISE_ROUTES"
|
||||
if [ "$VARIANT" = "root" ]; then
|
||||
echo 1 >/proc/sys/net/ipv4/ip_forward 2>/dev/null || true
|
||||
echo 1 >/proc/sys/net/ipv6/conf/all/forwarding 2>/dev/null || true
|
||||
fi
|
||||
TAILSCALE_CMD="$TAILSCALE_CMD --advertise-routes=$ADVERTISE_ROUTES"
|
||||
fi
|
||||
|
||||
# Run `tailscale up` in the background and act on its outcome. If the node needs
|
||||
@@ -115,27 +115,27 @@ fi
|
||||
# for it from here, because in POSIX sh `wait` only works on children of the
|
||||
# current shell — a subshell waiting on the parent's child returns 127.
|
||||
{
|
||||
eval "$TAILSCALE_CMD"
|
||||
up_exit=$?
|
||||
if [ "$up_exit" -eq 0 ]; then
|
||||
if [ "$VARIANT" = "root" ]; then
|
||||
logger -t "Tailscale_VPN" "Tailscale VPN is running (root mode)"
|
||||
else
|
||||
logger -t "Tailscale_VPN" "Tailscale VPN is running"
|
||||
fi
|
||||
# Auth succeeded with a one-time auth key — signal param_bridge to clear it
|
||||
if [ -n "$AUTH_KEY" ]; then
|
||||
: > "$STATE_DIR/authkey_clear"
|
||||
fi
|
||||
else
|
||||
logger -t "Tailscale_VPN" "ERROR: tailscale up failed (exit $up_exit)"
|
||||
fi
|
||||
eval "$TAILSCALE_CMD"
|
||||
up_exit=$?
|
||||
if [ "$up_exit" -eq 0 ]; then
|
||||
if [ "$VARIANT" = "root" ]; then
|
||||
logger -t "Tailscale_VPN" "Tailscale VPN is running (root mode)"
|
||||
else
|
||||
logger -t "Tailscale_VPN" "Tailscale VPN is running"
|
||||
fi
|
||||
# Auth succeeded with a one-time auth key — signal param_bridge to clear it
|
||||
if [ -n "$AUTH_KEY" ]; then
|
||||
: >"$STATE_DIR/authkey_clear"
|
||||
fi
|
||||
else
|
||||
logger -t "Tailscale_VPN" "ERROR: tailscale up failed (exit $up_exit)"
|
||||
fi
|
||||
} &
|
||||
TAILSCALE_UP_PID=$!
|
||||
|
||||
if [ "$VARIANT" != "root" ]; then
|
||||
logger -t "Tailscale_VPN" "HTTP/HTTPS proxy: http://127.0.0.1:$CONF_HTTP"
|
||||
logger -t "Tailscale_VPN" "SOCKS5 proxy: 127.0.0.1:$CONF_SOCKS"
|
||||
logger -t "Tailscale_VPN" "HTTP/HTTPS proxy: http://127.0.0.1:$CONF_HTTP"
|
||||
logger -t "Tailscale_VPN" "SOCKS5 proxy: 127.0.0.1:$CONF_SOCKS"
|
||||
fi
|
||||
|
||||
# Publish tailscale's real backend state as JSON for the web UI to consume.
|
||||
@@ -145,19 +145,19 @@ fi
|
||||
STATUS_FILE="$APP_DIR/html/status.json"
|
||||
|
||||
publish_status() {
|
||||
if "$TAILSCALE_PATH" --socket="$SOCKET_PATH" status --json > "$STATUS_FILE.tmp" 2>/dev/null; then
|
||||
mv "$STATUS_FILE.tmp" "$STATUS_FILE" 2>/dev/null
|
||||
chmod 644 "$STATUS_FILE" 2>/dev/null
|
||||
else
|
||||
rm -f "$STATUS_FILE.tmp" 2>/dev/null
|
||||
fi
|
||||
if "$TAILSCALE_PATH" --socket="$SOCKET_PATH" status --json >"$STATUS_FILE.tmp" 2>/dev/null; then
|
||||
mv "$STATUS_FILE.tmp" "$STATUS_FILE" 2>/dev/null
|
||||
chmod 644 "$STATUS_FILE" 2>/dev/null
|
||||
else
|
||||
rm -f "$STATUS_FILE.tmp" 2>/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
status_loop() {
|
||||
while true; do
|
||||
publish_status
|
||||
sleep 5
|
||||
done
|
||||
while true; do
|
||||
publish_status
|
||||
sleep 5
|
||||
done
|
||||
}
|
||||
status_loop &
|
||||
STATUS_LOOP_PID=$!
|
||||
@@ -166,11 +166,11 @@ STATUS_LOOP_PID=$!
|
||||
# stop/restart so param_bridge (which signals this script) leaves no orphans or
|
||||
# stale state.
|
||||
cleanup() {
|
||||
[ -n "$STATUS_LOOP_PID" ] && kill "$STATUS_LOOP_PID" 2>/dev/null
|
||||
[ -n "$TAILSCALE_UP_PID" ] && kill "$TAILSCALE_UP_PID" 2>/dev/null
|
||||
[ -n "$TAILSCALED_PID" ] && kill "$TAILSCALED_PID" 2>/dev/null
|
||||
rm -f "$STATUS_FILE" 2>/dev/null
|
||||
exit 0
|
||||
[ -n "$STATUS_LOOP_PID" ] && kill "$STATUS_LOOP_PID" 2>/dev/null
|
||||
[ -n "$TAILSCALE_UP_PID" ] && kill "$TAILSCALE_UP_PID" 2>/dev/null
|
||||
[ -n "$TAILSCALED_PID" ] && kill "$TAILSCALED_PID" 2>/dev/null
|
||||
rm -f "$STATUS_FILE" 2>/dev/null
|
||||
exit 0
|
||||
}
|
||||
trap cleanup TERM INT
|
||||
|
||||
|
||||
Reference in New Issue
Block a user