Configuration Reference

Sentinel is configured by passing a sentinel.Config struct to sentinel.Mount(). Every field has a sensible default, so you can start with an empty struct and enable features incrementally. This page documents every configuration section, its fields, default values, and usage patterns.

Zero-Value Friendly

All config fields are zero-value safe. An empty sentinel.Config{} gives you a working setup with SQLite storage, the dashboard enabled, security headers active, and performance monitoring on. Features like WAF, rate limiting, and anomaly detection are opt-in via their Enabled field.

Complete Example

Below is a fully configured Sentinel instance with every major feature enabled. In practice, you only need to set the fields relevant to your application.

main.gogo
1package main
2
3import (
4 "time"
5
6 sentinel "github.com/MUKE-coder/sentinel"
7 "github.com/gin-gonic/gin"
8)
9
10func main() {
11 r := gin.Default()
12
13 sentinel.Mount(r, nil, sentinel.Config{
14 Dashboard: sentinel.DashboardConfig{
15 Username: "admin",
16 Password: "s3cur3-p4ss!",
17 SecretKey: "my-jwt-secret-change-in-production",
18 },
19
20 Storage: sentinel.StorageConfig{
21 Driver: sentinel.SQLite,
22 DSN: "sentinel.db",
23 RetentionDays: 90,
24 MaxOpenConns: 10,
25 MaxIdleConns: 5,
26 },
27
28 WAF: sentinel.WAFConfig{
29 Enabled: true,
30 Mode: sentinel.ModeBlock,
31 Rules: sentinel.RuleSet{
32 SQLInjection: sentinel.RuleStrict,
33 XSS: sentinel.RuleStrict,
34 PathTraversal: sentinel.RuleStrict,
35 CommandInjection: sentinel.RuleStrict,
36 SSRF: sentinel.RuleMedium,
37 XXE: sentinel.RuleStrict,
38 LFI: sentinel.RuleStrict,
39 OpenRedirect: sentinel.RuleMedium,
40 },
41 CustomRules: []sentinel.WAFRule{
42 {
43 ID: "block-admin-enum",
44 Name: "Block admin enumeration",
45 Pattern: `(?i)/(wp-admin|phpmyadmin|administrator)`,
46 AppliesTo: []string{"path"},
47 Severity: sentinel.SeverityMedium,
48 Action: "block",
49 Enabled: true,
50 },
51 },
52 ExcludeRoutes: []string{"/health", "/metrics"},
53 ExcludeIPs: []string{"10.0.0.0/8"},
54 },
55
56 RateLimit: sentinel.RateLimitConfig{
57 Enabled: true,
58 Strategy: sentinel.SlidingWindow,
59 ByIP: &sentinel.Limit{Requests: 100, Window: time.Minute},
60 ByUser: &sentinel.Limit{Requests: 500, Window: time.Minute},
61 Global: &sentinel.Limit{Requests: 5000, Window: time.Minute},
62 ByRoute: map[string]sentinel.Limit{
63 "/api/login": {Requests: 5, Window: 15 * time.Minute},
64 "/api/register": {Requests: 3, Window: time.Hour},
65 },
66 },
67
68 AuthShield: sentinel.AuthShieldConfig{
69 Enabled: true,
70 LoginRoute: "/api/login",
71 MaxFailedAttempts: 5,
72 LockoutDuration: 15 * time.Minute,
73 CredentialStuffingDetection: true,
74 BruteForceDetection: true,
75 },
76
77 Headers: sentinel.HeaderConfig{
78 ContentSecurityPolicy: "default-src 'self'",
79 StrictTransportSecurity: true,
80 XFrameOptions: "DENY",
81 XContentTypeOptions: true,
82 ReferrerPolicy: "strict-origin-when-cross-origin",
83 PermissionsPolicy: "camera=(), microphone=(), geolocation=()",
84 },
85
86 Anomaly: sentinel.AnomalyConfig{
87 Enabled: true,
88 Sensitivity: sentinel.AnomalySensitivityMedium,
89 LearningPeriod: 7 * 24 * time.Hour,
90 Checks: []sentinel.AnomalyCheckType{
91 sentinel.CheckImpossibleTravel,
92 sentinel.CheckUnusualAccess,
93 sentinel.CheckDataExfiltration,
94 sentinel.CheckOffHoursAccess,
95 sentinel.CheckVelocityAnomaly,
96 },
97 },
98
99 IPReputation: sentinel.IPReputationConfig{
100 Enabled: true,
101 AbuseIPDBKey: "your-abuseipdb-api-key",
102 AutoBlock: true,
103 MinAbuseScore: 80,
104 },
105
106 Geo: sentinel.GeoConfig{
107 Enabled: true,
108 Provider: sentinel.GeoIPFree,
109 },
110
111 Alerts: sentinel.AlertConfig{
112 MinSeverity: sentinel.SeverityHigh,
113 Slack: &sentinel.SlackConfig{
114 WebhookURL: "https://hooks.slack.com/services/...",
115 },
116 Email: &sentinel.EmailConfig{
117 SMTPHost: "smtp.example.com",
118 SMTPPort: 587,
119 Username: "alerts@example.com",
120 Password: "smtp-password",
121 Recipients: []string{"security@example.com"},
122 },
123 Webhook: &sentinel.WebhookConfig{
124 URL: "https://your-siem.example.com/webhook",
125 Headers: map[string]string{
126 "Authorization": "Bearer your-token",
127 },
128 },
129 },
130
131 AI: &sentinel.AIConfig{
132 Provider: sentinel.Claude,
133 APIKey: "your-anthropic-api-key",
134 Model: "claude-sonnet-4-20250514",
135 DailySummary: true,
136 },
137
138 UserExtractor: func(c *gin.Context) *sentinel.UserContext {
139 userID := c.GetHeader("X-User-ID")
140 if userID == "" {
141 return nil
142 }
143 return &sentinel.UserContext{
144 ID: userID,
145 Email: c.GetHeader("X-User-Email"),
146 Role: c.GetHeader("X-User-Role"),
147 }
148 },
149
150 Performance: sentinel.PerformanceConfig{
151 SlowRequestThreshold: 2 * time.Second,
152 SlowQueryThreshold: 500 * time.Millisecond,
153 TrackMemory: true,
154 TrackGoroutines: true,
155 },
156 })
157
158 r.GET("/api/hello", func(c *gin.Context) {
159 c.JSON(200, gin.H{"message": "Hello, World!"})
160 })
161
162 r.Run(":8080")
163}

