## New Features - **Nextcloud Role**: Complete cloud storage deployment using Podman Quadlet - FPM variant with Caddy reverse proxy and FastCGI - PostgreSQL database via Unix socket - Valkey/Redis for app-level caching and file locking - Automatic HTTPS with Let's Encrypt via Caddy - Dual-root pattern: Caddy serves static assets, FPM handles PHP - **Split Caching Strategy**: Redis caching WITHOUT Redis sessions - Custom redis.config.php template for app-level caching only - File-based PHP sessions for stability (avoids session lock issues) - Prevents cascading failures from session lock contention - Documented in role README with detailed rationale ## Infrastructure Updates - **Socket Permissions**: Update PostgreSQL and Valkey to mode 777 - Required for containers that switch users (root → www-data) - Nextcloud container loses supplementary groups on user switch - Security maintained via password authentication (scram-sha-256, requirepass) - Documented socket permission architecture in docs/ - **PostgreSQL**: Export client group GID as fact for dependent roles - **Valkey**: Export client group GID as fact, update socket fix service ## Documentation - New: docs/socket-permissions-architecture.md - Explains 777 vs 770 socket permission trade-offs - Documents why group-based access doesn't work for user-switching containers - Provides TCP alternative for stricter security requirements - Updated: All role READMEs with socket permission notes - New: Nextcloud README with comprehensive deployment, troubleshooting, and Redis architecture documentation ## Configuration - host_vars: Add Nextcloud vault variables and configuration - site.yml: Include Nextcloud role in main playbook ## Technical Details **Why disable Redis sessions?** The official Nextcloud container enables Redis session handling via REDIS_HOST env var, which causes severe performance issues: 1. Session lock contention under high concurrency (browser parallel asset requests) 2. Infinite lock retries (default lock_retries=-1) blocking FPM workers 3. Timeout orphaning: reverse proxy kills connection, worker keeps lock 4. Worker pool exhaustion: all 5 default workers blocked on same session lock 5. Cascading failure: new requests queue, more timeouts, more orphaned locks Solution: Use file-based sessions (reliable, fast for single-server) while keeping Redis for distributed cache and transactional file locking via custom config file. This provides optimal performance without the complexity of Redis session debugging. Tested: Fresh deployment on arch-vps (69.62.119.31) Domain: https://cloud.jnss.me/
7.4 KiB
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:
dependencies:
- role: postgresql
tags: ['postgresql', 'infrastructure']
Then create your application's database and user in your tasks:
- 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
- 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=truePrivateTmp=trueProtectHome=trueProtectSystem=strict- Memory execution protection
- System call filtering
Authentication
- Secure
scram-sha-256password authentication peerauthentication 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:
# 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:
sudo -u postgres psql
Create application database and user:
CREATE ROLE myapp WITH LOGIN PASSWORD 'secure_password';
CREATE DATABASE myapp WITH OWNER myapp TEMPLATE template0 ENCODING 'UTF8';
List databases:
\l
List users:
\du
Performance Tuning
The role provides conservative performance defaults suitable for most applications. For production workloads, consider adjusting:
postgresql_shared_buffers: 25% of system RAMpostgresql_effective_cache_size: 75% of system RAMpostgresql_max_connections: Based on application needspostgresql_maintenance_work_mem: For large datasets
Monitoring
Service Status
systemctl status postgresql
Logs
journalctl -u postgresql
# or
sudo -u postgres tail -f /var/log/postgresql/postgresql-*.log
Connection Test
sudo -u postgres psql -c "SELECT version();"
Troubleshooting
Common Issues
- Permission Denied: Ensure postgres user owns data directory
- Connection Refused: Check service status and listen_addresses
- Authentication Failed: Verify pg_hba.conf configuration
Debug Mode
Enable detailed logging:
postgresql_log_statement: "all"
postgresql_log_connections: true
postgresql_log_disconnections: true
Examples
Development Setup
postgresql_log_statement: "all" # Log all statements
postgresql_max_connections: 50 # Lower for development
Production Setup
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
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:
- Update this README for any new features
- Test with example applications
- Ensure security configurations remain intact
- Follow rick-infra coding standards
Integration Examples
See roles that use this infrastructure:
gitea: Git repository managementnextcloud(planned): File sharing and collaboration
Rick-Infra PostgreSQL Infrastructure Role
Provides secure, performant PostgreSQL database infrastructure for rick-infra applications.