15 KiB
Bitip GeoIP Service - Configuration Guide
This document provides detailed information about configuring the Bitip GeoIP Service using environment variables.
Table of Contents
Backend Configuration
The backend is configured via environment variables, typically stored in .env
at the project root or src/backend/.env
.
Configuration File Locations
- Development:
d:\Git\Home\Bitip\.env
(project root) - Production: Set via Docker environment variables or system environment
Backend Environment Variables
API Keys
FRONTEND_API_KEY=frontend-dev-key
EXTERNAL_API_KEYS=external-dev-key-1,external-dev-key-2
FRONTEND_API_KEY
- Purpose: API key used by the frontend application to authenticate with the backend
- Format: String (alphanumeric recommended)
- Required: Yes
- Security: Change this to a secure random value in production
- Example:
your-secure-frontend-api-key-here
EXTERNAL_API_KEYS
- Purpose: Comma-separated list of API keys for external clients (non-frontend applications)
- Format: Comma-separated strings
- Required: Yes (can be empty string if no external access needed)
- Security: Use strong, randomly generated keys in production
- Example:
key1-abc123,key2-def456,key3-ghi789
Frontend Origin Validation
FRONTEND_ALLOWED_ORIGINS=http://localhost:5173,http://localhost:5174,http://localhost:5175
FRONTEND_ALLOWED_ORIGINS
- Purpose: Comma-separated list of allowed origins (domains) that can use the frontend API key
- Format: Comma-separated full URLs (including protocol and port)
- Required: Yes
- Default:
http://localhost:5173
(if not set) - Security:
- Provides additional protection layer beyond rate limiting
- Validates
Origin
orReferer
header for requests using frontend API key - Only applies to frontend API key - external keys are not origin-restricted
- Note: Can be bypassed from Postman/curl, but blocks browser-based abuse from other domains
- Development Example:
http://localhost:5173,http://localhost:5174,http://localhost:5175
- Production Example:
https://your-domain.com,https://www.your-domain.com
- Use Cases:
- Prevent frontend API key theft and reuse from other websites
- Block cross-site abuse while still allowing legitimate frontend access
- Works in conjunction with CORS for defense-in-depth
- Important Notes:
- Must include protocol (
http://
orhttps://
) - Must include port if non-standard (e.g.,
http://localhost:5173
) - Requests without
Origin
orReferer
header will be rejected - Multiple origins supported for staging/production environments
- Must include protocol (
Server Configuration
PORT=5172
BASE_PATH=/geoip-ui
NODE_ENV=development
ENABLE_HTTPS_SECURITY=false
PORT
- Purpose: Port number on which the backend API server listens
- Format: Integer (1-65535)
- Required: Yes
- Default: 5172 (if not set)
- Development: 5172
- Production: Typically 5172 or 8080
- Example:
5172
BASE_PATH
- Purpose: Base URL path for all API routes and static files
- Format: String starting with
/
(or just/
for root) - Required: Yes
- Default:
/
- Use Cases:
/
- Application at root (e.g.,http://localhost:5172/api/health
)/geoip-ui
- Application under subpath (e.g.,http://localhost:5172/geoip-ui/api/health
)- Useful for reverse proxy scenarios or hosting multiple apps on same domain
- Example:
/geoip-ui
- Note: All API routes are prefixed with this path automatically
- Health Check: The
/api/health
endpoint is ALWAYS available at root (/api/health
) for Docker HEALTHCHECK compatibility, AND also at{BASE_PATH}/api/health
for consistency
NODE_ENV
- Purpose: Node.js environment mode
- Format: String
- Required: No (defaults to 'development')
- Valid Values:
development
- Enables verbose logging, detailed errorsproduction
- Optimized for performance, minimal logging
- Example:
production
LOG_LEVEL
- Purpose: Minimum logging level for both console and Seq output
- Format: String
- Required: No
- Default:
info
- Valid Values:
debug
- All logs including debug messages (very verbose, use only for troubleshooting)info
- Informational messages, warnings, and errors (recommended for development)warning
- Only warnings and errors (recommended for production)error
- Only error messages (minimal logging)
- Use Cases:
- Development:
debug
orinfo
- Full visibility into application behavior - Production:
warning
orerror
- Reduce log volume and focus on issues - Troubleshooting: Temporarily set to
debug
to diagnose problems
- Development:
- Example:
warning
- Note: Similar to Serilog's minimum level filtering in .NET
- Impact: Affects both console output and Seq structured logging
ENABLE_HTTPS_SECURITY
- Purpose: Enable/disable HTTPS security headers (Helmet middleware)
- Format: Boolean string (
true
orfalse
) - Required: No
- Default:
false
- Valid Values:
false
- Disables CSP, HSTS, COOP, and CORP headers (required for plain HTTP)true
- Enables all security headers (use when behind HTTPS reverse proxy)
- Use Cases:
- Set to
false
for development on HTTP - Set to
false
for production HTTP deployments - Set to
true
when using HTTPS with reverse proxy (nginx, Traefik, Caddy, etc.)
- Set to
- Important: Browser security policies will block resources if HTTPS security headers are enabled on plain HTTP connections. Only enable when serving over HTTPS.
- Example:
false
MaxMind Database Configuration
MAXMIND_DB_PATH=D:\\tools\\maxmind-dbs
MAXMIND_DB_PATH
- Purpose: Absolute file system path to MaxMind GeoLite2 database files
- Format: Absolute path (OS-specific)
- Required: Yes
- Windows Example:
D:\\tools\\maxmind-dbs
(note double backslashes) - Linux Example:
/usr/share/maxmind
- Docker Example:
/usr/share/maxmind
(mounted volume) - Expected Files:
GeoLite2-City.mmdb
- City-level geolocation database- Provided by separate GeoIP update service or manual download
- Note: Bitip does NOT download databases - they must be provided externally
Rate Limiting Configuration
FRONTEND_RATE_WINDOW_MS=60000
FRONTEND_RATE_MAX=30
EXTERNAL_RATE_WINDOW_MS=60000
EXTERNAL_RATE_MAX=1000
FRONTEND_RATE_WINDOW_MS
- Purpose: Time window (milliseconds) for frontend API key rate limiting
- Format: Integer (milliseconds)
- Required: Yes
- Default: 60000 (1 minute)
- Example:
60000
= 1 minute window
FRONTEND_RATE_MAX
- Purpose: Maximum number of requests allowed from frontend API key within the time window
- Format: Integer
- Required: Yes
- Default: 100
- Example:
100
= 100 requests per minute
EXTERNAL_RATE_WINDOW_MS
- Purpose: Time window (milliseconds) for external API keys rate limiting
- Format: Integer (milliseconds)
- Required: Yes
- Default: 60000 (1 minute)
- Example:
60000
= 1 minute window
EXTERNAL_RATE_MAX
- Purpose: Maximum number of requests allowed from external API keys within the time window
- Format: Integer
- Required: Yes
- Default: 1000
- Example:
1000
= 1000 requests per minute
Batch Configuration
BATCH_LIMIT=100
DEBOUNCE_MS=2000
BATCH_LIMIT
- Purpose: Maximum number of IP addresses allowed in a single batch lookup request
- Format: Integer
- Required: Yes
- Default: 100
- Example:
100
- Use Case: Prevents abuse and excessive memory usage
DEBOUNCE_MS
- Purpose: Debounce delay (milliseconds) for frontend input - delays API calls until user stops typing
- Format: Integer (milliseconds)
- Required: Yes
- Default: 2000 (2 seconds)
- Example:
2000
= 2 seconds - Note: Also configured on frontend - backend value is for reference
Seq Logging Configuration (Optional)
# SEQ_URL=http://localhost:5341
# SEQ_API_KEY=your-seq-api-key
SEQ_URL
- Purpose: URL of Seq structured logging server
- Format: HTTP/HTTPS URL
- Required: No (logging works without Seq)
- Default: Not set (Seq logging disabled)
- Example:
http://localhost:5341
- Use Case: Centralized structured logging and monitoring
SEQ_API_KEY
- Purpose: API key for authenticating with Seq server
- Format: String
- Required: No (some Seq instances don't require authentication)
- Default: Not set
- Example:
your-seq-api-key
Frontend Configuration
The frontend is configured via environment variables, typically stored in src/frontend/.env
.
Configuration File Location
- Development:
src/frontend/.env
- Production: Build-time environment variables or
.env.production
Frontend Environment Variables
VITE_API_KEY=frontend-dev-key
VITE_API_URL=http://localhost:5172/geoip-ui
VITE_DEBOUNCE_MS=2000
VITE_API_KEY
- Purpose: API key to authenticate with the backend (must match
FRONTEND_API_KEY
in backend) - Format: String
- Required: Yes
- Example:
frontend-dev-key
- Note: Must match backend's
FRONTEND_API_KEY
exactly
VITE_API_URL
- Purpose: Base URL to the backend server
- Format: HTTP/HTTPS URL
- Required: Yes
- Development Example:
http://localhost:5172/geoip-ui
- Production Example:
https://your-domain.com/geoip-ui
- Note: Must match backend's
PORT
andBASE_PATH
configuration.
VITE_DEBOUNCE_MS
- Purpose: Debounce delay (milliseconds) for IP input field - delays API calls until user stops typing
- Format: Integer (milliseconds)
- Required: Yes
- Default: 2000 (2 seconds)
- Example:
2000
= 2 seconds - Use Case: Reduces API calls while user is still typing
Development Setup
Quick Start
-
Copy
.env.example
to.env
:cp .env.example .env
-
Edit
.env
for development:FRONTEND_API_KEY=frontend-dev-key EXTERNAL_API_KEYS=external-dev-key-1,external-dev-key-2 PORT=5172 BASE_PATH=/geoip-ui NODE_ENV=development ENABLE_HTTPS_SECURITY=false MAXMIND_DB_PATH=D:\\tools\\maxmind-dbs FRONTEND_RATE_WINDOW_MS=60000 FRONTEND_RATE_MAX=30 EXTERNAL_RATE_WINDOW_MS=60000 EXTERNAL_RATE_MAX=1000 BATCH_LIMIT=100 DEBOUNCE_MS=2000
-
Edit
src/frontend/.env
:VITE_API_KEY=frontend-dev-key VITE_API_URL=http://localhost:5172/geoip-ui VITE_DEBOUNCE_MS=2000
-
Ensure MaxMind databases are available:
- Databases should be provided by separate GeoIP update service
- Place
GeoLite2-City.mmdb
in the path specified byMAXMIND_DB_PATH
-
Start development servers:
npm run dev
Development URLs
- Frontend: http://localhost:5173/
- Backend API: http://localhost:5172/geoip-ui/api/
- Health Check: http://localhost:5172/geoip-ui/api/health
Production Setup
Environment Variables
Backend (via Docker or system environment):
FRONTEND_API_KEY=<secure-random-key>
EXTERNAL_API_KEYS=<key1>,<key2>,<key3>
FRONTEND_ALLOWED_ORIGINS=https://your-domain.com,https://www.your-domain.com
PORT=5172
BASE_PATH=/
NODE_ENV=production
ENABLE_HTTPS_SECURITY=true
MAXMIND_DB_PATH=/usr/share/maxmind
FRONTEND_RATE_WINDOW_MS=60000
FRONTEND_RATE_MAX=30
EXTERNAL_RATE_WINDOW_MS=60000
EXTERNAL_RATE_MAX=1000
BATCH_LIMIT=100
DEBOUNCE_MS=2000
Frontend (build-time .env.production
):
VITE_API_KEY=<same-as-backend-FRONTEND_API_KEY>
VITE_API_URL=https://your-domain.com
VITE_DEBOUNCE_MS=2000
Security Recommendations
-
Generate Strong API Keys:
# Linux/Mac openssl rand -hex 32 # PowerShell [Convert]::ToBase64String((1..32 | ForEach-Object { Get-Random -Maximum 256 }))
-
Never Commit Real Keys:
- Keep
.env
in.gitignore
- Use
.env.example
as template only - Use secret management in production (Docker secrets, Kubernetes secrets, etc.)
- Keep
-
Configure Allowed Origins:
- Set
FRONTEND_ALLOWED_ORIGINS
to your actual production domain(s) - Include all variants (www, non-www, subdomains)
- Must use HTTPS in production:
https://your-domain.com
- This provides defense-in-depth against frontend API key theft
- Set
-
Use HTTPS in Production:
- Set
VITE_API_URL
to HTTPS endpoint - Configure reverse proxy (nginx, Traefik, etc.) for TLS termination
- Set
-
Adjust Rate Limits:
- Based on expected traffic patterns
- Monitor and adjust as needed
- Consider more aggressive limits for frontend key (e.g., 30-50 req/min)
-
Understanding Security Model:
- Frontend API Key: Semi-public, visible in browser
- Protected by: Origin validation + Rate limiting + CORS
- Can still be extracted and used from Postman/curl
- Origin validation blocks browser-based cross-site abuse
- External API Keys: Fully secret, never exposed to browser
- Protected by: Rate limiting only
- For trusted backend integrations
- Best Practice: Use aggressive rate limiting on frontend key to make abuse impractical
- Frontend API Key: Semi-public, visible in browser
Troubleshooting
Backend Won't Start
- Check
MAXMIND_DB_PATH
: Ensure path exists and containsGeoLite2-City.mmdb
- Check Port Conflicts: Ensure
PORT
is not already in use - Check Environment Loading: Verify
.env
file is at project root
Frontend Can't Connect to Backend
- Check
VITE_API_URL
: Must match backendPORT
andBASE_PATH
- Check CORS: Backend allows frontend origin by default
- Check API Key:
VITE_API_KEY
must match backendFRONTEND_API_KEY
Authentication Errors
- 401 Unauthorized: API key mismatch between frontend and backend
- Verify Keys Match: Frontend
VITE_API_KEY
=== BackendFRONTEND_API_KEY
Origin Validation Errors
-
403 Forbidden - "Origin header required": Request missing
Origin
orReferer
header- Cause: Typically happens when testing from Postman/curl with frontend API key
- Solution: Use external API key for non-browser clients, or add
Origin
header manually in testing tools
-
403 Forbidden - "Invalid origin": Frontend origin not in allowed list
- Check
FRONTEND_ALLOWED_ORIGINS
: Ensure your frontend domain is listed - Protocol Mismatch: Ensure protocol matches (
http://
vshttps://
) - Port Mismatch: Include port if non-standard (e.g.,
http://localhost:5173
) - Development: Add all Vite dev server ports (5173, 5174, 5175, etc.)
- Production: Add all domain variants (www, non-www, subdomains)
- Check
Rate Limiting Issues
- 429 Too Many Requests: Exceeded rate limits
- Increase Limits: Adjust
*_RATE_MAX
values in.env
- Check Time Window: Adjust
*_RATE_WINDOW_MS
values
Additional Resources
- Main README:
/README.md
- Breaking Changes:
/docs/BREAKING-CHANGES-FIXED.md
- Package Updates:
/docs/PACKAGE-UPDATES.md
- API Documentation: See inline code comments in
/src/backend/routes/api.ts