Dashboard

The DashboardConfig controls the embedded React security dashboard. The dashboard is enabled by default and served under the configured prefix. It is protected by JWT-based authentication using the username and password you provide.

FieldTypeDefaultDescription
Enabled*booltrueWhether the dashboard is served. Set to false to disable entirely.
Prefixstring/sentinelURL prefix for the dashboard and API routes. The UI is available at {prefix}/ui.
UsernamestringadminUsername for dashboard login.
PasswordstringsentinelPassword for dashboard login.
SecretKeystringsentinel-default-secret-change-meSecret key used to sign JWT tokens for dashboard sessions.
config.gogo
1Dashboard: sentinel.DashboardConfig{
2 Prefix: "/admin/security",
3 Username: "secops",
4 Password: "change-me-in-production",
5 SecretKey: "a-strong-random-secret",
6}

Change Default Credentials

The default username/password (admin/sentinel) and secret key are intended for development only. Always set strong values in production. The SecretKey is used to sign JWT tokens — if it is compromised, attackers can forge dashboard sessions.

Disabling the Dashboard

To run Sentinel as a headless middleware without any dashboard routes, set Enabled to false. Because the field is a *bool, you need to use a pointer:
disabled := false
Dashboard: sentinel.DashboardConfig{
Enabled: &disabled,
}

Storage

The StorageConfig controls how Sentinel persists security events, threat actors, rate limit counters, and other data. Sentinel ships with two built-in storage drivers and supports additional drivers.

FieldTypeDefaultDescription
DriverStorageDriversentinel.SQLiteStorage backend. Options: sentinel.SQLite, sentinel.Memory, sentinel.Postgres, sentinel.MySQL.
DSNstringsentinel.dbData source name. For SQLite, this is a file path. For Postgres/MySQL, a full connection string.
RetentionDaysint90Number of days to retain security events before automatic cleanup.
MaxOpenConnsint10Maximum number of open database connections.
MaxIdleConnsint5Maximum number of idle database connections.

Storage Drivers

DriverConstantNotes
SQLitesentinel.SQLitePure Go (no CGo). Recommended for most deployments. Data persists to a file.
Memorysentinel.MemoryIn-memory store. No persistence — data is lost on restart. Useful for testing.
Postgressentinel.PostgresPostgreSQL backend for high-availability production deployments.
MySQLsentinel.MySQLMySQL/MariaDB backend.
config.gogo
1// SQLite (default, recommended)
2Storage: sentinel.StorageConfig{
3 Driver: sentinel.SQLite,
4 DSN: "sentinel.db",
5 RetentionDays: 30,
6}
7
8// In-memory (for development/testing)
9Storage: sentinel.StorageConfig{
10 Driver: sentinel.Memory,
11}
12
13// PostgreSQL
14Storage: sentinel.StorageConfig{
15 Driver: sentinel.Postgres,
16 DSN: "postgres://user:pass@localhost:5432/sentinel?sslmode=disable",
17 MaxOpenConns: 25,
18 MaxIdleConns: 10,
19}

