Pulse 6.5.0
Overview
This guide shows how to launch and verify Pulse 6.5.0 on Ubuntu 24.04 from SecureAnyCloud on Amazon EC2. It is one version of the SecureAnyCloud Hardened Uptime Kuma, Gatus & Uptime and Status Pages AMIs listing on AWS Marketplace. You choose it as the software version when you subscribe and launch. The other products in the listing are described on the listing's guide hub.
Pulse is an open source monitoring server for home labs and infrastructure teams. Connect it to your Proxmox VE clusters, Proxmox Backup Server and Mail Gateway with an API token, or install the small Pulse agent on Docker, Podman, Kubernetes and plain Linux hosts. One dashboard then shows live CPU, memory, disk and network for every node, VM, container and storage pool, together with backup status, alert rules, and notifications by email, webhook or Apprise. TrueNAS SCALE and VMware vCenter (preview) are supported too.
The image runs Pulse 6.5.0, compiled by SecureAnyCloud from the official 6.5.0 source with Go 1.27.3 and updated golang.org/x/net and golang.org/x/crypto modules. The web interface is built from the same source with updated libraries. The upstream 6.5.0 release binary was built with Go 1.26.8 and golang.org/x/net 0.58.0, and govulncheck lists 14 known advisories against it. This build has none that govulncheck finds reachable. The build is reproducible, and its record ships with the image.
The base is a fully patched Ubuntu 24.04 LTS, and unattended security upgrades stay on for your instance.
What you get:
- Pulse 6.5.0 (
pulse.service) running as the unprivilegedpulseuser and listening on127.0.0.1:7655only. - nginx publishing Pulse over HTTPS on port 443 with a certificate created on your instance's first boot. Port 80 redirects to HTTPS.
- A local
adminaccount with a password unique to your instance, created on first boot. - An empty data directory,
/etc/pulse. No monitored systems, tokens or history ship with the image. Pulse creates its own encryption key there on its first start on your instance. pulse-set-hostname, a helper that serves Pulse under your own DNS name.- The build record (
BUILD-INFO.txt),go.mod,go.sum, the web interface's package lock, thegovulncheckandnpm auditresults, and the MIT licence in/usr/share/doc/pulse/. - Defaults: user
ubuntu, x86_64 architecture and an 8 GiB gp3 root volume.
Security posture
- No open dashboard. A fresh Pulse install with no account accepts anonymous requests from the machine itself and offers a setup wizard. This image never runs Pulse without an account. A check before every start refuses to launch Pulse until first boot has created the
adminaccount. The first-run setup wizard is closed, so nobody else can claim your instance. - Per-instance password. The
adminpassword is generated on each instance's first boot. Pulse's configuration (/etc/pulse/.env, readable only by thepulseaccount) holds only its bcrypt hash. The plain text is written to/root/pulse-credentials.txt(mode 0600, root only). No password or hash ships in the image. - Per-instance encryption key. Pulse encrypts the Proxmox, Backup Server, TrueNAS and vSphere credentials you add with an AES-256 key in
/etc/pulse/.encryption.key. The image ships no key. Pulse creates it on its first start on your instance, so no two instances share one. - Loopback only. Pulse listens on
127.0.0.1only. nginx on 443 is the only way in. - HTTPS on first boot. nginx serves Pulse with a TLS key and self-signed certificate created on your instance, using TLS 1.2 and 1.3 only. Port 80 only redirects to HTTPS. Pulse adds its own content security policy, HSTS and frame-blocking headers.
- Fixed host name. Pulse is served under a name taken from the instance metadata at first boot, or one that you set, and never from the request. Requests for any other host name are dropped. Cross-site form posts and WebSocket connections are refused, both by nginx and by Pulse's own origin check.
- Real client addresses. nginx passes the connecting address to Pulse and ignores any
X-Forwarded-Forheader that a client sends. Pulse's login lockout (5 failed attempts) and its logs therefore see who really connected. - Local recovery stays local. Pulse's account-recovery endpoint is refused through nginx. It works only from a shell on the instance.
- No telemetry, no update checks. Pulse's outbound usage telemetry, which is on by default upstream, is turned off. The hourly update check against GitHub is off, and network discovery does not scan your VPC unless you turn it on.
- No metadata access. Pulse connects to whatever Proxmox, webhook and AI provider addresses you enter. For that reason,
pulse.serviceandnginx.serviceare blocked from reaching the instance metadata service (169.254.169.254 and fd00:ec2::254). Amazon Time Sync keeps working. - Least privilege.
pulse.serviceruns with no Linux capabilities, a read-only system (ProtectSystem=strict) except/etc/pulse, and its own private/tmp. Pulse's ping checks use unprivileged ICMP sockets, which the image allows for thepulsegroup only. - No scheduled firmware-metadata refresh. The
fwupdfirmware updater stays installed, but its LVFS metadata refresh (fwupd-refresh.timerand.service) is masked. An LVFS outage therefore never marks your instance unhealthy at boot. If you use fwupd, runsudo fwupdmgr refreshyourself. - IMDSv2 required. The AMI is registered with
ImdsSupport v2.0, so instances launched from it refuse token-less (IMDSv1) metadata requests. - Per-instance identity. SSH host keys and the machine ID are generated fresh on every instance.
Known advisory in a bundled library
govulncheck reports no vulnerability reachable from Pulse. It lists one advisory at module level only, GO-2026-5932. The golang.org/x/crypto/openpgp package is deprecated, the Go team describes it as unsafe by design, and it has no fixed version. That package is not compiled into Pulse. It is only part of the golang.org/x/crypto module that Pulse uses for bcrypt and SSH, and the build fails if the package is ever linked.
The binary also contains one private-key block that is not a secret. It is the public test key that the crewjam/saml library (used for SAML sign-in) ships for its fuzz tests. It is the same in every build of that library, including upstream's release binaries, and Pulse never uses it.
The full output ships in /usr/share/doc/pulse/govulncheck-binary.txt and govulncheck-source.txt. The web interface's npm audit --omit=dev result (0 vulnerabilities) is in npm-audit-production.txt.
Community edition
This is the MIT-licensed community Pulse server. Pulse also has paid Relay, Pro and Cloud plans, which its developer sells. This build cannot activate them because it carries no licence verification key, and none of their features are part of this image.
Everything in the community edition works: monitoring, alerts and notifications, the API, the agents, and Patrol with your own AI provider.
Prerequisites
- An AWS account and permission to launch EC2 instances.
- An EC2 key pair in the Region you launch in.
- A subnet that gives the instance a public IPv4 address, or private connectivity from where you will use the dashboard.
- Network access from the instance to the Proxmox, Backup Server or agent hosts you want to monitor, for example a VPN or AWS Direct Connect link to your data centre.
- Recommended instance type:
m5.large. Pulse is a single Go process with SQLite storage, and a smaller burstable type also works for a few nodes.
Connecting to your instance
Pulse 6.5.0 on Ubuntu 24.04 runs on Ubuntu 24.04 LTS. Connect over SSH as the user ubuntu.
Launch the instance
Option A: AWS Marketplace console
- Open the SecureAnyCloud Hardened Uptime Kuma, Gatus & Uptime and Status Pages AMIs listing on AWS Marketplace. Choose View purchase options, then Subscribe. One subscription covers every version in the listing.
- When the subscription is active, choose Launch your software.
- Choose One-click launch from AWS Marketplace, or Launch from EC2 Console for the full launch wizard. In Version, choose Pulse 6.5.0 on Ubuntu 24.04, then choose your Region.
- Pick an instance type and your key pair.
m5.largeis recommended, and the software charge is $0.04 per vCPU per hour. - Set the security group. The listing's default group allows SSH (22), HTTP (80) and HTTPS (443). Restrict SSH to your own IP address, and restrict 80 and 443 to the people who need the dashboard.
- Choose your VPC and a subnet that gives the instance a public IP. Leave the metadata defaults, because the image already requires IMDSv2. Then choose Launch.
Option B: AWS CLI
Run these commands on your own workstation. They create a security group that allows SSH and the dashboard from your management address only, then launch the instance. Replace the AMI ID with the one shown for your Region on the Marketplace launch page. Replace the VPC, subnet, key pair and CIDR with your own.
SG=$(aws ec2 create-security-group --group-name pulse \
--description "Pulse" --vpc-id vpc-0123456789abcdef0 \
--query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 22 --cidr <your-mgmt-cidr>
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 443 --cidr <your-mgmt-cidr>
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 80 --cidr <your-mgmt-cidr>
aws ec2 run-instances \
--image-id ami-0123456789abcdef0 \
--instance-type m5.large \
--key-name my-key-pair \
--security-group-ids "$SG" \
--subnet-id subnet-0123456789abcdef0 \
--associate-public-ip-address \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=pulse}]'You do not need --metadata-options, because the AMI already requires IMDSv2.
Connect and read your login
Connect as ubuntu with the key pair you chose:
ssh -i ~/.ssh/my-key-pair.pem ubuntu@<public-ip>First boot finishes within a minute of launch. It creates the HTTPS certificate and the admin password, then starts Pulse and nginx. Your login is in a file that only root can read:
sudo cat /root/pulse-credentials.txt# Pulse - generated on first boot by pulse-firstboot.service
# These credentials are unique to this instance. Store them somewhere safe. PULSE_URL=https://ec2-18-212-195-121.compute-1.amazonaws.com/ PULSE_USERNAME=admin PULSE_PASSWORD=<PULSE_PASSWORD>
#
# Open PULSE_URL in a browser (self-signed certificate minted on this instance's first boot; port 80 redirects to # https) and sign in with the username and password above. Then add your Proxmox VE / Backup Server nodes (API # token), or install the Pulse agent on your Docker, Kubernetes or Linux hosts, from Settings. # Change the name it is served as:
sudo pulse-set-hostname <your-dns-name>
# Restrict 80/443 in the security group to the people who need the dashboard.
# Full deployment guide: https://secureanycloud.com/stacks/pulse-6-5-0/PULSE_PASSWORD holds your instance's own password.
Confirm the services are running
Check that the first boot service, Pulse and nginx are active, that Pulse runs as the unprivileged pulse user, and that its health endpoint reports healthy:
systemctl is-active pulse-firstboot.service pulse.service nginx.service ps -o user= -C pulse curl -sk https://localhost/api/health | jq -e '.status == "healthy"'active active active pulse true/api/health needs no login, so you can use it for a load balancer health check over HTTPS. Everything else needs a signed-in session.
List the ports that the instance listens on. These are the only ones.
sudo ss -Hltnu | awk '{print $1, $5}' | sort -utcp 0.0.0.0:22 tcp 0.0.0.0:443 tcp 0.0.0.0:80 tcp 127.0.0.1:7655 tcp 127.0.0.1:9091 tcp 127.0.0.53%lo:53 tcp 127.0.0.54:53 tcp [::]:22 tcp [::]:443 tcp [::]:80 udp 127.0.0.1:323 udp 127.0.0.53%lo:53 udp 127.0.0.54:53 udp 172.31.83.107%ens5:68 udp [::1]:323Pulse (7655) and its Prometheus metrics endpoint (9091) listen on loopback only, and nginx publishes Pulse on 443. The loopback port 53 entries are Ubuntu's local stub resolver (systemd-resolved). Port 323 is chrony's local control socket, and port 68 is the DHCP client.
The binary is the reproducible SecureAnyCloud build of the 6.5.0 source. It is the only program in /opt/pulse/bin, and no agent binaries ship. Its record ships with the image:
sha256sum /opt/pulse/bin/pulse grep -E '^(source|binary|govulncheck) ' /usr/share/doc/pulse/BUILD-INFO.txt ls /opt/pulse/binc8255cc44aa5f26536fd9e829cd724678055dee0675bb253701d9f1e6ac2bbfb /opt/pulse/bin/pulse source https://github.com/rcourtman/Pulse/archive/refs/tags/v6.5.0.tar.gz source sha256 e5473d7d447825946154101220ad6e74f55eec0abb52dfe52cacfbe6fd500c58 (tag commit 38c981a397c7a37f469b619200b5035bfc60b328) binary sha256 c8255cc44aa5f26536fd9e829cd724678055dee0675bb253701d9f1e6ac2bbfb (reproducible) govulncheck v1.9.0 -mode=binary and source mode: 0 reachable vulnerabilities (DB updated: 2026-10-21 00:27:29 +0000 UTC) pulseSign in to Pulse
Browse to the PULSE_URL from Step 2, for example https://ec2-18-212-195-121.compute-1.amazonaws.com/. The certificate is self-signed, so your browser warns once. Accept it, or install your own certificate (Step 7). Pulse shows its sign-in page.
Sign in as admin with the password from Step 2. On a new instance, Pulse opens Settings > Infrastructure, where you add the systems to monitor (Step 5).
Port 80 only redirects to the HTTPS address:
curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' http://localhost/301 https://ec2-18-212-195-121.compute-1.amazonaws.com/You can also check the login from the command line. These requests go to nginx on the instance itself. The monitoring state needs a session, a wrong password is refused, and the instance's own password signs in and reads the state. The password is read from the credentials file and passed to curl on standard input, never on the command line. The block stops with an error if any answer is not the expected one.
H=$(sudo sed -n 's/^set $pulse_host "\(.*\)";$/\1/p' /etc/nginx/pulse-host.conf) PW() {
sudo sed -n 's/^PULSE_PASSWORD=//p' /root/pulse-credentials.txt; }
J=$(mktemp); trap 'rm -f "$J"' EXIT
U=$(curl -sk --resolve "$H:443:127.0.0.1" -o /dev/null -w '%{http_code}' "https://$H/api/state")
W=$(printf '{"username":"admin","password":"not-the-password"}' | curl -sk --resolve "$H:443:127.0.0.1" -o /dev/null -w '%{http_code}' \
-H 'Content-Type: application/json' -H "Origin: https://$H" --data-binary @- "https://$H/api/login")
A=$(printf '{"username":"admin","password":"%s"}' "$(PW)" | curl -sk --resolve "$H:443:127.0.0.1" -c "$J" -o /dev/null -w '%{http_code}' \
-H 'Content-Type: application/json' -H "Origin: https://$H" --data-binary @- "https://$H/api/login")
S=$(curl -sk --resolve "$H:443:127.0.0.1" -b "$J" -o /dev/null -w '%{http_code}' "https://$H/api/state")
echo "no session : $U";
echo "wrong password : $W";
echo "admin login : $A";
echo "with session : $S" [ "$U" = 401 ] && [ "$W" = 401 ] && [ "$A" = 200 ] && [ "$S" = 200 ]no session : 401 wrong password : 401 admin login : 200 with session : 200Pulse locks an account, and the address it is used from, for 15 minutes after 5 failed sign-ins. Avoid mistyping the password repeatedly.
The first-run setup is closed. An anonymous request to set up an account is refused, no setup token exists, and the account-recovery endpoint is refused through nginx. Pulse itself reports that authentication is required:
H=$(sudo sed -n 's/^set $pulse_host "\(.*\)";$/\1/p' /etc/nginx/pulse-host.conf)
QS=$(curl -sk --resolve "$H:443:127.0.0.1" -o /dev/null -w '%{http_code}' -X POST -H 'Content-Type: application/json' -H "Origin: https://$H" \
--data '{"username":"someone","password":"Someone-Else-123"}' "https://$H/api/security/quick-setup")
BT=$(curl -sk --resolve "$H:443:127.0.0.1" -o /dev/null -w '%{http_code}' -X POST -H "Origin: https://$H" "https://$H/api/security/validate-bootstrap-token")
RC=$(curl -sk --resolve "$H:443:127.0.0.1" -o /dev/null -w '%{http_code}' -X POST -H "Origin: https://$H" --data '{"action":"disable_auth"}' "https://$H/api/security/recovery")
curl -sk --resolve "$H:443:127.0.0.1" "https://$H/api/security/status" | jq -c '{hasAuthentication, requiresAuth}' echo "anonymous setup : $QS"; echo "bootstrap token : $BT"; echo "remote recovery : $RC" [ "$QS" = 401 ] && [ "$BT" = 409 ] && [ "$RC" = 403 ]{"hasAuthentication":true,"requiresAuth":true} anonymous setup : 401 bootstrap token : 409 remote recovery : 403Add your infrastructure
In Settings > Infrastructure, choose Add infrastructure. You can paste a hostname or URL and let Pulse detect the platform, install the Pulse agent on a host, or pick a source type. The source types are Proxmox VE, TrueNAS SCALE and Unraid. Under Show 5 more sources, you will find further types such as Proxmox Backup Server, Proxmox Mail Gateway and VMware vCenter (preview).
Pulse connects out from this instance, so it needs a network path to each system. Use a VPN, AWS Direct Connect, or systems that run in AWS.
Proxmox VE, Backup Server and Mail Gateway are monitored through their API. In the Proxmox VE form, enter a node name and the endpoint URL (for example https://<your-proxmox-host>:8006) and keep API Token (Recommended).
- Connect via API shows one command to run on the Proxmox VE server. The command creates the monitoring user
pulse-monitor@pvewith an API token and read-only permissions (PVEAuditor, guest agent access and backup visibility), and registers the node with Pulse. The Proxmox server must be able to reach this instance on port 443 for this to work. - Manual Token Setup is the alternative when it cannot. Create the user and token yourself on the Proxmox node, then paste the token ID and secret into the form:
pveum user add pulse-monitor@pve pveum aclmod / -user pulse-monitor@pve -role PVEAuditor pveum user token add pulse-monitor@pve pulse --privsep 0If your Proxmox node uses its default self-signed certificate, go to SSL settings and either turn off Verify SSL certificate or enter the node's certificate fingerprint. Pulse stores the token secret encrypted with your instance's own key.
Docker, Podman, Kubernetes and Linux, macOS, Windows or Unraid hosts are monitored by the Pulse agent. Choose Install Pulse Agent and run the installer command that Pulse shows on that host. The installer comes from this instance, with its upstream OpenSSH signature (/opt/pulse/scripts/install.sh.sshsig). The agent binary is the official signed 6.5.0 release, which Pulse fetches from GitHub for you.
Agents connect to Pulse on port 443 at the PULSE_PUBLIC_URL (Step 7), so allow 443 from those hosts in the security group. Install your own certificate (Step 7) before you install agents, so that they can trust it.
You can check this chain from the instance itself. The installer that Pulse serves carries upstream's OpenSSH signature in an X-Signature-SSHSIG header. The installer and the agent verify it against the signing key pinned in the script, using the same ssh-keygen -Y verify check that they run. The agent binary that Pulse fetches for a host arrives with a matching checksum and both of upstream's signatures:
H=$(sudo sed -n 's/^set $pulse_host "\(.*\)";$/\1/p' /etc/nginx/pulse-host.conf)
T=$(mktemp -d); trap 'rm -rf "$T"' EXIT
KEY=$(sed -n 's/^PINNED_INSTALLER_SSH_PUBLIC_KEY="\(ssh-ed25519 [A-Za-z0-9+/=]*\)[ "].*/\1/p' /opt/pulse/scripts/install.sh) printf 'pulse-installer %s\n' "$KEY" > "$T/allowed_signers" curl -sk --resolve "$H:443:127.0.0.1" -D "$T/h" -o "$T/install.sh" "https://$H/install.sh" tr -d '\r' < "$T/h" | sed -n 's/^[Xx]-[Ss]ignature-[Ss][Ss][Hh][Ss][Ii][Gg]: //p' | base64 -d > "$T/install.sh.sshsig" ssh-keygen -Y verify -f "$T/allowed_signers" -I pulse-installer -n pulse-install -s "$T/install.sh.sshsig" < "$T/install.sh" && V=ok curl -sk --resolve "$H:443:127.0.0.1" -D "$T/a" -o "$T/agent" "https://$H/download/pulse-agent?arch=linux-amd64"
CS=$(tr -d '\r' < "$T/a" | sed -n 's/^[Xx]-[Cc]hecksum-[Ss]ha256: //p') [ "$CS" = "$(sha256sum "$T/agent" | cut -d' ' -f1)" ] && echo "agent download: checksum matches"
SIGS=$(tr -d '\r' < "$T/a" | grep -ioE '^x-signature-(ed25519|sshsig)' | tr 'A-Z' 'a-z' | sort)
echo "$SIGS" [ "${V:-}" = ok ] && [ "$CS" = "$(sha256sum "$T/agent" | cut -d' ' -f1)" ] && [ "$(echo "$SIGS" | wc -l)" = 2 ]Good "pulse-install" signature for pulse-installer with ED25519 key SHA256:WjzDnbyb4fF3hPGRE1ZLtYcXzLimGpJq6Ou4opquTV0 agent download: checksum matches x-signature-ed25519 x-signature-sshsigAlerts and notifications: set alert thresholds under Alerts. Email, webhook and Apprise destinations are in the alert settings. Webhooks to private addresses are blocked unless you allow them.
Read the monitoring state from the API
Everything in the dashboard comes from Pulse's REST API. With a session, or an API token from Settings > API Access, you can read it from scripts. On a new instance no systems are configured, so the node list is empty and there are no alerts:
H=$(sudo sed -n 's/^set $pulse_host "\(.*\)";$/\1/p' /etc/nginx/pulse-host.conf) PW() {
sudo sed -n 's/^PULSE_PASSWORD=//p' /root/pulse-credentials.txt; }
J=$(mktemp); trap 'rm -f "$J"' EXIT printf '{"username":"admin","password":"%s"}' "$(PW)" | curl -sk --resolve "$H:443:127.0.0.1" -c "$J" -o /dev/null \
-H 'Content-Type: application/json' -H "Origin: https://$H" --data-binary @- "https://$H/api/login" curl -sk --resolve "$H:443:127.0.0.1" -b "$J" "https://$H/api/config/nodes" | jq -c '{configured_nodes: length}' curl -sk --resolve "$H:443:127.0.0.1" -b "$J" "https://$H/api/state" | jq -e -c '{active_alerts: (.activeAlerts | length)}' curl -sk --resolve "$H:443:127.0.0.1" -b "$J" "https://$H/api/version" | jq -e -c '{version}'{"configured_nodes":0} {"active_alerts":0} {"version":"6.5.0"}HTTPS certificate and host name
The certificate was created on your instance's first boot for the instance's public DNS name, public IP, private IP and localhost. The key, Pulse's configuration and encryption key, and the credentials file are readable only by their owners. The configuration holds the password only as a bcrypt hash.
sudo openssl x509 -in /etc/ssl/pulse/pulse.crt -noout -subject -dates -ext subjectAltName
sudo stat -c '%a %U:%G %n' /etc/ssl/pulse/pulse.key /etc/ssl/pulse/pulse.crt /etc/pulse/.env /etc/pulse/.encryption.key /root/pulse-credentials.txt
sudo sed -E -n "s/^(PULSE_AUTH_USER=.*)/\1/p; s/^(PULSE_AUTH_PASS=')(.{7}).*/\1\2.../p" /etc/pulse/.env cat /etc/sac/pulse-host.envsubject=CN = ec2-18-212-195-121.compute-1.amazonaws.com, O = sac notBefore=Oct 21 17:40:29 2026 GMT notAfter=Jan 23 17:40:29 2029 GMT X509v3 Subject Alternative Name: DNS:ec2-18-212-195-121.compute-1.amazonaws.com, IP Address:18.212.195.121, IP Address:172.31.83.107, IP Address:127.0.0.1, DNS:localhost 600 root:root /etc/ssl/pulse/pulse.key 644 root:root /etc/ssl/pulse/pulse.crt 600 pulse:pulse /etc/pulse/.env 600 pulse:pulse /etc/pulse/.encryption.key 600 root:root /root/pulse-credentials.txt PULSE_AUTH_USER='admin' PULSE_AUTH_PASS='$2y$12$... PULSE_PUBLIC_URL=https://ec2-18-212-195-121.compute-1.amazonaws.com/ ALLOWED_ORIGINS=https://ec2-18-212-195-121.compute-1.amazonaws.com,https://18.212.195.121,https://172.31.83.107,https://127.0.0.1,https://localhostPULSE_PUBLIC_URL is the address that Pulse puts in agent install commands and notification links. To serve Pulse under your own DNS name, for example pulse.example.com pointed at this instance, run the helper. The helper records the name and creates a new self-signed certificate for it. It also updates nginx and Pulse's public URL, restarts Pulse and rewrites the URL in the credentials file.
sudo pulse-set-hostname pulse.example.comIf the instance's public address changes after a stop and start, run the helper again so that the certificate names the new address too. To use a certificate from your own certificate authority, replace /etc/ssl/pulse/pulse.key (keep it 0600 root) and /etc/ssl/pulse/pulse.crt, then run sudo systemctl reload nginx.
Telemetry, updates and metadata
Pulse's environment turns off outbound telemetry and network discovery, binds Pulse to loopback, and trusts forwarded headers from the local nginx only. A marker file turns off the update check. Pulse's log confirms this, including that no paid-plan licence can be activated on this build:
systemctl show -p Environment pulse.service | tr ' ' '\n' | grep -E '^(BIND_ADDRESS|PULSE_TELEMETRY|PULSE_TRUSTED_PROXY_CIDRS|DISCOVERY_ENABLED)='
sudo journalctl -u pulse.service -o cat --no-pager | grep -oE '"message":"(Outbound usage telemetry is disabled|discovery service disabled by configuration|no license public key configured)' | sort -u head -1 /opt/pulse/BUILD_FROM_SOURCEBIND_ADDRESS=127.0.0.1 PULSE_TRUSTED_PROXY_CIDRS=127.0.0.1/32 PULSE_TELEMETRY=false DISCOVERY_ENABLED=false "message":"Outbound usage telemetry is disabled "message":"discovery service disabled by configuration "message":"no license public key configured sac source build of Pulse v6.5.0 (see /usr/share/doc/pulse/BUILD-INFO.txt).pulse.service and nginx.service carry a systemd IPAddressDeny rule for the instance metadata addresses, so no Proxmox address, webhook or AI provider URL entered in Pulse can reach the metadata service. Each entry is a single address, so the Amazon Time Sync Service at 169.254.169.123 keeps working, as chrony shows. Pulse also runs with no capabilities.
systemctl show -p IPAddressDeny pulse.service nginx.service chronyc -n sources | grep 169.254 grep CapEff /proc/$(systemctl show -p MainPID --value pulse.service)/statusIPAddressDeny=168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128 IPAddressDeny=168.63.129.16/32 169.254.169.254/32 fd00:ec2::254/128 ^* 169.254.169.123 3 4 377 16 +17us[ +19us] +/- 614us CapEff: 0000000000000000Maintenance
- Password: change the
adminpassword in Settings > Authentication. Pulse stores the new bcrypt hash in/etc/pulse/.env. Then update/root/pulse-credentials.txt, or delete it. Single sign-on (OIDC) is available in Settings > Single Sign-On. - Locked out: if you lose the password, use Pulse's recovery endpoint. It works from a shell on the instance only. See
curl -s http://127.0.0.1:7655/api/security/recoveryand the Pulse recovery documentation. - Backups: everything Pulse knows lives in
/etc/pulse, including the encryption key that protects your stored credentials. Back up the whole directory with Pulse stopped (sudo systemctl stop pulse). Keep the backup as safe as the credentials themselves, because without the key the stored node credentials cannot be decrypted. - Upgrades: this build does not update itself. To move to a newer Pulse release, launch the newer version from the listing when it is published, and restore your
/etc/pulsebackup. - Telemetry: to send Pulse's anonymous usage data to its developer, set
PULSE_TELEMETRY=truewithsudo systemctl edit pulseand restart Pulse. The image keeps telemetry off. - Security patches: unattended-upgrades stays enabled, so the OS keeps receiving security updates.
Security recommendations
- Keep the security group tight. Open port 22 only to your management address, and ports 80 and 443 only to the people and agent hosts that need the dashboard.
- Use read-only tokens. Give Pulse a Proxmox token with
PVEAuditorunless you want it to act on your systems. - Use your own certificate if other people sign in, or before you install agents, so that browsers and agents trust it without exceptions.
- Keep Pulse on loopback. Leave
BIND_ADDRESS=127.0.0.1and reach Pulse through nginx. nginx keeps forwarded headers honest and the recovery endpoint local.
Support and licensing
Pulse is developed by Richard Courtman (Pulse Monitoring Ltd) and contributors and distributed under the MIT License. This image ships a binary that SecureAnyCloud compiled from the unmodified 6.5.0 source with Go 1.27.3, updated Go modules and updated web interface libraries. The build record and licence are in /usr/share/doc/pulse/. SecureAnyCloud provides the packaging, the hardening, first-boot HTTPS, per-instance credentials and 24/7 support. Pulse's paid plans are sold separately by its developer and are not part of this image.
SecureAnyCloud is not affiliated with, or endorsed by, the Pulse project or Pulse Monitoring Ltd. Product names are marks of their owners and are used here only to identify the software.
For help with deployment or configuration, email sales@secureanycloud.com or visit SecureAnyCloud support.
Deploy on AWS
Launch Pulse 6.5.0 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com