Skip to content

Getting Started

This walks through the fastest path to seeing Salesforce events in Loki: one Salesforce org, one Pub/Sub topic, client_credentials auth (no keypair to generate), running the published container. See Installation for other install methods and Configuration for everything this skips.

Prerequisites

  • A Salesforce External Client App with the Client Credentials Flow enabled, a Consumer Key
  • Secret, and a Run As user with View Real-Time Event Monitoring Data + API Enabled permissions. See the README's Salesforce setup walkthrough if you haven't created one yet.
  • A Grafana Cloud stack (or any Loki-compatible endpoint) and its push URL, tenant ID, and an access-policy token with the logs:write scope.
  • Docker and Docker Compose.

1. Write a minimal config

config.yaml
salesforce:
  # client_credentials needs your My Domain URL explicitly — the generic
  # login.salesforce.com / test.salesforce.com hosts reject this flow.
  login_url: https://yourorg.my.salesforce.com
  auth_mode: client_credentials
  client_id: ${SF_CLIENT_ID}
  client_secret_file: /etc/sf2loki/secrets/client-secret

sources:
  pubsub:
    topics: ["/event/LoginEventStream"]

sink:
  loki:
    url: ${GC_LOKI}
    tenant_id: ${GC_TENANT_ID}
    auth_token_file: /etc/sf2loki/secrets/loki-token

Everything else (batching, structured metadata, HA, telemetry) has a working default — see the full config reference for every key.

${VAR} placeholders

${SF_CLIENT_ID}, ${GC_LOKI}, and ${GC_TENANT_ID} are interpolated from the environment at load time; a missing variable is fatal at startup, not a silent blank.

2. Provide secrets and run it

docker-compose.yml
services:
  sf2loki:
    image: ghcr.io/rknightion/sf2loki:latest
    environment:
      SF_CLIENT_ID: "your-consumer-key"
      GC_LOKI: "https://logs-prod-<zone>.grafana.net/loki/api/v1/push"
      GC_TENANT_ID: "your-loki-tenant-id"
    volumes:
      - ./config.yaml:/etc/sf2loki/config.yaml:ro
      - ./secrets:/etc/sf2loki/secrets:ro
      - ./state:/var/lib/sf2loki
    ports:
      - "127.0.0.1:8080:8080"
    command: ["--config", "/etc/sf2loki/config.yaml"]
mkdir -p secrets state
echo -n "your-consumer-secret" > secrets/client-secret
echo -n "your-grafana-cloud-token" > secrets/loki-token
chmod 640 secrets/*          # the container runs as uid 10001; root-owned 0600 files crash-loop it
mkdir -p state && chmod 770 state && chown 10001 state

docker compose up -d

Validate before you run it

docker compose run --rm sf2loki --config /etc/sf2loki/config.yaml --check validates secrets, the label allowlist, and source-overlap rules without touching the network — a fast way to catch a typo before the container starts polling Salesforce.

3. Confirm ingestion

Every stream sf2loki writes carries job="sf2loki" and service_name="sf2loki". In Grafana Explore (or logcli), run:

{service_name="sf2loki"} | json

You should see LoginEventStream rows arriving within a few seconds of a login on the org. If nothing shows up, check docker compose logs -f sf2loki and run doctor for a live preflight (auth, topic reachability, a one-line Loki test write):

docker compose run --rm sf2loki doctor --config /etc/sf2loki/config.yaml

Next steps

  • Configuration — every setting, config loading precedence, and secret sourcing.
  • Sources — add SOQL-polled objects, EventLogFile, ApexLog, or your own custom platform events / Change Data Capture channels.
  • Deployment — production Docker/Kubernetes deployment, HA, and checkpoint stores.