Skip to main content
Activity logging provides a complete audit trail of all resource-related actions in NetBird Selfservice. Every create, update, delete, approval, and status change is recorded with full context for compliance and troubleshooting.

What Gets Logged

NetBird Selfservice logs every action that affects network resources:

Resource Lifecycle

  • Created
  • Updated
  • Deleted

Status Changes

  • Enabled
  • Disabled

Approval Workflow

  • Requested
  • Approved
  • Denied
  • Cancelled

ResourceLog Model

Activity logs are stored in the resource_logs table using the ResourceLog model:

Log Fields

// From ResourceLog.php:11-18
protected $fillable = [
    'netbird_id',
    'action',
    'resource_name',
    'resource_address',
    'performed_by',
    'changes',
];
FieldTypeDescription
netbird_idstringNetBird resource ID (null for requests)
actionstringType of action performed
resource_namestringName of the resource
resource_addressstringIP, CIDR, or domain
performed_bystringName of the user who performed the action
changesarrayJSON object with detailed changes
created_attimestampWhen the action occurred

Changes Field

The changes field is cast to an array and stores action-specific details:
// From ResourceLog.php:20-24
protected function casts(): array
{
    return [
        'changes' => 'array',
    ];
}

Action Types

All actions are defined in the ResourceAction enum:
// From ResourceAction.php:6-15
enum ResourceAction: string
{
    case Created = 'created';
    case Approved = 'approved';
    case Updated = 'updated';
    case Deleted = 'deleted';
    case Denied = 'denied';
    case Requested = 'requested';
    case Cancelled = 'cancelled';
    case Enabled = 'enabled';
    case Disabled = 'disabled';
}

Action Categories

Created
  • Direct creation by admin users
  • Logs: name, address, description, enabled status
Approved
  • Resource created via approval workflow
  • Logs: requester info, approved resource details

Logging Implementation

Helper Method

The ResourceLog model provides a static helper method for easy logging:
// From ResourceLog.php:27-43
public static function logAction(
    string $action,
    string $resourceName,
    ?string $netbirdId = null,
    ?string $resourceAddress = null,
    ?string $performedBy = null,
    ?array $changes = null
): self {
    return self::create([
        'action' => $action,
        'resource_name' => $resourceName,
        'netbird_id' => $netbirdId,
        'resource_address' => $resourceAddress,
        'performed_by' => $performedBy,
        'changes' => $changes,
    ]);
}

Example: Logging a Resource Creation

// From CreateResourceAction.php:46-58
ResourceLog::logAction(
    action: ResourceAction::Created->value,
    resourceName: $name,
    netbirdId: $result['id'],
    resourceAddress: $address,
    performedBy: $user->name,
    changes: [
        'name' => $name,
        'address' => $address,
        'description' => $description,
        'enabled' => $enabled,
    ]
);

Example: Logging an Update

// From UpdateResourceAction.php:41-53
ResourceLog::logAction(
    action: ResourceAction::Updated->value,
    resourceName: $name,
    netbirdId: $resourceId,
    resourceAddress: $address,
    performedBy: $user->name,
    changes: [
        'name' => $name,
        'address' => $address,
        'description' => $description,
        'enabled' => $enabled,
    ]
);
Every action class that modifies resources includes a corresponding ResourceLog::logAction() call to ensure complete audit coverage.

Viewing Activity Logs

Activity logs can be viewed through the admin dashboard or queried directly:

Recent Activity

// Get the 50 most recent logs
$recentLogs = ResourceLog::orderBy('created_at', 'desc')
    ->limit(50)
    ->get();

Filter by Action

// Get all approval actions
$approvals = ResourceLog::where('action', ResourceAction::Approved->value)
    ->orderBy('created_at', 'desc')
    ->get();

Filter by Resource

// Get all logs for a specific resource
$resourceLogs = ResourceLog::where('netbird_id', $resourceId)
    ->orderBy('created_at', 'desc')
    ->get();

Filter by User

// Get all actions performed by a specific user
$userActions = ResourceLog::where('performed_by', $userName)
    ->orderBy('created_at', 'desc')
    ->get();

Audit Trail Use Cases

Compliance & Reporting

Demonstrate who accessed what resources and when for regulatory compliance (SOC 2, HIPAA, etc.)

Security Investigations

Track suspicious activity or unauthorized resource changes with complete attribution

Troubleshooting

Identify when and why a resource was modified when investigating connectivity issues

Change Management

Review the complete history of resource changes for documentation and rollback

Activity Log Badges

