7.6 KiB
7.6 KiB
PostgreSQL Setup for Asteroid Radio
- Overview
- What This Provides
- Quick Start
- Database Schema
- Connection Details
- Default Users
- Management Commands
- Backup and Restore
- Migration from Radiance Default DB
- Troubleshooting
- Performance Tuning
- Security Recommendations
- Next Steps
- Status: ✅ READY FOR INTEGRATION
Overview
Complete PostgreSQL setup with Docker, persistent storage, and Radiance integration for Asteroid Radio.
What This Provides
Persistent Storage
- All data survives container restarts
- Database stored in Docker volume
postgres-data - Automatic backups possible
Full Database Features
- Proper UPDATE/DELETE operations
- Transactions and ACID compliance
- Indexes for fast queries
- Foreign key constraints
- Triggers for automatic timestamps
Tables Created
users- User accounts with rolestracks- Music library metadataplaylists- User playlistsplaylist_tracks- Many-to-many playlist/track relationshipsessions- Session management
Quick Start
1. Start PostgreSQL Container
cd docker
docker compose up -d postgres
Wait 10 seconds for initialization, then verify:
docker logs asteroid-postgres
You should see: "Asteroid Radio database initialized successfully!"
2. Test Connection
docker exec -it asteroid-postgres psql -U asteroid -d asteroid
Inside psql:
\dt -- List tables
SELECT * FROM users; -- View users
\q -- Quit
3. Configure Radiance (When Ready)
Edit your Radiance configuration to use PostgreSQL:
(load "config/radiance-postgres.lisp")
Database Schema
Users Table
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(255) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash TEXT NOT NULL,
role VARCHAR(50) DEFAULT 'listener',
active BOOLEAN DEFAULT true,
created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_login TIMESTAMP
);
Tracks Table
CREATE TABLE tracks (
id SERIAL PRIMARY KEY,
title VARCHAR(500) NOT NULL,
artist VARCHAR(500),
album VARCHAR(500),
duration INTEGER DEFAULT 0,
format VARCHAR(50),
file_path TEXT NOT NULL UNIQUE,
play_count INTEGER DEFAULT 0,
added_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_played TIMESTAMP
);
Playlists Table
CREATE TABLE playlists (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
description TEXT,
created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
modified_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Playlist Tracks Junction Table
CREATE TABLE playlist_tracks (
id SERIAL PRIMARY KEY,
playlist_id INTEGER NOT NULL REFERENCES playlists(id) ON DELETE CASCADE,
track_id INTEGER NOT NULL REFERENCES tracks(id) ON DELETE CASCADE,
position INTEGER NOT NULL,
added_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(playlist_id, track_id, position)
);
Connection Details
From Host Machine
- Host:
localhost - Port:
5432 - Database:
asteroid - Username:
asteroid - Password:
asteroid_db_2025
From Docker Containers
- Host:
asteroid-postgres - Port:
5432 - Database:
asteroid - Username:
asteroid - Password:
asteroid_db_2025
Connection String
postgresql://asteroid:asteroid_db_2025@localhost:5432/asteroid
Default Users
Admin User
- Username:
admin - Password:
admin(⚠️ CHANGE THIS!) - Role:
admin
Test Listener
- Username:
listener - Password:
admin(⚠️ CHANGE THIS!) - Role:
listener
Management Commands
Access PostgreSQL CLI
docker exec -it asteroid-postgres psql -U asteroid -d asteroid
View All Tables
\dt
View Table Structure
\d users
\d tracks
\d playlists
\d playlist_tracks
Count Records
SELECT COUNT(*) FROM users;
SELECT COUNT(*) FROM tracks;
SELECT COUNT(*) FROM playlists;
View Playlists with Track Counts
SELECT p.id, p.name, u.username, COUNT(pt.track_id) as track_count
FROM playlists p
JOIN users u ON p.user_id = u.id
LEFT JOIN playlist_tracks pt ON p.id = pt.playlist_id
GROUP BY p.id, p.name, u.username;
Backup and Restore
Create Backup
docker exec asteroid-postgres pg_dump -U asteroid asteroid > backup.sql
Restore from Backup
cat backup.sql | docker exec -i asteroid-postgres psql -U asteroid -d asteroid
Backup with Docker Volume
docker run --rm \
-v docker_postgres-data:/data \
-v $(pwd):/backup \
alpine tar czf /backup/postgres-backup.tar.gz /data
Migration from Radiance Default DB
Export Current Data
Create a script to export from current database:
(defun export-users-to-postgres ()
"Export users from Radiance DB to PostgreSQL"
(let ((users (db:select "users" (db:query :all))))
(loop for user in users
do (format t "INSERT INTO users (username, email, password_hash, role, active) VALUES (~
'~a', '~a', '~a', '~a', ~a);~%"
(gethash "username" user)
(gethash "email" user)
(gethash "password-hash" user)
(gethash "role" user)
(gethash "active" user)))))
Import to PostgreSQL
# Run export script, save to file
# Then import:
cat export.sql | docker exec -i asteroid-postgres psql -U asteroid -d asteroid
Troubleshooting
Container Won't Start
Check logs:
docker logs asteroid-postgres
Connection Refused
Ensure container is running:
docker ps | grep postgres
Check health:
docker exec asteroid-postgres pg_isready -U asteroid
Permission Denied
Reset permissions:
docker exec -it asteroid-postgres psql -U postgres -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO asteroid;"
Data Not Persisting
Check volume:
docker volume ls | grep postgres
docker volume inspect docker_postgres-data
Performance Tuning
Increase Shared Buffers
Edit docker-compose.yml:
postgres:
command: postgres -c shared_buffers=256MB -c max_connections=100
Enable Query Logging
postgres:
command: postgres -c log_statement=all
Security Recommendations
Change Default Passwords
ALTER USER asteroid WITH PASSWORD 'new_secure_password';
UPDATE users SET password_hash = '$2a$12$...' WHERE username = 'admin';
Restrict Network Access
In production, don't expose port 5432 externally:
postgres:
ports: [] # Remove port mapping
Enable SSL
Add to docker-compose.yml:
postgres:
command: postgres -c ssl=on -c ssl_cert_file=/etc/ssl/certs/server.crt
Next Steps
- ✅ PostgreSQL container running
- ⏳ Configure Radiance to use PostgreSQL
- ⏳ Migrate existing data
- ⏳ Update application code for PostgreSQL
- ⏳ Test playlist functionality
- ⏳ Deploy to production
Status: ✅ READY FOR INTEGRATION
PostgreSQL is set up and ready. Next step is configuring Radiance and migrating data.
What Works Now
- ✅ PostgreSQL container running
- ✅ Database initialized with schema
- ✅ Persistent storage configured
- ✅ Default users created
- ✅ Indexes and constraints in place
What Needs Fade
- ⏳ Radiance PostgreSQL adapter configuration
- ⏳ Data migration from current DB
- ⏳ Application code updates
- ⏳ Testing and validation