The main config file of Pigsty, Describe your entire deployment
This is the multi-page printable view of this section. .
Configuration
Pigsty treats Infra & Database as Code. You can describe everything with declarative config Inventory.
Which is usually an Ansible Inventory in YAML format: pigsty.yml.
But CMDB can also be used as dynamic inventory.
The configure procedure will generate a config according to your environment and input.
But it’s OPTIONAL: you can always edit the pigsty.yml file directly as tutorial shows.
And there are plenty of templates for your reference.
Generate config file according to your input & environment
Planning your deployment according to business requirements
Available configuration templates and examples
Security considerations and best practices for prod deployment
Use PostgreSQL as CMDB instead of local YAML config file
PostgreSQL Cluster with HA, PITR, IaC, ACL, Monitoring, Pooling
Nginx, Repo, DNS, NTP, Prometheus and Grafana stack for Observability
Enroll nodes into the desired state and monitor it, and VIP, HAProxy
Reliable distributed consensus storage (DCS), empowering PGSQL HA
S3 compatible object storage, optional backup storage
High-performance in-memory cache, optional data structure server
1 - Inventory
Each pigsty deployment has a corresponding config inventory.
It could be stored in a local config file in YAML format, or dynamically generated from CMDB or any ansible compatible format.
Pigsty uses one monolith YAML config file by default, which is pigsty.yml, located in the pigsty home directory.
pigsty/
The configure script will generate the pigsty.yml file scaffold with good defaults according to your env and input,
but it’s OPTIONAL: you can always edit the pigsty.yml file directly as the tutorial shows.
Structure
The inventory consists of two parts: global vars & multiple groups. You can define new clusters in all.children.
And describe infra with global vars: all.vars. Which may look like this:
There are plenty of examples under conf/, which can also be used as templates during configure.
Cluster
Each ansible group may represent a cluster, which could be a Node cluster, PostgreSQL cluster, Redis cluster, Etcd cluster, or Minio cluster, etc…
Cluster definition consists of two parts: hosts & vars.
You can define cluster members in <cls>.hosts and describe cluster with parameters in <cls>.vars.
Here’s an example of a 3-node HA PG cluster:
The vars in cluster level will override the global vars, and vars in host level will override the cluster vars and global vars.
Parameter
Parameters are key-value pairs that define all entities in the deployment. The key is a string name, and the value can be one of five types: boolean, string, number, array, or object.
And parameters can be set at different levels with the following precedence:
| Level | Location | Description | Precedence |
|---|---|---|---|
| CLI Args | Command Line | via -e cli param arg |
Highest (5) |
| Host Vars | <group>.hosts.<host> |
Parameters specific to a single host | High (4) |
| Group Vars | <group>.vars |
Parameters shared by hosts in a group/cluster | Medium (3) |
| Global Vars | all.vars |
Parameters shared by all hosts | Low (2) |
| Defaults | <roles>/default/main.yml |
Role implementation default values | Lowest (1) |
Here are some examples about parameter precedence:
- Override the PostgreSQL major version with Playbook CLI Args
-e pg_version=16 - Override pg instance role with Instance Level Parameter
pg_roleon Host Vars - Override pg cluster name with Cluster Level Parameter
pg_clusteron Group Vars. - Specify global NTP servers with Global Parameter
node_ntp_serverson Global Vars - If no
pg_versionis set, pigsty will use the default value from role implementation (18by default)
Every parameter has a proper default value except for mandatory IDENTITY PARAMETERS; they are used as identifiers and must be set explicitly.
Such as pg_cluster, pg_role, and pg_seq in above snippet.
Available parameters vary according to the modules:
Reference
Pigsty has 290+ parameters, check module parameters for details.
| Module | Section | Description | Count |
|---|---|---|---|
INFRA |
META |
Pigsty Metadata | 4 |
INFRA |
CA |
Self-Signed CA | 3 |
INFRA |
INFRA_ID |
Infra Portals & Identity | 2 |
INFRA |
REPO |
Local Software Repo | 9 |
INFRA |
INFRA_PACKAGE |
Infra Packages | 2 |
INFRA |
NGINX |
Nginx Web Server | 7 |
INFRA |
DNS |
DNSMASQ Nameserver | 3 |
INFRA |
PROMETHEUS |
Prometheus Stack | 18 |
INFRA |
GRAFANA |
Grafana Stack | 6 |
INFRA |
LOKI |
Loki Logging Service | 4 |
NODE |
NODE_ID |
Node Identity Parameters | 5 |
NODE |
NODE_DNS |
Node domain names & resolver | 6 |
NODE |
NODE_PACKAGE |
Node Repo & Packages | 5 |
NODE |
NODE_TUNE |
Node Tuning & Kernel features | 10 |
NODE |
NODE_ADMIN |
Admin User & Credentials | 7 |
NODE |
NODE_TIME |
Node Timezone, NTP, Crontabs | 5 |
NODE |
NODE_VIP |
Node Keepalived L2 VIP | 8 |
NODE |
HAPROXY |
HAProxy the load balancer | 10 |
NODE |
NODE_EXPORTER |
Node Monitoring Agent | 3 |
NODE |
PROMTAIL |
Promtail logging Agent | 4 |
DOCKER |
DOCKER |
Docker Daemon | 4 |
ETCD |
ETCD |
ETCD DCS Cluster | 10 |
MINIO |
MINIO |
MINIO S3 Object Storage | 15 |
REDIS |
REDIS |
Redis the key-value NoSQL cache | 20 |
PGSQL |
PG_ID |
PG Identity Parameters | 11 |
PGSQL |
PG_BUSINESS |
PG Business Object Definition | 12 |
PGSQL |
PG_INSTALL |
Install PG Packages & Extensions | 10 |
PGSQL |
PG_BOOTSTRAP |
Init HA PG Cluster with Patroni | 35 |
PGSQL |
PG_PROVISION |
Create in-database objects | 9 |
PGSQL |
PG_BACKUP |
Set Backup Repo with pgBackRest | 5 |
PGSQL |
PG_ACCESS |
Exposing service, bind vip, dns | 16 |
PGSQL |
PG_MONITOR |
Collect metrics & logs for Postgres | 18 |
PGSQL |
PG_EXPORTER |
Remove a Postgres cluster | 4 |
2 - Configure
The configure script will generate the pigsty.yml config file inventory with good defaults according to your environment and input.
It’s OPTIONAL, you can edit the pigsty.yml directly as the tutorial shows.
pigsty/
Usage
The configure script is an interactive wizard unless -n|--non-interactive is specified.
| Option | Description |
|---|---|
-c|--conf |
Generate config from config templates according to this parameter |
-i|--ip |
Replace IP address placeholder 10.10.10.10 with given IP |
-v|--version |
Specify PostgreSQL major version number (13|14|15|16|17|18) |
-r|--region |
Set upstream repo mirror according to region (default|china|europe) |
-o|--output |
Write the generated inventory to this file (pigsty.yml by default) |
-x|--proxy |
Write current proxy env to the config proxy_env |
-s|--skip |
Skip interactive wizard and using default/arg values |
-n|--non-interactive |
Non-interactively mode |
-p|--port |
Specify SSH port (only used if set) |
Example
configure output example:
Behavior
If -c|--conf <template> is specified, it will generate the config file from the specified template. Such as meta, app/supa, etc…
If no config template is given, it will use the default 1-node config template meta.
If -i|--ip <ipaddr> is specified, it will replace the placeholder 10.10.10.10 in the config template with the given IP address.
Otherwise, if the current node has only one IP address, it will be used. If there are multiple IP addresses, it will ask you to input the primary IP address of current node manually.
If -v|--version is specified, it will use the specified PostgreSQL major version number, range from 13 to 18.
If no version is specified, it leaves the pg_version intact, which usually fallbacks to 18 by default.
If -r|--region is specified, it will use the specified region directly. The china mirror will be used where Google services are not accessible.
If -x|--proxy is specified, it will write the current proxy environment variables to the config proxy_env.
Will be reused during installation. Including: HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, NO_PROXY.
If -s|--skip is specified, it will skip IP address replacement and ssh sudo privilege check
If -n|--non-interactive is specified, this script will not ask you for anything, but you have to specify a primary IP address with -i|--ip <ipaddr> explicitly.
If -p|--port is specified, it will use the specified SSH port instead of the default 22.
It is used when your local SSH port is not 22.
Pigsty will use C.UTF-8 as the default locale, If:
- PostgreSQL major version ≥ 17, with built-in local provider (default)
- OR, Your system supports
C.utf8/C.utf-8locale (locale -a)
Otherwise, local C will be used by default.
3 - Tutorial
Instead of using configure to generate config, you can write a pigsty config file from scratch manually.
Here is a tutorial to help you to build a complex config file inventory from scratch.
Minimal
This is a minimal working config example, you have to tell pigsty the IP of admin node and infra node.
This will install INFRA and NODE module on 10.10.10.10 (change to your IP address).
You’ll have a complete observability stack with node monitoring. But database service is not running yet.
PGSQL & ETCD
To provide PostgreSQL service, you have to define additional groups and install PGSQL & ETCD modules.
We add two new groups here: etcd and pg-meta, which defines an 1-node ETCD cluster and a 1-node PGSQL cluster.
Recreate everything with ./install.yml, or using these cmd to do incremental steps:
The PGSQL module depends on ETCD for HA consensus, so make sure to install ETCD module first.
Database & Users
Now we want to customize our postgres database cluster, with users, database, and backups:
We define some additional details at the pg-meta cluster level:
pg_users: define a new userdbuser_metawith passwordDBUser.Metapg_databases: define a new databasemetawith pigsty CMDB schema andvectorextensionnode_crontab: define crontab that takes a full backup at 1 am every day
Instead of recreating everything with ./install.yml, we make changes incrementally:
PG VER & Extensions
You can install different major versions of PostgreSQL, and 437+ corresponding extensions.
Let’s install PostgreSQL 16 (instead of default 18) with timescaledb, postgis, and pgvector extensions.
repo_extra_packages: downloadtimescaledbandpostgisextensions.pg_libs: preloadtimescaledb,pg_stat_statements,auto_explainextensions.
Let’s redownload missing packages (PG 16 kernel & extensions), remove the old cluster, and recreate it:
More NODE
We can add 3 more nodes to this deployment.
Or add them one by one:
PGSQL HA
Now we want to add a new database cluster pg-test, with 3-node HA setup:
Pigsty’s working assumption is there’s only ONE postgres instance on each node. There’s no support to run multiple postgres instances on a single node.
Redis Up
Pigsty has optional Redis support, which is used as a cache in front of PostgreSQL.
Redis HA setup requires cluster mode, or sentinel infra, check Redis Config for details.
MinIO Up
Pigsty has optional MinIO support, which is used as a backup storage for PostgreSQL.
Serious production MinIO deployment usually requires at least 4 nodes with 4 disks each (4N/16D)
Docker Up
Install docker on the infra group:
Run PgAdmin
Check the App: Pgadmin for details on how to run pgAdmin with Pigsty. Short version:
Self-Hosting Supabase
Check the App: Supabase for details on how to run Supabase with Pigsty. Short version:
4 - Template
This directory conf contains pigsty config templates, which will be used during configure procedure.
Config templates can be designated using ./configure -c <conf>, where the conf is a relative path to conf directory (with or without .yml suffix).
e.g. the ~/pigsty/conf/rich.yml can be specified as rich
If no -c|--conf is given, the single-node meta config template will be automatically selected by default.
Basic Templates
Here are one-node templates, which provide different features and configurations.
| Template | Node | Description |
|---|---|---|
meta.yml |
1 | Default 1-node config, pgsql, infra, node, etcd, minimal ext |
rich.yml |
1 | meta + minio + all extensions |
slim.yml |
1 | meta - infra - node monitor, minimal install |
fat.yml |
1 | PG 13-18 packages, and install all extensions for current ver |
Exotic Kernel
Using exotic Postgres kernel forks:
| Template | Node | Description |
|---|---|---|
mssql.yml |
1 | WiltonDB & Babelfish with MSSQL wire-compatibility |
polar.yml |
1 | PolarDB for PostgreSQL with Aurora RAC Flavor |
ivory.yml |
1 | IvorySQL cluster with Oracle compatibility |
mysql.yml |
1 | Halo cluster with MySQL wire-compatibility |
mongo.yml |
1 | FerretDB & DocumentDB with Mongo wire-compatibility |
oriole.yml |
1 | OrioleDB cluster with OLTP enhancement |
Multi Node
| Template | Node | Description |
|---|---|---|
dual.yml |
2 | Semi-HA deployment |
trio.yml |
3 | Standard HA deployment |
full.yml |
4 | Sandbox deployment |
safe.yml |
4 | Security enhancement with delayed replica |
simu.yml |
36 | Production simulation |
Applications
| Template | Description |
|---|---|
app/supa.yml |
Launch 1-node supabase |
app/odoo.yml |
Launch the odoo ERP system |
app/dify.yml |
Launch the dify AI workflow system |
app/electric.yml |
Launch the electric sync engine app |
Demo Templates
| Template | Description |
|---|---|
demo/el.yml |
Config file with all default parameters for EL 8/9/10 systems |
demo/debian.yml |
Config file with all default parameters for debian/ubuntu systems |
demo/remote.yml |
Example config for monitoring a remote pgsql cluster or RDS PG |
demo/redis.yml |
Example config for redis clusters |
demo/minio.yml |
Example config for a 3-node minio clusters |
demo/demo.yml |
Config file for the pigsty public demo |
citus.yml |
Citus cluster example: 1 coordinator and 3 data nodes (4-node) |
Build Templates
| Template | Description |
|---|---|
build/oss.yml |
Building config for EL 8, 9, Debian 12, and Ubuntu 22.04/24.04 OSS |
build/pro.yml |
Building config for EL 7-10, Ubuntu, Debian pro version |
5 - Security
Pigsty already provides a secure-by-default database authentication and access control model.
It is strong enough for most common scenarios, as long as you follow the security best-practices below.
Confidentiality
Files
pigsty.ymlhold very sensitive information like passwords- Limit access to admin/infra nodes to admin/DBA users only
- Limit access to repo, if you are managing pigsty config with GitOps
- Generated at
~/pigsty/files/pki/ca/ca.keyby default - Secure & backup it in a safe place, DON’T THROW IT AWAY!
- Also consider secure other private keys for various certs
Passwords
Always change these default passwords in serious deployment
grafana_admin_password:pigstypg_admin_password:DBUser.DBApg_monitor_password:DBUser.Monitorpg_replication_password:DBUser.Replicatorpatroni_password:Patroni.APIhaproxy_admin_password:pigstyminio_secret_key:minioadmin
If you are using MinIO as backup storage, also change these credentials:
- Change the password for
minio_users.[pgbackrest].secret_key - Change pgbackrest references:
pgbackrest_repo.minio.s3_key_secret
- add
$lib/passwordchecktopg_libsto enforce password policy. - stronger version:
passwordcheck_cracklib
- check
pgbackrest_repodefinitionrepo_cipher_type cipher_type: aes-256-cbcby default
- use
pg_pwd_encdefaultscram-sha-256instead of legacymd5 - default behavior is
scram-sha-256,md5is deprecated
You can set an expiry date for each user for compliance purposes.
Don’t forget to refresh these expiry dates periodically with pgsql-user.yml playbook
IP Addresses
- The default
pg_listenaddress is0.0.0.0, which is all IPv4 addresses. - Consider using
pg_listen: '${ip},${vip},${lo}'to bind to specific addresses for better security.
- Grafana/Prometheus are bind to all IP address by default for convenience.
- You can modify their bind configuration to listen on localhost/intranet IP and expose by Nginx.
- Redis server are bind to all IP address by default for convenience. You can change
redis_bind_addressto listen on intranet IP. - You can also implement it with the security group or firewall rules.
- There’s a security enhance config template:
safe.yml
- This is restricted by default with
restapi.allowlist
Network Traffic
- Nginx SSL is controlled by
nginx_sslmode, which isenableby default. - Nginx Domain names are specified by
infra_portal..domain.
patroni_ssl_enabledis disabled by default- Since it affects health checks and API invocation.
- Note this is a global option, and you have to decide before deployment.
pgbouncer_sslmodeisdisableby default- Since it has a significant performance impact.
Integrity
Consistency
- Use
crit.ymltemplates forpg_confwill trade some availability for the best consistency.
-
set
node_tunetocritto reduce dirty page ratio. -
Enable data checksum to detect silent data corruption.
-
pg_checksumis enabled by default in v3.7.0 -
This can be enabled later, which requires a full cluster scan/stop.
Audit
- Enable
log_connectionsandlog_disconnectionsafter the pg cluster bootstrap. - Audit incoming sessions; this is enabled in
crit.ymlby default.
Fat Finger
Running install.yml again will nuke (overwrite) the entire deployment!
It will OVERWRITE existing PostgreSQL by default before v3.5.
Use pg_safeguard to avoid fat fingers
Availability
Redundancy
- You need at least three nodes (tolerate one node failure) to achieve production-grade high availability.
- If you only have two nodes, you can tolerate the failure of the specific standby node.
- If you have one node, use an external S3/MinIO for cold backup & wal archive storage.
- Use multiple infra nodes in serious production deployment (e.g., 1~3)
- Usually, 2 ~ 3 is enough for a large production deployment.
- Use enough etcd members and use odd numbers (1,3,5,7).
- Check ETCD Configuration for details.
Fault Tolerance
Access
- Do not access the database directly via a fixed IP address; use VIP, DNS, HAProxy, or their combination.
- Haproxy will handle the traffic control for the clients in case of failover/switchover.
6 - CMDB
Pigsty allows you to use a database (CMDB) as a dynamic configuration source instead of a static configuration file. You can use the built-in PostgreSQL as config inventory for config management.
With Postgres CMDB, configuration is organized in structured relational tables, which can be easily queried and manipulated using SQL. This allows for easier integration with other systems and tools.
How does it work?
Ansible allows you to use a dynamic inventory script to generate the inventory config on-the-fly.
The idea is to replace static pigsty.yml in ansible.cfg with a dynamic shell script inventory.sh
The content of inventory.sh is very simple, it will query the PostgreSQL CMDB and retrieve config.
bin/inventory_load: Loads YAML config file into the CMDBbin/inventory_cmdb: Use CMDB as config inventory (meta.pigsty)bin/inventory_conf: Use YAML file as config inventory (pigsty.yml)
CMDB Schema
The CMDB baseline schema is shipped with pigsty: files/cmdb.sql
And most of the default config templates will use it as example baseline. Which means it can be used by default.
Load Config Data
CMDB is empty by default, load config file into the CMDB with the bin/inventory_load script.
Run bin/inventory_load without arguments will load the default pigsty.yml into the default CMDB.
Use -p to specify the config file path, and -d to specify the CMDB URL.
Switch Inventory
You can switch to dynamic CMDB inventory with:
Which essentially changes the inventory parameter in the ansible.cfg to use the inventory.sh script.