- Application Prerequisites
- Managed Database Prerequisites
- Application Setup
- Environment Variables
- Production Checklist
Azimutt Inspector is a NodeJS application that can be deployed using:
It needs a database as storage, either PostgreSQL (production) or SQLite (in local, with a file, or in memory).
Azimutt Inspector uses pg, working with most PostgreSQL versions. See connection troubleshooting if you encounter any issue.
Create an azimutt user with minimal rights:
CREATE USER azimutt WITH PASSWORD 'your_password';
GRANT CONNECT ON DATABASE your_database TO azimutt;
GRANT pg_monitor TO azimutt;If you have to grant access to many databases, you can use:
SELECT concat('GRANT CONNECT ON DATABASE "', datname, '" TO azimutt;') AS query FROM pg_database;For cleanup, you can revoke the rights and drop the user:
REVOKE CONNECT ON DATABASE your_database FROM azimutt;
DROP USER azimutt;For the best results, make sure to:
- enable
pg_stat_statementsextension (probably enabled by default): track query execution statistics - enabled
auto_explainextension: log the plan of slow queries - install
pg_show_plansextension: allow to get the plan of a running query - extract an interesting sample of database logs
- in Instance configuration, make sure to fill vCPU, RAM, and Storage properties (for settings tuning)
Azimutt Inspector uses mysql2, working with most MySQL versions. See connection troubleshooting if you encounter any issue.
Create an azimutt user with minimal rights:
-- Create the user
CREATE USER 'azimutt'@'%' IDENTIFIED BY 'your_password';
-- Grant system access for monitoring
GRANT SELECT ON information_schema.* TO 'azimutt'@'%';
GRANT SELECT ON performance_schema.* TO 'azimutt'@'%';For cleanup, you can revoke the rights and drop the user:
REVOKE SELECT ON information_schema.* FROM 'azimutt'@'%';
REVOKE SELECT ON performance_schema.* FROM 'azimutt'@'%';
DROP USER 'azimutt'@'%';If you have a database connection issue, there are troubleshooting tests:
- open postgresql.test.ts or mysql.test.ts
- find the
connectstest, remove the, and use your own database credentials - run it with
npm test -w backend postgresql.test.ts -- -t connects(if you haven't already, runnpm installfirst) - change connection parameters until it works
If you can't make it work, maybe Azimutt Inspector is missing a configuration for your case. You can try to connect directly with pg (doc) or mysql2:
- below in the same file postgresql.test.ts (or mysql.test.ts)
- find the
connects rawtest, remove the, and use your own database credentials - run it with
npm test -w backend postgresql.test.ts -- -t "connects raw" - change connection parameters until it works
If you still can't make it work, ping us so we can troubleshoot together.
For a production setup, use these two commands:
npm run build:prod
npm run start:prodFor full configuration, see Environment Variables.
- Create a Node.js application
- Setup required Environment variables
PORT=8080: required by Clever CloudCC_NODE_BUILD_TOOL=custom: to allowCC_CUSTOM_BUILD_TOOLCC_CUSTOM_BUILD_TOOL=npm run build:prod: to build the app with dev dependenciesCC_RUN_COMMAND=npm run start:prod: to start the app in production mode- set needed environment variables
- Add Clever Cloud git remote:
git remote add clever git+ssh://git@push-n3-par-clevercloud-customers.services.clever-cloud.com/app_00000000-0000-0000-0000-000000000000.git - Push your code:
git push clever your_branch:master - Open your app
- Create an app
- Add Heroku git remote:
heroku git:remote -a your_app_name - Push your code:
git push heroku your_branch:main(custom start command configured inProcfile) - Open your app
Using the pre-built image:
# Run with your database URL (PostgreSQL example)
docker run --rm --pull always -p 3000:3000 -e QUICKSTART_DB=postgresql://user:password@host:5432/database --name inspector ghcr.io/azimuttapp/inspector:latestBuilding the image yourself:
# Build the Docker image locally
docker build -t azimutt/inspector .
# Run with your database URL (PostgreSQL example)
docker run --rm -p 3000:3000 -e QUICKSTART_DB=postgresql://user:password@host:5432/database --name inspector azimutt/inspectorDocker networking note:
When running in Docker, localhost refers to the container itself. To connect to a database on your host machine:
- Linux: Use
--network hostflag:docker run --network host ... - Mac/Windows: Use
host.docker.internalinstead oflocalhostin the connection URL - Alternative: Use your machine's IP address instead of
localhost
If you got: "Error response from daemon: Conflict. The container name "/inspector" is already in use", use docker rm -f inspector.
For full configuration, see Environment Variables.
There is a Helm chart available for Kubernetes.
For full configuration, see Environment Variables.
All variables are optional, Azimutt Inspector uses default values if not provided.
| Variable | Description | Default |
|---|---|---|
PORT |
Azimutt server port | 3000 |
DATABASE_URL |
Azimutt own database, PostgreSQL or SQLite | :memory: |
DATABASE_ROLE |
Role to use for PostgreSQL storage if different from user | - |
DATABASE_POOL_MAX |
Max connections in pool for PostgreSQL storage | 5 |
APP_SECRET |
Used to encrypt secrets in database (see Secret Rotation below) | change-me |
AUTH_JWT_SECRET |
Used to sign JWT tokens (see Secret Rotation below) | change-me-change-me |
AUTH_CACHE_DURATION |
Cache duration for auth roles/providers | 1m |
AUTH_EMERGENCY_USER |
Emergency only: Login bypass with full rights (see Security below) | - |
AUTH_EMERGENCY_PASS |
Emergency only: Password for emergency user | - |
SCHEDULER_START |
Start the scheduler when the application starts | true |
INSTANCE_TAG_FILTER |
Comma-separated tags to filter which instances this app manages (default: all) | - |
PLUGIN_FOLDERS |
Folders to load plugins from (comma-separated) | - |
RUNBOOK_FOLDERS |
Folders to load runbooks from (comma-separated) | - |
QUICKSTART_DB |
Auto create an instance and monitoring for this database | - |
QUICKSTART_CONF |
Path to JSON file for initial configuration (see below) | - |
LOG_LEVEL |
Log level (verbose, debug, log, warn, error, fatal) | log |
LOG_LEVEL_CONFIG |
Log level configuration (pattern:level, comma-separated) | - |
DIAG_EVENT_LOOP_BLOCKED |
Log event loop blocked detection threshold in ms | - |
LICENSE |
License key for Enterprise features (see docs/ee.md) | - |
⚠️ Security note: The default values forAPP_SECRETandAUTH_JWT_SECRETare not secure. For any deployment beyond local testing, change them to strong random strings (e.g.openssl rand -hex 32). Using the defaults in production exposes your encrypted secrets and authentication tokens.
Both APP_SECRET and AUTH_JWT_SECRET support key rotation to allow updating secrets without downtime:
# Rotate APP_SECRET (for database encryption)
APP_SECRET="rotate:NEW_SECRET_KEY,OLD_SECRET_KEY"
# Rotate AUTH_JWT_SECRET (for JWT tokens)
AUTH_JWT_SECRET="rotate:NEW_JWT_SECRET,OLD_JWT_SECRET"Important:
- The first secret in the rotation list is used for new encryptions/signatures
- Additional secrets are used as fallbacks for decryption/verification (you can have as many as you want, not just one)
- Never remove a secret from the rotation list until all data encrypted/signed with it has been migrated
- For
APP_SECRETrotation: All database passwords, API keys, and sensitive config are encrypted with this key. Changing it without rotation will make all encrypted data unreadable.
Emergency User: The AUTH_EMERGENCY_USER and AUTH_EMERGENCY_PASS provide a backdoor for system recovery when the normal authentication system is unavailable (e.g., locked out of all accounts, database issues).
- This user bypasses all authentication checks and has full admin/owner rights
- Should only be configured temporarily for emergency recovery
- All emergency user logins are logged for security audit
- Remove these environment variables immediately after resolving the emergency
The QUICKSTART_DB environment variable allows you to create a database instance when none exists; useful for quick setup and testing.
The QUICKSTART_CONF environment variable allows you to bootstrap Azimutt Inspector with a complete configuration from a JSON file (settings, users, roles...); missing entities are created.
They can be used together, QUICKSTART_CONF taks precedence over QUICKSTART_DB, so if a database instance is defined in QUICKSTART_CONF, the one from QUICKSTART_DB is ignored.
QUICKSTART_CONF is useful for:
- Automated deployments with predefined settings
- Reproducing configurations across environments
- Infrastructure as Code setups
The configuration file can define:
- settings: Application settings (LLM context, server URL, observability, etc.)
- roles: User roles with permissions
- users: User accounts with role assignments
- authProviders: Authentication providers (local, OAuth)
- llmModels: LLM model configurations (OpenAI, Google, Ollama, etc.)
- llmTools: Custom LLM tools (SQL queries, external integrations)
- llmSystemPrompts: Custom system prompts for the AI assistant
- collectors: Data collectors (built-in modules or custom SQL queries)
- presets: Collector presets for easy instance configuration
- analyzers: Analyzers for generating alerts and suggestions
- notifiers: Notification channels (Slack, webhooks, etc.)
- instances: Database instances to monitor
Environment variable substitution: Use $VAR_NAME syntax for sensitive values:
{
"llmModels": [
{ "name": "gpt4", "provider": "openai", "model": "gpt-4", "apiKey": "$OPENAI_API_KEY" }
]
}See quickstart-conf.example.json for a complete example.
When monitoring a large number of database instances, a single Azimutt Inspector node may become a bottleneck (too many open connection pools). You can start several instances of Azimutt Inspector on the same storage, the load will be distributed across them.
You can go further with instance tag-based filtering to limit the opened connections to a subset of instances.
How it works:
- Tag each database instance with a group identifier (e.g.
node-eu,node-us) from the instance settings page. - Set the
INSTANCE_TAG_FILTERenvironment variable on Azimutt Inspector nodes, they will schedule collectors only for instances with a matching tag, but also any analyzers and notifiers.
Recommended deployment topology for, say, 100 instances:
| Node | INSTANCE_TAG_FILTER |
SCHEDULER_START |
Role |
|---|---|---|---|
| eu-1 | node-eu |
true |
Schedules collectors only for EU instances |
| eu-2 | node-eu |
true |
Same, useful for redundancy |
| us-1 | node-us |
true |
Schedules collectors only for US instances |
| us-2 | node-us |
true |
Same, useful for redundancy |
| fallback | (unset) | true |
Schedules everything, including collectors with not matching tags |
| ui | (unset) | false |
UI-only, no scheduling (no CPU/RAM competition between UI & jobs) |
Notes:
INSTANCE_TAG_FILTERis comma-separated, with OR semantics:node-eu,node-usmatches instances tagged with either tag.- Nodes with no
INSTANCE_TAG_FILTERmanage all instances — useSCHEDULER_START=falseif you want a UI-only node. - Analyzer, notifier, and retention jobs are global; all nodes compete for them via the shared queue (this is intentional).
- The General Settings page shows the active tag filter under the Scheduler status section for the instance.
Before deploying Azimutt Inspector to production, make sure to:
- Change
APP_SECRET: use a strong random string (openssl rand -hex 32). This encrypts all database passwords and API keys stored by Inspector. Losing or changing it without rotation makes all encrypted data unreadable. - Change
AUTH_JWT_SECRET: use a different strong random string. This signs authentication tokens. - Setup storage: set
DATABASE_URLto SQLite file for community and a PostgreSQL connection string in enterprise. In-memory SQLite (the default) loses all data on restart (only good for quick testing). - Enable authentication (Enterprise): configure auth providers to restrict access to your Inspector instance.
- Create a dedicated database user: follow the PostgreSQL or MySQL setup above to grant minimal read-only rights to the database user provided to Azimutt Inspector.
- Back Azimutt Inspector database: include the Azimutt Inspector database in your backup strategy. It holds your configuration, alert history, and execution logs.
- Review security considerations: understand the security model, especially if exposing Inspector on a network.