Includes FastAPI application with device authentication, Docker configuration, Bruno API tests, and git-based deployment scripts for Unraid. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
255 lines
5.9 KiB
Markdown
255 lines
5.9 KiB
Markdown
# 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
|
|
|
|
1. Clone the repository and navigate to the project directory
|
|
|
|
2. Install dependencies:
|
|
```bash
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
3. Create environment file:
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
4. Edit `.env` with your configuration values
|
|
|
|
5. Run the development server:
|
|
```bash
|
|
uvicorn src.main:app --reload
|
|
```
|
|
|
|
6. Access the API at `http://localhost:8000`
|
|
|
|
## Docker Deployment
|
|
|
|
### Prerequisites
|
|
|
|
- Docker
|
|
- Docker Compose
|
|
|
|
### Setup
|
|
|
|
1. Create environment file:
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
2. Configure `.env` with production values:
|
|
```env
|
|
CONFIG_URL=https://your-production-server.com
|
|
CONFIG_PORT=8000
|
|
CONFIG_TIMEZONE=America/New_York
|
|
CONFIG_UPDATE_INTERVAL=3600
|
|
```
|
|
|
|
3. Configure authorized devices in `config/authorized_devices.json`:
|
|
```json
|
|
{
|
|
"authorized_devices": [
|
|
"tvos-device-001",
|
|
"tvos-device-002"
|
|
]
|
|
}
|
|
```
|
|
|
|
4. Build and launch the container:
|
|
```bash
|
|
docker-compose up -d
|
|
```
|
|
|
|
5. Verify the service is running:
|
|
```bash
|
|
curl http://localhost:8000/health
|
|
```
|
|
|
|
## API Endpoints
|
|
|
|
### Health Check
|
|
|
|
**GET** `/health`
|
|
|
|
Returns service health status.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"status": "healthy"
|
|
}
|
|
```
|
|
|
|
### Get Configuration
|
|
|
|
**GET** `/api/v1/config`
|
|
|
|
**Headers:**
|
|
- `X-Device-ID` (required): Device identifier
|
|
|
|
**Response (Authorized):**
|
|
```json
|
|
{
|
|
"authorized": true,
|
|
"config": {
|
|
"url": "https://your-server.example.com",
|
|
"port": 8000,
|
|
"timezone": "America/New_York",
|
|
"update_interval": 3600
|
|
}
|
|
}
|
|
```
|
|
|
|
**Response (Unauthorized):**
|
|
```json
|
|
{
|
|
"authorized": false,
|
|
"config": {}
|
|
}
|
|
```
|
|
|
|
**Error Response (Missing Header):**
|
|
```json
|
|
{
|
|
"detail": "X-Device-ID header is required"
|
|
}
|
|
```
|
|
Status: `400 Bad Request`
|
|
|
|
## Usage Examples
|
|
|
|
### Test with curl (Authorized Device)
|
|
|
|
```bash
|
|
curl -H "X-Device-ID: device-example-001" http://localhost:8000/api/v1/config
|
|
```
|
|
|
|
### Test with curl (Unauthorized Device)
|
|
|
|
```bash
|
|
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](https://www.usebruno.com/)
|
|
|
|
**Usage:**
|
|
1. Open Bruno
|
|
2. Open Collection → Select the `bruno/` directory in this project
|
|
3. Select environment (Local or Production)
|
|
4. Run individual requests or entire collection
|
|
|
|
**Available Requests:**
|
|
- `Health Check` - Verify service status
|
|
- `Config - Authorized Device` - Test authorized device response
|
|
- `Config - Unauthorized Device` - Test unauthorized device response
|
|
- `Config - 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:
|
|
|
|
```json
|
|
{
|
|
"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:
|
|
```bash
|
|
docker-compose logs -f
|
|
```
|
|
|
|
### Authorization not working
|
|
|
|
1. Verify `config/authorized_devices.json` format is valid JSON
|
|
2. Check that device ID matches exactly (case-sensitive)
|
|
3. 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.
|