├── molecule └── default │ ├── collections.yml │ ├── converge.yml │ ├── prepare.yml │ ├── verify.yml │ └── molecule.yml ├── vars ├── empty.yml ├── focal.yml ├── bionic.yml ├── buster.yml ├── bullseye.yml ├── postgresql_12.yml ├── postgresql_13.yml └── postgresql_11.yml ├── templates ├── repmgr.custom.conf.j2 ├── etc_apt_preferences.d_apt_postgresql_org_pub_repos_apt.pref.j2 ├── repmgr_barman_ssh_config.j2 ├── repmgr_logroate.j2 ├── sudoers.postgresql.j2 ├── pgpass.j2 ├── etc_systemd_system_postgresql.service.d_custom.conf.j2 ├── pg_hba.conf.j2 ├── pg_ident.conf.j2 ├── repmgr.conf-5.1.orig ├── repmgr.conf-5.2.orig ├── repmgr.conf-5.3.orig ├── repmgr.conf-5.1.j2 ├── repmgr.conf-5.2.j2 └── repmgr.conf-5.3.j2 ├── requirements.txt ├── tasks ├── fdw.yml ├── extensions │ ├── dev_headers.yml │ ├── contrib.yml │ ├── postgis.yml │ ├── repmgr.yml │ ├── detect_repmgr_primary.yml │ └── configure_repmgr.yml ├── extensions.yml ├── users_privileges.yml ├── schemas.yml ├── users.yml ├── check_pg_version_mismatch.yml ├── main.yml ├── install_apt.yml ├── databases.yml └── configure.yml ├── .ansible-lint ├── handlers └── main.yml ├── meta └── main.yml ├── .yamllint ├── LICENSE ├── .travis.yml ├── inventory.example.yml ├── defaults └── main │ └── 002-repmgr.yml └── README.md /molecule/default/collections.yml: -------------------------------------------------------------------------------- 1 | --- 2 | collections: 3 | - community.crypto 4 | -------------------------------------------------------------------------------- /vars/empty.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # This file intentionally does not define any variables. 3 | -------------------------------------------------------------------------------- /vars/focal.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # PostgreSQL vars for Ubuntu Focal (20.04LTS) 3 | postgresql_systemctl_path: /bin 4 | -------------------------------------------------------------------------------- /vars/bionic.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # PostgreSQL vars for Ubuntu Bionic (18.04LTS) 3 | postgresql_systemctl_path: /bin 4 | -------------------------------------------------------------------------------- /vars/buster.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # PostgreSQL vars for Debian Buster (10.x) 3 | postgresql_systemctl_path: /usr/bin 4 | -------------------------------------------------------------------------------- /vars/bullseye.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # PostgreSQL vars for Debian Bullseye (11.x) 3 | postgresql_systemctl_path: /usr/bin 4 | -------------------------------------------------------------------------------- /templates/repmgr.custom.conf.j2: -------------------------------------------------------------------------------- 1 | [Service] 2 | # Location of repmgr conf file: 3 | Environment=REPMGRDCONF={{ postgresql_conf_directory }}/repmgr.conf 4 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | ansible>=6 2 | molecule>=4.0.3 3 | molecule-vagrant>=1.0.0 4 | ansible-lint==6.9.0 5 | cryptography>=3.0 6 | yamllint 7 | python-vagrant 8 | pyOpenSSL 9 | -------------------------------------------------------------------------------- /vars/postgresql_12.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # PostgreSQL vars for v12 3 | postgresql_stats_temp_directory: /var/run/postgresql/{{ postgresql_version }}-{{ postgresql_cluster_name }}.pg_stat_tmp/ 4 | -------------------------------------------------------------------------------- /vars/postgresql_13.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # PostgreSQL vars for v13 3 | postgresql_stats_temp_directory: /var/run/postgresql/{{ postgresql_version }}-{{ postgresql_cluster_name }}.pg_stat_tmp/ 4 | -------------------------------------------------------------------------------- /templates/etc_apt_preferences.d_apt_postgresql_org_pub_repos_apt.pref.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | 3 | Package: * 4 | Pin: release o=apt.postgresql.org 5 | Pin-Priority: {{ postgresql_apt_pin_priority }} 6 | -------------------------------------------------------------------------------- /templates/repmgr_barman_ssh_config.j2: -------------------------------------------------------------------------------- 1 | Host {{ repmgr_barman_host }} 2 | Hostname {{ repmgr_barman_host }} 3 | User {{ repmgr_barman_user }} 4 | Port {{ repmgr_barman_port }} 5 | IdentityFile ~/.ssh/id_rsa 6 | -------------------------------------------------------------------------------- /vars/postgresql_11.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # PostgreSQL vars for v11 3 | postgresql_stats_temp_directory: /var/run/postgresql/{{ postgresql_version }}-{{ postgresql_cluster_name }}.pg_stat_tmp/ 4 | postgresql_jit: off 5 | postgresql_autovacuum_vacuum_cost_delay: 20ms 6 | -------------------------------------------------------------------------------- /templates/repmgr_logroate.j2: -------------------------------------------------------------------------------- 1 | {{ repmgr_log_file }} { 2 | missingok 3 | compress 4 | rotate 52 5 | maxsize 100M 6 | weekly 7 | create 0600 postgres postgres 8 | postrotate 9 | /usr/bin/killall -HUP repmgrd 10 | endscript 11 | } 12 | -------------------------------------------------------------------------------- /tasks/fdw.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: PostgreSQL | FDW | MySQL 3 | ansible.builtin.package: 4 | name: "{{ postgresql_fdw_mysql_packages }}" 5 | state: present 6 | when: postgresql_fdw_mysql 7 | 8 | - name: PostgreSQL | FDW | OGR 9 | ansible.builtin.package: 10 | name: "{{ postgresql_fdw_ogr_packages }}" 11 | state: present 12 | when: postgresql_fdw_ogr 13 | -------------------------------------------------------------------------------- /.ansible-lint: -------------------------------------------------------------------------------- 1 | --- 2 | # https://docs.ansible.com/ansible-lint/rules/default_rules.html 3 | exclude_paths: 4 | - ../.ansible/roles/ 5 | - .cache/ 6 | - .github/ 7 | verbosity: 1 8 | use_default_rules: true 9 | skip_list: 10 | - command-instead-of-shell 11 | - no-changed-when 12 | - no-handler 13 | - empty-string-compare 14 | warn_list: 15 | - no-log-password 16 | -------------------------------------------------------------------------------- /tasks/extensions/dev_headers.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: PostgreSQL | Extensions | Make sure the development headers are installed | Debian 3 | ansible.builtin.apt: 4 | name: libpq-dev 5 | state: present 6 | update_cache: yes 7 | cache_valid_time: "{{ apt_cache_valid_time | default(3600) }}" 8 | when: ansible_os_family == "Debian" 9 | notify: Restart postgresql 10 | -------------------------------------------------------------------------------- /templates/sudoers.postgresql.j2: -------------------------------------------------------------------------------- 1 | # this is required when running sudo over ssh without -t: 2 | Defaults:{{ postgresql_admin_user }} !requiretty 3 | {{ postgresql_admin_user }} ALL = NOPASSWD: /usr/bin/pg_ctlcluster *, \ 4 | /usr/lib/postgresql/{{ postgresql_version }}/bin/pg_ctl, \ 5 | {{ postgresql_systemctl_path }}/systemctl start repmgrd, \ 6 | {{ postgresql_systemctl_path }}/systemctl stop repmgrd 7 | -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Restart postgresql 3 | ansible.builtin.shell: 4 | cmd: pg_ctlcluster {{ postgresql_version }} {{ postgresql_cluster_name }} restart 5 | executable: /bin/bash 6 | become: yes 7 | become_user: "{{ postgresql_service_user }}" 8 | 9 | - name: Reload repmgr 10 | ansible.builtin.sysvinit: 11 | name: repmgrd 12 | state: reloaded 13 | become: yes 14 | -------------------------------------------------------------------------------- /templates/pgpass.j2: -------------------------------------------------------------------------------- 1 | {% for server in repmgr_target_group_hosts %} 2 | {{ server }}:{{ postgresql_port }}:{{ repmgr_database }}:{{ repmgr_user }}:{% for user in postgresql_users if user['name'] == repmgr_user %}{{user['pass']}}{% endfor %} 3 | {{ server }}:{{ postgresql_port }}:replication:{{repmgr_replication_user}}:{% for user in postgresql_users if user['name'] == repmgr_user %}{{user['pass']}}{% endfor %} 4 | {% endfor %} 5 | -------------------------------------------------------------------------------- /tasks/extensions/contrib.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: PostgreSQL | Extensions | Make sure the postgres contrib extensions are installed | Debian 3 | ansible.builtin.apt: 4 | name: "postgresql-contrib-{{ postgresql_version }}" 5 | state: present 6 | update_cache: yes 7 | cache_valid_time: "{{ apt_cache_valid_time | default(3600) }}" 8 | when: ansible_os_family == "Debian" 9 | notify: 10 | - Restart postgresql 11 | -------------------------------------------------------------------------------- /tasks/extensions/postgis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - ansible.builtin.include_vars: "{{ item }}" 3 | with_first_found: 4 | - "../vars/{{ ansible_distribution_release }}.yml" 5 | - "../vars/empty.yml" 6 | tags: skip_ansible_lint 7 | 8 | - name: PostgreSQL | Extensions | Make sure the postgis extensions are installed | Debian 9 | ansible.builtin.apt: 10 | name: "{{ postgresql_ext_postgis_deps }}" 11 | state: present 12 | update_cache: yes 13 | cache_valid_time: "{{ apt_cache_valid_time | default(3600) }}" 14 | when: ansible_os_family == "Debian" 15 | notify: Restart postgresql 16 | -------------------------------------------------------------------------------- /tasks/extensions.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install contrib extensions 3 | ansible.builtin.import_tasks: extensions/contrib.yml 4 | when: postgresql_ext_install_contrib 5 | - name: Install development headers 6 | ansible.builtin.import_tasks: extensions/dev_headers.yml 7 | when: postgresql_ext_install_dev_headers 8 | - name: Install Postgis extension 9 | ansible.builtin.import_tasks: extensions/postgis.yml 10 | when: postgresql_ext_install_postgis 11 | - name: Install Repmgr 12 | ansible.builtin.import_tasks: extensions/repmgr.yml 13 | when: postgresql_ext_install_repmgr and ansible_service_mgr == 'systemd' 14 | -------------------------------------------------------------------------------- /tasks/users_privileges.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: PostgreSQL | Update the user privileges 3 | community.postgresql.postgresql_user: 4 | name: "{{ item.name }}" 5 | db: "{{ item.db | default(omit) }}" 6 | port: "{{ postgresql_port }}" 7 | priv: "{{ item.priv | default(omit) }}" 8 | state: present 9 | login_host: "{{ item.host | default(omit) }}" 10 | login_user: "{{ postgresql_admin_user }}" 11 | role_attr_flags: "{{ item.role_attr_flags | default(omit) }}" 12 | become: yes 13 | become_user: "{{ postgresql_admin_user }}" 14 | with_items: "{{ postgresql_user_privileges }}" 15 | when: postgresql_users|length > 0 and repmgr_primary 16 | -------------------------------------------------------------------------------- /tasks/schemas.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: PostgreSQL | Add Schema to databases 3 | community.postgresql.postgresql_schema: 4 | database: "{{ item.database }}" 5 | schema: "{{ item.schema }}" 6 | owner: "{{ item.owner | default(postgresql_database_owner) }}" 7 | login_host: "{{ item.host | default(omit) }}" 8 | login_password: "{{ item.password | default(omit) }}" 9 | login_user: "{{ postgresql_admin_user }}" 10 | port: "{{ postgresql_port }}" 11 | state: "{{ item.state | default(present) }}" 12 | become: yes 13 | become_user: "{{ postgresql_admin_user }}" 14 | with_items: "{{ postgresql_database_schemas }}" 15 | when: postgresql_databases|length > 0 16 | -------------------------------------------------------------------------------- /templates/etc_systemd_system_postgresql.service.d_custom.conf.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | # Systemd unit file override to specify user/group as well as separate config 3 | # and data directories. 4 | [Service] 5 | User={{ postgresql_service_user }} 6 | Group={{ postgresql_service_group }} 7 | 8 | Environment=PGDATA={{ postgresql_conf_directory }} 9 | ExecStartPre= 10 | {% if postgresql_version is version_compare('10', '>=') %} 11 | ExecStartPre={{ postgresql_bin_directory }}/postgresql-{{ postgresql_version_terse }}-check-db-dir {{ postgresql_data_directory }} 12 | {% else %} 13 | ExecStartPre={{ postgresql_bin_directory }}/postgresql{{ postgresql_version_terse }}-check-db-dir {{ postgresql_data_directory }} 14 | {% endif %} 15 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: Frank FIDANZA 4 | company: RG 5 | namespace: fidanf 6 | role_name: postgresql_ha 7 | description: Install and configure PostgreSQL cluster managed with repmgr. Add dependencies, extensions, databases and users. 8 | min_ansible_version: '2.12' 9 | license: MIT 10 | platforms: 11 | - name: Debian 12 | versions: 13 | - buster 14 | - name: Ubuntu 15 | versions: 16 | - bionic 17 | galaxy_tags: 18 | - postgresql 19 | - postgres 20 | - cluster 21 | - repmgr 22 | - pgpool 23 | - database 24 | - rdbms 25 | - sql 26 | - postgis 27 | - debian 28 | - ubuntu 29 | collections: 30 | - community.crypto 31 | -------------------------------------------------------------------------------- /molecule/default/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: pgcluster 4 | gather_facts: yes 5 | become: yes 6 | 7 | pre_tasks: 8 | - name: Debug variables 9 | ansible.builtin.debug: 10 | msg: 11 | "ansible_python_version": "{{ ansible_python_version }}" 12 | "ansible_version.full": "{{ ansible_version.full }}" 13 | "postgresql_version": "{{ postgresql_version }}" 14 | "repmgr_version": "{{ repmgr_version }}" 15 | "repmgr_master": "{{ repmgr_master }}" 16 | "repmgr_target_group": "{{ repmgr_target_group }}" 17 | "repmgr_node_id": "{{ repmgr_node_id }}" 18 | roles: 19 | - role: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}" 20 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | # Based on ansible-lint config 3 | extends: default 4 | ignore: | 5 | *vault.yml 6 | rules: 7 | braces: 8 | max-spaces-inside: 1 9 | level: error 10 | brackets: 11 | max-spaces-inside: 1 12 | level: error 13 | colons: 14 | max-spaces-after: -1 15 | level: error 16 | commas: 17 | max-spaces-after: -1 18 | level: error 19 | comments: disable 20 | comments-indentation: disable 21 | document-start: { present: true } 22 | empty-lines: 23 | max: 3 24 | level: error 25 | hyphens: 26 | level: error 27 | indentation: { spaces: 2 } 28 | key-duplicates: enable 29 | line-length: disable 30 | new-lines: disable 31 | new-line-at-end-of-file: enable 32 | trailing-spaces: disable 33 | truthy: { allowed-values: ['yes', 'no', 'true', 'false', 'on', 'off'] } 34 | -------------------------------------------------------------------------------- /tasks/users.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: PostgreSQL | Ensure PostgreSQL is running 3 | ansible.builtin.shell: 4 | cmd: pg_ctlcluster {{ postgresql_version }} {{ postgresql_cluster_name }} status 5 | executable: /bin/bash 6 | become: yes 7 | become_user: "{{ postgresql_service_user }}" 8 | 9 | - name: PostgreSQL | Make sure the PostgreSQL users are present 10 | community.postgresql.postgresql_user: 11 | name: "{{ item.name }}" 12 | password: "{{ item.pass | default(omit) }}" 13 | encrypted: "{{ item.encrypted | default(omit) }}" 14 | port: "{{ postgresql_port }}" 15 | state: present 16 | login_user: "{{ postgresql_admin_user }}" 17 | # no_log: true 18 | become: yes 19 | become_user: "{{ postgresql_admin_user }}" 20 | with_items: "{{ postgresql_users }}" 21 | when: postgresql_users|length > 0 and repmgr_primary 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Frank Fidanza 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /molecule/default/prepare.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Prepare 3 | hosts: pgcluster 4 | gather_facts: no 5 | become: yes 6 | 7 | pre_tasks: 8 | - name: Wait for SSH 9 | ansible.builtin.wait_for_connection: 10 | 11 | - name: Gather facts for the first time 12 | ansible.builtin.setup: 13 | 14 | - name: Install python dependencies 15 | ansible.builtin.apt: 16 | name: 17 | - python3-apt 18 | update_cache: yes 19 | 20 | - name: Use python3 by default 21 | community.general.system.alternatives: 22 | path: /usr/bin/python3 23 | link: /usr/bin/python 24 | name: python 25 | priority: 1 26 | 27 | - name: Build hosts file 28 | ansible.builtin.lineinfile: 29 | path: /etc/hosts 30 | regexp: '.*{{ item }}$' 31 | line: "{{ hostvars[item].ansible_eth1.ipv4.address }} {{ item }}" 32 | state: present 33 | mode: 0644 34 | when: hostvars[item].ansible_eth1.ipv4.address is defined 35 | loop: "{{ groups[repmgr_target_group] }}" 36 | 37 | - name: Install acl package 38 | ansible.builtin.apt: 39 | name: acl 40 | -------------------------------------------------------------------------------- /tasks/extensions/repmgr.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: PostgreSQL | Extensions | Add 2nd Quadrant repo gpg key | apt 3 | ansible.builtin.apt_key: 4 | url: "{{ repmgr_gpg_key_url }}" 5 | when: ansible_pkg_mgr == "apt" and repmgr_apt_repository_add 6 | 7 | - name: PostgreSQL | Extensions | Add 2nd Quadrant repo for repmgr | apt 8 | ansible.builtin.apt_repository: 9 | repo: "{{ repmgr_apt_repository }}" 10 | filename: 2ndquadrant-dl-default-release 11 | when: ansible_pkg_mgr == "apt" and repmgr_apt_repository_add 12 | 13 | - name: PostgreSQL | Extensions | Use specific version from repo | apt 14 | ansible.builtin.set_fact: 15 | repmgr_apt_name: "postgresql-{{ postgresql_version }}-repmgr={{ repmgr_version_debian }}" 16 | when: 17 | - ansible_os_family == "Debian" 18 | - repmgr_version_debian is defined 19 | 20 | - name: PostgreSQL | Extensions | Make sure the postgres repmgr extensions are installed | apt 21 | ansible.builtin.apt: 22 | name: "{{ repmgr_apt_name | default('postgresql-' + postgresql_version | string + '-repmgr') }}" 23 | state: present 24 | update_cache: yes 25 | cache_valid_time: "{{ apt_cache_valid_time | default(3600) }}" 26 | when: ansible_pkg_mgr == "apt" 27 | notify: Restart postgresql 28 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | os: linux 3 | dist: focal 4 | language: python 5 | python: 6 | - 3.8 7 | env: 8 | global: 9 | - VAGRANT_DEFAULT_PROVIDER: libvirt 10 | - PY_COLORS: 1 11 | jobs: 12 | - MOLECULE_DISTRO: generic/ubuntu2004 13 | - MOLECULE_DISTRO: generic/debian11 14 | cache: 15 | directories: 16 | - /home/travis/.vagrant.d/boxes 17 | pip: true 18 | before_install: 19 | - | 20 | wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg 21 | echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list 22 | sudo apt update && sudo apt install vagrant 23 | install: 24 | - | 25 | sudo apt-get install -y build-essential qemu-kvm qemu-utils libvirt-dev libvirt-daemon-system libvirt-clients bridge-utils virtinst virt-manager dnsmasq 26 | CONFIGURE_ARGS="with-libvirt-include=/usr/share/libvirt with-libvirt-lib=/usr/lib64" sudo vagrant plugin install vagrant-libvirt 27 | before_script: 28 | - | 29 | sudo -H pip install --upgrade --ignore-installed --requirement requirements.txt 30 | molecule --version 31 | script: 32 | - | 33 | sudo -E molecule -vvv test 34 | -------------------------------------------------------------------------------- /tasks/check_pg_version_mismatch.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: PostgreSQL | Check binary version 3 | ansible.builtin.shell: 4 | cmd: | 5 | set -o pipefail 6 | psql --version | sed 's/^psql (//' | sed 's/)//' | awk '{print $1, $2}' 7 | executable: /bin/bash 8 | become: yes 9 | become_user: "{{ postgresql_service_user }}" 10 | changed_when: false 11 | failed_when: postgresql_binary_version.stdout == "" 12 | register: postgresql_binary_version 13 | check_mode: no 14 | 15 | - name: PostgreSQL | Check database version 16 | ansible.builtin.shell: 17 | cmd: | 18 | set -o pipefail 19 | psql --quiet --tuples-only --port={{ postgresql_port | int }} --command="select substring(version(),'[^\s]+\s+[^\s]+');" | sed 's/^ //' 20 | executable: /bin/bash 21 | become: yes 22 | become_user: "{{ postgresql_service_user }}" 23 | changed_when: false 24 | failed_when: postgresql_database_version.stdout == "" 25 | register: postgresql_database_version 26 | check_mode: no 27 | 28 | - name: PostgreSQL | Verify binary and database versions match 29 | ansible.builtin.debug: 30 | msg: "WARNING: Binary ({{ postgresql_binary_version.stdout }}) and Database ({{ postgresql_database_version.stdout }}) version mismatch. Restart required!" 31 | when: postgresql_binary_version.stdout != postgresql_database_version.stdout 32 | changed_when: postgresql_binary_version.stdout != postgresql_database_version.stdout 33 | notify: Restart postgresql 34 | -------------------------------------------------------------------------------- /tasks/extensions/detect_repmgr_primary.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Repmgr | Get hosts from targeted group 3 | ansible.builtin.set_fact: 4 | repmgr_target_group_hosts: "{{ groups[repmgr_target_group] }}" 5 | 6 | - name: Repmgr | Detect primary 7 | ansible.builtin.shell: "repmgr -f {{ postgresql_conf_directory }}/repmgr.conf cluster show | grep primary | cut -d '|' -f 2" 8 | register: repmgr_primary_check 9 | become: yes 10 | become_user: "{{ postgresql_service_user }}" 11 | ignore_errors: yes 12 | 13 | - name: Repmgr | Debug check 14 | ansible.builtin.debug: 15 | msg: 16 | "repmgr_primary_hostname": "{{ repmgr_primary_check.stdout | trim }}" 17 | "repmgr_is_primary": "{{ ansible_hostname == repmgr_primary_check.stdout | trim }}" 18 | verbosity: 1 19 | 20 | - name: Repmgr | Declare as primary for existing installation 21 | ansible.builtin.set_fact: 22 | repmgr_primary: "{{ ansible_hostname == repmgr_primary_check.stdout | trim }}" 23 | when: repmgr_primary_check.stdout is defined and repmgr_primary_check.rc == 0 24 | 25 | - name: Repmgr | Declare as primary for new installation 26 | ansible.builtin.set_fact: 27 | repmgr_primary: "{{ ansible_hostname == repmgr_master }}" 28 | when: repmgr_primary_check.stdout == "" 29 | 30 | - name: Repmgr | Ensure repmgr_master host exists 31 | ansible.builtin.fail: 32 | msg: "{{ repmgr_master }} was not found in {{ repmgr_target_group }}" 33 | when: 34 | - repmgr_primary_check.stdout == "" and 35 | repmgr_master is not in repmgr_target_group_hosts 36 | -------------------------------------------------------------------------------- /templates/pg_hba.conf.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | # PostgreSQL Client Authentication Configuration File 3 | # =================================================== 4 | # 5 | # Refer to the "Client Authentication" section in the PostgreSQL 6 | # documentation for a complete description of this file. A short 7 | # synopsis follows. 8 | # 9 | # This file controls: which hosts are allowed to connect, how clients 10 | # are authenticated, which PostgreSQL user names they can use, which 11 | # databases they can access. Records take one of these forms: 12 | # 13 | # local DATABASE USER METHOD [OPTIONS] 14 | # host DATABASE USER ADDRESS METHOD [OPTIONS] 15 | # hostssl DATABASE USER ADDRESS METHOD [OPTIONS] 16 | # hostnossl DATABASE USER ADDRESS METHOD [OPTIONS] 17 | # 18 | # TYPE DATABASE USER ADDRESS METHOD 19 | 20 | # Default: 21 | {% for connection in postgresql_pg_hba_default %} 22 | {% if connection.comment is defined %} 23 | # {{connection.comment}} 24 | {% endif %} 25 | {{connection.type}} {{connection.database}} {{connection.user}} {{connection.address}} {{connection.method}} 26 | {% endfor %} 27 | 28 | # MD5 hashed password hosts 29 | {% for host in postgresql_pg_hba_md5_hosts %} 30 | host all all {{host}} md5 31 | {% endfor %} 32 | 33 | # Password hosts 34 | {% for host in postgresql_pg_hba_passwd_hosts %} 35 | host all all {{host}} password 36 | {% endfor %} 37 | 38 | # Trusted hosts 39 | {% for host in postgresql_pg_hba_trust_hosts %} 40 | host all all {{host}} trust 41 | {% endfor %} 42 | 43 | # User custom 44 | {% for connection in postgresql_pg_hba_custom %} 45 | {% if connection.comment is defined %} 46 | # {{connection.comment}} 47 | {% endif %} 48 | {{connection.type}} {{connection.database}} {{connection.user}} {{connection.address}} {{connection.method}} 49 | {% endfor %} 50 | -------------------------------------------------------------------------------- /templates/pg_ident.conf.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | # PostgreSQL User Name Maps 3 | # ========================= 4 | # 5 | # Refer to the PostgreSQL documentation, chapter "Client 6 | # Authentication" for a complete description. A short synopsis 7 | # follows. 8 | # 9 | # This file controls PostgreSQL user name mapping. It maps external 10 | # user names to their corresponding PostgreSQL user names. Records 11 | # are of the form: 12 | # 13 | # MAPNAME SYSTEM-USERNAME PG-USERNAME 14 | # 15 | # (The uppercase quantities must be replaced by actual values.) 16 | # 17 | # MAPNAME is the (otherwise freely chosen) map name that was used in 18 | # pg_hba.conf. SYSTEM-USERNAME is the detected user name of the 19 | # client. PG-USERNAME is the requested PostgreSQL user name. The 20 | # existence of a record specifies that SYSTEM-USERNAME may connect as 21 | # PG-USERNAME. 22 | # 23 | # If SYSTEM-USERNAME starts with a slash (/), it will be treated as a 24 | # regular expression. Optionally this can contain a capture (a 25 | # parenthesized subexpression). The substring matching the capture 26 | # will be substituted for \1 (backslash-one) if present in 27 | # PG-USERNAME. 28 | # 29 | # Multiple maps may be specified in this file and used by pg_hba.conf. 30 | # 31 | # No map names are defined in the default configuration. If all 32 | # system user names and PostgreSQL user names are the same, you don't 33 | # need anything in this file. 34 | # 35 | # This file is read on server startup and when the postmaster receives 36 | # a SIGHUP signal. If you edit the file on a running system, you have 37 | # to SIGHUP the postmaster for the changes to take effect. You can 38 | # use "pg_ctl reload" to do that. 39 | 40 | # Put your actual configuration here 41 | # ---------------------------------- 42 | 43 | # MAPNAME SYSTEM-USERNAME PG-USERNAME 44 | {% for pg_ident in postgresql_pg_ident %} 45 | {% if pg_ident.comment is defined %} 46 | # {{ pg_ident.comment }} 47 | {% endif %} 48 | {{ pg_ident.mapname }} {{ pg_ident.system_username }} {{ pg_ident.pg_username }} 49 | {% endfor %} 50 | -------------------------------------------------------------------------------- /molecule/default/verify.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Verify 3 | hosts: pgcluster 4 | become: yes 5 | gather_facts: yes 6 | 7 | tasks: 8 | - name: Verify cluster functionality 9 | ansible.builtin.shell: 10 | cmd: repmgr cluster crosscheck 11 | executable: /bin/bash 12 | become_user: "{{ postgresql_service_user }}" 13 | register: cluster_crosscheck 14 | tags: ['skip_ansible_lint'] 15 | 16 | - name: Print result 17 | ansible.builtin.debug: 18 | msg: 19 | "cluster_crosscheck": "{{ cluster_crosscheck.stdout_lines }}" 20 | 21 | - name: Ensure testdb is created 22 | ansible.builtin.shell: 23 | cmd: psql -c '\l testdb' # returns 0 if exists 24 | become_user: "{{ postgresql_service_user }}" 25 | 26 | - name: Perform manual failover check 27 | ansible.builtin.shell: 28 | cmd: repmgr standby switchover --siblings-follow --dry-run 29 | executable: /bin/bash 30 | become_user: "{{ postgresql_service_user }}" 31 | when: ansible_hostname == 'pgsql02' 32 | register: repmgr_switchover_check 33 | 34 | - name: Print result 35 | ansible.builtin.debug: 36 | msg: 37 | "repmgr_switchover_check": "{{ repmgr_switchover_check.stdout_lines }}" 38 | when: ansible_hostname == 'pgsql02' 39 | 40 | - name: Perform actual manual switchover 41 | ansible.builtin.shell: 42 | cmd: repmgr standby switchover --siblings-follow 43 | executable: /bin/bash 44 | become_user: "{{ postgresql_service_user }}" 45 | when: ansible_hostname == 'pgsql02' 46 | 47 | - name: Wait for pgsql service 48 | ansible.builtin.wait_for: 49 | port: "{{ postgresql_port }}" 50 | 51 | - name: Show cluster status 52 | ansible.builtin.shell: 53 | cmd: repmgr cluster show 54 | executable: /bin/bash 55 | become_user: "{{ postgresql_service_user }}" 56 | register: cluster_status 57 | 58 | - name: Print result 59 | ansible.builtin.debug: 60 | msg: 61 | "cluster_status": "{{ cluster_status.stdout_lines }}" 62 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Load OS-specific variables 3 | ansible.builtin.include_vars: "{{ item }}" 4 | with_first_found: 5 | - "../vars/{{ ansible_distribution_release }}.yml" 6 | - "../vars/empty.yml" 7 | tags: [always] 8 | 9 | # 10 | # Override defaults/main.yml with PostgreSQL version specific values 11 | # 12 | - name: Load PG version specific variables 13 | ansible.builtin.include_vars: "{{ item }}" 14 | with_first_found: 15 | - "../vars/postgresql_{{ postgresql_version }}.yml" 16 | - "../vars/empty.yml" 17 | tags: [always] 18 | 19 | - name: Install PostgreSQL with apt 20 | ansible.builtin.import_tasks: install_apt.yml 21 | when: ansible_pkg_mgr == "apt" 22 | tags: [postgresql, postgresql-install] 23 | 24 | - name: Install PostgreSQL extensions 25 | ansible.builtin.import_tasks: extensions.yml 26 | tags: [postgresql, postgresql-extensions] 27 | 28 | - name: Detect Repmgr primary 29 | ansible.builtin.import_tasks: extensions/detect_repmgr_primary.yml 30 | when: postgresql_ext_install_repmgr and ansible_service_mgr == 'systemd' 31 | tags: [postgresql, postgresql-extensions] 32 | 33 | - name: Install Foreign Data Wrappers 34 | ansible.builtin.import_tasks: fdw.yml 35 | tags: [postgresql, postgresql-fdw] 36 | 37 | - name: Configure PostgreSQL 38 | ansible.builtin.import_tasks: configure.yml 39 | tags: [postgresql, postgresql-configure] 40 | 41 | - name: Create PostgreSQL users 42 | ansible.builtin.import_tasks: users.yml 43 | tags: [postgresql, postgresql-users] 44 | 45 | - name: Create PostgreSQL databases 46 | ansible.builtin.import_tasks: databases.yml 47 | tags: [postgresql, postgresql-databases] 48 | 49 | - name: Create PostgreSQL schemass 50 | ansible.builtin.import_tasks: schemas.yml 51 | tags: [postgresql, postgresql-schemas] 52 | 53 | - name: Configure PostgreSQL users privileges 54 | ansible.builtin.import_tasks: users_privileges.yml 55 | tags: [postgresql, postgresql-users] 56 | 57 | - name: Configure Repmgr 58 | ansible.builtin.import_tasks: extensions/configure_repmgr.yml 59 | when: postgresql_ext_install_repmgr and ansible_service_mgr == 'systemd' 60 | tags: [postgresql, postgresql-extensions] 61 | 62 | - name: Check PostgreSQL version mismatch 63 | ansible.builtin.import_tasks: check_pg_version_mismatch.yml 64 | tags: [postgresql, postgresql-version-mismatch] 65 | -------------------------------------------------------------------------------- /tasks/install_apt.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # The standard ca-certs are needed because without them apt_key will fail to 3 | # validate www.postgresql.org (or probably any other source). 4 | - name: PostgreSQL | Make sure the CA certificates are available | apt 5 | ansible.builtin.apt: 6 | pkg: ['ca-certificates', 'gnupg'] 7 | state: present 8 | 9 | - name: PostgreSQL | Add PostgreSQL repository apt-key | apt 10 | ansible.builtin.apt_key: 11 | id: "{{ postgresql_apt_key_id }}" 12 | url: "{{ postgresql_apt_key_url }}" 13 | state: present 14 | when: postgresql_apt_key_url and postgresql_apt_key_id and postgresql_install_repository 15 | 16 | - name: PostgreSQL | Add PostgreSQL repository | apt 17 | ansible.builtin.apt_repository: 18 | repo: "{{ postgresql_apt_repository }}" 19 | state: present 20 | when: postgresql_apt_repository | default('') != '' and postgresql_install_repository 21 | 22 | - name: PostgreSQL | Add PostgreSQL repository preferences | apt 23 | ansible.builtin.template: 24 | src: etc_apt_preferences.d_apt_postgresql_org_pub_repos_apt.pref.j2 25 | dest: /etc/apt/preferences.d/apt_postgresql_org_pub_repos_apt.pref 26 | mode: 0640 27 | when: postgresql_apt_pin_priority and postgresql_install_repository 28 | 29 | - name: PostgreSQL | Make sure the dependencies are installed | apt 30 | ansible.builtin.apt: 31 | pkg: "{{ postgresql_apt_dependencies }}" 32 | state: present 33 | update_cache: yes 34 | cache_valid_time: "{{ apt_cache_valid_time | default(3600) }}" 35 | 36 | - name: PostgreSQL | Install PostgreSQL | apt 37 | ansible.builtin.apt: 38 | name: 39 | - "postgresql-{{ postgresql_version }}" 40 | - "postgresql-client-{{ postgresql_version }}" 41 | - "postgresql-contrib-{{ postgresql_version }}" 42 | state: present 43 | update_cache: yes 44 | default_release: "{{ postgresql_default_release | default(ansible_distribution_release + '-pgdg') }}" 45 | cache_valid_time: "{{ apt_cache_valid_time | default(3600) }}" 46 | register: postgresql_install 47 | environment: "{{ postgresql_env }}" 48 | 49 | - name: PostgreSQL | Shutdown systemd-based instance upon first installation 50 | ansible.builtin.service: 51 | name: "postgresql@{{ postgresql_version }}-{{ postgresql_cluster_name }}" 52 | state: stopped 53 | enabled: no 54 | when: postgresql_install.changed 55 | 56 | - name: PostgreSQL | Ensure systemd unit is disabled 57 | ansible.builtin.shell: 58 | cmd: | 59 | systemctl disable postgresql 60 | executable: /bin/bash 61 | warn: no 62 | 63 | - name: PostgreSQL | Start postgresql using pg_ctlcluster binary 64 | ansible.builtin.shell: 65 | cmd: pg_ctlcluster {{ postgresql_version }} {{ postgresql_cluster_name }} restart 66 | executable: /bin/bash 67 | become: yes 68 | become_user: "{{ postgresql_service_user }}" 69 | when: postgresql_install.changed 70 | -------------------------------------------------------------------------------- /molecule/default/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | options: 5 | requirements-file: ${MOLECULE_PROJECT_DIRECTORY}/molecule/default/collections.yml 6 | lint: | 7 | set -e 8 | yamllint . 9 | ansible-lint 10 | driver: 11 | name: vagrant 12 | provider: 13 | name: libvirt 14 | platforms: 15 | - name: pgsql01 16 | box: ${MOLECULE_DISTRO:-"generic/debian11"} 17 | groups: 18 | - pgcluster 19 | config_options: 20 | ssh.keep_alive: yes 21 | ssh.remote_user: "'vagrant'" 22 | memory: 1024 23 | cpus: 1 24 | interfaces: 25 | - network_name: private_network 26 | type: static 27 | ip: 192.168.30.2 28 | auto_config: true 29 | - name: pgsql02 30 | box: ${MOLECULE_DISTRO:-"generic/debian11"} 31 | config_options: 32 | ssh.keep_alive: yes 33 | ssh.remote_user: "'vagrant'" 34 | groups: 35 | - pgcluster 36 | memory: 1024 37 | cpus: 1 38 | interfaces: 39 | - network_name: private_network 40 | type: static 41 | ip: 192.168.30.3 42 | auto_config: true 43 | scenario: 44 | test_sequence: 45 | - dependency 46 | - lint 47 | - cleanup 48 | - destroy 49 | - syntax 50 | - create 51 | - prepare 52 | - converge 53 | # - idempotence 54 | - side_effect 55 | - verify 56 | - cleanup 57 | - destroy 58 | provisioner: 59 | name: ansible 60 | log: true 61 | inventory: 62 | group_vars: 63 | pgcluster: 64 | postgresql_version: ${POSTGRESQL_VERSION:-"13"} 65 | postgresql_port: 5432 66 | repmgr_version: ${REPMGR_VERSION:-"5.3"} 67 | repmgr_master: pgsql01 68 | repmgr_target_group: pgcluster 69 | postgresql_service_user: postgres 70 | postgresql_listen_addresses: "*" 71 | postgresql_wal_level: "replica" 72 | postgresql_max_wal_senders: 10 73 | postgresql_max_replication_slots: 10 74 | postgresql_wal_keep_segments: 100 75 | postgresql_hot_standby: on 76 | postgresql_ext_install_repmgr: yes 77 | postgresql_shared_preload_libraries: 78 | - repmgr 79 | postgresql_pg_hba_custom: 80 | - { type: "host", database: "all", user: "all", address: "192.168.30.0/24", method: "md5" } 81 | - { type: "host", database: "replication", user: "{{ repmgr_user }}", address: "192.168.30.0/24", method: "trust" } 82 | - { type: "host", database: "replication", user: "{{ repmgr_user }}", address: "127.0.0.1/32", method: "trust" } 83 | - { type: "host", database: "{{ repmgr_database }}", user: "{{ repmgr_user }}", address: "127.0.0.1/32", method: "trust" } 84 | - { type: "host", database: "{{ repmgr_database }}", user: "{{ repmgr_user }}", address: "192.168.30.0/24", method: "trust" } 85 | # Databases 86 | postgresql_databases: 87 | - name: "{{ repmgr_database }}" 88 | owner: "{{ repmgr_user }}" 89 | encoding: "UTF-8" 90 | - name: testdb 91 | owner: admin 92 | encoding: "UTF-8" 93 | # Users 94 | postgresql_users: 95 | - name: "{{ repmgr_user }}" 96 | pass: "{{ repmgr_password }}" 97 | - name: admin 98 | pass: secret 99 | encrypted: yes 100 | # Roles 101 | postgresql_user_privileges: 102 | - name: "{{ repmgr_user }}" 103 | db: "{{ repmgr_database }}" 104 | priv: "ALL" 105 | role_attr_flags: "SUPERUSER,REPLICATION" 106 | - name: admin 107 | db: testdb 108 | role_attr_flags: "SUPERUSER" 109 | host_vars: 110 | pgsql01: 111 | repmgr_node_id: 1 112 | pgsql02: 113 | repmgr_node_id: 2 114 | config_options: 115 | defaults: 116 | callbacks_enabled: "profile_tasks,timer" 117 | interpreter_python: /usr/bin/python3 118 | pipelining: true 119 | local_tmp: /var/tmp 120 | -------------------------------------------------------------------------------- /inventory.example.yml: -------------------------------------------------------------------------------- 1 | --- 2 | all: 3 | vars: 4 | ansible_python_interpreter: /usr/bin/python3 5 | postgresql_version: 12 6 | repmgr_version: 5.2 7 | repmgr_master: pgsql01 8 | pgcluster: 9 | hosts: 10 | pgsql01: 11 | ansible_host: 192.168.56.10 12 | repmgr_node_id: 1 13 | repmgr_priority: 3 14 | pgsql02: 15 | ansible_host: 192.168.56.11 16 | repmgr_node_id: 2 17 | repmgr_priority: 2 18 | pgsql03: 19 | ansible_host: 192.168.56.12 20 | repmgr_node_id: 3 21 | repmgr_priority: 1 22 | vars: 23 | # Required configuration items 24 | repmgr_target_group: pgcluster 25 | repmgr_promote_command: /usr/bin/repmgr standby promote -f /etc/repmgr.conf --log-to-file 26 | repmgr_follow_command: /usr/bin/repmgr standby follow -f /etc/repmgr.conf --log-to-file --upstream-node-id=%n 27 | repmgr_monitoring_history: "yes" 28 | repmgr_connection_check_type: query 29 | repmgr_log_level: INFO 30 | # Basic settings 31 | postgresql_listen_addresses: "*" 32 | postgresql_port: 5432 33 | postgresql_max_connections: 128 34 | # WAL 35 | postgresql_wal_level: "replica" 36 | postgresql_max_wal_senders: 10 37 | postgresql_max_replication_slots: 10 38 | postgresql_wal_keep_segments: 100 39 | postgresql_hot_standby: on 40 | postgresql_ext_install_repmgr: yes 41 | postgresql_shared_preload_libraries: 42 | - repmgr 43 | postgresql_checkpoint_completion_target: 0.7 44 | postgresql_wal_buffers: 16MB 45 | postgresql_min_wal_size: 1GB 46 | postgresql_max_wal_size: 4GB 47 | # memory 48 | postgresql_work_mem: 5242kB 49 | postgresql_shared_buffers: 512MB 50 | postgresql_maintenance_work_mem: 128MB 51 | # query tuning 52 | postgresql_effective_cache_size: 1536MB 53 | postgresql_random_page_cost: 1.1 54 | # disk 55 | postgresql_effective_io_concurrency: 200 56 | postgresql_max_worker_processes: 2 57 | postgresql_max_parallel_workers_per_gather: 1 58 | postgresql_max_parallel_workers: 2 59 | postgresql_max_parallel_maintenance_workers: 1 60 | # postgresql logging 61 | postgresql_log_checkpoints: on 62 | postgresql_log_connections: on 63 | postgresql_log_disconnections: on 64 | postgresql_log_temp_files: 0 65 | # pg_hba.conf 66 | postgresql_pg_hba_custom: 67 | - { type: "host", database: "replication", user: "{{ repmgr_user }}", address: "192.168.56.0/24", method: "trust" } 68 | - { type: "host", database: "replication", user: "{{ repmgr_user }}", address: "127.0.0.1/32", method: "trust" } 69 | - { type: "host", database: "{{ repmgr_database }}", user: "{{ repmgr_user }}", address: "127.0.0.1/32", method: "trust" } 70 | - { type: "host", database: "{{ repmgr_database }}", user: "{{ repmgr_user }}", address: "192.168.56.0/24", method: "trust" } 71 | - { type: "host", database: "all", user: "postgres", address: "192.168.56.0/24", method: "trust" } 72 | - { type: "host", database: "testdb", user: "all", address: "192.168.56.0/24", method: "md5" } 73 | 74 | # Databases 75 | postgresql_databases: 76 | - name: "{{ repmgr_database }}" 77 | owner: "{{ repmgr_user }}" 78 | encoding: "UTF-8" 79 | - name: testdb 80 | owner: admin 81 | encoding: "UTF-8" 82 | # Users 83 | postgresql_users: 84 | - name: "{{ repmgr_user }}" 85 | pass: "{{ repmgr_password }}" 86 | - name: admin 87 | pass: secret # postgresql >=10 does not accept unencrypted passwords 88 | encrypted: yes 89 | # Roles 90 | postgresql_user_privileges: 91 | - name: "{{ repmgr_user }}" 92 | db: "{{ repmgr_database }}" 93 | priv: "ALL" 94 | role_attr_flags: "SUPERUSER,REPLICATION" 95 | - name: admin 96 | db: testdb 97 | role_attr_flags: "SUPERUSER" 98 | # required for repmgr node rejoin --force-rewind 99 | postgresql_data_checksums: true 100 | postgresql_wal_compression: on 101 | postgresql_wal_log_hints: on 102 | -------------------------------------------------------------------------------- /defaults/main/002-repmgr.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Required configuration items 3 | repmgr_target_group: "" 4 | repmgr_user: repmgr 5 | repmgr_password: repmgr 6 | repmgr_database: repmgr 7 | repmgr_conninfo: "host={{ ansible_hostname }} user={{ repmgr_user }} dbname={{ repmgr_database }} connect_timeout=2" 8 | repmgr_data_directory: "{{ postgresql_data_directory }}" 9 | # Loads the matching configuration file located in role's templates folder 10 | repmgr_version: 5.3 11 | 12 | # Optional configuration items 13 | # 14 | 15 | # Repositories 16 | repmgr_apt_repository_add: true 17 | repmgr_gpg_key_url: https://dl.2ndquadrant.com/gpg-key.asc 18 | repmgr_apt_repository: "deb [arch=amd64] https://dl.2ndquadrant.com/default/release/apt {{ ansible_distribution_release }}-2ndquadrant main" 19 | # Add the following variable in order to install a specific version from 2nd Quadrant repos using apt. 20 | # repmgr_version_debian: 21 | 22 | # Replication 23 | repmgr_primary: false 24 | repmgr_config_directory: "{{ postgresql_conf_directory }}" 25 | repmgr_replication_user: "{{ repmgr_user }}" 26 | repmgr_replication_type: physical 27 | repmgr_location: default 28 | repmgr_use_replication_slots: "no" 29 | repmgr_witness_sync_interval: 15 30 | repmgr_use_primary_conninfo_password: "false" 31 | repmgr_passfile: /var/lib/postgresql/.pgpass 32 | repmgr_base_key_path: /var/lib/postgresql/.ssh 33 | repmgr_private_key_path: /var/lib/postgresql/.ssh/id_rsa 34 | repmgr_public_key_path: /var/lib/postgresql/.ssh/id_rsa.pub 35 | repmgr_ssh_key_bits: 2048 36 | repmgr_ssh_key_type: rsa 37 | repmgr_ssh_force_renewal: false 38 | 39 | # Logging 40 | repmgr_log_level: INFO 41 | repmgr_log_facility: STDERR 42 | repmgr_log_file: /var/lib/postgresql/repmgrd.log 43 | repmgr_log_status_interval: 300 44 | 45 | # Notification 46 | repmgr_event_notification_command: "" 47 | repmgr_event_notifications: "" 48 | 49 | # Directories 50 | repmgr_pg_bindir: "{{ postgresql_bin_directory }}" 51 | repmgr_repmgr_bindir: "{{ postgresql_bin_directory }}" 52 | 53 | # Commands & options 54 | repmgr_pg_ctl_options: "" 55 | repmgr_pg_basebackup_options: "" 56 | repmgr_rsync_options: "" 57 | repmgr_tablespace_mapping: "" 58 | repmgr_restore_command: "" 59 | repmgr_archive_cleanup_command: "" 60 | repmgr_recovery_min_apply_delay: "" 61 | repmgr_ssh_options: "-o StrictHostKeyChecking=no" 62 | 63 | # Intervals & timeouts 64 | repmgr_promote_check_timeout: 60 65 | repmgr_promote_check_interval: 1 66 | repmgr_primary_follow_timeout: 60 67 | repmgr_standby_follow_timeout: 30 68 | repmgr_standby_follow_restart: "false" 69 | repmgr_shutdown_check_timeout: 60 70 | repmgr_standby_reconnect_timeout: 60 71 | repmgr_node_rejoin_timeout: 60 72 | 73 | # Barman 74 | repmgr_barman_host: "" 75 | repmgr_barman_port: 22 76 | repmgr_barman_user: barman 77 | repmgr_barman_server: "" 78 | repmgr_barman_config: "" 79 | repmgr_repmgrd_pid_file: "" 80 | 81 | # Fail-over 82 | repmgr_failover: manual 83 | repmgr_priority: 100 84 | repmgr_connection_check_type: ping # Accepted: ping, connection, query 85 | repmgr_reconnect_attempts: 6 86 | repmgr_reconnect_interval: 10 87 | repmgr_promote_command: "" 88 | repmgr_follow_command: "" 89 | repmgr_primary_notification_timeout: 60 90 | repmgr_repmgrd_standby_startup_timeout: 60 91 | repmgrd_exit_on_inactive_node: "false" 92 | 93 | # Monitoring 94 | repmgr_monitoring_history: "no" 95 | repmgr_keep_history_days: 2 # used by the 'repmgr cluster cleanup' command which is to be executed by a cronjob. See configure_repmgr.yml 96 | repmgr_monitor_interval_secs: 2 97 | repmgr_degraded_monitoring_timeout: -1 98 | repmgr_async_query_timeout: 60 99 | 100 | # Advanced failover parameters (new in version 5.x) 101 | repmgr_standby_disconnect_on_failover: "false" 102 | repmgr_sibling_nodes_disconnect_timeout: 30 103 | repmgr_primary_visibility_consensus: "false" 104 | repmgr_always_promote: "false" 105 | repmgr_failover_validation_command: '' 106 | repmgr_election_rerun_interval: 15 107 | repmgr_child_nodes_check_interval: 5 108 | repmgr_child_nodes_connected_min_count: -1 109 | repmgr_child_nodes_disconnect_min_count: -1 110 | repmgr_child_nodes_disconnect_timeout: 30 111 | repmgr_child_nodes_disconnect_command: '' 112 | 113 | # Service commands 114 | repmgr_service_start_command: pg_ctlcluster {{ postgresql_version }} {{ postgresql_cluster_name }} start 115 | repmgr_service_stop_command: pg_ctlcluster {{ postgresql_version }} {{ postgresql_cluster_name }} stop 116 | repmgr_service_restart_command: pg_ctlcluster {{ postgresql_version }} {{ postgresql_cluster_name }} restart 117 | repmgr_service_reload_command: pg_ctlcluster {{ postgresql_version }} {{ postgresql_cluster_name }} reload 118 | repmgr_service_promote_command: /usr/lib/postgresql/{{ postgresql_version }}/bin/pg_ctl -w -D {{ postgresql_data_directory }} promote 119 | 120 | # Warning levels 121 | repmgr_archive_ready_warning: 16 122 | repmgr_archive_ready_critical: 128 123 | repmgr_replication_lag_warning: 300 124 | repmgr_replication_lag_critical: 600 125 | 126 | # repmgrd configuration 127 | repmgrd_service_start_command: systemctl start repmgrd 128 | repmgrd_service_stop_command: systemctl stop repmgrd 129 | -------------------------------------------------------------------------------- /tasks/databases.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: PostgreSQL | Ensure PostgreSQL is running 3 | ansible.builtin.shell: 4 | cmd: pg_ctlcluster {{ postgresql_version }} {{ postgresql_cluster_name }} status 5 | executable: /bin/bash 6 | become_user: "{{ postgresql_service_user }}" 7 | 8 | - name: PostgreSQL | Make sure the PostgreSQL databases are present 9 | community.postgresql.postgresql_db: 10 | name: "{{ item.name }}" 11 | owner: "{{ item.owner | default(postgresql_database_owner) }}" 12 | encoding: "{{ item.encoding | default(postgresql_encoding) }}" 13 | lc_collate: "{{ item.lc_collate | default(postgresql_locale) }}" 14 | lc_ctype: "{{ item.lc_ctype | default(postgresql_ctype) }}" 15 | port: "{{ postgresql_port }}" 16 | template: "template0" 17 | state: present 18 | login_user: "{{ postgresql_admin_user }}" 19 | become: yes 20 | become_user: "{{ postgresql_admin_user }}" 21 | loop: "{{ postgresql_databases | flatten(levels=1) }}" 22 | when: postgresql_databases|length > 0 and repmgr_primary 23 | 24 | - name: PostgreSQL | Add extensions to the databases 25 | become: yes 26 | become_user: "{{ postgresql_admin_user }}" 27 | community.postgresql.postgresql_ext: 28 | db: "{{ item.0.db }}" 29 | login_user: "{{ postgresql_service_user }}" 30 | port: "{{ postgresql_port }}" 31 | name: "{{ item.1 }}" 32 | with_subelements: 33 | - "{{ postgresql_database_extensions }}" 34 | - extensions 35 | register: result 36 | 37 | - name: PostgreSQL | Add hstore to the databases with the requirement 38 | become: yes 39 | become_user: "{{ postgresql_service_user }}" 40 | ansible.builtin.shell: "{{ postgresql_bin_directory }}/psql {{ item.name }} --port={{ postgresql_port | int }} --username {{ postgresql_admin_user }} -c 'CREATE EXTENSION IF NOT EXISTS hstore;'" 41 | loop: "{{ postgresql_databases | flatten(levels=1) }}" 42 | register: hstore_ext_result 43 | failed_when: hstore_ext_result.rc != 0 and ("already exists, skipping" not in hstore_ext_result.stderr) 44 | changed_when: hstore_ext_result.rc == 0 and ("already exists, skipping" not in hstore_ext_result.stderr) 45 | when: item.hstore is defined and item.hstore 46 | 47 | - name: PostgreSQL | Add uuid-ossp to the database with the requirement 48 | become: yes 49 | become_user: "{{ postgresql_service_user }}" 50 | ansible.builtin.shell: "{{ postgresql_bin_directory }}/psql {{ item.name }} --port={{ postgresql_port | int }} --username {{ postgresql_admin_user }} -c 'CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";'" 51 | loop: "{{ postgresql_databases | flatten(levels=1) }}" 52 | register: uuid_ext_result 53 | failed_when: uuid_ext_result.rc != 0 and ("already exists, skipping" not in uuid_ext_result.stderr) 54 | changed_when: uuid_ext_result.rc == 0 and ("already exists, skipping" not in uuid_ext_result.stderr) 55 | when: item.uuid_ossp is defined and item.uuid_ossp 56 | 57 | - name: PostgreSQL | Add postgis to the databases with the requirement 58 | become: yes 59 | become_user: "{{ postgresql_service_user }}" 60 | ansible.builtin.shell: "{{ postgresql_bin_directory }}/psql {{ item.name }} --port={{ postgresql_port | int }} --username {{ postgresql_admin_user }} -c 'CREATE EXTENSION IF NOT EXISTS postgis;'&&psql {{ item.name }} -c 'CREATE EXTENSION IF NOT EXISTS postgis_topology;'" 61 | loop: "{{ postgresql_databases | flatten(levels=1) }}" 62 | when: item.gis is defined and item.gis 63 | 64 | - name: PostgreSQL | add cube to the database with the requirement 65 | become: yes 66 | become_user: "{{ postgresql_service_user }}" 67 | ansible.builtin.shell: "{{ postgresql_bin_directory }}/psql {{ item.name }} --port={{ postgresql_port | int }} --username {{ postgresql_admin_user }} -c 'create extension if not exists cube;'" 68 | loop: "{{ postgresql_databases | flatten(levels=1) }}" 69 | when: item.cube is defined and item.cube 70 | 71 | - name: PostgreSQL | Add plpgsql to the database with the requirement 72 | become: yes 73 | become_user: "{{ postgresql_service_user }}" 74 | ansible.builtin.shell: "{{ postgresql_bin_directory }}/psql {{ item.name }} --port={{ postgresql_port | int }} --username {{ postgresql_admin_user }} -c 'CREATE EXTENSION IF NOT EXISTS plpgsql;'" 75 | loop: "{{ postgresql_databases | flatten(levels=1) }}" 76 | when: item.plpgsql is defined and item.plpgsql 77 | 78 | - name: PostgreSQL | add earthdistance to the database with the requirement 79 | become: yes 80 | become_user: "{{ postgresql_service_user }}" 81 | ansible.builtin.shell: "{{ postgresql_bin_directory }}/psql {{ item.name }} --port={{ postgresql_port | int }} --username {{ postgresql_admin_user }} -c 'create extension if not exists earthdistance;'" 82 | loop: "{{ postgresql_databases | flatten(levels=1) }}" 83 | when: item.earthdistance is defined and item.earthdistance 84 | 85 | - name: PostgreSQL | Add citext to the database with the requirement 86 | become: yes 87 | become_user: "{{ postgresql_service_user }}" 88 | ansible.builtin.shell: "{{ postgresql_bin_directory }}/psql {{ item.name }} --port={{ postgresql_port | int }} --username {{ postgresql_admin_user }} -c 'CREATE EXTENSION IF NOT EXISTS citext;'" 89 | loop: "{{ postgresql_databases | flatten(levels=1) }}" 90 | register: citext_ext_result 91 | failed_when: citext_ext_result.rc != 0 and ("already exists, skipping" not in citext_ext_result.stderr) 92 | changed_when: citext_ext_result.rc == 0 and ("already exists, skipping" not in citext_ext_result.stderr) 93 | when: item.citext is defined and item.citext 94 | -------------------------------------------------------------------------------- /tasks/configure.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: PostgreSQL | Make sure the postgres data directory exists 3 | ansible.builtin.file: 4 | path: "{{ postgresql_data_directory }}" 5 | owner: "{{ postgresql_service_user }}" 6 | group: "{{ postgresql_service_group }}" 7 | state: directory 8 | mode: 0700 9 | register: pgdata_dir_exist 10 | 11 | - name: PostgreSQL | Make sure the postgres WAL directory exists 12 | ansible.builtin.file: 13 | path: "{{ postgresql_wal_directory }}" 14 | owner: "{{ postgresql_service_user }}" 15 | group: "{{ postgresql_service_group }}" 16 | state: directory 17 | mode: 0700 18 | register: pgwal_dir_exist 19 | when: postgresql_wal_directory != "" 20 | 21 | - name: PostgreSQL | Make sure the postgres log directory exists 22 | ansible.builtin.file: 23 | path: "{{ postgresql_log_directory }}" 24 | owner: "{{ postgresql_service_user }}" 25 | group: "{{ postgresql_service_group }}" 26 | state: directory 27 | mode: 0700 28 | register: pglog_dir_exist 29 | when: postgresql_log_directory != "pg_log" 30 | 31 | - name: PostgreSQL | Ensure the locale for lc_collate and lc_ctype is generated | Debian 32 | become: yes 33 | community.general.system.locale_gen: 34 | name: "{{ item }}" 35 | state: present 36 | with_items: 37 | - "{{ postgresql_locale }}" 38 | - "{{ postgresql_ctype }}" 39 | when: ansible_os_family == "Debian" and item != "C.UTF-8" 40 | 41 | - name: PostgreSQL | Stop PostgreSQL | Debian 42 | ansible.builtin.shell: 43 | cmd: pg_ctlcluster {{ postgresql_version }} {{ postgresql_cluster_name }} stop 44 | executable: /bin/bash 45 | become_user: "{{ postgresql_service_user }}" 46 | when: ansible_os_family == "Debian" and postgresql_cluster_reset and pgdata_dir_exist.changed 47 | 48 | - name: PostgreSQL | Reset the cluster - drop the existing one | Debian 49 | ansible.builtin.shell: pg_dropcluster {{ postgresql_version }} {{ postgresql_cluster_name }} 50 | become: yes 51 | become_user: "{{ postgresql_service_user }}" 52 | when: ansible_os_family == "Debian" and postgresql_cluster_reset and pgdata_dir_exist.changed 53 | 54 | - name: PostgreSQL | Reset the cluster - create a new one (with specified encoding and locale) | Debian 55 | ansible.builtin.shell: > 56 | pg_createcluster --locale {{ postgresql_locale }} 57 | -e {{ postgresql_encoding }} -d {{ postgresql_data_directory }} 58 | {{ postgresql_version }} {{ postgresql_cluster_name }} 59 | -- 60 | {% if postgresql_data_checksums and postgresql_version is version_compare('9.3', '>=') %}--data-checksums{% endif %} 61 | {% if postgresql_pwfile != "" %}--pwfile={{ postgresql_pwfile }} {% endif %} 62 | {% if postgresql_wal_directory != "" and postgresql_version is version_compare('10', '<') %}--xlogdir={{ postgresql_wal_directory }} {% endif %} 63 | {% if postgresql_wal_directory != "" and postgresql_version is version_compare('10', '>=') %}--waldir={{ postgresql_wal_directory }} {% endif %} 64 | become: yes 65 | become_user: "{{ postgresql_service_user }}" 66 | when: ansible_os_family == "Debian" and postgresql_cluster_reset and pgdata_dir_exist.changed 67 | 68 | - name: PostgreSQL | Start PostgreSQL | Debian 69 | ansible.builtin.shell: 70 | cmd: pg_ctlcluster {{ postgresql_version }} {{ postgresql_cluster_name }} start 71 | executable: /bin/bash 72 | become_user: "{{ postgresql_service_user }}" 73 | when: ansible_os_family == "Debian" and postgresql_cluster_reset and pgdata_dir_exist.changed 74 | 75 | - name: PostgreSQL | Verify postgresql cluster version 76 | ansible.builtin.command: grep ^{{ postgresql_version }}$ {{ postgresql_data_directory }}/PG_VERSION 77 | changed_when: false 78 | 79 | - name: PostgreSQL | Ensure configuration directory exists 80 | ansible.builtin.file: 81 | path: "{{ postgresql_conf_directory }}" 82 | owner: "{{ postgresql_service_user }}" 83 | group: "{{ postgresql_service_group }}" 84 | mode: 0700 85 | state: directory 86 | 87 | - name: PostgreSQL | Update configuration - pt. 1 (pg_hba.conf) # TODO : consider refactoring using postgresql_pg_hba module instead 88 | ansible.builtin.template: 89 | src: pg_hba.conf.j2 90 | dest: "{{ postgresql_conf_directory }}/pg_hba.conf" 91 | owner: "{{ postgresql_service_user }}" 92 | group: "{{ postgresql_service_group }}" 93 | mode: 0640 94 | register: postgresql_configuration_pt1 95 | 96 | - name: PostgreSQL | Update configuration - pt. 2 (postgresql.conf) 97 | ansible.builtin.template: 98 | src: "postgresql.conf-{{ postgresql_version }}.j2" 99 | dest: "{{ postgresql_conf_directory }}/postgresql.conf" 100 | owner: "{{ postgresql_service_user }}" 101 | group: "{{ postgresql_service_group }}" 102 | mode: 0640 103 | register: postgresql_configuration_pt2 104 | changed_when: true 105 | 106 | - name: PostgreSQL | Update configuration - pt. 3 (pg_ident.conf) 107 | ansible.builtin.template: 108 | src: pg_ident.conf.j2 109 | dest: "{{ postgresql_ident_file }}" 110 | owner: "{{ postgresql_service_user }}" 111 | group: "{{ postgresql_service_group }}" 112 | mode: 0640 113 | register: postgresql_configuration_pt4 114 | notify: Restart postgresql 115 | 116 | - name: PostgreSQL | Create folder for additional configuration files 117 | ansible.builtin.file: 118 | name: "{{ postgresql_conf_directory }}/conf.d" 119 | state: directory 120 | owner: "{{ postgresql_service_user }}" 121 | group: "{{ postgresql_service_group }}" 122 | mode: 0755 123 | 124 | - name: PostgreSQL | Ensure the pid directory for PostgreSQL exists 125 | ansible.builtin.file: 126 | name: "{{ postgresql_pid_directory }}" 127 | state: directory 128 | owner: "{{ postgresql_service_user }}" 129 | group: "{{ postgresql_service_group }}" 130 | mode: u=rwX,g=rwXs,o=rx 131 | notify: Restart postgresql 132 | 133 | - name: PostgreSQL | Reload all conf files 134 | ansible.builtin.shell: 135 | cmd: pg_ctlcluster {{ postgresql_version }} {{ postgresql_cluster_name }} reload 136 | executable: /bin/bash 137 | become_user: "{{ postgresql_service_user }}" 138 | when: postgresql_configuration_pt1.changed or postgresql_configuration_pt2.changed or postgresql_configuration_pt3.changed or postgresql_systemd_custom_conf.changed 139 | 140 | - name: PostgreSQL | Restart service 141 | ansible.builtin.shell: 142 | cmd: pg_ctlcluster {{ postgresql_version }} {{ postgresql_cluster_name }} restart 143 | executable: /bin/bash 144 | become_user: "{{ postgresql_service_user }}" 145 | when: postgresql_configuration_pt2.changed 146 | register: postgresql_restart 147 | failed_when: postgresql_restart.rc not in [0, 2] # handle already-running return codes 148 | -------------------------------------------------------------------------------- /tasks/extensions/configure_repmgr.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Repmgr | Update configuration (repmgr.conf) 3 | ansible.builtin.template: 4 | src: "repmgr.conf-{{ repmgr_version }}.j2" 5 | dest: "{{ postgresql_conf_directory }}/repmgr.conf" 6 | owner: "{{ postgresql_service_user }}" 7 | group: "{{ postgresql_service_group }}" 8 | mode: 0640 9 | notify: Reload repmgr 10 | 11 | - name: Repmgr | Upload logrotate configuration 12 | ansible.builtin.template: 13 | src: repmgr_logroate.j2 14 | dest: /etc/logrotate.d/repmgr 15 | mode: 0640 16 | 17 | - name: Repmgr | Create repmgr.conf symlink for shorter commands # see: https://repmgr.org/docs/5.0/configuration-file.html 18 | ansible.builtin.file: 19 | src: "{{ postgresql_conf_directory }}/repmgr.conf" 20 | dest: /etc/repmgr.conf 21 | state: link 22 | mode: 0640 23 | 24 | - name: Repmgr | Ensure systemd drop-in directory exists 25 | ansible.builtin.file: 26 | path: "/etc/systemd/system/repmgr{{ postgresql_version }}.service.d/" 27 | state: directory 28 | mode: 0755 29 | 30 | - name: Repmgr | Update drop-in 31 | ansible.builtin.template: 32 | src: "repmgr.custom.conf.j2" 33 | dest: "/etc/systemd/system/repmgr{{ postgresql_version }}.service.d/custom.conf" 34 | mode: 0640 35 | 36 | - name: Repmgr | Allow passwordless restarts with postgres user 37 | ansible.builtin.template: 38 | src: "sudoers.postgresql.j2" 39 | dest: "/etc/sudoers.d/postgresql" 40 | mode: 0640 41 | 42 | - name: Repmgr | Update .pgpass for postgres user 43 | ansible.builtin.template: 44 | src: "pgpass.j2" 45 | dest: "{{ repmgr_passfile }}" 46 | owner: "{{ postgresql_service_user }}" 47 | group: "{{ postgresql_service_group }}" 48 | mode: 0600 49 | trim_blocks: no 50 | 51 | - name: Repmgr | Ensure ssh keys destination folder exists 52 | ansible.builtin.file: 53 | path: "{{ repmgr_base_key_path }}" 54 | state: directory 55 | owner: "{{ postgresql_service_user }}" 56 | group: "{{ postgresql_service_group }}" 57 | mode: 0700 58 | 59 | - name: Repmgr | Generate an SSH keypair locally 60 | community.crypto.openssh_keypair: 61 | path: "{{ lookup('config', 'DEFAULT_LOCAL_TMP') | dirname }}/postgres_id_rsa" 62 | backend: cryptography 63 | regenerate: partial_idempotence 64 | size: "{{ repmgr_ssh_key_bits }}" 65 | type: "{{ repmgr_ssh_key_type }}" 66 | force: "{{ repmgr_ssh_force_renewal }}" 67 | mode: 0644 68 | delegate_to: 127.0.0.1 69 | become: no 70 | 71 | - name: Repmgr | Fetch pubkey content 72 | ansible.builtin.set_fact: 73 | pubkey_content: " 74 | {{ lookup( 75 | 'file', 76 | lookup('config','DEFAULT_LOCAL_TMP') | dirname + '/postgres_id_rsa.pub' 77 | ) }}" 78 | become: no 79 | tags: ['skip_ansible_lint'] 80 | 81 | - name: Repmgr | Update authorized_keys on all nodes 82 | ansible.posix.authorized_key: 83 | user: "{{ postgresql_service_user }}" 84 | key: "{{ pubkey_content }}" 85 | state: present 86 | 87 | - name: Repmgr | Upload private key on all nodes 88 | ansible.builtin.copy: 89 | src: "{{ lookup('config', 'DEFAULT_LOCAL_TMP') | dirname }}/postgres_id_rsa" 90 | dest: "{{ repmgr_private_key_path }}" 91 | owner: "{{ postgresql_service_user }}" 92 | group: "{{ postgresql_service_group }}" 93 | mode: 0600 94 | 95 | - name: Repmgr | Setup SSH config for Barman 96 | ansible.builtin.template: 97 | src: repmgr_barman_ssh_config.j2 98 | dest: "{{ repmgr_base_key_path }}/config" 99 | owner: "{{ postgresql_service_user }}" 100 | group: "{{ postgresql_service_group }}" 101 | mode: 0600 102 | when: repmgr_barman_host and repmgr_barman_server 103 | 104 | - name: Determine repmgr primary hostname 105 | ansible.builtin.set_fact: 106 | repmgr_primary_hostname: "{% for host, vars in hostvars.items() if 'repmgr_primary' in vars and vars['repmgr_primary'] %}{{ host|trim }}{% endfor %}" 107 | when: repmgr_primary_hostname is not defined 108 | 109 | - name: Debug repmgr primary hostname 110 | ansible.builtin.debug: 111 | msg: 112 | "repmgr_primary_hostname": "{{ repmgr_primary_hostname == ansible_hostname }}" 113 | 114 | - name: Repmgr | Register as primary 115 | ansible.builtin.command: "repmgr primary register -F" 116 | become: yes 117 | become_user: "{{ postgresql_service_user }}" 118 | when: ansible_hostname == repmgr_primary_hostname 119 | 120 | - name: Repmgr | Ensure postgresql slave is stopped before clone 121 | ansible.builtin.shell: 122 | cmd: pg_ctlcluster {{ postgresql_version }} {{ postgresql_cluster_name }} stop 123 | executable: /bin/bash 124 | become: yes 125 | become_user: "{{ postgresql_service_user }}" 126 | when: ansible_hostname != repmgr_primary_hostname 127 | 128 | - name: Repmgr | Clone standby 129 | ansible.builtin.command: "repmgr -F -h {{ repmgr_primary_hostname }} -U repmgr -d repmgr standby clone" 130 | become: yes 131 | become_user: "{{ postgresql_service_user }}" 132 | when: ansible_hostname != repmgr_primary_hostname 133 | 134 | - name: Repmgr | Ensure postgresql slave is running after clone 135 | ansible.builtin.shell: 136 | cmd: pg_ctlcluster {{ postgresql_version }} {{ postgresql_cluster_name }} start 137 | executable: /bin/bash 138 | become: yes 139 | become_user: "{{ postgresql_service_user }}" 140 | when: ansible_hostname != repmgr_primary_hostname 141 | 142 | - name: Repmgr | Wait for Postgres 143 | ansible.builtin.wait_for: 144 | port: "{{ postgresql_port }}" 145 | timeout: 3 146 | 147 | - name: Repmgr | Register standby 148 | ansible.builtin.command: "repmgr -F -h {{ repmgr_primary_hostname }} -U repmgr -d repmgr standby register" 149 | become: yes 150 | become_user: "{{ postgresql_service_user }}" 151 | when: ansible_hostname != repmgr_primary_hostname 152 | 153 | - name: Repmgr | Verify cluster functionality 154 | ansible.builtin.command: "repmgr -F -h {{ repmgr_primary_hostname }} -U repmgr -d repmgr cluster crosscheck" 155 | become: yes 156 | become_user: "{{ postgresql_service_user }}" 157 | 158 | - name: Repmgr | Ensure repmgrd is running 159 | ansible.builtin.command: "/usr/bin/repmgrd daemon start" 160 | when: repmgr_monitoring_history or repmgr_failover == 'automatic' 161 | become: yes 162 | become_user: "{{ postgresql_service_user }}" 163 | 164 | - name: Repmgr | Show repmgrd status 165 | ansible.builtin.command: "repmgr daemon status" 166 | register: repmgrd_status 167 | when: repmgr_monitoring_history or repmgr_failover == 'automatic' 168 | become: yes 169 | become_user: "{{ postgresql_service_user }}" 170 | 171 | - name: Debug repmgrd status 172 | ansible.builtin.debug: 173 | msg: 174 | "{{ repmgrd_status.stdout_lines }}" 175 | 176 | - name: Repmgr | Setup cluster monitoring history cleanup with cron task 177 | ansible.builtin.cron: 178 | name: Purges repmgr.monitoring_history table 179 | job: "repmgr cluster cleanup --keep-history={{ repmgr_keep_history_days }}" 180 | special_time: daily 181 | when: repmgr_monitoring_history and repmgr_failover == 'automatic' 182 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## PostgreSQL HA 2 | 3 | [![Build Status](https://travis-ci.com/fidanf/ansible-role-postgresql-ha.svg?branch=master)](https://travis-ci.com/fidanf/ansible-role-postgresql-ha) 4 | 5 | Install and configure a PostgreSQL high-availability cluster managed with repmgr. Add dependencies, extensions, databases and users. Works for standalone installations as well. 6 | 7 | Tested with : 8 | - Debian 10.x :heavy_check_mark: 9 | - Debian 11.x :heavy_check_mark: 10 | - Ubuntu 18.04.x :heavy_check_mark: 11 | - Ubuntu 20.04.x :heavy_check_mark: 12 | 13 | --- 14 | 15 | - [PostgreSQL HA](#postgresql-ha) 16 | - [Requirements](#requirements) 17 | - [Installation](#installation) 18 | - [Dependencies](#dependencies) 19 | - [Example Inventory](#example-inventory) 20 | - [Role variables](#role-variables) 21 | - [Example Playbook](#example-playbook) 22 | - [Usefull commands to run after your first installation](#usefull-commands-to-run-after-your-first-installation) 23 | - [Verifying cluster functionality](#verifying-cluster-functionality) 24 | - [Show cluster status](#show-cluster-status) 25 | - [List nodes and their attributes](#list-nodes-and-their-attributes) 26 | - [Register (clone) an additionnal standby node](#register-clone-an-additionnal-standby-node) 27 | - [Register former primary as a standby node after automatic failover](#register-former-primary-as-a-standby-node-after-automatic-failover) 28 | - [License](#license) 29 | 30 | ### Requirements 31 | 32 | - Python >=3.8 33 | - Ansible-core >=2.12 34 | 35 | See [./requirements.txt](./requirements.txt) for detailled dependencies used to develop the role. 36 | 37 | **Recommended, for each postgresql host** 38 | - Python3 in PATH 39 | - Pip3 in PATH 40 | - [psycopg2-binary](https://pypi.org/project/psycopg2-binary/) (itself requires libpq-dev apt-package) 41 | 42 | You can take a look at [prepare.yml](molecule/default/prepare.yml) to check out an example setup for Python 3. 43 | 44 | ### Installation 45 | 46 | Shell 47 | ```bash 48 | ansible-galaxy collection install community.crypto 49 | ansible-galaxy install fidanf.postgresql_ha 50 | ``` 51 | 52 | Requirements file 53 | ```yaml 54 | --- 55 | roles: 56 | - src: https://github.com/fidanf/ansible-role-postgresql-ha 57 | name: fidanf.postgresql_ha 58 | version: master 59 | 60 | collections: 61 | - community.crypto 62 | 63 | ``` 64 | 65 | ### Dependencies 66 | 67 | - [cryptography](https://pypi.org/project/cryptography/) (ansible host) 68 | 69 | ### Example Inventory 70 | 71 | See [inventory.yml](./inventory.example.yml) for detailed group and host vars. 72 | 73 | ### Role variables 74 | 75 | Role default variables are split amongst two files : 76 | - [001-postgresql.yml](./defaults/main/001-postgresql.yml) 77 | - [002-repmgr.yml](./defaults/main/002-repmgr.yml) 78 | 79 | In order to exactly figure out the purpose and valid values for each of these variables, do not hesitate to inspect all the Jinja templates in the [templates](./templates) directory. Original default configuration files are also included (`.orig`). 80 | 81 | ### Example Playbook 82 | 83 | ```yaml 84 | --- 85 | - hosts: pgcluster 86 | gather_facts: yes 87 | become: yes 88 | roles: 89 | - name: fidanf.postgresql_ha 90 | vars: 91 | # Required configuration items 92 | repmgr_target_group: pgcluster 93 | repmgr_master: pgsql01 94 | repmgr_failover: automatic 95 | repmgr_promote_command: /usr/bin/repmgr standby promote -f /etc/repmgr.conf --log-to-file 96 | repmgr_follow_command: /usr/bin/repmgr standby follow -f /etc/repmgr.conf --log-to-file --upstream-node-id=%n 97 | repmgr_monitoring_history: "yes" 98 | repmgr_connection_check_type: query 99 | repmgr_log_level: DEBUG 100 | repmgr_reconnect_attempts: 2 101 | repmgr_reconnect_interval: 10 102 | # Basic settings 103 | postgresql_version: 13 104 | postgresql_cluster_name: main 105 | postgresql_cluster_reset: false # TODO: Needs to be tested for repmgr 106 | postgresql_listen_addresses: "*" 107 | postgresql_port: 5432 108 | postgresql_wal_level: "replica" 109 | postgresql_max_wal_senders: 10 110 | postgresql_max_replication_slots: 10 111 | postgresql_wal_keep_segments: 100 112 | postgresql_hot_standby: on 113 | postgresql_archive_mode: on 114 | postgresql_archive_command: "test ! -f /tmp/%f && cp %p /tmp/%f" 115 | postgresql_ext_install_repmgr: yes 116 | postgresql_shared_preload_libraries: 117 | - repmgr 118 | # postgresql logging 119 | postgresql_log_checkpoints: on 120 | postgresql_log_connections: on 121 | postgresql_log_disconnections: on 122 | postgresql_log_temp_files: 0 123 | # pg_hba.conf 124 | postgresql_pg_hba_custom: 125 | - { type: "host", database: "all", user: "all", address: "192.168.56.0/24", method: "md5" } 126 | - { type: "host", database: "replication", user: "{{ repmgr_user }}", address: "192.168.56.0/24", method: "trust" } 127 | - { type: "host", database: "replication", user: "{{ repmgr_user }}", address: "127.0.0.1/32", method: "trust" } 128 | - { type: "host", database: "{{ repmgr_database }}", user: "{{ repmgr_user }}", address: "127.0.0.1/32", method: "trust" } 129 | - { type: "host", database: "{{ repmgr_database }}", user: "{{ repmgr_user }}", address: "192.168.56.0/32", method: "trust" } 130 | # Databases 131 | postgresql_databases: 132 | - name: "{{ repmgr_database }}" 133 | owner: "{{ repmgr_user }}" 134 | encoding: "UTF-8" 135 | - name: testdb 136 | owner: admin 137 | encoding: "UTF-8" 138 | # Users 139 | postgresql_users: 140 | - name: "{{ repmgr_user }}" 141 | pass: "{{ repmgr_password }}" 142 | - name: admin 143 | pass: secret # postgresql >=10 does not accept unencrypted passwords 144 | encrypted: yes 145 | # Roles 146 | postgresql_user_privileges: 147 | - name: "{{ repmgr_user }}" 148 | db: "{{ repmgr_database }}" 149 | priv: "ALL" 150 | role_attr_flags: "SUPERUSER,REPLICATION" 151 | - name: admin 152 | db: testdb 153 | role_attr_flags: "SUPERUSER" 154 | 155 | ``` 156 | 157 | ## Usefull commands to run after your first installation 158 | 159 | ### Verifying cluster functionality 160 | 161 | ```bash 162 | ansible pgcluster -b --become-user postgres -m shell -a "repmgr cluster crosscheck" 163 | ``` 164 | 165 | ### Show cluster status 166 | 167 | ```bash 168 | ansible pgcluster -b --become-user postgres -m shell -a "repmgr cluster show" 169 | ``` 170 | 171 | ### List nodes and their attributes 172 | 173 | ```bash 174 | ansible pgcluster -b --become-user postgres -m shell -a "repmgr node status" 175 | ``` 176 | 177 | ### Register (clone) an additionnal standby node 178 | 179 | ```bash 180 | # Assuming the current primary hostname is pgsql01 181 | ansible-playbook myplaybook.yml -l 'pgsql04' -e 'repmgr_primary_hostname=pgsql01' -vv 182 | ``` 183 | 184 | ## Register former primary as a standby node after automatic failover 185 | 186 | ``` 187 | postgres@pgsql01:~$ pg_ctlcluster 13 main stop 188 | postgres@pgsql01:~$ repmgr standby clone --force -h pgsql02 -U repmgr -d repmgr 189 | postgres@pgsql01:~$ pg_ctlcluster 13 main start 190 | postgres@pgsql01:~$ repmgr standby register --force 191 | ``` 192 | 193 | Or you may use the repmgr node rejoin with [pg_rewind](https://repmgr.org/docs/current/repmgr-node-rejoin.html#REPMGR-NODE-REJOIN-PG-REWIND) 194 | 195 | ```bash 196 | repmgr node rejoin -d repmgr -U repmgr -h pgsql02 --verbose --force-rewind=/usr/lib/postgresql/13/bin/pg_rewind 197 | ``` 198 | 199 | ## License 200 | 201 | MIT / BSD 202 | -------------------------------------------------------------------------------- /templates/repmgr.conf-5.1.orig: -------------------------------------------------------------------------------- 1 | ################################################### 2 | # repmgr sample configuration file 3 | ################################################### 4 | 5 | # Some configuration items will be set with a default value; this 6 | # is noted for each item. Where no default value is shown, the 7 | # parameter will be treated as empty or false. 8 | # 9 | # repmgr parses its configuration file in the same way as PostgreSQL itself 10 | # does. In particular, strings must be enclosed in single quotes (although 11 | # simple identifiers may be provided as-is). 12 | # 13 | # For details on the configuration file format see the documentation at: 14 | # 15 | # https://repmgr.org/docs/current/configuration-file.html#CONFIGURATION-FILE-FORMAT 16 | # 17 | # ============================================================================= 18 | # Required configuration items 19 | # ============================================================================= 20 | # 21 | # repmgr and repmgrd require the following items to be explicitly configured. 22 | 23 | 24 | #node_id= # A unique integer greater than zero 25 | #node_name='' # An arbitrary (but unique) string; we recommend 26 | # using the server's hostname or another identifier 27 | # unambiguously associated with the server to avoid 28 | # confusion. Avoid choosing names which reflect the 29 | # node's current role, e.g. 'primary' or 'standby1', 30 | # as roles can change and it will be confusing if 31 | # the current primary is called 'standby1'. 32 | # The string's maximum length is 63 characters and it should 33 | # contain only printable ASCII characters. 34 | 35 | #conninfo='' # Database connection information as a conninfo string. 36 | # All servers in the cluster must be able to connect to 37 | # the local node using this string. 38 | # 39 | # For details on conninfo strings, see: 40 | # https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING 41 | # 42 | # If repmgrd is in use, consider explicitly setting 43 | # "connect_timeout" in the conninfo string to determine 44 | # the length of time which elapses before a network 45 | # connection attempt is abandoned; for details see: 46 | # https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNECT-CONNECT-TIMEOUT 47 | 48 | #data_directory='' # The node's data directory. This is needed by repmgr 49 | # when performing operations when the PostgreSQL instance 50 | # is not running and there's no other way of determining 51 | # the data directory. 52 | 53 | 54 | # ============================================================================= 55 | # Optional configuration items 56 | # ============================================================================= 57 | 58 | 59 | #------------------------------------------------------------------------------ 60 | # Server settings 61 | #------------------------------------------------------------------------------ 62 | 63 | #config_directory='' # If configuration files are located outside the data 64 | # directory, specify the directory where the main 65 | # postgresql.conf file is located. 66 | 67 | #------------------------------------------------------------------------------ 68 | # Replication settings 69 | #------------------------------------------------------------------------------ 70 | 71 | #replication_user='repmgr' # User to make replication connections with, if not set 72 | # defaults to the user defined in "conninfo". 73 | 74 | #replication_type='physical' # Must "physical" (the default). 75 | 76 | #location='default' # An arbitrary string defining the location of the node; this 77 | # is used during failover to check visibility of the 78 | # current primary node. For further details see: 79 | # https://repmgr.org/docs/current/repmgrd-network-split.html 80 | 81 | #use_replication_slots=no # whether to use physical replication slots 82 | # NOTE: when using replication slots, 83 | # 'max_replication_slots' should be configured for 84 | # at least the number of standbys which will connect 85 | # to the primary. 86 | 87 | #------------------------------------------------------------------------------ 88 | # Witness server settings 89 | #------------------------------------------------------------------------------ 90 | 91 | #witness_sync_interval=15 # interval (in seconds) to synchronise node records 92 | # to the witness server 93 | 94 | #------------------------------------------------------------------------------ 95 | # Logging settings 96 | #------------------------------------------------------------------------------ 97 | # 98 | # Note that logging facility settings will only apply to `repmgrd` by default; 99 | # `repmgr` will always write to STDERR unless the switch `--log-to-file` is 100 | # supplied, in which case it will log to the same destination as `repmgrd`. 101 | # This is mainly intended for those cases when `repmgr` is executed directly 102 | # by `repmgrd`. 103 | 104 | #log_level='INFO' # Log level: possible values are DEBUG, INFO, NOTICE, 105 | # WARNING, ERROR, ALERT, CRIT or EMERG 106 | 107 | #log_facility='STDERR' # Logging facility: possible values are STDERR, or for 108 | # syslog integration, one of LOCAL0, LOCAL1, ..., LOCAL7, USER 109 | 110 | #log_file='' # STDERR can be redirected to an arbitrary file 111 | #log_status_interval=300 # interval (in seconds) for repmgrd to log a status message 112 | 113 | 114 | #------------------------------------------------------------------------------ 115 | # Event notification settings 116 | #------------------------------------------------------------------------------ 117 | 118 | # event notifications can be passed to an arbitrary external program 119 | # together with the following parameters: 120 | # 121 | # %n - node ID 122 | # %e - event type 123 | # %s - success (1 or 0) 124 | # %t - timestamp 125 | # %d - details 126 | # 127 | # the values provided for "%t" and "%d" will probably contain spaces, 128 | # so should be quoted in the provided command configuration, e.g.: 129 | # 130 | # event_notification_command='/path/to/some/script %n %e %s "%t" "%d"' 131 | # 132 | # By default, all notifications will be passed; the notification types 133 | # can be filtered to explicitly named ones, e.g.: 134 | # 135 | # event_notifications=primary_register,standby_register 136 | 137 | #event_notification_command='' # An external program or script which 138 | # can be executed by the user under which 139 | # repmgr/repmgrd are run. 140 | 141 | #event_notifications='' # A commas-separated list of notification 142 | # types 143 | 144 | #------------------------------------------------------------------------------ 145 | # Environment/command settings 146 | #------------------------------------------------------------------------------ 147 | 148 | #pg_bindir='' # Path to PostgreSQL binary directory (location 149 | # of pg_ctl, pg_basebackup etc.). Only needed 150 | # if these files are not in the system $PATH. 151 | # 152 | # Debian/Ubuntu users: you will probably need to 153 | # set this to the directory where `pg_ctl` is located, 154 | # e.g. /usr/lib/postgresql/9.6/bin/ 155 | # 156 | # *NOTE* "pg_bindir" is only used when repmgr directly 157 | # executes PostgreSQL binaries; any user-defined scripts 158 | # *must* be specified with the full path 159 | 160 | #repmgr_bindir='' # Path to repmgr binary directory (location of the repmgr 161 | # binary. Only needed if the repmgr executable is not in 162 | # the system $PATH or the path defined in "pg_bindir". 163 | 164 | #use_primary_conninfo_password=false # explicitly set "password" in "primary_conninfo" 165 | # using the value contained in the environment variable 166 | # PGPASSWORD 167 | #passfile='' # path to .pgpass file to include in "primary_conninfo" 168 | 169 | #------------------------------------------------------------------------------ 170 | # external command options 171 | #------------------------------------------------------------------------------ 172 | # 173 | # Options which can be passed to external commands invoked by repmgr/repmgrd. 174 | # 175 | # Examples: 176 | # 177 | # pg_ctl_options='-s' 178 | # pg_basebackup_options='--label=repmgr_backup' 179 | # rsync_options=--archive --checksum --compress --progress --rsh="ssh -o \"StrictHostKeyChecking no\"" 180 | # ssh_options=-o "StrictHostKeyChecking no" 181 | 182 | #pg_ctl_options='' # Options to append to "pg_ctl" 183 | #pg_basebackup_options='' # Options to append to "pg_basebackup" 184 | #rsync_options='' # Options to append to "rsync" 185 | ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh" 186 | 187 | 188 | 189 | #------------------------------------------------------------------------------ 190 | # "standby clone" settings 191 | #------------------------------------------------------------------------------ 192 | # 193 | # These settings apply when cloning a standby ("repmgr standby clone"). 194 | # 195 | # Examples: 196 | # 197 | # tablespace_mapping='/path/to/original/tablespace=/path/to/new/tablespace' 198 | # restore_command = 'cp /path/to/archived/wals/%f %p' 199 | 200 | #tablespace_mapping='' # Tablespaces can be remapped from one 201 | # file system location to another. This 202 | # parameter can be provided multiple times. 203 | 204 | #restore_command='' # This will be included in the recovery configuration 205 | # generated by repmgr. 206 | 207 | #archive_cleanup_command='' # This will be included in the recovery configuration 208 | # generated by repmgr. Note we recommend using Barman for 209 | # managing WAL archives (see: https://www.pgbarman.org ) 210 | 211 | #recovery_min_apply_delay= # If provided, "recovery_min_apply_delay" will be set to 212 | # this value (PostgreSQL 9.4 and later). 213 | 214 | 215 | #------------------------------------------------------------------------------ 216 | # "standby promote" settings 217 | #------------------------------------------------------------------------------ 218 | 219 | # These settings apply when instructing a standby to promote itself to the 220 | # new primary ("repmgr standby promote"). 221 | 222 | #promote_check_timeout=60 # The length of time (in seconds) to wait 223 | # for the new primary to finish promoting 224 | #promote_check_interval=1 # The interval (in seconds) to check whether 225 | # the new primary has finished promoting 226 | 227 | 228 | #------------------------------------------------------------------------------ 229 | # "standby follow" settings 230 | #------------------------------------------------------------------------------ 231 | 232 | # These settings apply when instructing a standby to follow the new primary 233 | # ("repmgr standby follow"). 234 | 235 | #primary_follow_timeout=60 # The max length of time (in seconds) to wait 236 | # for the new primary to become available 237 | #standby_follow_timeout=15 # The max length of time (in seconds) to wait 238 | # for the standby to connect to the primary 239 | 240 | 241 | #------------------------------------------------------------------------------ 242 | # "standby switchover" settings 243 | #------------------------------------------------------------------------------ 244 | 245 | # These settings apply when switching roles between a primary and a standby 246 | # ("repmgr standby switchover"). 247 | 248 | #shutdown_check_timeout=60 # The max length of time (in seconds) to wait for the demotion 249 | # candidate (current primary) to shut down 250 | #standby_reconnect_timeout=60 # The max length of time (in seconds) to wait 251 | # for the demoted standby to reconnect to the promoted 252 | # primary (note: this value should be equal to or greater 253 | # than that set for "node_rejoin_timeout") 254 | #wal_receive_check_timeout=30 # The max length of time (in seconds) to wait for the walreceiver 255 | # on the standby to flush WAL to disk before comparing location 256 | # with the shut-down primary 257 | 258 | #------------------------------------------------------------------------------ 259 | # "node rejoin" settings 260 | #------------------------------------------------------------------------------ 261 | 262 | # These settings apply when reintegrating a node into a replication cluster 263 | # with "repmgrd_node_rejoin" 264 | 265 | #node_rejoin_timeout=60 # The maximum length of time (in seconds) to wait for 266 | # the node to reconnect to the replication cluster 267 | 268 | #------------------------------------------------------------------------------ 269 | # Barman options 270 | #------------------------------------------------------------------------------ 271 | 272 | #barman_server='' # The barman configuration section 273 | #barman_host='' # The host name of the barman server 274 | #barman_config='' # The Barman configuration file on the 275 | # Barman server (needed if the file is 276 | # in a non-standard location) 277 | 278 | #------------------------------------------------------------------------------ 279 | # Failover and monitoring settings (repmgrd) 280 | #------------------------------------------------------------------------------ 281 | # 282 | # These settings are only applied when repmgrd is running. Values shown 283 | # are defaults. 284 | 285 | #failover='manual' # one of 'automatic', 'manual'. 286 | # determines what action to take in the event of upstream failure 287 | # 288 | # 'automatic': repmgrd will automatically attempt to promote the 289 | # node or follow the new upstream node 290 | # 'manual': repmgrd will take no action and the node will require 291 | # manual attention to reattach it to replication 292 | 293 | #priority=100 # indicates a preferred priority for promoting nodes; 294 | # a value of zero prevents the node being promoted to primary 295 | # (default: 100) 296 | 297 | #connection_check_type=ping # How to check availability of the upstream node; valid options: 298 | # 'ping': use PQping() to check if the node is accepting connections 299 | # 'connection': execute a throwaway query on the current connection 300 | # 'query': execute an SQL statement on the node via the existing connection 301 | #reconnect_attempts=6 # Number of attempts which will be made to reconnect to an unreachable 302 | # primary (or other upstream node) 303 | #reconnect_interval=10 # Interval between attempts to reconnect to an unreachable 304 | # primary (or other upstream node) 305 | #promote_command='' # command repmgrd executes when promoting a new primary; use something like: 306 | # 307 | # repmgr standby promote -f /etc/repmgr.conf 308 | # 309 | #follow_command='' # command repmgrd executes when instructing a standby to follow a new primary; 310 | # use something like: 311 | # 312 | # repmgr standby follow -f /etc/repmgr.conf -W --upstream-node-id=%n 313 | # 314 | #primary_notification_timeout=60 # Interval (in seconds) which repmgrd on a standby 315 | # will wait for a notification from the new primary, 316 | # before falling back to degraded monitoring 317 | #repmgrd_standby_startup_timeout=60 # Interval (in seconds) which repmgrd on a standby will wait 318 | # for the the local node to restart and become ready to accept connections after 319 | # executing "follow_command" (defaults to the value set in "standby_reconnect_timeout") 320 | 321 | #monitoring_history=no # Whether to write monitoring data to the "montoring_history" table 322 | #monitor_interval_secs=2 # Interval (in seconds) at which to write monitoring data 323 | #degraded_monitoring_timeout=-1 # Interval (in seconds) after which repmgrd will terminate if the 324 | # server(s) being monitored are no longer available. -1 (default) 325 | # disables the timeout completely. 326 | #async_query_timeout=60 # Interval (in seconds) which repmgrd will wait before 327 | # cancelling an asynchronous query. 328 | #repmgrd_pid_file= # Path of PID file to use for repmgrd; if not set, a PID file will 329 | # be generated in a temporary directory specified by the environment 330 | # variable $TMPDIR, or if not set, in "/tmp". This value can be overridden 331 | # by the command line option "-p/--pid-file"; the command line option 332 | # "--no-pid-file" will force PID file creation to be skipped. 333 | # Note: there is normally no need to set this, particularly if 334 | # repmgr was installed from packages. 335 | #standby_disconnect_on_failover=false # If "true", in a failover situation wait for all standbys to 336 | # disconnect their WAL receivers before electing a new primary 337 | # (PostgreSQL 9.5 and later only; repmgr user must be a superuser for this) 338 | #sibling_nodes_disconnect_timeout=30 # If "standby_disconnect_on_failover" is true, the maximum length of time 339 | # (in seconds) to wait for other standbys to confirm they have disconnected their 340 | # WAL receivers 341 | #primary_visibility_consensus=false # If "true", only continue with failover if no standbys have seen 342 | # the primary node recently. *Must* be the same on all nodes. 343 | #failover_validation_command='' # Script to execute for an external mechanism to validate the failover 344 | # decision made by repmgrd. One or both of the following parameter placeholders 345 | # should be provided, which will be replaced by repmgrd with the appropriate 346 | # value: %n (node_id), %a (node_name). *Must* be the same on all nodes. 347 | #election_rerun_interval=15 # if "failover_validation_command" is set, and the command returns 348 | # an error, pause the specified amount of seconds before rerunning the election. 349 | # 350 | # The following items are relevant for repmgrd running on the primary, 351 | # and will be ignored on non-primary nodes 352 | #child_nodes_check_interval=5 # Interval (in seconds) to check for attached child nodes (standbys) 353 | #child_nodes_connected_min_count=-1 # Minimum number of child nodes which must remain connected, otherwise 354 | # disconnection command will be triggered 355 | #child_nodes_disconnect_min_count=-1 # Minimum number of disconnected child nodes required to execute disconnection command 356 | # (ignored if "child_nodes_connected_min_count" set) 357 | #child_nodes_disconnect_timeout=30 # Interval between child node disconnection and disconnection command execution 358 | #child_nodes_disconnect_command='' # Command to execute if child node disconnection detected 359 | 360 | #------------------------------------------------------------------------------ 361 | # service control commands 362 | #------------------------------------------------------------------------------ 363 | # 364 | # repmgr provides options to override the default pg_ctl commands 365 | # used to stop, start, restart, reload and promote the PostgreSQL cluster 366 | # 367 | # These options are useful when PostgreSQL has been installed from a package 368 | # which provides OS-level service commands. In environments using an init system 369 | # such as systemd, which keeps track of the state of various services, it is 370 | # essential that the service commands are correctly configured and pg_ctl is 371 | # not executed directly. 372 | # 373 | # NOTE: These commands must be runnable on remote nodes as well for switchover 374 | # to function correctly. 375 | # 376 | # If you use sudo, the user repmgr runs as (usually 'postgres') must have 377 | # passwordless sudo access to execute the command. 378 | # 379 | # For example, to use systemd, you can set 380 | # 381 | # service_start_command = 'sudo systemctl start postgresql-9.6' 382 | # (...) 383 | # 384 | # and then use the following sudoers configuration: 385 | # 386 | # # this is required when running sudo over ssh without -t: 387 | # Defaults:postgres !requiretty 388 | # postgres ALL = NOPASSWD: /usr/bin/systemctl stop postgresql-9.6, \ 389 | # /usr/bin/systemctl start postgresql-9.6, \ 390 | # /usr/bin/systemctl restart postgresql-9.6 391 | # 392 | # Debian/Ubuntu users: use "sudo pg_ctlcluster" to execute service control commands. 393 | # 394 | # For more details, see: https://repmgr.org/docs/current/configuration-service-commands.html 395 | 396 | #service_start_command = '' 397 | #service_stop_command = '' 398 | #service_restart_command = '' 399 | #service_reload_command = '' 400 | #service_promote_command = '' # This parameter is intended for systems which provide a 401 | # package-level promote command, such as Debian's 402 | # "pg_ctlcluster". *IMPORTANT*: it is *not* a substitute 403 | # for "promote_command"; do not use "repmgr standby promote" 404 | # (or a script which executes "repmgr standby promote") here. 405 | 406 | # Used by "repmgr service (start|stop)" to control repmgrd 407 | # 408 | #repmgrd_service_start_command = '' 409 | #repmgrd_service_stop_command = '' 410 | 411 | #------------------------------------------------------------------------------ 412 | # Status check thresholds 413 | #------------------------------------------------------------------------------ 414 | 415 | # Various warning/critical thresholds used by "repmgr node check". 416 | 417 | #archive_ready_warning=16 # repmgr node check --archive-ready 418 | #archive_ready_critical=128 # 419 | # Numbers of files pending archiving via PostgreSQL's 420 | # "archive_command" configuration parameter. If 421 | # files can't be archived fast enough, or the archive 422 | # command is failing, the buildup of files can 423 | # cause various issues, such as server shutdown being 424 | # delayed until all files are archived, or excessive 425 | # space being occupied by unarchived files. 426 | # 427 | # Note that these values will be checked when executing 428 | # "repmgr standby switchover" to warn about potential 429 | # issues with shutting down the demotion candidate. 430 | 431 | #replication_lag_warning=300 # repmgr node check --replication-lag 432 | #replication_lag_critical=600 # 433 | # Note that these values will be checked when executing 434 | # "repmgr standby switchover" to warn about potential 435 | # issues with shutting down the demotion candidate. 436 | -------------------------------------------------------------------------------- /templates/repmgr.conf-5.2.orig: -------------------------------------------------------------------------------- 1 | ################################################### 2 | # repmgr sample configuration file 3 | ################################################### 4 | 5 | # Some configuration items will be set with a default value; this 6 | # is noted for each item. Where no default value is shown, the 7 | # parameter will be treated as empty or false. 8 | # 9 | # repmgr parses its configuration file in the same way as PostgreSQL itself 10 | # does. In particular, strings must be enclosed in single quotes (although 11 | # simple identifiers may be provided as-is). 12 | # 13 | # For details on the configuration file format see the documentation at: 14 | # 15 | # https://repmgr.org/docs/current/configuration-file.html#CONFIGURATION-FILE-FORMAT 16 | # 17 | # ============================================================================= 18 | # Required configuration items 19 | # ============================================================================= 20 | # 21 | # repmgr and repmgrd require the following items to be explicitly configured. 22 | 23 | 24 | #node_id= # A unique integer greater than zero 25 | #node_name='' # An arbitrary (but unique) string; we recommend 26 | # using the server's hostname or another identifier 27 | # unambiguously associated with the server to avoid 28 | # confusion. Avoid choosing names which reflect the 29 | # node's current role, e.g. 'primary' or 'standby1', 30 | # as roles can change and it will be confusing if 31 | # the current primary is called 'standby1'. 32 | # The string's maximum length is 63 characters and it should 33 | # contain only printable ASCII characters. 34 | 35 | #conninfo='' # Database connection information as a conninfo string. 36 | # All servers in the cluster must be able to connect to 37 | # the local node using this string. 38 | # 39 | # For details on conninfo strings, see: 40 | # https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING 41 | # 42 | # If repmgrd is in use, consider explicitly setting 43 | # "connect_timeout" in the conninfo string to determine 44 | # the length of time which elapses before a network 45 | # connection attempt is abandoned; for details see: 46 | # https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNECT-CONNECT-TIMEOUT 47 | 48 | #data_directory='' # The node's data directory. This is needed by repmgr 49 | # when performing operations when the PostgreSQL instance 50 | # is not running and there's no other way of determining 51 | # the data directory. 52 | 53 | 54 | # ============================================================================= 55 | # Optional configuration items 56 | # ============================================================================= 57 | 58 | 59 | #------------------------------------------------------------------------------ 60 | # Server settings 61 | #------------------------------------------------------------------------------ 62 | 63 | #config_directory='' # If configuration files are located outside the data 64 | # directory, specify the directory where the main 65 | # postgresql.conf file is located. 66 | 67 | #------------------------------------------------------------------------------ 68 | # Replication settings 69 | #------------------------------------------------------------------------------ 70 | 71 | #replication_user='repmgr' # User to make replication connections with, if not set 72 | # defaults to the user defined in "conninfo". 73 | 74 | #replication_type='physical' # Must "physical" (the default). 75 | 76 | #location='default' # An arbitrary string defining the location of the node; this 77 | # is used during failover to check visibility of the 78 | # current primary node. For further details see: 79 | # https://repmgr.org/docs/current/repmgrd-network-split.html 80 | 81 | #use_replication_slots=no # whether to use physical replication slots 82 | # NOTE: when using replication slots, 83 | # 'max_replication_slots' should be configured for 84 | # at least the number of standbys which will connect 85 | # to the primary. 86 | 87 | #------------------------------------------------------------------------------ 88 | # Witness server settings 89 | #------------------------------------------------------------------------------ 90 | 91 | #witness_sync_interval=15 # interval (in seconds) to synchronise node records 92 | # to the witness server 93 | 94 | #------------------------------------------------------------------------------ 95 | # Logging settings 96 | #------------------------------------------------------------------------------ 97 | # 98 | # Note that logging facility settings will only apply to `repmgrd` by default; 99 | # `repmgr` will always write to STDERR unless the switch `--log-to-file` is 100 | # supplied, in which case it will log to the same destination as `repmgrd`. 101 | # This is mainly intended for those cases when `repmgr` is executed directly 102 | # by `repmgrd`. 103 | 104 | #log_level='INFO' # Log level: possible values are DEBUG, INFO, NOTICE, 105 | # WARNING, ERROR, ALERT, CRIT or EMERG 106 | 107 | #log_facility='STDERR' # Logging facility: possible values are STDERR, or for 108 | # syslog integration, one of LOCAL0, LOCAL1, ..., LOCAL7, USER 109 | 110 | #log_file='' # STDERR can be redirected to an arbitrary file 111 | #log_status_interval=300 # interval (in seconds) for repmgrd to log a status message 112 | 113 | 114 | #------------------------------------------------------------------------------ 115 | # Event notification settings 116 | #------------------------------------------------------------------------------ 117 | 118 | # event notifications can be passed to an arbitrary external program 119 | # together with the following parameters: 120 | # 121 | # %n - node ID 122 | # %e - event type 123 | # %s - success (1 or 0) 124 | # %t - timestamp 125 | # %d - details 126 | # 127 | # the values provided for "%t" and "%d" will probably contain spaces, 128 | # so should be quoted in the provided command configuration, e.g.: 129 | # 130 | # event_notification_command='/path/to/some/script %n %e %s "%t" "%d"' 131 | # 132 | # By default, all notifications will be passed; the notification types 133 | # can be filtered to explicitly named ones, e.g.: 134 | # 135 | # event_notifications=primary_register,standby_register 136 | 137 | #event_notification_command='' # An external program or script which 138 | # can be executed by the user under which 139 | # repmgr/repmgrd are run. 140 | 141 | #event_notifications='' # A commas-separated list of notification 142 | # types 143 | 144 | #------------------------------------------------------------------------------ 145 | # Environment/command settings 146 | #------------------------------------------------------------------------------ 147 | 148 | #pg_bindir='' # Path to PostgreSQL binary directory (location 149 | # of pg_ctl, pg_basebackup etc.). Only needed 150 | # if these files are not in the system $PATH. 151 | # 152 | # Debian/Ubuntu users: you will probably need to 153 | # set this to the directory where `pg_ctl` is located, 154 | # e.g. /usr/lib/postgresql/9.6/bin/ 155 | # 156 | # *NOTE* "pg_bindir" is only used when repmgr directly 157 | # executes PostgreSQL binaries; any user-defined scripts 158 | # *must* be specified with the full path 159 | 160 | #repmgr_bindir='' # Path to repmgr binary directory (location of the repmgr 161 | # binary. Only needed if the repmgr executable is not in 162 | # the system $PATH or the path defined in "pg_bindir". 163 | 164 | #use_primary_conninfo_password=false # explicitly set "password" in "primary_conninfo" 165 | # using the value contained in the environment variable 166 | # PGPASSWORD 167 | #passfile='' # path to .pgpass file to include in "primary_conninfo" 168 | 169 | #------------------------------------------------------------------------------ 170 | # external command options 171 | #------------------------------------------------------------------------------ 172 | # 173 | # Options which can be passed to external commands invoked by repmgr/repmgrd. 174 | # 175 | # Examples: 176 | # 177 | # pg_ctl_options='-s' 178 | # pg_basebackup_options='--label=repmgr_backup' 179 | # rsync_options=--archive --checksum --compress --progress --rsh="ssh -o \"StrictHostKeyChecking no\"" 180 | # ssh_options=-o "StrictHostKeyChecking no" 181 | 182 | #pg_ctl_options='' # Options to append to "pg_ctl" 183 | #pg_basebackup_options='' # Options to append to "pg_basebackup" 184 | # (Note: when cloning from Barman, repmgr will honour any 185 | # --waldir/--xlogdir setting present in "pg_basebackup_options" 186 | #rsync_options='' # Options to append to "rsync" 187 | ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh" 188 | 189 | 190 | 191 | #------------------------------------------------------------------------------ 192 | # "standby clone" settings 193 | #------------------------------------------------------------------------------ 194 | # 195 | # These settings apply when cloning a standby ("repmgr standby clone"). 196 | # 197 | # Examples: 198 | # 199 | # tablespace_mapping='/path/to/original/tablespace=/path/to/new/tablespace' 200 | # restore_command = 'cp /path/to/archived/wals/%f %p' 201 | 202 | #tablespace_mapping='' # Tablespaces can be remapped from one 203 | # file system location to another. This 204 | # parameter can be provided multiple times. 205 | 206 | #restore_command='' # This will be included in the recovery configuration 207 | # generated by repmgr. 208 | 209 | #archive_cleanup_command='' # This will be included in the recovery configuration 210 | # generated by repmgr. Note we recommend using Barman for 211 | # managing WAL archives (see: https://www.pgbarman.org ) 212 | 213 | #recovery_min_apply_delay= # If provided, "recovery_min_apply_delay" will be set to 214 | # this value (PostgreSQL 9.4 and later). Value can be 215 | # an integer representing milliseconds, or a string 216 | # representing a period of time (e.g. '5 min'). 217 | 218 | 219 | #------------------------------------------------------------------------------ 220 | # "standby promote" settings 221 | #------------------------------------------------------------------------------ 222 | 223 | # These settings apply when instructing a standby to promote itself to the 224 | # new primary ("repmgr standby promote"). 225 | 226 | #promote_check_timeout=60 # The length of time (in seconds) to wait 227 | # for the new primary to finish promoting 228 | #promote_check_interval=1 # The interval (in seconds) to check whether 229 | # the new primary has finished promoting 230 | 231 | 232 | #------------------------------------------------------------------------------ 233 | # "standby follow" settings 234 | #------------------------------------------------------------------------------ 235 | 236 | # These settings apply when instructing a standby to follow the new primary 237 | # ("repmgr standby follow"). 238 | 239 | #primary_follow_timeout=60 # The max length of time (in seconds) to wait 240 | # for the new primary to become available 241 | #standby_follow_timeout=15 # The max length of time (in seconds) to wait 242 | # for the standby to connect to the primary 243 | #standby_follow_restart=false # Restart the standby instead of sending a SIGHUP 244 | # (only for PostgreSQL 13 and later) 245 | 246 | #------------------------------------------------------------------------------ 247 | # "standby switchover" settings 248 | #------------------------------------------------------------------------------ 249 | 250 | # These settings apply when switching roles between a primary and a standby 251 | # ("repmgr standby switchover"). 252 | 253 | #shutdown_check_timeout=60 # The max length of time (in seconds) to wait for the demotion 254 | # candidate (current primary) to shut down 255 | #standby_reconnect_timeout=60 # The max length of time (in seconds) to wait 256 | # for the demoted standby to reconnect to the promoted 257 | # primary (note: this value should be equal to or greater 258 | # than that set for "node_rejoin_timeout") 259 | #wal_receive_check_timeout=30 # The max length of time (in seconds) to wait for the walreceiver 260 | # on the standby to flush WAL to disk before comparing location 261 | # with the shut-down primary 262 | 263 | #------------------------------------------------------------------------------ 264 | # "node rejoin" settings 265 | #------------------------------------------------------------------------------ 266 | 267 | # These settings apply when reintegrating a node into a replication cluster 268 | # with "repmgrd_node_rejoin" 269 | 270 | #node_rejoin_timeout=60 # The maximum length of time (in seconds) to wait for 271 | # the node to reconnect to the replication cluster 272 | 273 | #------------------------------------------------------------------------------ 274 | # Barman options 275 | #------------------------------------------------------------------------------ 276 | 277 | #barman_server='' # The barman configuration section 278 | #barman_host='' # The host name of the barman server 279 | #barman_config='' # The Barman configuration file on the 280 | # Barman server (needed if the file is 281 | # in a non-standard location) 282 | 283 | #------------------------------------------------------------------------------ 284 | # Failover and monitoring settings (repmgrd) 285 | #------------------------------------------------------------------------------ 286 | # 287 | # These settings are only applied when repmgrd is running. Values shown 288 | # are defaults. 289 | 290 | #failover='manual' # one of 'automatic', 'manual'. 291 | # determines what action to take in the event of upstream failure 292 | # 293 | # 'automatic': repmgrd will automatically attempt to promote the 294 | # node or follow the new upstream node 295 | # 'manual': repmgrd will take no action and the node will require 296 | # manual attention to reattach it to replication 297 | 298 | #priority=100 # indicates a preferred priority for promoting nodes; 299 | # a value of zero prevents the node being promoted to primary 300 | # (default: 100) 301 | 302 | #connection_check_type=ping # How to check availability of the upstream node; valid options: 303 | # 'ping': use PQping() to check if the node is accepting connections 304 | # 'connection': execute a throwaway query on the current connection 305 | # 'query': execute an SQL statement on the node via the existing connection 306 | #reconnect_attempts=6 # Number of attempts which will be made to reconnect to an unreachable 307 | # primary (or other upstream node) 308 | #reconnect_interval=10 # Interval between attempts to reconnect to an unreachable 309 | # primary (or other upstream node) 310 | #promote_command='' # command repmgrd executes when promoting a new primary; use something like: 311 | # 312 | # repmgr standby promote -f /etc/repmgr.conf 313 | # 314 | #follow_command='' # command repmgrd executes when instructing a standby to follow a new primary; 315 | # use something like: 316 | # 317 | # repmgr standby follow -f /etc/repmgr.conf -W --upstream-node-id=%n 318 | # 319 | #primary_notification_timeout=60 # Interval (in seconds) which repmgrd on a standby 320 | # will wait for a notification from the new primary, 321 | # before falling back to degraded monitoring 322 | #repmgrd_standby_startup_timeout=60 # Interval (in seconds) which repmgrd on a standby will wait 323 | # for the the local node to restart and become ready to accept connections after 324 | # executing "follow_command" (defaults to the value set in "standby_reconnect_timeout") 325 | 326 | #monitoring_history=no # Whether to write monitoring data to the "montoring_history" table 327 | #monitor_interval_secs=2 # Interval (in seconds) at which to write monitoring data 328 | #degraded_monitoring_timeout=-1 # Interval (in seconds) after which repmgrd will terminate if the 329 | # server(s) being monitored are no longer available. -1 (default) 330 | # disables the timeout completely. 331 | #async_query_timeout=60 # Interval (in seconds) which repmgrd will wait before 332 | # cancelling an asynchronous query. 333 | #repmgrd_pid_file= # Path of PID file to use for repmgrd; if not set, a PID file will 334 | # be generated in a temporary directory specified by the environment 335 | # variable $TMPDIR, or if not set, in "/tmp". This value can be overridden 336 | # by the command line option "-p/--pid-file"; the command line option 337 | # "--no-pid-file" will force PID file creation to be skipped. 338 | # Note: there is normally no need to set this, particularly if 339 | # repmgr was installed from packages. 340 | #standby_disconnect_on_failover=false # If "true", in a failover situation wait for all standbys to 341 | # disconnect their WAL receivers before electing a new primary 342 | # (PostgreSQL 9.5 and later only; repmgr user must be a superuser for this) 343 | #sibling_nodes_disconnect_timeout=30 # If "standby_disconnect_on_failover" is true, the maximum length of time 344 | # (in seconds) to wait for other standbys to confirm they have disconnected their 345 | # WAL receivers 346 | #primary_visibility_consensus=false # If "true", only continue with failover if no standbys have seen 347 | # the primary node recently. *Must* be the same on all nodes. 348 | #always_promote=false # Always promote a node, even if repmgr metadata is outdated 349 | #failover_validation_command='' # Script to execute for an external mechanism to validate the failover 350 | # decision made by repmgrd. One or both of the following parameter placeholders 351 | # should be provided, which will be replaced by repmgrd with the appropriate 352 | # value: %n (node_id), %a (node_name). *Must* be the same on all nodes. 353 | #election_rerun_interval=15 # if "failover_validation_command" is set, and the command returns 354 | # an error, pause the specified amount of seconds before rerunning the election. 355 | # 356 | # The following items are relevant for repmgrd running on the primary, 357 | # and will be ignored on non-primary nodes 358 | #child_nodes_check_interval=5 # Interval (in seconds) to check for attached child nodes (standbys) 359 | #child_nodes_connected_min_count=-1 # Minimum number of child nodes which must remain connected, otherwise 360 | # disconnection command will be triggered 361 | #child_nodes_disconnect_min_count=-1 # Minimum number of disconnected child nodes required to execute disconnection command 362 | # (ignored if "child_nodes_connected_min_count" set) 363 | #child_nodes_disconnect_timeout=30 # Interval between child node disconnection and disconnection command execution 364 | #child_nodes_disconnect_command='' # Command to execute if child node disconnection detected 365 | 366 | #------------------------------------------------------------------------------ 367 | # service control commands 368 | #------------------------------------------------------------------------------ 369 | # 370 | # repmgr provides options to override the default pg_ctl commands 371 | # used to stop, start, restart, reload and promote the PostgreSQL cluster 372 | # 373 | # These options are useful when PostgreSQL has been installed from a package 374 | # which provides OS-level service commands. In environments using an init system 375 | # such as systemd, which keeps track of the state of various services, it is 376 | # essential that the service commands are correctly configured and pg_ctl is 377 | # not executed directly. 378 | # 379 | # NOTE: These commands must be runnable on remote nodes as well for switchover 380 | # to function correctly. 381 | # 382 | # If you use sudo, the user repmgr runs as (usually 'postgres') must have 383 | # passwordless sudo access to execute the command. 384 | # 385 | # For example, to use systemd, you can set 386 | # 387 | # service_start_command = 'sudo systemctl start postgresql-9.6' 388 | # (...) 389 | # 390 | # and then use the following sudoers configuration: 391 | # 392 | # # this is required when running sudo over ssh without -t: 393 | # Defaults:postgres !requiretty 394 | # postgres ALL = NOPASSWD: /usr/bin/systemctl stop postgresql-9.6, \ 395 | # /usr/bin/systemctl start postgresql-9.6, \ 396 | # /usr/bin/systemctl restart postgresql-9.6 397 | # 398 | # Debian/Ubuntu users: use "sudo pg_ctlcluster" to execute service control commands. 399 | # 400 | # For more details, see: https://repmgr.org/docs/current/configuration-service-commands.html 401 | 402 | #service_start_command = '' 403 | #service_stop_command = '' 404 | #service_restart_command = '' 405 | #service_reload_command = '' 406 | #service_promote_command = '' # This parameter is intended for systems which provide a 407 | # package-level promote command, such as Debian's 408 | # "pg_ctlcluster". *IMPORTANT*: it is *not* a substitute 409 | # for "promote_command"; do not use "repmgr standby promote" 410 | # (or a script which executes "repmgr standby promote") here. 411 | 412 | # Used by "repmgr service (start|stop)" to control repmgrd 413 | # 414 | #repmgrd_service_start_command = '' 415 | #repmgrd_service_stop_command = '' 416 | 417 | #------------------------------------------------------------------------------ 418 | # Status check thresholds 419 | #------------------------------------------------------------------------------ 420 | 421 | # Various warning/critical thresholds used by "repmgr node check". 422 | 423 | #archive_ready_warning=16 # repmgr node check --archive-ready 424 | #archive_ready_critical=128 # 425 | # Numbers of files pending archiving via PostgreSQL's 426 | # "archive_command" configuration parameter. If 427 | # files can't be archived fast enough, or the archive 428 | # command is failing, the buildup of files can 429 | # cause various issues, such as server shutdown being 430 | # delayed until all files are archived, or excessive 431 | # space being occupied by unarchived files. 432 | # 433 | # Note that these values will be checked when executing 434 | # "repmgr standby switchover" to warn about potential 435 | # issues with shutting down the demotion candidate. 436 | 437 | #replication_lag_warning=300 # repmgr node check --replication-lag 438 | #replication_lag_critical=600 # 439 | # Note that these values will be checked when executing 440 | # "repmgr standby switchover" to warn about potential 441 | # issues with shutting down the demotion candidate. 442 | 443 | -------------------------------------------------------------------------------- /templates/repmgr.conf-5.3.orig: -------------------------------------------------------------------------------- 1 | ################################################### 2 | # repmgr sample configuration file 3 | ################################################### 4 | 5 | # Some configuration items will be set with a default value; this 6 | # is noted for each item. Where no default value is shown, the 7 | # parameter will be treated as empty or false. 8 | # 9 | # repmgr parses its configuration file in the same way as PostgreSQL itself 10 | # does. In particular, strings must be enclosed in single quotes (although 11 | # simple identifiers may be provided as-is). 12 | # 13 | # For details on the configuration file format see the documentation at: 14 | # 15 | # https://repmgr.org/docs/current/configuration-file.html#CONFIGURATION-FILE-FORMAT 16 | # 17 | # ============================================================================= 18 | # Required configuration items 19 | # ============================================================================= 20 | # 21 | # repmgr and repmgrd require the following items to be explicitly configured. 22 | 23 | 24 | #node_id= # A unique integer greater than zero 25 | #node_name='' # An arbitrary (but unique) string; we recommend 26 | # using the server's hostname or another identifier 27 | # unambiguously associated with the server to avoid 28 | # confusion. Avoid choosing names which reflect the 29 | # node's current role, e.g. 'primary' or 'standby1', 30 | # as roles can change and it will be confusing if 31 | # the current primary is called 'standby1'. 32 | # The string's maximum length is 63 characters and it should 33 | # contain only printable ASCII characters. 34 | 35 | #conninfo='' # Database connection information as a conninfo string. 36 | # All servers in the cluster must be able to connect to 37 | # the local node using this string. 38 | # 39 | # For details on conninfo strings, see: 40 | # https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING 41 | # 42 | # If repmgrd is in use, consider explicitly setting 43 | # "connect_timeout" in the conninfo string to determine 44 | # the length of time which elapses before a network 45 | # connection attempt is abandoned; for details see: 46 | # https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNECT-CONNECT-TIMEOUT 47 | 48 | #data_directory='' # The node's data directory. This is needed by repmgr 49 | # when performing operations when the PostgreSQL instance 50 | # is not running and there's no other way of determining 51 | # the data directory. 52 | 53 | 54 | # ============================================================================= 55 | # Optional configuration items 56 | # ============================================================================= 57 | 58 | 59 | #------------------------------------------------------------------------------ 60 | # Server settings 61 | #------------------------------------------------------------------------------ 62 | 63 | #config_directory='' # If configuration files are located outside the data 64 | # directory, specify the directory where the main 65 | # postgresql.conf file is located. 66 | 67 | #------------------------------------------------------------------------------ 68 | # Replication settings 69 | #------------------------------------------------------------------------------ 70 | 71 | #replication_user='repmgr' # User to make replication connections with, if not set 72 | # defaults to the user defined in "conninfo". 73 | 74 | #replication_type='physical' # Must "physical" (the default). 75 | 76 | #location='default' # An arbitrary string defining the location of the node; this 77 | # is used during failover to check visibility of the 78 | # current primary node. For further details see: 79 | # https://repmgr.org/docs/current/repmgrd-network-split.html 80 | 81 | #use_replication_slots=no # whether to use physical replication slots 82 | # NOTE: when using replication slots, 83 | # 'max_replication_slots' should be configured for 84 | # at least the number of standbys which will connect 85 | # to the primary. 86 | 87 | #------------------------------------------------------------------------------ 88 | # Witness server settings 89 | #------------------------------------------------------------------------------ 90 | 91 | #witness_sync_interval=15 # interval (in seconds) to synchronise node records 92 | # to the witness server 93 | 94 | #------------------------------------------------------------------------------ 95 | # Logging settings 96 | #------------------------------------------------------------------------------ 97 | # 98 | # Note that logging facility settings will only apply to `repmgrd` by default; 99 | # `repmgr` will always write to STDERR unless the switch `--log-to-file` is 100 | # supplied, in which case it will log to the same destination as `repmgrd`. 101 | # This is mainly intended for those cases when `repmgr` is executed directly 102 | # by `repmgrd`. 103 | 104 | #log_level='INFO' # Log level: possible values are DEBUG, INFO, NOTICE, 105 | # WARNING, ERROR, ALERT, CRIT or EMERG 106 | 107 | #log_facility='STDERR' # Logging facility: possible values are STDERR, or for 108 | # syslog integration, one of LOCAL0, LOCAL1, ..., LOCAL7, USER 109 | 110 | #log_file='' # STDERR can be redirected to an arbitrary file 111 | #log_status_interval=300 # interval (in seconds) for repmgrd to log a status message 112 | 113 | 114 | #------------------------------------------------------------------------------ 115 | # Event notification settings 116 | #------------------------------------------------------------------------------ 117 | 118 | # event notifications can be passed to an arbitrary external program 119 | # together with the following parameters: 120 | # 121 | # %n - node ID 122 | # %e - event type 123 | # %s - success (1 or 0) 124 | # %t - timestamp 125 | # %d - details 126 | # 127 | # the values provided for "%t" and "%d" will probably contain spaces, 128 | # so should be quoted in the provided command configuration, e.g.: 129 | # 130 | # event_notification_command='/path/to/some/script %n %e %s "%t" "%d"' 131 | # 132 | # By default, all notifications will be passed; the notification types 133 | # can be filtered to explicitly named ones, e.g.: 134 | # 135 | # event_notifications=primary_register,standby_register 136 | 137 | #event_notification_command='' # An external program or script which 138 | # can be executed by the user under which 139 | # repmgr/repmgrd are run. 140 | 141 | #event_notifications='' # A commas-separated list of notification 142 | # types 143 | 144 | #------------------------------------------------------------------------------ 145 | # Environment/command settings 146 | #------------------------------------------------------------------------------ 147 | 148 | #pg_bindir='' # Path to PostgreSQL binary directory (location 149 | # of pg_ctl, pg_basebackup etc.). Only needed 150 | # if these files are not in the system $PATH. 151 | # 152 | # Debian/Ubuntu users: you will probably need to 153 | # set this to the directory where `pg_ctl` is located, 154 | # e.g. /usr/lib/postgresql/9.6/bin/ 155 | # 156 | # *NOTE* "pg_bindir" is only used when repmgr directly 157 | # executes PostgreSQL binaries; any user-defined scripts 158 | # *must* be specified with the full path 159 | 160 | #repmgr_bindir='' # Path to repmgr binary directory (location of the repmgr 161 | # binary. Only needed if the repmgr executable is not in 162 | # the system $PATH or the path defined in "pg_bindir". 163 | 164 | #use_primary_conninfo_password=false # explicitly set "password" in "primary_conninfo" 165 | # using the value contained in the environment variable 166 | # PGPASSWORD 167 | #passfile='' # path to .pgpass file to include in "primary_conninfo" 168 | 169 | #------------------------------------------------------------------------------ 170 | # external command options 171 | #------------------------------------------------------------------------------ 172 | # 173 | # Options which can be passed to external commands invoked by repmgr/repmgrd. 174 | # 175 | # Examples: 176 | # 177 | # pg_ctl_options='-s' 178 | # pg_basebackup_options='--label=repmgr_backup' 179 | # rsync_options=--archive --checksum --compress --progress --rsh="ssh -o \"StrictHostKeyChecking no\"" 180 | # ssh_options=-o "StrictHostKeyChecking no" 181 | 182 | #pg_ctl_options='' # Options to append to "pg_ctl" 183 | #pg_basebackup_options='' # Options to append to "pg_basebackup" 184 | # (Note: when cloning from Barman, repmgr will honour any 185 | # --waldir/--xlogdir setting present in "pg_basebackup_options" 186 | #rsync_options='' # Options to append to "rsync" 187 | ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh" 188 | 189 | 190 | 191 | #------------------------------------------------------------------------------ 192 | # "standby clone" settings 193 | #------------------------------------------------------------------------------ 194 | # 195 | # These settings apply when cloning a standby ("repmgr standby clone"). 196 | # 197 | # Examples: 198 | # 199 | # tablespace_mapping='/path/to/original/tablespace=/path/to/new/tablespace' 200 | # restore_command = 'cp /path/to/archived/wals/%f %p' 201 | 202 | #tablespace_mapping='' # Tablespaces can be remapped from one 203 | # file system location to another. This 204 | # parameter can be provided multiple times. 205 | 206 | #restore_command='' # This will be included in the recovery configuration 207 | # generated by repmgr. 208 | 209 | #archive_cleanup_command='' # This will be included in the recovery configuration 210 | # generated by repmgr. Note we recommend using Barman for 211 | # managing WAL archives (see: https://www.pgbarman.org ) 212 | 213 | #recovery_min_apply_delay= # If provided, "recovery_min_apply_delay" will be set to 214 | # this value (PostgreSQL 9.4 and later). Value can be 215 | # an integer representing milliseconds, or a string 216 | # representing a period of time (e.g. '5 min'). 217 | 218 | 219 | #------------------------------------------------------------------------------ 220 | # "standby promote" settings 221 | #------------------------------------------------------------------------------ 222 | 223 | # These settings apply when instructing a standby to promote itself to the 224 | # new primary ("repmgr standby promote"). 225 | 226 | #promote_check_timeout=60 # The length of time (in seconds) to wait 227 | # for the new primary to finish promoting 228 | #promote_check_interval=1 # The interval (in seconds) to check whether 229 | # the new primary has finished promoting 230 | 231 | 232 | #------------------------------------------------------------------------------ 233 | # "standby follow" settings 234 | #------------------------------------------------------------------------------ 235 | 236 | # These settings apply when instructing a standby to follow the new primary 237 | # ("repmgr standby follow"). 238 | 239 | #primary_follow_timeout=60 # The max length of time (in seconds) to wait 240 | # for the new primary to become available 241 | #standby_follow_timeout=30 # The max length of time (in seconds) to wait 242 | # for the standby to connect to the primary 243 | #standby_follow_restart=false # Restart the standby instead of sending a SIGHUP 244 | # (only for PostgreSQL 13 and later) 245 | 246 | #------------------------------------------------------------------------------ 247 | # "standby switchover" settings 248 | #------------------------------------------------------------------------------ 249 | 250 | # These settings apply when switching roles between a primary and a standby 251 | # ("repmgr standby switchover"). 252 | 253 | #shutdown_check_timeout=60 # The max length of time (in seconds) to wait for the demotion 254 | # candidate (current primary) to shut down 255 | #standby_reconnect_timeout=60 # The max length of time (in seconds) to wait 256 | # for the demoted standby to reconnect to the promoted 257 | # primary (note: this value should be equal to or greater 258 | # than that set for "node_rejoin_timeout") 259 | #wal_receive_check_timeout=30 # The max length of time (in seconds) to wait for the walreceiver 260 | # on the standby to flush WAL to disk before comparing location 261 | # with the shut-down primary 262 | 263 | #------------------------------------------------------------------------------ 264 | # "node rejoin" settings 265 | #------------------------------------------------------------------------------ 266 | 267 | # These settings apply when reintegrating a node into a replication cluster 268 | # with "repmgrd_node_rejoin" 269 | 270 | #node_rejoin_timeout=60 # The maximum length of time (in seconds) to wait for 271 | # the node to reconnect to the replication cluster 272 | 273 | #------------------------------------------------------------------------------ 274 | # Barman options 275 | #------------------------------------------------------------------------------ 276 | 277 | #barman_server='' # The barman configuration section 278 | #barman_host='' # The host name of the barman server 279 | #barman_config='' # The Barman configuration file on the 280 | # Barman server (needed if the file is 281 | # in a non-standard location) 282 | 283 | #------------------------------------------------------------------------------ 284 | # Failover and monitoring settings (repmgrd) 285 | #------------------------------------------------------------------------------ 286 | # 287 | # These settings are only applied when repmgrd is running. Values shown 288 | # are defaults. 289 | 290 | #failover='manual' # one of 'automatic', 'manual'. 291 | # determines what action to take in the event of upstream failure 292 | # 293 | # 'automatic': repmgrd will automatically attempt to promote the 294 | # node or follow the new upstream node 295 | # 'manual': repmgrd will take no action and the node will require 296 | # manual attention to reattach it to replication 297 | 298 | #priority=100 # indicates a preferred priority for promoting nodes; 299 | # a value of zero prevents the node being promoted to primary 300 | # (default: 100) 301 | 302 | #connection_check_type=ping # How to check availability of the upstream node; valid options: 303 | # 'ping': use PQping() to check if the node is accepting connections 304 | # 'connection': attempt to make a new connection to the node 305 | # 'query': execute an SQL statement on the node via the existing connection 306 | #reconnect_attempts=6 # Number of attempts which will be made to reconnect to an unreachable 307 | # primary (or other upstream node) 308 | #reconnect_interval=10 # Interval between attempts to reconnect to an unreachable 309 | # primary (or other upstream node) 310 | #promote_command='' # command repmgrd executes when promoting a new primary; use something like: 311 | # 312 | # repmgr standby promote -f /etc/repmgr.conf 313 | # 314 | #follow_command='' # command repmgrd executes when instructing a standby to follow a new primary; 315 | # use something like: 316 | # 317 | # repmgr standby follow -f /etc/repmgr.conf -W --upstream-node-id=%n 318 | # 319 | #primary_notification_timeout=60 # Interval (in seconds) which repmgrd on a standby 320 | # will wait for a notification from the new primary, 321 | # before falling back to degraded monitoring 322 | #repmgrd_standby_startup_timeout=60 # Interval (in seconds) which repmgrd on a standby will wait 323 | # for the the local node to restart and become ready to accept connections after 324 | # executing "follow_command" (defaults to the value set in "standby_reconnect_timeout") 325 | 326 | #monitoring_history=no # Whether to write monitoring data to the "monitoring_history" table 327 | #monitor_interval_secs=2 # Interval (in seconds) at which to write monitoring data 328 | #degraded_monitoring_timeout=-1 # Interval (in seconds) after which repmgrd will terminate if the 329 | # server(s) being monitored are no longer available. -1 (default) 330 | # disables the timeout completely. 331 | #async_query_timeout=60 # Interval (in seconds) which repmgrd will wait before 332 | # cancelling an asynchronous query. 333 | #repmgrd_pid_file= # Path of PID file to use for repmgrd; if not set, a PID file will 334 | # be generated in a temporary directory specified by the environment 335 | # variable $TMPDIR, or if not set, in "/tmp". This value can be overridden 336 | # by the command line option "-p/--pid-file"; the command line option 337 | # "--no-pid-file" will force PID file creation to be skipped. 338 | # Note: there is normally no need to set this, particularly if 339 | # repmgr was installed from packages. 340 | #repmgrd_exit_on_inactive_node=false # If "true", and the node record is marked as "inactive", abort repmgrd startup 341 | #standby_disconnect_on_failover=false # If "true", in a failover situation wait for all standbys to 342 | # disconnect their WAL receivers before electing a new primary 343 | # (PostgreSQL 9.5 and later only; repmgr user must be a superuser for this) 344 | #sibling_nodes_disconnect_timeout=30 # If "standby_disconnect_on_failover" is true, the maximum length of time 345 | # (in seconds) to wait for other standbys to confirm they have disconnected their 346 | # WAL receivers 347 | #primary_visibility_consensus=false # If "true", only continue with failover if no standbys have seen 348 | # the primary node recently. *Must* be the same on all nodes. 349 | #always_promote=false # Always promote a node, even if repmgr metadata is outdated 350 | #failover_validation_command='' # Script to execute for an external mechanism to validate the failover 351 | # decision made by repmgrd. One or both of the following parameter placeholders 352 | # should be provided, which will be replaced by repmgrd with the appropriate 353 | # value: %n (node_id), %a (node_name). *Must* be the same on all nodes. 354 | #election_rerun_interval=15 # if "failover_validation_command" is set, and the command returns 355 | # an error, pause the specified amount of seconds before rerunning the election. 356 | # 357 | # The following items are relevant for repmgrd running on the primary, 358 | # and will be ignored on non-primary nodes 359 | #child_nodes_check_interval=5 # Interval (in seconds) to check for attached child nodes (standbys) 360 | #child_nodes_connected_min_count=-1 # Minimum number of child nodes which must remain connected, otherwise 361 | # disconnection command will be triggered 362 | #child_nodes_disconnect_min_count=-1 # Minimum number of disconnected child nodes required to execute disconnection command 363 | # (ignored if "child_nodes_connected_min_count" set) 364 | #child_nodes_disconnect_timeout=30 # Interval between child node disconnection and disconnection command execution 365 | #child_nodes_disconnect_command='' # Command to execute if child node disconnection detected 366 | 367 | #------------------------------------------------------------------------------ 368 | # service control commands 369 | #------------------------------------------------------------------------------ 370 | # 371 | # repmgr provides options to override the default pg_ctl commands 372 | # used to stop, start, restart, reload and promote the PostgreSQL cluster 373 | # 374 | # These options are useful when PostgreSQL has been installed from a package 375 | # which provides OS-level service commands. In environments using an init system 376 | # such as systemd, which keeps track of the state of various services, it is 377 | # essential that the service commands are correctly configured and pg_ctl is 378 | # not executed directly. 379 | # 380 | # NOTE: These commands must be runnable on remote nodes as well for switchover 381 | # to function correctly. 382 | # 383 | # If you use sudo, the user repmgr runs as (usually 'postgres') must have 384 | # passwordless sudo access to execute the command. 385 | # 386 | # For example, to use systemd, you can set 387 | # 388 | # service_start_command = 'sudo systemctl start postgresql-9.6' 389 | # (...) 390 | # 391 | # and then use the following sudoers configuration: 392 | # 393 | # # this is required when running sudo over ssh without -t: 394 | # Defaults:postgres !requiretty 395 | # postgres ALL = NOPASSWD: /usr/bin/systemctl stop postgresql-9.6, \ 396 | # /usr/bin/systemctl start postgresql-9.6, \ 397 | # /usr/bin/systemctl restart postgresql-9.6 398 | # 399 | # Debian/Ubuntu users: use "sudo pg_ctlcluster" to execute service control commands. 400 | # 401 | # For more details, see: https://repmgr.org/docs/current/configuration-service-commands.html 402 | 403 | #service_start_command = '' 404 | #service_stop_command = '' 405 | #service_restart_command = '' 406 | #service_reload_command = '' 407 | #service_promote_command = '' # This parameter is intended for systems which provide a 408 | # package-level promote command, such as Debian's 409 | # "pg_ctlcluster". *IMPORTANT*: it is *not* a substitute 410 | # for "promote_command"; do not use "repmgr standby promote" 411 | # (or a script which executes "repmgr standby promote") here. 412 | 413 | # Used by "repmgr service (start|stop)" to control repmgrd 414 | # 415 | #repmgrd_service_start_command = '' 416 | #repmgrd_service_stop_command = '' 417 | 418 | #------------------------------------------------------------------------------ 419 | # Status check thresholds 420 | #------------------------------------------------------------------------------ 421 | 422 | # Various warning/critical thresholds used by "repmgr node check". 423 | 424 | #archive_ready_warning=16 # repmgr node check --archive-ready 425 | #archive_ready_critical=128 # 426 | # Numbers of files pending archiving via PostgreSQL's 427 | # "archive_command" configuration parameter. If 428 | # files can't be archived fast enough, or the archive 429 | # command is failing, the buildup of files can 430 | # cause various issues, such as server shutdown being 431 | # delayed until all files are archived, or excessive 432 | # space being occupied by unarchived files. 433 | # 434 | # Note that these values will be checked when executing 435 | # "repmgr standby switchover" to warn about potential 436 | # issues with shutting down the demotion candidate. 437 | 438 | #replication_lag_warning=300 # repmgr node check --replication-lag 439 | #replication_lag_critical=600 # 440 | # Note that these values will be checked when executing 441 | # "repmgr standby switchover" to warn about potential 442 | # issues with shutting down the demotion candidate. 443 | -------------------------------------------------------------------------------- /templates/repmgr.conf-5.1.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | ################################################### 3 | # repmgr sample configuration file 4 | ################################################### 5 | 6 | # Some configuration items will be set with a default value; this 7 | # is noted for each item. Where no default value is shown, the 8 | # parameter will be treated as empty or false. 9 | 10 | # ============================================================================= 11 | # Required configuration items 12 | # ============================================================================= 13 | # 14 | # repmgr and repmgrd require the following items to be explicitly configured. 15 | 16 | 17 | node_id='{{ repmgr_node_id if repmgr_node_id is defined else range(1, 65535) | random(seed=ansible_hostname) }}' # A unique integer greater than zero 18 | node_name='{{ansible_hostname}}' # An arbitrary (but unique) string; we recommend 19 | # using the server's hostname or another identifier 20 | # unambiguously associated with the server to avoid 21 | # confusion. Avoid choosing names which reflect the 22 | # node's current role, e.g. "primary" or "standby1", 23 | # as roles can change and it will be confusing if 24 | # the current primary is called "standby1". 25 | 26 | conninfo='{{repmgr_conninfo}}' # Database connection information as a conninfo string. 27 | # All servers in the cluster must be able to connect to 28 | # the local node using this string. 29 | # 30 | # For details on conninfo strings, see: 31 | # https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING 32 | # 33 | # If repmgrd is in use, consider explicitly setting 34 | # "connect_timeout" in the conninfo string to determine 35 | # the length of time which elapses before a network 36 | # connection attempt is abandoned; for details see: 37 | # https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNECT-CONNECT-TIMEOUT 38 | 39 | data_directory='{{repmgr_data_directory}}' # The node's data directory. This is needed by repmgr 40 | # when performing operations when the PostgreSQL instance 41 | # is not running and there's no other way of determining 42 | # the data directory. 43 | 44 | 45 | # ============================================================================= 46 | 47 | # Optional configuration items 48 | # ============================================================================= 49 | 50 | 51 | #------------------------------------------------------------------------------ 52 | # Server settings 53 | #------------------------------------------------------------------------------ 54 | 55 | config_directory='{{repmgr_config_directory}}' # If configuration files are located outside the data 56 | # directory, specify the directory where the main 57 | # postgresql.conf file is located. 58 | 59 | #------------------------------------------------------------------------------ 60 | # Replication settings 61 | #------------------------------------------------------------------------------ 62 | 63 | replication_user='{{repmgr_replication_user}}' # User to make replication connections with, if not set defaults 64 | # to the user defined in "conninfo". 65 | 66 | replication_type='{{repmgr_replication_type}}' # Must be one of 'physical' or 'bdr'. 67 | 68 | location='{{repmgr_location}}' # arbitrary string defining the location of the node; this 69 | # is used during failover to check visibilty of the 70 | # current primary node. See the 'repmgrd' documentation 71 | # in README.md for further details. 72 | 73 | use_replication_slots='{{repmgr_use_replication_slots}}' # whether to use physical replication slots 74 | # NOTE: when using replication slots, 75 | # 'max_replication_slots' should be configured for 76 | # at least the number of standbys which will connect 77 | # to the primary. 78 | 79 | #------------------------------------------------------------------------------ 80 | # Witness server settings 81 | #------------------------------------------------------------------------------ 82 | 83 | witness_sync_interval={{repmgr_witness_sync_interval}} # interval (in seconds) to synchronise node records 84 | # to the witness server 85 | 86 | #------------------------------------------------------------------------------ 87 | # Logging settings 88 | #------------------------------------------------------------------------------ 89 | # 90 | # Note that logging facility settings will only apply to `repmgrd` by default; 91 | # `repmgr` will always write to STDERR unless the switch `--log-to-file` is 92 | # supplied, in which case it will log to the same destination as `repmgrd`. 93 | # This is mainly intended for those cases when `repmgr` is executed directly 94 | # by `repmgrd`. 95 | 96 | log_level={{repmgr_log_level}} # Log level: possible values are DEBUG, INFO, NOTICE, 97 | # WARNING, ERROR, ALERT, CRIT or EMERG 98 | 99 | log_facility={{repmgr_log_facility}} # Logging facility: possible values are STDERR, or for 100 | # syslog integration, one of LOCAL0, LOCAL1, ..., LOCAL7, USER 101 | 102 | {{ '' if repmgr_log_file else '#' }}log_file='{{repmgr_log_file}}' # STDERR can be redirected to an arbitrary file 103 | log_status_interval={{repmgr_log_status_interval}} # interval (in seconds) for repmgrd to log a status message 104 | 105 | 106 | #------------------------------------------------------------------------------ 107 | # Event notification settings 108 | #------------------------------------------------------------------------------ 109 | 110 | # event notifications can be passed to an arbitrary external program 111 | # together with the following parameters: 112 | # 113 | # %n - node ID 114 | # %e - event type 115 | # %s - success (1 or 0) 116 | # %t - timestamp 117 | # %d - details 118 | # 119 | # the values provided for "%t" and "%d" will probably contain spaces, 120 | # so should be quoted in the provided command configuration, e.g.: 121 | # 122 | # event_notification_command='/path/to/some/script %n %e %s "%t" "%d"' 123 | # 124 | # By default, all notifications will be passed; the notification types 125 | # can be filtered to explicitly named ones, e.g.: 126 | # 127 | # event_notifications=primary_register,standby_register 128 | 129 | {{ '' if repmgr_event_notification_command else '#' }}event_notification_command='{{repmgr_event_notification_command}}' # An external program or script which 130 | # can be executed by the user under which 131 | # repmgr/repmgrd are run. 132 | 133 | {{ '' if repmgr_event_notifications else '#' }}event_notifications='{{repmgr_event_notifications}}' # A commas-separated list of notification 134 | # types 135 | 136 | #------------------------------------------------------------------------------ 137 | # Environment/command settings 138 | #------------------------------------------------------------------------------ 139 | 140 | pg_bindir='{{repmgr_pg_bindir}}' # Path to PostgreSQL binary directory (location 141 | # of pg_ctl, pg_basebackup etc.). Only needed 142 | # if these files are not in the system $PATH. 143 | # 144 | # Debian/Ubuntu users: you will probably need to 145 | # set this to the directory where `pg_ctl` is located, 146 | # e.g. /usr/lib/postgresql/9.6/bin/ 147 | # 148 | # *NOTE* "pg_bindir" is only used when repmgr directly 149 | # executes PostgreSQL binaries; any user-defined scripts 150 | # *must* be specified with the full path 151 | 152 | repmgr_bindir='{{repmgr_repmgr_bindir}}' # Path to repmgr binary directory (location of the repmgr 153 | # binary. Only needed if the repmgr executable is not in 154 | # the system $PATH or the path defined in "pg_bindir". 155 | 156 | use_primary_conninfo_password={{repmgr_use_primary_conninfo_password}} # explicitly set "password" in recovery.conf's 157 | # "primary_conninfo" parameter using the value contained 158 | # in the environment variable PGPASSWORD 159 | passfile='{{ repmgr_passfile }}' # path to .pgpass file to include in "primary_conninfo" 160 | 161 | #------------------------------------------------------------------------------ 162 | # external command options 163 | #------------------------------------------------------------------------------ 164 | # 165 | # Options which can be passed to external commands invoked by repmgr/repmgrd. 166 | # 167 | # Examples: 168 | # 169 | # pg_ctl_options='-s' 170 | # pg_basebackup_options='--label=repmgr_backup' 171 | # rsync_options=--archive --checksum --compress --progress --rsh="ssh -o \"StrictHostKeyChecking no\"" 172 | # ssh_options=-o "StrictHostKeyChecking no" 173 | 174 | {{ '' if repmgr_pg_ctl_options else '#' }}pg_ctl_options='{{repmgr_pg_ctl_options}}' # Options to append to "pg_ctl" 175 | {{ '' if repmgr_pg_basebackup_options else '#' }}pg_basebackup_options='{{repmgr_pg_basebackup_options}}' # Options to append to "pg_basebackup" 176 | {{ '' if repmgr_rsync_options else '#' }}rsync_options='{{repmgr_rsync_options}}' # Options to append to "rsync" 177 | ssh_options='{{repmgr_ssh_options}}' # Options to append to "ssh" 178 | 179 | 180 | 181 | #------------------------------------------------------------------------------ 182 | # "standby clone" settings 183 | #------------------------------------------------------------------------------ 184 | # 185 | # These settings apply when cloning a standby ("repmgr standby clone"). 186 | # 187 | # Examples: 188 | # 189 | # tablespace_mapping=/path/to/original/tablespace=/path/to/new/tablespace 190 | # restore_command = 'cp /path/to/archived/wals/%f %p' 191 | 192 | {{ '' if repmgr_tablespace_mapping else '#' }}tablespace_mapping='{{repmgr_tablespace_mapping}}' # Tablespaces can be remapped from one 193 | # file system location to another. This 194 | # parameter can be provided multiple times. 195 | 196 | {{ '' if repmgr_restore_command else '#' }}restore_command='{{repmgr_restore_command}}' # This will be placed in the recovery.conf file generated 197 | # by repmgr. 198 | 199 | {{ '' if repmgr_archive_cleanup_command else '#' }}archive_cleanup_command='{{repmgr_archive_cleanup_command}}' # This will be placed in the recovery.conf file generated 200 | # by repmgr. Note we recommend using Barman for managing 201 | # WAL archives (see: https://www.pgbarman.org ) 202 | 203 | {{ '' if repmgr_recovery_min_apply_delay else '#' }}recovery_min_apply_delay={{repmgr_recovery_min_apply_delay}} # If provided, "recovery_min_apply_delay" in recovery.conf 204 | # will be set to this value (PostgreSQL 9.4 and later). 205 | 206 | 207 | #------------------------------------------------------------------------------ 208 | # "standby promote" settings 209 | #------------------------------------------------------------------------------ 210 | 211 | # These settings apply when instructing a standby to promote itself to the 212 | # new primary ("repmgr standby promote"). 213 | 214 | promote_check_timeout={{repmgr_promote_check_timeout}} # The length of time (in seconds) to wait 215 | # for the new primary to finish promoting 216 | promote_check_interval={{repmgr_promote_check_interval}} # The interval (in seconds) to check whether 217 | # the new primary has finished promoting 218 | 219 | 220 | #------------------------------------------------------------------------------ 221 | # "standby follow" settings 222 | #------------------------------------------------------------------------------ 223 | 224 | # These settings apply when instructing a standby to follow the new primary 225 | # ("repmgr standby follow"). 226 | 227 | primary_follow_timeout={{repmgr_primary_follow_timeout}} # The max length of time (in seconds) to wait 228 | # for the new primary to become available 229 | standby_follow_timeout={{repmgr_standby_follow_timeout}} # The max length of time (in seconds) to wait 230 | # for the standby to connect to the primary 231 | 232 | 233 | #------------------------------------------------------------------------------ 234 | # "standby switchover" settings 235 | #------------------------------------------------------------------------------ 236 | 237 | # These settings apply when switching roles between a primary and a standby 238 | # ("repmgr standby switchover"). 239 | 240 | shutdown_check_timeout={{repmgr_shutdown_check_timeout}} # The max length of time (in seconds) to wait for the demotion 241 | # candidate (current primary) to shut down 242 | standby_reconnect_timeout={{repmgr_standby_reconnect_timeout}} # The max length of time (in seconds) to wait 243 | # for the demoted standby to reconnect to the promoted 244 | # primary (note: this value should be equal to or greater 245 | # than that set for "node_rejoin_timeout") 246 | #wal_receive_check_timeout=30 # The max length of time (in seconds) to wait for the walreceiver 247 | # on the standby to flush WAL to disk before comparing location 248 | # with the shut-down primary 249 | 250 | #------------------------------------------------------------------------------ 251 | # "node rejoin" settings 252 | #------------------------------------------------------------------------------ 253 | 254 | # These settings apply when reintegrating a node into a replication cluster 255 | # with "repmgrd_node_rejoin" 256 | 257 | node_rejoin_timeout={{repmgr_node_rejoin_timeout}} # The maximum length of time (in seconds) to wait for 258 | # the node to reconnect to the replication cluster 259 | 260 | #------------------------------------------------------------------------------ 261 | # Barman options 262 | #------------------------------------------------------------------------------ 263 | 264 | {{ '' if repmgr_barman_server else '#' }}barman_server='{{repmgr_barman_server}}' # The barman configuration section 265 | {{ '' if repmgr_barman_host else '#' }}barman_host='{{repmgr_barman_host}}' # The host name of the barman server 266 | {{ '' if repmgr_barman_config else '#' }}barman_config='{{repmgr_barman_config}}' # The Barman configuration file on the 267 | # Barman server (needed if the file is 268 | # in a non-standard location) 269 | 270 | #------------------------------------------------------------------------------ 271 | # Failover and monitoring settings (repmgrd) 272 | #------------------------------------------------------------------------------ 273 | # 274 | # These settings are only applied when repmgrd is running. Values shown 275 | # are defaults. 276 | 277 | failover={{repmgr_failover}} # one of 'automatic', 'manual'. 278 | # determines what action to take in the event of upstream failure 279 | # 280 | # 'automatic': repmgrd will automatically attempt to promote the 281 | # node or follow the new upstream node 282 | # 'manual': repmgrd will take no action and the node will require 283 | # manual attention to reattach it to replication 284 | # (does not apply to BDR mode) 285 | 286 | priority={{repmgr_priority}} # indicate a preferred priority for promoting nodes; 287 | # a value of zero prevents the node being promoted to primary 288 | # (default: 100) 289 | connection_check_type={{repmgr_connection_check_type}} # How to check availability of the upstream node; valid options: 290 | # 'ping': use PQping() to check if the node is accepting connections 291 | # 'connection': execute a throwaway query on the current connection 292 | # 'query': execute an SQL statement on the node via the existing connection 293 | reconnect_attempts={{repmgr_reconnect_attempts}} # Number of attempts which will be made to reconnect to an unreachable 294 | # primary (or other upstream node) 295 | reconnect_interval={{repmgr_reconnect_interval}} # Interval between attempts to reconnect to an unreachable 296 | # primary (or other upstream node) 297 | {{ '' if repmgr_promote_command else '#' }}promote_command='{{repmgr_promote_command}}' # command repmgrd executes when promoting a new primary; use something like: 298 | # 299 | # repmgr standby promote -f /etc/repmgr.conf 300 | # 301 | {{ '' if repmgr_follow_command else '#' }}follow_command='{{repmgr_follow_command}}' # command repmgrd executes when instructing a standby to follow a new primary; 302 | # use something like: 303 | # 304 | # repmgr standby follow -f /etc/repmgr.conf -W --upstream-node-id=%n 305 | # 306 | primary_notification_timeout={{repmgr_primary_notification_timeout}} # Interval (in seconds) which repmgrd on a standby 307 | # will wait for a notification from the new primary, 308 | # before falling back to degraded monitoring 309 | repmgrd_standby_startup_timeout={{repmgr_repmgrd_standby_startup_timeout}} # Interval (in seconds) which repmgrd on a standby will wait 310 | # for the the local node to restart and become ready to accept connections after 311 | # executing "follow_command" (defaults to the value set in "standby_reconnect_timeout") 312 | 313 | monitoring_history={{repmgr_monitoring_history}} # Whether to write monitoring data to the "montoring_history" table 314 | monitor_interval_secs={{repmgr_monitor_interval_secs}} # Interval (in seconds) at which to write monitoring data 315 | degraded_monitoring_timeout={{repmgr_degraded_monitoring_timeout}} # Interval (in seconds) after which repmgrd will terminate if the 316 | # server being monitored is no longer available. -1 (default) 317 | # disables the timeout completely. 318 | async_query_timeout={{repmgr_async_query_timeout}} # Interval (in seconds) which repmgrd will wait before 319 | # cancelling an asynchronous query. 320 | {{ '' if repmgr_repmgrd_pid_file else '#' }}repmgrd_pid_file={{repmgr_repmgrd_pid_file}} # Path of PID file to use for repmgrd; if not set, a PID file will 321 | # be generated in a temporary directory specified by the environment 322 | # variable $TMPDIR, or if not set, in "/tmp". This value can be overridden 323 | # by the command line option "-p/--pid-file"; the command line option 324 | # "--no-pid-file" will force PID file creation to be skipped. 325 | standby_disconnect_on_failover={{repmgr_standby_disconnect_on_failover}} # If "true", in a failover situation wait for all standbys to 326 | # disconnect their WAL receivers before electing a new primary 327 | # (PostgreSQL 9.5 and later only; repmgr user must be a superuser for this) 328 | sibling_nodes_disconnect_timeout={{repmgr_sibling_nodes_disconnect_timeout}} # If "standby_disconnect_on_failover" is true, the maximum length of time 329 | # (in seconds) to wait for other standbys to confirm they have disconnected their 330 | # WAL receivers 331 | primary_visibility_consensus={{repmgr_primary_visibility_consensus}} # If "true", only continue with failover if no standbys have seen 332 | # the primary node recently. *Must* be the same on all nodes. 333 | {{ '' if repmgr_failover_validation_command else '#' }}failover_validation_command='{{repmgr_failover_validation_command}}' # Script to execute for an external mechanism to validate the failover 334 | # decision made by repmgrd. One or both of the following parameter placeholders 335 | # should be provided, which will be replaced by repmgrd with the appropriate 336 | # value: %n (node_id), %a (node_name). *Must* be the same on all nodes. 337 | election_rerun_interval={{repmgr_election_rerun_interval}} # if "failover_validation_command" is set, and the command returns 338 | # an error, pause the specified amount of seconds before rerunning the election. 339 | # 340 | # The following items are relevant for repmgrd running on the primary, 341 | # and will be ignored on non-primary nodes 342 | child_nodes_check_interval={{repmgr_child_nodes_check_interval}} # Interval (in seconds) to check for attached child nodes (standbys) 343 | child_nodes_connected_min_count={{repmgr_child_nodes_connected_min_count}} # Minimum number of child nodes which must remain connected, otherwise 344 | # disconnection command will be triggered 345 | child_nodes_disconnect_min_count={{repmgr_child_nodes_disconnect_min_count}} # Minimum number of disconnected child nodes required to execute disconnection command 346 | # (ignored if "child_nodes_connected_min_count" set) 347 | child_nodes_disconnect_timeout={{repmgr_child_nodes_disconnect_timeout}} # Interval between child node disconnection and disconnection command execution 348 | {{ '' if repmgr_child_nodes_disconnect_command else '#' }}={{repmgr_child_nodes_disconnect_command}} # Command to execute if child node disconnection detected 349 | 350 | #------------------------------------------------------------------------------ 351 | # service control commands 352 | #------------------------------------------------------------------------------ 353 | # 354 | # repmgr provides options to override the default pg_ctl commands 355 | # used to stop, start, restart, reload and promote the PostgreSQL cluster 356 | # 357 | # NOTE: These commands must be runnable on remote nodes as well for switchover 358 | # to function correctly. 359 | # 360 | # If you use sudo, the user repmgr runs as (usually 'postgres') must have 361 | # passwordless sudo access to execute the command. 362 | # 363 | # For example, to use systemd, you can set 364 | # 365 | # service_start_command = 'sudo systemctl start postgresql-9.6' 366 | # (...) 367 | # 368 | # and then use the following sudoers configuration: 369 | # 370 | # # this is required when running sudo over ssh without -t: 371 | # Defaults:postgres !requiretty 372 | # postgres ALL = NOPASSWD: /usr/bin/systemctl stop postgresql-9.6, \ 373 | # /usr/bin/systemctl start postgresql-9.6, \ 374 | # /usr/bin/systemctl restart postgresql-9.6 375 | # 376 | # Debian/Ubuntu users: use "sudo pg_ctlcluster" to execute service control commands. 377 | # 378 | # For more details, see: https://repmgr.org/docs/current/configuration-service-commands.html 379 | 380 | service_start_command ='{{ repmgr_service_start_command }}' 381 | service_stop_command ='{{ repmgr_service_stop_command }}' 382 | service_restart_command ='{{ repmgr_service_restart_command }}' 383 | service_reload_command ='{{ repmgr_service_reload_command }}' 384 | {{ '' if repmgr_service_promote_command else '#' }}service_promote_command ='{{ repmgr_service_promote_command }}' # This parameter is intended for systems which provide a 385 | # package-level promote command, such as Debian's 386 | # "pg_ctlcluster". *IMPORTANT*: it is *not* a substitute 387 | # for "promote_command"; do not use "repmgr standby promote" 388 | # (or a script which executes "repmgr standby promote") here. 389 | 390 | # Used by "repmgr service (start|stop)" to control repmgrd 391 | # 392 | repmgrd_service_start_command = '{{ repmgrd_service_start_command }}' 393 | repmgrd_service_stop_command = '{{ repmgrd_service_stop_command }}' 394 | 395 | #------------------------------------------------------------------------------ 396 | # Status check thresholds 397 | #------------------------------------------------------------------------------ 398 | 399 | # Various warning/critical thresholds used by "repmgr node check". 400 | 401 | archive_ready_warning={{repmgr_archive_ready_warning}} # repmgr node check --archive-ready 402 | archive_ready_critical={{repmgr_archive_ready_critical}} # 403 | # Numbers of files pending archiving via PostgreSQL's 404 | # "archive_command" configuration parameter. If 405 | # files can't be archived fast enough, or the archive 406 | # command is failing, the buildup of files can 407 | # cause various issues, such as server shutdown being 408 | # delayed until all files are archived, or excessive 409 | # space being occupied by unarchived files. 410 | # 411 | # Note that these values will be checked when executing 412 | # "repmgr standby switchover" to warn about potential 413 | # issues with shutting down the demotion candidate. 414 | 415 | replication_lag_warning={{repmgr_replication_lag_warning}} # repmgr node check --replication-lag 416 | replication_lag_critical={{repmgr_replication_lag_critical}} # 417 | # Note that these values will be checked when executing 418 | # "repmgr standby switchover" to warn about potential 419 | # issues with shutting down the demotion candidate. 420 | -------------------------------------------------------------------------------- /templates/repmgr.conf-5.2.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | ################################################### 3 | # repmgr sample configuration file 4 | ################################################### 5 | 6 | # Some configuration items will be set with a default value; this 7 | # is noted for each item. Where no default value is shown, the 8 | # parameter will be treated as empty or false. 9 | 10 | # ============================================================================= 11 | # Required configuration items 12 | # ============================================================================= 13 | # 14 | # repmgr and repmgrd require the following items to be explicitly configured. 15 | 16 | 17 | node_id='{{ repmgr_node_id if repmgr_node_id is defined else range(1, 65535) | random(seed=ansible_hostname) }}' # A unique integer greater than zero 18 | node_name='{{ansible_hostname}}' # An arbitrary (but unique) string; we recommend 19 | # using the server's hostname or another identifier 20 | # unambiguously associated with the server to avoid 21 | # confusion. Avoid choosing names which reflect the 22 | # node's current role, e.g. "primary" or "standby1", 23 | # as roles can change and it will be confusing if 24 | # the current primary is called "standby1". 25 | 26 | conninfo='{{repmgr_conninfo}}' # Database connection information as a conninfo string. 27 | # All servers in the cluster must be able to connect to 28 | # the local node using this string. 29 | # 30 | # For details on conninfo strings, see: 31 | # https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING 32 | # 33 | # If repmgrd is in use, consider explicitly setting 34 | # "connect_timeout" in the conninfo string to determine 35 | # the length of time which elapses before a network 36 | # connection attempt is abandoned; for details see: 37 | # https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNECT-CONNECT-TIMEOUT 38 | 39 | data_directory='{{repmgr_data_directory}}' # The node's data directory. This is needed by repmgr 40 | # when performing operations when the PostgreSQL instance 41 | # is not running and there's no other way of determining 42 | # the data directory. 43 | 44 | 45 | # ============================================================================= 46 | 47 | # Optional configuration items 48 | # ============================================================================= 49 | 50 | 51 | #------------------------------------------------------------------------------ 52 | # Server settings 53 | #------------------------------------------------------------------------------ 54 | 55 | config_directory='{{repmgr_config_directory}}' # If configuration files are located outside the data 56 | # directory, specify the directory where the main 57 | # postgresql.conf file is located. 58 | 59 | #------------------------------------------------------------------------------ 60 | # Replication settings 61 | #------------------------------------------------------------------------------ 62 | 63 | replication_user='{{repmgr_replication_user}}' # User to make replication connections with, if not set defaults 64 | # to the user defined in "conninfo". 65 | 66 | #replication_type='{{repmgr_replication_type}}' # Must be one of 'physical' or 'bdr'. 67 | 68 | location='{{repmgr_location}}' # arbitrary string defining the location of the node; this 69 | # is used during failover to check visibilty of the 70 | # current primary node. See the 'repmgrd' documentation 71 | # in README.md for further details. 72 | 73 | use_replication_slots='{{repmgr_use_replication_slots}}' # whether to use physical replication slots 74 | # NOTE: when using replication slots, 75 | # 'max_replication_slots' should be configured for 76 | # at least the number of standbys which will connect 77 | # to the primary. 78 | 79 | #------------------------------------------------------------------------------ 80 | # Witness server settings 81 | #------------------------------------------------------------------------------ 82 | 83 | witness_sync_interval={{repmgr_witness_sync_interval}} # interval (in seconds) to synchronise node records 84 | # to the witness server 85 | 86 | #------------------------------------------------------------------------------ 87 | # Logging settings 88 | #------------------------------------------------------------------------------ 89 | # 90 | # Note that logging facility settings will only apply to `repmgrd` by default; 91 | # `repmgr` will always write to STDERR unless the switch `--log-to-file` is 92 | # supplied, in which case it will log to the same destination as `repmgrd`. 93 | # This is mainly intended for those cases when `repmgr` is executed directly 94 | # by `repmgrd`. 95 | 96 | log_level={{repmgr_log_level}} # Log level: possible values are DEBUG, INFO, NOTICE, 97 | # WARNING, ERROR, ALERT, CRIT or EMERG 98 | 99 | log_facility={{repmgr_log_facility}} # Logging facility: possible values are STDERR, or for 100 | # syslog integration, one of LOCAL0, LOCAL1, ..., LOCAL7, USER 101 | 102 | {{ '' if repmgr_log_file else '#' }}log_file='{{repmgr_log_file}}' # STDERR can be redirected to an arbitrary file 103 | log_status_interval={{repmgr_log_status_interval}} # interval (in seconds) for repmgrd to log a status message 104 | 105 | 106 | #------------------------------------------------------------------------------ 107 | # Event notification settings 108 | #------------------------------------------------------------------------------ 109 | 110 | # event notifications can be passed to an arbitrary external program 111 | # together with the following parameters: 112 | # 113 | # %n - node ID 114 | # %e - event type 115 | # %s - success (1 or 0) 116 | # %t - timestamp 117 | # %d - details 118 | # 119 | # the values provided for "%t" and "%d" will probably contain spaces, 120 | # so should be quoted in the provided command configuration, e.g.: 121 | # 122 | # event_notification_command='/path/to/some/script %n %e %s "%t" "%d"' 123 | # 124 | # By default, all notifications will be passed; the notification types 125 | # can be filtered to explicitly named ones, e.g.: 126 | # 127 | # event_notifications=primary_register,standby_register 128 | 129 | {{ '' if repmgr_event_notification_command else '#' }}event_notification_command='{{repmgr_event_notification_command}}' # An external program or script which 130 | # can be executed by the user under which 131 | # repmgr/repmgrd are run. 132 | 133 | {{ '' if repmgr_event_notifications else '#' }}event_notifications='{{repmgr_event_notifications}}' # A commas-separated list of notification 134 | # types 135 | 136 | #------------------------------------------------------------------------------ 137 | # Environment/command settings 138 | #------------------------------------------------------------------------------ 139 | 140 | pg_bindir='{{repmgr_pg_bindir}}' # Path to PostgreSQL binary directory (location 141 | # of pg_ctl, pg_basebackup etc.). Only needed 142 | # if these files are not in the system $PATH. 143 | # 144 | # Debian/Ubuntu users: you will probably need to 145 | # set this to the directory where `pg_ctl` is located, 146 | # e.g. /usr/lib/postgresql/9.6/bin/ 147 | # 148 | # *NOTE* "pg_bindir" is only used when repmgr directly 149 | # executes PostgreSQL binaries; any user-defined scripts 150 | # *must* be specified with the full path 151 | 152 | repmgr_bindir='{{repmgr_repmgr_bindir}}' # Path to repmgr binary directory (location of the repmgr 153 | # binary. Only needed if the repmgr executable is not in 154 | # the system $PATH or the path defined in "pg_bindir". 155 | 156 | use_primary_conninfo_password={{repmgr_use_primary_conninfo_password}} # explicitly set "password" in recovery.conf's 157 | # "primary_conninfo" parameter using the value contained 158 | # in the environment variable PGPASSWORD 159 | passfile='{{ repmgr_passfile }}' # path to .pgpass file to include in "primary_conninfo" 160 | 161 | #------------------------------------------------------------------------------ 162 | # external command options 163 | #------------------------------------------------------------------------------ 164 | # 165 | # Options which can be passed to external commands invoked by repmgr/repmgrd. 166 | # 167 | # Examples: 168 | # 169 | # pg_ctl_options='-s' 170 | # pg_basebackup_options='--label=repmgr_backup' 171 | # rsync_options=--archive --checksum --compress --progress --rsh="ssh -o \"StrictHostKeyChecking no\"" 172 | # ssh_options=-o "StrictHostKeyChecking no" 173 | 174 | {{ '' if repmgr_pg_ctl_options else '#' }}pg_ctl_options='{{repmgr_pg_ctl_options}}' # Options to append to "pg_ctl" 175 | {{ '' if repmgr_pg_basebackup_options else '#' }}pg_basebackup_options='{{repmgr_pg_basebackup_options}}' # Options to append to "pg_basebackup" 176 | # (Note: when cloning from Barman, repmgr will honour any 177 | # --waldir/--xlogdir setting present in "pg_basebackup_options" 178 | {{ '' if repmgr_rsync_options else '#' }}rsync_options='{{repmgr_rsync_options}}' # Options to append to "rsync" 179 | ssh_options='{{repmgr_ssh_options}}' # Options to append to "ssh" 180 | 181 | 182 | 183 | #------------------------------------------------------------------------------ 184 | # "standby clone" settings 185 | #------------------------------------------------------------------------------ 186 | # 187 | # These settings apply when cloning a standby ("repmgr standby clone"). 188 | # 189 | # Examples: 190 | # 191 | # tablespace_mapping=/path/to/original/tablespace=/path/to/new/tablespace 192 | # restore_command = 'cp /path/to/archived/wals/%f %p' 193 | 194 | {{ '' if repmgr_tablespace_mapping else '#' }}tablespace_mapping='{{repmgr_tablespace_mapping}}' # Tablespaces can be remapped from one 195 | # file system location to another. This 196 | # parameter can be provided multiple times. 197 | 198 | {{ '' if repmgr_restore_command else '#' }}restore_command='{{repmgr_restore_command}}' # This will be placed in the recovery.conf file generated 199 | # by repmgr. 200 | 201 | {{ '' if repmgr_archive_cleanup_command else '#' }}archive_cleanup_command='{{repmgr_archive_cleanup_command}}' # This will be placed in the recovery.conf file generated 202 | # by repmgr. Note we recommend using Barman for managing 203 | # WAL archives (see: https://www.pgbarman.org ) 204 | 205 | {{ '' if repmgr_recovery_min_apply_delay else '#' }}recovery_min_apply_delay={{repmgr_recovery_min_apply_delay}} # If provided, "recovery_min_apply_delay" in recovery.conf 206 | # will be set to this value (PostgreSQL 9.4 and later). Value can be 207 | # an integer representing milliseconds, or a string 208 | # representing a period of time (e.g. '5 min'). 209 | 210 | #------------------------------------------------------------------------------ 211 | # "standby promote" settings 212 | #------------------------------------------------------------------------------ 213 | 214 | # These settings apply when instructing a standby to promote itself to the 215 | # new primary ("repmgr standby promote"). 216 | 217 | promote_check_timeout={{repmgr_promote_check_timeout}} # The length of time (in seconds) to wait 218 | # for the new primary to finish promoting 219 | promote_check_interval={{repmgr_promote_check_interval}} # The interval (in seconds) to check whether 220 | # the new primary has finished promoting 221 | 222 | 223 | #------------------------------------------------------------------------------ 224 | # "standby follow" settings 225 | #------------------------------------------------------------------------------ 226 | 227 | # These settings apply when instructing a standby to follow the new primary 228 | # ("repmgr standby follow"). 229 | 230 | primary_follow_timeout={{repmgr_primary_follow_timeout}} # The max length of time (in seconds) to wait 231 | # for the new primary to become available 232 | standby_follow_timeout={{repmgr_standby_follow_timeout}} # The max length of time (in seconds) to wait 233 | # for the standby to connect to the primary 234 | standby_follow_restart={{repmgr_standby_follow_restart}} # Restart the standby instead of sending a SIGHUP (only for PostgreSQL 13 and later) 235 | 236 | #------------------------------------------------------------------------------ 237 | # "standby switchover" settings 238 | #------------------------------------------------------------------------------ 239 | 240 | # These settings apply when switching roles between a primary and a standby 241 | # ("repmgr standby switchover"). 242 | 243 | shutdown_check_timeout={{repmgr_shutdown_check_timeout}} # The max length of time (in seconds) to wait for the demotion 244 | # candidate (current primary) to shut down 245 | standby_reconnect_timeout={{repmgr_standby_reconnect_timeout}} # The max length of time (in seconds) to wait 246 | # for the demoted standby to reconnect to the promoted 247 | # primary (note: this value should be equal to or greater 248 | # than that set for "node_rejoin_timeout") 249 | #wal_receive_check_timeout=30 # The max length of time (in seconds) to wait for the walreceiver 250 | # on the standby to flush WAL to disk before comparing location 251 | # with the shut-down primary 252 | 253 | #------------------------------------------------------------------------------ 254 | # "node rejoin" settings 255 | #------------------------------------------------------------------------------ 256 | 257 | # These settings apply when reintegrating a node into a replication cluster 258 | # with "repmgrd_node_rejoin" 259 | 260 | node_rejoin_timeout={{repmgr_node_rejoin_timeout}} # The maximum length of time (in seconds) to wait for 261 | # the node to reconnect to the replication cluster 262 | 263 | #------------------------------------------------------------------------------ 264 | # Barman options 265 | #------------------------------------------------------------------------------ 266 | 267 | {{ '' if repmgr_barman_server else '#' }}barman_server='{{repmgr_barman_server}}' # The barman configuration section 268 | {{ '' if repmgr_barman_host else '#' }}barman_host='{{repmgr_barman_host}}' # The host name of the barman server 269 | {{ '' if repmgr_barman_config else '#' }}barman_config='{{repmgr_barman_config}}' # The Barman configuration file on the 270 | # Barman server (needed if the file is 271 | # in a non-standard location) 272 | 273 | #------------------------------------------------------------------------------ 274 | # Failover and monitoring settings (repmgrd) 275 | #------------------------------------------------------------------------------ 276 | # 277 | # These settings are only applied when repmgrd is running. Values shown 278 | # are defaults. 279 | 280 | failover={{repmgr_failover}} # one of 'automatic', 'manual'. 281 | # determines what action to take in the event of upstream failure 282 | # 283 | # 'automatic': repmgrd will automatically attempt to promote the 284 | # node or follow the new upstream node 285 | # 'manual': repmgrd will take no action and the node will require 286 | # manual attention to reattach it to replication 287 | # (does not apply to BDR mode) 288 | 289 | priority={{repmgr_priority}} # indicate a preferred priority for promoting nodes; 290 | # a value of zero prevents the node being promoted to primary 291 | # (default: 100) 292 | connection_check_type={{repmgr_connection_check_type}} # How to check availability of the upstream node; valid options: 293 | # 'ping': use PQping() to check if the node is accepting connections 294 | # 'connection': execute a throwaway query on the current connection 295 | # 'query': execute an SQL statement on the node via the existing connection 296 | reconnect_attempts={{repmgr_reconnect_attempts}} # Number of attempts which will be made to reconnect to an unreachable 297 | # primary (or other upstream node) 298 | reconnect_interval={{repmgr_reconnect_interval}} # Interval between attempts to reconnect to an unreachable 299 | # primary (or other upstream node) 300 | {{ '' if repmgr_promote_command else '#' }}promote_command='{{repmgr_promote_command}}' # command repmgrd executes when promoting a new primary; use something like: 301 | # 302 | # repmgr standby promote -f /etc/repmgr.conf 303 | # 304 | {{ '' if repmgr_follow_command else '#' }}follow_command='{{repmgr_follow_command}}' # command repmgrd executes when instructing a standby to follow a new primary; 305 | # use something like: 306 | # 307 | # repmgr standby follow -f /etc/repmgr.conf -W --upstream-node-id=%n 308 | # 309 | primary_notification_timeout={{repmgr_primary_notification_timeout}} # Interval (in seconds) which repmgrd on a standby 310 | # will wait for a notification from the new primary, 311 | # before falling back to degraded monitoring 312 | repmgrd_standby_startup_timeout={{repmgr_repmgrd_standby_startup_timeout}} # Interval (in seconds) which repmgrd on a standby will wait 313 | # for the the local node to restart and become ready to accept connections after 314 | # executing "follow_command" (defaults to the value set in "standby_reconnect_timeout") 315 | 316 | monitoring_history={{repmgr_monitoring_history}} # Whether to write monitoring data to the "montoring_history" table 317 | monitor_interval_secs={{repmgr_monitor_interval_secs}} # Interval (in seconds) at which to write monitoring data 318 | degraded_monitoring_timeout={{repmgr_degraded_monitoring_timeout}} # Interval (in seconds) after which repmgrd will terminate if the 319 | # server being monitored is no longer available. -1 (default) 320 | # disables the timeout completely. 321 | async_query_timeout={{repmgr_async_query_timeout}} # Interval (in seconds) which repmgrd will wait before 322 | # cancelling an asynchronous query. 323 | {{ '' if repmgr_repmgrd_pid_file else '#' }}repmgrd_pid_file={{repmgr_repmgrd_pid_file}} # Path of PID file to use for repmgrd; if not set, a PID file will 324 | # be generated in a temporary directory specified by the environment 325 | # variable $TMPDIR, or if not set, in "/tmp". This value can be overridden 326 | # by the command line option "-p/--pid-file"; the command line option 327 | # "--no-pid-file" will force PID file creation to be skipped. 328 | standby_disconnect_on_failover={{repmgr_standby_disconnect_on_failover}} # If "true", in a failover situation wait for all standbys to 329 | # disconnect their WAL receivers before electing a new primary 330 | # (PostgreSQL 9.5 and later only; repmgr user must be a superuser for this) 331 | sibling_nodes_disconnect_timeout={{repmgr_sibling_nodes_disconnect_timeout}} # If "standby_disconnect_on_failover" is true, the maximum length of time 332 | # (in seconds) to wait for other standbys to confirm they have disconnected their 333 | # WAL receivers 334 | primary_visibility_consensus={{repmgr_primary_visibility_consensus}} # If "true", only continue with failover if no standbys have seen 335 | # the primary node recently. *Must* be the same on all nodes. 336 | always_promote={{repmgr_always_promote}} # Always promote a node, even if repmgr metadata is outdated 337 | {{ '' if repmgr_failover_validation_command else '#' }}failover_validation_command='{{repmgr_failover_validation_command}}' # Script to execute for an external mechanism to validate the failover 338 | # decision made by repmgrd. One or both of the following parameter placeholders 339 | # should be provided, which will be replaced by repmgrd with the appropriate 340 | # value: %n (node_id), %a (node_name). *Must* be the same on all nodes. 341 | election_rerun_interval={{repmgr_election_rerun_interval}} # if "failover_validation_command" is set, and the command returns 342 | # an error, pause the specified amount of seconds before rerunning the election. 343 | # 344 | # The following items are relevant for repmgrd running on the primary, 345 | # and will be ignored on non-primary nodes 346 | child_nodes_check_interval={{repmgr_child_nodes_check_interval}} # Interval (in seconds) to check for attached child nodes (standbys) 347 | child_nodes_connected_min_count={{repmgr_child_nodes_connected_min_count}} # Minimum number of child nodes which must remain connected, otherwise 348 | # disconnection command will be triggered 349 | child_nodes_disconnect_min_count={{repmgr_child_nodes_disconnect_min_count}} # Minimum number of disconnected child nodes required to execute disconnection command 350 | # (ignored if "child_nodes_connected_min_count" set) 351 | child_nodes_disconnect_timeout={{repmgr_child_nodes_disconnect_timeout}} # Interval between child node disconnection and disconnection command execution 352 | {{ '' if repmgr_child_nodes_disconnect_command else '#' }}={{repmgr_child_nodes_disconnect_command}} # Command to execute if child node disconnection detected 353 | 354 | #------------------------------------------------------------------------------ 355 | # service control commands 356 | #------------------------------------------------------------------------------ 357 | # 358 | # repmgr provides options to override the default pg_ctl commands 359 | # used to stop, start, restart, reload and promote the PostgreSQL cluster 360 | # 361 | # NOTE: These commands must be runnable on remote nodes as well for switchover 362 | # to function correctly. 363 | # 364 | # If you use sudo, the user repmgr runs as (usually 'postgres') must have 365 | # passwordless sudo access to execute the command. 366 | # 367 | # For example, to use systemd, you can set 368 | # 369 | # service_start_command = 'sudo systemctl start postgresql-9.6' 370 | # (...) 371 | # 372 | # and then use the following sudoers configuration: 373 | # 374 | # # this is required when running sudo over ssh without -t: 375 | # Defaults:postgres !requiretty 376 | # postgres ALL = NOPASSWD: /usr/bin/systemctl stop postgresql-9.6, \ 377 | # /usr/bin/systemctl start postgresql-9.6, \ 378 | # /usr/bin/systemctl restart postgresql-9.6 379 | # 380 | # Debian/Ubuntu users: use "sudo pg_ctlcluster" to execute service control commands. 381 | # 382 | # For more details, see: https://repmgr.org/docs/current/configuration-service-commands.html 383 | 384 | service_start_command ='{{ repmgr_service_start_command }}' 385 | service_stop_command ='{{ repmgr_service_stop_command }}' 386 | service_restart_command ='{{ repmgr_service_restart_command }}' 387 | service_reload_command ='{{ repmgr_service_reload_command }}' 388 | {{ '' if repmgr_service_promote_command else '#' }}service_promote_command ='{{ repmgr_service_promote_command }}' # This parameter is intended for systems which provide a 389 | # package-level promote command, such as Debian's 390 | # "pg_ctlcluster". *IMPORTANT*: it is *not* a substitute 391 | # for "promote_command"; do not use "repmgr standby promote" 392 | # (or a script which executes "repmgr standby promote") here. 393 | 394 | # Used by "repmgr service (start|stop)" to control repmgrd 395 | # 396 | repmgrd_service_start_command = '{{ repmgrd_service_start_command }}' 397 | repmgrd_service_stop_command = '{{ repmgrd_service_stop_command }}' 398 | 399 | #------------------------------------------------------------------------------ 400 | # Status check thresholds 401 | #------------------------------------------------------------------------------ 402 | 403 | # Various warning/critical thresholds used by "repmgr node check". 404 | 405 | archive_ready_warning={{repmgr_archive_ready_warning}} # repmgr node check --archive-ready 406 | archive_ready_critical={{repmgr_archive_ready_critical}} # 407 | # Numbers of files pending archiving via PostgreSQL's 408 | # "archive_command" configuration parameter. If 409 | # files can't be archived fast enough, or the archive 410 | # command is failing, the buildup of files can 411 | # cause various issues, such as server shutdown being 412 | # delayed until all files are archived, or excessive 413 | # space being occupied by unarchived files. 414 | # 415 | # Note that these values will be checked when executing 416 | # "repmgr standby switchover" to warn about potential 417 | # issues with shutting down the demotion candidate. 418 | 419 | replication_lag_warning={{repmgr_replication_lag_warning}} # repmgr node check --replication-lag 420 | replication_lag_critical={{repmgr_replication_lag_critical}} # 421 | # Note that these values will be checked when executing 422 | # "repmgr standby switchover" to warn about potential 423 | # issues with shutting down the demotion candidate. 424 | -------------------------------------------------------------------------------- /templates/repmgr.conf-5.3.j2: -------------------------------------------------------------------------------- 1 | # {{ ansible_managed }} 2 | ################################################### 3 | # repmgr sample configuration file 4 | ################################################### 5 | 6 | # Some configuration items will be set with a default value; this 7 | # is noted for each item. Where no default value is shown, the 8 | # parameter will be treated as empty or false. 9 | 10 | # ============================================================================= 11 | # Required configuration items 12 | # ============================================================================= 13 | # 14 | # repmgr and repmgrd require the following items to be explicitly configured. 15 | 16 | 17 | node_id='{{ repmgr_node_id if repmgr_node_id is defined else range(1, 65535) | random(seed=ansible_hostname) }}' # A unique integer greater than zero 18 | node_name='{{ansible_hostname}}' # An arbitrary (but unique) string; we recommend 19 | # using the server's hostname or another identifier 20 | # unambiguously associated with the server to avoid 21 | # confusion. Avoid choosing names which reflect the 22 | # node's current role, e.g. "primary" or "standby1", 23 | # as roles can change and it will be confusing if 24 | # the current primary is called "standby1". 25 | 26 | conninfo='{{repmgr_conninfo}}' # Database connection information as a conninfo string. 27 | # All servers in the cluster must be able to connect to 28 | # the local node using this string. 29 | # 30 | # For details on conninfo strings, see: 31 | # https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING 32 | # 33 | # If repmgrd is in use, consider explicitly setting 34 | # "connect_timeout" in the conninfo string to determine 35 | # the length of time which elapses before a network 36 | # connection attempt is abandoned; for details see: 37 | # https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNECT-CONNECT-TIMEOUT 38 | 39 | data_directory='{{repmgr_data_directory}}' # The node's data directory. This is needed by repmgr 40 | # when performing operations when the PostgreSQL instance 41 | # is not running and there's no other way of determining 42 | # the data directory. 43 | 44 | 45 | # ============================================================================= 46 | 47 | # Optional configuration items 48 | # ============================================================================= 49 | 50 | 51 | #------------------------------------------------------------------------------ 52 | # Server settings 53 | #------------------------------------------------------------------------------ 54 | 55 | config_directory='{{repmgr_config_directory}}' # If configuration files are located outside the data 56 | # directory, specify the directory where the main 57 | # postgresql.conf file is located. 58 | 59 | #------------------------------------------------------------------------------ 60 | # Replication settings 61 | #------------------------------------------------------------------------------ 62 | 63 | replication_user='{{repmgr_replication_user}}' # User to make replication connections with, if not set defaults 64 | # to the user defined in "conninfo". 65 | 66 | #replication_type='{{repmgr_replication_type}}' # Must be one of 'physical' or 'bdr'. 67 | 68 | location='{{repmgr_location}}' # arbitrary string defining the location of the node; this 69 | # is used during failover to check visibilty of the 70 | # current primary node. See the 'repmgrd' documentation 71 | # in README.md for further details. 72 | 73 | use_replication_slots='{{repmgr_use_replication_slots}}' # whether to use physical replication slots 74 | # NOTE: when using replication slots, 75 | # 'max_replication_slots' should be configured for 76 | # at least the number of standbys which will connect 77 | # to the primary. 78 | 79 | #------------------------------------------------------------------------------ 80 | # Witness server settings 81 | #------------------------------------------------------------------------------ 82 | 83 | witness_sync_interval={{repmgr_witness_sync_interval}} # interval (in seconds) to synchronise node records 84 | # to the witness server 85 | 86 | #------------------------------------------------------------------------------ 87 | # Logging settings 88 | #------------------------------------------------------------------------------ 89 | # 90 | # Note that logging facility settings will only apply to `repmgrd` by default; 91 | # `repmgr` will always write to STDERR unless the switch `--log-to-file` is 92 | # supplied, in which case it will log to the same destination as `repmgrd`. 93 | # This is mainly intended for those cases when `repmgr` is executed directly 94 | # by `repmgrd`. 95 | 96 | log_level={{repmgr_log_level}} # Log level: possible values are DEBUG, INFO, NOTICE, 97 | # WARNING, ERROR, ALERT, CRIT or EMERG 98 | 99 | log_facility={{repmgr_log_facility}} # Logging facility: possible values are STDERR, or for 100 | # syslog integration, one of LOCAL0, LOCAL1, ..., LOCAL7, USER 101 | 102 | {{ '' if repmgr_log_file else '#' }}log_file='{{repmgr_log_file}}' # STDERR can be redirected to an arbitrary file 103 | log_status_interval={{repmgr_log_status_interval}} # interval (in seconds) for repmgrd to log a status message 104 | 105 | 106 | #------------------------------------------------------------------------------ 107 | # Event notification settings 108 | #------------------------------------------------------------------------------ 109 | 110 | # event notifications can be passed to an arbitrary external program 111 | # together with the following parameters: 112 | # 113 | # %n - node ID 114 | # %e - event type 115 | # %s - success (1 or 0) 116 | # %t - timestamp 117 | # %d - details 118 | # 119 | # the values provided for "%t" and "%d" will probably contain spaces, 120 | # so should be quoted in the provided command configuration, e.g.: 121 | # 122 | # event_notification_command='/path/to/some/script %n %e %s "%t" "%d"' 123 | # 124 | # By default, all notifications will be passed; the notification types 125 | # can be filtered to explicitly named ones, e.g.: 126 | # 127 | # event_notifications=primary_register,standby_register 128 | 129 | {{ '' if repmgr_event_notification_command else '#' }}event_notification_command='{{repmgr_event_notification_command}}' # An external program or script which 130 | # can be executed by the user under which 131 | # repmgr/repmgrd are run. 132 | 133 | {{ '' if repmgr_event_notifications else '#' }}event_notifications='{{repmgr_event_notifications}}' # A commas-separated list of notification 134 | # types 135 | 136 | #------------------------------------------------------------------------------ 137 | # Environment/command settings 138 | #------------------------------------------------------------------------------ 139 | 140 | pg_bindir='{{repmgr_pg_bindir}}' # Path to PostgreSQL binary directory (location 141 | # of pg_ctl, pg_basebackup etc.). Only needed 142 | # if these files are not in the system $PATH. 143 | # 144 | # Debian/Ubuntu users: you will probably need to 145 | # set this to the directory where `pg_ctl` is located, 146 | # e.g. /usr/lib/postgresql/9.6/bin/ 147 | # 148 | # *NOTE* "pg_bindir" is only used when repmgr directly 149 | # executes PostgreSQL binaries; any user-defined scripts 150 | # *must* be specified with the full path 151 | 152 | repmgr_bindir='{{repmgr_repmgr_bindir}}' # Path to repmgr binary directory (location of the repmgr 153 | # binary. Only needed if the repmgr executable is not in 154 | # the system $PATH or the path defined in "pg_bindir". 155 | 156 | use_primary_conninfo_password={{repmgr_use_primary_conninfo_password}} # explicitly set "password" in recovery.conf's 157 | # "primary_conninfo" parameter using the value contained 158 | # in the environment variable PGPASSWORD 159 | passfile='{{ repmgr_passfile }}' # path to .pgpass file to include in "primary_conninfo" 160 | 161 | #------------------------------------------------------------------------------ 162 | # external command options 163 | #------------------------------------------------------------------------------ 164 | # 165 | # Options which can be passed to external commands invoked by repmgr/repmgrd. 166 | # 167 | # Examples: 168 | # 169 | # pg_ctl_options='-s' 170 | # pg_basebackup_options='--label=repmgr_backup' 171 | # rsync_options=--archive --checksum --compress --progress --rsh="ssh -o \"StrictHostKeyChecking no\"" 172 | # ssh_options=-o "StrictHostKeyChecking no" 173 | 174 | {{ '' if repmgr_pg_ctl_options else '#' }}pg_ctl_options='{{repmgr_pg_ctl_options}}' # Options to append to "pg_ctl" 175 | {{ '' if repmgr_pg_basebackup_options else '#' }}pg_basebackup_options='{{repmgr_pg_basebackup_options}}' # Options to append to "pg_basebackup" 176 | # (Note: when cloning from Barman, repmgr will honour any 177 | # --waldir/--xlogdir setting present in "pg_basebackup_options" 178 | {{ '' if repmgr_rsync_options else '#' }}rsync_options='{{repmgr_rsync_options}}' # Options to append to "rsync" 179 | ssh_options='{{repmgr_ssh_options}}' # Options to append to "ssh" 180 | 181 | 182 | 183 | #------------------------------------------------------------------------------ 184 | # "standby clone" settings 185 | #------------------------------------------------------------------------------ 186 | # 187 | # These settings apply when cloning a standby ("repmgr standby clone"). 188 | # 189 | # Examples: 190 | # 191 | # tablespace_mapping=/path/to/original/tablespace=/path/to/new/tablespace 192 | # restore_command = 'cp /path/to/archived/wals/%f %p' 193 | 194 | {{ '' if repmgr_tablespace_mapping else '#' }}tablespace_mapping='{{repmgr_tablespace_mapping}}' # Tablespaces can be remapped from one 195 | # file system location to another. This 196 | # parameter can be provided multiple times. 197 | 198 | {{ '' if repmgr_restore_command else '#' }}restore_command='{{repmgr_restore_command}}' # This will be placed in the recovery.conf file generated 199 | # by repmgr. 200 | 201 | {{ '' if repmgr_archive_cleanup_command else '#' }}archive_cleanup_command='{{repmgr_archive_cleanup_command}}' # This will be placed in the recovery.conf file generated 202 | # by repmgr. Note we recommend using Barman for managing 203 | # WAL archives (see: https://www.pgbarman.org ) 204 | 205 | {{ '' if repmgr_recovery_min_apply_delay else '#' }}recovery_min_apply_delay={{repmgr_recovery_min_apply_delay}} # If provided, "recovery_min_apply_delay" in recovery.conf 206 | # will be set to this value (PostgreSQL 9.4 and later). Value can be 207 | # an integer representing milliseconds, or a string 208 | # representing a period of time (e.g. '5 min'). 209 | 210 | #------------------------------------------------------------------------------ 211 | # "standby promote" settings 212 | #------------------------------------------------------------------------------ 213 | 214 | # These settings apply when instructing a standby to promote itself to the 215 | # new primary ("repmgr standby promote"). 216 | 217 | promote_check_timeout={{repmgr_promote_check_timeout}} # The length of time (in seconds) to wait 218 | # for the new primary to finish promoting 219 | promote_check_interval={{repmgr_promote_check_interval}} # The interval (in seconds) to check whether 220 | # the new primary has finished promoting 221 | 222 | 223 | #------------------------------------------------------------------------------ 224 | # "standby follow" settings 225 | #------------------------------------------------------------------------------ 226 | 227 | # These settings apply when instructing a standby to follow the new primary 228 | # ("repmgr standby follow"). 229 | 230 | primary_follow_timeout={{repmgr_primary_follow_timeout}} # The max length of time (in seconds) to wait 231 | # for the new primary to become available 232 | standby_follow_timeout={{repmgr_standby_follow_timeout}} # The max length of time (in seconds) to wait 233 | # for the standby to connect to the primary 234 | standby_follow_restart={{repmgr_standby_follow_restart}} # Restart the standby instead of sending a SIGHUP (only for PostgreSQL 13 and later) 235 | 236 | #------------------------------------------------------------------------------ 237 | # "standby switchover" settings 238 | #------------------------------------------------------------------------------ 239 | 240 | # These settings apply when switching roles between a primary and a standby 241 | # ("repmgr standby switchover"). 242 | 243 | shutdown_check_timeout={{repmgr_shutdown_check_timeout}} # The max length of time (in seconds) to wait for the demotion 244 | # candidate (current primary) to shut down 245 | standby_reconnect_timeout={{repmgr_standby_reconnect_timeout}} # The max length of time (in seconds) to wait 246 | # for the demoted standby to reconnect to the promoted 247 | # primary (note: this value should be equal to or greater 248 | # than that set for "node_rejoin_timeout") 249 | #wal_receive_check_timeout=30 # The max length of time (in seconds) to wait for the walreceiver 250 | # on the standby to flush WAL to disk before comparing location 251 | # with the shut-down primary 252 | 253 | #------------------------------------------------------------------------------ 254 | # "node rejoin" settings 255 | #------------------------------------------------------------------------------ 256 | 257 | # These settings apply when reintegrating a node into a replication cluster 258 | # with "repmgrd_node_rejoin" 259 | 260 | node_rejoin_timeout={{repmgr_node_rejoin_timeout}} # The maximum length of time (in seconds) to wait for 261 | # the node to reconnect to the replication cluster 262 | 263 | #------------------------------------------------------------------------------ 264 | # Barman options 265 | #------------------------------------------------------------------------------ 266 | 267 | {{ '' if repmgr_barman_server else '#' }}barman_server='{{repmgr_barman_server}}' # The barman configuration section 268 | {{ '' if repmgr_barman_host else '#' }}barman_host='{{repmgr_barman_host}}' # The host name of the barman server 269 | {{ '' if repmgr_barman_config else '#' }}barman_config='{{repmgr_barman_config}}' # The Barman configuration file on the 270 | # Barman server (needed if the file is 271 | # in a non-standard location) 272 | 273 | #------------------------------------------------------------------------------ 274 | # Failover and monitoring settings (repmgrd) 275 | #------------------------------------------------------------------------------ 276 | # 277 | # These settings are only applied when repmgrd is running. Values shown 278 | # are defaults. 279 | 280 | failover={{repmgr_failover}} # one of 'automatic', 'manual'. 281 | # determines what action to take in the event of upstream failure 282 | # 283 | # 'automatic': repmgrd will automatically attempt to promote the 284 | # node or follow the new upstream node 285 | # 'manual': repmgrd will take no action and the node will require 286 | # manual attention to reattach it to replication 287 | # (does not apply to BDR mode) 288 | 289 | priority={{repmgr_priority}} # indicate a preferred priority for promoting nodes; 290 | # a value of zero prevents the node being promoted to primary 291 | # (default: 100) 292 | connection_check_type={{repmgr_connection_check_type}} # How to check availability of the upstream node; valid options: 293 | # 'ping': use PQping() to check if the node is accepting connections 294 | # 'connection': attempt to make a new connection to the node 295 | # 'query': execute an SQL statement on the node via the existing connection 296 | reconnect_attempts={{repmgr_reconnect_attempts}} # Number of attempts which will be made to reconnect to an unreachable 297 | # primary (or other upstream node) 298 | reconnect_interval={{repmgr_reconnect_interval}} # Interval between attempts to reconnect to an unreachable 299 | # primary (or other upstream node) 300 | {{ '' if repmgr_promote_command else '#' }}promote_command='{{repmgr_promote_command}}' # command repmgrd executes when promoting a new primary; use something like: 301 | # 302 | # repmgr standby promote -f /etc/repmgr.conf 303 | # 304 | {{ '' if repmgr_follow_command else '#' }}follow_command='{{repmgr_follow_command}}' # command repmgrd executes when instructing a standby to follow a new primary; 305 | # use something like: 306 | # 307 | # repmgr standby follow -f /etc/repmgr.conf -W --upstream-node-id=%n 308 | # 309 | primary_notification_timeout={{repmgr_primary_notification_timeout}} # Interval (in seconds) which repmgrd on a standby 310 | # will wait for a notification from the new primary, 311 | # before falling back to degraded monitoring 312 | repmgrd_standby_startup_timeout={{repmgr_repmgrd_standby_startup_timeout}} # Interval (in seconds) which repmgrd on a standby will wait 313 | # for the the local node to restart and become ready to accept connections after 314 | # executing "follow_command" (defaults to the value set in "standby_reconnect_timeout") 315 | 316 | monitoring_history={{repmgr_monitoring_history}} # Whether to write monitoring data to the "monitoring_history" table 317 | monitor_interval_secs={{repmgr_monitor_interval_secs}} # Interval (in seconds) at which to write monitoring data 318 | degraded_monitoring_timeout={{repmgr_degraded_monitoring_timeout}} # Interval (in seconds) after which repmgrd will terminate if the 319 | # server being monitored is no longer available. -1 (default) 320 | # disables the timeout completely. 321 | async_query_timeout={{repmgr_async_query_timeout}} # Interval (in seconds) which repmgrd will wait before 322 | # cancelling an asynchronous query. 323 | {{ '' if repmgr_repmgrd_pid_file else '#' }}repmgrd_pid_file={{repmgr_repmgrd_pid_file}} # Path of PID file to use for repmgrd; if not set, a PID file will 324 | # be generated in a temporary directory specified by the environment 325 | # variable $TMPDIR, or if not set, in "/tmp". This value can be overridden 326 | # by the command line option "-p/--pid-file"; the command line option 327 | # "--no-pid-file" will force PID file creation to be skipped. 328 | repmgrd_exit_on_inactive_node={{repmgrd_exit_on_inactive_node}} # If "true", and the node record is marked as "inactive", abort repmgrd startup 329 | standby_disconnect_on_failover={{repmgr_standby_disconnect_on_failover}} # If "true", in a failover situation wait for all standbys to 330 | # disconnect their WAL receivers before electing a new primary 331 | # (PostgreSQL 9.5 and later only; repmgr user must be a superuser for this) 332 | sibling_nodes_disconnect_timeout={{repmgr_sibling_nodes_disconnect_timeout}} # If "standby_disconnect_on_failover" is true, the maximum length of time 333 | # (in seconds) to wait for other standbys to confirm they have disconnected their 334 | # WAL receivers 335 | primary_visibility_consensus={{repmgr_primary_visibility_consensus}} # If "true", only continue with failover if no standbys have seen 336 | # the primary node recently. *Must* be the same on all nodes. 337 | always_promote={{repmgr_always_promote}} # Always promote a node, even if repmgr metadata is outdated 338 | {{ '' if repmgr_failover_validation_command else '#' }}failover_validation_command='{{repmgr_failover_validation_command}}' # Script to execute for an external mechanism to validate the failover 339 | # decision made by repmgrd. One or both of the following parameter placeholders 340 | # should be provided, which will be replaced by repmgrd with the appropriate 341 | # value: %n (node_id), %a (node_name). *Must* be the same on all nodes. 342 | election_rerun_interval={{repmgr_election_rerun_interval}} # if "failover_validation_command" is set, and the command returns 343 | # an error, pause the specified amount of seconds before rerunning the election. 344 | # 345 | # The following items are relevant for repmgrd running on the primary, 346 | # and will be ignored on non-primary nodes 347 | child_nodes_check_interval={{repmgr_child_nodes_check_interval}} # Interval (in seconds) to check for attached child nodes (standbys) 348 | child_nodes_connected_min_count={{repmgr_child_nodes_connected_min_count}} # Minimum number of child nodes which must remain connected, otherwise 349 | # disconnection command will be triggered 350 | child_nodes_disconnect_min_count={{repmgr_child_nodes_disconnect_min_count}} # Minimum number of disconnected child nodes required to execute disconnection command 351 | # (ignored if "child_nodes_connected_min_count" set) 352 | child_nodes_disconnect_timeout={{repmgr_child_nodes_disconnect_timeout}} # Interval between child node disconnection and disconnection command execution 353 | {{ '' if repmgr_child_nodes_disconnect_command else '#' }}={{repmgr_child_nodes_disconnect_command}} # Command to execute if child node disconnection detected 354 | 355 | #------------------------------------------------------------------------------ 356 | # service control commands 357 | #------------------------------------------------------------------------------ 358 | # 359 | # repmgr provides options to override the default pg_ctl commands 360 | # used to stop, start, restart, reload and promote the PostgreSQL cluster 361 | # 362 | # NOTE: These commands must be runnable on remote nodes as well for switchover 363 | # to function correctly. 364 | # 365 | # If you use sudo, the user repmgr runs as (usually 'postgres') must have 366 | # passwordless sudo access to execute the command. 367 | # 368 | # For example, to use systemd, you can set 369 | # 370 | # service_start_command = 'sudo systemctl start postgresql-9.6' 371 | # (...) 372 | # 373 | # and then use the following sudoers configuration: 374 | # 375 | # # this is required when running sudo over ssh without -t: 376 | # Defaults:postgres !requiretty 377 | # postgres ALL = NOPASSWD: /usr/bin/systemctl stop postgresql-9.6, \ 378 | # /usr/bin/systemctl start postgresql-9.6, \ 379 | # /usr/bin/systemctl restart postgresql-9.6 380 | # 381 | # Debian/Ubuntu users: use "sudo pg_ctlcluster" to execute service control commands. 382 | # 383 | # For more details, see: https://repmgr.org/docs/current/configuration-service-commands.html 384 | 385 | service_start_command ='{{ repmgr_service_start_command }}' 386 | service_stop_command ='{{ repmgr_service_stop_command }}' 387 | service_restart_command ='{{ repmgr_service_restart_command }}' 388 | service_reload_command ='{{ repmgr_service_reload_command }}' 389 | {{ '' if repmgr_service_promote_command else '#' }}service_promote_command ='{{ repmgr_service_promote_command }}' # This parameter is intended for systems which provide a 390 | # package-level promote command, such as Debian's 391 | # "pg_ctlcluster". *IMPORTANT*: it is *not* a substitute 392 | # for "promote_command"; do not use "repmgr standby promote" 393 | # (or a script which executes "repmgr standby promote") here. 394 | 395 | # Used by "repmgr service (start|stop)" to control repmgrd 396 | # 397 | repmgrd_service_start_command = '{{ repmgrd_service_start_command }}' 398 | repmgrd_service_stop_command = '{{ repmgrd_service_stop_command }}' 399 | 400 | #------------------------------------------------------------------------------ 401 | # Status check thresholds 402 | #------------------------------------------------------------------------------ 403 | 404 | # Various warning/critical thresholds used by "repmgr node check". 405 | 406 | archive_ready_warning={{repmgr_archive_ready_warning}} # repmgr node check --archive-ready 407 | archive_ready_critical={{repmgr_archive_ready_critical}} # 408 | # Numbers of files pending archiving via PostgreSQL's 409 | # "archive_command" configuration parameter. If 410 | # files can't be archived fast enough, or the archive 411 | # command is failing, the buildup of files can 412 | # cause various issues, such as server shutdown being 413 | # delayed until all files are archived, or excessive 414 | # space being occupied by unarchived files. 415 | # 416 | # Note that these values will be checked when executing 417 | # "repmgr standby switchover" to warn about potential 418 | # issues with shutting down the demotion candidate. 419 | 420 | replication_lag_warning={{repmgr_replication_lag_warning}} # repmgr node check --replication-lag 421 | replication_lag_critical={{repmgr_replication_lag_critical}} # 422 | # Note that these values will be checked when executing 423 | # "repmgr standby switchover" to warn about potential 424 | # issues with shutting down the demotion candidate. 425 | --------------------------------------------------------------------------------