Compare commits

..

1 Commits

11 changed files with 99776 additions and 147 deletions

View File

@@ -1,20 +0,0 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 10
labels:
- dependencies
- github-actions
- package-ecosystem: docker
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 10
labels:
- dependencies
- docker

View File

@@ -13,10 +13,6 @@ permissions:
security-events: write security-events: write
statuses: read statuses: read
concurrency:
group: docker-release-${{ github.ref }}
cancel-in-progress: true
on: on:
pull_request: pull_request:
branches: branches:
@@ -32,9 +28,14 @@ jobs:
Docker_Build: Docker_Build:
name: Docker Build And Release name: Docker Build And Release
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
arch: [amd64, arm64]
version: [1.12.2]
steps: steps:
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v6 uses: actions/checkout@v4
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v3 uses: docker/setup-qemu-action@v3
@@ -43,7 +44,6 @@ jobs:
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: Login to Registry - name: Login to Registry
if: github.event_name != 'pull_request'
id: login id: login
uses: docker/login-action@v3 uses: docker/login-action@v3
with: with:
@@ -53,28 +53,46 @@ jobs:
- name: Build - name: Build
id: docker_build id: docker_build
uses: docker/build-push-action@v6 uses: docker/build-push-action@v5
with: with:
context: . context: .
build-args: | build-args: |
VERSION=1.16.0-2 ARCH=${{ matrix.arch }}
push: ${{ github.event_name != 'pull_request' }} VERSION=${{ matrix.version }}
platforms: linux/amd64,linux/arm64 push: true
tags: ${{ env.REGISTRY_IMAGE }}:latest platforms: linux/${{ matrix.arch }}
provenance: false outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true
sbom: false
outputs: type=registry,compression=zstd,compression-level=6,oci-mediatypes=true,force-compression=true
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Export Digests
run: |
mkdir -p /tmp/digests
digest="${{ steps.docker_build.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v3
with:
name: digests
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1
MergeRefs: MergeRefs:
name: Publish Multi-Arch Image And Release name: Do The Horrible Merge Thing
if: github.ref == 'refs/heads/main' if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: needs:
- Docker_Build - Docker_Build
steps: steps:
- name: Download digests
uses: actions/download-artifact@v3
with:
name: digests
path: /tmp/digests
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Registry - name: Login to Registry
id: login id: login
uses: docker/login-action@v3 uses: docker/login-action@v3
@@ -83,6 +101,25 @@ jobs:
username: ${{ secrets.REGISTRY_USERNAME }} username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }} password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY_IMAGE }}
tags: |
# set latest tag for default branch
# https://github.com/docker/metadata-action#latest-tag
type=raw,value=latest,enable={{is_default_branch}}
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
- name: Inspect image
run: |
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }}
- name: Generate SBOM - name: Generate SBOM
uses: anchore/sbom-action@v0 uses: anchore/sbom-action@v0
id: sbom id: sbom
@@ -94,7 +131,7 @@ jobs:
output-file: ./sbom.spdx.json output-file: ./sbom.spdx.json
- name: Scan SBOM - name: Scan SBOM
uses: anchore/scan-action@v7 uses: anchore/scan-action@v3
id: scan id: scan
with: with:
sbom: sbom.spdx.json sbom: sbom.spdx.json
@@ -103,15 +140,15 @@ jobs:
only-fixed: true only-fixed: true
- name: upload Anchore scan SARIF report - name: upload Anchore scan SARIF report
uses: github/codeql-action/upload-sarif@v4 uses: github/codeql-action/upload-sarif@v2
with: with:
sarif_file: ${{ steps.scan.outputs.sarif }} sarif_file: ${{ steps.scan.outputs.sarif }}
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v6 uses: actions/checkout@v4
- name: Changelog - name: Changelog
uses: TriPSs/conventional-changelog-action@v6 uses: TriPSs/conventional-changelog-action@v3
id: changelog id: changelog
if: ${{ github.event_name != 'pull_request' }} if: ${{ github.event_name != 'pull_request' }}
with: with:
@@ -124,11 +161,11 @@ jobs:
skip-on-empty: false # otherwise we don't publish fixes skip-on-empty: false # otherwise we don't publish fixes
- name: Create Release - name: Create Release
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v1
id: release id: release
if: ${{ steps.changelog.outputs.skipped == 'false' }} if: ${{ steps.changelog.outputs.skipped == 'false' }}
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.github_token }}
with: with:
tag_name: ${{ steps.changelog.outputs.tag }} tag_name: ${{ steps.changelog.outputs.tag }}
name: ${{ steps.changelog.outputs.tag }} name: ${{ steps.changelog.outputs.tag }}