No CGo Required

The SQLite driver uses a pure-Go implementation (github.com/glebarez/sqlite), so you do not need CGo or any C compiler installed. This makes cross-compilation and Docker builds straightforward.

WAF (Web Application Firewall)

The WAFConfig controls the built-in Web Application Firewall. When enabled, it inspects incoming requests for SQL injection, XSS, path traversal, command injection, SSRF, XXE, LFI, and open redirect attacks. It can operate in log-only mode (observe without blocking) or block mode (reject malicious requests with a 403 status).

FieldTypeDefaultDescription
EnabledboolfalseEnables the WAF middleware. Must be set to true to activate.
ModeWAFModesentinel.ModeLogHow detected threats are handled. Options: sentinel.ModeLog, sentinel.ModeBlock, sentinel.ModeChallenge.
RulesRuleSetAll RuleStrictPer-category sensitivity levels for built-in detection rules.
CustomRules[]WAFRulenilCustom regex-based rules for application-specific patterns.
ExcludeRoutes[]stringnilRoutes to exclude from WAF inspection (e.g., health check endpoints).
ExcludeIPs[]stringnilIP addresses or CIDR ranges to exclude from WAF inspection.

WAF Modes

ModeConstantBehavior
Logsentinel.ModeLogDetects and logs threats but allows the request to proceed. Good for initial rollout.
Blocksentinel.ModeBlockDetects threats and rejects the request with HTTP 403. Recommended for production.
Challengesentinel.ModeChallengePresents a challenge to the client before allowing the request through.

RuleSet — Per-Category Sensitivity

Each built-in detection category can have its sensitivity tuned independently. The available levels are sentinel.RuleOff, sentinel.RuleLow, sentinel.RuleMedium, and sentinel.RuleStrict.

FieldDefaultDescription
SQLInjectionRuleStrictSQL injection detection sensitivity.
XSSRuleStrictCross-site scripting detection sensitivity.
PathTraversalRuleStrictPath traversal (../../etc/passwd) detection sensitivity.
CommandInjectionRuleStrictOS command injection detection sensitivity.
SSRFRuleMediumServer-side request forgery detection sensitivity.
XXERuleStrictXML external entity injection detection sensitivity.
LFIRuleStrictLocal file inclusion detection sensitivity.
OpenRedirectRuleMediumOpen redirect detection sensitivity.

Custom WAF Rules

Custom rules let you add application-specific detection patterns using regular expressions. Each rule is defined as a WAFRule struct.

FieldTypeDescription
IDstringUnique identifier for the rule.
NamestringHuman-readable name displayed in the dashboard.
PatternstringGo-compatible regular expression to match against request data.
AppliesTo[]stringWhich parts of the request to inspect: "path", "query", "body", "headers".
SeveritySeveritySeverity level: sentinel.SeverityLow, SeverityMedium, SeverityHigh, SeverityCritical.
ActionstringAction to take: "block" or "log".
EnabledboolWhether the rule is active.
config.gogo
1WAF: sentinel.WAFConfig{
2 Enabled: true,
3 Mode: sentinel.ModeBlock,
4 Rules: sentinel.RuleSet{
5 SQLInjection: sentinel.RuleStrict,
6 XSS: sentinel.RuleStrict,
7 PathTraversal: sentinel.RuleStrict,
8 CommandInjection: sentinel.RuleStrict,
9 SSRF: sentinel.RuleMedium,
10 XXE: sentinel.RuleStrict,
11 LFI: sentinel.RuleStrict,
12 OpenRedirect: sentinel.RuleMedium,
13 },
14 CustomRules: []sentinel.WAFRule{
15 {
16 ID: "block-admin-enum",
17 Name: "Block admin enumeration",
18 Pattern: `(?i)/(wp-admin|phpmyadmin|administrator)`,
19 AppliesTo: []string{"path"},
20 Severity: sentinel.SeverityMedium,
21 Action: "block",
22 Enabled: true,
23 },
24 {
25 ID: "block-sensitive-files",
26 Name: "Block sensitive file access",
27 Pattern: `(?i)\.(env|git|bak|sql|log)$`,
28 AppliesTo: []string{"path"},
29 Severity: sentinel.SeverityHigh,
30 Action: "block",
31 Enabled: true,
32 },
33 },
34 ExcludeRoutes: []string{"/health", "/readiness"},
35 ExcludeIPs: []string{"127.0.0.1", "10.0.0.0/8"},
36}

