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:

    pip install -r requirements.txt
    
  3. Create environment file:

    cp .env.example .env
    
  4. Edit .env with your configuration values

  5. Run the development server:

    uvicorn src.main:app --reload
    
  6. Access the API at http://localhost:8000

Docker Deployment

Prerequisites

  • Docker
  • Docker Compose

Setup

  1. Create environment file:

    cp .env.example .env
    
  2. Configure .env with production values:

    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:

    {
      "authorized_devices": [
        "tvos-device-001",
        "tvos-device-002"
      ]
    }
    
  4. Build and launch the container:

    docker-compose up -d
    
  5. 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:

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:

{
  "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

  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.

Description
No description provided
Readme 40 KiB
Languages
Python 49.7%
Shell 45.9%
Dockerfile 4.4%