The system provides visual indicators for different action types:
// From ResourceAction.php:32-40
public function badgeClasses(): string
{
    return match ($this) {
        self::Created, self::Approved, self::Enabled => 
            'bg-green-100 text-green-800 dark:bg-green-900/50 dark:text-green-300',
        self::Updated => 
            'bg-blue-100 text-blue-800 dark:bg-blue-900/50 dark:text-blue-300',
        self::Deleted, self::Denied => 
            'bg-red-100 text-red-800 dark:bg-red-900/50 dark:text-red-300',
        self::Requested => 
            'bg-amber-100 text-amber-800 dark:bg-amber-900/50 dark:text-amber-300',
        self::Cancelled, self::Disabled => 
            'bg-zinc-100 text-zinc-800 dark:bg-zinc-700/50 dark:text-zinc-300',
    };
}
This creates color-coded badges:
  • 🟢 Green: Positive actions (created, approved, enabled)
  • 🔵 Blue: Modifications (updated)
  • 🔴 Red: Destructive actions (deleted, denied)
  • 🟡 Amber: Pending actions (requested)
  • Gray: Neutral actions (cancelled, disabled)

Changes Tracking

The changes field captures action-specific details:

For Create/Update Actions

{
  "name": "Production API",
  "address": "api.example.com",
  "description": "Main production API endpoint",
  "enabled": true
}

For Toggle Actions

{
  "enabled": false
}

For Request Actions

{
  "name": "Database Server",
  "address": "10.50.1.100",
  "description": "Access to production database",
  "enabled": true,
  "requested_by": "John Doe"
}

For Delete Actions

{
  "name": "Legacy Service",
  "address": "192.168.1.50",
  "description": "Deprecated service endpoint"
}

Pending Resource Logging

When a request is submitted, the PendingResource model provides a method to format changes for logging:
// From PendingResource.php:51-60
public function toLogChanges(): array
{
    return [
        'name' => $this->name,
        'address' => $this->address,
        'description' => $this->description,
        'enabled' => $this->enabled,
        'requested_by' => $this->requested_by,
    ];
}
This ensures consistent formatting across all request-related log entries.

Log Retention

Currently, logs are retained indefinitely. Consider implementing a retention policy based on your compliance requirements.

Suggested Retention Policies

Depending on your compliance requirements:
Use CaseSuggested Retention
General auditing90 days
SOC 2 compliance1 year
HIPAA compliance6 years
Financial industry7 years

Implementing Log Cleanup

Example scheduled job to clean old logs:
// In app/Console/Kernel.php
$schedule->call(function () {
    ResourceLog::where('created_at', '<', now()->subDays(90))->delete();
})->daily();

Querying Logs

Advanced Queries

Get logs with complex filters:
// Resources modified in the last 24 hours
$recentChanges = ResourceLog::whereIn('action', [
        ResourceAction::Created->value,
        ResourceAction::Updated->value,
        ResourceAction::Deleted->value,
    ])
    ->where('created_at', '>=', now()->subDay())
    ->orderBy('created_at', 'desc')
    ->get();
// All denied requests
$deniedRequests = ResourceLog::where('action', ResourceAction::Denied->value)
    ->with('user') // If you add a user relationship
    ->orderBy('created_at', 'desc')
    ->get();

Export Logs

Generate CSV export for compliance reporting:
$logs = ResourceLog::orderBy('created_at', 'desc')->get();

$csv = Writer::createFromString('');
$csv->insertOne(['Date', 'Action', 'Resource', 'Address', 'Performed By']);

foreach ($logs as $log) {
    $csv->insertOne([
        $log->created_at->format('Y-m-d H:i:s'),
        $log->action,
        $log->resource_name,
        $log->resource_address,
        $log->performed_by,
    ]);
}

return response($csv->toString())
    ->header('Content-Type', 'text/csv')
    ->header('Content-Disposition', 'attachment; filename="resource_logs.csv"');

Best Practices

Never Delete Logs

Logs are your audit trail. Archive old logs instead of deleting them if storage is a concern

Include Context

Always include the user name and resource details so logs are self-documenting

Regular Reviews

Periodically review logs to identify patterns, anomalies, or training opportunities

Secure Access

Restrict log viewing to admins and compliance officers - logs contain sensitive information

Integration with External Systems

Sending Logs to SIEM

For enterprise deployments, stream logs to your Security Information and Event Management (SIEM) system:
// In ResourceLog model after creating a log
protected static function booted()
{
    static::created(function ($log) {
        // Send to external SIEM
        SiemService::send([
            'timestamp' => $log->created_at,
            'action' => $log->action,
            'resource' => $log->resource_name,
            'user' => $log->performed_by,
            'changes' => $log->changes,
        ]);
    });
}

Webhook Notifications

Trigger webhooks on specific actions for real-time alerting:
if ($action === ResourceAction::Deleted->value) {
    WebhookService::notify('resource.deleted', [
        'resource' => $resourceName,
        'deleted_by' => $performedBy,
        'deleted_at' => now(),
    ]);
}

Summary

Activity logging in NetBird Selfservice provides: Complete audit trail of all resource operations
User attribution for every action
Detailed change tracking with before/after states
Compliance support for regulatory requirements
Troubleshooting data for investigating issues
Security monitoring for detecting unauthorized changes
Every action that modifies resources is automatically logged with full context, creating a permanent, tamper-evident record of your network access management.

Build docs developers (and LLMs) love