diff --git a/roles/postgresql/README.md b/roles/postgresql/README.md
new file mode 100644
index 0000000..6457931
--- /dev/null
+++ b/roles/postgresql/README.md
@@ -0,0 +1,37 @@
+# Role `postgresql`
+
+Ensures `postgresql` is installed by installing the distributions package.  
+Also ensures the optionally given databases and users are set up as specified.
+
+## Supported Distributions
+
+Should work on Debian-based distributions.
+
+## Required Arguments
+
+None.
+
+## Optional Arguments
+
+- `postgresql__dbs`: List of databases with their owner to ensure are set up.  
+- `postgresql__dbs.*.name`: Name of the database.
+- `postgresql__dbs.*.owner`: Owner of the database.
+- `postgresql__users`: List of users to ensure are set up.
+- `postgresql__users.*.name`: Name of the user.
+- `postgresql__users.*.password`: Optional password for the user.
+   If left unset, the user will have no password set, but can still connect using [peer authentication](https://www.postgresql.org/docs/current/auth-peer.html) on the local system.
+   (Peer authentication works when a password is set as well.)
+
+## Example Arguments
+
+```yaml
+postgresql__dbs:
+  - name: netbox
+    owner: netbox
+  - name: foo
+    owner: bar
+postgresql__users:
+  - name: netbox
+    password: super_secret
+  - name: bar
+```
diff --git a/roles/postgresql/defaults/main.yaml b/roles/postgresql/defaults/main.yaml
new file mode 100644
index 0000000..21fcd46
--- /dev/null
+++ b/roles/postgresql/defaults/main.yaml
@@ -0,0 +1,2 @@
+postgresql__dbs: [ ]
+postgresql__users: [ ]
diff --git a/roles/postgresql/meta/argument_specs.yaml b/roles/postgresql/meta/argument_specs.yaml
new file mode 100644
index 0000000..28e5813
--- /dev/null
+++ b/roles/postgresql/meta/argument_specs.yaml
@@ -0,0 +1,28 @@
+argument_specs:
+  main:
+    options:
+      postgresql__dbs:
+        type: list
+        elements: dict
+        required: false
+        default: [ ]
+        options:
+          name:
+            type: str
+            required: true
+          owner:
+            type: str
+            required: true
+      postgresql__users:
+        type: list
+        elements: dict
+        required: false
+        default: [ ]
+        options:
+          name:
+            type: str
+            required: true
+          password:
+            type: str
+            required: false
+            default: ""
diff --git a/roles/postgresql/tasks/main.yaml b/roles/postgresql/tasks/main.yaml
new file mode 100644
index 0000000..fc61857
--- /dev/null
+++ b/roles/postgresql/tasks/main.yaml
@@ -0,0 +1,28 @@
+- name: Ensure postgresql is installed
+  ansible.builtin.apt:
+    name:
+      - postgresql
+  become: true
+
+- name: Ensure Python library for community.postgresql is installed if needed
+  ansible.builtin.apt:
+    name:
+      - python3-psycopg
+  become: true
+  when: postgresql__dbs != [ ] or postgresql__users != [ ]
+
+- name: Ensure users
+  community.postgresql.postgresql_user:
+    name: "{{ item.name }}"
+    password: "{{ item.password | default('') }}"
+  become: true
+  become_user: postgres
+  loop: "{{ postgresql__users }}"
+
+- name: Ensure dbs with owners
+  community.postgresql.postgresql_db:
+    name: "{{ item.name }}"
+    owner: "{{ item.owner }}"
+  become: true
+  become_user: postgres
+  loop: "{{ postgresql__dbs }}"