This is the multi-page printable view of this section. .
Administration
- 1: Nginx Management
- 2: Software Repository
- 3: Domain Management
- 4: Module Management
- 5: CA and Certificates
- 6: Grafana High Availability: Using PostgreSQL Backend
This section covers daily administration and operations for Pigsty deployments.
1 - Nginx Management
Pigsty installs Nginx on INFRA nodes as the entry point for all web services, listening on standard ports 80/443.
In Pigsty, you can configure Nginx to provide various services through inventory:
- Expose web interfaces for monitoring components like Grafana, VictoriaMetrics (VMUI), Alertmanager, and VictoriaLogs
- Serve static files (software repos, documentation sites, websites, etc.)
- Proxy custom application services (internal apps, database management UIs, Docker application interfaces, etc.)
- Automatically issue self-signed HTTPS certificates, or use Certbot to obtain free Let’s Encrypt certificates
- Expose services through a single port using different subdomains for unified access
Basic Configuration
Customize Nginx behavior via infra_portal parameter:
infra_portal is a dictionary where each key defines a service and the value is the service configuration.
Only services with a domain defined will generate corresponding Nginx config files.
home: Special default server for homepage and built-in monitoring component reverse proxies- Proxy services: Specify upstream service address via
endpointfor reverse proxy - Static services: Specify local directory via
pathfor static file serving
Server Parameters
Basic Parameters
| Parameter | Description |
|---|---|
domain |
Optional proxy domain |
endpoint |
Upstream service address (IP:PORT or socket) |
path |
Local directory for static content |
scheme |
Protocol type (http/https), default http |
domains |
Additional domain list (aliases) |
SSL/TLS Options
| Parameter | Description |
|---|---|
certbot |
Enable Let’s Encrypt cert management, value is cert name |
cert |
Custom certificate file path |
key |
Custom private key file path |
enforce_https |
Force HTTPS redirect (301) |
Advanced Settings
| Parameter | Description |
|---|---|
config |
Custom Nginx config snippet |
index |
Enable directory listing (for static) |
log |
Custom log file name |
websocket |
Enable WebSocket support |
auth |
Enable Basic Auth |
realm |
Basic Auth prompt message |
Configuration Examples
Reverse Proxy Services
Static Files and Directory Listing
Custom SSL Certificate
Using Let’s Encrypt Certificates
Force HTTPS Redirect
Custom Config Snippet
Management Commands
Domain Resolution
Three ways to resolve domains to Pigsty servers:
- Public domains: Configure via DNS provider
- Internal DNS server: Configure internal DNS resolution
- Local hosts file: Modify
/etc/hosts
For local development, add to /etc/hosts:
Pigsty includes dnsmasq service, configurable via dns_records parameter for internal DNS resolution.
HTTPS Configuration
Configure HTTPS via nginx_sslmode parameter:
| Mode | Description |
|---|---|
disable |
Listen HTTP only (nginx_port) |
enable |
Also listen HTTPS (nginx_ssl_port), default self-signed cert |
enforce |
Force redirect to HTTPS, all port 80 requests get 301 redirect |
For self-signed certificates, several access options:
- Trust the self-signed CA in browser (download at
http://<ip>/ca.crt) - Use browser security bypass (type “thisisunsafe” in Chrome)
- Configure proper CA-signed certs or Let’s Encrypt for production
Certbot Certificates
Pigsty supports using Certbot to request free Let’s Encrypt certificates.
Enable Certbot
- Add
certbotparameter to services ininfra_portal, specifying cert name - Configure
certbot_emailwith a valid email - Set
certbot_signtotruefor auto-signing during deployment
Manual Certificate Signing
Or run the scripts directly on the server:
For more info, see Certbot: Request and Renew HTTPS Certificates
Default Homepage
Pigsty’s default home server provides these built-in routes:
| Path | Description |
|---|---|
/ |
Homepage navigation |
/ui/ |
Grafana monitoring dashboards |
/vmetrics/ |
VictoriaMetrics VMUI |
/vlogs/ |
VictoriaLogs log query |
/vtraces/ |
VictoriaTraces tracing |
/vmalert/ |
VMAlert alerting rules |
/alertmgr/ |
AlertManager alert management |
/blackbox/ |
Blackbox Exporter |
/pev |
PostgreSQL Explain visualization |
/haproxy/<cluster>/ |
HAProxy admin interface (if any) |
These routes allow accessing all monitoring components through a single entry point, no need for multiple domain configurations.
Best Practices
- Use domain names instead of IP:PORT for service access
- Properly configure DNS resolution or hosts file
- Enable WebSocket for real-time apps (e.g., Grafana, Jupyter)
- Enable HTTPS for production
- Use meaningful subdomains to organize services
- Monitor Let’s Encrypt certificate expiration
- Use
configparameter for custom Nginx configurations
Full Example
Here’s the Nginx configuration used by Pigsty’s public demo site demo.pigsty.io:
2 - Software Repository
Pigsty’s REPO role downloads required packages and creates a local YUM/APT repository under /www/pigsty that Nginx can serve. The current package candidate is SOW 0.3.0; the source uses SOW to generate metadata for both repository types instead of calling createrepo_c, modifyrepo_c, or dpkg-scanpackages separately.
Quick Start
Add packages to repo_packages or repo_extra_packages, then run:
If /www/pigsty/repo_complete already exists, the default repo_build skips the build. To force a rebuild, override it explicitly:
To rebuild metadata for packages already present without downloading new ones:
SOW Prerequisites
Both repo_create and cache_create require sow on the target node. A fresh online build automatically adds infra to the effective repo_modules list and installs SOW from the Pigsty INFRA upstream repository.
Offline bundles and local repositories created before this change may not contain SOW. Before rebuilding from old media, refresh the bundle/local repository or install the current SOW 0.3.0 candidate from the Pigsty INFRA repository. Do not assume that older environments can still fall back to createrepo_c.
On a fresh installation, if /www does not exist, the role creates /data/nginx and makes /www point to it. Existing directories and symlinks are preserved rather than forcibly replaced.
Build Flow
| Task | Purpose |
|---|---|
repo_check |
Check repo_complete to determine whether the local repository is complete |
repo_prepare |
Configure and use an existing repository |
repo_dir |
Create /www/pigsty and ACME directories |
repo_upstream |
Back up and add upstream YUM or APT definitions |
repo_url_pkg |
Download packages from direct URLs |
repo_cache |
Run yum makecache or apt update |
repo_boot_pkg |
Install sow and the RPM platform’s dnf-utils / yum-utils |
repo_pkg |
Download packages and dependencies |
repo_create |
Run SOW to clean and atomically publish repository metadata |
repo_use |
Write the local Pigsty repository definition on the current host |
repo_nginx |
Start a temporary Nginx when no service is already running |
The command executed by repo_create is:
--pigsty removes unneeded or conflict-prone packages and atomically publishes the result only after all metadata has been generated. A typical layout is:
Do not treat repo_complete as an empty sentinel; it contains SHA-256 checksums. Its presence means SOW completed publication of local repository metadata. It does not prove that remote mirrors, signed repositories, or offline bundles have been synchronized.
DNF Module Streams
Pigsty no longer fabricates modules.yaml / ModuleMD metadata for the aggregated local repository. System upstream repositories retain native DNF module filtering. Only an upstream repository that truly needs to replace an EL module stream should set meta explicitly:
The aggregated Pigsty local repository itself is configured with module_hotfixes=1 so local PostgreSQL packages are not hidden by system module streams. This is distinct from generating fake ModuleMD metadata.
Package Aliases
The default repo_packages uses these alias groups:
node-bootstrap includes Ansible, Python dependencies, SOW, and SSH tools. infra-package includes Nginx, etcd, HAProxy, Victoria exporters, Redis/Valkey, Silo, mcli, SOW, and Pig. Exact names vary by OS mapping; always use roles/node_id/vars/<os>.<arch>.yml as the authority.
Common Commands
3 - Domain Management
Use domain names instead of IP addresses to access Pigsty’s various web services.
Quick Start
Add the following static resolution records to /etc/hosts:
Replace IP address with your actual Pigsty node’s IP.
Why Use Domain Names
- Easier to remember than IP addresses
- Flexible pointing to different IPs
- Unified service management through Nginx
- Support for HTTPS encryption
- Prevent ISP hijacking in some regions
- Allow access to internally bound services via proxy
DNS Mechanism
DNS Protocol: Resolves domain names to IP addresses. Multiple domains can point to same IP.
HTTP Protocol: Uses Host header to route requests to different sites on same port (80/443).
Default Domains
Pigsty predefines the following default domains:
| Domain | Service | Port | Purpose |
|---|---|---|---|
i.pigsty |
Nginx | 80/443 | Default homepage, local repo, unified entry |
m.pigsty |
Silo | 9001 | Object storage console |
Grafana, VictoriaMetrics, and Alertmanager are accessed by default through the /ui/, /vmetrics/, and /alertmgr/ subpaths under i.pigsty. To use dedicated domains such as g.pigsty, p.pigsty, and a.pigsty, configure them explicitly in infra_portal and dns_records.
Resolution Methods
Local Static Resolution
Add entries to /etc/hosts on the client machine:
Add content:
Internal Dynamic Resolution
Pigsty includes dnsmasq as an internal DNS server. Configure managed nodes to use INFRA node as DNS server:
Configure domain records resolved by dnsmasq via dns_records:
Public Domain Names
Purchase a domain and add DNS A record pointing to public IP:
- Purchase domain from registrar (e.g.,
example.com) - Configure A record pointing to server public IP
- Use real domain in
infra_portal
Built-in DNS Service
Pigsty runs dnsmasq on INFRA nodes as a DNS server.
Related Parameters
| Parameter | Default | Description |
|---|---|---|
dns_enabled |
true |
Enable DNS service |
dns_port |
53 |
DNS listen port |
dns_records |
See below | Default DNS records |
Default DNS records:
Dynamic DNS Registration
Pigsty automatically registers DNS records for PostgreSQL clusters and instances:
- Instance-level DNS:
<pg_instance>points to instance IP (e.g.,pg-meta-1) - Cluster-level DNS:
<pg_cluster>points to primary IP or VIP (e.g.,pg-meta)
Cluster-level DNS target controlled by pg_dns_target:
| Value | Description |
|---|---|
auto |
Auto-select: use VIP if available, else primary IP |
primary |
Always point to primary IP |
vip |
Always point to VIP (requires VIP enabled) |
none |
Don’t register cluster DNS |
<ip> |
Specify fixed IP address |
Add suffix to cluster DNS via pg_dns_suffix.
Node DNS Configuration
Pigsty manages DNS configuration on managed nodes.
Static hosts Records
Configure static /etc/hosts records via node_etc_hosts:
DNS Server Configuration
| Parameter | Default | Description |
|---|---|---|
node_dns_method |
add |
DNS config method |
node_dns_servers |
['${admin_ip}'] |
DNS server list |
node_dns_options |
See below | resolv.conf options |
node_dns_method options:
| Value | Description |
|---|---|
add |
Prepend to existing DNS server list |
overwrite |
Completely overwrite DNS config |
none |
Don’t modify DNS config |
Default DNS options:
HTTPS Certificates
Pigsty uses self-signed certificates by default. Options include:
- Ignore warnings, use HTTP
- Trust self-signed CA certificate (download at
http://<ip>/ca.crt) - Use real CA or get free public domain certs via Certbot
See CA and Certificates documentation for details.
Extended Domains
Pigsty reserves the following domains for various application services:
| Domain | Purpose |
|---|---|
adm.pigsty |
PgAdmin interface |
ddl.pigsty |
Bytebase DDL management |
cli.pigsty |
PgWeb CLI interface |
api.pigsty |
PostgREST API service |
lab.pigsty |
Jupyter environment |
git.pigsty |
Gitea Git service |
wiki.pigsty |
Wiki.js docs |
noco.pigsty |
NocoDB |
supa.pigsty |
Supabase |
dify.pigsty |
Dify AI |
odoo.pigsty |
Odoo ERP |
mm.pigsty |
Mattermost |
Using these domains requires configuring corresponding services in infra_portal.
Management Commands
4 - Module Management
This document covers daily management operations for the INFRA module, including installation, uninstallation, scaling, and component maintenance.
Install INFRA Module
Use the infra.yml playbook to install the INFRA module on the infra group:
Uninstall INFRA Module
Use the infra-rm.yml playbook to uninstall the INFRA module from the infra group:
This playbook has no deletion safeguard. Full execution removes infra_data, nginx_data, nginx_home (default: /www), and /var/lib/grafana.
If you only need to stop services or deregister targets, use -t service or -t deregister. Read the complete removal scope and back up required data before running it.
Scale Out INFRA Module
Assign infra_seq to new nodes and add them to the infra group in the inventory:
Use the -l limit option to execute the playbook on the new node only:
Manage Local Repository
Local repository management tasks:
Complete subtask list:
Manage Nginx
Nginx management tasks:
Request HTTPS certificate:
Manage Infrastructure Components
Management commands for various infrastructure components:
Common maintenance commands:
Manage Grafana Passwords
Grafana uses two password parameters: grafana_admin_password, whose public default is pigsty, and grafana_view_password, whose default is DBUser.Viewer.
| Parameter | Rendered configuration |
|---|---|
grafana_admin_password |
/etc/grafana/grafana.ini and /infra/env/pigsty |
grafana_view_password |
/etc/grafana/provisioning/datasources/pigsty.yml |
Change the public defaults before production. After Grafana initializes, changing grafana_admin_password in inventory does not by itself reset the live Grafana account password; change it through Grafana (or its supported administration interface), keep the inventory consistent, and rerender the environment when needed:
grafana_view_password is the password used by the default PostgreSQL metadb data source as dbuser_view. If that database role password changes, update both the declared value and the Grafana data source; changing only one side breaks the dashboard connection.
5 - CA and Certificates
Pigsty maintains a self-signed Certificate Authority (CA) on the admin node by default. It signs certificates for PostgreSQL, Patroni, etcd, Silo, Nginx, and other internal services. Public Nginx entries can use Certbot/Let’s Encrypt certificates configured through infra_portal.
files/pki/ca/ca.key is the trust-root private key for the entire deployment. Never print, commit, upload, or transmit it over an unprotected channel. Back it up together with ca.crt, encrypted, with tightly restricted read access.
Self-Signed CA
The ca stage of infra.yml creates or reuses the CA locally on the admin node running Ansible, not on a remote Infra node. The default layout is:
The core defaults match the v4.5.0 roles:
| Parameter | Default | Meaning |
|---|---|---|
ca_create |
true |
Allow creation when ca.key is missing |
ca_cn |
pigsty-ca |
Common Name of the CA certificate |
cert_validity |
7300d |
Default internal service/client validity (20 years) |
nginx_cert_validity |
397d |
Nginx self-signed HTTPS certificate validity |
The role hard-codes the CA certificate lifetime to 36500d (about 100 years). These long-lived certificates are for a controlled internal trust domain; they are not publicly browser-trusted. Clients must explicitly trust ca.crt, while public endpoints should use a publicly trusted CA.
Initialize the local CA stage:
Running ./infra.yml -t ca may create a missing key or certificate and therefore changes PKI state. Confirm the admin node, configuration, and existing CA backup first.
Use an External CA
To reuse an enterprise CA:
- Set
ca_create: falseinpigsty.yml. - Place a matching
files/pki/ca/ca.keyandfiles/pki/ca/ca.crtpair on the admin node. - Set permissions and verify that the public-key digests match.
ca_create: false prevents generation of a new private key only when ca.key is missing. If the key exists but ca.crt does not, the role still creates a new self-signed CA certificate from that key. Always restore the pair together instead of relying on certificate regeneration.
Before running the CA stage, verify the files that will be used, the existing CA backup, and the admin node.
Back Up and Restore the CA
Retain at least:
files/pki/ca/ca.keyandca.crt- CA state such as
ca.srl,index.txt, and CRL files if issuance/revocation management uses them - backup time, the CA certificate SHA-256 fingerprint, and restoration instructions
Encrypt the backup and keep it in controlled offline media or a secrets-management system; do not leave an unencrypted tar archive. Restore into an isolated temporary directory first, then verify file count, type, permissions, public-key match, and certificate fingerprint before replacement.
Losing ca.key does not immediately make existing certificates unverifiable: they remain verifiable while clients trust ca.crt and the certificates remain valid and unrevoked. You can no longer issue, renew, or revoke with the original CA, so recovery usually requires a new CA, reissuing every certificate, and rolling out a new trust chain.
Issue Certificates with cert.yml
cert.yml runs locally on the admin node and issues generic certificates with the Pigsty CA. Pass cn explicitly instead of relying on the generic script default:
Default outputs:
| Parameter | Default | Meaning |
|---|---|---|
cn |
pigsty |
Common Name; set explicitly in real use |
san |
[DNS:localhost, IP:127.0.0.1] |
Subject Alternative Names |
org |
pigsty |
Organization |
unit |
pigsty |
Organizational Unit |
expire |
7300d |
Validity |
key |
files/pki/misc/<cn>.key |
Private-key output path |
crt |
files/pki/misc/<cn>.crt |
Certificate output path |
Advanced examples:
Verify the certificate without displaying or copying private-key content:
For PostgreSQL client certificates, cn must match the database role expected by HBA/cert authentication. Install the certificate, key, and root certificate on the client with the private key at mode 0600. With sslmode=verify-full, the connection hostname must appear in the server certificate SAN.
Trust the CA Certificate
Distribute only public ca.crt, never ca.key. Verify its SHA-256 fingerprint through a separate trusted channel before installation.
Debian / Ubuntu
RHEL / Rocky / AlmaLinux
macOS
Windows (Administrator PowerShell)
Infra Nginx normally exposes the public CA certificate at http://<infra_ip>/ca.crt. Verify the fingerprint after download; HTTP transport alone does not prove certificate authenticity.
Nginx and Let’s Encrypt
Each infra_portal entry can name a certbot certificate. Pigsty’s /etc/nginx/sign-cert uses Certbot webroot mode, groups domain and domains entries that share a certificate name, and then /etc/nginx/link-cert links the result into Nginx.
Prerequisites:
- Public DNS A/AAAA records resolve to the intended Infra node.
- Port 80 is publicly reachable for HTTP-01, and Nginx serves the ACME webroot.
certbot_emailis valid and the Certbot package is installed.- Portal domains, additional domains, and certificate names are exact.
Update the Nginx configuration and issue certificates:
In v4.5.0, the nginx_certbot task has ignore_errors: true. A playbook that continues or reports overall success does not prove certificate issuance. Inspect Certbot state, certificate files, Nginx configuration, and a real TLS handshake.
Renewal scheduling depends on the Certbot package for the operating system. Do not add a duplicate cron job before checking existing timers and cron configuration:
After Certbot replaces certificates on disk, Nginx still needs a reload to use them. Configure and verify a renewal deploy hook such as systemctl reload nginx, or an equivalent managed process. Treat automatic renewal as proven only after a real or staging renewal exercise.
Troubleshooting and Acceptance
| Symptom | Check |
|---|---|
| Browser rejects an internal cert | Correct ca.crt, SAN hostname, and system time |
verify-full fails |
Connection hostname, SAN, chain, and root certificate |
| Certbot HTTP-01 fails | DNS, port 80, ACME webroot, proxy/CDN, and rate limits |
| Playbook succeeds but old cert remains | Ignored nginx_certbot errors, link-cert, and Nginx reload |
| Permission denied | Private key 0600 (deployed Nginx key is 0640 root:nginx) |
| Trust breaks after CA rotation | Roll out client trust, then service certs, then reload services |
Final acceptance should separately prove correct certificate content and SANs, successful chain validation, that the service loaded the new certificate, that target clients trust it, and that renewal exists and passes a dry run. A generated file or successful playbook alone proves none of those later layers.
6 - Grafana High Availability: Using PostgreSQL Backend
You can use PostgreSQL as Grafana’s backend database.
This is a great opportunity to understand Pigsty’s deployment system. By completing this tutorial, you’ll learn:
- How to create a new database cluster
- How to create new business users in an existing cluster
- How to create new business databases in an existing cluster
- How to access databases created by Pigsty
- How to manage Grafana dashboards
- How to manage PostgreSQL datasources in Grafana
- How to upgrade Grafana database in one step
TL;DR
Create Database Cluster
We can define a new database grafana on pg-meta, or create a dedicated Grafana database cluster pg-grafana on new nodes.
Define Cluster
To create a new dedicated cluster pg-grafana on machines 10.10.10.11 and 10.10.10.12, use this config:
Create Cluster
Use this command to create the pg-grafana cluster: pgsql.yml.
This command is the Ansible Playbook pgsql.yml for creating database clusters.
Users and databases defined in pg_users and pg_databases are automatically created during cluster initialization. With this config, after cluster creation (without DNS), you can access the database using these connection strings (any one works):
Since Pigsty is installed on a single meta node by default, the following steps will create Grafana’s user and database on the existing pg-meta cluster, not the pg-grafana cluster created here.
Create Grafana Business User
The usual convention for business object management: create user first, then database.
Because if the database has an owner configured, it depends on the corresponding user.
Define User
To create user dbuser_grafana on the pg-meta cluster, first add this user definition to pg-meta’s cluster definition:
Location: all.children.pg-meta.vars.pg_users
If you define a different password here, replace the corresponding parameter in subsequent steps
Create User
Use this command to create the dbuser_grafana user (either works):
This actually calls the Ansible Playbook pgsql-user.yml to create the user:
The dbrole_admin role has permission to execute DDL changes in the database, which is exactly what Grafana needs.
Create Grafana Business Database
Define Database
Creating a business database follows the same pattern as users. First add the new database grafana definition to pg-meta’s cluster definition.
Location: all.children.pg-meta.vars.pg_databases
Create Database
Use this command to create the grafana database (either works):
This actually calls the Ansible Playbook pgsql-db.yml to create the database:
Use Grafana Business Database
Verify Connection String Reachability
You can access the database using different services or access methods, for example:
Here, we’ll use the Default service that directly accesses the primary through load balancer.
First verify the connection string is reachable and has DDL execution permissions:
Directly Modify Grafana Config
To make Grafana use a Postgres datasource, edit /etc/grafana/grafana.ini and modify the config:
Change the default config to:
Then restart Grafana:
When you see activity in the newly added grafana database from the monitoring system, Grafana is now using Postgres as its primary backend database.
But there’s a new issue—the original Dashboards and Datasources in Grafana have disappeared! You need to re-import dashboards and Postgres datasources.
Manage Grafana Dashboards
As admin user, navigate to the files/grafana directory under the Pigsty directory and run grafana.py init to reload Pigsty dashboards.
Execution result:
This script detects the current environment (defined in ~/pigsty during installation), gets Grafana access info, and replaces dashboard URL placeholder domains (*.pigsty) with actual domains used.
As a side note, use grafana.py clean to clear target dashboards, and grafana.py load to load all dashboards from the current directory. When Pigsty dashboards change, use these two commands to upgrade all dashboards.
Manage Postgres Datasources
When creating a new PostgreSQL cluster with pgsql.yml or a new business database with pgsql-db.yml, Pigsty registers new PostgreSQL datasources in Grafana. You can directly access target database instances through Grafana using the default monitoring user. Most pgcat application features depend on this.
To register Postgres databases, use the register_grafana task in pgsql.yml:
One-Step Grafana Upgrade
You can directly modify the Pigsty config file to change Grafana’s backend datasource, completing the database switch in one step. Edit the grafana_pgurl parameter in pigsty.yml:
Then re-run the grafana task from infra.yml to complete the Grafana upgrade: