diff --git a/.github/workflows/build-deb.yml b/.github/workflows/build-deb.yml new file mode 100644 index 0000000..c03fe91 --- /dev/null +++ b/.github/workflows/build-deb.yml @@ -0,0 +1,420 @@ +name: Build Debian Packages + +on: + push: + branches: + - master + - feature/debian-packaging + tags: + - "v*" + pull_request: + branches: + - master + workflow_dispatch: + +env: + CARGO_TERM_COLOR: always + +jobs: + build-deb: + name: Build .deb for ${{ matrix.target }} + runs-on: ubuntu-latest + strategy: + matrix: + include: + - target: x86_64-unknown-linux-gnu + arch: amd64 + - target: aarch64-unknown-linux-gnu + arch: arm64 + - target: armv7-unknown-linux-gnueabihf + arch: armhf + - target: riscv64gc-unknown-linux-gnu + arch: riscv64 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - name: Install cargo-deb + run: cargo install cargo-deb + + - name: Install build dependencies + run: | + sudo apt-get update + sudo apt-get install -y dpkg-dev + + - name: Install cross-compilation tools (ARM64) + if: matrix.target == 'aarch64-unknown-linux-gnu' + run: | + sudo dpkg --add-architecture arm64 + # Disable all existing sources and create new ones with proper arch specifications + sudo mv /etc/apt/sources.list /etc/apt/sources.list.backup + sudo mv /etc/apt/sources.list.d /etc/apt/sources.list.d.backup || true + sudo mkdir -p /etc/apt/sources.list.d + # Clear APT cache and lists + sudo rm -rf /var/lib/apt/lists/* + sudo mkdir -p /var/lib/apt/lists/partial + # Create new sources.list with both amd64 and arm64 + cat << EOF | sudo tee /etc/apt/sources.list + deb [arch=amd64] http://archive.ubuntu.com/ubuntu $(lsb_release -sc) main universe restricted multiverse + deb [arch=amd64] http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-updates main universe restricted multiverse + deb [arch=amd64] http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe restricted multiverse + deb [arch=amd64] http://security.ubuntu.com/ubuntu $(lsb_release -sc)-security main universe restricted multiverse + deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports $(lsb_release -sc) main universe restricted multiverse + deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports $(lsb_release -sc)-updates main universe restricted multiverse + deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports $(lsb_release -sc)-backports main universe restricted multiverse + deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports $(lsb_release -sc)-security main universe restricted multiverse + EOF + echo "=== Contents of /etc/apt/sources.list ===" + cat /etc/apt/sources.list + echo "=== Contents of /etc/apt/sources.list.d/ ===" + ls -la /etc/apt/sources.list.d/ || true + sudo apt-get update + sudo apt-get install -y gcc-aarch64-linux-gnu libdrm-dev:arm64 libdrm-amdgpu1:arm64 + + - name: Install cross-compilation tools (ARMhf) + if: matrix.target == 'armv7-unknown-linux-gnueabihf' + run: | + sudo apt-get update + sudo apt-get install -y gcc-arm-linux-gnueabihf + + - name: Install cross-compilation tools (RISC-V) + if: matrix.target == 'riscv64gc-unknown-linux-gnu' + run: | + sudo apt-get update + sudo apt-get install -y gcc-riscv64-linux-gnu + + - name: Install GPU libraries (x86_64) + if: matrix.target == 'x86_64-unknown-linux-gnu' + run: | + sudo apt-get update + sudo apt-get install -y libdrm-dev libdrm-amdgpu1 + + - name: Configure cross-compilation (ARM64) + if: matrix.target == 'aarch64-unknown-linux-gnu' + run: | + mkdir -p .cargo + cat >> .cargo/config.toml << EOF + [target.aarch64-unknown-linux-gnu] + linker = "aarch64-linux-gnu-gcc" + EOF + + - name: Configure cross-compilation (ARMhf) + if: matrix.target == 'armv7-unknown-linux-gnueabihf' + run: | + mkdir -p .cargo + cat >> .cargo/config.toml << EOF + [target.armv7-unknown-linux-gnueabihf] + linker = "arm-linux-gnueabihf-gcc" + EOF + + - name: Configure cross-compilation (RISC-V) + if: matrix.target == 'riscv64gc-unknown-linux-gnu' + run: | + mkdir -p .cargo + cat >> .cargo/config.toml << EOF + [target.riscv64gc-unknown-linux-gnu] + linker = "riscv64-linux-gnu-gcc" + EOF + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: ~/.cargo/registry + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo index + uses: actions/cache@v4 + with: + path: ~/.cargo/git + key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache target directory + uses: actions/cache@v4 + with: + path: target + key: ${{ runner.os }}-target-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }} + + - name: Build socktop .deb package + run: | + cargo deb --package socktop --target ${{ matrix.target }} --no-strip + + - name: Build socktop_agent .deb package (with GPU support) + if: matrix.target == 'x86_64-unknown-linux-gnu' || matrix.target == 'aarch64-unknown-linux-gnu' + run: | + cargo deb --package socktop_agent --target ${{ matrix.target }} --no-strip + + - name: Build socktop_agent .deb package (without GPU support) + if: matrix.target == 'armv7-unknown-linux-gnueabihf' || matrix.target == 'riscv64gc-unknown-linux-gnu' + run: | + cargo deb --package socktop_agent --target ${{ matrix.target }} --no-strip --no-default-features + + - name: Copy packages to debs directory + run: | + mkdir -p debs + cp target/${{ matrix.target }}/debian/*.deb debs/ + + - name: List generated packages + run: ls -lh debs/ + + - name: Upload .deb packages as artifacts + uses: actions/upload-artifact@v4 + with: + name: debian-packages-${{ matrix.arch }} + path: debs/*.deb + if-no-files-found: error + retention-days: 90 + + # Combine all artifacts into a single downloadable archive + combine-artifacts: + name: Combine all .deb packages + needs: build-deb + runs-on: ubuntu-latest + steps: + - name: Download AMD64 packages + uses: actions/download-artifact@v4 + with: + name: debian-packages-amd64 + path: all-debs + + - name: Download ARM64 packages + uses: actions/download-artifact@v4 + with: + name: debian-packages-arm64 + path: all-debs + + - name: Download ARMhf packages + uses: actions/download-artifact@v4 + with: + name: debian-packages-armhf + path: all-debs + + - name: Download RISC-V packages + uses: actions/download-artifact@v4 + with: + name: debian-packages-riscv64 + path: all-debs + + - name: List all packages + run: | + echo "All generated .deb packages:" + ls -lh all-debs/ + + - name: Upload combined artifacts + uses: actions/upload-artifact@v4 + with: + name: all-debian-packages + path: all-debs/*.deb + if-no-files-found: error + retention-days: 90 + + - name: Generate checksums + run: | + cd all-debs + sha256sum *.deb > SHA256SUMS + cat SHA256SUMS + + - name: Upload checksums + uses: actions/upload-artifact@v4 + with: + name: checksums + path: all-debs/SHA256SUMS + retention-days: 90 + + # Publish packages to gh-pages APT repository + publish-apt-repo: + name: Publish to APT Repository + needs: combine-artifacts + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v') + permissions: + contents: write + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Download all packages + uses: actions/download-artifact@v4 + with: + name: all-debian-packages + path: debs + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y dpkg-dev gpg + + - name: Checkout gh-pages branch + run: | + git fetch origin gh-pages:gh-pages || echo "gh-pages branch doesn't exist yet" + if git show-ref --verify --quiet refs/heads/gh-pages; then + git checkout gh-pages + else + git checkout --orphan gh-pages + git rm -rf . 2>/dev/null || true + # Create basic structure + mkdir -p dists/stable/main/{binary-amd64,binary-arm64,binary-armhf,binary-riscv64} + mkdir -p pool/main + fi + + - name: Copy packages to pool + run: | + mkdir -p pool/main + cp debs/*.deb pool/main/ + ls -lh pool/main/ + + - name: Generate Packages files + run: | + for arch in amd64 arm64 armhf riscv64; do + mkdir -p dists/stable/main/binary-$arch + dpkg-scanpackages --arch $arch pool/main /dev/null > dists/stable/main/binary-$arch/Packages 2>/dev/null || true + if [ -s dists/stable/main/binary-$arch/Packages ]; then + gzip -9 -k -f dists/stable/main/binary-$arch/Packages + echo "Generated Packages file for $arch" + fi + done + + - name: Generate Release file + run: | + cat > dists/stable/Release << EOF + Origin: socktop + Label: socktop + Suite: stable + Codename: stable + Architectures: amd64 arm64 armhf riscv64 + Components: main + Description: socktop APT repository + Date: $(date -Ru) + EOF + + # Add MD5Sum + echo "MD5Sum:" >> dists/stable/Release + for arch in amd64 arm64 armhf riscv64; do + for file in dists/stable/main/binary-$arch/Packages*; do + if [ -f "$file" ]; then + md5sum "$file" | awk '{print " " $1, "'$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file" 2>/dev/null)'", "'"${file#dists/stable/}"'"}' >> dists/stable/Release + fi + done + done + + # Add SHA256 + echo "SHA256:" >> dists/stable/Release + for arch in amd64 arm64 armhf riscv64; do + for file in dists/stable/main/binary-$arch/Packages*; do + if [ -f "$file" ]; then + sha256sum "$file" | awk '{print " " $1, "'$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file" 2>/dev/null)'", "'"${file#dists/stable/}"'"}' >> dists/stable/Release + fi + done + done + + - name: Set GPG available flag + id: check_gpg + env: + GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} + run: | + if [ -n "$GPG_PRIVATE_KEY" ]; then + echo "available=true" >> $GITHUB_OUTPUT + else + echo "available=false" >> $GITHUB_OUTPUT + fi + + - name: Import GPG key + if: steps.check_gpg.outputs.available == 'true' + env: + GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} + run: | + echo "$GPG_PRIVATE_KEY" | gpg --batch --import + gpg --list-secret-keys + + - name: Sign repository + if: steps.check_gpg.outputs.available == 'true' + env: + GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} + run: | + if [ -n "$GPG_PASSPHRASE" ]; then + echo "$GPG_PASSPHRASE" | gpg --batch --yes --no-tty --pinentry-mode loopback --passphrase-fd 0 \ + --default-key "$GPG_KEY_ID" \ + -abs -o dists/stable/Release.gpg dists/stable/Release + echo "$GPG_PASSPHRASE" | gpg --batch --yes --no-tty --pinentry-mode loopback --passphrase-fd 0 \ + --default-key "$GPG_KEY_ID" \ + --clearsign -o dists/stable/InRelease dists/stable/Release + else + gpg --batch --yes --no-tty --pinentry-mode loopback \ + --default-key "$GPG_KEY_ID" \ + -abs -o dists/stable/Release.gpg dists/stable/Release + gpg --batch --yes --no-tty --pinentry-mode loopback \ + --default-key "$GPG_KEY_ID" \ + --clearsign -o dists/stable/InRelease dists/stable/Release + fi + gpg --armor --export "$GPG_KEY_ID" > KEY.gpg + echo "✓ Repository signed" + + - name: Create unsigned repository notice + if: steps.check_gpg.outputs.available == 'false' + run: | + echo "⚠️ Warning: GPG_PRIVATE_KEY not set. Repository will be UNSIGNED." + echo "⚠️ Add GPG secrets to sign the repository automatically." + echo "To add secrets: Settings → Secrets and variables → Actions → Repository secrets" + + - name: Copy index.html if exists + run: | + git checkout ${{ github.ref_name }} -- index.html 2>/dev/null || echo "No index.html in source branch" + + - name: Commit and push to gh-pages + run: | + git config user.name "GitHub Actions" + git config user.email "actions@github.com" + git add . + + if git diff --staged --quiet; then + echo "No changes to commit" + else + COMMIT_MSG="Update APT repository" + if [[ "${{ github.ref }}" == refs/tags/* ]]; then + COMMIT_MSG="$COMMIT_MSG - Release ${{ github.ref_name }}" + else + COMMIT_MSG="$COMMIT_MSG - $(date -u +'%Y-%m-%d %H:%M:%S UTC')" + fi + git commit -m "$COMMIT_MSG" + git push origin gh-pages + echo "✓ Published to gh-pages" + fi + + # Optional: Create a release with the .deb files if this is a tag + create-release: + name: Create GitHub Release + needs: combine-artifacts + runs-on: ubuntu-latest + if: startsWith(github.ref, 'refs/tags/v') + permissions: + contents: write + steps: + - name: Download all packages + uses: actions/download-artifact@v4 + with: + name: all-debian-packages + path: release-debs + + - name: Download checksums + uses: actions/download-artifact@v4 + with: + name: checksums + path: release-debs + + - name: Create Release + uses: softprops/action-gh-release@v1 + with: + files: release-debs/* + draft: false + prerelease: false + generate_release_notes: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 1370721..15914e0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,16 @@ /target .vscode/ /socktop-wasm-test/target +/.cargo/ # Documentation files from development sessions (context-specific, not for public repo) /OPTIMIZATION_PROCESS_DETAILS.md /THREAD_SUPPORT.md + +# APT Repository - Safety: Never commit private keys! +*.asc +*-private.key +*-secret.key +gpg-private-backup.key +secring.gpg +# Note: Release.gpg, InRelease, and KEY.gpg (public) ARE safe to commit diff --git a/Cargo.lock b/Cargo.lock index 5c542cb..e9ecde5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2060,7 +2060,7 @@ dependencies = [ [[package]] name = "socktop_agent" -version = "1.50.1" +version = "1.50.2" dependencies = [ "anyhow", "assert_cmd", diff --git a/DEBIAN_PACKAGING_SUMMARY.md b/DEBIAN_PACKAGING_SUMMARY.md new file mode 100644 index 0000000..6e19b21 --- /dev/null +++ b/DEBIAN_PACKAGING_SUMMARY.md @@ -0,0 +1,156 @@ +# Debian Packaging Implementation Summary + +## Overview + +Successfully implemented Debian packaging for socktop using `cargo-deb`, with GitHub Actions automation for building packages for both AMD64 and ARM64 architectures. + +## Branches Created + +1. **`feature/debian-packaging`** - Main branch with debian packaging implementation +2. **`feature/man-pages`** - Separate branch for man pages work (to be researched further) + +## What Was Added + +### 1. Cargo.toml Updates + +Both `socktop/Cargo.toml` and `socktop_agent/Cargo.toml` were updated with: +- `[package.metadata.deb]` sections +- Package metadata (maintainer, description, dependencies) +- Asset definitions (binaries, documentation) +- Systemd service configuration (agent only) + +### 2. Systemd Service + +**File**: `socktop_agent/socktop-agent.service` +- Runs as `socktop` user/group +- Listens on port 3000 by default +- Security hardening enabled +- Disabled by default (user must explicitly enable) + +### 3. Maintainer Scripts + +**Directory**: `socktop_agent/debian/` + +- **`postinst`**: Creates `socktop` user/group, sets up `/var/lib/socktop` directory +- **`postrm`**: Cleanup on package removal/purge + +### 4. GitHub Actions Workflow + +**File**: `.github/workflows/build-deb.yml` + +Features: +- Builds for both x86_64 and ARM64 +- Triggered on: + - Push to `master` or `feature/debian-packaging` + - Pull requests to `master` + - Version tags (v*) + - Manual workflow dispatch +- Creates artifacts: + - `debian-packages-amd64` + - `debian-packages-arm64` + - `all-debian-packages` (combined) + - `checksums` (SHA256SUMS) +- Automatic GitHub releases for version tags + +### 5. Documentation + +**File**: `docs/DEBIAN_PACKAGING.md` + +Comprehensive guide covering: +- Building packages locally +- Cross-compilation for ARM64 +- Installation and configuration +- Using GitHub Actions artifacts +- Creating local APT repositories +- Troubleshooting + +## Package Details + +### socktop (TUI Client) +- **Binary**: `/usr/bin/socktop` +- **Size**: ~3.5 MB (x86_64) +- **Dependencies**: Auto-detected + +### socktop_agent (Daemon) +- **Binary**: `/usr/bin/socktop_agent` +- **Service**: `socktop-agent.service` +- **User/Group**: `socktop` (created automatically) +- **State directory**: `/var/lib/socktop` +- **Size**: ~6.7 MB (x86_64) +- **Dependencies**: Auto-detected + +## Testing + +Both packages successfully built locally: +``` +✓ socktop_1.50.0-1_amd64.deb +✓ socktop-agent_1.50.1-1_amd64.deb +``` + +Verified: +- Package contents (dpkg -c) +- Package metadata (dpkg -I) +- Systemd service file inclusion +- Maintainer scripts inclusion +- Documentation inclusion + +## Usage + +### For Users + +Download pre-built packages from GitHub Actions artifacts: +1. Go to Actions tab +2. Select latest "Build Debian Packages" run +3. Download architecture-specific artifact +4. Install: `sudo dpkg -i socktop*.deb` + +### For Developers + +Build locally: +```bash +cargo install cargo-deb +cargo deb --package socktop +cargo deb --package socktop_agent +``` + +Cross-compile for ARM64: +```bash +rustup target add aarch64-unknown-linux-gnu +sudo apt install gcc-aarch64-linux-gnu libc6-dev-arm64-cross +cargo deb --package socktop --target aarch64-unknown-linux-gnu +``` + +## Next Steps + +To get packages in official APT repositories: + +1. **Short term**: Host packages on GitHub Releases (automated) +2. **Medium term**: Create PPA for Ubuntu users +3. **Long term**: Submit to Debian/Ubuntu official repositories + +## Files Modified/Created + +``` +Modified: + socktop/Cargo.toml + socktop_agent/Cargo.toml + +Created: + .github/workflows/build-deb.yml + docs/DEBIAN_PACKAGING.md + socktop_agent/socktop-agent.service + socktop_agent/debian/postinst + socktop_agent/debian/postrm +``` + +## Commit + +``` +532ed16 Add Debian packaging support with cargo-deb +``` + +## Resources + +- [cargo-deb documentation](https://github.com/kornelski/cargo-deb) +- [Debian Policy Manual](https://www.debian.org/doc/debian-policy/) +- Full documentation in `docs/DEBIAN_PACKAGING.md` diff --git a/README.md b/README.md index c7db51a..d16a03b 100644 --- a/README.md +++ b/README.md @@ -51,15 +51,23 @@ exec bash # or: exec zsh / exec fish Windows (for the brave): install from https://rustup.rs with the MSVC toolchain. Yes, you’ll need Visual Studio Build Tools. You chose Windows — enjoy the ride. -### Raspberry Pi / Ubuntu / PopOS (required) +### Raspberry Pi / Ubuntu / PopOS (required for GPU support) -Install GPU support with apt command below +**Note:** GPU monitoring is only supported on x86_64 and aarch64 (64-bit ARM) platforms. ARMv7 (32-bit) and RISC-V builds do not include GPU support. + +For 64-bit systems with GPU support: ```bash sudo apt-get update sudo apt-get install libdrm-dev libdrm-amdgpu1 ``` +For ARMv7 (32-bit Raspberry Pi), build with `--no-default-features` to disable GPU support: + +```bash +cargo build --release -p socktop_agent --no-default-features +``` + _Additional note for Raspberry Pi users. Please update your system to use the newest kernel available through app, kernel version 6.6+ will use considerably less overall CPU to run the agent. For example on a rpi4 the kernel < 6.6 the agent will consume .8 cpu but on the same hardware on > 6.6 the agent will consume only .2 cpu. (these numbers indicate continuous polling at web socket endpoints, when not in use the usage is 0)_ --- diff --git a/apt-repo/KEY.gpg b/apt-repo/KEY.gpg new file mode 100644 index 0000000..c96e90e --- /dev/null +++ b/apt-repo/KEY.gpg @@ -0,0 +1,42 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +Dg== +=AaPQ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/apt-repo/README.md b/apt-repo/README.md new file mode 100644 index 0000000..6bac3ec --- /dev/null +++ b/apt-repo/README.md @@ -0,0 +1,38 @@ +# socktop APT Repository + +This repository contains Debian packages for socktop and socktop-agent. + +## Adding this repository + +Add the repository to your system: + +```bash +# Add the GPG key +curl -fsSL https://jasonwitty.github.io/socktop/KEY.gpg | sudo gpg --dearmor -o /usr/share/keyrings/socktop-archive-keyring.gpg + +# Add the repository +echo "deb [signed-by=/usr/share/keyrings/socktop-archive-keyring.gpg] https://jasonwitty.github.io/socktop stable main" | sudo tee /etc/apt/sources.list.d/socktop.list + +# Update and install +sudo apt update +sudo apt install socktop socktop-agent +``` + +## Manual Installation + +You can also download and install packages manually from the `pool/main/` directory. + +```bash +wget https://jasonwitty.github.io/socktop/pool/main/socktop_VERSION_ARCH.deb +sudo dpkg -i socktop_VERSION_ARCH.deb +``` + +## Supported Architectures + +- amd64 (x86_64) +- arm64 (aarch64) +- armhf (32-bit ARM) + +## Building from Source + +See the main repository at https://github.com/jasonwitty/socktop diff --git a/apt-repo/dists/stable/InRelease b/apt-repo/dists/stable/InRelease new file mode 100644 index 0000000..0507251 --- /dev/null +++ b/apt-repo/dists/stable/InRelease @@ -0,0 +1,32 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +Origin: socktop +Label: socktop +Suite: stable +Codename: stable +Architectures: amd64 arm64 armhf +Components: main +Description: socktop APT repository +Date: Sun, 23 Nov 2025 04:05:21 +0000 +MD5Sum: + 0bddefb2f13cb7c86cd05fe1ce20310f 1549 main/binary-amd64/Packages + 674f0e552cbb7dc65380651a2a8d279e 799 main/binary-amd64/Packages.gz +SHA256: + babfbb4839e7fdfbc83742c16996791b0402a1315889b530330b338380398263 1549 main/binary-amd64/Packages + f8c48d0f7bf53eb02c6dbf5f1cdd046fe71b87273cf763c5bb2e95d9757a7a82 799 main/binary-amd64/Packages.gz + +-----BEGIN PGP SIGNATURE----- + +iQGzBAEBCgAdFiEEHnVWqAU5uDlLwoINESwaeYRl+/IFAmkiiAYACgkQESwaeYRl ++/KBsAv/eYhnK/XrNtPhLyw/zX2cGfUtBsBZrypFhV/n+TvudAIwQaqxDEvLlBUn +HBAhMKDQXGs7V45+nOgDX4rKWUqJh4SPbJgNbVte2PX7U+hsMpZBsYp3vkjApgTO +pq2CCkViyBXgTY+6vUigtvfJ9afTTWI6Qm4dLXZ7hxErBxgHQyowOoO/sF92cNOu +AosBMpE+qSy7sVqJU5g/JXJh0kddKFotXHSGA1kFMzJafJC/n5nLrusDzFJRQqyH +Io+6inYWjlb5o79z0tJzAvG1mgplLRppMBjoVJ/RJ+gT+QE70kokR6wvsgDqsKNd +mvB0TNj0zY0g6Is6V3XMyf0u+6BtLTbua913HPiqBfErgeV58vzsst+y0It42TXi +aw+UF2Kw/YhPq1rZFxgnAVcMja3qlXWpH57gmgIPovBCsPsiywWiHLsSHRzAI22b +zeTsUST/4toR/ruZVbUZvWoWAR4tzsSuwXJFx/hhinTQQTNHErXASOX986UaL9L7 +o2/pTKLe +=IeBY +-----END PGP SIGNATURE----- diff --git a/apt-repo/dists/stable/Release b/apt-repo/dists/stable/Release new file mode 100644 index 0000000..5e0b87a --- /dev/null +++ b/apt-repo/dists/stable/Release @@ -0,0 +1,14 @@ +Origin: socktop +Label: socktop +Suite: stable +Codename: stable +Architectures: amd64 arm64 armhf +Components: main +Description: socktop APT repository +Date: Sun, 23 Nov 2025 04:05:21 +0000 +MD5Sum: + 0bddefb2f13cb7c86cd05fe1ce20310f 1549 main/binary-amd64/Packages + 674f0e552cbb7dc65380651a2a8d279e 799 main/binary-amd64/Packages.gz +SHA256: + babfbb4839e7fdfbc83742c16996791b0402a1315889b530330b338380398263 1549 main/binary-amd64/Packages + f8c48d0f7bf53eb02c6dbf5f1cdd046fe71b87273cf763c5bb2e95d9757a7a82 799 main/binary-amd64/Packages.gz diff --git a/apt-repo/dists/stable/Release.gpg b/apt-repo/dists/stable/Release.gpg new file mode 100644 index 0000000..1f4a323 --- /dev/null +++ b/apt-repo/dists/stable/Release.gpg @@ -0,0 +1,14 @@ +-----BEGIN PGP SIGNATURE----- + +iQGzBAABCgAdFiEEHnVWqAU5uDlLwoINESwaeYRl+/IFAmkiiAEACgkQESwaeYRl ++/KzeAv+OUIbxud5FboerwpAJULV+rS3+VX4kvwg/daVZ3yX3tJNrsyNCHgmWLVu +fLeEFFc2Ax9GvFW4jrbxRAGD+3TXQEEFkb5lGzYyDjlgVzR6wLiVTTrmzWoK+cbB +4DMozqeLiZFfQjq4UFn3+mwiYFX9Dj7PVF0M60XAUJSObbJFmaEPZIfx6wcZfkiL +lLLk1eeU5MPiyudPOhVGgaD76KrUCw+8DBNKoCKIEcCY0LvuKtUK8mWYXRSPSved +4Znd3QZz063Z6R+Lj1XlGLoTPResna28T/Nca+2JgLhbrihsLMcHoFxmrvFP9FpT +MChKngj7NnGt0yqHH5J16hdwMra/vvhmF0yoQ0loIcy+q06tYEqOcau8tvAjfbId +k3rgQgnxxVE8WUmV9Bugp7jhNMO+ImKWMwzEr6wGd9ZHqpknUlAaWeO73VP+qtAN +6mEqWhkqvXGg+srH6qp3Sg0W28dYG29X3Kx8jOp7HeyvA/gLZRN7L+bq/XaA7WFA +1hba6LIY +=QoLf +-----END PGP SIGNATURE----- diff --git a/apt-repo/dists/stable/main/binary-amd64/Packages b/apt-repo/dists/stable/main/binary-amd64/Packages new file mode 100644 index 0000000..0f0a3fa --- /dev/null +++ b/apt-repo/dists/stable/main/binary-amd64/Packages @@ -0,0 +1,38 @@ +Package: socktop +Version: 1.50.0-1 +Architecture: amd64 +Maintainer: Jason Witty +Installed-Size: 3459 +Filename: pool/main/socktop_1.50.0-1_amd64.deb +Size: 1278940 +MD5sum: 0215e178e306d9379669065e8c78582b +SHA1: 04e0416389f5cecd584fd1f6b3568711f2645eee +SHA256: 69eb04b1de48541c95950a97b16357fcd9c51ffaceb143f63de4a9d758fad297 +Section: admin +Priority: optional +Homepage: https://github.com/jasonwitty/socktop +Description: Remote system monitor over WebSocket, TUI like top + socktop is a remote system monitor with a rich terminal user interface (TUI) + that connects to remote hosts running the socktop_agent over WebSocket. It + provides real-time monitoring of CPU, memory, processes, and more with an + interface similar to the traditional 'top' command. + +Package: socktop-agent +Version: 1.50.2-1 +Architecture: amd64 +Maintainer: Jason Witty +Installed-Size: 6793 +Filename: pool/main/socktop-agent_1.50.2-1_amd64.deb +Size: 1896272 +MD5sum: 22e78d03e83dcf84d6ec4a009b285902 +SHA1: 26a9f4fedfdba06a047044027223f2944cf72ba6 +SHA256: 11922af475146f60347a9c52cff4bbce1ce524bdb4293b2c436f3c71876e17d5 +Section: admin +Priority: optional +Homepage: https://github.com/jasonwitty/socktop +Description: Socktop agent daemon. Serves host metrics over WebSocket. + socktop_agent is the daemon component that runs on remote hosts to collect and + serve system metrics over WebSocket. It gathers CPU, memory, disk, network, + GPU, and process information that can be monitored remotely by the socktop TUI + client. + diff --git a/apt-repo/dists/stable/main/binary-amd64/Packages.gz b/apt-repo/dists/stable/main/binary-amd64/Packages.gz new file mode 100644 index 0000000..2584bd7 Binary files /dev/null and b/apt-repo/dists/stable/main/binary-amd64/Packages.gz differ diff --git a/apt-repo/dists/stable/main/binary-amd64/Release b/apt-repo/dists/stable/main/binary-amd64/Release new file mode 100644 index 0000000..7b55517 --- /dev/null +++ b/apt-repo/dists/stable/main/binary-amd64/Release @@ -0,0 +1,5 @@ +Archive: stable +Component: main +Origin: socktop +Label: socktop +Architecture: amd64 diff --git a/apt-repo/index.html b/apt-repo/index.html new file mode 100644 index 0000000..fc486f2 --- /dev/null +++ b/apt-repo/index.html @@ -0,0 +1,58 @@ + + + + + + socktop APT Repository + + + +

