Premium Documentation β Everything you need to configure SkysPy for any environment
π
# Minimum Required Configuration
DJANGO_SECRET_KEY=your-secure-random-key-here
FEEDER_LAT=47.9377
FEEDER_LON=-121.9687
AUTH_MODE=hybrid
| Setting | Purpose | Get Started |
|---|
π DJANGO_SECRET_KEY | Cryptographic security | python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())" |
π FEEDER_LAT/LON | Your antenna location | Use GPS coordinates in decimal degrees |
π AUTH_MODE | Access control | public / private / hybrid |
ποΈ DATABASE_URL | Database connection | postgresql://user:pass@host:5432/db |
flowchart TD
subgraph Sources["π Configuration Sources"]
ENV["π§ .env File"]
DOCKER["π³ Docker Environment"]
RUNTIME["β‘ Runtime / Admin"]
end
subgraph Layers["ποΈ Configuration Layers"]
ENV --> DJANGO["π Django Settings"]
DOCKER --> DJANGO
DJANGO --> COMPOSE["π¦ Docker Compose"]
COMPOSE --> RUNTIME
end
subgraph Outputs["π― Applied To"]
RUNTIME --> API["π API Server"]
RUNTIME --> CELERY["β° Celery Workers"]
RUNTIME --> WS["π‘ Socket.IO Channels"]
RUNTIME --> FRONTEND["π» Frontend"]
end
style ENV fill:#e1f5fe
style DJANGO fill:#fff3e0
style COMPOSE fill:#f3e5f5
style RUNTIME fill:#e8f5e9
- Copy
.env.example to .env
- Set
DJANGO_SECRET_KEY to a secure random value
- Configure
FEEDER_LAT and FEEDER_LON for your antenna location
- Set
AUTH_MODE based on your security requirements
- Run
docker-compose up -d
β οΈ
| Variable | Description | Default | Status |
|---|
DEBUG | Enable Django debug mode | False | βͺ Optional |
DJANGO_SECRET_KEY | Django secret key for cryptographic signing | None | π΄ Required |
ALLOWED_HOSTS | Comma-separated list of allowed host/domain names | localhost,127.0.0.1,[::1] | βͺ Optional |
DJANGO_LOG_LEVEL | Log level for Django framework | INFO | βͺ Optional |
BUILD_MODE | Set to True during Docker builds to skip external connections | False | βͺ Optional |
DJANGO_SETTINGS_MODULE | Python path to settings module | skyspy.settings | βͺ Optional |
π‘
| Variable | Description | Default | Status |
|---|
DJANGO_SUPERUSER_USERNAME | Username for auto-created admin account | admin | βͺ Optional |
DJANGO_SUPERUSER_EMAIL | Email for auto-created admin account | [email protected] | βͺ Optional |
DJANGO_SUPERUSER_PASSWORD | Password for auto-created admin account | changeme | π‘ Change in production |
flowchart LR
subgraph Modes["π AUTH_MODE Options"]
PUBLIC["π public<br/>No auth required"]
HYBRID["π hybrid<br/>Per-feature control"]
PRIVATE["π private<br/>Full authentication"]
end
PUBLIC -.->|"Development"| DEV["π» Local Dev"]
HYBRID -.->|"Recommended"| PROD["π Production"]
PRIVATE -.->|"High Security"| ENT["π’ Enterprise"]
style PUBLIC fill:#fff9c4
style HYBRID fill:#c8e6c9
style PRIVATE fill:#ffcdd2
| Mode | Description | Use Case |
|---|
π public | No authentication required for any endpoint | Local/development use |
π hybrid | Per-feature access control with granular permissions | Production (recommended) |
π private | Authentication required for all endpoints | Maximum security |
| Variable | Description | Default | Status |
|---|
AUTH_MODE | Authentication mode | hybrid | βͺ Optional |
LOCAL_AUTH_ENABLED | Enable local username/password authentication | True | βͺ Optional |
API_KEY_ENABLED | Enable API key authentication | True | βͺ Optional |
| Variable | Description | Default | Status |
|---|
JWT_SECRET_KEY | Secret key for JWT signing | Uses DJANGO_SECRET_KEY | π‘ Recommended |
JWT_ACCESS_TOKEN_LIFETIME_MINUTES | Access token validity period | 60 | βͺ Optional |
JWT_REFRESH_TOKEN_LIFETIME_DAYS | Refresh token validity period | 2 | βͺ Optional |
JWT_AUTH_COOKIE | Use httpOnly cookie for refresh token storage | False | βͺ Optional |
π‘
Enable Single Sign-On with identity providers like Keycloak, Authentik, Azure AD, Okta, or Auth0.
| Variable | Description | Default | Status |
|---|
OIDC_ENABLED | Enable OIDC authentication | False | βͺ Optional |
OIDC_PROVIDER_NAME | Display name shown on login button | SSO | βͺ Optional |
OIDC_PROVIDER_URL | Authorization server base URL | None | π΄ If OIDC enabled |
OIDC_CLIENT_ID | Client ID from your OIDC provider | None | π΄ If OIDC enabled |
OIDC_CLIENT_SECRET | Client secret from your OIDC provider | None | π΄ If OIDC enabled |
OIDC_SCOPES | Space-separated OAuth scopes to request | openid profile email groups | βͺ Optional |
OIDC_DEFAULT_ROLE | Default role for new OIDC users | viewer | βͺ Optional |
π OIDC Provider Configuration Examples
OIDC_ENABLED=True
OIDC_PROVIDER_NAME=Keycloak
OIDC_PROVIDER_URL=https://keycloak.example.com/realms/skyspy
OIDC_CLIENT_ID=skyspy-client
OIDC_CLIENT_SECRET=<client-secret>
OIDC_ENABLED=True
OIDC_PROVIDER_NAME=Authentik
OIDC_PROVIDER_URL=https://authentik.example.com/application/o/skyspy
OIDC_CLIENT_ID=<client-id>
OIDC_CLIENT_SECRET=<client-secret>
OIDC_ENABLED=True
OIDC_PROVIDER_NAME=Microsoft
OIDC_PROVIDER_URL=https://login.microsoftonline.com/{tenant-id}/v2.0
OIDC_CLIENT_ID=<application-client-id>
OIDC_CLIENT_SECRET=<client-secret-value>
OIDC_SCOPES=openid profile email
| Variable | Description | Default | Status |
|---|
DATABASE_URL | PostgreSQL connection URL | postgresql://adsb:adsb@postgres:5432/adsb | βͺ Optional |
POSTGRES_USER | PostgreSQL username (Docker Compose) | adsb | βͺ Optional |
POSTGRES_PASSWORD | PostgreSQL password (Docker Compose) | adsb | βͺ Optional |
POSTGRES_DB | PostgreSQL database name (Docker Compose) | adsb | βͺ Optional |
| Variable | Description | Default | Status |
|---|
REDIS_URL | Redis connection URL for Celery, cache, and channels | redis://redis:6379/0 | βͺ Optional |
| Variable | Description | Default | Status |
|---|
CACHE_TTL | Default cache time-to-live in seconds | 5 | βͺ Optional |
UPSTREAM_API_MIN_INTERVAL | Minimum seconds between upstream API calls | 60 | βͺ Optional |
π
| Variable | Description | Default | Status |
|---|
FEEDER_LAT | Latitude of your antenna position (decimal degrees) | 47.9377 | π‘ Recommended |
FEEDER_LON | Longitude of your antenna position (decimal degrees) | -121.9687 | π‘ Recommended |
ULTRAFEEDER_HOST | Hostname of Ultrafeeder/readsb/tar1090 service | ultrafeeder | βͺ Optional |
ULTRAFEEDER_PORT | HTTP port of Ultrafeeder service | 80 | βͺ Optional |
DUMP978_HOST | Hostname of dump978 UAT service | dump978 | βͺ Optional |
DUMP978_PORT | HTTP port of dump978 service | 80 | βͺ Optional |
| Variable | Description | Default | Status |
|---|
POLLING_INTERVAL | Seconds between ADS-B polls from data sources | 2 | βͺ Optional |
DB_STORE_INTERVAL | Seconds between database position writes | 5 | βͺ Optional |
SESSION_TIMEOUT_MINUTES | Minutes of inactivity before aircraft session ends | 30 | βͺ Optional |
β οΈ
| Variable | Description | Default | Status |
|---|
SAFETY_MONITORING_ENABLED | Enable safety event detection and alerts | True | βͺ Optional |
SAFETY_VS_CHANGE_THRESHOLD | Vertical speed change threshold (ft/min) | 2000 | βͺ Optional |
SAFETY_VS_EXTREME_THRESHOLD | Extreme vertical speed threshold (ft/min) | 6000 | βͺ Optional |
SAFETY_PROXIMITY_NM | Proximity alert distance in nautical miles | 0.5 | βͺ Optional |
SAFETY_ALTITUDE_DIFF_FT | Altitude difference for proximity alerts (feet) | 500 | βͺ Optional |
SAFETY_CLOSURE_RATE_KT | Closure rate threshold for alerts (knots) | 200 | βͺ Optional |
SAFETY_TCAS_VS_THRESHOLD | TCAS vertical speed threshold (ft/min) | 1500 | βͺ Optional |
| Variable | Description | Default | Status |
|---|
PROXIMITY_ALERT_NM | Default proximity alert radius in nautical miles | 5.0 | βͺ Optional |
WATCH_ICAO_LIST | Comma-separated ICAO hex codes to watch | Empty | βͺ Optional |
WATCH_FLIGHT_LIST | Comma-separated flight numbers to watch | Empty | βͺ Optional |
ALERT_MILITARY | Generate alerts for military aircraft | True | βͺ Optional |
ALERT_EMERGENCY | Generate alerts for emergency squawks (7500, 7600, 7700) | True | βͺ Optional |
SkysPy uses Apprise for multi-platform notifications.
| Variable | Description | Default | Status |
|---|
APPRISE_URLS | Comma-separated Apprise notification URLs | Empty | βͺ Optional |
NOTIFICATION_COOLDOWN | Seconds between duplicate notifications | 300 | βͺ Optional |
π Apprise URL Examples
# Telegram
APPRISE_URLS=telegram://bot_token/chat_id
# Discord
APPRISE_URLS=discord://webhook_id/webhook_token
# Slack
APPRISE_URLS=slack://token_a/token_b/token_c
# Pushover
APPRISE_URLS=pushover://user_key/app_token
# Email
APPRISE_URLS=email://user:[email protected]
# Multiple services (comma-separated)
APPRISE_URLS=telegram://...,discord://...,email://...
| Variable | Description | Default | Status |
|---|
ACARS_ENABLED | Enable ACARS message processing | True | βͺ Optional |
ACARS_PORT | UDP port for ACARS messages | 5555 | βͺ Optional |
VDLM2_PORT | UDP port for VDL Mode 2 messages | 5556 | βͺ Optional |
| Variable | Description | Default | Status |
|---|
RADIO_ENABLED | Enable radio transmission processing | True | βͺ Optional |
RADIO_AUDIO_DIR | Directory for audio file storage | /data/radio | βͺ Optional |
RADIO_MAX_FILE_SIZE_MB | Maximum audio file size in megabytes | 50 | βͺ Optional |
RADIO_RETENTION_DAYS | Days to retain audio files | 7 | βͺ Optional |
RADIO_S3_PREFIX | S3 prefix for radio file storage | radio-transmissions | βͺ Optional |
| Variable | Description | Default | Status |
|---|
TRANSCRIPTION_ENABLED | Enable audio transcription | False | βͺ Optional |
TRANSCRIPTION_SERVICE_URL | External transcription service URL | None | π΄ If using external |
TRANSCRIPTION_MODEL | Model to use for transcription | None | βͺ Optional |
TRANSCRIPTION_API_KEY | API key for transcription service | None | π΄ If using external |
| Variable | Description | Default | Status |
|---|
WHISPER_ENABLED | Enable local Whisper transcription | False | βͺ Optional |
WHISPER_URL | URL of Whisper service | http://whisper:9000 | βͺ Optional |
π― ATC-Whisper Configuration (Specialized ATC Transcription)
| Variable | Description | Default | Status |
|---|
ATC_WHISPER_ENABLED | Enable ATC-optimized Whisper transcription | False | βͺ Optional |
ATC_WHISPER_MAX_CONCURRENT | Maximum concurrent transcription jobs | 2 | βͺ Optional |
ATC_WHISPER_SEGMENT_BY_VAD | Use voice activity detection for segmentation | True | βͺ Optional |
ATC_WHISPER_PREPROCESS | Enable audio preprocessing | True | βͺ Optional |
ATC_WHISPER_NOISE_REDUCE | Enable noise reduction | True | βͺ Optional |
ATC_WHISPER_POSTPROCESS | Enable post-processing cleanup | True | βͺ Optional |
Optional LLM integration for improved callsign extraction accuracy from transcripts.
| Variable | Description | Default | Status |
|---|
LLM_ENABLED | Enable LLM-enhanced transcript analysis | False | βͺ Optional |
LLM_API_URL | OpenAI-compatible API endpoint | https://api.openai.com/v1 | βͺ Optional |
LLM_API_KEY | API key (not needed for local Ollama) | Empty | π΄ If using cloud |
LLM_MODEL | Model to use | gpt-4o-mini | βͺ Optional |
LLM_TIMEOUT | Request timeout in seconds | 30 | βͺ Optional |
LLM_MAX_RETRIES | Maximum retries on failure | 3 | βͺ Optional |
LLM_CACHE_TTL | Cache TTL in seconds | 3600 | βͺ Optional |
LLM_MAX_TOKENS | Maximum response tokens | 500 | βͺ Optional |
LLM_TEMPERATURE | Temperature (lower = more deterministic) | 0.1 | βͺ Optional |
π LLM Provider Examples
LLM_ENABLED=True
LLM_API_URL=https://api.openai.com/v1
LLM_API_KEY=sk-xxx
LLM_MODEL=gpt-4o-mini
LLM_ENABLED=True
LLM_API_URL=http://localhost:11434/v1
LLM_API_KEY=ollama
LLM_MODEL=llama3.2
LLM_ENABLED=True
LLM_API_URL=https://openrouter.ai/api/v1
LLM_API_KEY=sk-or-xxx
LLM_MODEL=anthropic/claude-3-haiku
| Variable | Description | Default | Status |
|---|
PHOTO_CACHE_ENABLED | Enable aircraft photo caching | True | βͺ Optional |
PHOTO_CACHE_DIR | Directory for cached photos | /data/photos | βͺ Optional |
PHOTO_AUTO_DOWNLOAD | Automatically download photos for tracked aircraft | True | βͺ Optional |
| Variable | Description | Default | Status |
|---|
S3_ENABLED | Enable S3 storage for photos and audio | False | βͺ Optional |
S3_BUCKET | S3 bucket name | Empty | π΄ If S3 enabled |
S3_REGION | AWS region | us-east-1 | βͺ Optional |
S3_ACCESS_KEY | AWS access key ID | None | π΄ If S3 enabled |
S3_SECRET_KEY | AWS secret access key | None | π΄ If S3 enabled |
S3_ENDPOINT_URL | Custom endpoint URL for S3-compatible storage | None | βͺ Optional |
S3_PREFIX | Prefix for photo storage | aircraft-photos | βͺ Optional |
S3_PUBLIC_URL | Public URL for serving files | None | βͺ Optional |
| Variable | Description | Default | Status |
|---|
OPENSKY_DB_ENABLED | Enable OpenSky aircraft database lookup | True | βͺ Optional |
OPENSKY_DB_PATH | Path to OpenSky CSV database file | /data/opensky/aircraft-database.csv | βͺ Optional |
π External API Integrations
| Variable | Description | Default | Status |
|---|
CHECKWX_ENABLED | Enable CheckWX weather data (3,000 req/day free) | False | βͺ Optional |
CHECKWX_API_KEY | CheckWX API key | Empty | π΄ If enabled |
| Variable | Description | Default | Status |
|---|
AVWX_ENABLED | Enable AVWX weather data (unlimited basic) | True | βͺ Optional |
AVWX_API_KEY | AVWX API key (optional, higher rate limits) | Empty | βͺ Optional |
| Variable | Description | Default | Status |
|---|
OPENAIP_ENABLED | Enable OpenAIP airspace data | False | βͺ Optional |
OPENAIP_API_KEY | OpenAIP API key | Empty | π΄ If enabled |
| Variable | Description | Default | Status |
|---|
OPENSKY_LIVE_ENABLED | Enable OpenSky live data (4,000 credits/day free) | False | βͺ Optional |
OPENSKY_USERNAME | OpenSky Network username | Empty | π΄ If enabled |
OPENSKY_PASSWORD | OpenSky Network password | Empty | π΄ If enabled |
| Variable | Description | Default | Status |
|---|
ADSBX_LIVE_ENABLED | Enable ADS-B Exchange live data via RapidAPI | False | βͺ Optional |
ADSBX_RAPIDAPI_KEY | RapidAPI key for ADS-B Exchange | Empty | π΄ If enabled |
| Variable | Description | Default | Status |
|---|
AVIATIONSTACK_ENABLED | Enable Aviationstack schedules (100 req/month free) | False | βͺ Optional |
AVIATIONSTACK_API_KEY | Aviationstack API key | Empty | π΄ If enabled |
| Variable | Description | Default | Status |
|---|
SENTRY_DSN | Sentry DSN for error tracking | Empty | βͺ Optional |
SENTRY_ENVIRONMENT | Environment tag (e.g., production, staging) | development | βͺ Optional |
SENTRY_TRACES_SAMPLE_RATE | Performance tracing sample rate (0.0 to 1.0) | 0.1 | βͺ Optional |
SENTRY_PROFILES_SAMPLE_RATE | Profiling sample rate (0.0 to 1.0) | 0.1 | βͺ Optional |
| Variable | Description | Default | Status |
|---|
PROMETHEUS_ENABLED | Enable Prometheus metrics endpoint | True | βͺ Optional |
| Variable | Description | Default | Status |
|---|
CORS_ALLOWED_ORIGINS | Comma-separated list of allowed CORS origins | Empty | βͺ Optional |
CORS_ALLOWED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000,https://skyspy.example.com
| Variable | Description | Default | Status |
|---|
FORCE_SECURE_COOKIES | Force secure cookie flags in debug mode | False | βͺ Optional |
The main settings file provides the default configuration for most deployments.
| Characteristic | Value |
|---|
| Polling Interval | 2 seconds |
| Database Store Interval | 5 seconds |
| All Features | Enabled |
| Cache TTL | 5 seconds |
| Logging Level | INFO (DEBUG when DEBUG=True) |
π‘
# Enable RPi settings via environment
export DJANGO_SETTINGS_MODULE=skyspy.settings_rpi
# Or in Docker Compose
environment:
- DJANGO_SETTINGS_MODULE=skyspy.settings_rpi
π Raspberry Pi Optimization Details
| Setting | Standard | RPi-Optimized | Impact |
|---|
POLLING_INTERVAL | 2s | 3s | ~33% CPU reduction |
DB_STORE_INTERVAL | 5s | 10s | 50% fewer DB writes |
CACHE_TTL | 5s | 10s | Fewer cache refreshes |
MAX_SEEN_AIRCRAFT | 10,000 | 5,000 | 50% memory savings |
ACARS_BUFFER_SIZE | 50 | 30 | Reduced buffer memory |
WEBSOCKET_CAPACITY | 1,500 | 1,000 | Lower memory usage |
CONN_MAX_AGE | 60s | 120s | Fewer DB connections |
| Task | Standard | RPi-Optimized |
|---|
| Flight pattern/geographic stats | 2 min | 10 min |
| Time comparison stats | 5 min | 15 min |
| Tracking quality stats | 2 min | 10 min |
| Engagement stats | 2 min | 10 min |
| Antenna analytics | 5 min | 10 min |
| ACARS stats | 60s | 2 min |
| Stats cache | 60s | 90s |
| Safety stats | 30s | 60s |
| Data Type | Standard | RPi |
|---|
| Sighting retention | 30 days | 7 days |
| Session retention | 90 days | 14 days |
| Alert history | 30 days | 7 days |
| Antenna snapshots | 7 days | 3 days |
| Limit | Value |
|---|
MAX_HISTORY_HOURS | 72 hours |
MAX_QUERY_RESULTS | 10,000 |
MAX_STATS_SAMPLE_SIZE | 1,000 |
The frontend stores user preferences in browser localStorage via /web/src/utils/config.js.
{
apiBaseUrl: '', // Always empty (uses relative URLs)
mapMode: 'pro', // Map display mode
mapDarkMode: true, // Dark mode enabled
browserNotifications: false, // Browser notification permission
shortTrackLength: 15, // Track trail positions (5-50)
}
| Mode | Description |
|---|
π‘ radar | Classic radar sweep display |
π₯οΈ crt | Retro CRT monitor aesthetic |
βοΈ pro | Professional aviation display |
πΊοΈ map | Standard map view |
π¨ Default Overlay Settings
{
aircraft: true, // Aircraft icons
vors: true, // VOR navigation aids
airports: true, // Airport locations
airspace: true, // Airspace boundaries
metars: false, // Weather observations
pireps: false, // Pilot reports
// Terrain overlays (pro mode)
water: false,
counties: false,
states: false,
countries: false,
// Aviation overlays (pro mode)
usArtcc: false, // US ARTCC boundaries
usRefueling: false, // US A2A refueling tracks
ukMilZones: false, // UK military zones
euMilAwacs: false, // EU military AWACS orbits
trainingAreas: false // IFT/USAFA training areas
}
| Variable | Description | Default |
|---|
VITE_API_TARGET | Backend API URL for proxy | http://localhost:8000 |
NODE_ENV | Node environment | development |
DASHBOARD_PORT | Frontend dev server port | 3000 |
π Complete Feature Flag Reference
| Feature | Environment Variable | Default |
|---|
| Safety Monitoring | SAFETY_MONITORING_ENABLED | True |
| ACARS Processing | ACARS_ENABLED | True |
| Photo Caching | PHOTO_CACHE_ENABLED | True |
| Auto Photo Download | PHOTO_AUTO_DOWNLOAD | True |
| Radio Processing | RADIO_ENABLED | True |
| OpenSky Database | OPENSKY_DB_ENABLED | True |
| Prometheus | PROMETHEUS_ENABLED | True |
| Local Auth | LOCAL_AUTH_ENABLED | True |
| API Key Auth | API_KEY_ENABLED | True |
| Feature | Environment Variable | Default |
|---|
| Transcription | TRANSCRIPTION_ENABLED | False |
| Whisper | WHISPER_ENABLED | False |
| ATC Whisper | ATC_WHISPER_ENABLED | False |
| LLM Analysis | LLM_ENABLED | False |
| S3 Storage | S3_ENABLED | False |
| OIDC/SSO | OIDC_ENABLED | False |
| Feature | Environment Variable | Default |
|---|
| AVWX Weather | AVWX_ENABLED | True |
| CheckWX Weather | CHECKWX_ENABLED | False |
| OpenAIP Airspace | OPENAIP_ENABLED | False |
| OpenSky Live | OPENSKY_LIVE_ENABLED | False |
| ADS-B Exchange | ADSBX_LIVE_ENABLED | False |
| Aviationstack | AVIATIONSTACK_ENABLED | False |
π‘ Socket.IO Rate Limiting
Control Socket.IO broadcast frequencies to prevent client overload:
WS_RATE_LIMITS = {
'aircraft:update': 10, # Max 10 Hz
'aircraft:position': 5, # Max 5 Hz for position-only
'aircraft:delta': 10, # Max 10 Hz for delta updates
'stats:update': 0.5, # Max 0.5 Hz (2s minimum)
'default': 5, # Default rate limit
}
π¦ Message Batching
Configure message batching for efficiency:
WS_BATCH_WINDOW_MS = 50 # Collect messages for 50ms
WS_MAX_BATCH_SIZE = 50 # Maximum messages per batch
WS_IMMEDIATE_TYPES = [ # Types that bypass batching
'alert', 'safety', 'emergency',
'aircraft:update', 'aircraft:new', 'aircraft:position',
]
β° Celery Worker Configuration
# docker-compose.yml
celery-worker:
command: >
celery -A skyspy worker
--loglevel=info
--concurrency=100 # Adjust based on resources
--queues=polling,default,database,transcription,notifications
--pool=gevent # Greenlet-based concurrency
| Queue | Tasks | Priority |
|---|
polling | Aircraft polling, stats updates | High |
default | General tasks | Normal |
database | External DB sync, cleanup | Low |
transcription | Audio transcription | Low |
notifications | Alert notifications | Normal |
low_priority | Analytics, cleanup | Lowest |
π΄ Redis Configuration
redis:
command: >
redis-server
--appendonly yes
--maxmemory 256mb
--maxmemory-policy allkeys-lru
π‘ Channel Layer Configuration
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
'hosts': [REDIS_URL],
'capacity': 1500, # Message capacity per channel
'expiry': 60, # Message expiry (seconds)
'group_expiry': 300, # Group membership expiry
},
},
}
ποΈ Database Connection Pooling
DATABASES = {
'default': {
'CONN_MAX_AGE': 60, # Connection lifetime (seconds)
'OPTIONS': {
'connect_timeout': 10, # Connection timeout
},
}
}
For high-load deployments, consider PgBouncer:
pgbouncer:
environment:
- POOL_MODE=transaction
- MAX_CLIENT_CONN=1000
- DEFAULT_POOL_SIZE=20
| Logger | Debug Mode | Production |
|---|
root | INFO | INFO |
django | Configurable via DJANGO_LOG_LEVEL | INFO |
skyspy | DEBUG | INFO |
celery | INFO | INFO |
π Logging Configuration
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
'style': '{',
},
'simple': {
'format': '{levelname} {message}',
'style': '{',
},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'simple',
},
},
'loggers': {
'django': {
'level': os.environ.get('DJANGO_LOG_LEVEL', 'INFO'),
},
'skyspy': {
'level': 'DEBUG' if DEBUG else 'INFO',
},
'celery': {
'level': 'INFO',
},
},
}
# settings_rpi.py
LOGGING['root']['level'] = 'WARNING'
LOGGING['loggers']['skyspy']['level'] = 'INFO'
LOGGING['loggers']['django']['level'] = 'WARNING'
When DEBUG=True:
- Django debug toolbar enabled
- Detailed error pages
- Auto-generated secret key (development only)
- Default
ALLOWED_HOSTS includes localhost
skyspy logger set to DEBUG level
- Stack traces in API error responses
# Docker Compose logs
docker-compose logs -f api
docker-compose logs -f celery-worker
docker-compose logs -f celery-beat
# Filter by service
docker-compose logs -f api celery-worker
# Last 100 lines
docker-compose logs --tail=100 api
| User Type | Rate Limit |
|---|
| Anonymous | 100 requests/minute |
| Authenticated | 1,000 requests/minute |
βοΈ Rate Limiting Configuration
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle',
],
'DEFAULT_THROTTLE_RATES': {
'anon': '100/minute',
'user': '1000/minute',
}
}
β οΈ
# Django Secret Key
python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
# JWT Secret Key (use a different value)
python -c "import secrets; print(secrets.token_urlsafe(64))"
| Profile | Description | Usage |
|---|
| (default) | Core services: api, postgres, redis, celery | docker-compose up -d |
acars | Include ACARS UDP listener | docker-compose --profile acars up -d |
dev | Development with hot-reload | docker-compose -f docker-compose.test.yaml --profile dev up |
test | Run test suite | docker-compose -f docker-compose.test.yaml --profile test up |
| Volume | Path | Description |
|---|
postgres_data | /var/lib/postgresql/data | PostgreSQL database |
redis_data | /data | Redis persistence |
photo_cache | /data/photos | Cached aircraft photos |
radio_data | /data/radio | Audio transmissions |
opensky_data | /data/opensky | OpenSky database |
Default Docker network: skyspy-network
| Service | Internal Port | Default External Port |
|---|
| API | 8000 | $API_PORT (8000) |
| PostgreSQL | 5432 | Not exposed |
| Redis | 6379 | Not exposed |
| ACARS (UDP) | 5555 | $ACARS_PORT (5555) |
| VDL2 (UDP) | 5556 | $VDLM2_PORT (5556) |
π¨ Common Issues and Solutions
ImproperlyConfigured: DJANGO_SECRET_KEY must be set in production
Solution: Set DJANGO_SECRET_KEY environment variable.
could not connect to server: Connection refused
Solution: Ensure PostgreSQL container is healthy before starting API.
redis.exceptions.ConnectionError
Solution: Check REDIS_URL and ensure Redis container is running.
Access-Control-Allow-Origin header missing
Solution: Add your frontend origin to CORS_ALLOWED_ORIGINS.
Token is invalid or expired
Solution: Ensure JWT_SECRET_KEY is consistent across all services.