Recommended Rollout Strategy

Start with sentinel.ModeLog in production to observe what the WAF detects without blocking real traffic. Review the dashboard for false positives, tune rule sensitivities, then switch to sentinel.ModeBlock when confident.

Rate Limiting

The RateLimitConfig enables multi-dimensional rate limiting. You can set limits per IP, per authenticated user, per route, and globally. All dimensions are enforced independently — a request must pass all applicable limits.

FieldTypeDefaultDescription
EnabledboolfalseEnables the rate limiting middleware.
StrategyRateLimitStrategysentinel.SlidingWindowAlgorithm used for counting. Options: sentinel.SlidingWindow, sentinel.FixedWindow, sentinel.TokenBucket.
ByIP*LimitnilPer-IP rate limit. Each unique client IP gets its own counter.
ByUser*LimitnilPer-user rate limit. Requires a UserIDExtractor or UserExtractor.
ByRoutemap[string]LimitnilPer-route rate limits. Keys are route patterns (e.g., /api/login).
Global*LimitnilGlobal rate limit applied across all requests regardless of source.
UserIDExtractorfunc(*gin.Context) stringnilFunction to extract a user ID from the request for per-user limiting.

The Limit Struct

Each limit is defined by a number of allowed requests within a time window.

FieldTypeDescription
RequestsintMaximum number of requests allowed within the window.
Windowtime.DurationTime window for the limit (e.g., time.Minute, 15 * time.Minute).

Rate Limit Strategies

StrategyConstantDescription
Sliding Windowsentinel.SlidingWindowDefault. Provides smooth rate limiting without burst spikes at window boundaries.
Fixed Windowsentinel.FixedWindowSimple fixed time windows. Slightly less accurate but lower memory overhead.
Token Bucketsentinel.TokenBucketAllows short bursts while maintaining an average rate over time.
config.gogo
1RateLimit: sentinel.RateLimitConfig{
2 Enabled: true,
3 Strategy: sentinel.SlidingWindow,
4
5 // 100 requests per minute per IP
6 ByIP: &sentinel.Limit{Requests: 100, Window: time.Minute},
7
8 // 500 requests per minute per authenticated user
9 ByUser: &sentinel.Limit{Requests: 500, Window: time.Minute},
10
11 // 5000 requests per minute globally
12 Global: &sentinel.Limit{Requests: 5000, Window: time.Minute},
13
14 // Strict limits on sensitive routes
15 ByRoute: map[string]sentinel.Limit{
16 "/api/login": {Requests: 5, Window: 15 * time.Minute},
17 "/api/register": {Requests: 3, Window: time.Hour},
18 "/api/password-reset": {Requests: 3, Window: time.Hour},
19 },
20
21 // Extract user ID from your auth system
22 UserIDExtractor: func(c *gin.Context) string {
23 return c.GetHeader("X-User-ID")
24 },
25}

Rate Limit Headers

When rate limiting is active, Sentinel automatically sets standard rate limit headers on every response: X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. When a limit is exceeded, the client receives a 429 Too Many Requests response.

Auth Shield

The AuthShieldConfig protects authentication endpoints from brute-force attacks and credential stuffing. When enabled, it monitors the configured login route for failed authentication attempts and automatically locks out offending IPs.

FieldTypeDefaultDescription
EnabledboolfalseEnables the Auth Shield middleware.
LoginRoutestring""The route path for your login endpoint (e.g., /api/login).
MaxFailedAttemptsint5Number of failed login attempts before lockout is triggered.
LockoutDurationtime.Duration15 * time.MinuteHow long an IP is locked out after exceeding MaxFailedAttempts.
CredentialStuffingDetectionboolfalseDetects credential stuffing patterns (many different usernames from the same IP).
BruteForceDetectionboolfalseDetects brute force patterns (many password attempts for the same username).
config.gogo
1AuthShield: sentinel.AuthShieldConfig{
2 Enabled: true,
3 LoginRoute: "/api/login",
4 MaxFailedAttempts: 5,
5 LockoutDuration: 15 * time.Minute,
6 CredentialStuffingDetection: true,
7 BruteForceDetection: true,
8}

