Tutorial
Get started on Azure Database for PostgreSQL
Follow this guided path to take an Azure Database for PostgreSQL Flexible Server from nothing to a first Elevarq Signals snapshot. It assumes you know Azure but not PostgreSQL internals — the only database step is pasting a short block of SQL — and it ends with a working snapshot on your host. This guide uses the simple password method; passwordless Microsoft Entra auth is referenced at the end.
Topology
Signals connects to your Flexible Server like any database client, so it has to sit on a network path that reaches the server:
- Recommended: run Signals on a VM, VMSS, or AKS in the same VNet as the server when it uses private access (VNet integration).
- Public access works too — add a server firewall rulethat allows the Signals host's public IP to reach the server on TCP
5432. - Point Signals at the server endpoint (e.g.
myserver.postgres.database.azure.com) on port5432. That endpoint hostname is not the database name — the database name is the logical DB inside it (oftenpostgresor your application's database).
Prerequisites
- A Flexible Server running PostgreSQL 14+: its endpoint, port (
5432), database name, and the admin (server administrator) username. - The admin username and its password.
- Network reach from where Signals will run to that endpoint — confirm with
psqlfirst (step 1). docker(this guide) or the host binaries.- The Azure root CA, for
verify-fullTLS (downloaded in step 1).
1. Confirm you can reach the database
Download the root CA that Microsoft documents for Flexible Server — currently the DigiCert Global Root G2 and Microsoft RSA Root CA 2017certificates. Use the download links in Microsoft's Networking and TLS documentation and save the certificate as signals-data/azure-ca.pem. Then connect as the admin user over verify-full TLS. If this fails, fix networking or TLS before going further:
mkdir -p signals-data
# Download the Flexible Server root CA documented by Microsoft
# (DigiCert Global Root G2 / Microsoft RSA Root CA 2017) and save it as:
# signals-data/azure-ca.pem
psql "host=<server-name>.postgres.database.azure.com port=5432 dbname=<dbname> \
user=<admin-user> sslmode=verify-full \
sslrootcert=signals-data/azure-ca.pem"2. Create the read-only Signals role
Run this once per server, connected as the admin user to the database you want to observe. The Signals role is a plain LOGIN role granted pg_monitor — read-only, least-privilege:
-- as the admin user, connected to <dbname>:
CREATE ROLE signals LOGIN PASSWORD '<choose-a-strong-password>'
NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS;
GRANT pg_monitor TO signals;
GRANT CONNECT ON DATABASE <dbname> TO signals;Verify the role by connecting as signals in a fresh session, using the same host and TLS settings:
psql "host=<server-name>.postgres.database.azure.com port=5432 dbname=<dbname> \
user=signals sslmode=verify-full \
sslrootcert=signals-data/azure-ca.pem"Then, in that session:
SELECT count(*) FROM pg_stat_database; -- succeeds: read access
CREATE TABLE _signals_check (id int); -- fails: permission denied3. (Optional) Enable query statistics
pg_stat_statements adds query-level statistics. It is optional — Signals collects everything else without it. On Flexible Server you do not edit postgresql.conf; instead use Server parameters in the Azure portal or CLI:
- Add
pg_stat_statementsto theshared_preload_librariesserver parameter, and ensure it is on theazure.extensionsallow-list. - Restart the server if Azure marks the change as requiring a restart.
- Then, connected to the database, run
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
See Azure's PostgreSQL extensions documentation for the allow-list details.
4. Write the config and an API token
# API token shared by the daemon and signalsctl:
openssl rand -hex 32 > signals-data/api-token
cat > signals.yaml <<'YAML'
signals:
poll_interval: 6h
retention_days: 30
api:
listen_addr: 0.0.0.0:8081 # bind inside the container; -p limits exposure to loopback
database:
path: /data/signals.db
targets:
- name: primary
host: <server-name>.postgres.database.azure.com
port: 5432
dbname: <dbname>
user: signals
sslmode: verify-full
sslrootcert_file: /data/azure-ca.pem
password_env: SIGNALS_PRIMARY_PASSWORD
YAMLpassword_env) keeps the first run simple. For production, store the secret in Azure Key Vault (auth_method: secret_store), or go passwordless with Microsoft Entra (azure_entra). See Authentication methods for all options.5. Run the container
Bind-mount ./signals-data to /data so the SQLite store, the CA certificate, the token, and any exports all live in a directory you can see on the host:
docker run -d --name signals \
-v "$PWD/signals.yaml:/etc/signals/signals.yaml:ro" \
-v "$PWD/signals-data:/data" \
-e SIGNALS_API_TOKEN="$(cat signals-data/api-token)" \
-e SIGNALS_PRIMARY_PASSWORD="<the-password-from-step-2>" \
-p 127.0.0.1:8081:8081 \
ghcr.io/elevarq/signals:<version><version> with a release tag from the Signals releases page and pin it (e.g. v1.2.0) for anything beyond a trial. ghcr.io/elevarq/signals:latest tracks the newest release and is fine for a quick evaluation.0.0.0.0:8081 inside the container so the published port works, while -p 127.0.0.1:8081:8081restricts exposure to your host's loopback — reachable from this host and via docker exec, never from the network.6. Verify, collect, export
Drive the running daemon with signalsctl inside the container — it inherits SIGNALS_API_TOKEN, so it authenticates to the local API automatically:
docker exec signals signalsctl status
docker exec signals signalsctl connect test primary
docker exec signals signalsctl collect now
docker exec signals signalsctl export --output /data/snapshot.zipBecause /data is the bind mount, the export lands at ./signals-data/snapshot.zip on the host (or pull it with docker cp signals:/data/snapshot.zip .). You now have a working snapshot.
docker exec signals signalsctl status shows the collector state per target; connect test primary confirms connectivity before you rely on the schedule.Where next
To run Signals without a stored password, use the passwordless Microsoft Entra method described in Authentication methods, and see Run as a service to keep the collector running on a schedule.