-- Database security initialization -- This script sets up secure defaults for PostgreSQL -- Create application-specific user with limited privileges DO $$ BEGIN IF NOT EXISTS (SELECT FROM pg_catalog.pg_user WHERE usename = 'liferpg_app') THEN CREATE USER liferpg_app WITH ENCRYPTED PASSWORD 'app_secure_password_2024'; END IF; END $$; -- Revoke unnecessary privileges REVOKE ALL ON SCHEMA public FROM PUBLIC; REVOKE ALL ON ALL TABLES IN SCHEMA public FROM PUBLIC; REVOKE ALL ON ALL SEQUENCES IN SCHEMA public FROM PUBLIC; REVOKE ALL ON ALL FUNCTIONS IN SCHEMA public FROM PUBLIC; -- Grant minimal required privileges to application user GRANT CONNECT ON DATABASE liferpg TO liferpg_app; GRANT USAGE ON SCHEMA public TO liferpg_app; GRANT CREATE ON SCHEMA public TO liferpg_app; -- Enable row level security by default for sensitive tables ALTER TABLE IF EXISTS users ENABLE ROW LEVEL SECURITY; ALTER TABLE IF EXISTS habits ENABLE ROW LEVEL SECURITY; ALTER TABLE IF EXISTS projects ENABLE ROW LEVEL SECURITY; -- Set secure configuration parameters ALTER SYSTEM SET log_statement = 'all'; ALTER SYSTEM SET log_min_duration_statement = 1000; ALTER SYSTEM SET log_connections = 'on'; ALTER SYSTEM SET log_disconnections = 'on'; ALTER SYSTEM SET log_min_error_statement = 'error'; ALTER SYSTEM SET shared_preload_libraries = 'pg_stat_statements'; -- Security settings ALTER SYSTEM SET ssl = 'on'; ALTER SYSTEM SET password_encryption = 'scram-sha-256'; ALTER SYSTEM SET row_security = 'on'; -- Limit connections ALTER SYSTEM SET max_connections = 100; ALTER SYSTEM SET superuser_reserved_connections = 3; -- Memory and performance settings ALTER SYSTEM SET shared_buffers = '256MB'; ALTER SYSTEM SET effective_cache_size = '1GB'; ALTER SYSTEM SET maintenance_work_mem = '64MB'; ALTER SYSTEM SET checkpoint_completion_target = 0.9; ALTER SYSTEM SET wal_buffers = '16MB'; ALTER SYSTEM SET default_statistics_target = 100; SELECT pg_reload_conf();