feat: add pg-essentials

This commit is contained in:
AJ ONeal
2024-12-25 00:28:19 +00:00
parent bc81147500
commit 54ce1007f1
3 changed files with 286 additions and 0 deletions

200
pg-essentials/README.md Normal file
View File

@@ -0,0 +1,200 @@
---
title: pg-essentials
homepage: https://github.com/bnnanet/pg-essentials
tagline: |
pg-essentials: client and server scripts for working with postgres
---
To update or switch versions, run `webi pg-essentials@stable` (or `@v1.0.0`,
`@beta`, etc).
### Files
These are the files / directories that are created and/or modified with this
install:
```text
~/.local/bin/
~/.local/opt/pg-essentials/
~/.pgpass
~/.psqlrc
~/.config/psql/psqlrc.sql
~/.config/psql/history
```
## Cheat Sheet
> `pg-essentials` includes scripts to manage credentials, backups, and
> preferences.
```sh
psql-store-credential 'postgres://my-userdb:my-token@my-host:5432/my-userdb'
psql-backup 'my-userdb'
psql-connect 'my-userdb'
psql-init TODO
```
```sh
pg-register-service '5432'
pg-addgroup 'hostssl' 'remote_users' 5432
pg-adduser 'my-user-prefix' '5432' 'remote_users'
pg-passwd 'my-user-prefix-and-suffix' 5432
```
### Client Scripts
#### How to Store Credentials
This will parse the PG URL and put it in the correct credential format in
`~/.pgpass`.
```sh
psql-store-credential 'postgres://my-userdb:my-token@my-host:5432/my-userdb'
```
This is the same as manually editing `~/.pgpass` to add
```text
# export PGPASSFILE="$HOME/.pgpass"
# hostname:port:database:username:password
my-host:5432:my-userdb:my-userdb:my-token
```
#### How to Connect
The `psql` only uses `~/.pgpass` to fill in the password.
`psql-connect` will lookup the userdb name in `~/.pgpass` and use the rest of
the connection details to connect (excluding the password, which will be read
from `~/.pgpass`).
```sh
psql-connect 'my-userdb'
```
This is the same as:
```sh
psql 'postgress://my-userdb@my-host:5432/my-userdb'
```
#### How to Backup
This uses `pg_dump` to create an easy-to-restore backup (using the correct
permission options), with the schema and data separated.
```sh
psql-backup 'my-userdb'
```
```text
my-userdb.schema.drop.sql # drops and then creates schema
my-userdb.schema.sql # creates schema, without dropping
my-userdb.data.sql # inserts data
```
This is the same as:
```sh
pg_dump --no-privileges --no-owner --schema-only --clean \
--username 'my-userdb' --no-password --host 'my-host' --port 5432 \
-f ./my-userdb.schema.drop.sql 'my-userdb'
pg_dump --no-privileges --no-owner --schema-only \
--username 'my-userdb' --no-password --host 'my-host' --port 5432 \
-f ./my-userdb.schema.sql 'my-userdb'
pg_dump --no-privileges --no-owner --data-only \
--username 'my-userdb' --no-password --host 'my-host' --port 5432 \
-f ./my-userdb.data.sql 'my-userdb'
```
### Server Scripts
These assume a conflict-free installation of postgres at
`~/.local/share/postgres/var/`.
The scripts can easily be manually modified for other locations.
#### How to Register Service
```sh
pg-register-service '5432'
```
This is the same as
```sh
curl https://webi.sh/serviceman | sh
source ~/.config/envman/PATH.env
mkdir -p ~/.local/share/postgres
serviceman add --name 'postgres' -- \
postgres -D ~/.local/share/postgres/var -p 5432
```
#### How to add Remote Role (Group)
This will add a role (group) which allows users (named the same as their
database name) to access the pg database remotely, using TLS with SNI (ALPN will
be set to 'postgresql' and must be explicitly accepted by proxies).
```sh
pg-addgroup 'hostssl' 'remote_users' 5432
```
This is the same as adding a remote users role and editing
`~/.local/share/postgres/var/hba.conf`
```sql
CREATE ROLE "remote_users" NOLOGIN;
```
```ini
hostssl sameuser +remote_users 0.0.0.0/0 scram-sha-256
hostssl sameuser +remote_users ::0/0 scram-sha-256
```
#### How to add Remote User
This will create a user and database of the same name, with the given prefix
(followed by a random suffix), as a member of 'remote_users':
```sh
pg-adduser 'my-user-prefix'
```
This is the same as generating a random suffix and password (ex: using `uuidgen`
or `xxd -l 16 -ps /dev/urandom`), and creating the `DATABASE`, `ROLE`, and
granting `PRIVILEGES`:
```sql
CREATE DATABASE "my-user-prefix-1234";
CREATE ROLE "my-user-prefix-1234" LOGIN INHERIT IN ROLE "remote_users" ENCRYPTED PASSWORD 'supersecret';
GRANT ALL PRIVILEGES ON DATABASE "my-user-prefix-1234" to "my-user-prefix-1234";
```
Note: the password is NOT encrypted, just hashed - a misnomer from days of yore
#### How to Set a User's Password
This generates a new random password for the user/db.
```sh
pg-passwd 'my-user-prefix-and-suffix'
```
This is the same as generating a random password and running the following:
```sql
ALTER USER "my-user-prefix-and-suffix" WITH PASSWORD 'supersecret';
```
### Building Postgres from Source
These scripts will build postgres in `~/relocatable`, from source.
```sh
pg-build-linux "$(hostname)" 17.2
pg-build-macos "$(hostname)" 17.2
```

