Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Subspace TV Configuration Server
A Docker-hosted FastAPI service that serves JSON configuration to tvOS clients. Authorized devices receive privileged configuration while unauthorized devices receive blank configuration.
Features
- Device-based authorization via custom header (
X-Device-ID) - Hot-reload of authorization list without service restart
- Docker containerization with non-root user
- CORS support for web-based clients
- Health check endpoint for monitoring
Architecture
subspace-tv/
├── src/
│ ├── __init__.py
│ ├── config.py # Pydantic settings management
│ ├── auth.py # Authorization logic with hot-reload
│ └── main.py # FastAPI application
├── bruno/
│ ├── environments/ # Bruno environment configurations
│ └── *.bru # Bruno API test requests
├── config/
│ └── authorized_devices.json # Device authorization list
├── .env.example # Environment variable template
├── Dockerfile # Container image definition
├── docker-compose.yml # Service orchestration
└── requirements.txt # Python dependencies
Local Development
Prerequisites
- Python 3.11+
- pip
Setup
-
Clone the repository and navigate to the project directory
-
Install dependencies:
pip install -r requirements.txt -
Create environment file:
cp .env.example .env -
Edit
.envwith your configuration values -
Run the development server:
uvicorn src.main:app --reload -
Access the API at
http://localhost:8000
Docker Deployment
Prerequisites
- Docker
- Docker Compose
Setup
-
Create environment file:
cp .env.example .env -
Configure
.envwith production values:CONFIG_URL=https://your-production-server.com CONFIG_PORT=8000 CONFIG_TIMEZONE=America/New_York CONFIG_UPDATE_INTERVAL=3600 -
Configure authorized devices in
config/authorized_devices.json:{ "authorized_devices": [ "tvos-device-001", "tvos-device-002" ] } -
Build and launch the container:
docker-compose up -d -
Verify the service is running:
curl http://localhost:8000/health
API Endpoints
Health Check
GET /health
Returns service health status.
Response:
{
"status": "healthy"
}
Get Configuration
GET /api/v1/config
Headers:
X-Device-ID(required): Device identifier
Response (Authorized):
{
"authorized": true,
"config": {
"url": "https://your-server.example.com",
"port": 8000,
"timezone": "America/New_York",
"update_interval": 3600
}
}
Response (Unauthorized):
{
"authorized": false,
"config": {}
}
Error Response (Missing Header):
{
"detail": "X-Device-ID header is required"
}
Status: 400 Bad Request
Usage Examples
Test with curl (Authorized Device)
curl -H "X-Device-ID: device-example-001" http://localhost:8000/api/v1/config
Test with curl (Unauthorized Device)
curl -H "X-Device-ID: unknown-device" http://localhost:8000/api/v1/config
Test with Bruno
A Bruno API collection is available in the bruno/ directory for comprehensive API testing.
Prerequisites:
- Install Bruno
Usage:
- Open Bruno
- Open Collection → Select the
bruno/directory in this project - Select environment (Local or Production)
- Run individual requests or entire collection
Available Requests:
Health Check- Verify service statusConfig - Authorized Device- Test authorized device responseConfig - Unauthorized Device- Test unauthorized device responseConfig - Missing Header- Test error handling for missing header
All requests include assertions to validate expected responses.
Authorization Management
Adding Authorized Devices
Edit config/authorized_devices.json and add device IDs:
{
"authorized_devices": [
"tvos-device-001",
"tvos-device-002",
"new-device-id"
]
}
The authorization list is automatically reloaded when the file is modified. No service restart required.
Removing Authorized Devices
Remove device IDs from config/authorized_devices.json. Changes take effect immediately.
Configuration Reference
Environment Variables
| Variable | Description | Default |
|---|---|---|
HOST |
Server bind address | 0.0.0.0 |
PORT |
Server port | 8000 |
DEBUG |
Debug mode | false |
AUTHORIZATION_FILE |
Path to authorization JSON | /app/config/authorized_devices.json |
CONFIG_URL |
URL returned to authorized devices | https://your-server.example.com |
CONFIG_PORT |
Port returned to authorized devices | 8000 |
CONFIG_TIMEZONE |
Timezone for authorized devices | America/New_York |
CONFIG_UPDATE_INTERVAL |
Update interval in seconds | 3600 |
CORS_ORIGINS |
Allowed CORS origins | ["*"] |
Security Considerations
- The service runs as a non-root user (
appuser) in the Docker container - Authorization file is mounted from the host filesystem
- Privileged configuration data is stored in environment variables
- No sensitive data is returned to unauthorized devices
- Health check endpoint is publicly accessible for orchestration
Troubleshooting
Service won't start
Check Docker logs:
docker-compose logs -f
Authorization not working
- Verify
config/authorized_devices.jsonformat is valid JSON - Check that device ID matches exactly (case-sensitive)
- Confirm file permissions allow reading by container user
Hot-reload not working
The authorization file is checked for modifications on each request. Ensure the file modification timestamp changes when editing.