mirror of
https://github.com/netbirdio/dashboard.git
synced 2026-09-23 00:30:43 -07:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a34fc6b81 |
No files matched your search
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"extends": ["next/core-web-vitals","prettier"],
|
||||||
|
"plugins": ["simple-import-sort"],
|
||||||
|
"rules": {
|
||||||
|
"simple-import-sort/imports": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
"groups": [["^\\u0000", "^@?\\w", "^[^.]", "^\\."]]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"simple-import-sort/exports": "warn"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,7 +39,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
repository: netbirdio/IronRDP
|
repository: netbirdio/IronRDP
|
||||||
tag: v0.0.2
|
latest: true
|
||||||
fileName: "*.ts"
|
fileName: "*.ts"
|
||||||
out-file-path: 'public/ironrdp-pkg'
|
out-file-path: 'public/ironrdp-pkg'
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
repository: netbirdio/IronRDP
|
repository: netbirdio/IronRDP
|
||||||
tag: v0.0.2
|
latest: true
|
||||||
fileName: "*.js"
|
fileName: "*.js"
|
||||||
out-file-path: 'public/ironrdp-pkg'
|
out-file-path: 'public/ironrdp-pkg'
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
repository: netbirdio/IronRDP
|
repository: netbirdio/IronRDP
|
||||||
tag: v0.0.2
|
latest: true
|
||||||
fileName: "ironrdp_web_bg.wasm"
|
fileName: "ironrdp_web_bg.wasm"
|
||||||
out-file-path: 'public/ironrdp-pkg'
|
out-file-path: 'public/ironrdp-pkg'
|
||||||
|
|
||||||
@@ -99,14 +99,12 @@ jobs:
|
|||||||
type=sha
|
type=sha
|
||||||
|
|
||||||
- name: Log in to Docker Hub
|
- name: Log in to Docker Hub
|
||||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
|
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.NB_DOCKER_USER }}
|
username: ${{ secrets.NB_DOCKER_USER }}
|
||||||
password: ${{ secrets.NB_DOCKER_TOKEN }}
|
password: ${{ secrets.NB_DOCKER_TOKEN }}
|
||||||
|
|
||||||
- name: Log in to the GitHub Container registry
|
- name: Log in to the GitHub Container registry
|
||||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
|
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
@@ -118,12 +116,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: docker/Dockerfile
|
file: docker/Dockerfile
|
||||||
push: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
|
push: true
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm
|
platforms: linux/amd64,linux/arm64,linux/arm
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
||||||
- if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
|
- run: |
|
||||||
run: |
|
|
||||||
echo '### Pushed tags' >> $GITHUB_STEP_SUMMARY
|
echo '### Pushed tags' >> $GITHUB_STEP_SUMMARY
|
||||||
echo '${{ steps.meta.outputs.tags }}' >> $GITHUB_STEP_SUMMARY
|
echo '${{ steps.meta.outputs.tags }}' >> $GITHUB_STEP_SUMMARY
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
name: Bump netbird wasm client
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
tag:
|
|
||||||
description: 'NetBird release tag (e.g. v0.78.0)'
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ inputs.tag }}
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
bump:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
pull-requests: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: main
|
|
||||||
token: ${{ secrets.NETBIRD_DEV_BOT_GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Configure git
|
|
||||||
run: |
|
|
||||||
git config --global user.email "dev@netbird.io"
|
|
||||||
git config --global user.name "netbirddev"
|
|
||||||
|
|
||||||
# The tag rides in env and is validated before use, so a crafted dispatch
|
|
||||||
# input cannot expand into shell source or reach the sed expression.
|
|
||||||
- name: Update the default wasm path
|
|
||||||
id: bump
|
|
||||||
env:
|
|
||||||
TAG: ${{ inputs.tag }}
|
|
||||||
run: |
|
|
||||||
if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
||||||
echo "Refusing tag '$TAG': expected vMAJOR.MINOR.PATCH"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
sed -i "s|https://pkgs.netbird.io/wasm/client/v[0-9.]*|https://pkgs.netbird.io/wasm/client/${TAG}|" src/utils/config.ts
|
|
||||||
|
|
||||||
branch="bump-netbird-wasm-${TAG#v}"
|
|
||||||
echo "branch=${branch}" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
# The branch name is derived from the tag, so a re-dispatch of the
|
|
||||||
# same release would collide with the branch and pull request an
|
|
||||||
# earlier run left behind.
|
|
||||||
if git ls-remote --exit-code --heads origin "${branch}" >/dev/null 2>&1; then
|
|
||||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "Branch ${branch} already exists, ${TAG} was handled by an earlier run"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
git checkout -b "${branch}"
|
|
||||||
git add src/utils/config.ts
|
|
||||||
if git diff --cached --quiet; then
|
|
||||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
|
||||||
echo "Default wasm path already at ${TAG}, nothing to do"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
echo "skip=false" >> "$GITHUB_OUTPUT"
|
|
||||||
git commit -m "Bump the WASM client to ${TAG}"
|
|
||||||
git push --set-upstream origin "${branch}"
|
|
||||||
|
|
||||||
- name: Create pull request
|
|
||||||
if: steps.bump.outputs.skip != 'true'
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.NETBIRD_DEV_BOT_GITHUB_TOKEN }}
|
|
||||||
TAG: ${{ inputs.tag }}
|
|
||||||
BRANCH: ${{ steps.bump.outputs.branch }}
|
|
||||||
run: |
|
|
||||||
gh pr create \
|
|
||||||
--base main \
|
|
||||||
--head "$BRANCH" \
|
|
||||||
--title "Bump the WASM client to ${TAG}" \
|
|
||||||
--body "Automated wasm path bump triggered by netbird release ${TAG}."
|
|
||||||
@@ -101,61 +101,17 @@ jobs:
|
|||||||
echo "Using reverse-proxy tag: $TAG"
|
echo "Using reverse-proxy tag: $TAG"
|
||||||
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Restore geolocation database cache
|
- name: Setup test environment
|
||||||
id: geo-cache
|
|
||||||
uses: actions/cache/restore@v4
|
|
||||||
with:
|
|
||||||
path: e2e/environment/geo-cache
|
|
||||||
key: geolite-dbs-v1
|
|
||||||
|
|
||||||
- name: Build dashboard and set up test environment
|
|
||||||
env:
|
env:
|
||||||
MANAGEMENT_IMAGE_TAG: ${{ steps.management_tag.outputs.tag }}
|
MANAGEMENT_IMAGE_TAG: ${{ steps.management_tag.outputs.tag }}
|
||||||
REVERSE_PROXY_IMAGE_TAG: ${{ steps.reverse_proxy_tag.outputs.tag }}
|
REVERSE_PROXY_IMAGE_TAG: ${{ steps.reverse_proxy_tag.outputs.tag }}
|
||||||
# The docker environment (image pulls, Zitadel bootstrap) is
|
run: cd ./e2e/environment && bash create-test-env.sh
|
||||||
# network-bound and the Next build is CPU-bound, so they overlap.
|
|
||||||
# The build reads .test-config.json via the @/config/test alias,
|
|
||||||
# and create-test-env.sh renders that file only after the Zitadel
|
|
||||||
# bootstrap — so the build waits for it before starting.
|
|
||||||
run: |
|
|
||||||
(cd ./e2e/environment && bash create-test-env.sh) > env-setup.log 2>&1 &
|
|
||||||
ENV_PID=$!
|
|
||||||
until [ -s .test-config.json ] && jq empty .test-config.json 2>/dev/null; do
|
|
||||||
if ! kill -0 "$ENV_PID" 2>/dev/null; then break; fi
|
|
||||||
sleep 2
|
|
||||||
done
|
|
||||||
if ! [ -s .test-config.json ]; then
|
|
||||||
echo "::error::create-test-env.sh exited before rendering .test-config.json"
|
|
||||||
cat env-setup.log
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
# Lowest CPU priority: the containers must win the scheduler, or
|
|
||||||
# the build can starve management past the proxy-registration wait.
|
|
||||||
if ! nice -n 19 env APP_ENV=test npx next build; then
|
|
||||||
kill "$ENV_PID" 2>/dev/null || true
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if ! wait "$ENV_PID"; then
|
|
||||||
echo "::error::Test environment setup failed"
|
|
||||||
cat env-setup.log
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
cat env-setup.log
|
|
||||||
|
|
||||||
# Saved right after env setup rather than in a post step, so a later
|
|
||||||
# test failure doesn't lose the cache.
|
|
||||||
- name: Save geolocation database cache
|
|
||||||
if: always() && steps.geo-cache.outputs.cache-hit != 'true' && hashFiles('e2e/environment/geo-cache/**') != ''
|
|
||||||
uses: actions/cache/save@v4
|
|
||||||
with:
|
|
||||||
path: e2e/environment/geo-cache
|
|
||||||
key: geolite-dbs-v1
|
|
||||||
|
|
||||||
- name: Run Playwright tests
|
- name: Run Playwright tests
|
||||||
id: playwright
|
id: playwright
|
||||||
run: |
|
run: |
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
npx playwright test --config=e2e/playwright.config.ts 2>&1 | tee playwright-output.log
|
npm run test:ci 2>&1 | tee playwright-output.log
|
||||||
|
|
||||||
- name: Append Playwright summary to job summary
|
- name: Append Playwright summary to job summary
|
||||||
if: always() && hashFiles('e2e/test-results/results.json') != ''
|
if: always() && hashFiles('e2e/test-results/results.json') != ''
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
name: Sync deploy templates to S3
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
paths:
|
|
||||||
- "templates/reverse-proxy/**"
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
id-token: write
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
sync:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
|
|
||||||
- uses: aws-actions/configure-aws-credentials@v4
|
|
||||||
with:
|
|
||||||
role-to-assume: ${{ secrets.DEPLOY_TEMPLATES_ROLE_ARN }}
|
|
||||||
aws-region: eu-central-1
|
|
||||||
|
|
||||||
- name: Validate CloudFormation template
|
|
||||||
run: |
|
|
||||||
aws cloudformation validate-template \
|
|
||||||
--template-body file://templates/reverse-proxy/netbird-proxy-cfn.yaml
|
|
||||||
|
|
||||||
- name: Upload CloudFormation template
|
|
||||||
run: |
|
|
||||||
aws s3 cp templates/reverse-proxy/netbird-proxy-cfn.yaml \
|
|
||||||
s3://netbird-deploy-templates/templates/netbird-proxy-cfn.yaml
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
name: Test cloud deploy config
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- "docker/init_react_envs.sh"
|
|
||||||
- "templates/reverse-proxy/**"
|
|
||||||
- "src/modules/reverse-proxy/clusters/ClusterCloudDeploy.tsx"
|
|
||||||
- ".github/workflows/test-cloud-deploy.yml"
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
csp-connect-src:
|
|
||||||
name: CSP allows cloud provider APIs
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install nginx
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y nginx gettext-base
|
|
||||||
|
|
||||||
- name: Prepare nginx layout expected by the init script
|
|
||||||
run: |
|
|
||||||
sudo mkdir -p /etc/nginx/http.d /usr/share/nginx/html
|
|
||||||
echo 'add_header Content-Security-Policy "placeholder" always;' | sudo tee /etc/nginx/http.d/default.conf
|
|
||||||
sudo touch /usr/share/nginx/html/OidcTrustedDomains.js.tmpl
|
|
||||||
sudo systemctl start nginx
|
|
||||||
|
|
||||||
- name: Run init script with production-like env
|
|
||||||
env:
|
|
||||||
AUTH_AUTHORITY: https://auth.example.com
|
|
||||||
AUTH_CLIENT_ID: test-client
|
|
||||||
AUTH_AUDIENCE: test-audience
|
|
||||||
AUTH_SUPPORTED_SCOPES: openid profile email
|
|
||||||
USE_AUTH0: "false"
|
|
||||||
NETBIRD_MGMT_API_ENDPOINT: https://api.example.com
|
|
||||||
run: sudo -E bash docker/init_react_envs.sh
|
|
||||||
|
|
||||||
- name: Assert provider APIs are in connect-src
|
|
||||||
run: |
|
|
||||||
CSP=$(grep -o 'Content-Security-Policy "[^"]*"' /etc/nginx/http.d/default.conf)
|
|
||||||
echo "Generated CSP: $CSP"
|
|
||||||
CONNECT_SRC=$(echo "$CSP" | sed 's/.*connect-src \([^;]*\);.*/\1/')
|
|
||||||
echo "connect-src: $CONNECT_SRC"
|
|
||||||
status=0
|
|
||||||
for origin in https://api.hetzner.cloud https://api.digitalocean.com; do
|
|
||||||
if echo "$CONNECT_SRC" | grep -qF "$origin"; then
|
|
||||||
echo "OK: $origin"
|
|
||||||
else
|
|
||||||
echo "MISSING in connect-src: $origin"
|
|
||||||
status=1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
exit $status
|
|
||||||
|
|
||||||
cfn-template-url:
|
|
||||||
name: CloudFormation template URL is live
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Extract template URL from component and check it
|
|
||||||
run: |
|
|
||||||
URL=$(grep -o 'https://[^"]*netbird-proxy-cfn\.yaml' src/modules/reverse-proxy/clusters/ClusterCloudDeploy.tsx)
|
|
||||||
echo "CFN_TEMPLATE_URL: $URL"
|
|
||||||
test -n "$URL"
|
|
||||||
# Non-blocking: the template is published by sync-deploy-templates on
|
|
||||||
# the default branch, so it may not exist yet for a PR that only edits
|
|
||||||
# the URL. Warn instead of failing the check.
|
|
||||||
if curl -sfI "$URL" >/dev/null; then
|
|
||||||
echo "OK: template URL is live"
|
|
||||||
else
|
|
||||||
echo "::warning::CloudFormation template URL is not reachable yet: $URL"
|
|
||||||
fi
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
name: Unit Tests
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
# Cancel superseded runs on the same ref so a new push doesn't queue behind an
|
|
||||||
# outdated one (mirrors build_and_push.yml).
|
|
||||||
concurrency:
|
|
||||||
group: unit-tests-${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
vitest:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
|
|
||||||
- name: setup-node
|
|
||||||
uses: actions/setup-node@v5
|
|
||||||
with:
|
|
||||||
node-version: '20'
|
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm ci
|
|
||||||
|
|
||||||
- name: Run unit tests
|
|
||||||
run: npm run test:unit
|
|
||||||
@@ -44,7 +44,6 @@ e2e/test-results/
|
|||||||
e2e/playwright-report/
|
e2e/playwright-report/
|
||||||
/test-results/
|
/test-results/
|
||||||
/playwright-report/
|
/playwright-report/
|
||||||
playwright-report*.zip
|
|
||||||
.configs/.local-config.zitadel.json
|
.configs/.local-config.zitadel.json
|
||||||
.configs/.staging-config.json
|
.configs/.staging-config.json
|
||||||
.configs/.temp-config.json
|
.configs/.temp-config.json
|
||||||
|
|||||||
+3
-3
@@ -1,8 +1,8 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"tag": "New",
|
"tag": "Preview",
|
||||||
"text": "The new NetBird desktop app is here - now available in the v0.75 release.",
|
"text": "The new NetBird desktop app is here - now available as a 0.75 release candidate.",
|
||||||
"link": "https://netbird.io/knowledge-hub/netbird-v0-75-new-desktop-app",
|
"link": "https://github.com/netbirdio/netbird/discussions/6483",
|
||||||
"linkText": "Learn more",
|
"linkText": "Learn more",
|
||||||
"variant": "important",
|
"variant": "important",
|
||||||
"isExternal": true,
|
"isExternal": true,
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# Build the netbird-dashboard Docker image for linux/amd64 and export it as a
|
|
||||||
# portable tarball that can be loaded and run on a remote server.
|
|
||||||
#
|
|
||||||
# The dashboard image is nginx serving a Next.js *static export*: the Dockerfile
|
|
||||||
# only COPYs the pre-built out/ directory, so we build out/ on the host first
|
|
||||||
# (the static files are arch-independent) and then assemble the amd64 image.
|
|
||||||
#
|
|
||||||
# Usage:
|
|
||||||
# ./build.sh # build + export netbird-dashboard.tar.gz
|
|
||||||
# IMAGE_TAG=v1 ./build.sh # override the image tag
|
|
||||||
# SKIP_BUILD=1 ./build.sh # reuse an existing out/ (skip npm build)
|
|
||||||
#
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# Always run relative to this script's directory (the project root).
|
|
||||||
cd "$(dirname "$0")"
|
|
||||||
|
|
||||||
IMAGE_NAME="${IMAGE_NAME:-netbird-dashboard}"
|
|
||||||
IMAGE_TAG="${IMAGE_TAG:-amd64}"
|
|
||||||
IMAGE="${IMAGE_NAME}:${IMAGE_TAG}"
|
|
||||||
OUTPUT="${OUTPUT:-${IMAGE_NAME}.tar.gz}"
|
|
||||||
|
|
||||||
# Build the static export (out/) unless told to reuse an existing one. Next 16
|
|
||||||
# no longer runs ESLint during `next build`; types are checked by the build via
|
|
||||||
# tsc (verify separately with `npx tsc --noEmit`).
|
|
||||||
if [[ "${SKIP_BUILD:-0}" != "1" ]]; then
|
|
||||||
if [[ ! -d node_modules ]]; then
|
|
||||||
echo "==> Installing dependencies (npm ci)"
|
|
||||||
npm ci
|
|
||||||
fi
|
|
||||||
echo "==> Building static export (next build) into out/"
|
|
||||||
npx next build
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -d out ]]; then
|
|
||||||
echo "ERROR: out/ not found — the static export did not build." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# The .dockerignore lives under docker/, but Docker reads it from the build
|
|
||||||
# context root. Stage it for the duration of the build so node_modules/.next
|
|
||||||
# don't get shipped into the build context.
|
|
||||||
cleanup() { rm -f .dockerignore; }
|
|
||||||
trap cleanup EXIT
|
|
||||||
cp docker/.dockerignore .dockerignore
|
|
||||||
|
|
||||||
echo "==> Building ${IMAGE} for linux/amd64"
|
|
||||||
docker build \
|
|
||||||
--platform linux/amd64 \
|
|
||||||
-f docker/Dockerfile \
|
|
||||||
-t "${IMAGE}" \
|
|
||||||
.
|
|
||||||
|
|
||||||
echo "==> Exporting ${IMAGE} to ${OUTPUT}"
|
|
||||||
docker save "${IMAGE}" | gzip > "${OUTPUT}"
|
|
||||||
|
|
||||||
echo "==> Done: ${OUTPUT} ($(du -h "${OUTPUT}" | cut -f1))"
|
|
||||||
echo
|
|
||||||
echo "Copy and run on the server:"
|
|
||||||
echo " scp ${OUTPUT} user@your-server:/tmp/"
|
|
||||||
echo " docker load < /tmp/${OUTPUT}"
|
|
||||||
echo
|
|
||||||
echo "Run (nginx serves on container port 80). Set the runtime env vars the"
|
|
||||||
echo "dashboard templates at startup — for the Agent Network onboarding test,"
|
|
||||||
echo "flip NETBIRD_AGENT_NETWORK_ONLY=true:"
|
|
||||||
echo " docker run -d --name ${IMAGE_NAME} --restart unless-stopped \\"
|
|
||||||
echo " -p 8080:80 \\"
|
|
||||||
echo " -e NETBIRD_MGMT_API_ENDPOINT=https://your-mgmt:443 \\"
|
|
||||||
echo " -e AUTH_AUTHORITY=https://your-idp/realms/netbird \\"
|
|
||||||
echo " -e AUTH_CLIENT_ID=netbird-dashboard \\"
|
|
||||||
echo " -e AUTH_AUDIENCE=netbird-dashboard \\"
|
|
||||||
echo " -e AUTH_SUPPORTED_SCOPES='openid profile email' \\"
|
|
||||||
echo " -e USE_AUTH0=false \\"
|
|
||||||
echo " -e NETBIRD_AGENT_NETWORK_ONLY=true \\"
|
|
||||||
echo " ${IMAGE}"
|
|
||||||
@@ -18,8 +18,6 @@
|
|||||||
"wasmPath": "$NETBIRD_WASM_PATH",
|
"wasmPath": "$NETBIRD_WASM_PATH",
|
||||||
"licensed": "$NETBIRD_LICENSED",
|
"licensed": "$NETBIRD_LICENSED",
|
||||||
"cloud": "$NETBIRD_CLOUD",
|
"cloud": "$NETBIRD_CLOUD",
|
||||||
"agentNetworkOnly": "$NETBIRD_AGENT_NETWORK_ONLY",
|
|
||||||
"agentNetworkEnabled": "$NETBIRD_AGENT_NETWORK_ENABLED",
|
|
||||||
"hubspotPortalId": "$NETBIRD_HUBSPOT_PORTAL_ID",
|
"hubspotPortalId": "$NETBIRD_HUBSPOT_PORTAL_ID",
|
||||||
"hubspotSignupFormId": "$NETBIRD_HUBSPOT_SIGNUP_FORM_ID",
|
"hubspotSignupFormId": "$NETBIRD_HUBSPOT_SIGNUP_FORM_ID",
|
||||||
"hubspotOnboardingFormId": "$NETBIRD_HUBSPOT_ONBOARDING_FORM_ID",
|
"hubspotOnboardingFormId": "$NETBIRD_HUBSPOT_ONBOARDING_FORM_ID",
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
# The image only needs the pre-built static export (out/) and the docker/
|
|
||||||
# config files. Keep the build context small by dropping everything heavy and
|
|
||||||
# irrelevant — without this, `docker build .` ships node_modules and .next.
|
|
||||||
node_modules
|
|
||||||
.next
|
|
||||||
.git
|
|
||||||
.github
|
|
||||||
e2e
|
|
||||||
src
|
|
||||||
public
|
|
||||||
*.tar.gz
|
|
||||||
*.tar
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
FROM alpine:3.24
|
FROM alpine:3.14
|
||||||
|
|
||||||
RUN apk add --no-cache bash curl less ca-certificates git tzdata zip gettext \
|
RUN apk add --no-cache bash curl less ca-certificates git tzdata zip gettext \
|
||||||
nginx curl supervisor certbot-nginx && \
|
nginx curl supervisor certbot-nginx && \
|
||||||
|
|||||||
@@ -66,8 +66,6 @@ export NETBIRD_WASM_PATH=${NETBIRD_WASM_PATH}
|
|||||||
export NETBIRD_CSP=${NETBIRD_CSP}
|
export NETBIRD_CSP=${NETBIRD_CSP}
|
||||||
export NETBIRD_LICENSED=${NETBIRD_LICENSED:-false}
|
export NETBIRD_LICENSED=${NETBIRD_LICENSED:-false}
|
||||||
export NETBIRD_CLOUD=${NETBIRD_CLOUD:-false}
|
export NETBIRD_CLOUD=${NETBIRD_CLOUD:-false}
|
||||||
export NETBIRD_AGENT_NETWORK_ONLY=${NETBIRD_AGENT_NETWORK_ONLY:-false}
|
|
||||||
export NETBIRD_AGENT_NETWORK_ENABLED=${NETBIRD_AGENT_NETWORK_ENABLED:-false}
|
|
||||||
export NETBIRD_HUBSPOT_PORTAL_ID=${NETBIRD_HUBSPOT_PORTAL_ID}
|
export NETBIRD_HUBSPOT_PORTAL_ID=${NETBIRD_HUBSPOT_PORTAL_ID}
|
||||||
export NETBIRD_HUBSPOT_SIGNUP_FORM_ID=${NETBIRD_HUBSPOT_SIGNUP_FORM_ID}
|
export NETBIRD_HUBSPOT_SIGNUP_FORM_ID=${NETBIRD_HUBSPOT_SIGNUP_FORM_ID}
|
||||||
export NETBIRD_HUBSPOT_ONBOARDING_FORM_ID=${NETBIRD_HUBSPOT_ONBOARDING_FORM_ID}
|
export NETBIRD_HUBSPOT_ONBOARDING_FORM_ID=${NETBIRD_HUBSPOT_ONBOARDING_FORM_ID}
|
||||||
@@ -80,7 +78,7 @@ echo "NetBird latest version: ${NETBIRD_LATEST_VERSION}"
|
|||||||
FIRST_PARTY_CSP="pkgs.netbird.io"
|
FIRST_PARTY_CSP="pkgs.netbird.io"
|
||||||
FIRST_PARTY_CSP_CONNECT_SRC="wss://*.netbird.io"
|
FIRST_PARTY_CSP_CONNECT_SRC="wss://*.netbird.io"
|
||||||
THIRD_PARTY_CSP="*.licdn.com *.linkedin.com *.vector.co *.sibforms.com *.hotjar.com *.hotjar.io *.redditstatic.com pixel-config.reddit.com *.clarity.ms c.bing.com *.microsoft.com googleads.g.doubleclick.net pagead2.googlesyndication.com www.google.com www.googleadservices.com *.google-analytics.com *.googletagmanager.com analytics.google.com *.hubapi.com *.hs-banner.com *.hubspot.com *.hubspot.net js.hs-analytics.com *.hsforms.net *.hscollectedforms.net *.hs-analytics.net *.hsforms.com track.hubspot.com *.hsadspixel.net static.hsappstatic.net"
|
THIRD_PARTY_CSP="*.licdn.com *.linkedin.com *.vector.co *.sibforms.com *.hotjar.com *.hotjar.io *.redditstatic.com pixel-config.reddit.com *.clarity.ms c.bing.com *.microsoft.com googleads.g.doubleclick.net pagead2.googlesyndication.com www.google.com www.googleadservices.com *.google-analytics.com *.googletagmanager.com analytics.google.com *.hubapi.com *.hs-banner.com *.hubspot.com *.hubspot.net js.hs-analytics.com *.hsforms.net *.hscollectedforms.net *.hs-analytics.net *.hsforms.com track.hubspot.com *.hsadspixel.net static.hsappstatic.net"
|
||||||
THIRD_PARTY_CSP_CONNECT_SRC="https://api.github.com/repos/netbirdio/netbird/releases/latest https://raw.githubusercontent.com/netbirdio/dashboard/ wss://ws.hotjar.com https://api.hetzner.cloud https://api.digitalocean.com"
|
THIRD_PARTY_CSP_CONNECT_SRC="https://api.github.com/repos/netbirdio/netbird/releases/latest https://raw.githubusercontent.com/netbirdio/dashboard/ wss://ws.hotjar.com"
|
||||||
THIRD_PARTY_CSP_SCRIPT_SRC="'sha256-7knV6EIjKUvCpYWE2rCYx8dYV2WCNb2bpTuitFXzBcA=' *.hs-scripts.com"
|
THIRD_PARTY_CSP_SCRIPT_SRC="'sha256-7knV6EIjKUvCpYWE2rCYx8dYV2WCNb2bpTuitFXzBcA=' *.hs-scripts.com"
|
||||||
|
|
||||||
CSP_DOMAINS=""
|
CSP_DOMAINS=""
|
||||||
@@ -93,8 +91,6 @@ fi
|
|||||||
# Add AUTH_AUTHORITY to CSP
|
# Add AUTH_AUTHORITY to CSP
|
||||||
if [[ -n "${AUTH_AUTHORITY}" ]]; then
|
if [[ -n "${AUTH_AUTHORITY}" ]]; then
|
||||||
CSP_DOMAINS="$CSP_DOMAINS $AUTH_AUTHORITY"
|
CSP_DOMAINS="$CSP_DOMAINS $AUTH_AUTHORITY"
|
||||||
AUTH_AUTHORITY_ORIGIN=$(echo "$AUTH_AUTHORITY" | sed -E 's|^(https?://[^/]+).*|\1|')
|
|
||||||
CSP_DOMAINS="$CSP_DOMAINS $AUTH_AUTHORITY_ORIGIN"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Add AUTH_AUDIENCE to CSP
|
# Add AUTH_AUDIENCE to CSP
|
||||||
@@ -141,18 +137,8 @@ CSP_CONNECT_SRC=$(echo $CSP_CONNECT_SRC | tr ' ' '\n' | sort -u | tr '\n' ' ' |
|
|||||||
CSP_FRAME_SRC=$(echo $CSP_FRAME_SRC | tr ' ' '\n' | sort -u | tr '\n' ' ' | sed 's/ $//')
|
CSP_FRAME_SRC=$(echo $CSP_FRAME_SRC | tr ' ' '\n' | sort -u | tr '\n' ' ' | sed 's/ $//')
|
||||||
CSP_SCRIPT_SRC=$(echo $CSP_SCRIPT_SRC | tr ' ' '\n' | sort -u | tr '\n' ' ' | sed 's/ $//')
|
CSP_SCRIPT_SRC=$(echo $CSP_SCRIPT_SRC | tr ' ' '\n' | sort -u | tr '\n' ' ' | sed 's/ $//')
|
||||||
|
|
||||||
# upgrade-insecure-requests tells the browser to rewrite every http subresource,
|
|
||||||
# fetch and WebSocket to https/wss. That is correct for https deployments but breaks
|
|
||||||
# plain-http ones (e.g. local or self-hosted over http), where it would rewrite the
|
|
||||||
# working http/ws endpoints to unreachable https/wss. Emit it only when the backend
|
|
||||||
# is served over https, matching the ws:// vs wss:// scheme logic above.
|
|
||||||
CSP_UPGRADE_INSECURE=" upgrade-insecure-requests;"
|
|
||||||
if [[ "$NETBIRD_MGMT_API_ENDPOINT" == http://* || "$AUTH_AUTHORITY" == http://* ]]; then
|
|
||||||
CSP_UPGRADE_INSECURE=""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Update CSP in nginx config
|
# Update CSP in nginx config
|
||||||
CSP_POLICY="default-src 'none'; connect-src 'self' $CSP_CONNECT_SRC; frame-src 'self' $CSP_FRAME_SRC; script-src 'self' 'wasm-unsafe-eval' $CSP_SCRIPT_SRC; font-src 'self'; img-src * data:; manifest-src 'self'; style-src 'self' 'unsafe-inline'; frame-ancestors 'self'; base-uri 'self'; form-action 'self';$CSP_UPGRADE_INSECURE"
|
CSP_POLICY="default-src 'none'; connect-src 'self' $CSP_CONNECT_SRC; frame-src 'self' $CSP_FRAME_SRC; script-src 'self' 'wasm-unsafe-eval' $CSP_SCRIPT_SRC; font-src 'self'; img-src * data:; manifest-src 'self'; style-src 'self' 'unsafe-inline'; frame-ancestors 'self'; base-uri 'self'; form-action 'self'; upgrade-insecure-requests;"
|
||||||
CSP_HEADER="add_header Content-Security-Policy \"$CSP_POLICY\" always;"
|
CSP_HEADER="add_header Content-Security-Policy \"$CSP_POLICY\" always;"
|
||||||
|
|
||||||
echo "CSP header: $CSP_HEADER"
|
echo "CSP header: $CSP_HEADER"
|
||||||
@@ -163,7 +149,7 @@ sed -i "s|add_header Content-Security-Policy \"[^\"]*\" always;|$CSP_HEADER|g" /
|
|||||||
}
|
}
|
||||||
|
|
||||||
# replace ENVs in the config
|
# replace ENVs in the config
|
||||||
ENV_STR="\$\$USE_AUTH0 \$\$AUTH_AUDIENCE \$\$AUTH_AUTHORITY \$\$AUTH_CLIENT_ID \$\$AUTH_CLIENT_SECRET \$\$AUTH_SUPPORTED_SCOPES \$\$NETBIRD_MGMT_API_ENDPOINT \$\$NETBIRD_MGMT_GRPC_API_ENDPOINT \$\$NETBIRD_HOTJAR_TRACK_ID \$\$NETBIRD_GOOGLE_ANALYTICS_ID \$\$NETBIRD_GOOGLE_TAG_MANAGER_ID \$\$AUTH_REDIRECT_URI \$\$AUTH_SILENT_REDIRECT_URI \$\$NETBIRD_TOKEN_SOURCE \$\$NETBIRD_DRAG_QUERY_PARAMS \$\$NETBIRD_AUTH_SERVICE_URL \$\$NETBIRD_WASM_PATH \$\$NETBIRD_LICENSED \$\$NETBIRD_CLOUD \$\$NETBIRD_AGENT_NETWORK_ONLY \$\$NETBIRD_AGENT_NETWORK_ENABLED \$\$NETBIRD_HUBSPOT_PORTAL_ID \$\$NETBIRD_HUBSPOT_SIGNUP_FORM_ID \$\$NETBIRD_HUBSPOT_ONBOARDING_FORM_ID \$\$NETBIRD_HUBSPOT_SURVEY_FORM_ID \$\$NETBIRD_ANALYTICS_EXCLUDED_EMAILS"
|
ENV_STR="\$\$USE_AUTH0 \$\$AUTH_AUDIENCE \$\$AUTH_AUTHORITY \$\$AUTH_CLIENT_ID \$\$AUTH_CLIENT_SECRET \$\$AUTH_SUPPORTED_SCOPES \$\$NETBIRD_MGMT_API_ENDPOINT \$\$NETBIRD_MGMT_GRPC_API_ENDPOINT \$\$NETBIRD_HOTJAR_TRACK_ID \$\$NETBIRD_GOOGLE_ANALYTICS_ID \$\$NETBIRD_GOOGLE_TAG_MANAGER_ID \$\$AUTH_REDIRECT_URI \$\$AUTH_SILENT_REDIRECT_URI \$\$NETBIRD_TOKEN_SOURCE \$\$NETBIRD_DRAG_QUERY_PARAMS \$\$NETBIRD_AUTH_SERVICE_URL \$\$NETBIRD_WASM_PATH \$\$NETBIRD_LICENSED \$\$NETBIRD_CLOUD \$\$NETBIRD_HUBSPOT_PORTAL_ID \$\$NETBIRD_HUBSPOT_SIGNUP_FORM_ID \$\$NETBIRD_HUBSPOT_ONBOARDING_FORM_ID \$\$NETBIRD_HUBSPOT_SURVEY_FORM_ID \$\$NETBIRD_ANALYTICS_EXCLUDED_EMAILS"
|
||||||
|
|
||||||
OIDC_TRUSTED_DOMAINS="/usr/share/nginx/html/OidcTrustedDomains.js"
|
OIDC_TRUSTED_DOMAINS="/usr/share/nginx/html/OidcTrustedDomains.js"
|
||||||
envsubst "$ENV_STR" < "$OIDC_TRUSTED_DOMAINS".tmpl > "$OIDC_TRUSTED_DOMAINS"
|
envsubst "$ENV_STR" < "$OIDC_TRUSTED_DOMAINS".tmpl > "$OIDC_TRUSTED_DOMAINS"
|
||||||
@@ -171,25 +157,4 @@ for f in $(grep -R -l AUTH_SUPPORTED_SCOPES /usr/share/nginx/html); do
|
|||||||
cp "$f" "$f".copy
|
cp "$f" "$f".copy
|
||||||
envsubst "$ENV_STR" < "$f".copy > "$f"
|
envsubst "$ENV_STR" < "$f".copy > "$f"
|
||||||
rm "$f".copy
|
rm "$f".copy
|
||||||
done
|
done
|
||||||
|
|
||||||
# Reload nginx so the patched CSP header takes effect.
|
|
||||||
# supervisord starts nginx (priority 100) before this script (priority 201) and
|
|
||||||
# never reloads it, so without this nginx keeps serving the static default.conf
|
|
||||||
# CSP that has no connect-src, breaking OIDC discovery over plain HTTP.
|
|
||||||
reloaded=false
|
|
||||||
for i in $(seq 1 10); do
|
|
||||||
if nginx -s reload 2>/dev/null; then
|
|
||||||
echo "Reloaded nginx to apply updated CSP configuration"
|
|
||||||
reloaded=true
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
echo "Waiting for nginx to be ready before reload (attempt $i)..."
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ "$reloaded" != true ]]; then
|
|
||||||
echo "Failed to reload nginx after patching CSP header" >&2
|
|
||||||
nginx -t || true
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 23 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB |
@@ -218,7 +218,6 @@ await visitByNavigation(page, "Policies"); // Click child
|
|||||||
| Notifications | `settings-notifications-email.spec.ts`, `settings-notifications-slack.spec.ts`, `settings-notifications-webhook.spec.ts` | `@notifications` |
|
| Notifications | `settings-notifications-email.spec.ts`, `settings-notifications-slack.spec.ts`, `settings-notifications-webhook.spec.ts` | `@notifications` |
|
||||||
| Team | `team-users.spec.ts`, `team-service-users.spec.ts`, `team-users-approval-and-billing.spec.ts` | `@team` |
|
| Team | `team-users.spec.ts`, `team-service-users.spec.ts`, `team-users-approval-and-billing.spec.ts` | `@team` |
|
||||||
| Setup Keys | `setup-keys.spec.ts` | `@setup-keys` |
|
| Setup Keys | `setup-keys.spec.ts` | `@setup-keys` |
|
||||||
| Control Center | `control-center-*.spec.ts` (`-draft`, `-draft-connections`, `-draft-matrix`, `-draft-extras`, `-draft-install`, `-draft-remove`, `-draft-shortcuts`, `-deploy`, `-drilldown`, `-live`, `-peers`) | `@control-center` |
|
|
||||||
|
|
||||||
## Debugging
|
## Debugging
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
# Ignore zitadel environment
|
# Ignore zitadel environment
|
||||||
.env
|
.env
|
||||||
Caddyfile
|
Caddyfile
|
||||||
agentgateway-stub.Caddyfile
|
|
||||||
management.json
|
management.json
|
||||||
turnserver.conf
|
turnserver.conf
|
||||||
zitadel.env
|
zitadel.env
|
||||||
@@ -10,6 +9,4 @@ proxy-no-ports.env
|
|||||||
proxy-certs/
|
proxy-certs/
|
||||||
proxy-certs-no-ports/
|
proxy-certs-no-ports/
|
||||||
docker-compose.yml
|
docker-compose.yml
|
||||||
/machinekey
|
/machinekey
|
||||||
geo-cache/
|
|
||||||
geo-dump/
|
|
||||||
@@ -19,7 +19,7 @@ check_docker_compose() {
|
|||||||
DOCKER_COMPOSE_COMMAND=$(check_docker_compose)
|
DOCKER_COMPOSE_COMMAND=$(check_docker_compose)
|
||||||
|
|
||||||
$DOCKER_COMPOSE_COMMAND down --volumes
|
$DOCKER_COMPOSE_COMMAND down --volumes
|
||||||
rm -f docker-compose.yml Caddyfile agentgateway-stub.Caddyfile zitadel.env .env dashboard.env machinekey/zitadel-admin-sa.token turnserver.conf management.json proxy.env proxy-no-ports.env
|
rm -f docker-compose.yml Caddyfile zitadel.env .env dashboard.env machinekey/zitadel-admin-sa.token turnserver.conf management.json proxy.env proxy-no-ports.env
|
||||||
rm -rf proxy-certs proxy-certs-no-ports
|
rm -rf proxy-certs proxy-certs-no-ports
|
||||||
rm -f ../../.test-config.json ../playwright.env.json
|
rm -f ../../.test-config.json ../playwright.env.json
|
||||||
rm -f ../fixtures/auth/owner.json ../fixtures/auth/user.json
|
rm -f ../fixtures/auth/owner.json ../fixtures/auth/user.json
|
||||||
Loaded 20 of 417 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user