2
.gitignore vendored
View File

@@ -1,2 +0,0 @@
sbom.spdx.json
results.sarif

View File

@@ -1,33 +1,3 @@
## [1.2.4](https://github.com/dangeroustech/ZeroTierBridge/compare/v1.2.3...v1.2.4) (2025-10-26)
## [1.2.3](https://github.com/dangeroustech/ZeroTierBridge/compare/v1.2.2...v1.2.3) (2025-10-26)
## [1.2.2](https://github.com/dangeroustech/ZeroTierBridge/compare/v1.2.1...v1.2.2) (2025-10-26)
## [1.2.1](https://github.com/dangeroustech/ZeroTierBridge/compare/v1.2.0...v1.2.1) (2025-10-26)
# [1.2.0](https://github.com/dangeroustech/ZeroTierBridge/compare/v1.1.2...v1.2.0) (2025-10-26)
### Bug Fixes
* **workflow:** update artifact naming and handling in docker-build.yml ([96ebbf8](https://github.com/dangeroustech/ZeroTierBridge/commit/96ebbf805d2cb3bb4089a5a0dc70114e3c16cc1b))
### Features
* **docker:** add health check to Dockerfile for zerotier-cli ([7d643e3](https://github.com/dangeroustech/ZeroTierBridge/commit/7d643e3ff6c0683d335baae5138ceef475cd37c3))
## [1.1.2](https://github.com/dangeroustech/ZeroTierBridge/compare/v1.1.1...v1.1.2) (2023-10-18) ## [1.1.2](https://github.com/dangeroustech/ZeroTierBridge/compare/v1.1.1...v1.1.2) (2023-10-18)

View File

@@ -1,41 +1,19 @@
FROM debian:13.1 AS stage FROM debian:12.6 as stage
SHELL ["/bin/bash", "-o", "pipefail", "-c"] ARG PACKAGE_BASEURL=https://download.zerotier.com/debian/bookworm/pool/main/z/zerotier-one
ENV DEBIAN_FRONTEND=noninteractive ARG ARCH=amd64
ARG PACKAGE_BASEURL=https://download.zerotier.com/debian/trixie/pool/main/z/zerotier-one ARG VERSION=1.12.2
ARG TARGETARCH RUN apt-get update -qq && apt-get install -qq --no-install-recommends -y ca-certificates curl
ARG VERSION=1.16.0-2 RUN curl -sSL -o zerotier-one.deb "${PACKAGE_BASEURL}/zerotier-one_${VERSION}_${ARCH}.deb"
RUN apt-get update -qq && apt-get install -qq --no-install-recommends -y \
ca-certificates=20250419 \
curl=8.14.1-2
RUN set -e; \
DETECTED_ARCH="${TARGETARCH:-}"; \
if [ -z "$DETECTED_ARCH" ]; then DETECTED_ARCH="$(dpkg --print-architecture)"; fi; \
case "$DETECTED_ARCH" in \
amd64|x86_64) ARCH_MAPPING=amd64 ;; \
arm64|aarch64) ARCH_MAPPING=arm64 ;; \
armhf|armv7*) ARCH_MAPPING=armhf ;; \
*) echo "Unsupported architecture: $DETECTED_ARCH" >&2; exit 1 ;; \
esac; \
echo "Downloading ZeroTier: arch=$ARCH_MAPPING version=$VERSION"; \
curl -fsSL -o zerotier-one.deb "${PACKAGE_BASEURL}/zerotier-one_${VERSION}_${ARCH_MAPPING}.deb"
FROM debian:13.1 FROM debian:12.6
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
ENV DEBIAN_FRONTEND=noninteractive
ARG VERSION
RUN mkdir /app RUN mkdir /app
WORKDIR /app WORKDIR /app
COPY --from=stage zerotier-one.deb . COPY --from=stage zerotier-one.deb .
RUN apt-get update -qq && apt-get install -qq --no-install-recommends -y \ RUN apt-get update -qq && apt-get install -qq --no-install-recommends -y procps iptables openssl \
adduser=3.152 \
procps=2:4.0.4-9 \
iptables=1.8.11-2 \
openssl=3.5.1-1 \
&& apt-get clean \ && apt-get clean \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
RUN dpkg -i zerotier-one.deb && rm -f zerotier-one.deb RUN dpkg -i zerotier-one.deb && rm -f zerotier-one.deb
RUN echo "${VERSION}" >/etc/zerotier-version RUN echo "${VERSION}" >/etc/zerotier-version
COPY entrypoint.sh entrypoint.sh COPY entrypoint.sh entrypoint.sh
RUN chmod 755 entrypoint.sh RUN chmod 755 entrypoint.sh
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 CMD sh -c 'zerotier-cli info 2>/dev/null | grep -q ONLINE'
ENTRYPOINT ["/app/entrypoint.sh"] ENTRYPOINT ["/app/entrypoint.sh"]

