# PostgreSQL Infrastructure Role This role provides PostgreSQL as shared database infrastructure for rick-infra applications. It follows the self-contained service architecture where this role provides the database server, and applications manage their own databases and users. ## Architecture PostgreSQL serves as database infrastructure (similar to how Caddy provides web infrastructure): - **PostgreSQL Role**: Installs and configures PostgreSQL server - **Application Roles**: Create their own databases/users via dependency ## Features - ✅ Native Arch Linux installation via pacman - ✅ Secure configuration with scram-sha-256 authentication - ✅ SystemD security hardening - ✅ Data integrity with checksums enabled by default - ✅ Performance-tuned defaults - ✅ Comprehensive logging configuration - ✅ UTF-8 encoding with C.UTF-8 locale ## Usage ### In Application Roles Add PostgreSQL as a dependency in your application's `meta/main.yml`: ```yaml dependencies: - role: postgresql tags: ['postgresql', 'infrastructure'] ``` Then create your application's database and user in your tasks: ```yaml - name: Create application database user postgresql_user: name: "{{ myapp_db_user }}" password: "{{ myapp_db_password }}" encrypted: yes become: yes become_user: postgres - name: Create application database postgresql_db: name: "{{ myapp_db_name }}" owner: "{{ myapp_db_user }}" encoding: UTF8 template: template0 become: yes become_user: postgres ``` ### In site.yml ```yaml - name: Deploy Infrastructure hosts: arch-vps become: yes roles: - role: postgresql tags: ['postgresql', 'infrastructure', 'database'] - role: myapp # Will use PostgreSQL infrastructure tags: ['myapp'] ``` ## Configuration Variables ### Basic Configuration | Variable | Default | Description | |----------|---------|-------------| | `postgresql_service_enabled` | `true` | Enable PostgreSQL service | | `postgresql_service_state` | `"started"` | Service state | | `postgresql_port` | `5432` | PostgreSQL port | | `postgresql_listen_addresses` | `"localhost"` | Listen addresses | ### Security Configuration | Variable | Default | Description | |----------|---------|-------------| | `postgresql_auth_method` | `"scram-sha-256"` | Authentication method | | `postgresql_systemd_security` | `true` | Enable systemd security hardening | | `postgresql_data_checksums` | `true` | Enable data checksums | | `postgresql_ssl` | `false` | Enable SSL/TLS | ### Performance Configuration | Variable | Default | Description | |----------|---------|-------------| | `postgresql_max_connections` | `100` | Maximum connections | | `postgresql_shared_buffers` | `"128MB"` | Shared buffer size | | `postgresql_effective_cache_size` | `"1GB"` | Effective cache size | See `defaults/main.yml` for all available configuration options. ## Security Features ### SystemD Hardening The role implements comprehensive systemd security restrictions: - `NoNewPrivileges=true` - `PrivateTmp=true` - `ProtectHome=true` - `ProtectSystem=strict` - Memory execution protection - System call filtering ### Authentication - Secure `scram-sha-256` password authentication - `peer` authentication for postgres superuser - Local connections only by default - Encrypted password storage ### Unix Socket Permissions **Current Configuration**: Socket permissions are set to `0777` (world-readable/writable) **Rationale**: - Allows containers running as any UID to access the socket - Needed for containers that start as root and switch to unprivileged users (e.g., Nextcloud's www-data) - Security is maintained via password authentication (scram-sha-256) - Sockets are local-only (not network-exposed) **Security Considerations**: - ✅ Any local process can connect to the socket - ✅ But still requires valid username + password to authenticate - ✅ Limited to processes on same host (not network) - ✅ Passwords stored encrypted with scram-sha-256 **Alternative Approach (TCP)**: If you prefer more restrictive socket permissions, you can use TCP instead: ```yaml # In host_vars postgresql_listen_addresses: "127.0.0.1" # Listen on localhost TCP postgresql_unix_socket_permissions: "0770" # Restrict socket to group # In application configs # Use: host=127.0.0.1 port=5432 # Instead of: host=/var/run/postgresql ``` This provides the same security level (password-authenticated, localhost-only) but uses TCP instead of Unix sockets. ### File System Security - Proper ownership and permissions - Protected configuration files (mode 0600) - Separate log directory with appropriate access ## Directory Structure ``` /var/lib/postgres/data/ # PostgreSQL data directory /var/lib/postgres/ # PostgreSQL home directory /var/log/postgresql/ # PostgreSQL logs /etc/systemd/system/postgresql.service.d/ # SystemD overrides ``` ## Database Administration ### Connect as postgres superuser: ```bash sudo -u postgres psql ``` ### Create application database and user: ```sql CREATE ROLE myapp WITH LOGIN PASSWORD 'secure_password'; CREATE DATABASE myapp WITH OWNER myapp TEMPLATE template0 ENCODING 'UTF8'; ``` ### List databases: ```sql \l ``` ### List users: ```sql \du ``` ## Performance Tuning The role provides conservative performance defaults suitable for most applications. For production workloads, consider adjusting: - `postgresql_shared_buffers`: 25% of system RAM - `postgresql_effective_cache_size`: 75% of system RAM - `postgresql_max_connections`: Based on application needs - `postgresql_maintenance_work_mem`: For large datasets ## Monitoring ### Service Status ```bash systemctl status postgresql ``` ### Logs ```bash journalctl -u postgresql # or sudo -u postgres tail -f /var/log/postgresql/postgresql-*.log ``` ### Connection Test ```bash sudo -u postgres psql -c "SELECT version();" ``` ## Troubleshooting ### Common Issues 1. **Permission Denied**: Ensure postgres user owns data directory 2. **Connection Refused**: Check service status and listen_addresses 3. **Authentication Failed**: Verify pg_hba.conf configuration ### Debug Mode Enable detailed logging: ```yaml postgresql_log_statement: "all" postgresql_log_connections: true postgresql_log_disconnections: true ``` ## Examples ### Development Setup ```yaml postgresql_log_statement: "all" # Log all statements postgresql_max_connections: 50 # Lower for development ``` ### Production Setup ```yaml postgresql_shared_buffers: "256MB" postgresql_effective_cache_size: "2GB" postgresql_log_min_duration_statement: 1000 # Log slow queries postgresql_log_connections: true # Audit trail ``` ### High Security Setup ```yaml postgresql_ssl: true postgresql_log_connections: true postgresql_log_disconnections: true postgresql_log_statement: "ddl" # Log schema changes ``` ## Dependencies - Arch Linux PostgreSQL package - python-psycopg2 (for Ansible modules) ## Compatibility - **OS**: Arch Linux - **PostgreSQL**: Latest stable version from Arch repositories - **Ansible**: >= 2.9 ## Contributing When modifying this role: 1. Update this README for any new features 2. Test with example applications 3. Ensure security configurations remain intact 4. Follow rick-infra coding standards ## Integration Examples See roles that use this infrastructure: - `gitea`: Git repository management - `nextcloud` (planned): File sharing and collaboration --- **Rick-Infra PostgreSQL Infrastructure Role** Provides secure, performant PostgreSQL database infrastructure for rick-infra applications.