diff --git a/.gitea/workflows/publish-deb.yml b/.gitea/workflows/publish-deb.yml new file mode 100644 index 0000000..713cd53 --- /dev/null +++ b/.gitea/workflows/publish-deb.yml @@ -0,0 +1,77 @@ +name: "Publish Debian package" +run-name: "Publish Debian package" +on: + workflow_dispatch: + inputs: + deb_version: + description: "Version to publish" + type: string + + deb_revision: + description: "Debian package revision" + type: string + default: "1" + required: true + + rust_toolchain: + description: "Whether to build the package with stable rust" + type: choice + options: + - stable + - nightly + - beta + default: stable + +env: + BINSTALL_DISABLE_TELEMETRY: 'true' + +# TODO: dynamic matrix builds when... +# https://github.com/go-gitea/gitea/issues/25179 +jobs: + build-deb: + strategy: + matrix: + os: [ + debian-trixie, + debian-bookworm, + # ubuntu-resolute, + ubuntu-noble, + ubuntu-jammy, + ] + name: Build and publish for ${{ matrix.os }} + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v6 + - uses: cargo-bins/cargo-binstall@main + + - name: Install rust toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ inputs.rust_toolchain }} + + - name: Install cargo-deb + run: cargo binstall -y cargo-deb + + - name: Build deb package + env: + CREATE_DEB_DEBUG: "1" + run: | + CREATE_DEB_ARGS=( + --deb-revision "${{ inputs.deb_revision }}" + ) + + if [ "${{ inputs.deb_version }}" != "" ]; then + CREATE_DEB_ARGS+=("--deb-version" "${{ inputs.deb_version }}") + fi + + ./scripts/create-deb.sh "${CREATE_DEB_ARGS[@]}" + + - name: Upload deb package artifact + uses: actions/upload-artifact@v3 + with: + name: roowho2-deb-${{ matrix.os }}-${{ gitea.sha }} + path: target/debian/*.deb + if-no-files-found: error + retention-days: 30 + # Already compressed + compression: 0 diff --git a/.gitignore b/.gitignore index 2ff6c7f..5cb86a4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,14 @@ +# Rust /target +config.toml + +# Nix +/.direnv/ result result-* +# Nix VM *.qcow2 + +# Packaging +/assets/completions/ diff --git a/Cargo.toml b/Cargo.toml index ef527ce..e7943cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,10 @@ users = { version = "0.11.0", default-features = false } tracing-journald = "0.3.2" chrono-tz = "0.10.4" +[dev-dependencies] +indoc = "2.0.7" +tempfile = "3.27.0" + [features] default = ["systemd"] systemd = ["sd-notify", "uucore/feat_systemd_logind"] @@ -89,6 +93,74 @@ strip = true lto = true codegen-units = 1 -[dev-dependencies] -indoc = "2.0.7" -tempfile = "3.27.0" +[package.metadata.deb] +name = "roowho2" +priority = "optional" +section = "net" +depends = "$auto" +license-file = ["LICENSE", "0"] +maintainer = "Programvareverkstedet " +copyright = "Copyright (c) 2026, Programvareverkstedet" +assets = [ + [ + "target/release/roowhod", + "usr/bin/roowhod", + "0755" + ], + [ + "target/release/finger", + "usr/bin/finger", + "0755" + ], + [ + "target/release/ruptime", + "usr/bin/ruptime", + "0755" + ], + [ + "target/release/rwho", + "usr/bin/rwho", + "0755" + ], + [ + "assets/debian/config.toml", + "etc/roowho2/config.toml", + "0644" + ], + [ + "assets/debian/user_ignore_list.txt", + "etc/roowho2/rwhod-ignore-list", + "0644" + ], + [ + "assets/debian/user_ignore_list.txt", + "etc/roowho2/fingerd-ignore-list", + "0644" + ], + [ + "assets/completions/_*", + "usr/share/zsh/site-functions/completions/", + "644", + ], + [ + "assets/completions/*.bash", + "usr/share/bash-completion/completions/", + "644", + ], + [ + "assets/completions/*.fish", + "usr/share/fish/vendor_completions.d/", + "644", + ], + [ + "README.md", + "usr/share/doc/roowho2/", + "644", + ], +] +maintainer-scripts = "debian/" +systemd-units = [ + { unit-name = "roowho2", unit-scripts = "assets/systemd", enable = true }, + { unit-name = "roowho2-client", unit-scripts = "assets/systemd", enable = true }, + { unit-name = "roowho2-rwhod", unit-scripts = "assets/systemd", enable = true }, +] diff --git a/assets/debian/user_ignore_list.txt b/assets/debian/user_ignore_list.txt new file mode 100644 index 0000000..1e60fd7 --- /dev/null +++ b/assets/debian/user_ignore_list.txt @@ -0,0 +1,4 @@ +# # In this file, you can specify users to ignore, either by username or by UID. +# # Example values: +# user:alice +# uid:1000 diff --git a/assets/systemd/roowho2-client.socket b/assets/systemd/roowho2-client.socket new file mode 100644 index 0000000..bcdd2a2 --- /dev/null +++ b/assets/systemd/roowho2-client.socket @@ -0,0 +1,10 @@ +[Unit] +Description=Roowho2 Client Communication Socket + +[Socket] +FileDescriptorName=client_socket +Service=roowho2.service +ListenStream=/run/roowho2/roowho2.varlink + +[Install] +WantedBy=sockets.target diff --git a/assets/systemd/roowho2-rwhod.socket b/assets/systemd/roowho2-rwhod.socket new file mode 100644 index 0000000..536eea7 --- /dev/null +++ b/assets/systemd/roowho2-rwhod.socket @@ -0,0 +1,11 @@ +[Unit] +Description=Roowho2 Rwhod Socket + +[Socket] +FileDescriptorName=rwhod_socket +Service=roowho2.service +ListenDatagram=0.0.0.0:513 +Broadcast=true + +[Install] +WantedBy=sockets.target diff --git a/assets/systemd/roowho2.service b/assets/systemd/roowho2.service new file mode 100644 index 0000000..b632b7d --- /dev/null +++ b/assets/systemd/roowho2.service @@ -0,0 +1,43 @@ +[Unit] + +[Service] +Type=notify +Restart=on-failure +DynamicUser=true +ExecStart=/usr/bin/roowhod + +ConfigurationDirectory=roowho2 + +AmbientCapabilities=CAP_DAC_READ_SEARCH +CapabilityBoundingSet=CAP_DAC_READ_SEARCH +DeviceAllow= +DevicePolicy=closed +LockPersonality=true +MemoryDenyWriteExecute=true +NoNewPrivileges=true +PrivateDevices=true +PrivateIPC=true +PrivateMounts=true +PrivateTmp=true +ProcSubset=pid +ProtectClock=true +ProtectControlGroups=strict +ProtectHostname=true +ProtectKernelLogs=true +ProtectKernelModules=true +ProtectKernelTunables=true +ProtectProc=invisible +RemoveIPC=true +RestrictAddressFamilies=AF_INET +RestrictAddressFamilies=AF_INET6 +RestrictAddressFamilies=AF_UNIX +RestrictAddressFamilies=AF_NETLINK +RestrictNamespaces=true +RestrictRealtime=true +RestrictSUIDSGID=true +SocketBindDeny=any +SystemCallArchitectures=native +SystemCallFilter=@system-service +SystemCallFilter=~@privileged +SystemCallFilter=~@resources +UMask=0077 diff --git a/flake.nix b/flake.nix index 27284c1..f22a2e5 100644 --- a/flake.nix +++ b/flake.nix @@ -55,6 +55,7 @@ nativeBuildInputs = with pkgs; [ toolchain cargo-edit + cargo-deb ] ++ (lib.optionals stdenv.buildPlatform.isLinux [ systemdLibs ]); diff --git a/scripts/create-deb.sh b/scripts/create-deb.sh new file mode 100755 index 0000000..cb7e18a --- /dev/null +++ b/scripts/create-deb.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +set -euo pipefail + +declare -r RUST_PROFILE="releaselto" + +if [[ "${CREATE_DEB_DEBUG:-}" == "1" ]]; then + set -x +fi + +if ! command -v cargo &> /dev/null; then + echo "cargo could not be found" >&2 + exit 1 +fi + +if ! command -v cargo-deb &> /dev/null; then + echo "cargo-deb could not be found" >&2 + exit 1 +fi + +cargo build --profile "$RUST_PROFILE" + +mkdir -p assets/completions + +for bin in finger ruptime rwho; do + ( + PATH="./target/$RUST_PROFILE:$PATH" + + "$bin" --completions=bash > "assets/completions/$bin.bash" + "$bin" --completions=zsh > "assets/completions/_$bin" + "$bin" --completions=fish > "assets/completions/$bin.fish" + ) +done + +DEFAULT_CARGO_DEB_ARGS=( + --profile "$RUST_PROFILE" + --no-build +) + +cargo deb "${DEFAULT_CARGO_DEB_ARGS[@]}" "$@"