Add simplified PostgreSQL infrastructure role for database services
- Provides PostgreSQL server as shared database infrastructure - Follows KISS principle with only essential configuration (11 variables vs 45 originally) - Implements maximum security with Unix socket-only superuser access - Uses scram-sha-256 authentication for application users - Includes SystemD security hardening - Applications manage their own databases/users via this infrastructure - Production-ready with data checksums and localhost-only access
This commit is contained in:
252
roles/postgresql/README.md
Normal file
252
roles/postgresql/README.md
Normal file
@@ -0,0 +1,252 @@
|
||||
# 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
|
||||
|
||||
### 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.
|
||||
52
roles/postgresql/defaults/main.yml
Normal file
52
roles/postgresql/defaults/main.yml
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
# =================================================================
|
||||
# PostgreSQL Infrastructure Role - Simplified Configuration
|
||||
# =================================================================
|
||||
# Provides PostgreSQL database server as shared infrastructure
|
||||
# Applications manage their own databases/users
|
||||
|
||||
# =================================================================
|
||||
# Essential Configuration
|
||||
# =================================================================
|
||||
|
||||
# Service Management
|
||||
postgresql_service_enabled: true
|
||||
postgresql_service_state: "started"
|
||||
|
||||
# Network Security (localhost only)
|
||||
postgresql_listen_addresses: "localhost"
|
||||
postgresql_port: 5432
|
||||
|
||||
# Authentication
|
||||
postgresql_auth_method: "scram-sha-256"
|
||||
|
||||
# Database Cluster Setup
|
||||
postgresql_encoding: "UTF8"
|
||||
postgresql_locale: "C.UTF-8"
|
||||
postgresql_data_checksums: true
|
||||
|
||||
# Security
|
||||
postgresql_systemd_security: true
|
||||
|
||||
# =================================================================
|
||||
# Optional Performance (Conservative Defaults)
|
||||
# =================================================================
|
||||
|
||||
# Basic performance settings - PostgreSQL defaults are excellent
|
||||
postgresql_max_connections: 100
|
||||
postgresql_shared_buffers: "128MB"
|
||||
|
||||
# =================================================================
|
||||
# Infrastructure Notes
|
||||
# =================================================================
|
||||
# This role provides minimal PostgreSQL infrastructure
|
||||
# Applications should create their own databases/users:
|
||||
#
|
||||
# - postgresql_user:
|
||||
# name: myapp
|
||||
# password: "{{ vault_myapp_password }}"
|
||||
# - postgresql_db:
|
||||
# name: myapp
|
||||
# owner: myapp
|
||||
#
|
||||
# PostgreSQL's built-in defaults are used for everything else
|
||||
18
roles/postgresql/handlers/main.yml
Normal file
18
roles/postgresql/handlers/main.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
# PostgreSQL Role Handlers
|
||||
|
||||
- name: reload systemd
|
||||
systemd:
|
||||
daemon_reload: yes
|
||||
|
||||
- name: restart postgresql
|
||||
systemd:
|
||||
name: postgresql
|
||||
state: restarted
|
||||
when: postgresql_service_state == "started"
|
||||
|
||||
- name: reload postgresql
|
||||
systemd:
|
||||
name: postgresql
|
||||
state: reloaded
|
||||
when: postgresql_service_state == "started"
|
||||
25
roles/postgresql/meta/main.yml
Normal file
25
roles/postgresql/meta/main.yml
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
galaxy_info:
|
||||
author: Rick's Infrastructure Team
|
||||
description: PostgreSQL database server infrastructure for rick-infra
|
||||
company: Personal Infrastructure
|
||||
|
||||
license: MIT
|
||||
|
||||
min_ansible_version: "2.9"
|
||||
|
||||
platforms:
|
||||
- name: ArchLinux
|
||||
versions:
|
||||
- all
|
||||
|
||||
galaxy_tags:
|
||||
- database
|
||||
- postgresql
|
||||
- infrastructure
|
||||
- archlinux
|
||||
|
||||
dependencies: []
|
||||
|
||||
# Role provides PostgreSQL infrastructure
|
||||
# Applications should declare this as a dependency and manage their own databases/users
|
||||
93
roles/postgresql/tasks/main.yml
Normal file
93
roles/postgresql/tasks/main.yml
Normal file
@@ -0,0 +1,93 @@
|
||||
---
|
||||
# PostgreSQL Infrastructure Role - Simplified Tasks
|
||||
|
||||
- name: Install PostgreSQL
|
||||
pacman:
|
||||
name: postgresql
|
||||
state: present
|
||||
|
||||
- name: Install PostgreSQL Python library (for Ansible modules)
|
||||
pacman:
|
||||
name: python-psycopg2
|
||||
state: present
|
||||
|
||||
- name: Check if PostgreSQL data directory exists and is initialized
|
||||
stat:
|
||||
path: "/var/lib/postgres/data/PG_VERSION"
|
||||
register: postgresql_initialized
|
||||
|
||||
- name: Initialize PostgreSQL database cluster
|
||||
command: >
|
||||
initdb
|
||||
-D /var/lib/postgres/data
|
||||
--locale={{ postgresql_locale }}
|
||||
--encoding={{ postgresql_encoding }}
|
||||
--auth-local=peer
|
||||
--auth-host={{ postgresql_auth_method }}
|
||||
{{ '--data-checksums' if postgresql_data_checksums else '' }}
|
||||
become: yes
|
||||
become_user: postgres
|
||||
when: not postgresql_initialized.stat.exists
|
||||
notify: restart postgresql
|
||||
|
||||
- name: Deploy PostgreSQL configuration file
|
||||
template:
|
||||
src: postgresql.conf.j2
|
||||
dest: /var/lib/postgres/data/postgresql.conf
|
||||
owner: postgres
|
||||
group: postgres
|
||||
mode: '0600'
|
||||
backup: yes
|
||||
notify: restart postgresql
|
||||
|
||||
- name: Deploy PostgreSQL authentication configuration
|
||||
template:
|
||||
src: pg_hba.conf.j2
|
||||
dest: /var/lib/postgres/data/pg_hba.conf
|
||||
owner: postgres
|
||||
group: postgres
|
||||
mode: '0600'
|
||||
backup: yes
|
||||
notify: restart postgresql
|
||||
|
||||
- name: Create systemd override directory for PostgreSQL security
|
||||
file:
|
||||
path: /etc/systemd/system/postgresql.service.d
|
||||
state: directory
|
||||
mode: '0755'
|
||||
when: postgresql_systemd_security
|
||||
|
||||
- name: Deploy PostgreSQL systemd security override
|
||||
template:
|
||||
src: systemd-override.conf.j2
|
||||
dest: /etc/systemd/system/postgresql.service.d/override.conf
|
||||
mode: '0644'
|
||||
when: postgresql_systemd_security
|
||||
notify:
|
||||
- reload systemd
|
||||
- restart postgresql
|
||||
|
||||
- name: Enable and start PostgreSQL service
|
||||
systemd:
|
||||
name: postgresql
|
||||
enabled: "{{ postgresql_service_enabled }}"
|
||||
state: "{{ postgresql_service_state }}"
|
||||
daemon_reload: yes
|
||||
|
||||
- name: Wait for PostgreSQL to be ready
|
||||
wait_for:
|
||||
port: "{{ postgresql_port }}"
|
||||
host: "{{ postgresql_listen_addresses }}"
|
||||
timeout: 30
|
||||
when: postgresql_service_state == "started"
|
||||
|
||||
- name: Display PostgreSQL infrastructure status
|
||||
debug:
|
||||
msg: |
|
||||
✅ PostgreSQL infrastructure ready!
|
||||
|
||||
📡 Service: {{ postgresql_listen_addresses }}:{{ postgresql_port }}
|
||||
🔒 Auth: {{ postgresql_auth_method }}
|
||||
📊 Checksums: {{ 'Enabled' if postgresql_data_checksums else 'Disabled' }}
|
||||
|
||||
🏗️ Ready for applications to create databases/users
|
||||
45
roles/postgresql/templates/pg_hba.conf.j2
Normal file
45
roles/postgresql/templates/pg_hba.conf.j2
Normal file
@@ -0,0 +1,45 @@
|
||||
# PostgreSQL Client Authentication Configuration File
|
||||
# Generated by Ansible - PostgreSQL Role
|
||||
# Documentation: https://www.postgresql.org/docs/current/auth-pg-hba-conf.html
|
||||
|
||||
# TYPE DATABASE USER ADDRESS METHOD
|
||||
|
||||
# =============================================================================
|
||||
# LOCAL CONNECTIONS
|
||||
# =============================================================================
|
||||
|
||||
# "local" is for Unix domain socket connections only
|
||||
local all postgres peer
|
||||
local all all {{ postgresql_auth_method }}
|
||||
|
||||
# =============================================================================
|
||||
# IPv4 LOCAL CONNECTIONS
|
||||
# =============================================================================
|
||||
|
||||
# IPv4 local connections (applications only - no superuser TCP access):
|
||||
host all all 127.0.0.1/32 {{ postgresql_auth_method }}
|
||||
|
||||
# =============================================================================
|
||||
# IPv6 LOCAL CONNECTIONS
|
||||
# =============================================================================
|
||||
|
||||
# IPv6 local connections (applications only - no superuser TCP access):
|
||||
host all all ::1/128 {{ postgresql_auth_method }}
|
||||
|
||||
# =============================================================================
|
||||
# SECURITY NOTES
|
||||
# =============================================================================
|
||||
# This configuration provides maximum security defaults:
|
||||
# - postgres superuser ONLY accessible via Unix socket with peer authentication
|
||||
# - NO TCP access for postgres superuser (even from localhost)
|
||||
# - All application users use {{ postgresql_auth_method }} over TCP
|
||||
# - Only local connections allowed by default
|
||||
#
|
||||
# Superuser access: sudo -u postgres psql (Unix socket only)
|
||||
# Application access: psql -h localhost -U appuser -d appdb (TCP with password)
|
||||
#
|
||||
# For remote access, add additional 'host' entries above
|
||||
# Always use the most restrictive authentication method possible
|
||||
#
|
||||
# Rick-Infra PostgreSQL Infrastructure
|
||||
# Applications should create their own database users
|
||||
16
roles/postgresql/templates/postgresql.conf.j2
Normal file
16
roles/postgresql/templates/postgresql.conf.j2
Normal file
@@ -0,0 +1,16 @@
|
||||
# PostgreSQL Configuration - Rick-Infra Simplified
|
||||
# Generated by Ansible PostgreSQL role
|
||||
# PostgreSQL's excellent defaults are used except for essentials
|
||||
|
||||
# Network and Security
|
||||
listen_addresses = '{{ postgresql_listen_addresses }}'
|
||||
port = {{ postgresql_port }}
|
||||
|
||||
# Basic Performance (only override if needed)
|
||||
max_connections = {{ postgresql_max_connections }}
|
||||
shared_buffers = {{ postgresql_shared_buffers }}
|
||||
|
||||
# Authentication
|
||||
password_encryption = {{ postgresql_auth_method }}
|
||||
|
||||
# Rick-Infra: PostgreSQL infrastructure role - keeping it simple
|
||||
26
roles/postgresql/templates/systemd-override.conf.j2
Normal file
26
roles/postgresql/templates/systemd-override.conf.j2
Normal file
@@ -0,0 +1,26 @@
|
||||
# PostgreSQL SystemD Security Override - Rick-Infra Simplified
|
||||
# Generated by Ansible PostgreSQL role
|
||||
|
||||
[Service]
|
||||
# Essential Security Restrictions
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
PrivateDevices=true
|
||||
ProtectHome=true
|
||||
ProtectSystem=strict
|
||||
ProtectKernelTunables=true
|
||||
ProtectKernelModules=true
|
||||
RestrictRealtime=true
|
||||
LockPersonality=true
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
||||
|
||||
# File System Access (PostgreSQL standard paths)
|
||||
ReadWritePaths=/var/lib/postgres
|
||||
|
||||
# Network Security (localhost only)
|
||||
{% if postgresql_listen_addresses == "localhost" %}
|
||||
IPAddressDeny=any
|
||||
IPAddressAllow=localhost
|
||||
{% endif %}
|
||||
|
||||
# Rick-Infra: Essential security hardening only
|
||||
Reference in New Issue
Block a user