feat: serve install scripts from GitHub releases instead of main branch

Scripts like install.sh and install-sensor-proxy.sh are now attached
as release assets and downloaded from releases/latest/download/ URLs.
This ensures users always get scripts compatible with their installed
version, even while development continues on main.

Changes:
- build-release.sh: copy install scripts to release directory
- create-release.yml: upload scripts as release assets
- Updated all documentation and code references to use release URLs
- Scripts reference each other via release URLs for consistency
This commit is contained in:
rcourtman 2025-11-26 08:59:59 +00:00
parent 0f0832d30f
commit e467523a61
15 changed files with 63 additions and 49 deletions

View file

@ -474,8 +474,13 @@ jobs:
gh release upload "${TAG}" release/*.tgz
fi
# Upload install.sh
# Upload install scripts as standalone assets
# Users can now use: curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install.sh | bash
# This ensures scripts are version-locked to the release, not pulled from main branch
gh release upload "${TAG}" release/install.sh
gh release upload "${TAG}" release/install-sensor-proxy.sh
gh release upload "${TAG}" release/install-docker.sh
gh release upload "${TAG}" release/pulse-auto-update.sh
- name: Output release information
run: |

View file

@ -37,7 +37,7 @@ Designed for homelabs, sysadmins, and MSPs who need a "single pane of glass" wit
Run this one-liner on your Proxmox host to create a lightweight LXC container:
```bash
curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/install.sh | bash
curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install.sh | bash
```
### Option 2: Docker

View file

@ -40,7 +40,7 @@ environment where `PULSE_DOCKER=true`/`/.dockerenv` is detected.
1. **Install the sensor proxy on the Proxmox host that runs Pulse**
```bash
curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh | \
curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh | \
bash -s -- --ctid <pulse-lxc-id> --pulse-server https://pulse.example.com:7655
```
- For Docker or standalone hosts where Pulse cannot mount the socket (or when collecting temps from *other* nodes), run the installer with `--standalone --http-mode` so each host exposes its own HTTPS endpoint on port 8443.

View file

@ -9,7 +9,7 @@ capabilities, and produces append-only audit logs.
| Scenario | Command |
| --- | --- |
| **Recommended (automated)** | `curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh \| bash` |
| **Recommended (automated)** | `curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh \| bash` |
| **Manual build** | `go build ./cmd/pulse-sensor-proxy` and `sudo install -m 0755 pulse-sensor-proxy /usr/local/bin/` |
| **Prebuilt artifact** | Copy the binary from `/opt/pulse/bin/pulse-sensor-proxy-*` inside the Pulse Docker image or download via `/download/pulse-sensor-proxy?platform=linux&arch=amd64`. |
@ -191,7 +191,7 @@ If you suspect config corruption (service won't start, temperatures stopped):
2. **If corruption is detected, reinstall the proxy:**
```bash
curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh | \
curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh | \
sudo bash -s -- --standalone --pulse-server http://your-pulse:7655
```
The installer automatically migrates to file-based config and fixes corruption.

View file

@ -5,7 +5,7 @@
### What's the easiest way to install?
Run this one-liner on your Proxmox host:
```bash
curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/install.sh | bash
curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install.sh | bash
```
### How do I add a node?

View file

@ -8,7 +8,7 @@ Pulse offers flexible installation options ranging from a simple one-liner for P
The easiest way to run Pulse on Proxmox. This script creates a lightweight LXC container, configures networking, and starts the service.
```bash
curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/install.sh | bash
curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install.sh | bash
```
### Docker
@ -32,10 +32,10 @@ The installer supports advanced flags for automation or custom setups.
```bash
# Install specific version
curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/install.sh | bash -s -- --version v4.24.0
curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install.sh | bash -s -- --version v4.24.0
# Install from source (dev branch)
curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/install.sh | bash -s -- --source develop
curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install.sh | bash -s -- --source develop
```
### 2. Kubernetes (Helm)
@ -55,7 +55,7 @@ For bare-metal Linux servers (Debian/Ubuntu).
```bash
# The installer detects non-Proxmox systems and installs as a systemd service
curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/install.sh | bash
curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install.sh | bash
```
---

View file

@ -22,11 +22,11 @@ Temperature monitoring will not work for remote nodes until every Proxmox host i
```bash
# 1. Remove any pre-v4.31.0 proxy install
curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh | \
curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh | \
sudo bash -s -- --uninstall --purge
# 2. Install the HTTP-enabled proxy and register it with Pulse
curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh | \
curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh | \
sudo bash -s -- --standalone --http-mode --pulse-server https://your-pulse-host:7655
```

View file

@ -22,7 +22,7 @@ If running Pulse in Docker, you must install the proxy on the host and share the
1. **Install Proxy on Host**:
```bash
curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh | \
curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh | \
sudo bash -s -- --standalone --pulse-server http://<pulse-ip>:7655
```
@ -41,7 +41,7 @@ For nodes *other* than the one running Pulse, install the proxy in HTTP mode.
1. **Run Installer on Remote Node**:
```bash
curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh | \
curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh | \
sudo bash -s -- --standalone --http-mode --pulse-server http://<pulse-ip>:7655
```
2. **Verify**: Pulse will automatically detect the proxy and start collecting data.
@ -79,7 +79,7 @@ journalctl -u pulse-sensor-proxy -f
provisioner "remote-exec" {
inline = [
"curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh -o /tmp/install-sensor-proxy.sh",
"curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh -o /tmp/install-sensor-proxy.sh",
"chmod +x /tmp/install-sensor-proxy.sh",
"/tmp/install-sensor-proxy.sh --standalone --pulse-server ${var.pulse_server_url} --quiet",
"systemctl is-active pulse-sensor-proxy || exit 1"
@ -129,7 +129,7 @@ Allowed nodes live in `/etc/pulse-sensor-proxy/allowed_nodes.yaml`; change them
**5. Install systemd service:**
```bash
# Download from: https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh
# Download from: https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh
# Extract the systemd unit from the installer (ExecStartPre/ExecStart use /opt/pulse/sensor-proxy/bin)
systemctl daemon-reload
systemctl enable --now pulse-sensor-proxy
@ -440,7 +440,7 @@ cp id_ed25519.pub id_ed25519.pub.backup
ssh-keygen -t ed25519 -f id_ed25519 -N "" -C "pulse-sensor-proxy-rotated"
# 3. Re-run setup to push keys to cluster
curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh | \
curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh | \
bash -s -- --ctid <your-container-id>
# 4. Verify temperature data still works in Pulse UI
@ -639,7 +639,7 @@ test -S /run/pulse-sensor-proxy/pulse-sensor-proxy.sock && echo "Socket OK" || e
**New Cluster Node Not Showing Temperatures:**
1. Ensure lm-sensors installed: `ssh root@new-node "sensors -j"`
2. Proxy auto-discovers on next poll (may take up to 1 minute)
3. Re-run the setup script to configure SSH keys on the new node: `curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh | bash -s -- --ctid <CTID>`
3. Re-run the setup script to configure SSH keys on the new node: `curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh | bash -s -- --ctid <CTID>`
**Permission Denied Errors:**
1. Verify socket permissions: `ls -l /run/pulse-sensor-proxy/pulse-sensor-proxy.sock`

View file

@ -567,7 +567,7 @@ prompt_proxy_installation() {
echo ""
print_info "Skipping proxy installation"
print_info "Temperature monitoring from container will be unavailable"
print_info "To enable later, run: curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh | bash -s -- --ctid <CTID>"
print_info "To enable later, run: curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh | bash -s -- --ctid <CTID>"
return 1
fi
}
@ -1497,12 +1497,12 @@ create_lxc_container() {
# We're being piped, download the script
# Use timeout to prevent hanging
if command -v timeout >/dev/null 2>&1; then
if ! timeout 15 curl -fsSL --connect-timeout 5 --max-time 15 https://raw.githubusercontent.com/rcourtman/Pulse/main/install.sh > "$script_source" 2>/dev/null; then
if ! timeout 15 curl -fsSL --connect-timeout 5 --max-time 15 https://github.com/rcourtman/Pulse/releases/latest/download/install.sh > "$script_source" 2>/dev/null; then
print_error "Failed to download install script"
cleanup_on_error
fi
else
if ! curl -fsSL --connect-timeout 5 --max-time 15 https://raw.githubusercontent.com/rcourtman/Pulse/main/install.sh > "$script_source" 2>/dev/null; then
if ! curl -fsSL --connect-timeout 5 --max-time 15 https://github.com/rcourtman/Pulse/releases/latest/download/install.sh > "$script_source" 2>/dev/null; then
print_error "Failed to download install script"
cleanup_on_error
fi
@ -1670,21 +1670,21 @@ fi'; then
if [[ "$installer_ready" != true ]]; then
if command -v timeout >/dev/null 2>&1; then
if timeout 15 curl -fsSL --connect-timeout 5 --max-time 15 \
"https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh" \
"https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh" \
> "$proxy_script" 2>/dev/null; then
installer_ready=true
else
print_warn "Failed to download proxy installer - temperature monitoring unavailable"
print_info "Run manually later: curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh | bash -s -- --ctid $CTID"
print_info "Run manually later: curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh | bash -s -- --ctid $CTID"
fi
else
if curl -fsSL --connect-timeout 5 --max-time 15 \
"https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh" \
"https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh" \
> "$proxy_script" 2>/dev/null; then
installer_ready=true
else
print_warn "Failed to download proxy installer - temperature monitoring unavailable"
print_info "Run manually later: curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh | bash -s -- --ctid $CTID"
print_info "Run manually later: curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh | bash -s -- --ctid $CTID"
fi
fi
fi
@ -1823,7 +1823,7 @@ fi'; then
echo
echo "To fix, you can either:"
echo " 1. Fix the issue and run the proxy installer manually:"
echo " curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh | bash -s -- --ctid $CTID"
echo " curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh | bash -s -- --ctid $CTID"
echo
echo " 2. Re-run the Pulse installer and skip temperature monitoring when prompted"
echo
@ -1874,7 +1874,7 @@ refresh_container_proxy_installer() {
return
fi
local installer_url="https://raw.githubusercontent.com/${GITHUB_REPO}/${SOURCE_BRANCH:-main}/scripts/install-sensor-proxy.sh"
local installer_url="https://github.com/${GITHUB_REPO}/releases/latest/download/install-sensor-proxy.sh"
print_info "Refreshing sensor proxy installer inside container ${target_ctid}..."
if ! pct exec "$target_ctid" -- bash -c "set -euo pipefail; mkdir -p /usr/local/share/pulse; tmp=\$(mktemp); curl -fsSL --connect-timeout 10 --max-time 45 '${installer_url}' -o \$tmp && install -m 0755 \$tmp /usr/local/share/pulse/install-sensor-proxy.sh && rm -f \$tmp"; then
print_warn "Unable to refresh container installer; continuing with bundled version"
@ -3083,9 +3083,9 @@ fi
echo "Updating Pulse..."
if [[ ${#extra_args[@]} -gt 0 ]]; then
curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/install.sh | bash -s -- "${extra_args[@]}"
curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install.sh | bash -s -- "${extra_args[@]}"
else
curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/install.sh | bash
curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install.sh | bash
fi
echo ""
@ -3106,7 +3106,7 @@ EOF
}
download_auto_update_script() {
local url="https://raw.githubusercontent.com/$GITHUB_REPO/main/scripts/pulse-auto-update.sh"
local url="https://github.com/$GITHUB_REPO/releases/latest/download/pulse-auto-update.sh"
local dest="/usr/local/bin/pulse-auto-update.sh"
local attempts=0
local max_attempts=3
@ -3392,9 +3392,9 @@ print_completion() {
echo " journalctl -u $SERVICE_NAME -f - View logs"
echo
echo -e "${YELLOW}Management:${NC}"
echo " Update: curl -sSL https://raw.githubusercontent.com/rcourtman/Pulse/main/install.sh | bash"
echo " Reset: curl -sSL https://raw.githubusercontent.com/rcourtman/Pulse/main/install.sh | bash -s -- --reset"
echo " Uninstall: curl -sSL https://raw.githubusercontent.com/rcourtman/Pulse/main/install.sh | bash -s -- --uninstall"
echo " Update: curl -sSL https://github.com/rcourtman/Pulse/releases/latest/download/install.sh | bash"
echo " Reset: curl -sSL https://github.com/rcourtman/Pulse/releases/latest/download/install.sh | bash -s -- --reset"
echo " Uninstall: curl -sSL https://github.com/rcourtman/Pulse/releases/latest/download/install.sh | bash -s -- --uninstall"
local proxy_status="Not installed"
local pending_file="/etc/pulse-sensor-proxy/pending-control-plane.env"
@ -3423,7 +3423,7 @@ print_completion() {
echo
echo -e "${YELLOW}Temperature monitoring:${NC}"
echo " Run on the Proxmox host to enable secure temperature collection:"
echo " curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh | \\"
echo " curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh | \\"
echo " bash -s -- --ctid ${proxy_ctid} --pulse-server ${PULSE_URL}"
echo " See docs/TEMPERATURE_MONITORING.md for details."
fi

View file

@ -4044,7 +4044,7 @@ func (r *Router) handleTemperatureProxyInstallCommand(w http.ResponseWriter, req
node := strings.TrimSpace(req.URL.Query().Get("node"))
command := fmt.Sprintf(
"curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh | sudo bash -s -- --standalone --http-mode --pulse-server %s",
"curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh | sudo bash -s -- --standalone --http-mode --pulse-server %s",
baseURL,
)
@ -4090,7 +4090,7 @@ func (r *Router) handleHostProxyStatus(w http.ResponseWriter, req *http.Request)
ctid = summary.CTID
}
resp["reinstallCommand"] = fmt.Sprintf("curl -fsSL https://raw.githubusercontent.com/rcourtman/Pulse/main/scripts/install-sensor-proxy.sh | sudo bash -s -- --ctid %s --pulse-server %s", ctid, baseURL)
resp["reinstallCommand"] = fmt.Sprintf("curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh | sudo bash -s -- --ctid %s --pulse-server %s", ctid, baseURL)
resp["installerURL"] = fmt.Sprintf("%s/api/install/install-sensor-proxy.sh", baseURL)
if err := utils.WriteJSONResponse(w, resp); err != nil {

View file

@ -28,7 +28,7 @@ type InstallShAdapter struct {
func NewInstallShAdapter(history *UpdateHistory) *InstallShAdapter {
return &InstallShAdapter{
history: history,
installScriptURL: "https://raw.githubusercontent.com/rcourtman/Pulse/main/install.sh",
installScriptURL: "https://github.com/rcourtman/Pulse/releases/latest/download/install.sh",
logDir: "/var/log/pulse",
}
}

View file

@ -390,15 +390,21 @@ if [ "${SKIP_HELM_PACKAGE:-0}" != "1" ]; then
fi
fi
# Copy install.sh to release directory (required for GitHub releases)
echo "Copying install.sh to release directory..."
# Copy install scripts to release directory (required for GitHub releases)
# These are uploaded as standalone assets so users can:
# curl -fsSL https://github.com/rcourtman/Pulse/releases/latest/download/install.sh | bash
# instead of pulling from main branch (which may have newer, incompatible changes)
echo "Copying install scripts to release directory..."
cp install.sh "$RELEASE_DIR/"
cp scripts/install-sensor-proxy.sh "$RELEASE_DIR/"
cp scripts/install-docker.sh "$RELEASE_DIR/"
cp scripts/pulse-auto-update.sh "$RELEASE_DIR/"
# Generate checksums (include tarballs, zip files, helm chart, and install.sh)
cd "$RELEASE_DIR"
shopt -s nullglob extglob
# Match all tarballs, zip files, and install.sh
checksum_files=( *.tar.gz *.zip install.sh )
# Match all tarballs, zip files, and install scripts
checksum_files=( *.tar.gz *.zip install.sh install-sensor-proxy.sh install-docker.sh pulse-auto-update.sh )
if compgen -G "pulse-*.tgz" > /dev/null; then
checksum_files+=( pulse-*.tgz )
fi

View file

@ -38,7 +38,8 @@ set_github_fallback_url() {
local base=""
if [[ "$ref" == "main" ]]; then
base="https://raw.githubusercontent.com/rcourtman/Pulse/${ref}/release/pulse-sensor-proxy-${PROXY_ARCH_LABEL}"
# Use latest release for main branch
base="https://github.com/rcourtman/Pulse/releases/latest/download/pulse-sensor-proxy-${PROXY_ARCH_LABEL}"
else
base="https://github.com/rcourtman/Pulse/releases/download/${ref}/pulse-sensor-proxy-${PROXY_ARCH_LABEL}"
fi
@ -323,13 +324,13 @@ download_installer_from_github() {
fi
fi
local raw_url="https://raw.githubusercontent.com/rcourtman/Pulse/${ref}/scripts/install-sensor-proxy.sh"
local release_url="https://github.com/rcourtman/Pulse/releases/latest/download/install-sensor-proxy.sh"
attempted=true
if curl --fail --silent --location --connect-timeout 5 --max-time 30 "$raw_url" -o "$destination" 2>/dev/null; then
if curl --fail --silent --location --connect-timeout 5 --max-time 30 "$release_url" -o "$destination" 2>/dev/null; then
chmod +x "$destination"
PROXY_INSTALLER_SOURCE_LABEL="github:${ref}"
set_github_fallback_url "$ref"
echo " ✓ Downloaded proxy installer from ${raw_url}"
PROXY_INSTALLER_SOURCE_LABEL="github:latest"
set_github_fallback_url "main"
echo " ✓ Downloaded proxy installer from ${release_url}"
return 0
fi

View file

@ -892,9 +892,11 @@ cache_installer_for_self_heal() {
local candidate_urls=()
if [[ "$ref" != "main" ]]; then
# Try specific version from releases first
candidate_urls+=("https://github.com/${repo}/releases/download/${ref}/install-sensor-proxy.sh")
fi
candidate_urls+=("https://raw.githubusercontent.com/${repo}/${ref}/scripts/install-sensor-proxy.sh")
# Fall back to latest release
candidate_urls+=("https://github.com/${repo}/releases/latest/download/install-sensor-proxy.sh")
local tmp_file
tmp_file=$(mktemp)

View file

@ -178,7 +178,7 @@ perform_update() {
fi
fi
if curl -sSL "https://raw.githubusercontent.com/$GITHUB_REPO/main/install.sh" | \
if curl -sSL "https://github.com/$GITHUB_REPO/releases/latest/download/install.sh" | \
bash -s -- "${installer_args[@]}" 2>&1 | \
while IFS= read -r line; do
log info "installer: $line"