Two fixes for FreeBSD agent support:
1. The Docker image never built or included FreeBSD agent binaries, causing
404 errors when FreeBSD clients requested the download. Added FreeBSD
amd64/arm64 cross-compilation for both host-agent and unified-agent,
plus COPY statements to include them in the image. Also added bare
FreeBSD binaries to GitHub release assets for the redirect fallback.
2. pfSense does not use the standard FreeBSD rc.d boot system — scripts
in /usr/local/etc/rc.d/ must end in .sh to run at boot. The installer
now detects pfSense and creates a .sh boot wrapper alongside the
standard rc.d script. Also added -r flag to daemon for auto-restart.
Related to #1051
Restored original license signing key from backup - key was never
compromised (private repo). Removes unnecessary dual-key complexity:
- Remove legacyPublicKey and SetLegacyPublicKey from license.go
- Simplify signature verification to single key
- Remove EmbeddedLegacyPublicKey from pubkey.go
- Remove PULSE_LICENSE_LEGACY_PUBLIC_KEY from Dockerfile and workflows
- Remove dual-key test
- Simplify mock.env
The runtime stage was copying both amd64 and arm64 pulse binaries to /tmp/,
then selecting one based on TARGETARCH and deleting the rest. Due to Docker's
immutable layers, the deleted binaries were still counted toward image size.
Changed to copy directly using TARGETARCH variable substitution, which only
copies the needed binary for the target architecture.
This saves ~34MB per architecture in the final image.
Note: The agent_runtime stage and /opt/pulse/bin/ download binaries still have
room for optimization, but require more complex changes.
Related to #981
The previous commit forced the builder stage to linux/amd64 to avoid
QEMU timeouts, but forgot to add explicit GOARCH for the main pulse
binary. This caused amd64 binaries to be shipped in arm64 images,
resulting in "Exec format error" on ARM64 hosts.
Now the main pulse binary is cross-compiled for both amd64 and arm64
(like all the agent binaries already were), and the runtime stage
selects the correct binary based on TARGETARCH.
Related to #933
The multi-arch Docker build was timing out after 1 hour because
the backend-builder stage was running under QEMU emulation for arm64.
Building 31 Go binaries under QEMU is extremely slow.
Since Go cross-compiles all target architectures anyway, and the
frontend build produces platform-independent JS, there's no need
to run these stages under QEMU. Force them to linux/amd64 and let
Go handle cross-compilation natively.
Only the runtime stages need to be multi-arch (for the correct
Alpine base image and binary selection).
The healthcheck was hardcoded to use HTTP, which fails when
HTTPS_ENABLED=true. Now uses a script that detects the protocol
and uses --no-check-certificate for self-signed certs.
Related to #922
- Add HandleLicenseFeatures handler that was missing from license_handlers.go
- Add /api/license/features route to router
- Update AI service and metadata provider
- Update frontend license API and components
- Fix CI build failure caused by tests referencing unimplemented method
The unified agent system replaced install-host-agent.sh with install.sh.
This commit updates all references:
- Dockerfile: removed COPY for deleted script
- router.go: serve install.sh at /install-host-agent.sh endpoint (backwards compatible)
- build-release.sh: removed copy of deleted script
- validate-release.sh: removed validation of deleted script
- install.sh: updated script list for bare-metal installs
Implement self-update capability for the unified pulse-agent binary:
- Add internal/agentupdate package with cross-platform update logic
- Hourly version checks against /api/agent/version endpoint
- SHA256 checksum verification for downloaded binaries
- Atomic binary replacement with backup/rollback on failure
- Support for Linux, macOS, and Windows (10 platform/arch combinations)
Build and release changes:
- Dockerfile builds unified agent for all platforms
- build-release.sh includes unified agent in release artifacts
- validate-release.sh validates unified agent binaries
- Install scripts (install.sh, install.ps1) use correct URL format
Related to #727, #737
Related to systematic release workflow failures. The workflow has never
successfully completed from start to finish since validation was added.
Root causes identified and fixed:
1. **GraphQL node_id vs numeric release ID**: The create-release job was
using `gh release view --json id` which returns a GraphQL node_id
(RE_kwDON5nJtM4PmlTt) instead of the numeric database ID (261772525)
needed by the REST API. The validation workflow then failed with 404
when trying to download assets. Fixed by using `gh api` to get the
numeric ID from the releases list endpoint.
2. **Missing binaries in Docker image**: The validation script expects 26
binaries + 3 Windows symlinks in /opt/pulse/bin/, but the Dockerfile
was only copying a subset. Missing binaries included the main pulse
server binary, armv6/386 builds for all agents, and caused immediate
validation failure. Fixed by copying all built binaries from
backend-builder stage.
3. **Assets-only validation fallback broken**: When Docker image pull
times out, the workflow falls back to assets-only validation but was
still calling the validation script without --skip-docker flag,
causing it to fail on the first docker command. Fixed by passing
--skip-docker flag in the fallback path.
4. **Asset download pagination**: The asset download was not using
--paginate, which would cause silent failures once we exceed 30 assets
(currently at 27). Fixed by adding --paginate to gh api call.
All fixes verified locally and address the complete failure chain.
Adds build support for 32-bit Windows (windows-386) for pulse-host-agent.
Changes:
- Add windows-386 build to Dockerfile host-agent build section
- Add windows-386 binary copy and symlink to Dockerfile
- Add windows-386 build to build-release.sh
- Add windows-386 zip package to release artifacts
- Include windows-386 binary in standalone binary copies
This enables pulse-host-agent to run on 32-bit Windows systems, which are still relevant in legacy/industrial monitoring environments through late 2025.
Adds build support for 32-bit x86 (i386/i686) and ARMv6 (older Raspberry Pi models) architectures across all agents and install scripts.
Changes:
- Add linux-386 and linux-armv6 to build-release.sh builds array
- Update Dockerfile to build docker-agent, host-agent, and sensor-proxy for new architectures
- Update all install scripts to detect and handle i386/i686 and armv6l architectures
- Add architecture normalization in router download endpoints
- Update update manager architecture mapping
- Update validate-release.sh to expect 24 binaries (was 18)
This enables Pulse agents to run on older/legacy hardware including 32-bit x86 systems and Raspberry Pi Zero/Zero W devices.
Windows 11 25H2 ships exclusively on ARM64 hardware. When users on ARM64
attempt to install the host agent, the Service Control Manager fails to
load the amd64 binary with ERROR_BAD_EXE_FORMAT, surfaced as "The Pulse
Host Agent is not compatible with this Windows version".
Changes:
- Dockerfile: Build pulse-host-agent-windows-arm64.exe alongside amd64
- Dockerfile: Copy windows-arm64 binary and create symlink for download endpoint
- install-host-agent.ps1: Use RuntimeInformation.OSArchitecture to detect ARM64
- build-release.sh: Build darwin-amd64, darwin-arm64, windows-amd64, windows-arm64
- build-release.sh: Package Windows binaries as .zip archives
- validate-release.sh: Check for windows-arm64 binary and symlink
- validate-release.sh: Add architecture validation for all darwin/windows variants
The installer now correctly detects ARM64 and downloads the appropriate binary.
The Dockerfile and build-release.sh were missing several installer and uninstaller
scripts that the router expects to serve via HTTP endpoints:
- install-container-agent.sh
- install-host-agent.ps1
- uninstall-host-agent.sh
- uninstall-host-agent.ps1
This caused 404 errors when users attempted to add Docker/Podman hosts or use the
PowerShell installer, as reported in #644.
Changes:
- Dockerfile: Added missing scripts to /opt/pulse/scripts/ with proper permissions
- build-release.sh: Added missing scripts to both per-platform and universal tarballs
to ensure bare-metal deployments serve the same endpoints as Docker deployments
The Docker build was only setting internal/dockeragent.Version but not
main.Version, causing the pulse binary to show "dev" instead of the
actual version. Now matches build-release.sh ldflags pattern.
Related to v4.26.1 release
Addresses the root cause of issue #631 (infinite Docker agent restart loop)
and prevents similar issues with host-agent and sensor-proxy.
Changes:
- Set dockeragent.Version default to "dev" instead of hardcoded version
- Add version embedding to server build in Dockerfile
- Add version embedding to host-agent builds (all platforms)
- Add version embedding to sensor-proxy builds (all platforms)
This ensures:
1. Server's /api/agent/version endpoint returns correct v4.26.0
2. Downloaded agent binaries have matching embedded versions
3. Dev builds skip auto-update (Version="dev")
4. No version mismatch triggers infinite restart loops
Related to #631
The docker agent binaries built in the Dockerfile were missing version
information in their ldflags, causing them to always report v4.30.0
(the hardcoded default). This created an update loop where agents would
continuously download and restart when checking for updates.
The server's /api/agent/version endpoint returns dockeragent.Version,
which for the bundled binaries was always v4.30.0 instead of the actual
release version (e.g., v4.25.0). When an older agent (e.g., v4.23.0)
checked for updates, it would see v4.30.0 available, download it, restart,
and repeat the cycle continuously.
This fix adds the VERSION file content to the ldflags when building
all docker agent binaries (amd64, arm64, armv7), matching the pattern
already used in scripts/build-release.sh.
Related to #631
Related to #571
This addresses multiple temperature monitoring issues:
1. Fix single-node Proxmox installation failure: Add '|| true' to pvecm status
calls to prevent script exit on standalone (non-clustered) nodes with
'set -euo pipefail'. The script now properly falls through to standalone
node configuration when cluster detection fails.
2. Build pulse-sensor-proxy for all Linux architectures (amd64, arm64, armv7)
in Dockerfile to ensure binaries are available for download on all supported
platforms. This resolves the missing binary issue from v4.23.0.
Note: AMD Tctl sensor support was already implemented in a previous commit.
- Build host agent binaries for all platforms (linux/darwin/windows, amd64/arm64/armv7) in Docker
- Add Makefile target for building agent binaries locally
- Add startup validation to check for missing agent binaries
- Improve download endpoint error messages with troubleshooting guidance
- Enhance host details drawer layout with better organization and visual hierarchy
- Update base images to rolling versions (node:20-alpine, golang:1.24-alpine, alpine:3.20)
- Changed SSH key generation from RSA 2048 to Ed25519 (more secure, faster, smaller)
- Added openssh-client package to Docker image (required for temperature monitoring)
- Updated SSH config template to use id_ed25519
- Removed unused crypto/rsa and crypto/x509 imports
Ed25519 provides better security with shorter keys and faster operations
compared to RSA. The container now has SSH client tools needed to connect
to Proxmox nodes for temperature data collection.
The router's handleDownloadAgent searches for /opt/pulse/bin/pulse-docker-agent
as a fallback when arch-specific binaries are not found or requested. In v4.23.0,
this fallback binary was missing from the Docker image, causing 404 errors for
linux-amd64 downloads.
The Dockerfile now explicitly copies the fallback binary to /opt/pulse/bin/pulse-docker-agent
alongside the arch-specific binaries (linux-amd64, linux-arm64, linux-armv7).
Verified with local build - all four binaries now exist in /opt/pulse/bin/.
Addresses #528
When Pulse runs in Docker, ARM users couldn't download the docker-agent
because only the host architecture binary was built. The Dockerfile now
builds amd64, arm64, and armv7 binaries and includes them at /opt/pulse/bin/
so the download endpoint can serve all architectures.