User/Role
In this document, “user” refers to a logical object within a database cluster created with
CREATE USER/ROLE.
In PostgreSQL, users belong directly to the database cluster rather than a specific database. Therefore, when creating business databases and users, follow the principle of “users first, databases later”.
Pigsty defines roles and users through two config parameters:
pg_default_roles: Define globally shared roles and userspg_users: Define business users and roles at cluster level
The former defines roles/users shared across the entire environment; the latter defines business roles/users specific to a single cluster. Both have the same format as arrays of user definition objects. Users/roles are created sequentially in array order, so later users can belong to roles defined earlier.
By default, all users marked with pgbouncer: true are added to the Pgbouncer connection pool user list.
Define Users
Example from Pigsty demo pg-meta cluster:
Each user/role definition is a complex object. Only name is required:
User-level pool quota is consistently defined by
pool_connlimit(mapped to Pgbouncermax_user_connections).
Parameter Overview
The only required field is name - a valid, unique username within the cluster. All other params have sensible defaults.
| Field | Category | Type | Attr | Description |
|---|---|---|---|---|
name |
Basic | string |
Required | Username, must be valid and unique |
state |
Basic | enum |
Optional | State: create (default), absent |
password |
Basic | string |
Mutable | User password, plaintext or hash |
comment |
Basic | string |
Mutable | User comment |
login |
Privilege | bool |
Mutable | Can login, default true |
superuser |
Privilege | bool |
Mutable | Is superuser, default false |
createdb |
Privilege | bool |
Mutable | Can create databases, default false |
createrole |
Privilege | bool |
Mutable | Can create roles, default false |
inherit |
Privilege | bool |
Mutable | Inherit role privileges, default true |
replication |
Privilege | bool |
Mutable | Can replicate, default false |
bypassrls |
Privilege | bool |
Mutable | Bypass RLS, default false |
connlimit |
Privilege | int |
Mutable | Connection limit, -1 unlimited |
expire_in |
Validity | int |
Mutable | Expire N days from now (priority) |
expire_at |
Validity | string |
Mutable | Expiration date, YYYY-MM-DD format |
roles |
Role | array |
Additive | Roles array, string or object format |
parameters |
Params | object |
Mutable | Role-level parameters |
pgbouncer |
Pool | bool |
Mutable | Add to connection pool, default false |
pool_mode |
Pool | enum |
Mutable | Pool mode: transaction (default) |
pool_connlimit |
Pool | int |
Mutable | Pool user max connections |
Parameter Details
name
String, required. Username - must be unique within the cluster.
Must be a valid PostgreSQL identifier matching ^[a-z_][a-z0-9_]{0,62}$: starts with lowercase letter or underscore, contains only lowercase letters, digits, underscores, max 63 chars.
state
Enum for user operation: create or absent. Default create.
| State | Description |
|---|---|
create |
Default, create user, update if exists |
absent |
Delete user with DROP ROLE |
These system users cannot be deleted via state: absent (to prevent cluster failure):
postgres: Database superuserreplicator: Replication user (orpg_replication_username)dbuser_dba: Admin user (orpg_admin_username)dbuser_monitor: Monitor user (orpg_monitor_username)
password
String, mutable. User password - users without password can’t login via password auth.
Password can be:
| Format | Example | Description |
|---|---|---|
| Plaintext | DBUser.Meta |
Not recommended, logged to config |
| SCRAM-SHA-256 | SCRAM-SHA-256$4096:xxx$yyy:zzz |
Recommended, PG10+ default |
| MD5 hash | md5... |
Legacy compatibility |
When setting password, Pigsty temporarily disables logging to prevent leakage:
To generate SCRAM-SHA-256 hash:
comment
String, mutable. User comment, defaults to business user {name}.
Set via COMMENT ON ROLE, supports special chars (quotes auto-escaped).
login
Boolean, mutable. Can login, default true.
Setting false creates a Role rather than User - typically for permission grouping.
In PostgreSQL, CREATE USER equals CREATE ROLE ... LOGIN.
superuser
Boolean, mutable. Is superuser, default false.
Superusers have full database privileges, bypassing all permission checks.
Pigsty provides default superuser via pg_admin_username (dbuser_dba). Don’t create additional superusers unless necessary.
createdb
Boolean, mutable. Can create databases, default false.
Some applications (Gitea, Odoo, etc.) may require CREATEDB privilege for their admin users.
createrole
Boolean, mutable. Can create other roles, default false.
Users with CREATEROLE can create, modify, delete other non-superuser roles.
inherit
Boolean, mutable. Auto-inherit privileges from member roles, default true.
Setting false requires explicit SET ROLE to use member role privileges.
replication
Boolean, mutable. Can initiate streaming replication, default false.
Usually only replication users (replicator) need this. Normal users shouldn’t have it unless for logical decoding subscriptions.
bypassrls
Boolean, mutable. Bypass row-level security (RLS) policies, default false.
When enabled, user can access all rows even with RLS policies. Usually only for admins.
connlimit
Integer, mutable. Max concurrent connections, default -1 (unlimited).
Positive integer limits max simultaneous sessions for this user. Doesn’t affect superusers.
expire_in
Integer, mutable. Expire N days from current date.
This param has higher priority than expire_at. Expiration recalculated on each playbook run - good for temp users needing periodic renewal.
Generates SQL:
expire_at
String, mutable. Expiration date in YYYY-MM-DD format, or special value infinity.
Lower priority than expire_in. Use infinity for never-expiring users.
roles
Array, additive. Roles this user belongs to. Elements can be strings or objects.
Simple format - strings for role names:
Full format - objects for fine-grained control:
Object Format Parameters:
| Param | Type | Description |
|---|---|---|
name |
string | Role name (required) |
state |
enum | grant (default) or absent/revoke: control membership |
admin |
bool | true: WITH ADMIN OPTION, false: REVOKE ADMIN |
set |
bool | PG16+: true: WITH SET TRUE, false: REVOKE SET |
inherit |
bool | PG16+: true: WITH INHERIT TRUE, false: REVOKE INHERIT |
PostgreSQL 16+ New Features:
PostgreSQL 16 introduced finer-grained role membership control:
- ADMIN OPTION: Allow granting role to other users
- SET OPTION: Allow using
SET ROLEto switch to this role - INHERIT OPTION: Auto-inherit this role’s privileges
set and inherit options only work in PG16+. On earlier versions they’re ignored with warning comments.
parameters
Object, mutable. Role-level config params via ALTER ROLE ... SET. Applies to all sessions for this user.
Use special value DEFAULT (case-insensitive) to reset to PostgreSQL default:
Common role-level params:
| Parameter | Description | Example |
|---|---|---|
work_mem |
Query work memory | '64MB' |
statement_timeout |
Statement timeout | '30s' |
lock_timeout |
Lock wait timeout | '10s' |
idle_in_transaction_session_timeout |
Idle transaction timeout | '10min' |
search_path |
Schema search path | 'app,public' |
log_statement |
Log level | 'ddl' |
temp_file_limit |
Temp file size limit | '10GB' |
Query user-level params via pg_db_role_setting system view.
pgbouncer
Boolean, mutable. Add user to Pgbouncer user list, default false.
For prod users needing connection pool access, must explicitly set pgbouncer: true.
Default false prevents accidentally exposing internal users to the pool.
Users with pgbouncer: true are added to /etc/pgbouncer/userlist.txt.
pool_mode
Enum, mutable. User-level pool mode: transaction, session, or statement. Default transaction.
| Mode | Description | Use Case |
|---|---|---|
transaction |
Return connection after txn | Most OLTP apps, default |
session |
Return connection after session | Apps needing session state |
statement |
Return after each statement | Simple stateless queries |
User-level pool params are configured via /etc/pgbouncer/useropts.txt:
pool_connlimit
Integer, mutable. User-level maximum pool connections. If omitted, no user-level override is generated and Pigsty’s global pgbouncer.ini default of 100 applies. PgBouncer uses 0 to mean unlimited.
ACL System
Pigsty provides a built-in access control / ACL model. Assign these default business roles to users as required:
| Role | Privileges | Typical Use Case |
|---|---|---|
dbrole_readwrite |
Global read-write | Primary application accounts |
dbrole_readonly |
Global read-only | Read-only application access |
dbrole_admin |
DDL privileges | Application administrators and table creation |
dbrole_offline |
Independent read-only; instance scope controlled by HBA | Ad hoc users, ETL, and analytics |
dbrole_offline does not itself restrict a user to offline instances. To establish that boundary, set role: offline on the corresponding HBA rule; see Offline Role and Instance Isolation.
To redesign your own ACL system, customize:
pg_default_roles: System-wide roles and global userspg_default_privileges: Default privileges for new objectspg-init-roles.sql: Role creation SQL templatepg-init-template.sql: Privilege SQL template
Pgbouncer Users
Pgbouncer is enabled by default as connection pool middleware. Pigsty adds all users in pg_users with explicit pgbouncer: true flag to the pgbouncer user list.
Users in connection pool are listed in /etc/pgbouncer/userlist.txt:
User-level pool params are maintained in /etc/pgbouncer/useropts.txt:
When creating users, Pgbouncer user list is refreshed via online reload - doesn’t affect existing connections.
Pgbouncer runs as same dbsu as PostgreSQL (default postgres OS user). Use pgb alias to access pgbouncer admin functions.
pgbouncer_auth_query param allows dynamic query for pool user auth - convenient when you prefer not to manually manage pool users.
Related Resources
For user management operations, see User Management.
For user access privileges, see Access Control: Role System.