Compare commits

...

17 commits

Author SHA1 Message Date
Kristoffer Dalby
bb4a3c5c4c
Merge 46ccfff71d into 0089ceaf1d 2024-11-08 09:26:20 +13:00
Philip Henning
0089ceaf1d
Feature tvos documentation (#2226)
Some checks failed
Build / build (push) Has been cancelled
Build documentation / build (push) Has been cancelled
Build documentation / deploy (push) Has been cancelled
Tests / test (push) Has been cancelled
* Add usage documentation for tvOS

* lint and format

* Change admonition to mkdocs flavoured style

* fix typos

* Update hscontrol/templates/apple.go

Co-authored-by: Kristoffer Dalby <kristoffer@dalby.cc>

* change outer quoting for where quoting in-text is used

---------

Co-authored-by: Kristoffer Dalby <kristoffer@dalby.cc>
2024-11-07 14:56:18 +00:00
Kristoffer Dalby
46ccfff71d
pull_request_target
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-08-13 08:43:47 +02:00
Kristoffer Dalby
71607ae13c
disable sbom
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-08-13 08:35:29 +02:00
Kristoffer Dalby
8e26fcfeea
remove pr number again
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-08-13 08:24:21 +02:00
Kristoffer Dalby
610223df67
add back pr attempt in hope for more perms
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-08-12 10:04:42 +02:00
Kristoffer Dalby
10a9eda893
restore write all
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-08-12 09:56:02 +02:00
Kristoffer Dalby
9a4c7e4446
run ko with nix
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-08-12 09:48:47 +02:00
Kristoffer Dalby
aba61ceb1b
test without pr number
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-08-12 09:47:21 +02:00
Kristoffer Dalby
1efb817acc
all
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-08-12 09:29:52 +02:00
Kristoffer Dalby
49952dda40
derp
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-08-12 09:27:30 +02:00
Kristoffer Dalby
53a08e5ab6
derp
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-08-12 09:26:23 +02:00
Kristoffer Dalby
52cce46cd8
debug pr number
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-08-12 09:22:29 +02:00
Kristoffer Dalby
68669238f9
debug pr name
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-08-12 09:18:04 +02:00
Kristoffer Dalby
0d6a25d6ee
env it
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-08-12 09:16:50 +02:00
Kristoffer Dalby
e1416a72cb
make it so ko.yaml changes trigger build
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-08-12 09:15:15 +02:00
Kristoffer Dalby
cec46716b6
build docker images on PR
Sometimes we want people to test features in PRs and
not everyone is used to using git, build go and docker.

This commit builds docker containers and pushes them to
GHCR (not dockerhub) for testing on pushes to branches
that has open pull requests to main using Ko.
This is configured to mimic the debug images produced
by goreleaser.

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
2024-08-12 09:09:08 +02:00
7 changed files with 281 additions and 72 deletions

71
.github/workflows/build-docker-pr.yml vendored Normal file
View file

@ -0,0 +1,71 @@
name: Build
on:
push:
branches:
- main
pull_request:
branches:
- main
concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
permissions: write-all
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Get changed files
id: changed-files
uses: dorny/paths-filter@v3
with:
filters: |
files:
- '*.nix'
- 'go.*'
- '**/*.go'
- 'integration_test/'
- 'config-example.yaml'
- uses: DeterminateSystems/nix-installer-action@main
if: steps.changed-files.outputs.files == 'true'
- uses: DeterminateSystems/magic-nix-cache-action@main
if: steps.changed-files.outputs.files == 'true'
- name: Run build
id: build
if: steps.changed-files.outputs.files == 'true'
run: |
nix build |& tee build-result
BUILD_STATUS="${PIPESTATUS[0]}"
OLD_HASH=$(cat build-result | grep specified: | awk -F ':' '{print $2}' | sed 's/ //g')
NEW_HASH=$(cat build-result | grep got: | awk -F ':' '{print $2}' | sed 's/ //g')
echo "OLD_HASH=$OLD_HASH" >> $GITHUB_OUTPUT
echo "NEW_HASH=$NEW_HASH" >> $GITHUB_OUTPUT
exit $BUILD_STATUS
- name: Nix gosum diverging
uses: actions/github-script@v6
if: failure() && steps.build.outcome == 'failure'
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.rest.pulls.createReviewComment({
pull_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'Nix build failed with wrong gosum, please update "vendorSha256" (${{ steps.build.outputs.OLD_HASH }}) for the "headscale" package in flake.nix with the new SHA: ${{ steps.build.outputs.NEW_HASH }}'
})
- uses: actions/upload-artifact@v4
if: steps.changed-files.outputs.files == 'true'
with:
name: headscale-linux
path: result/bin/headscale

View file

@ -1,10 +1,7 @@
name: Build name: Build Docker images for PRs
on: on:
push: pull_request_target:
branches:
- main
pull_request:
branches: branches:
- main - main
@ -31,41 +28,34 @@ jobs:
- '**/*.go' - '**/*.go'
- 'integration_test/' - 'integration_test/'
- 'config-example.yaml' - 'config-example.yaml'
- '.ko.yaml'
- uses: DeterminateSystems/nix-installer-action@main - uses: DeterminateSystems/nix-installer-action@main
if: steps.changed-files.outputs.files == 'true' if: steps.changed-files.outputs.files == 'true'
- uses: DeterminateSystems/magic-nix-cache-action@main - uses: DeterminateSystems/magic-nix-cache-action@main
if: steps.changed-files.outputs.files == 'true' if: steps.changed-files.outputs.files == 'true'
- name: Run build # - uses: actions/github-script@v7
# id: get_pr_data
# with:
# script: |
# return (
# await github.rest.repos.listPullRequestsAssociatedWithCommit({
# commit_sha: context.sha,
# owner: context.repo.owner,
# repo: context.repo.repo,
# })
# ).data[0];
# - name: Pull Request data
# run: |
# echo '${{steps.get_pr_data.outputs.result}}'
- name: Run ko build
id: build id: build
if: steps.changed-files.outputs.files == 'true' if: steps.changed-files.outputs.files == 'true'
env:
KO_DOCKER_REPO: ghcr.io/${{ github.repository_owner }}/headscale
# TAG_PR_NAME: pr-${{ fromJson(steps.get_pr_data.outputs.result).number }}
TAG_SHA: ${{ github.sha }}
run: | run: |
nix build |& tee build-result nix develop --command -- ko build --sbom=none --tags=$TAG_SHA ./cmd/headscale
BUILD_STATUS="${PIPESTATUS[0]}"
OLD_HASH=$(cat build-result | grep specified: | awk -F ':' '{print $2}' | sed 's/ //g')
NEW_HASH=$(cat build-result | grep got: | awk -F ':' '{print $2}' | sed 's/ //g')
echo "OLD_HASH=$OLD_HASH" >> $GITHUB_OUTPUT
echo "NEW_HASH=$NEW_HASH" >> $GITHUB_OUTPUT
exit $BUILD_STATUS
- name: Nix gosum diverging
uses: actions/github-script@v6
if: failure() && steps.build.outcome == 'failure'
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |
github.rest.pulls.createReviewComment({
pull_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: 'Nix build failed with wrong gosum, please update "vendorSha256" (${{ steps.build.outputs.OLD_HASH }}) for the "headscale" package in flake.nix with the new SHA: ${{ steps.build.outputs.NEW_HASH }}'
})
- uses: actions/upload-artifact@v4
if: steps.changed-files.outputs.files == 'true'
with:
name: headscale-linux
path: result/bin/headscale

View file

@ -28,8 +28,6 @@ builds:
- -mod=readonly - -mod=readonly
ldflags: ldflags:
- -s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=v{{.Version}} - -s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=v{{.Version}}
tags:
- ts2019
archives: archives:
- id: golang-cross - id: golang-cross

16
.ko.yaml Normal file
View file

@ -0,0 +1,16 @@
defaultBaseImage: gcr.io/distroless/base-debian12:debug
defaultPlatforms:
- linux/arm64
- linux/arm/v7
- linux/amd64
- linux/386
builds:
- id: headscale
main: ./cmd/headscale
env:
- CGO_ENABLED=0
flags:
- -mod=readonly
ldflags:
- -s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=v{{.Git.ShortCommit}}

View file

@ -13,3 +13,4 @@ headscale.
| Android | Yes (see [docs](../usage/connect/android.md)) | | Android | Yes (see [docs](../usage/connect/android.md)) |
| macOS | Yes (see [docs](../usage/connect/apple.md#macos) and `/apple` on your headscale for more information) | | macOS | Yes (see [docs](../usage/connect/apple.md#macos) and `/apple` on your headscale for more information) |
| iOS | Yes (see [docs](../usage/connect/apple.md#ios) and `/apple` on your headscale for more information) | | iOS | Yes (see [docs](../usage/connect/apple.md#ios) and `/apple` on your headscale for more information) |
| tvOS | Yes (see [docs](../usage/connect/apple.md#tvos) and `/apple` on your headscale for more information) |

View file

@ -47,3 +47,23 @@ tailscale login --login-server <YOUR_HEADSCALE_URL>
- Under `Custom Login Server`, select `Add Account...` - Under `Custom Login Server`, select `Add Account...`
- Enter the URL of your headscale instance (e.g `https://headscale.example.com`) and press `Add Account` - Enter the URL of your headscale instance (e.g `https://headscale.example.com`) and press `Add Account`
- Follow the login procedure in the browser - Follow the login procedure in the browser
## tvOS
### Installation
Install the official Tailscale tvOS client from the [App Store](https://apps.apple.com/app/tailscale/id1470499037).
!!! danger
**Don't** open the Tailscale App after installation!
### Configuring the headscale URL
- Go Settings (the apple tvOS settings) > Apps > Tailscale
- Under `ALTERNATE COORDINATION SERVER URL`, select `URL`
- Enter the URL of your headscale instance (e.g `https://headscale.example.com`) and press `OK`
- Return to the tvOS Home screen
- Open Tailscale
- Click the button `Install VPN configuration` and confirm the appearing popup by clicking the `Allow` button
- Scan the QR code and follow the login procedure

View file

@ -17,9 +17,13 @@ func Apple(url string) *elem.Element {
headerOne("headscale: iOS configuration"), headerOne("headscale: iOS configuration"),
headerTwo("GUI"), headerTwo("GUI"),
elem.Ol(nil, elem.Ol(nil,
elem.Li(nil, elem.Li(
nil,
elem.Text("Install the official Tailscale iOS client from the "), elem.Text("Install the official Tailscale iOS client from the "),
elem.A(attrs.Props{attrs.Href: "https://apps.apple.com/app/tailscale/id1470499037"}, elem.A(
attrs.Props{
attrs.Href: "https://apps.apple.com/app/tailscale/id1470499037",
},
elem.Text("App store"), elem.Text("App store"),
), ),
), ),
@ -31,27 +35,47 @@ func Apple(url string) *elem.Element {
elem.Li(nil, elem.Li(nil,
elem.Text("Open Settings on the iOS device"), elem.Text("Open Settings on the iOS device"),
), ),
elem.Li(nil, elem.Li(
elem.Text(`Scroll down to the "third party apps" section, under "Game Center" or "TV Provider"`), nil,
elem.Text(
`Scroll down to the "third party apps" section, under "Game Center" or "TV Provider"`,
),
), ),
elem.Li(nil, elem.Li(nil,
elem.Text("Find Tailscale and select it"), elem.Text("Find Tailscale and select it"),
elem.Ul(nil, elem.Ul(nil,
elem.Li(nil, elem.Li(
elem.Text(`If the iOS device was previously logged into Tailscale, switch the "Reset Keychain" toggle to "on"`), nil,
elem.Text(
`If the iOS device was previously logged into Tailscale, switch the "Reset Keychain" toggle to "on"`,
),
), ),
), ),
), ),
elem.Li(nil, elem.Li(
elem.Text(fmt.Sprintf(`Enter "%s" under "Alternate Coordination Server URL"`,url)), nil,
elem.Text(
fmt.Sprintf(
`Enter "%s" under "Alternate Coordination Server URL"`,
url,
),
),
), ),
elem.Li(nil, elem.Li(
elem.Text("Restart the app by closing it from the iOS app switcher, open the app and select the regular sign in option "), nil,
elem.Text(
"Restart the app by closing it from the iOS app switcher, open the app and select the regular sign in option ",
),
elem.I(nil, elem.Text("(non-SSO)")), elem.I(nil, elem.Text("(non-SSO)")),
elem.Text(". It should open up to the headscale authentication page."), elem.Text(
". It should open up to the headscale authentication page.",
),
), ),
elem.Li(nil, elem.Li(
elem.Text("Enter your credentials and log in. Headscale should now be working on your iOS device"), nil,
elem.Text(
"Enter your credentials and log in. Headscale should now be working on your iOS device",
),
), ),
), ),
headerOne("headscale: macOS configuration"), headerOne("headscale: macOS configuration"),
@ -61,39 +85,63 @@ func Apple(url string) *elem.Element {
), ),
elem.Pre(nil, elem.Pre(nil,
elem.Code(nil, elem.Code(nil,
elem.Text(fmt.Sprintf("tailscale login --login-server %s",url)), elem.Text(fmt.Sprintf("tailscale login --login-server %s", url)),
), ),
), ),
headerTwo("GUI"), headerTwo("GUI"),
elem.Ol(nil, elem.Ol(nil,
elem.Li(nil, elem.Li(
elem.Text("ALT + Click the Tailscale icon in the menu and hover over the Debug menu"), nil,
elem.Text(
"ALT + Click the Tailscale icon in the menu and hover over the Debug menu",
),
), ),
elem.Li(nil, elem.Li(nil,
elem.Text(`Under "Custom Login Server", select "Add Account..."`), elem.Text(`Under "Custom Login Server", select "Add Account..."`),
), ),
elem.Li(nil, elem.Li(
elem.Text(fmt.Sprintf(`Enter "%s" of the headscale instance and press "Add Account"`,url)), nil,
elem.Text(
fmt.Sprintf(
`Enter "%s" of the headscale instance and press "Add Account"`,
url,
),
),
), ),
elem.Li(nil, elem.Li(nil,
elem.Text(`Follow the login procedure in the browser`), elem.Text(`Follow the login procedure in the browser`),
), ),
), ),
headerTwo("Profiles"), headerTwo("Profiles"),
elem.P(nil, elem.P(
elem.Text("Headscale can be set to the default server by installing a Headscale configuration profile:"), nil,
elem.Text(
"Headscale can be set to the default server by installing a Headscale configuration profile:",
),
), ),
elem.P(nil, elem.P(
elem.A(attrs.Props{attrs.Href: "/apple/macos-app-store", attrs.Download: "headscale_macos.mobileconfig"}, nil,
elem.A(
attrs.Props{
attrs.Href: "/apple/macos-app-store",
attrs.Download: "headscale_macos.mobileconfig",
},
elem.Text("macOS AppStore profile "), elem.Text("macOS AppStore profile "),
), ),
elem.A(attrs.Props{attrs.Href: "/apple/macos-standalone", attrs.Download: "headscale_macos.mobileconfig"}, elem.A(
attrs.Props{
attrs.Href: "/apple/macos-standalone",
attrs.Download: "headscale_macos.mobileconfig",
},
elem.Text("macOS Standalone profile"), elem.Text("macOS Standalone profile"),
), ),
), ),
elem.Ol(nil, elem.Ol(nil,
elem.Li(nil, elem.Li(
elem.Text("Download the profile, then open it. When it has been opened, there should be a notification that a profile can be installed"), nil,
elem.Text(
"Download the profile, then open it. When it has been opened, there should be a notification that a profile can be installed",
),
), ),
elem.Li(nil, elem.Li(nil,
elem.Text(`Open System Preferences and go to "Profiles"`), elem.Text(`Open System Preferences and go to "Profiles"`),
@ -106,20 +154,35 @@ func Apple(url string) *elem.Element {
), ),
), ),
elem.P(nil, elem.Text("Or")), elem.P(nil, elem.Text("Or")),
elem.P(nil, elem.P(
elem.Text("Use your terminal to configure the default setting for Tailscale by issuing:"), nil,
elem.Text(
"Use your terminal to configure the default setting for Tailscale by issuing:",
),
), ),
elem.Ul(nil, elem.Ul(nil,
elem.Li(nil, elem.Li(nil,
elem.Text(`for app store client:`), elem.Text(`for app store client:`),
elem.Code(nil, elem.Code(
elem.Text(fmt.Sprintf(`defaults write io.tailscale.ipn.macos ControlURL %s`,url)), nil,
elem.Text(
fmt.Sprintf(
`defaults write io.tailscale.ipn.macos ControlURL %s`,
url,
),
),
), ),
), ),
elem.Li(nil, elem.Li(nil,
elem.Text(`for standalone client:`), elem.Text(`for standalone client:`),
elem.Code(nil, elem.Code(
elem.Text(fmt.Sprintf(`defaults write io.tailscale.ipn.macsys ControlURL %s`,url)), nil,
elem.Text(
fmt.Sprintf(
`defaults write io.tailscale.ipn.macsys ControlURL %s`,
url,
),
),
), ),
), ),
), ),
@ -127,23 +190,73 @@ func Apple(url string) *elem.Element {
elem.Text("Restart Tailscale.app and log in."), elem.Text("Restart Tailscale.app and log in."),
), ),
headerThree("Caution"), headerThree("Caution"),
elem.P(nil, elem.P(
elem.Text("You should always download and inspect the profile before installing it:"), nil,
elem.Text(
"You should always download and inspect the profile before installing it:",
),
), ),
elem.Ul(nil, elem.Ul(nil,
elem.Li(nil, elem.Li(nil,
elem.Text(`for app store client: `), elem.Text(`for app store client: `),
elem.Code(nil, elem.Code(nil,
elem.Text(fmt.Sprintf(`curl %s/apple/macos-app-store`,url)), elem.Text(fmt.Sprintf(`curl %s/apple/macos-app-store`, url)),
), ),
), ),
elem.Li(nil, elem.Li(nil,
elem.Text(`for standalone client: `), elem.Text(`for standalone client: `),
elem.Code(nil, elem.Code(nil,
elem.Text(fmt.Sprintf(`curl %s/apple/macos-standalone`,url)), elem.Text(fmt.Sprintf(`curl %s/apple/macos-standalone`, url)),
), ),
), ),
), ),
headerOne("headscale: tvOS configuration"),
headerTwo("GUI"),
elem.Ol(nil,
elem.Li(
nil,
elem.Text("Install the official Tailscale tvOS client from the "),
elem.A(
attrs.Props{
attrs.Href: "https://apps.apple.com/app/tailscale/id1470499037",
},
elem.Text("App store"),
),
),
elem.Li(
nil,
elem.Text(
"Open Settings (the Apple tvOS settings) > Apps > Tailscale",
),
),
elem.Li(
nil,
elem.Text(
fmt.Sprintf(
`Enter "%s" under "ALTERNATE COORDINATION SERVER URL"`,
url,
),
),
),
elem.Li(nil,
elem.Text("Return to the tvOS Home screen"),
),
elem.Li(nil,
elem.Text("Open Tailscale"),
),
elem.Li(nil,
elem.Text(`Select "Install VPN configuration"`),
),
elem.Li(nil,
elem.Text(`Select "Allow"`),
),
elem.Li(nil,
elem.Text("Scan the QR code and follow the login procedure"),
),
elem.Li(nil,
elem.Text("Headscale should now be working on your tvOS device"),
),
),
), ),
) )
} }