64
pg-essentials/install.sh Normal file
View File

@@ -0,0 +1,64 @@
#!/bin/sh
__init_pg_essentials() {
set -e
set -u
#########################
# Install pg-essentials #
#########################
# Every package should define these 6 variables
pkg_cmd_name="pg-essentials"
pkg_dst_cmd="$HOME/.local/bin/psql-backup"
pkg_dst="$pkg_dst_cmd"
pkg_src_cmd="$HOME/.local/opt/pg-essentials-v$WEBI_VERSION/bin/psql-backup"
pkg_src_bin="$HOME/.local/opt/pg-essentials-v$WEBI_VERSION/bin"
pkg_src_dir="$HOME/.local/opt/pg-essentials-v$WEBI_VERSION"
pkg_src="$pkg_src_cmd"
pkg_install() {
rm -rf "${pkg_src_dir}"
# mv ./bnnanet-pg-essentials-* "$HOME/.local/opt/pg-essentials-v1.0.0"
mv ./*"$pkg_cmd_name"*/ "${pkg_src_dir}"
}
pkg_link() {
(
cd ~/.local/opt/ || return 1
rm -rf ./pg-essentials
ln -s "pg-essentials-v$WEBI_VERSION" 'pg-essentials'
)
(
mkdir -p ~/.local/bin/
cd ~/.local/opt/pg-essentials/ || return 1
for b_file in pg-*; do
rm -rf ../../bin/"${b_file}"
ln -s "../opt/pg-essentials-v$WEBI_VERSION/bin/${b_file}" .
done
for b_file in psql-*; do
rm -rf ../../bin/"${b_file}"
ln -s "../opt/pg-essentials-v$WEBI_VERSION/bin/${b_file}" .
done
)
}
pkg_get_current_version() {
# 'psql-backup -V' has output in this format:
# psql-backup v1.0.0 - creates portable (across instances) SQL schema & data backups
#
# USAGE
# psql-backup <user> [host] [port] [dbname]
#
# ...
# This trims it down to just the version number:
# 1.0.0
psql-backup --version 2> /dev/null | head -n 1 | cut -d' ' -f2 | sed 's:^v::'
}
}
__init_pg_essentials

22
pg-essentials/releases.js Normal file
View File

@@ -0,0 +1,22 @@
'use strict';
let Releases = module.exports;
let GitHubSource = require('../_common/github-source.js');
let owner = 'BeyondCodeBootcamp';
let repo = 'aliasman';
Releases.latest = async function () {
let all = await GitHubSource.getDistributables({ owner, repo });
for (let pkg of all.releases) {
pkg.os = 'posix_2017';
}
return all;
};
if (module === require.main) {
Releases.latest().then(function (all) {
all = require('../_webi/normalize.js')(all);
console.info(JSON.stringify(all, null, 2));
});
}