Add Nginx web server for browsing recordings
Serves the recordings directory over HTTP with autoindex on port 8080. Users can browse by date and play MP3 files natively in the browser. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,3 +8,13 @@ services:
|
||||
volumes:
|
||||
- ./rtl_airband.conf:/app/rtl_airband.conf:ro
|
||||
- /home/m/recordings:/recordings
|
||||
|
||||
web:
|
||||
image: nginx:alpine
|
||||
container_name: sdr-web
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "8080:80"
|
||||
volumes:
|
||||
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
- /home/m/recordings:/recordings:ro
|
||||
|
||||
8
nginx.conf
Normal file
8
nginx.conf
Normal file
@@ -0,0 +1,8 @@
|
||||
server {
|
||||
listen 80;
|
||||
|
||||
location / {
|
||||
alias /recordings/;
|
||||
autoindex on;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-03-19
|
||||
@@ -0,0 +1,34 @@
|
||||
## Context
|
||||
|
||||
RTLSDR-Airband records CB transmissions as MP3 files into `/home/m/recordings/` on the Pi, organized by channel subdirectories with dated subdirectories inside. The recorder runs as a Docker container via `docker-compose.yml`.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- Serve the recordings directory over HTTP with browsable directory listings
|
||||
- Allow MP3 playback via the browser's native audio handling
|
||||
- Deploy as a Docker container alongside the existing `sdr-recorder` service
|
||||
|
||||
**Non-Goals:**
|
||||
- Custom web UI, styling, or JavaScript
|
||||
- Authentication (local network only)
|
||||
- Modifying, uploading, or deleting recordings
|
||||
- Live streaming or transcription
|
||||
|
||||
## Decisions
|
||||
|
||||
### Use Nginx with HTML autoindex, no custom frontend
|
||||
|
||||
**Decision**: Use `nginx:alpine` with `autoindex on` to serve the recordings directory. No custom HTML, JS, or CSS.
|
||||
|
||||
**Rationale**: Nginx's built-in directory listing is fully functional for browsing channel/date directories. Modern browsers play MP3 files natively when clicked. This requires only an Nginx config file and a docker-compose service — zero application code.
|
||||
|
||||
**Alternatives considered**:
|
||||
- **Custom SPA frontend**: Adds complexity (build tools, JS code) for marginal UX improvement over native directory listing.
|
||||
- **Python http.server**: Simpler but less performant and no Alpine image parity.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **[No search or filtering]** → Users browse by directory structure. Acceptable given the channel/date organization.
|
||||
- **[Plain directory listing]** → No styled UI. Acceptable for a local utility tool.
|
||||
- **[No auth]** → Anyone on the LAN can access. Acceptable per non-goals.
|
||||
@@ -0,0 +1,23 @@
|
||||
## Why
|
||||
|
||||
Recordings from the RTLSDR-Airband CB scanner are stored as MP3 files on the Pi's filesystem (`/home/m/recordings/`), organized by channel and date. There's currently no way to browse or listen to them without SSH access. A web server with directory listing would make recordings browsable and playable from any device on the local network.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Add an Nginx container to `docker-compose.yml` that serves the recordings directory with autoindex enabled
|
||||
- Users browse directories and click MP3 files to play them natively in the browser
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
- `recording-browser`: Nginx autoindex serving the recordings directory over HTTP, with browser-native MP3 playback
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
_(none)_
|
||||
|
||||
## Impact
|
||||
|
||||
- **Docker deployment**: New Nginx service added to `docker-compose.yml`, sharing the `/home/m/recordings` volume (read-only)
|
||||
- **Pi resources**: Negligible — Nginx Alpine uses ~2MB RAM
|
||||
- **Network**: Exposes HTTP port on the Pi's local network
|
||||
@@ -0,0 +1,34 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Serve recordings directory over HTTP
|
||||
The system SHALL serve the contents of the recordings directory via an Nginx web server with directory listing enabled.
|
||||
|
||||
#### Scenario: Browse channel directories
|
||||
- **WHEN** a user navigates to the root URL of the web server
|
||||
- **THEN** the server displays a directory listing showing the channel subdirectories
|
||||
|
||||
#### Scenario: Browse date directories within a channel
|
||||
- **WHEN** a user clicks a channel directory
|
||||
- **THEN** the server displays a directory listing of date subdirectories for that channel
|
||||
|
||||
#### Scenario: Browse recording files within a date
|
||||
- **WHEN** a user clicks a date directory
|
||||
- **THEN** the server displays a listing of MP3 recording files
|
||||
|
||||
### Requirement: Browser-native MP3 playback
|
||||
The system SHALL serve MP3 files with correct MIME type so browsers can play them natively.
|
||||
|
||||
#### Scenario: Play a recording
|
||||
- **WHEN** a user clicks an MP3 file link in the directory listing
|
||||
- **THEN** the browser opens and plays the MP3 file using its native audio player
|
||||
|
||||
### Requirement: Docker deployment
|
||||
The web server SHALL run as a Docker container defined in `docker-compose.yml`, mounting the recordings directory read-only.
|
||||
|
||||
#### Scenario: Start alongside recorder
|
||||
- **WHEN** a user runs `docker compose up` on the Pi
|
||||
- **THEN** the Nginx service starts alongside the `sdr-recorder` service and is accessible via HTTP
|
||||
|
||||
#### Scenario: Read-only access to recordings
|
||||
- **WHEN** the Nginx container accesses the recordings volume
|
||||
- **THEN** the volume is mounted read-only, preventing modification of recording files
|
||||
@@ -0,0 +1,11 @@
|
||||
## 1. Nginx Configuration
|
||||
|
||||
- [x] 1.1 Create `nginx.conf` with a server block that serves `/recordings` with `autoindex on` and correct MIME type for MP3 files
|
||||
|
||||
## 2. Docker Integration
|
||||
|
||||
- [x] 2.1 Add an `nginx` service to `docker-compose.yml` using `nginx:alpine`, mounting `/home/m/recordings` to `/recordings:ro` and `./nginx.conf` to the Nginx config path, exposing port 8080
|
||||
|
||||
## 3. Deploy and Verify
|
||||
|
||||
- [x] 3.1 Deploy to the Pi and verify directory browsing and MP3 playback work at `http://sdr-pi:8080`
|
||||
32
openspec/specs/recording-browser/spec.md
Normal file
32
openspec/specs/recording-browser/spec.md
Normal file
@@ -0,0 +1,32 @@
|
||||
### Requirement: Serve recordings directory over HTTP
|
||||
The system SHALL serve the contents of the recordings directory via an Nginx web server with directory listing enabled.
|
||||
|
||||
#### Scenario: Browse channel directories
|
||||
- **WHEN** a user navigates to the root URL of the web server
|
||||
- **THEN** the server displays a directory listing showing the channel subdirectories
|
||||
|
||||
#### Scenario: Browse date directories within a channel
|
||||
- **WHEN** a user clicks a channel directory
|
||||
- **THEN** the server displays a directory listing of date subdirectories for that channel
|
||||
|
||||
#### Scenario: Browse recording files within a date
|
||||
- **WHEN** a user clicks a date directory
|
||||
- **THEN** the server displays a listing of MP3 recording files
|
||||
|
||||
### Requirement: Browser-native MP3 playback
|
||||
The system SHALL serve MP3 files with correct MIME type so browsers can play them natively.
|
||||
|
||||
#### Scenario: Play a recording
|
||||
- **WHEN** a user clicks an MP3 file link in the directory listing
|
||||
- **THEN** the browser opens and plays the MP3 file using its native audio player
|
||||
|
||||
### Requirement: Docker deployment
|
||||
The web server SHALL run as a Docker container defined in `docker-compose.yml`, mounting the recordings directory read-only.
|
||||
|
||||
#### Scenario: Start alongside recorder
|
||||
- **WHEN** a user runs `docker compose up` on the Pi
|
||||
- **THEN** the Nginx service starts alongside the `sdr-recorder` service and is accessible via HTTP
|
||||
|
||||
#### Scenario: Read-only access to recordings
|
||||
- **WHEN** the Nginx container accesses the recordings volume
|
||||
- **THEN** the volume is mounted read-only, preventing modification of recording files
|
||||
Reference in New Issue
Block a user