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
statuses: read
concurrency:
group: docker-release-${{ github.ref }}
cancel-in-progress: true
on:
pull_request:
branches:
@@ -32,9 +28,14 @@ jobs:
Docker_Build:
name: Docker Build And Release
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
arch: [amd64, arm64]
version: [1.12.2]
steps:
- name: Checkout Repository
uses: actions/checkout@v5
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
@@ -43,7 +44,6 @@ jobs:
uses: docker/setup-buildx-action@v3
- name: Login to Registry
if: github.event_name != 'pull_request'
id: login
uses: docker/login-action@v3
with:
@@ -53,28 +53,46 @@ jobs:
- name: Build
id: docker_build
uses: docker/build-push-action@v6
uses: docker/build-push-action@v5
with:
context: .
build-args: |
VERSION=1.16.0-2
push: ${{ github.event_name != 'pull_request' }}
platforms: linux/amd64,linux/arm64
tags: ${{ env.REGISTRY_IMAGE }}:latest
provenance: false
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
ARCH=${{ matrix.arch }}
VERSION=${{ matrix.version }}
push: true
platforms: linux/${{ matrix.arch }}
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true
- 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:
name: Publish Multi-Arch Image And Release
name: Do The Horrible Merge Thing
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
needs:
- Docker_Build
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
id: login
uses: docker/login-action@v3
@@ -83,6 +101,25 @@ jobs:
username: ${{ secrets.REGISTRY_USERNAME }}
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
uses: anchore/sbom-action@v0
id: sbom
@@ -94,7 +131,7 @@ jobs:
output-file: ./sbom.spdx.json
- name: Scan SBOM
uses: anchore/scan-action@v7
uses: anchore/scan-action@v3
id: scan
with:
sbom: sbom.spdx.json
@@ -103,15 +140,15 @@ jobs:
only-fixed: true
- name: upload Anchore scan SARIF report
uses: github/codeql-action/upload-sarif@v4
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: ${{ steps.scan.outputs.sarif }}
- name: Checkout Repository
uses: actions/checkout@v5
uses: actions/checkout@v4
- name: Changelog
uses: TriPSs/conventional-changelog-action@v6
uses: TriPSs/conventional-changelog-action@v3
id: changelog
if: ${{ github.event_name != 'pull_request' }}
with:
@@ -124,11 +161,11 @@ jobs:
skip-on-empty: false # otherwise we don't publish fixes
- name: Create Release
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@v1
id: release
if: ${{ steps.changelog.outputs.skipped == 'false' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.github_token }}
with:
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)

View File

@@ -1,41 +1,19 @@
FROM debian:13.2 AS stage
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
ENV DEBIAN_FRONTEND=noninteractive
ARG PACKAGE_BASEURL=https://download.zerotier.com/debian/trixie/pool/main/z/zerotier-one
ARG TARGETARCH
ARG VERSION=1.16.0-2
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:12.6 as stage
ARG PACKAGE_BASEURL=https://download.zerotier.com/debian/bookworm/pool/main/z/zerotier-one
ARG ARCH=amd64
ARG VERSION=1.12.2
RUN apt-get update -qq && apt-get install -qq --no-install-recommends -y ca-certificates curl
RUN curl -sSL -o zerotier-one.deb "${PACKAGE_BASEURL}/zerotier-one_${VERSION}_${ARCH}.deb"
FROM debian:13.2
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
ENV DEBIAN_FRONTEND=noninteractive
ARG VERSION
FROM debian:12.6
RUN mkdir /app
WORKDIR /app
COPY --from=stage zerotier-one.deb .
RUN apt-get update -qq && apt-get install -qq --no-install-recommends -y \
adduser=3.152 \
procps=2:4.0.4-9 \
iptables=1.8.11-2 \
openssl=3.5.1-1 \
RUN apt-get update -qq && apt-get install -qq --no-install-recommends -y procps iptables openssl \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
RUN dpkg -i zerotier-one.deb && rm -f zerotier-one.deb
RUN echo "${VERSION}" >/etc/zerotier-version
COPY entrypoint.sh 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"]

View File

@@ -20,21 +20,21 @@ You also need to add a static route into ZeroTier so that the traffic is routed
### 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`.
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
`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.
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
@@ -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`
#### 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
image: registry.dangerous.tech/dangeroustech/zerotierbridge
restart: always
cap_add:
- NET_ADMIN
- NET_RAW
sysctls:
net.ipv4.ip_forward: "1"
privileged: true
volumes:
- zt_config:/var/lib/zerotier-one
environment:
ZT_NETWORKS: "NETWORK_ID_1 NETWORK_ID_2 NETWORK_ID_3"
ZT_BRIDGE: "true"
- ZT_NETWORKS=NETWORK_ID_1 NETWORK_ID_2 NETWORK_ID_3
- ZT_BRIDGE=true
volumes:
zt_config:

View File

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

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