LoginRoute Must Match Exactly

The LoginRoute must match the exact path of your login handler. Sentinel monitors this route for non-2xx responses to count failed login attempts. If the route does not match, Auth Shield will not detect failures.

Security Headers

The HeaderConfig controls automatic injection of security headers into every response. Security headers are enabled by default. These headers protect against clickjacking, MIME sniffing, XSS, and other client-side attacks.

FieldTypeDefaultDescription
Enabled*booltrueWhether security headers are injected. Use a *bool to explicitly disable.
ContentSecurityPolicystring"" (not set)Value for the Content-Security-Policy header. Left empty by default because CSP is application-specific.
StrictTransportSecurityboolfalseWhen true, sets Strict-Transport-Security: max-age=31536000; includeSubDomains.
XFrameOptionsstringDENYValue for the X-Frame-Options header. Common values: DENY, SAMEORIGIN.
XContentTypeOptionsbooltrueWhen true, sets X-Content-Type-Options: nosniff.
ReferrerPolicystringstrict-origin-when-cross-originValue for the Referrer-Policy header.
PermissionsPolicystring"" (not set)Value for the Permissions-Policy header. Controls browser feature access.
config.gogo
1Headers: sentinel.HeaderConfig{
2 ContentSecurityPolicy: "default-src 'self'; script-src 'self' 'unsafe-inline'",
3 StrictTransportSecurity: true,
4 XFrameOptions: "DENY",
5 XContentTypeOptions: true,
6 ReferrerPolicy: "strict-origin-when-cross-origin",
7 PermissionsPolicy: "camera=(), microphone=(), geolocation=()",
8}

HSTS Warning

Only enable StrictTransportSecurity if your application is served exclusively over HTTPS. Once a browser receives an HSTS header, it will refuse to connect over plain HTTP for the specified duration.

Anomaly Detection

The AnomalyConfig enables behavioral anomaly detection. Sentinel learns normal traffic patterns during a configurable learning period and then flags deviations such as impossible travel, unusual access patterns, and data exfiltration attempts.

FieldTypeDefaultDescription
EnabledboolfalseEnables the anomaly detection engine.
SensitivityAnomalySensitivitysentinel.AnomalySensitivityMediumDetection sensitivity. Options: sentinel.AnomalySensitivityLow, AnomalySensitivityMedium, AnomalySensitivityHigh.
LearningPeriodtime.Duration7 * 24 * time.Hour (7 days)Duration of the initial learning phase during which Sentinel builds baseline traffic patterns.
Checks[]AnomalyCheckTypenil (all checks)Which anomaly checks to run. When nil, all checks are enabled.

Anomaly Check Types

CheckConstantDescription
Impossible Travelsentinel.CheckImpossibleTravelDetects logins from geographically distant locations within impossibly short timeframes.
Unusual Accesssentinel.CheckUnusualAccessFlags access to endpoints not typically visited by a given user or IP.
Data Exfiltrationsentinel.CheckDataExfiltrationDetects abnormally large data transfers or rapid sequential data access.
Off-Hours Accesssentinel.CheckOffHoursAccessFlags access outside of normal business hours for a given user profile.
Velocity Anomalysentinel.CheckVelocityAnomalyDetects sudden spikes in request velocity from a single source.
Credential Stuffingsentinel.CheckCredentialStuffingIdentifies patterns consistent with credential stuffing attacks on auth endpoints.
config.gogo
1Anomaly: sentinel.AnomalyConfig{
2 Enabled: true,
3 Sensitivity: sentinel.AnomalySensitivityMedium,
4 LearningPeriod: 7 * 24 * time.Hour,
5 Checks: []sentinel.AnomalyCheckType{
6 sentinel.CheckImpossibleTravel,
7 sentinel.CheckUnusualAccess,
8 sentinel.CheckDataExfiltration,
9 sentinel.CheckVelocityAnomaly,
10 },
11}

Learning Period

During the learning period, Sentinel collects baseline data but does not flag anomalies. After the learning period expires, detections begin automatically. A shorter learning period may produce more false positives; a longer period provides more accurate baselines.

IP Reputation

The IPReputationConfig integrates with the AbuseIPDB API to check the reputation score of incoming IP addresses. Known malicious IPs can be automatically blocked.

