OpsNexus

Audit logs

The append-only, hash-chained record of sign-ins, changes, deployments and secret access, and how to search, export and check it.

On this page

OpsNexus records every sign-in, every change and every secret access in an append-only audit log. Each entry carries the hash of the entry before it, so editing or deleting a row breaks the chain.

Open it from Audit logs in the sidebar. You need Read only on the Audit logs module. Among the built-in roles, Organization Admin, DevOps Engineer and Security Engineer have it.

What an entry contains

Field Meaning
Time When it happened.
Actor Who did it: the user's email, system for the first-run setup, or the identifier typed on a failed sign-in.
Action A dotted name such as secret.reveal.
Category A group for filtering: Sign-in, Access, Secrets, Deploy, Integrations, Agents, System and others.
Resource The thing acted on, with its type and ID.
Result Usually success or failed. The data model also allows denied.
Source IP The client's IP address.
Details Extra context as JSON, such as which fields changed or the old and new value of a setting.
Hash The SHA-256 hash of this entry.

The audit log also records the project an action happened in.

What is never logged

Secret values never go into the audit log. Before an entry is saved, any detail whose key contains password, token, secret, api_token, private_key, client_secret or value is replaced with ***. Credential changes log the field names only.

Recorded actions

The table lists the action names found in OpsNexus, grouped by area.

Area Actions
Sign-in and your account auth.login (success and failure), auth.password.change, auth.mfa.enable, auth.mfa.disable, auth.api_key.create, auth.api_key.revoke, profile.update, profile.avatar.set, profile.avatar.remove, profile.session.revoke
Users, roles and teams user.create, user.update, user.delete, user.project_access, role.create, role.permission.update, role.delete, team.create, team.update, team.delete
Projects project.create, project.update, project.delete, project.member.add, project.member.role, project.member.remove, projects.sharing
Organization and settings system.bootstrap, organization.update, settings.password_policy.update, settings.theme.update
Secrets and variables secret.create, secret.update, secret.rotate, secret.reveal, secret.delete, variable.upsert, variable.delete
Pipelines and builds pipeline.trigger, build.cancel, ci.job.create, ci.job.update, ci.job.enable, ci.job.disable, ci.job.delete, ci.job.webhook_rotate, ci.run.approve, ci.run.reject, ci.artifact.delete
Pipeline plugins ci.plugin.install, ci.plugin.create, ci.plugin.publish, ci.plugin.enable, ci.plugin.disable, ci.plugin.delete
Build agents agent.token.create, agent.register, agent.unregister, agent.build_config, and agent.<command> for commands sent to an agent
Integrations integration.create, integration.update, integration.delete
Artifacts and marketplace registry.create, registry.update, registry.delete, artifact.tag.delete, retention.apply, deploy_target.create, marketplace.deploy, marketplace.uninstall
Cloud cloud.account.add, cloud.account.remove, cloud.budget.create
Infra designer infra.stack.create, infra.stack.update, infra.stack.delete, infra.run.approve, infra.run.reject, infra.run.cancel, infra.state.download, infra.state.force_unlock, infra.keypair.generate, infra.keypair.download, infra.windows_password.read
Kubernetes k8s.cluster.create, k8s.cluster.update, k8s.cluster.delete, k8s.agent.token
Servers and remote access remote.host.create, remote.host.update, remote.host.delete, remote.host.test, remote.host.reset_host_key, terminal.session.start, terminal.session.end, terminal.session.terminate
Monitoring alert.acknowledge, alert.resolve, alert_rule.create, alert_rule.update, alert_rule.delete, alert_rule.recommended
Notifications notification.channel.create, notification.channel.update, notification.channel.delete, notification.rule.create, notification.rule.update, notification.rule.delete, notification.digest.create, notification.digest.update, notification.digest.delete
Domains domain.create, domain.update, domain.delete, domain.traffic_source
Security security.scan.upload, security.finding.triage, security.sonarqube.connect
Dashboards and reports dashboard.create, dashboard.delete, report_layout.create, report_layout.update, report_layout.delete
Backups backup.config.update, backup.create, backup.download, backup.restore

Failed sign-ins are recorded as auth.login with result failed and a reason, for example the attempt count or "account locked".

Search and filter

  • Type in Search user, action, resource or IP to match the actor, action name, resource or IP address. The search runs after a short pause in typing.
  • Select a category: All, Sign-in, Access, Secrets, Deploy, Integrations, Agents or System.
  • Results are newest first, 50 per page.
  • Select a row to open its details: category, resource, resource type, source IP, the details JSON and the entry's hash.

The API supports more filters than the page. GET /api/audit-logs accepts category, q, result (success, failed or denied), since (an ISO date-time), page and page_size (up to 200).

bash
curl -H "X-API-Key: <access-key>.<secret-key>" \
  "https://opsnexus.example.com/api/audit-logs?result=failed&since=2026-11-01T00:00:00Z"

Export

Select Export CSV to download audit-logs.csv. The export uses the current category and search filter. It contains up to 50,000 entries, newest first, with these columns:

time,actor,action,category,resource,result,ip,details,hash

The export endpoint is GET /api/audit-logs/export.csv and accepts category, q and since.

You can also generate the Audit log report as PDF, Excel or CSV for a date range, or email it on a schedule. See Dashboards & reports.

Tip

To keep a copy outside OpsNexus, ship the CSV export to your SIEM on a schedule, or collect the API container's output with a log shipper.

The hash chain

Each organization has its own chain. When OpsNexus writes an entry, it:

  1. Reads the hash of the organization's most recent entry.
  2. Stores it in the new entry as prev_hash.
  3. Computes the new entry's hash as the SHA-256 of a JSON array holding the organization ID, actor ID, action, resource type, resource ID, result, the scrubbed details and prev_hash, serialized with sorted keys.

If someone changes a stored entry, its hash no longer matches its content. If someone deletes an entry, the next entry's prev_hash no longer points at an existing hash.

Check the chain

OpsNexus has no built-in verify button. To check the chain yourself, query the audit_logs table and confirm that each entry's prev_hash equals the hash of the entry before it in the same organization:

bash
docker compose exec -T db psql -U opsnexus -d opsnexus -c "
SELECT id, created_at, action
FROM (
  SELECT id, created_at, action, prev_hash,
         LAG(hash) OVER (PARTITION BY organization_id ORDER BY created_at) AS expected
  FROM audit_logs
) t
WHERE expected IS NOT NULL AND prev_hash IS DISTINCT FROM expected;"

An empty result means the links are intact. Replace the user and database names with the POSTGRES_USER and POSTGRES_DB values from your .env.

Note

This query checks the links only. To also detect edited content, recompute each hash from the fields listed above. The project ID is not part of the hash.

Retention

OpsNexus doesn't delete audit entries. There is no retention setting for the audit log, so it grows until you archive it. Plan database size with that in mind, and export older entries to long-term storage if your policy needs it.

Audit entries are included in platform backups. See Backup & restore.