## 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/
283 lines
7.4 KiB
Markdown
283 lines
7.4 KiB
Markdown
# 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. |