Security Best Practices
This guide covers hardening SLOzy for production use.
HTTPS / TLS
Terminate TLS at your reverse proxy or load balancer. Recommended configuration:
# nginx example
server {
listen 443 ssl;
server_name slozy.example.com;
ssl_certificate /etc/ssl/certs/slozy.crt;
ssl_certificate_key /etc/ssl/private/slozy.key;
ssl_protocols TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}For local development, the application sets HSTS headers in internal/middleware/security.go: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Secrets Management
Never store secrets in configuration files or source code. Use environment variables:
# .env (never commit this file)
JWT_SECRET=$(openssl rand -base64 32)
POSTGRES_PASSWORD=<strong-random-password>
REDIS_PASSWORD=<strong-random-password>In production, use a secrets manager (Hashicorp Vault, AWS Secrets Manager, or Kubernetes Secrets).
JWT Secret Rotation
- Generate a 256-bit (32-byte) secret:
openssl rand -base64 32 - Configure via
JWT_SECRETenvironment variable (seeinternal/config/config.go) - Rotate secrets periodically and after any suspected compromise
- Token expiration is controlled by
JWT_EXPIRATION(default: 8h)
Database Connection Encryption
PostgreSQL SSL modes are configured via POSTGRES_SSL_MODE:
| Mode | Use Case |
|---|---|
disable | Development only |
require | Encrypted connection, no certificate validation |
verify-ca | Encrypted + CA verification |
verify-full | Encrypted + full certificate verification (recommended for production) |
POSTGRES_SSL_MODE=verify-full
POSTGRES_SSL_CERT=/path/to/client.crt
POSTGRES_SSL_KEY=/path/to/client.key
POSTGRES_SSL_ROOT_CERT=/path/to/ca.crtRate Limiting
SLOzy uses a token bucket algorithm implemented in internal/middleware/security.go. Configure via RateLimiterConfig:
| Parameter | Description | Recommended Value |
|---|---|---|
GlobalRate | Requests per minute (all users) | 1000 |
GlobalBurst | Burst size for global limiter | 2000 |
PerIPRate | Requests per minute per IP | 60 |
PerIPBurst | Burst size per IP | 100 |
Whitelist | IPs exempt from rate limiting | Internal monitoring IPs |
Blacklist | IPs always blocked | Known bad actors |
Rate limit headers (X-RateLimit-Limit, X-RateLimit-Reset) are returned on every response.
Security Headers Checklist
The middleware in internal/middleware/security.go sets these headers automatically:
| Header | Value | Purpose |
|---|---|---|
X-Frame-Options | DENY | Prevents clickjacking |
X-Content-Type-Options | nosniff | Prevents MIME sniffing |
X-XSS-Protection | 1; mode=block | Enables XSS filter |
Referrer-Policy | strict-origin-when-cross-origin | Controls referrer leakage |
Permissions-Policy | default-src 'self' | Restricts API access |
Strict-Transport-Security | max-age=31536000; includeSubDomains; preload | Enforces HTTPS |
Content-Security-Policy | default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; ... | Prevents XSS and data injection |
Cross-Origin-Opener-Policy | same-origin | Isolates cross-origin windows |
Cross-Origin-Embedder-Policy | require-corp | Restricts cross-origin resource loading |
CORS Restrictions
Configure allowed origins via CORS_ORIGINS (comma-separated). In production, never use wildcard origins:
# Good — explicit allowed origins
CORS_ENABLED=true
CORS_ORIGINS=https://app.slozy.example.com,https://admin.slozy.example.comThe CORS middleware (see internal/middleware/security.go) validates the Origin header and responds with appropriate Access-Control-Allow-* headers. Credentials are supported only for explicit (non-wildcard) origins.
API Key Management
- Generate API keys with sufficient entropy (minimum 32 bytes)
- Store hashed keys in PostgreSQL — never log or expose raw keys
- Implement key rotation: issue a new key, migrate clients, revoke the old key
- Use scoped keys with least-privilege permissions via the RBAC system
Audit Logging
- Enable structured JSON logging:
LOG_FORMAT=json - Log all authentication events (login, logout, failed attempts)
- Log SLO create/update/delete operations with user and timestamp
- Log RBAC permission changes
- Ship logs to a centralized system (ELK, Loki, Datadog) for analysis
Regular Dependency Updates
Scan for vulnerabilities and update dependencies regularly:
# Go dependencies
go list -m all | go-licenses check
go mod tidy
# Update specific packages
go get -u github.com/gin-gonic/ginUse automated dependency scanning tools (Dependabot, Renovate, or Snyk) integrated with your CI pipeline.