FieldTypeDefaultDescription
EnabledboolfalseEnables IP reputation checking.
AbuseIPDBKeystring""Your AbuseIPDB API key. Required when Enabled is true.
AutoBlockboolfalseAutomatically add IPs exceeding MinAbuseScore to the blocklist.
MinAbuseScoreint80Minimum AbuseIPDB confidence score (0-100) to consider an IP malicious.
config.gogo
1IPReputation: sentinel.IPReputationConfig{
2 Enabled: true,
3 AbuseIPDBKey: os.Getenv("ABUSEIPDB_API_KEY"),
4 AutoBlock: true,
5 MinAbuseScore: 80,
6}

API Rate Limits

AbuseIPDB has rate limits on their free plan. Sentinel caches reputation lookups to minimize API calls, but high-traffic applications should consider a paid AbuseIPDB plan or adjust the MinAbuseScore threshold.

Geolocation

The GeoConfig enables IP geolocation for enriching security events with country, city, and coordinate data. This powers the dashboard map view and the impossible travel anomaly check.

FieldTypeDefaultDescription
EnabledboolfalseEnables IP geolocation lookups.
ProviderGeoProvidersentinel.GeoIPFreeGeolocation provider. Options: sentinel.GeoIPFree (GeoLite2), sentinel.GeoIPPaid (GeoIP2).
config.gogo
1Geo: sentinel.GeoConfig{
2 Enabled: true,
3 Provider: sentinel.GeoIPFree,
4}

Alerts

The AlertConfig configures real-time alerting when security events exceed a severity threshold. Sentinel supports three alert channels: Slack, email, and generic webhooks. You can enable one or more channels simultaneously.

FieldTypeDefaultDescription
MinSeveritySeveritysentinel.SeverityHighMinimum severity level to trigger alerts. Options: SeverityLow, SeverityMedium, SeverityHigh, SeverityCritical.
Slack*SlackConfignilSlack webhook configuration. Set to enable Slack alerts.
Email*EmailConfignilEmail SMTP configuration. Set to enable email alerts.
Webhook*WebhookConfignilGeneric webhook configuration. Set to enable webhook alerts.

Slack Alerts

FieldTypeDescription
WebhookURLstringThe Slack incoming webhook URL.

Email Alerts

FieldTypeDescription
SMTPHoststringSMTP server hostname.
SMTPPortintSMTP server port (typically 587 for TLS, 465 for SSL).
UsernamestringSMTP authentication username.
PasswordstringSMTP authentication password.
Recipients[]stringList of email addresses to receive alerts.

Webhook Alerts

FieldTypeDescription
URLstringThe webhook endpoint URL. Sentinel sends a JSON POST request.
Headersmap[string]stringCustom HTTP headers to include in webhook requests (e.g., for authentication).
config.gogo
1Alerts: sentinel.AlertConfig{
2 MinSeverity: sentinel.SeverityHigh,
3
4 // Slack alerts
5 Slack: &sentinel.SlackConfig{
6 WebhookURL: "https://hooks.slack.com/services/T00/B00/xxx",
7 },
8
9 // Email alerts
10 Email: &sentinel.EmailConfig{
11 SMTPHost: "smtp.example.com",
12 SMTPPort: 587,
13 Username: "alerts@example.com",
14 Password: "smtp-password",
15 Recipients: []string{
16 "security-team@example.com",
17 "oncall@example.com",
18 },
19 },
20
21 // Webhook alerts (e.g., to a SIEM)
22 Webhook: &sentinel.WebhookConfig{
23 URL: "https://siem.example.com/api/ingest",
24 Headers: map[string]string{
25 "Authorization": "Bearer your-api-token",
26 "X-Source": "sentinel",
27 },
28 },
29}

Multiple Alert Channels

You can enable any combination of Slack, email, and webhook alerts. When an event exceeds the MinSeverity threshold, it is dispatched to all configured channels concurrently.

AI Analysis

The AIConfig enables AI-powered security analysis. When configured, Sentinel uses large language models to analyze threat patterns, generate daily security summaries, and provide natural-language insights in the dashboard. This is an optional feature — it requires an API key from one of the supported providers.

FieldTypeDefaultDescription
ProviderAIProvider(none)AI provider. Options: sentinel.Claude, sentinel.OpenAI, sentinel.Gemini.
APIKeystring""API key for the selected provider.
Modelstring(provider default)Optional model override. If empty, Sentinel uses the provider's recommended model.
DailySummaryboolfalseWhen true, generates a daily AI-powered security summary.

Supported Providers