View File

@@ -20,21 +20,21 @@ You also need to add a static route into ZeroTier so that the traffic is routed
### Docker Compose ### Docker Compose
Edit the `ZT_NETWORKS` variable in `docker-compose.yml` to add your networks. Multi-arch images are published automatically; no architecture changes are needed. **You need to edit the `ZT_NETWORKS` and `ARCH` variable in the `docker-compose.yml` file first to add your networks and make sure your acrhitecture is correct (see [this page](http://download.zerotier.com/debian/buster/pool/main/z/zerotier-one/) for examples, usually either amd64 or arm64)**
Easiest way to bring up is via Docker Compose. Rename `docker-compose.yml.example` to `docker-compose.yml` and run `docker compose up -d`. Easiest way to bring up is via Docker Compose. Rename `docker-compose.yml.example` to `docker-compose.yml` and run `docker compose up -d`.
If you want to disable bridging, set `ZT_BRIDGE=false`. This can be done after the initial networks have been joined (just change the environment variable in the `docker-compose.yml` file and restart), as the ZeroTier config persists but IPTables forwarding is done on each container startup. If you want to disable bridging, set `ZT_BRIDGE=false`. This can be done after the initial networks have been joined (just change the environment variable in the `docker-compose.yml` file and run `), as the ZeroTier config persists but IPTables forwarding is done on each container startup.
### OG Docker ### OG Docker
`docker build -t zerotierbridge .` `docker build -t zerotierbridge .`
`docker run --cap-add NET_ADMIN --cap-add NET_RAW --sysctl net.ipv4.ip_forward=1 -e ZT_NETWORKS="NETWORK_1 NETWORK_2" -e ZT_BRIDGE=true zerotierbridge:latest` `docker run --privileged -e ZT_NETWORKS=NETWORK_1 NETWORK_2 -e ZT_BRIDGE=true zerotierbridge:latest`
Add your network ID(s) into the `ZT_NETWORKS` argument, space separated. Add your network ID(s) into the `ZT_NETWORKS` argument, space separated.
Disable bridging by passing `ZT_BRIDGE=false`. This can be done after the initial networks have been joined (just restart the container), as the ZeroTier config persists but IPTables forwarding is done on each container startup. Disable bridging by passing `ZT_BRIDGE=false`. This can be done after the initial networks have been joined (just rebuild the container), as the ZeroTier config persists but IPTables forwarding is done on each container startup.
#### Persistent Storage #### Persistent Storage
@@ -42,6 +42,8 @@ If you would like the container to retain the same ZeroTier client ID on reboot,
`docker run --privileged -e ZT_NETWORKS=NETWORK_ID_HERE ZT_BRIDGE=true -v zt_config:/var/lib/zerotier-one/ zerotierbridge:latest` `docker run --privileged -e ZT_NETWORKS=NETWORK_ID_HERE ZT_BRIDGE=true -v zt_config:/var/lib/zerotier-one/ zerotierbridge:latest`
#### Notes #### Caveat: Architecture
If your host requires additional privileges for networking, you may need to add device and capabilities in your runtime configuration. The provided Docker Compose example includes `cap_add: [NET_ADMIN, NET_RAW]` and `sysctls` for IP forwarding. If you need to run this on a device with different architecture (a raspberry pi, for instance), then just edit line 3 of the Dockerfile.
If you were using a Raspberry Pi 4, you would change this to `ARCH=arm64` and the container will pull the correct ZeroTier installer.

View File

@@ -5,15 +5,11 @@ services:
container_name: zerotierbridge container_name: zerotierbridge
image: registry.dangerous.tech/dangeroustech/zerotierbridge image: registry.dangerous.tech/dangeroustech/zerotierbridge
restart: always restart: always
cap_add: privileged: true
- NET_ADMIN
- NET_RAW
sysctls:
net.ipv4.ip_forward: "1"
volumes: volumes:
- zt_config:/var/lib/zerotier-one - zt_config:/var/lib/zerotier-one
environment: environment:
ZT_NETWORKS: "NETWORK_ID_1 NETWORK_ID_2 NETWORK_ID_3" - ZT_NETWORKS=NETWORK_ID_1 NETWORK_ID_2 NETWORK_ID_3
ZT_BRIDGE: "true" - ZT_BRIDGE=true
volumes: volumes:
zt_config: zt_config:

View File

@@ -1,22 +1,15 @@
#!/bin/sh #!/bin/sh
set -eu grepzt() {
(find /proc -name exe | xargs -I{} readlink {}) 2>/dev/null | grep -q zerotier-one
terminate() { return $?
# Try to terminate zerotier-one gracefully
if [ -n "${ZT_PID:-}" ]; then
kill -TERM "$ZT_PID" 2>/dev/null || true
wait "$ZT_PID" 2>/dev/null || true
fi
} }
trap terminate INT TERM
echo "starting zerotier" echo "starting zerotier"
setsid /usr/sbin/zerotier-one & setsid /usr/sbin/zerotier-one &
ZT_PID=$!
# Wait for zerotier to be responsive while ! grepzt
until zerotier-cli info >/dev/null 2>&1; do do
echo "zerotier hasn't started, waiting a second" echo "zerotier hasn't started, waiting a second"
sleep 1 sleep 1
done done
@@ -24,34 +17,34 @@ done
# Set IPTables to allow NATting # Set IPTables to allow NATting
sysctl -w net.ipv4.ip_forward=1 > /dev/null sysctl -w net.ipv4.ip_forward=1 > /dev/null
echo "joining networks: ${ZT_NETWORKS:-}" echo "joining networks: $ZT_NETWORKS"
for n in ${ZT_NETWORKS:-}; do for n in $ZT_NETWORKS
do
echo "joining $n" echo "joining $n"
until zerotier-cli join "$n"; do while ! zerotier-cli join "$n"
do
echo "joining $n failed; trying again in 1s" echo "joining $n failed; trying again in 1s"
sleep 1 sleep 1
done done
if [ "${ZT_BRIDGE:-true}" = "true" ]; then if [ "$ZT_BRIDGE" = "true" ]
ZT_IFACE=$(zerotier-cli get "$n" portDeviceName) then
PHY_IFACE=eth0 echo "Configuring iptables on $(zerotier-cli get $n portDeviceName)"
echo "Configuring iptables on ${ZT_IFACE}" PHY_IFACE=eth0; ZT_IFACE=$(zerotier-cli get $n portDeviceName)
# idempotent rules iptables -t nat -A POSTROUTING -o $PHY_IFACE -j MASQUERADE
iptables -t nat -C POSTROUTING -o "$PHY_IFACE" -j MASQUERADE 2>/dev/null || iptables -t nat -A POSTROUTING -o "$PHY_IFACE" -j MASQUERADE iptables -t nat -A POSTROUTING -o $ZT_IFACE -j MASQUERADE
iptables -t nat -C POSTROUTING -o "$ZT_IFACE" -j MASQUERADE 2>/dev/null || iptables -t nat -A POSTROUTING -o "$ZT_IFACE" -j MASQUERADE iptables -A FORWARD -i $PHY_IFACE -o $ZT_IFACE -j ACCEPT
iptables -C FORWARD -i "$PHY_IFACE" -o "$ZT_IFACE" -j ACCEPT 2>/dev/null || iptables -A FORWARD -i "$PHY_IFACE" -o "$ZT_IFACE" -j ACCEPT iptables -A FORWARD -i $ZT_IFACE -o $PHY_IFACE -j ACCEPT
iptables -C FORWARD -i "$ZT_IFACE" -o "$PHY_IFACE" -j ACCEPT 2>/dev/null || iptables -A FORWARD -i "$ZT_IFACE" -o "$PHY_IFACE" -j ACCEPT
fi fi
done done
# Give ZT a second to realise it's online # Give ZT a second realise it's online
sleep 10 sleep 10
# Print Client Info # Print Client Info
zerotier-cli info || true echo "$(zerotier-cli info)"
# Keep the container running while zerotier-one is alive sleep infinity
wait "$ZT_PID"

View File

@@ -1,3 +1,3 @@
{ {
"version": "1.2.4" "version": "1.1.2"
} }

16
results.sarif Normal file
View File

@@ -0,0 +1,16 @@
{
"version": "2.1.0",
"$schema": "https://json.schemastore.org/sarif-2.1.0-rtm.5.json",
"runs": [
{
"tool": {
"driver": {
"name": "Grype",
"version": "0.63.0",
"informationUri": "https://github.com/anchore/grype"
}
},
"results": []
}
]
}

99659
sbom.spdx.json Normal file

File diff suppressed because it is too large Load Diff