Files
pulse/docs/DOCKER.md
rcourtman 3355f7a671 Read host Docker credentials for private registry update checks
Container update detection only ever negotiated anonymous pull tokens, so
containers from registries that reject anonymous digest HEADs pinned a
permanent "authentication required" badge (#1706). The agent already runs
on the Docker host, so the checker now resolves the same credential store
docker pull uses - config.json auths entries, credsStore/credHelpers
credential helpers (docker-credential-<name> get), and Podman's auth.json -
and presents the stored login: Basic auth on Bearer token negotiation and
on the hardcoded Docker Hub / ghcr.io token endpoints, direct answers to
Basic challenges, and the refresh-token grant for identity-token logins
such as Azure ACR.

Credentials never leave the host: they are only presented to the registry
or its token endpoint, helper output stays out of reported check errors,
and lookups are cached in memory for five minutes. Helper names are
validated before exec, and a stale login falls back to the anonymous path
so checks that used to work keep working. Set
PULSE_DISABLE_REGISTRY_CREDENTIALS=true (--disable-registry-credentials)
to keep detection anonymous-only. The agent-lifecycle and security-privacy
subsystem contracts pin the host-local credential boundary.
2026-08-13 10:06:26 +01:00

9.9 KiB

🐳 Docker Guide

Pulse is distributed as a lightweight, Alpine-based Docker image.

Paid Pulse Pro / Relay / legacy customers: The public rcourtman/pulse Docker image is the community build. It can accept an activation key, but it does not include the private Pulse Pro runtime hooks. Use https://pulserelay.pro/download.html with your activation key, then run the private registry login and PULSE_IMAGE=license.pulserelay.pro/pulse-pro:<version> compose commands shown there. Those commands require the compose file image line to use the PULSE_IMAGE variable, as shown below. If your compose file hardcodes image: rcourtman/pulse:..., replace that line with the variable form or with the private image shown on the download page before restarting.

🚀 Quick Start

docker run -d \
  --name pulse \
  -p 7655:7655 \
  -v pulse_data:/data \
  -e PULSE_DEPLOYMENT_METHOD=docker_run \
  --restart unless-stopped \
  rcourtman/pulse:vX.Y.Z

Access at http://<your-ip>:7655.


📦 Docker Compose

Create a docker-compose.yml file:

services:
  pulse:
    image: ${PULSE_IMAGE:-rcourtman/pulse:vX.Y.Z}
    container_name: pulse
    restart: unless-stopped
    ports:
      - "7655:7655"
    volumes:
      - pulse_data:/data
    environment:
      - TZ=Europe/London
      - PULSE_DEPLOYMENT_METHOD=docker_compose
      # Optional: Pre-configure auth (skips setup wizard)
      # - PULSE_AUTH_USER=admin
      # - PULSE_AUTH_PASS=secret123

volumes:
  pulse_data:

Run with: docker compose up -d

The PULSE_IMAGE variable lets the same compose file run either the public community image or, for eligible paid customers, the private Pulse Pro image shown on https://pulserelay.pro/download.html.


⚙️ Configuration

Pulse is configured via the UI (system.json) with optional environment overrides.

Variable Description Default
TZ Timezone UTC
PULSE_AUTH_USER Admin Username (unset)
PULSE_AUTH_PASS Admin Password (unset)
DISCOVERY_SUBNET Custom CIDR to scan (auto)
ALLOWED_ORIGINS CORS allowed origin (* or a single origin). Empty = same-origin only. (unset)
LOG_LEVEL Log verbosity (debug, info, warn, error) info
PULSE_DISABLE_DOCKER_UPDATE_ACTIONS Hide Docker update buttons (read-only mode) false
PULSE_METRICS_DB_PATH Optional path for only metrics.db, useful with tmpfs /data/metrics.db
PULSE_METRICS_ROLLUP_INTERVAL Metrics aggregation cadence; minimum 5 minutes 15m

Tip

: Set LOG_LEVEL=warn to reduce log volume while still capturing important events. Note: API tokens are managed in the UI and stored in api_tokens.json. Note: Plain text values in PULSE_AUTH_PASS are auto-hashed on startup.

For SSD-sensitive installs, keep /data persistent and put only metrics history on tmpfs:

services:
  pulse:
    environment:
      PULSE_METRICS_DB_PATH: /metrics-tmpfs/metrics.db
    tmpfs:
      - /metrics-tmpfs:size=512m,uid=1000,gid=1000,mode=0700

Metrics history stored this way is lost on container restart.

Advanced: Resource Limits & Healthcheck
services:
  pulse:
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 256M
    healthcheck:
      test: ["CMD", "wget", "--spider", "-q", "http://localhost:7655/api/health"]
      interval: 30s
      timeout: 10s
      retries: 3

🔄 Updates

To update Pulse to a specific release tag:

docker pull rcourtman/pulse:vX.Y.Z
docker stop pulse
docker rm pulse
# Re-run your docker run command

If using Compose:

docker compose pull
docker compose up -d

🔄 Docker / Podman Updates

Pulse can detect and apply updates to your Docker / Podman containers directly from the UI.

How It Works

  1. Update Detection: Pulse compares the local image digest with the latest digest from the container registry
  2. Visual Indicator: Containers with available updates show a blue upward arrow icon
  3. Reviewed Update: Click the update button, approve the reviewed action, and Pulse handles the rest

Updating a Container

  1. Navigate to the Workloads page (or filter by Docker sources on Infrastructure)
  2. Look for containers with a blue update arrow (⬆️)
  3. Click the update button and approve the action in the review dialog (admin approval required)
  4. Pulse will:
    • Pull the latest image
    • Stop the current container
    • Create a backup (renamed with _pulse_backup_ suffix)
    • Start a new container with the same configuration
    • Clean up the backup after 15 minutes (if the update succeeds)

Batch Updates

Updates run as reviewed per-container actions, so there is currently no bulk update flow: update each container individually with its own update button. The "Update all" button in the host drawer only points you to the per-container buttons.

Safety Features

  • Automatic Backup: The old container is renamed, not deleted, until the update succeeds
  • Rollback on Failure: If the new container fails to start, the old one is restored
  • Configuration Preserved: Networks, volumes, ports, environment variables are all preserved

Requirements

  • Unified agent running on the Docker host with Docker monitoring enabled
  • Command execution enabled on the agent (--enable-commands or PULSE_ENABLE_COMMANDS=true) — updates run as reviewed actions through the agent's command channel, the same as container lifecycle actions, and share their requirements and limitations (admin approval, authorization-plugin block)
  • Agent must have Docker socket access (/var/run/docker.sock)
  • Registry must be accessible for update detection (public registries work automatically)

Private Registries

For private registries, log in with Docker on the container host as the user the agent runs as (the installer's systemd service runs the agent as root, so use sudo docker login):

docker login registry.example.com

Pulling updates goes through the Docker daemon, which reads these credentials natively. Update detection reads the same credential store: config.json auths entries, configured credsStore/credHelpers credential helpers, and Podman's auth.json (REGISTRY_AUTH_FILE and DOCKER_CONFIG overrides are honored). The agent presents the stored login to the registry when it rejects anonymous digest checks, so private images get real update detection instead of a permanent failed check. Credentials never leave the host — they are only sent to the registry itself and are never reported to the Pulse server.

To keep update detection anonymous-only (no credential store reads, no credential helper execution), set PULSE_DISABLE_REGISTRY_CREDENTIALS=true (or pass --disable-registry-credentials) on the agent.

Paid Pulse Pro Docker installs use the private Pulse Pro registry rather than the public rcourtman/pulse image. Open https://pulserelay.pro/download.html, paste your activation key, run the Docker login command shown there, then run the shown PULSE_IMAGE=license.pulserelay.pro/pulse-pro:<version> docker compose pull and docker compose up -d commands from the host that already runs Pulse. If your compose file has a hardcoded image: rcourtman/pulse:... line, change it to image: ${PULSE_IMAGE:-rcourtman/pulse:vX.Y.Z} or directly to the private image shown on the download page before running those commands.

Disabling Update Features

Pulse provides granular control over update features via environment variables on the Pulse server:

Variable Description
PULSE_DISABLE_DOCKER_UPDATE_ACTIONS Hides update buttons from the UI while still detecting updates. Use this for "read-only" monitoring.

Example - Read-Only Mode (detect updates but prevent actions):

services:
  pulse:
    image: ${PULSE_IMAGE:-rcourtman/pulse:vX.Y.Z}
    environment:
      - PULSE_DISABLE_DOCKER_UPDATE_ACTIONS=true

To disable registry checks entirely, set PULSE_DISABLE_DOCKER_UPDATE_CHECKS=true on the agent.

You can also toggle "Hide Docker Update Buttons" from the UI in Settings → System → General under Docker / Podman updates.


▶️ Container Lifecycle Actions

Pulse can start, stop, and restart Docker / Podman containers directly from the UI. Running containers offer stop and restart; stopped containers offer start.

Requirements

  • Pulse Agent installed on the container host (see Unified Agent) and currently connected
  • Command execution enabled on the agent — it is disabled by default. Either:
    • start the agent with --enable-commands (or PULSE_ENABLE_COMMANDS=true), or
    • tick Enable Pulse command execution in Settings → Infrastructure before copying the install command, which adds the flag and grants the token the command execution permission
  • Admin approval: every lifecycle action requires confirmation by an admin in the UI before it runs. The agent then verifies the container's state before the change and confirms it actually reached the requested state afterwards.

Limitations

  • If the Docker daemon has authorization plugins configured, Pulse blocks all daemon-mutating commands on that host (see advisory GO-2026-4887) and the lifecycle buttons are not offered. Podman hosts are not affected.
  • Actions are unavailable while the host's Docker inventory is stale or the agent is disconnected.

🛠️ Troubleshooting

  • Forgot Password?

    docker exec pulse rm /data/.env
    docker restart pulse
    # Access UI again. Pulse will require a bootstrap token for setup.
    # Get it with:
    docker exec pulse /app/pulse bootstrap-token
    
  • Logs

    docker logs -f pulse
    
  • Shell Access

    docker exec -it pulse /bin/sh