ProviderConstantDefault Model
Anthropic Claudesentinel.ClaudeClaude Sonnet
OpenAIsentinel.OpenAIGPT-4o
Google Geminisentinel.GeminiGemini Pro
config.gogo
1// Using Anthropic Claude
2AI: &sentinel.AIConfig{
3 Provider: sentinel.Claude,
4 APIKey: os.Getenv("ANTHROPIC_API_KEY"),
5 DailySummary: true,
6}
7
8// Using OpenAI
9AI: &sentinel.AIConfig{
10 Provider: sentinel.OpenAI,
11 APIKey: os.Getenv("OPENAI_API_KEY"),
12 Model: "gpt-4o",
13}
14
15// Using Google Gemini
16AI: &sentinel.AIConfig{
17 Provider: sentinel.Gemini,
18 APIKey: os.Getenv("GEMINI_API_KEY"),
19}

AI is Optional

The AI field is a pointer (*AIConfig). When left as nil, no AI provider is initialized and no API calls are made. The dashboard AI analysis tab will show a message indicating that AI is not configured.

User Extractor

The UserExtractor is a function that extracts authenticated user context from each incoming request. Sentinel uses this information for per-user rate limiting, user-level threat profiling, and audit logging. Return nil for unauthenticated requests.

FieldTypeDefaultDescription
UserExtractorfunc(*gin.Context) *UserContextnilFunction to extract user information from a request. Return nil if no user is authenticated.

UserContext Struct

FieldTypeDescription
IDstringUnique user identifier.
EmailstringUser email address (used in alerts and dashboard display).
RolestringUser role (e.g., "admin", "user"). Used for access pattern analysis.
config.gogo
1// Extract user from JWT claims set by your auth middleware
2UserExtractor: func(c *gin.Context) *sentinel.UserContext {
3 // Option 1: From headers (proxy/gateway sets these)
4 userID := c.GetHeader("X-User-ID")
5 if userID == "" {
6 return nil // Unauthenticated request
7 }
8 return &sentinel.UserContext{
9 ID: userID,
10 Email: c.GetHeader("X-User-Email"),
11 Role: c.GetHeader("X-User-Role"),
12 }
13}
14
15// Option 2: From Gin context (your auth middleware sets these)
16UserExtractor: func(c *gin.Context) *sentinel.UserContext {
17 userID, exists := c.Get("userID")
18 if !exists {
19 return nil
20 }
21 return &sentinel.UserContext{
22 ID: userID.(string),
23 Email: c.GetString("userEmail"),
24 Role: c.GetString("userRole"),
25 }
26}

UserExtractor vs UserIDExtractor

Config.UserExtractor provides full user context (ID, email, role) for threat profiling and dashboard display. RateLimitConfig.UserIDExtractor is a simpler function that returns only a user ID string for rate limiting. If you set UserExtractor, Sentinel can derive the user ID from it automatically. You only need UserIDExtractor if you want rate limiting to use a different identifier.

Performance Monitoring

The PerformanceConfig controls request performance tracking and system resource monitoring. Performance monitoring is enabled by default. Sentinel records request durations, flags slow requests, and optionally tracks memory usage and goroutine counts.

FieldTypeDefaultDescription
Enabled*booltrueWhether performance monitoring is active. Use a *bool to explicitly disable.
SlowRequestThresholdtime.Duration2 * time.SecondRequests exceeding this duration are flagged as slow in the dashboard.
SlowQueryThresholdtime.Duration500 * time.MillisecondDatabase queries exceeding this duration are flagged as slow (used with the GORM plugin).
TrackMemoryboolfalseTrack Go runtime memory statistics and expose them in the dashboard.
TrackGoroutinesboolfalseTrack the number of active goroutines and expose in the dashboard.
config.gogo
1Performance: sentinel.PerformanceConfig{
2 SlowRequestThreshold: 1 * time.Second,
3 SlowQueryThreshold: 200 * time.Millisecond,
4 TrackMemory: true,
5 TrackGoroutines: true,
6}

Defaults (Zero Config)

When you pass an empty sentinel.Config{}, Sentinel applies the following defaults via the ApplyDefaults() method. This table summarizes the effective configuration with zero user-provided values.

