Files
2026-11-05 12:52:32 +01:00

169 lines
6.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# Build a Debian/Ubuntu package with dpkg-deb only (no debhelper needed).
# scripts/build-deb.sh build release binary for the host and package it
# scripts/build-deb.sh --no-build package an existing target/release/active-push
# TARGET=aarch64-unknown-linux-gnu scripts/build-deb.sh (cross toolchain must be installed)
set -euo pipefail
ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"
fail() { printf 'error: %s\n' "$*" >&2; exit 1; }
command -v dpkg-deb >/dev/null || fail "dpkg-deb is required (apt install dpkg)"
VERSION="$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -1)"
REVISION="${DEB_REVISION:-1}"
BUILD=1
[[ "${1:-}" == "--no-build" ]] && BUILD=0
HOST_ARCH="$(uname -m)"
# Portable builds: link against an old glibc with cargo-zigbuild when available
# (pip install ziglang && cargo install cargo-zigbuild). GLIBC_TARGET=0 disables it.
GLIBC_TARGET="${GLIBC_TARGET:-2.31}"
TARGET="${TARGET:-}"
ZIG=0
if [[ -z "$TARGET" && "$GLIBC_TARGET" != "0" ]] && command -v cargo-zigbuild >/dev/null 2>&1; then
TARGET="${HOST_ARCH}-unknown-linux-gnu"
ZIG=1
fi
case "${TARGET:-$HOST_ARCH}" in
x86_64*) ARCH=amd64 ;;
aarch64*) ARCH=arm64 ;;
armv7*) ARCH=armhf ;;
*) ARCH="$(dpkg --print-architecture 2>/dev/null || echo amd64)" ;;
esac
if [[ -n "${BIN:-}" ]]; then
:
elif [[ -n "$TARGET" ]]; then
BIN="${CARGO_TARGET_DIR:-target}/$TARGET/release/active-push"
else
BIN="${CARGO_TARGET_DIR:-target}/release/active-push"
fi
if [[ $BUILD == 1 ]]; then
printf 'Building release binary %s...\n' "$VERSION"
if [[ $ZIG == 1 ]]; then
cargo zigbuild --release --locked --target "$TARGET.$GLIBC_TARGET"
elif [[ -n "$TARGET" ]]; then
cargo build --release --locked --target "$TARGET"
else
cargo build --release --locked
fi
fi
[[ -x "$BIN" ]] || fail "binary $BIN not found"
# minimal libc6 version from the binary's versioned symbols
LIBC_MIN="2.31"
if command -v objdump >/dev/null; then
v="$(objdump -T "$BIN" 2>/dev/null | grep -o 'GLIBC_[0-9.]*' | sed 's/GLIBC_//' | sort -V | tail -1)"
[[ -n "$v" ]] && LIBC_MIN="$v"
fi
printf 'Binary %s requires glibc >= %s\n' "$BIN" "$LIBC_MIN"
PKG="active-push_${VERSION}-${REVISION}_${ARCH}"
STAGE="$(mktemp -d)"
trap 'rm -rf "$STAGE"' EXIT
D="$STAGE/$PKG"
install -d -m 0755 "$D/DEBIAN" "$D/usr/bin" "$D/lib/systemd/system" "$D/etc/active-push" \
"$D/usr/share/doc/active-push/examples" "$D/usr/share/active-push"
install -m 0755 "$BIN" "$D/usr/bin/active-push"
strip --strip-unneeded "$D/usr/bin/active-push" 2>/dev/null || true
install -m 0644 deploy/active-push.service "$D/lib/systemd/system/active-push.service"
install -m 0640 deploy/environment.example "$D/etc/active-push/environment"
install -m 0644 deploy/nginx-active-push.conf "$D/usr/share/doc/active-push/examples/nginx-active-push.conf"
install -m 0644 deploy/active-push-autodiscover.conf "$D/usr/share/doc/active-push/examples/active-push-autodiscover.conf"
install -m 0644 README.md "$D/usr/share/doc/active-push/README.md"
for f in docs/*.md; do install -m 0644 "$f" "$D/usr/share/doc/active-push/"; done
install -m 0755 tools/zpush-import.py "$D/usr/share/active-push/zpush-import.py"
install -m 0644 LICENSE "$D/usr/share/doc/active-push/copyright"
gzip -9n -c CHANGELOG.md > "$D/usr/share/doc/active-push/changelog.gz"
SIZE="$(du -sk "$D" | cut -f1)"
cat > "$D/DEBIAN/control" <<EOF
Package: active-push
Version: ${VERSION}-${REVISION}
Section: mail
Priority: optional
Architecture: ${ARCH}
Maintainer: ActivePush maintainers <root@localhost>
Installed-Size: ${SIZE}
Depends: libc6 (>= ${LIBC_MIN}), adduser, ca-certificates
Recommends: nginx | apache2 | rust-proxy
Suggests: dovecot-imapd, postfix, radicale
Conflicts: z-push-common
Description: Exchange ActiveSync server for IMAP/SMTP, CalDAV and CardDAV
ActivePush lets phones and Outlook synchronise mail, calendars, tasks and
contacts over Exchange ActiveSync (2.5-14.1) with standard IMAP/SMTP,
CalDAV and CardDAV servers. It is a Rust rewrite of Z-Push with a built-in
administration panel (devices, remote wipe, policies, live statistics).
EOF
# Z-Push can be installed side by side; drop the Conflicts line if you rely on that.
sed -i '/^Conflicts: z-push-common/d' "$D/DEBIAN/control"
echo "/etc/active-push/environment" > "$D/DEBIAN/conffiles"
cat > "$D/DEBIAN/postinst" <<'EOF'
#!/bin/sh
set -e
case "$1" in
configure)
if ! getent group active-push >/dev/null; then addgroup --system active-push >/dev/null; fi
if ! getent passwd active-push >/dev/null; then
adduser --system --ingroup active-push --home /var/lib/active-push --no-create-home \
--shell /usr/sbin/nologin --gecos "ActivePush" active-push >/dev/null
fi
install -d -o active-push -g active-push -m 0700 /var/lib/active-push
chown root:active-push /etc/active-push /etc/active-push/environment
chmod 0750 /etc/active-push
chmod 0640 /etc/active-push/environment
if [ -d /run/systemd/system ]; then
systemctl daemon-reload >/dev/null 2>&1 || true
if [ -z "$2" ]; then
systemctl enable --now active-push.service >/dev/null 2>&1 || true
echo ""
echo "ActivePush installed and started."
echo " ActiveSync listener : 127.0.0.1:8081 (proxy /Microsoft-Server-ActiveSync and autodiscover here)"
echo " Admin panel : http://127.0.0.1:9091/ (ssh -L 9091:127.0.0.1:9091 server)"
echo " First administrator : sudo -u active-push active-push admin setup-token"
echo " nginx example : /usr/share/doc/active-push/examples/nginx-active-push.conf"
echo " Import Z-Push config: python3 /usr/share/active-push/zpush-import.py /usr/share/z-push > zpush.json"
echo " sudo -u active-push active-push config apply zpush.json"
echo ""
else
systemctl try-restart active-push.service >/dev/null 2>&1 || true
fi
fi
;;
esac
exit 0
EOF
cat > "$D/DEBIAN/prerm" <<'EOF'
#!/bin/sh
set -e
if [ -d /run/systemd/system ] && [ "$1" = remove ]; then
systemctl disable --now active-push.service >/dev/null 2>&1 || true
fi
exit 0
EOF
cat > "$D/DEBIAN/postrm" <<'EOF'
#!/bin/sh
set -e
if [ "$1" = purge ]; then
rm -rf /etc/active-push
# device states, statistics and settings
rm -rf /var/lib/active-push
if getent passwd active-push >/dev/null; then deluser --system active-push >/dev/null 2>&1 || true; fi
if getent group active-push >/dev/null; then delgroup --system active-push >/dev/null 2>&1 || true; fi
fi
if [ -d /run/systemd/system ]; then systemctl daemon-reload >/dev/null 2>&1 || true; fi
exit 0
EOF
chmod 0755 "$D/DEBIAN/postinst" "$D/DEBIAN/prerm" "$D/DEBIAN/postrm"
mkdir -p dist
dpkg-deb --root-owner-group -Zxz --build "$D" "dist/$PKG.deb" >/dev/null
sha256sum "dist/$PKG.deb" > "dist/$PKG.deb.sha256"
printf 'Package: dist/%s.deb\n' "$PKG"
dpkg-deb --info "dist/$PKG.deb" | sed -n '1,12p'