344 lines
7.6 KiB
Org Mode
344 lines
7.6 KiB
Org Mode
#+TITLE: PostgreSQL Setup for Asteroid Radio
|
|
#+AUTHOR: Asteroid Radio Development Team
|
|
#+DATE: 2025-10-26
|
|
|
|
* 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 roles
|
|
- =tracks= - Music library metadata
|
|
- =playlists= - User playlists
|
|
- =playlist_tracks= - Many-to-many playlist/track relationship
|
|
- =sessions= - Session management
|
|
|
|
* Quick Start
|
|
|
|
** 1. Start PostgreSQL Container
|
|
|
|
#+BEGIN_SRC bash
|
|
cd docker
|
|
docker compose up -d postgres
|
|
#+END_SRC
|
|
|
|
Wait 10 seconds for initialization, then verify:
|
|
|
|
#+BEGIN_SRC bash
|
|
docker logs asteroid-postgres
|
|
#+END_SRC
|
|
|
|
You should see: "Asteroid Radio database initialized successfully!"
|
|
|
|
** 2. Test Connection
|
|
|
|
#+BEGIN_SRC bash
|
|
docker exec -it asteroid-postgres psql -U asteroid -d asteroid
|
|
#+END_SRC
|
|
|
|
Inside psql:
|
|
#+BEGIN_SRC sql
|
|
\dt -- List tables
|
|
SELECT * FROM users; -- View users
|
|
\q -- Quit
|
|
#+END_SRC
|
|
|
|
** 3. Configure Radiance (When Ready)
|
|
|
|
Edit your Radiance configuration to use PostgreSQL:
|
|
|
|
#+BEGIN_SRC lisp
|
|
(load "config/radiance-postgres.lisp")
|
|
#+END_SRC
|
|
|
|
* Database Schema
|
|
|
|
** Users Table
|
|
#+BEGIN_SRC sql
|
|
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
|
|
);
|
|
#+END_SRC
|
|
|
|
** Tracks Table
|
|
#+BEGIN_SRC sql
|
|
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
|
|
);
|
|
#+END_SRC
|
|
|
|
** Playlists Table
|
|
#+BEGIN_SRC sql
|
|
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
|
|
);
|
|
#+END_SRC
|
|
|
|
** Playlist Tracks Junction Table
|
|
#+BEGIN_SRC sql
|
|
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)
|
|
);
|
|
#+END_SRC
|
|
|
|
* 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
|
|
#+BEGIN_SRC
|
|
postgresql://asteroid:asteroid_db_2025@localhost:5432/asteroid
|
|
#+END_SRC
|
|
|
|
* 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
|
|
#+BEGIN_SRC bash
|
|
docker exec -it asteroid-postgres psql -U asteroid -d asteroid
|
|
#+END_SRC
|
|
|
|
** View All Tables
|
|
#+BEGIN_SRC sql
|
|
\dt
|
|
#+END_SRC
|
|
|
|
** View Table Structure
|
|
#+BEGIN_SRC sql
|
|
\d users
|
|
\d tracks
|
|
\d playlists
|
|
\d playlist_tracks
|
|
#+END_SRC
|
|
|
|
** Count Records
|
|
#+BEGIN_SRC sql
|
|
SELECT COUNT(*) FROM users;
|
|
SELECT COUNT(*) FROM tracks;
|
|
SELECT COUNT(*) FROM playlists;
|
|
#+END_SRC
|
|
|
|
** View Playlists with Track Counts
|
|
#+BEGIN_SRC sql
|
|
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;
|
|
#+END_SRC
|
|
|
|
* Backup and Restore
|
|
|
|
** Create Backup
|
|
#+BEGIN_SRC bash
|
|
docker exec asteroid-postgres pg_dump -U asteroid asteroid > backup.sql
|
|
#+END_SRC
|
|
|
|
** Restore from Backup
|
|
#+BEGIN_SRC bash
|
|
cat backup.sql | docker exec -i asteroid-postgres psql -U asteroid -d asteroid
|
|
#+END_SRC
|
|
|
|
** Backup with Docker Volume
|
|
#+BEGIN_SRC bash
|
|
docker run --rm \
|
|
-v docker_postgres-data:/data \
|
|
-v $(pwd):/backup \
|
|
alpine tar czf /backup/postgres-backup.tar.gz /data
|
|
#+END_SRC
|
|
|
|
* Migration from Radiance Default DB
|
|
|
|
** Export Current Data
|
|
|
|
Create a script to export from current database:
|
|
|
|
#+BEGIN_SRC lisp
|
|
(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)))))
|
|
#+END_SRC
|
|
|
|
** Import to PostgreSQL
|
|
|
|
#+BEGIN_SRC bash
|
|
# Run export script, save to file
|
|
# Then import:
|
|
cat export.sql | docker exec -i asteroid-postgres psql -U asteroid -d asteroid
|
|
#+END_SRC
|
|
|
|
* Troubleshooting
|
|
|
|
** Container Won't Start
|
|
|
|
Check logs:
|
|
#+BEGIN_SRC bash
|
|
docker logs asteroid-postgres
|
|
#+END_SRC
|
|
|
|
** Connection Refused
|
|
|
|
Ensure container is running:
|
|
#+BEGIN_SRC bash
|
|
docker ps | grep postgres
|
|
#+END_SRC
|
|
|
|
Check health:
|
|
#+BEGIN_SRC bash
|
|
docker exec asteroid-postgres pg_isready -U asteroid
|
|
#+END_SRC
|
|
|
|
** Permission Denied
|
|
|
|
Reset permissions:
|
|
#+BEGIN_SRC bash
|
|
docker exec -it asteroid-postgres psql -U postgres -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO asteroid;"
|
|
#+END_SRC
|
|
|
|
** Data Not Persisting
|
|
|
|
Check volume:
|
|
#+BEGIN_SRC bash
|
|
docker volume ls | grep postgres
|
|
docker volume inspect docker_postgres-data
|
|
#+END_SRC
|
|
|
|
* Performance Tuning
|
|
|
|
** Increase Shared Buffers
|
|
|
|
Edit docker-compose.yml:
|
|
#+BEGIN_SRC yaml
|
|
postgres:
|
|
command: postgres -c shared_buffers=256MB -c max_connections=100
|
|
#+END_SRC
|
|
|
|
** Enable Query Logging
|
|
|
|
#+BEGIN_SRC yaml
|
|
postgres:
|
|
command: postgres -c log_statement=all
|
|
#+END_SRC
|
|
|
|
* Security Recommendations
|
|
|
|
** Change Default Passwords
|
|
|
|
#+BEGIN_SRC sql
|
|
ALTER USER asteroid WITH PASSWORD 'new_secure_password';
|
|
UPDATE users SET password_hash = '$2a$12$...' WHERE username = 'admin';
|
|
#+END_SRC
|
|
|
|
** Restrict Network Access
|
|
|
|
In production, don't expose port 5432 externally:
|
|
#+BEGIN_SRC yaml
|
|
postgres:
|
|
ports: [] # Remove port mapping
|
|
#+END_SRC
|
|
|
|
** Enable SSL
|
|
|
|
Add to docker-compose.yml:
|
|
#+BEGIN_SRC yaml
|
|
postgres:
|
|
command: postgres -c ssl=on -c ssl_cert_file=/etc/ssl/certs/server.crt
|
|
#+END_SRC
|
|
|
|
* Next Steps
|
|
|
|
1. ✅ PostgreSQL container running
|
|
2. ⏳ Configure Radiance to use PostgreSQL
|
|
3. ⏳ Migrate existing data
|
|
4. ⏳ Update application code for PostgreSQL
|
|
5. ⏳ Test playlist functionality
|
|
6. ⏳ 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
|