socktop APT Repository

+

System monitor with remote agent support for Linux systems.

+ +

Adding this repository

+
# Add the GPG key
+curl -fsSL https://jasonwitty.github.io/socktop/KEY.gpg | sudo gpg --dearmor -o /usr/share/keyrings/socktop-archive-keyring.gpg
+
+# Add the repository
+echo "deb [signed-by=/usr/share/keyrings/socktop-archive-keyring.gpg] https://jasonwitty.github.io/socktop stable main" | sudo tee /etc/apt/sources.list.d/socktop.list
+
+# Update and install
+sudo apt update
+sudo apt install socktop socktop-agent
+ +

Manual Installation

+

Download packages from pool/main/

+ +

Supported Architectures

+ + +

Source Code

+

Visit the GitHub repository

+ + diff --git a/apt-repo/pool/main/socktop-agent_1.50.2-1_amd64.deb b/apt-repo/pool/main/socktop-agent_1.50.2-1_amd64.deb new file mode 100644 index 0000000..45fd533 Binary files /dev/null and b/apt-repo/pool/main/socktop-agent_1.50.2-1_amd64.deb differ diff --git a/apt-repo/pool/main/socktop_1.50.0-1_amd64.deb b/apt-repo/pool/main/socktop_1.50.0-1_amd64.deb new file mode 100644 index 0000000..90a7972 Binary files /dev/null and b/apt-repo/pool/main/socktop_1.50.0-1_amd64.deb differ diff --git a/docs/DEBIAN_PACKAGING.md b/docs/DEBIAN_PACKAGING.md new file mode 100644 index 0000000..30a74d8 --- /dev/null +++ b/docs/DEBIAN_PACKAGING.md @@ -0,0 +1,274 @@ +# Debian Packaging for socktop + +This document describes how to build and use Debian packages for socktop and socktop_agent. + +## Prerequisites + +Install `cargo-deb`: + +```bash +cargo install cargo-deb +``` + +## Building Packages Locally + +### Build for your current architecture (x86_64) + +```bash +# Build socktop TUI client +cargo deb --package socktop + +# Build socktop_agent daemon +cargo deb --package socktop_agent +``` + +The `.deb` files will be created in `target/debian/`. + +### Cross-compile for ARM64 (Raspberry Pi, etc.) + +First, install cross-compilation tools: + +```bash +sudo apt-get update +sudo apt-get install gcc-aarch64-linux-gnu libc6-dev-arm64-cross +``` + +Add the ARM64 target: + +```bash +rustup target add aarch64-unknown-linux-gnu +``` + +Configure the linker by creating `.cargo/config.toml`: + +```toml +[target.aarch64-unknown-linux-gnu] +linker = "aarch64-linux-gnu-gcc" +``` + +Build the packages: + +```bash +# Build for ARM64 +cargo deb --package socktop --target aarch64-unknown-linux-gnu +cargo deb --package socktop_agent --target aarch64-unknown-linux-gnu +``` + +## Installing Packages + +### Install socktop TUI client + +```bash +sudo dpkg -i socktop_*.deb +``` + +### Install socktop_agent daemon + +```bash +sudo dpkg -i socktop_agent_*.deb +``` + +The agent package will: +- Create a `socktop` system user and group +- Install the binary to `/usr/bin/socktop_agent` +- Install a systemd service file (disabled by default) +- Create `/var/lib/socktop` for state files + +### Enable and start the agent service + +```bash +# Enable to start on boot +sudo systemctl enable socktop-agent + +# Start the service +sudo systemctl start socktop-agent + +# Check status +sudo systemctl status socktop-agent +``` + +### Configure the agent + +Edit the systemd service to customize settings: + +```bash +sudo systemctl edit socktop-agent +``` + +Add configuration in the override section: + +```ini +[Service] +Environment=SOCKTOP_PORT=8080 +Environment=SOCKTOP_TOKEN=your-secret-token +Environment=RUST_LOG=info +``` + +Then restart: + +```bash +sudo systemctl restart socktop-agent +``` + +## GitHub Actions + +The project includes a GitHub Actions workflow (`.github/workflows/build-deb.yml`) that automatically builds `.deb` packages for both x86_64 and ARM64 architectures on every push to master or when tags are created. + +### Downloading pre-built packages + +1. Go to the [Actions tab](https://github.com/jasonwitty/socktop/actions) +2. Click on the latest "Build Debian Packages" workflow run +3. Download the artifacts: + - `debian-packages-amd64` - x86_64 packages + - `debian-packages-arm64` - ARM64 packages + - `all-debian-packages` - All packages combined + - `checksums` - SHA256 checksums + +### Release packages + +When you create a git tag starting with `v` (e.g., `v1.50.0`), the workflow will automatically create a GitHub Release with all `.deb` packages attached. + +```bash +git tag v1.50.0 +git push origin v1.50.0 +``` + +## Package Details + +### socktop package + +- **Binary**: `/usr/bin/socktop` +- **Documentation**: `/usr/share/doc/socktop/` +- **Size**: ~5-8 MB (depends on architecture) + +### socktop_agent package + +- **Binary**: `/usr/bin/socktop_agent` +- **Service**: `socktop-agent.service` +- **User/Group**: `socktop` +- **State directory**: `/var/lib/socktop` +- **Config directory**: `/etc/socktop` (created but empty by default) +- **Documentation**: `/usr/share/doc/socktop_agent/` +- **Size**: ~5-8 MB (depends on architecture) + +## Uninstalling + +```bash +# Remove packages but keep configuration +sudo apt remove socktop socktop_agent + +# Remove packages and all configuration (purge) +sudo apt purge socktop socktop_agent +``` + +When purging `socktop_agent`, the following are removed: +- The `socktop` user and group +- `/var/lib/socktop` directory +- Empty `/etc/socktop` directory (if empty) + +## Verifying Packages + +Check package contents: + +```bash +dpkg -c socktop_*.deb +dpkg -c socktop_agent_*.deb +``` + +Check package information: + +```bash +dpkg -I socktop_*.deb +dpkg -I socktop_agent_*.deb +``` + +After installation, verify files: + +```bash +dpkg -L socktop +dpkg -L socktop-agent +``` + +## Troubleshooting + +### Service fails to start + +Check logs: + +```bash +sudo journalctl -u socktop-agent -f +``` + +Verify the socktop user exists: + +```bash +id socktop +``` + +### Permission issues + +Ensure the state directory has correct permissions: + +```bash +sudo chown -R socktop:socktop /var/lib/socktop +sudo chmod 755 /var/lib/socktop +``` + +### Missing dependencies + +If installation fails due to missing dependencies: + +```bash +sudo apt --fix-broken install +``` + +## Creating a Local APT Repository (Advanced) + +To create your own APT repository for easy installation: + +1. Install required tools: + ```bash + sudo apt install dpkg-dev + ``` + +2. Create repository structure: + ```bash + mkdir -p ~/socktop-repo/pool/main + cp *.deb ~/socktop-repo/pool/main/ + ``` + +3. Generate package index: + ```bash + cd ~/socktop-repo + dpkg-scanpackages pool/main /dev/null | gzip -9c > pool/main/Packages.gz + ``` + +4. Serve via HTTP (for testing): + ```bash + cd ~/socktop-repo + python3 -m http.server 8000 + ``` + +5. Add to sources on client machines: + ```bash + echo "deb [trusted=yes] http://your-server:8000 pool/main/" | \ + sudo tee /etc/apt/sources.list.d/socktop.list + sudo apt update + sudo apt install socktop socktop-agent + ``` + +## Contributing + +When adding new features that affect packaging: + +1. Update `Cargo.toml` metadata in the `[package.metadata.deb]` section +2. Add new assets to the `assets` array if needed +3. Update maintainer scripts in `socktop_agent/debian/` if needed +4. Test package building locally before committing +5. Update this documentation + +## References + +- [cargo-deb documentation](https://github.com/kornelski/cargo-deb) +- [Debian Policy Manual](https://www.debian.org/doc/debian-policy/) +- [systemd service files](https://www.freedesktop.org/software/systemd/man/systemd.service.html) \ No newline at end of file diff --git a/docs/cross-compiling.md b/docs/cross-compiling.md index d0ce42d..f2e7cdf 100644 --- a/docs/cross-compiling.md +++ b/docs/cross-compiling.md @@ -2,6 +2,8 @@ This guide explains how to cross-compile the socktop_agent on various host systems and deploy it to a Raspberry Pi. Cross-compiling is particularly useful for older or resource-constrained Pi models where native compilation might be slow. +**Note:** GPU monitoring support is not available on ARMv7 (32-bit) and RISC-V architectures due to library limitations. When building for these platforms, the `--no-default-features` flag must be used to disable GPU support. + ## Cross-Compilation Host Setup Choose your host operating system: @@ -23,8 +25,9 @@ sudo apt update sudo apt install gcc-aarch64-linux-gnu libc6-dev-arm64-cross libdrm-dev:arm64 # For 32-bit Raspberry Pi (armv7) +# Note: GPU support not available on armv7 sudo apt update -sudo apt install gcc-arm-linux-gnueabihf libc6-dev-armhf-cross libdrm-dev:armhf +sudo apt install gcc-arm-linux-gnueabihf libc6-dev-armhf-cross ``` ### Setup Rust Cross-Compilation Targets @@ -65,9 +68,8 @@ sudo pacman -S aarch64-linux-gnu-gcc yay -S aarch64-linux-gnu-libdrm # For 32-bit Raspberry Pi (armv7) +# Note: GPU support not available on armv7 sudo pacman -S arm-linux-gnueabihf-gcc -# Install libdrm for armv7 using an AUR helper -yay -S arm-linux-gnueabihf-libdrm ``` ### Setup Rust Cross-Compilation Targets @@ -114,8 +116,8 @@ cd path/to/socktop # For 64-bit Raspberry Pi docker run --rm -it -v "$(pwd)":/home/rust/src messense/rust-musl-cross:aarch64-musl cargo build --release --target aarch64-unknown-linux-musl -p socktop_agent -# For 32-bit Raspberry Pi -docker run --rm -it -v "$(pwd)":/home/rust/src messense/rust-musl-cross:armv7-musleabihf cargo build --release --target armv7-unknown-linux-musleabihf -p socktop_agent +# For 32-bit Raspberry Pi (without GPU support) +docker run --rm -it -v "$(pwd)":/home/rust/src messense/rust-musl-cross:armv7-musleabihf cargo build --release --target armv7-unknown-linux-musleabihf -p socktop_agent --no-default-features ``` The compiled binaries will be available in your local target directory. @@ -133,11 +135,11 @@ The recommended approach for Windows is to use Windows Subsystem for Linux (WSL2 After setting up your environment, build the socktop_agent for your target Raspberry Pi: ```bash -# For 64-bit Raspberry Pi +# For 64-bit Raspberry Pi (with GPU support) cargo build --release --target aarch64-unknown-linux-gnu -p socktop_agent -# For 32-bit Raspberry Pi -cargo build --release --target armv7-unknown-linux-gnueabihf -p socktop_agent +# For 32-bit Raspberry Pi (without GPU support) +cargo build --release --target armv7-unknown-linux-gnueabihf -p socktop_agent --no-default-features ``` ## Transfer the Binary to Your Raspberry Pi @@ -161,11 +163,12 @@ SSH into your Raspberry Pi and install the required dependencies: ```bash ssh pi@raspberry-pi-ip -# For Raspberry Pi OS (Debian-based) +# For Raspberry Pi OS (Debian-based) - 64-bit only +# (32-bit armv7 builds don't require these) sudo apt update sudo apt install libdrm-dev libdrm-amdgpu1 -# For Arch Linux ARM +# For Arch Linux ARM - 64-bit only sudo pacman -Syu sudo pacman -S libdrm ``` diff --git a/socktop/Cargo.toml b/socktop/Cargo.toml index b9df459..e7368a8 100644 --- a/socktop/Cargo.toml +++ b/socktop/Cargo.toml @@ -6,6 +6,8 @@ description = "Remote system monitor over WebSocket, TUI like top" edition = "2024" license = "MIT" readme = "README.md" +homepage = "https://github.com/jasonwitty/socktop" +repository = "https://github.com/jasonwitty/socktop" [dependencies] # socktop connector for agent communication @@ -25,3 +27,20 @@ sysinfo = { workspace = true } [dev-dependencies] assert_cmd = "2.0" tempfile = "3" + +[package.metadata.deb] +maintainer = "Jason Witty " +copyright = "2024, Jason Witty " +license-file = ["../LICENSE", "4"] +extended-description = """\ +socktop is a remote system monitor with a rich terminal user interface (TUI) \ +that connects to remote hosts running the socktop_agent over WebSocket. \ +It provides real-time monitoring of CPU, memory, processes, and more with \ +an interface similar to the traditional 'top' command.""" +depends = "$auto" +section = "admin" +priority = "optional" +assets = [ + ["target/release/socktop", "usr/bin/", "755"], + ["../README.md", "usr/share/doc/socktop/", "644"], +] diff --git a/socktop_agent/Cargo.toml b/socktop_agent/Cargo.toml index 78dd506..6de4b95 100644 --- a/socktop_agent/Cargo.toml +++ b/socktop_agent/Cargo.toml @@ -1,11 +1,13 @@ [package] name = "socktop_agent" -version = "1.50.1" +version = "1.50.2" authors = ["Jason Witty "] description = "Socktop agent daemon. Serves host metrics over WebSocket." edition = "2024" license = "MIT" readme = "README.md" +homepage = "https://github.com/jasonwitty/socktop" +repository = "https://github.com/jasonwitty/socktop" [dependencies] # Tokio: Use minimal features instead of "full" to reduce binary size @@ -21,10 +23,10 @@ flate2 = { version = "1", default-features = false, features = ["rust_backend"] futures-util = "0.3.31" tracing = { version = "0.1", optional = true } tracing-subscriber = { version = "0.3", features = ["env-filter"], optional = true } -gfxinfo = "0.1.2" +gfxinfo = { version = "0.1.2", optional = true } once_cell = "1.19" axum-server = { version = "0.7", features = ["tls-rustls"] } -rustls = "0.23" +rustls = { version = "0.23", features = ["aws-lc-rs"] } rustls-pemfile = "2.1" rcgen = "0.13" anyhow = "1" @@ -33,7 +35,8 @@ prost = { workspace = true } time = { version = "0.3", default-features = false, features = ["formatting", "macros", "parsing" ] } [features] -default = [] +default = ["gpu"] +gpu = ["gfxinfo"] logging = ["tracing", "tracing-subscriber"] [build-dependencies] @@ -45,3 +48,21 @@ protoc-bin-vendored = "3" assert_cmd = "2.0" tempfile = "3.10" tokio-tungstenite = "0.21" + +[package.metadata.deb] +maintainer = "Jason Witty " +copyright = "2024, Jason Witty " +license-file = ["../LICENSE", "4"] +extended-description = """\ +socktop_agent is the daemon component that runs on remote hosts to collect \ +and serve system metrics over WebSocket. It gathers CPU, memory, disk, network, \ +GPU, and process information that can be monitored remotely by the socktop TUI client.""" +depends = "$auto" +section = "admin" +priority = "optional" +assets = [ + ["target/release/socktop_agent", "usr/bin/", "755"], + ["../README.md", "usr/share/doc/socktop_agent/", "644"], +] +maintainer-scripts = "debian/" +systemd-units = { unit-name = "socktop-agent", unit-scripts = ".", enable = false } diff --git a/socktop_agent/debian/postinst b/socktop_agent/debian/postinst new file mode 100755 index 0000000..6ccb237 --- /dev/null +++ b/socktop_agent/debian/postinst @@ -0,0 +1,57 @@ +#!/bin/sh +set -e + +# Create socktop user and group if they don't exist +if ! getent group socktop >/dev/null; then + addgroup --system socktop +fi + +if ! getent passwd socktop >/dev/null; then + adduser --system --ingroup socktop --home /var/lib/socktop \ + --no-create-home --disabled-password --disabled-login \ + --gecos "Socktop Agent" socktop +fi + +# Create state directory +mkdir -p /var/lib/socktop +chown socktop:socktop /var/lib/socktop +chmod 755 /var/lib/socktop + +# Create config directory if it doesn't exist +mkdir -p /etc/socktop +chmod 755 /etc/socktop + +#DEBHELPER# + +# Print helpful message to the user +cat </dev/null; then + deluser --quiet socktop || true + fi + + if getent group socktop >/dev/null; then + delgroup --quiet socktop || true + fi + + # Remove state directory on purge + rm -rf /var/lib/socktop + + # Remove config directory if empty + rmdir --ignore-fail-on-non-empty /etc/socktop 2>/dev/null || true + ;; + + remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + # Do nothing on remove/upgrade + ;; + + *) + echo "postrm called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +#DEBHELPER# + +exit 0 diff --git a/socktop_agent/socktop-agent.service b/socktop_agent/socktop-agent.service new file mode 100644 index 0000000..5caaa14 --- /dev/null +++ b/socktop_agent/socktop-agent.service @@ -0,0 +1,27 @@ +[Unit] +Description=Socktop Agent - Remote System Monitor +Documentation=https://github.com/jasonwitty/socktop +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +ExecStart=/usr/bin/socktop_agent --port 3000 +Environment=RUST_LOG=info +# Optional authentication token: +# Environment=SOCKTOP_TOKEN=changeme +Restart=on-failure +RestartSec=5 +User=socktop +Group=socktop +NoNewPrivileges=true + +# Security hardening +PrivateTmp=true +ProtectSystem=strict +ProtectHome=true +ReadWritePaths=/var/lib/socktop +StateDirectory=socktop + +[Install] +WantedBy=multi-user.target diff --git a/socktop_agent/src/gpu.rs b/socktop_agent/src/gpu.rs index 9082dcb..9e0eb08 100644 --- a/socktop_agent/src/gpu.rs +++ b/socktop_agent/src/gpu.rs @@ -1,4 +1,5 @@ // gpu.rs +#[cfg(feature = "gpu")] use gfxinfo::active_gpu; #[derive(Debug, Clone, serde::Serialize)] @@ -9,6 +10,7 @@ pub struct GpuMetrics { pub mem_total_bytes: u64, } +#[cfg(feature = "gpu")] pub fn collect_all_gpus() -> Result, Box> { let gpu = active_gpu()?; // Use ? to unwrap Result let info = gpu.info(); @@ -22,3 +24,9 @@ pub fn collect_all_gpus() -> Result, Box> Ok(vec![metrics]) } + +#[cfg(not(feature = "gpu"))] +pub fn collect_all_gpus() -> Result, Box> { + // GPU support not available on this platform + Ok(vec![]) +} diff --git a/socktop_agent/src/main.rs b/socktop_agent/src/main.rs index 2933bf9..80a1c2f 100644 --- a/socktop_agent/src/main.rs +++ b/socktop_agent/src/main.rs @@ -30,6 +30,12 @@ fn arg_value(name: &str) -> Option { } fn main() -> anyhow::Result<()> { + // Install rustls crypto provider before any TLS operations + // This is required when using axum-server's tls-rustls feature + rustls::crypto::aws_lc_rs::default_provider() + .install_default() + .ok(); // Ignore error if already installed + #[cfg(feature = "logging")] tracing_subscriber::fmt::init(); diff --git a/socktop_agent/tests/tls_cert_creation.rs b/socktop_agent/tests/tls_cert_creation.rs index 09933d7..3bab90b 100644 --- a/socktop_agent/tests/tls_cert_creation.rs +++ b/socktop_agent/tests/tls_cert_creation.rs @@ -1,4 +1,3 @@ -use assert_cmd::prelude::*; use std::fs; use std::path::PathBuf; use std::process::Command; @@ -17,7 +16,7 @@ fn generates_self_signed_cert_and_key_in_xdg_path() { let xdg = tmpdir.path().to_path_buf(); // Run the agent once with --enableSSL, short timeout so it exits quickly when killed - let mut cmd = Command::cargo_bin("socktop_agent").expect("binary exists"); + let mut cmd = Command::new(assert_cmd::cargo::cargo_bin!("socktop_agent")); // Bind to an ephemeral port (-p 0) to avoid conflicts/flakes cmd.env("XDG_CONFIG_HOME", &xdg) .arg("--enableSSL")