43

I am running PostgreSQL 9.3 on FreeBSD. FreeBSD uses pgsql as the default system user for PostgreSQL. My /usr/local/pgsql/data/pg_hba.conf looks like this:

# TYPE  DATABASE        USER            ADDRESS                 METHOD
local   all             pgsql                                   peer
local   all             all                                     md5
host    all             all             127.0.0.1/32            md5
host    all             all             ::1/128                 md5

With this configuration I can connect to the database as pgsql without a password.

$ su pgsql
$ psql template1
template1=# \l
                         List of databases
...

That works as intended.

On a remote machine, I have an Ansible task to create a database on the FreeBSD server.

- name: Create the postgresql database
  postgresql_db: name=mydatabase login_user=pgsql

Executing this task fails with the error Peer authentication failed for user "pgsql".

PLAY [web] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [host.example.org]

TASK: [database | Create the postgresql database] *****************************
failed: [host.example.org] => {"failed": true}
msg: unable to connect to database: FATAL:  Peer authentication failed for user "pgsql"


FATAL: all hosts have already failed -- aborting

Why does this fail when peer authentication for the user pgsql is clearly working?

oakservice
  • 521
  • 1
  • 5
  • 5

10 Answers10

66

This worked for me:

- name: Create postgres database
  become: true
  become_user: postgres
  postgresql_db:
    name: <database-name>

In your specific case the user might be pgsql, but I think usually the user is postgres.

Nathan Smith
  • 683
  • 1
  • 10
  • 24
gitaarik
  • 42,736
  • 12
  • 98
  • 105
23

Or with slightly different syntax (from Ansible 1.9) and for user creation (might be helpful for someone)

- name: Create postgres user
  postgresql_user: name={{ pg_user }} password={{ pg_password }}
  become: true
  become_user: postgres
Most Wanted
  • 6,254
  • 5
  • 53
  • 70
19

For those running into "Failed to set permissions on the temporary files Ansible needs to create..." in order to switch to the postgres user with become_user you can leverage pipelining on Ubuntu hosts.

Create a ansible.cfg in your playbook directory and add the following lines:

[ssh_connection]
pipelining=True

Update: according to @lolcode Ansible 2.9.0 has updated to ansible_pipelining

   [ssh_connection]
   ansible_pipelining = true

Update 4/30/2020: for those who still have issues, try installing acl which will cause Ansible to use this acl filesystem to mount module that need to be accessible by the 2nd user instead of making them readable by everyone. Thanks @Andreas Florath

- name: install setfacl support
  become: yes
  apt: pkg=acl
Dylan Pierce
  • 4,313
  • 3
  • 35
  • 45
  • 2
    Thanks for saving hours of my life :) – Amir Rustamzadeh Nov 05 '16 at 05:40
  • 2
    No problem! Countless others have done the same for me. Pass it forward. – Dylan Pierce Nov 29 '16 at 14:54
  • 1
    The pipelining = True answer worked for me but on ansible 2.9.0 the format has changed to `ansible_pipelining = true` as per [this ansible issue][1] [1]: https://github.com/ansible/ansible/issues/31125#issuecomment-333847610 – lolcode Nov 20 '19 at 21:25
  • 2
    This did not work for me. I needed to install the acl tools as described: https://stackoverflow.com/questions/36646880/ansible-2-1-0-using-become-become-user-fails-to-set-permissions-on-temp-file/36681626 – Andreas Florath Apr 10 '20 at 19:34
  • 1
    @DylanPierce Note that you spelled `ansible_pipelining` a bit wrong in your edit (you wrote `piplining`). – Haakon Jun 14 '20 at 20:59
  • Thank you so much for the 2020 update. I have no idea about postgresql and stuff, just trying to cobble something together. Without the hint about `acl` I feel like this would have become a very, very long search... so, much <3 – Peter Nerlich May 29 '21 at 14:47
5

I had the same problem. In my case I overlooked that I configured my Ansible-playbook to run as another Linux user than the one with peer access (pgsql in your case). Solution is either run the Ansible play as pgsql:

- name: Create the postgresql database
  remote_user: pgsql
  postgresql_db: name=mydatabase login_user=pgsql
  ...

Or run it as root, and su to pgsql for the command:

- name: Create the postgresql database
  remote_user: root
  become: yes
  become_user: pgsql
  postgresql_db: name=mydatabase login_user=pgsql
  ...

... depending on your access rights via ssh.

This is using Ansible 2.0.

René Pijl
  • 4,310
  • 1
  • 19
  • 25
4

Another workaround is to connect via host (localhost) rather than the default local peer authentication method:

- name: Create the postgresql database
  postgresql_db:
    name: mydatabase
    login_user: postgres
    login_host: 127.0.0.1

Depending on the settings in pg_hba.conf, you may also need to provide login_password. You can circumvent this by setting

host    all         postgres        127.0.0.1/32            md5

to

host    all         postgres        127.0.0.1/32            trust
mdh
  • 5,355
  • 5
  • 26
  • 33
  • You helped me indirectly. I was using login_host: "{{ item.login_host | default('localhost') }}". Switching to default('omit') solved my issue. – frostymarvelous Apr 19 '17 at 17:35
1

I notice your Postgres version is really out of date (9.3). I had this issue recently when working on an Ubuntu 14 server with Postgres 9.3.

I tried a dozen different things, and finally what worked was installing the acl package via apt. Ansible uses it for navigating some of it's permissions issues. The package is installed by default on newer distros, hence why I've only seen this problem crop up on an old server.

bugged
  • 63
  • 1
  • 7
0

Thanks to this threat I made a variant of mdh's post. When I set up a database I generate a password for the postgres user and I store it in a file under the root directory.

I thought why not store it also (or instead) in a .pgpass file for root. So I created a template like this (only last line is important):

#### password file for posgres connection ###

#### *:*:*:*
#### works like
####    *      :      *    :     *     :     *
#### <ip addr> : <port nr> : <db name> : <password>

127.0.0.1:*:*:postgres:{{ new_postgres_pass }}

Store the .pgpass file in the home directory of root. Now you can use the module as root without switching user of having to change the pg_hba.conf:

- name: Ensure postgresql mydatabase
  postgresql_db:
    name: mydatabase
    login_user: postgres
    login_host: 127.0.0.1
Rooie3000
  • 459
  • 5
  • 9
0

If you don't have sudo (debian, etc) but have access to root

- name: Create database
  remote_user: root
  become: yes
  become_method: su
  become_user: postgres
  postgresql_db:
    name: my_db
Léo Benoist
  • 2,511
  • 1
  • 20
  • 18
0

This problem due to postgres authentication methods configured at /etc/postgresql/10/main/pg_hba.conf , the configuration location may vary depending on the version installed, /etc/postgresql//main/pg_hba.conf

sample ansible recipe
---
- name : "Dump PostgreSQL database"
  gather_facts: true
  hosts: posgre_host
  tasks:
    - name: Dump existing PostgreSQL database
      community.postgresql.postgresql_db:
        name: demo
        state: dump
        target: /tmp/backup/backup.sql.gz
      become: true

From

local           all           postgres           peer

To

local           all             postgres        trust

Here trust authentication method anyone connect to the server is authorized to access the database, since ansible is working based on ssh, it is safe to change.

Srijeyanthan
  • 126
  • 1
  • 2
-4

So if I understood well you are on a remote machine, and maybe you should change /usr/local/pgsql/data/pg_hba.conf to allow remote connections 'host all all 0.0.0.0/0 md5' or another specific network address.

Laurent B
  • 81
  • 1
  • 5