I did some changes to the initial commit by Nolan to the documentation of Mastodon PgBouncer Guide.
As my pull request is still waiting to be approved, I leave it also here because I had some trouble to get it to work with the instructions that were initially shared.
Installing PgBouncer
On Ubuntu/Debian:
sudo apt install pgbouncer
Then:
nano /etc/default/pgbouncer
START=1
Starting:
sudo service pgbouncer start
(Note that this guide assumes you aren’t using Docker.)
Configuring PgBouncer
Setting a password
First off, if your `mastodon` user in Postgres is set up wthout a password, you will need to set a password. There seems to be no way to use PgBouncer with an empty password.
Here’s how you might reset the password:
su - postgres
psql
ALTER USER mastodon WITH PASSWORD 'pineapple';
\q
exit
Configuring PgBouncer
PgBouncer has two config files: `pgbouncer.ini` and `userlist.txt` both in `/etc/pgbouncer/`. The first contains the configuration, whereas the second just contains a list of usernames and passwords.
Configuring userlist.txt
Add the `mastodon` user to the `userlist.txt` using md5 or plain text:
"mastodon" "pineapple"
Or using md5:
"mastodon" "md5bc8a988ff49c4d1d8c43c4747c68fc0b"
The md5 password is just the md5sum of `password+username` with the string `md5` prepended. For instance, to derive the hash for user mastodon with pineapple password, you can do:
# ubuntu, debian, etc.
echo -n "pineapplemastodon" | md5sum
# macOS, openBSD, etc.
md5 -s "pineapplemastodon"
You will get this as the result `bc8a988ff49c4d1d8c43c4747c68fc0b` and you prepend the string `md5`, resulting in `md5bc8a988ff49c4d1d8c43c4747c68fc0b`.
You’ll also want to create a `pgbouncer` admin user to log in to the PgBouncer admin database. So here’s a sample `userlist.txt`:
"mastodon" "md5bc8a988ff49c4d1d8c43c4747c68fc0b"
"pgbouncer" "p4ssw0rd"
Configuring pgbouncer.ini
Add a line under `[databases]` listing the Postgres databases you want to connect to. Here we’ll just have PgBouncer use the same username/password and database name to connect to the underlying Postgres database:
mastodon_production = host=127.0.0.1 port=5432 dbname=mastodon_production user=mastodon password=pineappleini
[databases]
The `listen_addr` and `listen_port` tells PgBouncer which address/port to accept connections. The defaults are fine:
ini
listen_addr = 127.0.0.1
listen_port = 6432
Put `md5` as the `auth_type` (auth_type md5 allows both plain text and md5 passwords):
ini
auth_type = md5
Make sure the `pgbouncer` user is an admin:
ini
admin_users = pgbouncer
This next part is very important! The default pooling mode is session-based, but for Mastodon we want transaction-based. In other words, a Postgres connection is created when a transaction is created and dropped when the transaction is done. So you’ll want to change the `pool_mode` from `session` to `transaction`:
ini
pool_mode = transaction
Next up, `max_client_conn` defines how many connections PgBouncer itself will accept, and `default_pool_size` puts a limit on how many Postgres connections will be opened under the hood. (In PgHero the number of connections reported will correspond to `default_pool_size` because it has no knowledge of PgBouncer.)
The defaults are fine to start, and you can always increase them later:
ini
max_client_conn = 100
default_pool_size = 20
Debugging that it all works
You should be able to connect to PgBouncer just like you would with Postgres:
psql -p 6432 -U mastodon mastodon_production
And then use your password to log in.
You can also check the PgBouncer logs like so:
tail -f /var/log/postgresql/pgbouncer.log
Configuring Mastodon to talk to PgBouncer
In your `.env.production` file, first off make sure that this is set:
bash
PREPARED_STATEMENTS=false
Since we’re using transaction-based pooling, we can’t use prepared statements.
Next up, configure Mastodon to use port 6432 (PgBouncer) instead of 5432 (Postgres) and you should be good to go:
bash
DB_HOST=localhost
DB_USER=mastodon
DB_NAME=mastodon_production
DB_PASS=password
DB_PORT=6432
After you need to restart your Mastodon services for the system to assume the `.env.production` changes:
systemctl restart mastodon-web.service mastodon-sidekiq.service mastodon-streaming.service
Your instance should be working and using PgBouncer.
Administering PgBouncer
The easiest way to reboot is:
sudo service pgbouncer restart
But if you’ve set up a PgBouncer admin user, you can also connect as the admin:
psql -p 6432 -U pgbouncer pgbouncer
And then do:
RELOAD;
If you want to see if PgBouncer is working, you can use:
SHOW STATS;
The total_request should not be 0.
There are plenty other values you may wish to look at, like:
SHOW SERVERS;
SHOW CLIENTS;
SHOW POOLS;
SHOW LISTS;
Resources
– Mastodon PgBouncer Guide
– Scaling Mastodon
– PgBouncer documentation
– Connection Pooling in PostgreSQL using pgbouncer
– PgBouncer on the Postgres wiki