feat: pg with extensions and open to podmans containers
This commit is contained in:
parent
ba37edd498
commit
e7dbe470da
@ -20,6 +20,24 @@ This Ansible role installs and configures PostgreSQL for local use only. It prov
|
||||
Available variables with defaults (see `defaults/main.yml`):
|
||||
|
||||
```yaml
|
||||
# PostgreSQL admin user
|
||||
postgres_admin_user: postgres
|
||||
|
||||
# PostgreSQL admin password (REQUIRED - must be set explicitly)
|
||||
# postgres_admin_password: "" # Intentionally undefined
|
||||
|
||||
# PostgreSQL data directory
|
||||
postgres_data_dir: /var/lib/postgres/data
|
||||
|
||||
# Network configuration
|
||||
postgres_listen_addresses: 127.0.0.1 # For container access: "127.0.0.1,{{ podman_subnet_gateway }}"
|
||||
postgres_port: 5432
|
||||
|
||||
# Firewall configuration
|
||||
postgres_firewall_allowed_sources:
|
||||
- 127.0.0.0/8 # Localhost
|
||||
- "{{ podman_subnet | default('10.88.0.0/16') }}" # Podman bridge network
|
||||
|
||||
# Performance tuning
|
||||
postgres_shared_buffers: 256MB
|
||||
postgres_effective_cache_size: 1GB
|
||||
@ -75,90 +93,38 @@ Each service role (immich, nextcloud, etc.) manages its own:
|
||||
- Each user has a unique password
|
||||
- Passwords stored in service role variables (use Ansible Vault for production)
|
||||
|
||||
## How to Use from Service Roles
|
||||
|
||||
### Pattern for Service Roles
|
||||
|
||||
When creating a service role that needs PostgreSQL:
|
||||
|
||||
**1. Add postgres as a dependency** (`meta/main.yml`):
|
||||
```yaml
|
||||
dependencies:
|
||||
- role: postgres
|
||||
```
|
||||
|
||||
**2. Define database variables** (`defaults/main.yml`):
|
||||
```yaml
|
||||
myservice_db_name: myservice
|
||||
myservice_db_user: myservice_user
|
||||
myservice_db_password: changeme # Use Ansible Vault in production!
|
||||
myservice_db_host: localhost
|
||||
myservice_db_port: 5432
|
||||
```
|
||||
|
||||
**3. Create database and user** (`tasks/main.yml`):
|
||||
```yaml
|
||||
- name: Create PostgreSQL database for myservice
|
||||
community.postgresql.postgresql_db:
|
||||
name: "{{ myservice_db_name }}"
|
||||
state: present
|
||||
become: true
|
||||
become_user: "{{ postgres_admin_user }}"
|
||||
|
||||
- name: Create PostgreSQL user for myservice
|
||||
community.postgresql.postgresql_user:
|
||||
name: "{{ myservice_db_user }}"
|
||||
password: "{{ myservice_db_password }}"
|
||||
db: "{{ myservice_db_name }}"
|
||||
priv: ALL
|
||||
state: present
|
||||
become: true
|
||||
become_user: "{{ postgres_admin_user }}"
|
||||
|
||||
- name: Ensure user has no superuser privileges
|
||||
community.postgresql.postgresql_user:
|
||||
name: "{{ myservice_db_user }}"
|
||||
role_attr_flags: NOSUPERUSER,NOCREATEDB,NOCREATEROLE
|
||||
state: present
|
||||
become: true
|
||||
become_user: "{{ postgres_admin_user }}"
|
||||
```
|
||||
|
||||
**Note:** `postgres_admin_user` is provided by the postgres role and defaults to `postgres`.
|
||||
|
||||
**4. Configure your service** to connect to:
|
||||
```
|
||||
Host: localhost
|
||||
Port: 5432
|
||||
Database: myservice
|
||||
User: myservice_user
|
||||
Password: changeme
|
||||
```
|
||||
|
||||
### Real Example: Immich
|
||||
|
||||
See `roles/immich/` for a complete working example of using this pattern.
|
||||
|
||||
## Connection Methods
|
||||
|
||||
### From Containers
|
||||
|
||||
If your service runs in a container (Docker/Podman), you need to:
|
||||
If your service runs in a container (Docker/Podman), you need to configure PostgreSQL to listen on the Podman bridge gateway:
|
||||
|
||||
**Option 1: Use host network mode**
|
||||
**Step 1: Configure PostgreSQL in inventory**
|
||||
```yaml
|
||||
network_mode: host
|
||||
# inventory/host_vars/yourserver.yml
|
||||
postgres_listen_addresses: "127.0.0.1,{{ podman_subnet_gateway }}"
|
||||
postgres_firewall_allowed_sources:
|
||||
- 127.0.0.0/8
|
||||
- "{{ podman_subnet }}"
|
||||
```
|
||||
Then connect to `localhost:5432`
|
||||
|
||||
**Option 2: Use host.containers.internal (Podman/Docker)**
|
||||
**Step 2: Use host.containers.internal in containers**
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
services:
|
||||
myservice:
|
||||
extra_hosts:
|
||||
- "host.containers.internal:host-gateway"
|
||||
environment:
|
||||
DB_HOSTNAME: host.containers.internal
|
||||
DB_PORT: 5432
|
||||
```
|
||||
|
||||
**Option 3: Bridge with firewall (less secure)**
|
||||
Bind postgres to `0.0.0.0` and use container gateway IP.
|
||||
**What this does:**
|
||||
- PostgreSQL listens on `127.0.0.1` (localhost) and `10.88.0.1` (Podman gateway)
|
||||
- UFW firewall allows connections from localhost and Podman subnet
|
||||
- `pg_hba.conf` automatically configured to allow Podman subnet
|
||||
- `host.containers.internal` resolves to the gateway IP inside containers
|
||||
|
||||
### From System Services
|
||||
|
||||
@ -198,11 +164,14 @@ The pattern above ensures users have:
|
||||
- ❌ Cannot create roles
|
||||
- ❌ Cannot access other databases
|
||||
|
||||
### 4. Local-Only Access
|
||||
### 4. Controlled Access
|
||||
|
||||
PostgreSQL is configured to listen on `localhost` only:
|
||||
- No remote connections allowed
|
||||
- Services must run on the same host
|
||||
PostgreSQL default configuration:
|
||||
- Listens on `localhost` only by default
|
||||
- To allow container access, set `postgres_listen_addresses` to include Podman gateway
|
||||
- UFW firewall rules automatically configured for allowed sources
|
||||
- `pg_hba.conf` automatically configured for Podman subnet when enabled
|
||||
- No remote network access by default
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
@ -228,7 +197,20 @@ sudo -u postgres psql
|
||||
|
||||
### Test connection from service
|
||||
```bash
|
||||
# From localhost
|
||||
psql -h localhost -U immich -d immich
|
||||
|
||||
# From Podman gateway (if configured)
|
||||
psql -h 10.88.0.1 -U immich -d immich
|
||||
|
||||
# Check listen addresses
|
||||
sudo -u postgres psql -c "SHOW listen_addresses;"
|
||||
|
||||
# Check firewall rules
|
||||
sudo ufw status | grep 5432
|
||||
|
||||
# Check pg_hba.conf
|
||||
sudo grep -v "^#" /var/lib/postgres/data/pg_hba.conf | grep -v "^$"
|
||||
```
|
||||
|
||||
### View logs
|
||||
|
||||
@ -1,15 +1,25 @@
|
||||
---
|
||||
# PostgreSQL admin user (used by service roles for database management)
|
||||
# PostgreSQL port
|
||||
postgres_port: 5432
|
||||
|
||||
# PostgreSQL admin user (only for database management)
|
||||
postgres_admin_user: postgres
|
||||
|
||||
# PostgreSQL admin password (REQUIRED - must be set explicitly)
|
||||
# Set via inventory, host_vars, or ansible-vault
|
||||
# See this file's comments for setup instructions
|
||||
# postgres_admin_password: "" # Intentionally undefined - role will fail if not set
|
||||
# postgres_admin_password: ""
|
||||
|
||||
# PostgreSQL data directory
|
||||
postgres_data_dir: /var/lib/postgres/data
|
||||
|
||||
# Binding address(es)
|
||||
postgres_listen_addresses: "127.0.0.1,{{ podman_subnet_gateway | default('10.88.0.1' }}"
|
||||
|
||||
# Firewall configuration
|
||||
postgres_firewall_allowed_sources:
|
||||
- 127.0.0.0/8 # Localhost
|
||||
- "{{ podman_subnet | default('10.88.0.0/16') }}" # Podman bridge network
|
||||
|
||||
# Performance tuning (adjust based on your hardware)
|
||||
postgres_shared_buffers: 256MB
|
||||
postgres_effective_cache_size: 1GB
|
||||
|
||||
38
roles/postgres/tasks/archlinux.yml
Normal file
38
roles/postgres/tasks/archlinux.yml
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
- name: Check if pgvector is installed
|
||||
ansible.builtin.command: pacman -Qi pgvector
|
||||
register: pgvector_installed
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Install pgvector from AUR
|
||||
when: pgvector_installed.rc != 0
|
||||
block:
|
||||
- name: Disable SUDOERS password prompt for AUR installation
|
||||
no_log: true
|
||||
ansible.builtin.lineinfile:
|
||||
dest: /etc/sudoers
|
||||
state: present
|
||||
regexp: "^#?%wheel"
|
||||
line: "%wheel ALL=(ALL) NOPASSWD: ALL"
|
||||
validate: /usr/sbin/visudo -cf %s
|
||||
|
||||
- name: Install pgvector from AUR
|
||||
become: false
|
||||
ansible.builtin.command:
|
||||
cmd: "paru -S --noconfirm pgvector"
|
||||
|
||||
- name: Restore SUDOERS password prompt after AUR installation
|
||||
no_log: true
|
||||
ansible.builtin.lineinfile:
|
||||
dest: /etc/sudoers
|
||||
state: present
|
||||
regexp: "^#?%wheel"
|
||||
line: "%wheel ALL=(ALL:ALL) ALL"
|
||||
validate: /usr/sbin/visudo -cf %s
|
||||
|
||||
- name: Ensure PostgreSQL is initialized
|
||||
ansible.builtin.command:
|
||||
cmd: initdb -D {{ postgres_data_dir }}
|
||||
creates: "{{ postgres_data_dir }}/PG_VERSION"
|
||||
become_user: "{{ postgres_admin_user }}"
|
||||
16
roles/postgres/tasks/debian.yml
Normal file
16
roles/postgres/tasks/debian.yml
Normal file
@ -0,0 +1,16 @@
|
||||
---
|
||||
- name: Create current version symlink
|
||||
ansible.builtin.shell:
|
||||
cmd: set -o pipefail && ln -sf $(ls -1 /etc/postgresql/ | grep -E '^[0-9]+$' | sort -V | tail -n1) /etc/postgresql/current
|
||||
creates: /etc/postgresql/current
|
||||
executable: /bin/bash
|
||||
|
||||
- name: Get installed PostgreSQL version
|
||||
ansible.builtin.shell: psql --version | grep -oP '\d+' | head -1
|
||||
register: postgres_version
|
||||
changed_when: false
|
||||
|
||||
- name: Install pgvector extension
|
||||
ansible.builtin.package:
|
||||
name: "postgresql-{{ postgres_version.stdout }}-pgvector"
|
||||
state: present
|
||||
@ -20,20 +20,8 @@
|
||||
name: "{{ postgres_packages }}"
|
||||
state: present
|
||||
|
||||
- name: Create current version symlink (Debian)
|
||||
ansible.builtin.shell:
|
||||
cmd: set -o pipefail && ln -sf $(ls -1 /etc/postgresql/ | grep -E '^[0-9]+$' | sort -V | tail -n1) /etc/postgresql/current
|
||||
creates: /etc/postgresql/current
|
||||
executable: /bin/bash
|
||||
when: ansible_facts['os_family'] == 'Debian'
|
||||
|
||||
- name: Ensure PostgreSQL is initialized (Arch)
|
||||
ansible.builtin.command:
|
||||
cmd: initdb -D {{ postgres_data_dir }}
|
||||
creates: "{{ postgres_data_dir }}/PG_VERSION"
|
||||
become: true
|
||||
become_user: "{{ postgres_admin_user }}"
|
||||
when: ansible_facts['os_family'] == 'Archlinux'
|
||||
- name: Include OS-specific tasks
|
||||
ansible.builtin.include_tasks: "{{ ansible_facts['os_family'] | lower }}.yml"
|
||||
|
||||
- name: Ensure PostgreSQL config directory exists
|
||||
ansible.builtin.file:
|
||||
@ -60,6 +48,25 @@
|
||||
mode: "0640"
|
||||
notify: Restart PostgreSQL
|
||||
|
||||
- name: Configure pg_hba.conf for Podman subnet access
|
||||
ansible.builtin.lineinfile:
|
||||
path: "{{ postgres_hba_path }}"
|
||||
line: "host all all {{ podman_subnet }} scram-sha-256"
|
||||
insertafter: "^# IPv4 local connections:"
|
||||
state: present
|
||||
when: podman_subnet is defined
|
||||
notify: Restart PostgreSQL
|
||||
|
||||
- name: Setup firewall rules for PostgreSQL
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
src: "{{ item }}"
|
||||
port: "{{ postgres_port }}"
|
||||
proto: tcp
|
||||
direction: in
|
||||
comment: "PostgreSQL"
|
||||
loop: "{{ postgres_firewall_allowed_sources }}"
|
||||
|
||||
- name: Enable and start PostgreSQL service
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ postgres_service_name }}"
|
||||
@ -71,5 +78,4 @@
|
||||
name: "{{ postgres_admin_user }}"
|
||||
password: "{{ postgres_admin_password }}"
|
||||
state: present
|
||||
become: true
|
||||
become_user: "{{ postgres_admin_user }}"
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
# Custom PostgreSQL configuration managed by Ansible
|
||||
# Override settings from main postgresql.conf
|
||||
|
||||
# Network configuration
|
||||
listen_addresses = '{{ postgres_listen_addresses }}'
|
||||
port = {{ postgres_port }}
|
||||
|
||||
# Performance tuning
|
||||
shared_buffers = {{ postgres_shared_buffers }}
|
||||
effective_cache_size = {{ postgres_effective_cache_size }}
|
||||
|
||||
@ -3,6 +3,10 @@ postgres_packages:
|
||||
- postgresql
|
||||
- python-psycopg2
|
||||
|
||||
# AUR packages (installed via paru)
|
||||
postgres_aur_packages:
|
||||
- pgvector
|
||||
|
||||
postgres_service_name: postgresql
|
||||
postgres_config_path: "{{ postgres_data_dir }}/postgresql.conf"
|
||||
postgres_config_dir: "{{ postgres_data_dir }}/conf.d"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user