Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3856eed3b | ||
|
|
eac54f8c79 |
No files matched your search
@@ -33,11 +33,15 @@ jobs:
|
|||||||
asset: tsunagi-linux-x86_64
|
asset: tsunagi-linux-x86_64
|
||||||
archive: tar.gz
|
archive: tar.gz
|
||||||
zig: true
|
zig: true
|
||||||
|
deb: true
|
||||||
|
deb_arch: amd64
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
target: aarch64-unknown-linux-musl
|
target: aarch64-unknown-linux-musl
|
||||||
asset: tsunagi-linux-aarch64
|
asset: tsunagi-linux-aarch64
|
||||||
archive: tar.gz
|
archive: tar.gz
|
||||||
zig: true
|
zig: true
|
||||||
|
deb: true
|
||||||
|
deb_arch: arm64
|
||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
target: aarch64-apple-darwin
|
target: aarch64-apple-darwin
|
||||||
asset: tsunagi-macos-aarch64
|
asset: tsunagi-macos-aarch64
|
||||||
@@ -133,13 +137,31 @@ jobs:
|
|||||||
tar -C dist/pkg -czf "${archive}" "${{ matrix.asset }}"
|
tar -C dist/pkg -czf "${archive}" "${{ matrix.asset }}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# A dependency-free .deb for the x86_64 and aarch64 Linux builds: it drops
|
||||||
|
# the static binary, the systemd service and the polkit rule. Built with
|
||||||
|
# dpkg-deb (present on the runner); see dist/deb/build-deb.sh.
|
||||||
|
- name: Build the Debian package
|
||||||
|
if: matrix.deb
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
version="${GITHUB_REF_NAME#v}"
|
||||||
|
bash dist/deb/build-deb.sh \
|
||||||
|
"target/${{ matrix.target }}/release/tsunagi" \
|
||||||
|
"${{ matrix.deb_arch }}" \
|
||||||
|
"$version" \
|
||||||
|
"tsunagi_${version}_${{ matrix.deb_arch }}.deb"
|
||||||
|
|
||||||
# @v3 on purpose: Gitea does not support the v4 artifact backend. This is
|
# @v3 on purpose: Gitea does not support the v4 artifact backend. This is
|
||||||
# what makes the archive show up under the run and hands it to `publish`.
|
# what makes the archive (and the .deb, where built) show up under the run
|
||||||
- name: Upload the archive as a run artifact
|
# and hands it to `publish`.
|
||||||
|
- name: Upload the build outputs as run artifacts
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.asset }}
|
name: ${{ matrix.asset }}
|
||||||
path: ${{ matrix.asset }}-*.*
|
path: |
|
||||||
|
${{ matrix.asset }}-*.*
|
||||||
|
*.deb
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
@@ -211,5 +233,5 @@ jobs:
|
|||||||
cat up.json >&2 || true
|
cat up.json >&2 || true
|
||||||
rc=1
|
rc=1
|
||||||
fi
|
fi
|
||||||
done < <(find artifacts -type f \( -name '*.tar.gz' -o -name '*.zip' \) -print0)
|
done < <(find artifacts -type f \( -name '*.tar.gz' -o -name '*.zip' -o -name '*.deb' \) -print0)
|
||||||
exit "$rc"
|
exit "$rc"
|
||||||
@@ -5,15 +5,10 @@ name: Release
|
|||||||
# macOS and Windows); only the publish half differs: GitHub needs the v4
|
# macOS and Windows); only the publish half differs: GitHub needs the v4
|
||||||
# artifact backend and fills the release with `gh`.
|
# artifact backend and fills the release with `gh`.
|
||||||
#
|
#
|
||||||
# Gitea reads both .gitea/workflows and .github/workflows, so without a guard it
|
# Every job is gated on `github.server_url == 'https://github.com'`, so this file
|
||||||
# would also try to run this file and fail on @v4 and `gh`. (Gitea reports
|
# runs only on GitHub. Gitea runs its own copy in .gitea/workflows; should a
|
||||||
# github.server_url as https://github.com, so that cannot tell the two apart.)
|
# Gitea instance also read .github/workflows, the guard skips these jobs there
|
||||||
# Instead every job is gated on a repository variable GITHUB_RELEASE=true, which
|
# so they never fail on the @v4 artifact backend or `gh`.
|
||||||
# is set only in the GitHub repository's settings — so on Gitea, where it is
|
|
||||||
# absent, these jobs are skipped and the .gitea file is the one that runs.
|
|
||||||
#
|
|
||||||
# To enable on GitHub: Settings → Secrets and variables → Actions → Variables →
|
|
||||||
# New variable, name GITHUB_RELEASE, value true.
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags: ["v*"]
|
tags: ["v*"]
|
||||||
@@ -28,7 +23,7 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: ${{ matrix.asset }}
|
name: ${{ matrix.asset }}
|
||||||
if: ${{ vars.GITHUB_RELEASE == 'true' }}
|
if: ${{ github.server_url == 'https://github.com' }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@@ -39,11 +34,15 @@ jobs:
|
|||||||
asset: tsunagi-linux-x86_64
|
asset: tsunagi-linux-x86_64
|
||||||
archive: tar.gz
|
archive: tar.gz
|
||||||
zig: true
|
zig: true
|
||||||
|
deb: true
|
||||||
|
deb_arch: amd64
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
target: aarch64-unknown-linux-musl
|
target: aarch64-unknown-linux-musl
|
||||||
asset: tsunagi-linux-aarch64
|
asset: tsunagi-linux-aarch64
|
||||||
archive: tar.gz
|
archive: tar.gz
|
||||||
zig: true
|
zig: true
|
||||||
|
deb: true
|
||||||
|
deb_arch: arm64
|
||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
target: aarch64-apple-darwin
|
target: aarch64-apple-darwin
|
||||||
asset: tsunagi-macos-aarch64
|
asset: tsunagi-macos-aarch64
|
||||||
@@ -139,17 +138,34 @@ jobs:
|
|||||||
tar -C dist/pkg -czf "${archive}" "${{ matrix.asset }}"
|
tar -C dist/pkg -czf "${archive}" "${{ matrix.asset }}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Upload the archive as a run artifact
|
# A dependency-free .deb for the x86_64 and aarch64 Linux builds: it drops
|
||||||
|
# the static binary, the systemd service and the polkit rule. Built with
|
||||||
|
# dpkg-deb (present on the runner); see dist/deb/build-deb.sh.
|
||||||
|
- name: Build the Debian package
|
||||||
|
if: matrix.deb
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
version="${GITHUB_REF_NAME#v}"
|
||||||
|
bash dist/deb/build-deb.sh \
|
||||||
|
"target/${{ matrix.target }}/release/tsunagi" \
|
||||||
|
"${{ matrix.deb_arch }}" \
|
||||||
|
"$version" \
|
||||||
|
"tsunagi_${version}_${{ matrix.deb_arch }}.deb"
|
||||||
|
|
||||||
|
- name: Upload the build outputs as run artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.asset }}
|
name: ${{ matrix.asset }}
|
||||||
path: ${{ matrix.asset }}-*.*
|
path: |
|
||||||
|
${{ matrix.asset }}-*.*
|
||||||
|
*.deb
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
name: Publish release
|
name: Publish release
|
||||||
needs: build
|
needs: build
|
||||||
if: ${{ vars.GITHUB_RELEASE == 'true' }}
|
if: ${{ github.server_url == 'https://github.com' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
@@ -172,7 +188,7 @@ jobs:
|
|||||||
|
|
||||||
# download-artifact@v4 nests each artifact under its own directory, so
|
# download-artifact@v4 nests each artifact under its own directory, so
|
||||||
# the archives are artifacts/<asset>/<file>.
|
# the archives are artifacts/<asset>/<file>.
|
||||||
mapfile -t files < <(find artifacts -type f \( -name '*.tar.gz' -o -name '*.zip' \))
|
mapfile -t files < <(find artifacts -type f \( -name '*.tar.gz' -o -name '*.zip' -o -name '*.deb' \))
|
||||||
printf 'asset: %s\n' "${files[@]}"
|
printf 'asset: %s\n' "${files[@]}"
|
||||||
|
|
||||||
prerelease=()
|
prerelease=()
|
||||||
|
|||||||
Vendored
+25
@@ -0,0 +1,25 @@
|
|||||||
|
// Installed by the tsunagi package.
|
||||||
|
//
|
||||||
|
// Lets a non-root agent configure systemd-resolved for its overlay zones — the
|
||||||
|
// four resolve1 actions it calls, and nothing else — for any user in the
|
||||||
|
// "tsunagi" group (created by the package). The packaged systemd service runs
|
||||||
|
// as root and does not need this rule; it is for running the agent as your own
|
||||||
|
// user instead:
|
||||||
|
//
|
||||||
|
// sudo usermod -aG tsunagi "$USER"
|
||||||
|
// sudo setcap cap_net_admin,cap_net_bind_service+p /usr/bin/tsunagi
|
||||||
|
// tsunagi up
|
||||||
|
//
|
||||||
|
// polkit decides by user/group id, not by capability, which is why the resolver
|
||||||
|
// needs this rule even once the binary has the capability.
|
||||||
|
polkit.addRule(function(action, subject) {
|
||||||
|
var allowed = [
|
||||||
|
"org.freedesktop.resolve1.set-dns-servers",
|
||||||
|
"org.freedesktop.resolve1.set-domains",
|
||||||
|
"org.freedesktop.resolve1.set-default-route",
|
||||||
|
"org.freedesktop.resolve1.revert"
|
||||||
|
];
|
||||||
|
if (allowed.indexOf(action.id) >= 0 && subject.isInGroup("tsunagi")) {
|
||||||
|
return polkit.Result.YES;
|
||||||
|
}
|
||||||
|
});
|
||||||
+92
@@ -0,0 +1,92 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Assemble a dependency-free Debian package from a prebuilt static tsunagi
|
||||||
|
# binary, using only dpkg-deb (no cargo-deb, no nfpm). The binary is statically
|
||||||
|
# linked, so the package declares no Depends and runs on any Debian/Ubuntu.
|
||||||
|
#
|
||||||
|
# Usage: build-deb.sh <binary> <deb_arch> <version> <output.deb>
|
||||||
|
# <binary> path to the built tsunagi executable
|
||||||
|
# <deb_arch> Debian architecture: amd64 or arm64
|
||||||
|
# <version> package version (the tag without its leading v)
|
||||||
|
# <output> path to write the .deb to
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
binary="$1"
|
||||||
|
arch="$2"
|
||||||
|
version="$3"
|
||||||
|
output="$4"
|
||||||
|
|
||||||
|
here="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
root="$(mktemp -d)"
|
||||||
|
trap 'rm -rf "$root"' EXIT
|
||||||
|
|
||||||
|
# Payload. Debian installs to /usr/bin (not /usr/local), so the service's
|
||||||
|
# ExecStart is rewritten to match; the source unit targets /usr/local/bin for
|
||||||
|
# the tarball installer.
|
||||||
|
install -D -m 0755 "$binary" "$root/usr/bin/tsunagi"
|
||||||
|
|
||||||
|
mkdir -p "$root/lib/systemd/system"
|
||||||
|
sed 's#/usr/local/bin/tsunagi#/usr/bin/tsunagi#' \
|
||||||
|
"$here/../linux/tsunagi.service" > "$root/lib/systemd/system/tsunagi.service"
|
||||||
|
chmod 0644 "$root/lib/systemd/system/tsunagi.service"
|
||||||
|
|
||||||
|
install -D -m 0644 "$here/50-tsunagi-resolved.rules" \
|
||||||
|
"$root/usr/share/polkit-1/rules.d/50-tsunagi-resolved.rules"
|
||||||
|
install -D -m 0644 "$here/../../README.md" "$root/usr/share/doc/tsunagi/README.md"
|
||||||
|
install -D -m 0644 "$here/../linux/README.md" "$root/usr/share/doc/tsunagi/INSTALL.md"
|
||||||
|
|
||||||
|
mkdir -p "$root/DEBIAN"
|
||||||
|
|
||||||
|
cat > "$root/DEBIAN/control" <<CTRL
|
||||||
|
Package: tsunagi
|
||||||
|
Version: ${version}
|
||||||
|
Architecture: ${arch}
|
||||||
|
Maintainer: AB <ab@hexor.cy>
|
||||||
|
Section: net
|
||||||
|
Priority: optional
|
||||||
|
Homepage: https://github.com/Ultradesu/tsunagi
|
||||||
|
Description: Serverless private mesh networking agent
|
||||||
|
tsunagi forms small private mesh IP networks between peers, with NAT
|
||||||
|
traversal and no central server. This package installs a static,
|
||||||
|
dependency-free binary, a systemd service that runs the agent as root, and a
|
||||||
|
polkit rule that lets a non-root agent configure systemd-resolved.
|
||||||
|
CTRL
|
||||||
|
|
||||||
|
# A system group for the optional non-root run (the polkit rule grants it the
|
||||||
|
# resolve1 actions). The packaged service runs as root and does not need it.
|
||||||
|
cat > "$root/DEBIAN/postinst" <<'POSTINST'
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
if ! getent group tsunagi >/dev/null 2>&1; then
|
||||||
|
addgroup --system tsunagi >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
if [ -d /run/systemd/system ]; then
|
||||||
|
systemctl daemon-reload >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
POSTINST
|
||||||
|
|
||||||
|
cat > "$root/DEBIAN/prerm" <<'PRERM'
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
if [ "$1" = remove ] || [ "$1" = purge ]; then
|
||||||
|
if [ -d /run/systemd/system ]; then
|
||||||
|
systemctl disable --now tsunagi.service >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
PRERM
|
||||||
|
|
||||||
|
cat > "$root/DEBIAN/postrm" <<'POSTRM'
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
if [ -d /run/systemd/system ]; then
|
||||||
|
systemctl daemon-reload >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
POSTRM
|
||||||
|
|
||||||
|
chmod 0755 "$root/DEBIAN/postinst" "$root/DEBIAN/prerm" "$root/DEBIAN/postrm"
|
||||||
|
|
||||||
|
# --root-owner-group writes the payload as root:root without needing fakeroot.
|
||||||
|
dpkg-deb --root-owner-group --build "$root" "$output"
|
||||||
|
echo "built $output"
|
||||||
Reference in new issue
Block a user