diff --git a/knowledge base/peerdb.md b/knowledge base/peerdb.md index 37d19f7..c3812d1 100644 --- a/knowledge base/peerdb.md +++ b/knowledge base/peerdb.md @@ -8,7 +8,143 @@ Fast, simple, and cost effective Postgres replication. ## TL;DR -API responses hide error messages behind a `200 OK` HTTP status code as of 2025-03-14. +
+ Glossary + +| Term | Summary | +| ------ | ------------------------------------------------------------------------- | +| Peer | Connection to a database that PeerDB can query | +| Mirror | Stream of changes, feed in real-time, from a source peer to a target peer | +| Alert | Notifications about issues in flows | + +
+ +
+ Gotchas + +- The [documentation] is **sorely lacking**. + +- The product appears to have **not** been designed with configuration automation via IaC (nor APIs in general) in mind. + +- The API proven **un**reliable, **non**-idempotent, or plain did **not** work as described in the [API Reference] as of + 2025-03-19.
+ E.g., the `allow_update: true` data parameter in a request to the `peers/create` endpoint should make the APIs update + a peer's settings when one with the given name already exists, but the peer just does **not** get updated. + +- API responses hide error messages behind a `200 OK` HTTP status code as of 2025-03-19. + +
+ Response example + + Output of a `ansible.builtin.uri` Ansible task executed against the PeerDB server: + + ```json + { + "json": { + "message": "POSTGRES peer some_pg_peer was invalidated: failed to create connection: failed to connect to `user=me database=testDb`:\n\t172.31.40.46:6005 (dblab.example.org): tls error: server refused TLS connection\n\t172.31.40.46:6005 (dblab.example.org): failed SASL auth: FATAL: password authentication failed for user \"me\" (SQLSTATE 28P01)", + "status": "FAILED" + }, + "msg": "OK (426 bytes)", + "status": 200, + "url": "http://localhost:3000/api/v1/peers/create", + } + ``` + +
+ +- PeerDB seems unable to connect to peers which `host` parameter is `localhost` or `127.0.0.1`, but can connect to the + IP address of the system running the service (e.g., `192.168.1.10`).
+ This is most likely a Docker-related issue. + +
+ + ```sh + $ docker run --rm --name 'postgres' -d -p '10000:5432' -e POSTGRES_PASSWORD='password' 'postgres:15.5' + 1cb9d450f1c1112601022dec4315a4dac7f564ee67760788850e4f61a8b5d8fb + + $ psql 'host=localhost port=10000 user=postgres password=password' -c '\conninfo' + You are connected to database "postgres" as user "postgres" on host "localhost" (address "127.0.0.1") at port "10000". + + $ psql 'host=192.168.1.10 port=10000 user=postgres password=password' -c '\conninfo' + You are connected to database "postgres" as user "postgres" on host "192.168.1.10" at port "10000". + + $ psql 'host=localhost port=9900 user=me password=peerdb' + psql (15.8, server 14) + Type "help" for help. + me=> CREATE PEER IF NOT EXISTS some_pg_peer FROM POSTGRES WITH (host='localhost', port='10000', user='postgres', password='password', database='postgres'); + ERROR: User provided error: ErrorInfo: ERROR, internal_error, failed to create peer: POSTGRES peer some_pg_peer was invalidated: failed to create connection: failed to connect to `user=postgres database=postgres`: + 127.0.0.1:10000 (localhost): dial error: dial tcp 127.0.0.1:10000: connect: connection refused + [::1]:10000 (localhost): dial error: dial tcp [::1]:10000: connect: cannot assign requested address + 127.0.0.1:10000 (localhost): dial error: dial tcp 127.0.0.1:10000: connect: connection refused + [::1]:10000 (localhost): dial error: dial tcp [::1]:10000: connect: cannot assign requested address + me=> CREATE PEER IF NOT EXISTS some_pg_peer FROM POSTGRES WITH (host='192.168.1.10', port='10000', user='postgres', password='password', database='postgres'); + OK + ``` + +
+ +- PostgreSQL peers do **not** accept connection options as of 2025-03-19.
+ This makes it impossible to specify any or override defaults. + +
+ + The connection string is composed in code.
+ The [data structure specifying its parameters][peers.proto#PostgresConfig] does **not** accept options, **nor** explicit + connection strings. + + ```go + // https://github.com/PeerDB-io/peerdb/blob/6a591128908cbd76df8f7e4094ec838fac08dcda/protos/peers.proto#L73 + message PostgresConfig { + string host = 1; + uint32 port = 2; + string user = 3; + string password = 4 [(peerdb_redacted) = true]; + string database = 5; + // defaults to _peerdb_internal + optional string metadata_schema = 7; + optional SSHConfig ssh_config = 8; + } + ``` + +
+ +- PostgreSQL peers have issues connecting to DBLab clones as of 2025-03-19.
+ Peers seemingly **require** SSL to connect to them for some reason, or fail the password authentication when given the + correct credentials. + +
+ + ```sh + $ nc -vz dblab.example.org 6005 + Ncat: Version 7.93 ( https://nmap.org/ncat ) + Ncat: Connected to 172.31.40.46:6005. + Ncat: 0 bytes sent, 0 bytes received in 0.04 seconds. + + $ psql 'postgresql://dblab.example.org:6005/testDb?user=me&password=1q2w3e4r' -c '\conninfo' + You are connected to database "testDb" as user "me" on host "dblab.example.org" (address "172.31.40.46") at port "6005". + + $ psql 'host=localhost port=9900 password=peerdb' + psql (15.8, server 14) + Type "help" for help. + + me=> CREATE PEER IF NOT EXISTS some_pg_peer FROM POSTGRES WITH (host='dblab.example.org', port='6005', user='me', password='1q2w3e4r', database='testDb'); + ERROR: User provided error: ErrorInfo: ERROR, internal_error, failed to create peer: POSTGRES peer some_pg_peer was invalidated: failed to create connection: failed to connect to `user=me database=testDb`: + 172.31.40.46:6005 (dblab.example.org): tls error: server refused TLS connection + 172.31.40.46:6005 (dblab.example.org): failed SASL auth: FATAL: password authentication failed for user "me" (SQLSTATE 28P01) + ``` + +
+ +- When creating alerts through the APIs, the alert's ID in the request's data must be `-1`.
+ This **will** create duplicates. + +- SQL mode is provided by a translation service, which intercepts the `CREATE PEER` (or other resource) command and + uses it to create the correct resources in the PostgreSQL backend.
+ The translator does **not** expose **all** the resources (e.g., I could find no alert configuration), **nor** allows + for easy updates (e.g. the peers and mirrors data is encoded).
+ The data for peers and mirrors is encoded in ways that are **not** disclosed in the [documentation]. + +
Setup @@ -33,37 +169,67 @@ ALTER SYSTEM SET max_replication_slots = 10;
+```sh +git clone 'https://github.com/PeerDB-io/peerdb.git' \ +&& docker compose -f 'peerdb/docker-compose.yml' up -d +``` + - - ## Further readings - [Website] -- [Main repository] +- [Codebase] - [Documentation] ### Sources - [Public IPs For PeerDB Cloud] +- [API Reference] +[api reference]: https://docs.peerdb.io/peerdb-api/reference +[codebase]: https://github.com/PeerDB-io/peerdb [documentation]: https://docs.peerdb.io/ -[main repository]: https://github.com/PeerDB-io/peerdb -[website]: https://www.peerdb.io/ +[peers.proto#PostgresConfig]: https://github.com/PeerDB-io/peerdb/blob/6a591128908cbd76df8f7e4094ec838fac08dcda/protos/peers.proto#L73 [public ips for peerdb cloud]: https://docs.peerdb.io/peerdb-cloud/ip-table +[website]: https://www.peerdb.io/ diff --git a/knowledge base/postgresql.md b/knowledge base/postgresql.md index 4929223..c0ec790 100644 --- a/knowledge base/postgresql.md +++ b/knowledge base/postgresql.md @@ -66,13 +66,15 @@ EOF # If not given: # - the hostname defaults to 'localhost'; # - the port defaults to '5432'; -# - the username defaults to the current user. +# - the username defaults to the current user; +# - the 'sslmode' parameter defaults to 'prefer'. psql 'my-db' psql 'my-db' 'user' +psql 'postgres://host' psql 'postgresql://host:5433/my-db?sslmode=require' psql -U 'username' -d 'my-db' -h 'hostname' -p 'port' -W psql --host 'host.fqnd' --port '5432' --username 'postgres' --database 'postgres' --password -psql "service=prod sslmode=require" +psql "service=prod sslmode=disable" # List available databases. psql … --list @@ -229,6 +231,7 @@ psql -h 'localhost' -p '6543' -U 'postgres' -d 'postgres' -W - [psql] - [pg_settings] - [Connect to a PostgreSQL database] +- [Database connection control functions] - [The password file] - [How to Generate SCRAM-SHA-256 to Create Postgres 13 User] - [PostgreSQL: Get member roles and permissions] @@ -253,11 +256,12 @@ psql -h 'localhost' -p '6543' -U 'postgres' -d 'postgres' -W [sql]: sql.md -[docker image]: https://github.com/docker-library/docs/blob/master/postgres/README.md -[psql]: https://www.postgresql.org/docs/current/app-psql.html -[pg_settings]: https://www.postgresql.org/docs/current/view-pg-settings.html -[the password file]: https://www.postgresql.org/docs/current/libpq-pgpass.html [create function]: https://www.postgresql.org/docs/current/sql-createfunction.html +[database connection control functions]: https://www.postgresql.org/docs/current/libpq-connect.html +[docker image]: https://github.com/docker-library/docs/blob/master/postgres/README.md +[pg_settings]: https://www.postgresql.org/docs/current/view-pg-settings.html +[psql]: https://www.postgresql.org/docs/current/app-psql.html +[the password file]: https://www.postgresql.org/docs/current/libpq-pgpass.html [an in-depth guide to postgres data masking with anonymizer]: https://thelinuxcode.com/postgresql-anonymizer-data-masking/ diff --git a/snippets/dblab.fish b/snippets/dblab.fish index ebaefe5..a9aff24 100644 --- a/snippets/dblab.fish +++ b/snippets/dblab.fish @@ -88,11 +88,11 @@ docker restart 'dblab_clone_6000' # Reset clones # Only available via the '/api' endpoints, no direct ones +dblab clone reset --async='true' --latest='true' 'some-clone' curl -X 'POST' 'https://dblab.example.org:1234/api/clone/some-clone/reset' \ -H "Verification-Token: $(gopass show -o 'dblab')" \ -H 'accept: application/json' -H 'content-type: application/json' \ -d '{ "latest": true }' -dblab clone reset --async='true' --latest='true' 'some-clone' # Reset all protected clones curl --url 'https://dblab.example.org:2345/status' --header 'verification-token: somePassword' \ | jq -r '.cloning.clones[]|select(.protected = "true")|.id' \ diff --git a/snippets/peerdb.fish b/snippets/peerdb.fish index c285c0d..6f8c318 100644 --- a/snippets/peerdb.fish +++ b/snippets/peerdb.fish @@ -2,6 +2,8 @@ # Connect to PeerDB server in SQL mode psql 'host=localhost port=9900 password=peerdb' +psql 'postgresql://peerdb.example.org:9900/?password=peerdb' + # List peers psql "host=localhost port=9900 password=$(gopass show -o 'peerdb/instance')" \ @@ -13,6 +15,14 @@ curl -fsS --url 'http://localhost:3000/api/v1/peers/list' \ # postgres: peer.type=3|'POSTGRES' + postgres_config={…} # clickhouse: peer.type=8 + clickhouse_config={…} # kafka: peer.type=9 + kafka_config={…} +psql "host=localhost port=9900 password=$(gopass show -o 'peerdb/instance')" \ + -c "CREATE PEER some_pg_peer FROM POSTGRES WITH ( + host = 'localhost', + port = '5432', + user = 'peerdb', + password = '$(gopass show -o 'peerdb/db-user')', + database = 'sales' + );" curl -fsS --url 'http://localhost:3000/api/v1/peers/create' -X 'POST' \ -H "Authorization: Basic $(gopass show -o 'peerdb/instance' | xargs printf '%s' ':' | base64)" \ -H 'Content-Type: application/json' \ @@ -29,14 +39,6 @@ curl -fsS --url 'http://localhost:3000/api/v1/peers/create' -X 'POST' \ } } }" -psql "host=localhost port=9900 password=$(gopass show -o 'peerdb/instance')" \ - -c "CREATE PEER some_pg_peer FROM POSTGRES WITH ( - host = 'localhost', - port = '5432', - user = 'peerdb', - password = '$(gopass show -o 'peerdb/db-user')', - database = 'sales' - );" # Update peers # Reuse the command for creation but add 'allow_update: true' to the data @@ -46,6 +48,11 @@ curl -fsS --url 'http://localhost:3000/api/v1/peers/create' -X 'POST' … \ allow_update: true }" +# Delete peers +psql "host=localhost port=9900 password=$(gopass show -o 'peerdb/instance')" \ + -c "DELETE FROM peers WHERE name == 'some_pg_peer';" + + # List mirrors curl -fsS --url 'http://localhost:3000/api/v1/mirrors/list' \ -H "Authorization: Basic $(gopass show -o 'peerdb/instance' | xargs printf '%s' ':' | base64)" \ @@ -104,6 +111,7 @@ curl -fsS 'http://localhost:3000/api/v1/flows/cdc/create' -X 'POST' \ } }' + # Show alerts' configuration curl -fsS --url 'http://localhost:3000/api/v1/alerts/config' \ -H "Authorization: Basic $(gopass show -o 'peerdb/instance' | xargs printf '%s' ':' | base64)" \