SectionFieldDefault Value
DashboardEnabledtrue
DashboardPrefix/sentinel
DashboardUsernameadmin
DashboardPasswordsentinel
DashboardSecretKeysentinel-default-secret-change-me
StorageDriversentinel.SQLite
StorageDSNsentinel.db
StorageRetentionDays90
StorageMaxOpenConns10
StorageMaxIdleConns5
WAFEnabledfalse
WAFModesentinel.ModeLog
WAF RulesSQLInjectionsentinel.RuleStrict
WAF RulesXSSsentinel.RuleStrict
WAF RulesPathTraversalsentinel.RuleStrict
WAF RulesCommandInjectionsentinel.RuleStrict
WAF RulesSSRFsentinel.RuleMedium
WAF RulesXXEsentinel.RuleStrict
WAF RulesLFIsentinel.RuleStrict
WAF RulesOpenRedirectsentinel.RuleMedium
Rate LimitEnabledfalse
Rate LimitStrategysentinel.SlidingWindow
Auth ShieldEnabledfalse
Auth ShieldMaxFailedAttempts5
Auth ShieldLockoutDuration15 * time.Minute
HeadersEnabledtrue
HeadersXFrameOptionsDENY
HeadersXContentTypeOptionstrue (nosniff)
HeadersReferrerPolicystrict-origin-when-cross-origin
AnomalyEnabledfalse
AnomalySensitivitysentinel.AnomalySensitivityMedium
AnomalyLearningPeriod7 * 24 * time.Hour
IP ReputationEnabledfalse
IP ReputationMinAbuseScore80
GeoEnabledfalse
GeoProvidersentinel.GeoIPFree
AlertsMinSeveritysentinel.SeverityHigh
AI(entire section)nil (disabled)
PerformanceEnabledtrue
PerformanceSlowRequestThreshold2 * time.Second
PerformanceSlowQueryThreshold500 * time.Millisecond
main.gogo
1// Zero config — all defaults applied automatically
2r := gin.Default()
3sentinel.Mount(r, nil, sentinel.Config{})
4
5// This is equivalent to:
6sentinel.Mount(r, nil, sentinel.Config{
7 Dashboard: sentinel.DashboardConfig{
8 // Enabled: true (default)
9 // Prefix: "/sentinel"
10 // Username: "admin"
11 // Password: "sentinel"
12 },
13 Storage: sentinel.StorageConfig{
14 // Driver: sentinel.SQLite
15 // DSN: "sentinel.db"
16 // RetentionDays: 90
17 },
18 // WAF: disabled
19 // RateLimit: disabled
20 // AuthShield: disabled
21 // Headers: enabled with safe defaults
22 // Anomaly: disabled
23 // Performance: enabled
24})

Production Checklist

Before deploying to production, make sure to:
  • Change the dashboard Username, Password, and SecretKey
  • Enable the WAF with ModeBlock
  • Set up rate limiting with appropriate thresholds for your traffic
  • Configure at least one alert channel (Slack, email, or webhook)
  • Use sentinel.SQLite or sentinel.Postgres for persistent storage
  • Set StrictTransportSecurity: true if serving over HTTPS

Environment Variables Pattern

While Sentinel does not read environment variables directly, a common pattern is to read them yourself and pass them into the config struct. This keeps secrets out of your source code.

main.gogo
1import "os"
2
3config := sentinel.Config{
4 Dashboard: sentinel.DashboardConfig{
5 Username: os.Getenv("SENTINEL_USERNAME"),
6 Password: os.Getenv("SENTINEL_PASSWORD"),
7 SecretKey: os.Getenv("SENTINEL_SECRET_KEY"),
8 },
9 Storage: sentinel.StorageConfig{
10 Driver: sentinel.SQLite,
11 DSN: os.Getenv("SENTINEL_DB_PATH"),
12 },
13 AI: &sentinel.AIConfig{
14 Provider: sentinel.Claude,
15 APIKey: os.Getenv("ANTHROPIC_API_KEY"),
16 },
17 Alerts: sentinel.AlertConfig{
18 Slack: &sentinel.SlackConfig{
19 WebhookURL: os.Getenv("SLACK_WEBHOOK_URL"),
20 },
21 },
22 IPReputation: sentinel.IPReputationConfig{
23 Enabled: os.Getenv("ABUSEIPDB_API_KEY") != "",
24 AbuseIPDBKey: os.Getenv("ABUSEIPDB_API_KEY"),
25 },
26}

Never Hardcode Secrets

Always use environment variables or a secrets manager for API keys, passwords, SMTP credentials, and webhook URLs. The code examples on this page use literal strings for clarity, but production deployments should never commit secrets to source control.

Next Steps

  • WAF Deep Dive — Advanced WAF configuration, custom rules, and tuning
  • Rate Limiting — Strategies, per-route limits, and response headers
  • Auth Shield — Brute-force and credential stuffing protection
  • Anomaly Detection — Behavioral analysis and learning periods
  • Alerting — Slack, email, and webhook integration
  • AI Analysis — Claude, OpenAI, and Gemini integration
  • Dashboard — Explore the 13-page security dashboard

Built with by JB