diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..4ff3bd7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Always use LF endings. +* text eol=lf \ No newline at end of file diff --git a/.github/workflows/auto-pr.yml b/.github/workflows/auto-pr.yml index 213d5b8..ae26510 100644 --- a/.github/workflows/auto-pr.yml +++ b/.github/workflows/auto-pr.yml @@ -10,7 +10,7 @@ jobs: steps: - name: Checkout Branch ${{ github.ref_name }} - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Create Pull Request uses: bfren/pull-request@v2 diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index 79579e1..d1ef8e5 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 build: strategy: fail-fast: false @@ -22,7 +22,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get repository name run: echo "REPOSITORY_NAME=$(echo '${{ github.repository }}' | awk -F '/' '{print $2}')" >> $GITHUB_ENV @@ -35,20 +35,20 @@ jobs: id: version - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Login to DockerHub - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push id: docker_build - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: context: . file: ./${{ matrix.postgresql }}/Dockerfile @@ -59,7 +59,7 @@ jobs: platforms: linux/amd64,linux/arm/v7,linux/arm64 tags: | bfren/postgresql:postgresql${{ matrix.postgresql }}-dev - bfren/postgresql:postgresql${{ matrix.postgresql }}-${{ steps.version.outputs.contents }}-beta + bfren/postgresql:postgresql${{ matrix.postgresql }}-${{ steps.version.outputs.contents }}-dev - name: Image digest run: echo ${{ steps.docker_build.outputs.digest }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index d9d4c8d..59ba126 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Get repository name run: echo "REPOSITORY_NAME=$(echo '${{ github.repository }}' | awk -F '/' '{print $2}')" >> $GITHUB_ENV @@ -46,20 +46,20 @@ jobs: id: version - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Login to DockerHub - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Build and push id: docker_build - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: context: . file: ./${{ matrix.postgresql }}/Dockerfile diff --git a/.github/workflows/update-readme.yml b/.github/workflows/update-readme.yml index 14fd935..7fc7506 100644 --- a/.github/workflows/update-readme.yml +++ b/.github/workflows/update-readme.yml @@ -15,10 +15,10 @@ jobs: shell: bash - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Login to DockerHub - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} diff --git a/12/Dockerfile b/12/Dockerfile index 75c2b3d..be7cbb3 100644 --- a/12/Dockerfile +++ b/12/Dockerfile @@ -1,21 +1,21 @@ -FROM bfren/alpine-s6:alpine3.18-4.5.9 +FROM bfren/alpine-s6:alpine3.18-5.0.5 LABEL org.opencontainers.image.source="https://github.com/bfren/docker-postgresql" ARG BF_IMAGE ARG BF_VERSION -ENV \ - # set to "1" to compress backup sql files - POSTGRESQL_BACKUP_COMPRESS_FILES="0" \ - # the number of days after which backups will be deleted - POSTGRESQL_BACKUP_KEEP_FOR_DAYS="28" - EXPOSE 5432 COPY ./overlay / COPY ./12/overlay / +ENV \ + # set to "1" to compress backup sql files + BF_PG_BACKUP_COMPRESS_FILES="0" \ + # the duration for which backups will be kept + BF_PG_BACKUP_KEEP_FOR="28day" + RUN bf-install -VOLUME [ "/data", "/backup" ] +VOLUME [ "/backup", "/data" ] diff --git a/12/overlay/tmp/POSTGRESQL_BUILD b/12/overlay/tmp/POSTGRESQL_BUILD index a93a48b..59321dc 100644 --- a/12/overlay/tmp/POSTGRESQL_BUILD +++ b/12/overlay/tmp/POSTGRESQL_BUILD @@ -1 +1 @@ -12.16-r0 \ No newline at end of file +12.17-r0 \ No newline at end of file diff --git a/12/overlay/tmp/POSTGRESQL_MINOR b/12/overlay/tmp/POSTGRESQL_MINOR index 499fd8b..339dacb 100644 --- a/12/overlay/tmp/POSTGRESQL_MINOR +++ b/12/overlay/tmp/POSTGRESQL_MINOR @@ -1 +1 @@ -12.16 \ No newline at end of file +12.17 \ No newline at end of file diff --git a/13/Dockerfile b/13/Dockerfile index e42116c..471eafc 100644 --- a/13/Dockerfile +++ b/13/Dockerfile @@ -1,21 +1,21 @@ -FROM bfren/alpine-s6:alpine3.18-4.5.9 +FROM bfren/alpine-s6:alpine3.18-5.0.5 LABEL org.opencontainers.image.source="https://github.com/bfren/docker-postgresql" ARG BF_IMAGE ARG BF_VERSION -ENV \ - # set to "1" to compress backup sql files - POSTGRESQL_BACKUP_COMPRESS_FILES="0" \ - # the number of days after which backups will be deleted - POSTGRESQL_BACKUP_KEEP_FOR_DAYS="28" - EXPOSE 5432 COPY ./overlay / COPY ./13/overlay / +ENV \ + # set to "1" to compress backup sql files + BF_PG_BACKUP_COMPRESS_FILES="0" \ + # the duration for which backups will be kept + BF_PG_BACKUP_KEEP_FOR="28day" + RUN bf-install -VOLUME [ "/data", "/backup" ] +VOLUME [ "/backup", "/data" ] diff --git a/13/overlay/tmp/POSTGRESQL_BUILD b/13/overlay/tmp/POSTGRESQL_BUILD index 197b9b2..8b980ab 100644 --- a/13/overlay/tmp/POSTGRESQL_BUILD +++ b/13/overlay/tmp/POSTGRESQL_BUILD @@ -1 +1 @@ -13.12-r0 \ No newline at end of file +13.13-r0 \ No newline at end of file diff --git a/13/overlay/tmp/POSTGRESQL_MINOR b/13/overlay/tmp/POSTGRESQL_MINOR index 2476028..1f8009c 100644 --- a/13/overlay/tmp/POSTGRESQL_MINOR +++ b/13/overlay/tmp/POSTGRESQL_MINOR @@ -1 +1 @@ -13.12 \ No newline at end of file +13.13 \ No newline at end of file diff --git a/14/Dockerfile b/14/Dockerfile index c0470b2..5138a2d 100644 --- a/14/Dockerfile +++ b/14/Dockerfile @@ -1,21 +1,21 @@ -FROM bfren/alpine-s6:alpine3.18-4.5.9 +FROM bfren/alpine-s6:alpine3.18-5.0.5 LABEL org.opencontainers.image.source="https://github.com/bfren/docker-postgresql" ARG BF_IMAGE ARG BF_VERSION -ENV \ - # set to "1" to compress backup sql files - POSTGRESQL_BACKUP_COMPRESS_FILES="0" \ - # the number of days after which backups will be deleted - POSTGRESQL_BACKUP_KEEP_FOR_DAYS="28" - EXPOSE 5432 COPY ./overlay / COPY ./14/overlay / +ENV \ + # set to "1" to compress backup sql files + BF_PG_BACKUP_COMPRESS_FILES="0" \ + # the duration for which backups will be kept + BF_PG_BACKUP_KEEP_FOR="28day" + RUN bf-install -VOLUME [ "/data", "/backup" ] +VOLUME [ "/backup", "/data" ] diff --git a/14/overlay/tmp/POSTGRESQL_BUILD b/14/overlay/tmp/POSTGRESQL_BUILD index 4ee21b4..595925a 100644 --- a/14/overlay/tmp/POSTGRESQL_BUILD +++ b/14/overlay/tmp/POSTGRESQL_BUILD @@ -1 +1 @@ -14.9-r0 \ No newline at end of file +14.10-r0 \ No newline at end of file diff --git a/14/overlay/tmp/POSTGRESQL_MINOR b/14/overlay/tmp/POSTGRESQL_MINOR index 94837c4..d3a61db 100644 --- a/14/overlay/tmp/POSTGRESQL_MINOR +++ b/14/overlay/tmp/POSTGRESQL_MINOR @@ -1 +1 @@ -14.9 \ No newline at end of file +14.10 \ No newline at end of file diff --git a/15/Dockerfile b/15/Dockerfile index b4e77e8..2569394 100644 --- a/15/Dockerfile +++ b/15/Dockerfile @@ -1,21 +1,21 @@ -FROM bfren/alpine-s6:alpine3.18-4.5.9 +FROM bfren/alpine-s6:alpine3.18-5.0.5 LABEL org.opencontainers.image.source="https://github.com/bfren/docker-postgresql" ARG BF_IMAGE ARG BF_VERSION -ENV \ - # set to "1" to compress backup sql files - POSTGRESQL_BACKUP_COMPRESS_FILES="0" \ - # the number of days after which backups will be deleted - POSTGRESQL_BACKUP_KEEP_FOR_DAYS="28" - EXPOSE 5432 COPY ./overlay / COPY ./15/overlay / +ENV \ + # set to "1" to compress backup sql files + BF_PG_BACKUP_COMPRESS_FILES="0" \ + # the duration for which backups will be kept + BF_PG_BACKUP_KEEP_FOR="28day" + RUN bf-install -VOLUME [ "/data", "/backup" ] +VOLUME [ "/backup", "/data" ] diff --git a/15/overlay/tmp/POSTGRESQL_BUILD b/15/overlay/tmp/POSTGRESQL_BUILD index c50dc6e..bbab991 100644 --- a/15/overlay/tmp/POSTGRESQL_BUILD +++ b/15/overlay/tmp/POSTGRESQL_BUILD @@ -1 +1 @@ -15.4-r0 \ No newline at end of file +15.5-r0 \ No newline at end of file diff --git a/15/overlay/tmp/POSTGRESQL_MINOR b/15/overlay/tmp/POSTGRESQL_MINOR index 441e3fb..474b680 100644 --- a/15/overlay/tmp/POSTGRESQL_MINOR +++ b/15/overlay/tmp/POSTGRESQL_MINOR @@ -1 +1 @@ -15.4 \ No newline at end of file +15.5 \ No newline at end of file diff --git a/Dockerfile.esh b/Dockerfile.esh index 5c6bab7..0be9b3d 100644 --- a/Dockerfile.esh +++ b/Dockerfile.esh @@ -1,21 +1,21 @@ -FROM bfren/alpine-s6:alpine3.18-<%= ${BASE_REVISION} %> +FROM bfren/alpine-s6:alpine3.18-<%= ${BASE_VERSION} %> LABEL org.opencontainers.image.source="https://github.com/bfren/docker-postgresql" ARG BF_IMAGE ARG BF_VERSION -ENV \ - # set to "1" to compress backup sql files - POSTGRESQL_BACKUP_COMPRESS_FILES="0" \ - # the number of days after which backups will be deleted - POSTGRESQL_BACKUP_KEEP_FOR_DAYS="28" - EXPOSE 5432 COPY ./overlay / COPY ./<%= ${POSTGRESQL_MAJOR} %>/overlay / +ENV \ + # set to "1" to compress backup sql files + BF_PG_BACKUP_COMPRESS_FILES="0" \ + # the duration for which backups will be kept + BF_PG_BACKUP_KEEP_FOR="28day" + RUN bf-install -VOLUME [ "/data", "/backup" ] +VOLUME [ "/backup", "/data" ] diff --git a/README.md b/README.md index 26aa0d5..c282767 100644 --- a/README.md +++ b/README.md @@ -40,29 +40,28 @@ See [For Backups](#for-backups) for configuration variables. ### For Backups -| Variable | Values | Description | Default | -| ---------------------------------- | ---------------------------- | -------------------------------------------------------- | ------- | -| `POSTGRESQL_BACKUP_COMPRESS_FILES` | 0 or 1 | Whether or not to compress backup files (using gzip). | 0 | -| `POSTGRESQL_BACKUP_KEEP_FOR_DAYS` | 0: keep forever
Num: days | How many days to keep backups before auto-deleting them. | 14 | +| Variable | Values | Description | Default | +| ----------------------------- | ------------- | ----------------------------------------------------- | --------- | +| `PG_BACKUP_COMPRESS_FILES` | 0 or 1 | Whether or not to compress backup files (using bzip). | 0 | +| `BF_PG_BACKUP_KEEP_FOR` | Nu duration | The length of time to keep backups. | 28day | ### For Database -| Variable | Values | Description | Default | -| --------------------- | ------ | ----------------------------------------------------------------------------------------- | ----------------- | -| `POSTGRESQL_USERNAME` | string | Application username - will be used as database name if `POSTGRESQL_DATABASE` is not set. | *None* - required | -| `POSTGRESQL_PASSWORD` | string | Application password. | *None* - required | -| `POSTGRESQL_DATABASE` | string | Database name(s) - multiple databases can be separated by a comma. | *None* | +| Variable | Values | Description | Default | +| ----------------- | ------ | -------------------------------------------------------------------------------------------------------- | --------- | +| `PG_APPLICATION` | string | Application name - will be used as `PG_DATABASE`, `PG_PASSWORD` and `PG_USERNAME` if they are not set. | *None* | +| `PG_DATABASE` | string | Database name(s) - multiple databases can be separated by a comma. | *None* | +| `PG_PASSWORD` | string | Application password. | *None* | +| `PG_USERNAME` | string | Application username. | *None* | ## Helper Functions -| Function | Purpose | Usage | -| ------------ | ---------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | -| `db-backup` | Run backup manually. | `docker exec <> db-backup` | -| `db-exists` | Echoes '0' or '1' depending on whether or not the specified database exists on the server. | `docker exec <> db-exists "foo"` | -| `db-export` | Dumps the specified database as a SQL file to the root of the `/backup` volume. | `docker exec <> db-export <>` | -| `db-import` | Executes all files in the root of the `/backup` volume. | `docker exec <> db-import` | -| `db-restore` | Deletes all files in `/data` volume, then shuts container down - on restart, the container will restore from the specified backup. | `docker exec <> db-restore 202107180500` | -| `db-stop` | Stops the database server (will automatically terminate the container). | `docker exec <> db-stop` | +| Function | Arguments | Purpose | Usage | +| ------------- | ----------------- | ------------------------------------------------------------------------------------- | ----------------------------------------------------- | +| `pg-dump` | *None* | Run backup manually. | `docker exec <> pg-dump` | +| `pg-export` | 1: Database name | Dumps the specified database as a SQL file to the root of the `/backup` volume. | `docker exec <> pg-export <>` | +| `pg-import` | 1: Database name | Executes all files in the root of the `/backup` volume. | `docker exec <> pg-import <>` | +| `pg-restore` | 1: Backup set | Deletes all files in `/data` volume, then restores from the specified backup dump. | `docker exec <> pg-restore 202107180500` | ## Licence diff --git a/VERSION b/VERSION index 47ccbfa..56fea8a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.3.29 \ No newline at end of file +3.0.0 \ No newline at end of file diff --git a/VERSION_MAJOR b/VERSION_MAJOR index d8263ee..e440e5c 100644 --- a/VERSION_MAJOR +++ b/VERSION_MAJOR @@ -1 +1 @@ -2 \ No newline at end of file +3 \ No newline at end of file diff --git a/VERSION_MINOR b/VERSION_MINOR index c0943d3..f398a20 100644 --- a/VERSION_MINOR +++ b/VERSION_MINOR @@ -1 +1 @@ -2.3 \ No newline at end of file +3.0 \ No newline at end of file diff --git a/generate-dockerfiles.sh b/generate-dockerfiles.sh index 100cbdc..e0ac7a1 100755 --- a/generate-dockerfiles.sh +++ b/generate-dockerfiles.sh @@ -4,8 +4,8 @@ set -euo pipefail docker pull bfren/alpine -BASE_REVISION="4.5.9" -echo "Base: ${BASE_REVISION}" +BASE_VERSION="5.0.5" +echo "Base: ${BASE_VERSION}" POSTGRESQL_VERSIONS="12 13 14 15" for V in ${POSTGRESQL_VERSIONS} ; do @@ -17,7 +17,7 @@ for V in ${POSTGRESQL_VERSIONS} ; do -e BF_DEBUG=0 \ bfren/alpine esh \ "/ws/Dockerfile.esh" \ - BASE_REVISION=${BASE_REVISION} \ + BASE_VERSION=${BASE_VERSION} \ POSTGRESQL_MAJOR=${V} ) diff --git a/overlay/etc/bf/ch.d/10-postgresql b/overlay/etc/bf/ch.d/10-postgresql index 4177848..8fd4af9 100644 --- a/overlay/etc/bf/ch.d/10-postgresql +++ b/overlay/etc/bf/ch.d/10-postgresql @@ -1,4 +1,3 @@ -/backup postgres:postgres 0770 0750 -/data postgres:postgres 0770 0750 -/run/postgresql postgres:postgres 0770 0750 -/usr/bin/bf/db-exists root:root 0555 +/backup postgres:postgres 0600 0700 +/data postgres:postgres 0600 0700 +/run/postgresql postgres:postgres 0600 0700 diff --git a/overlay/etc/bf/init.d/10-env b/overlay/etc/bf/init.d/10-env deleted file mode 100644 index 6b230d9..0000000 --- a/overlay/etc/bf/init.d/10-env +++ /dev/null @@ -1,26 +0,0 @@ -#!/command/with-contenv sh - -set -euo pipefail -export BF_E=`basename ${0}` - - -#====================================================================================================================== -# Add environment variables. -#====================================================================================================================== - -# Library configuration -bf-env "POSTGRESQL_LIB" "${BF_LIB}/postgresql" - -POSTGRESQL_BACKUP="/backup" -bf-env "POSTGRESQL_DATA" "/data" -bf-env "POSTGRESQL_BACKUP" "${POSTGRESQL_BACKUP}" - -bf-env "POSTGRESQL_BACKUP_FILENAME" "dump" -bf-env "POSTGRESQL_RESTORE" "${POSTGRESQL_BACKUP}/restore.sql" - -bf-env "POSTGRESQL_SERVER_VERSION" `cat /usr/libexec/postgresql/PG_VERSION` - -PG_VERSION="/data/PG_VERSION" -if [ -f "${PG_VERSION}" ]; then - bf-env "POSTGRESQL_DATA_VERSION" `cat ${PG_VERSION}` -fi diff --git a/overlay/etc/bf/init.d/10-env.nu b/overlay/etc/bf/init.d/10-env.nu new file mode 100644 index 0000000..3fa91c8 --- /dev/null +++ b/overlay/etc/bf/init.d/10-env.nu @@ -0,0 +1,30 @@ +use bf +bf env load + +# Set environment variables +def main [] { + let data = "/data" + bf env set PG_DATA $data + bf env set PG_DATA_CONF $"($data)/postgresql.conf" + bf env set PG_DATA_HBA_CONF $"($data)/pg_hba.conf" + + let backup = "/backup" + let backup_basename = "dump" + bf env set PG_BACKUP $backup + bf env set PG_DUMP_BASENAME $backup_basename + bf env set PG_DUMP_FILE_WITHOUT_EXT $"($backup)/($backup_basename)" + + let version = "PG_VERSION" + let data_version_file = $"($data)/($version)" + bf env set PG_DATA_VERSION (bf fs read --quiet $data_version_file) + bf env set PG_DATA_VERSION_FILE $data_version_file + bf env set PG_SERVER_VERSION (bf fs read --quiet $"/usr/libexec/postgresql/($version)") + + let application = bf env --safe PG_APPLICATION + bf env set PG_USERNAME (bf env PG_USERNAME $application) + bf env set PG_PASSWORD (bf env PG_PASSWORD $application) + bf env set PG_DATABASE (bf env PG_DATABASE $application) + + # return nothing + return +} diff --git a/overlay/etc/bf/init.d/11-user b/overlay/etc/bf/init.d/11-user deleted file mode 100644 index 3c75ba8..0000000 --- a/overlay/etc/bf/init.d/11-user +++ /dev/null @@ -1,31 +0,0 @@ -#!/command/with-contenv sh - -set -euo pipefail -export BF_E=`basename ${0}` - - -#====================================================================================================================== -# Check for application user and password. -#====================================================================================================================== - -[[ -z "${POSTGRESQL_USERNAME-}" || -z "${POSTGRESQL_PASSWORD-}" ]] \ - && bf-error "POSTGRESQL_USERNAME and POSTGRESQL_PASSWORD must be set." - - -#====================================================================================================================== -# Add user with password. -#====================================================================================================================== - -# add user if it doesn't exist -if [ -z "$(getent passwd ${POSTGRESQL_USERNAME})" ] ; then - - bf-echo "Adding user ${POSTGRESQL_USERNAME}..." - bf-adduser ${POSTGRESQL_USERNAME} 1001 - echo -e "${POSTGRESQL_PASSWORD}\n${POSTGRESQL_PASSWORD}" | passwd ${POSTGRESQL_USERNAME} - bf-done - -else - - bf-debug "User ${POSTGRESQL_USERNAME} exists." - -fi diff --git a/overlay/etc/bf/init.d/11-user.nu b/overlay/etc/bf/init.d/11-user.nu new file mode 100644 index 0000000..48c25c1 --- /dev/null +++ b/overlay/etc/bf/init.d/11-user.nu @@ -0,0 +1,20 @@ +use bf +bf env load + +# Ensure specified user exists +def main [] { + # get variables + let user = bf env PG_USERNAME + let pass = bf env PG_PASSWORD + if $user == "" or $pass == "" { bf write error "You must set PG_USERNAME and PG_PASSWORD (or PG_APPLICATION)." } + + # if user exists, return + if (bf user exists $user) { + bf write $"User ($user) already exists." + return + } + + # create user account and set password + bf user add --uid 1001 $user + { $"($pass)\n($pass)" | ^passwd $user } | bf handle +} diff --git a/overlay/etc/bf/init.d/12-postgresql-init b/overlay/etc/bf/init.d/12-postgresql-init deleted file mode 100644 index 83daed6..0000000 --- a/overlay/etc/bf/init.d/12-postgresql-init +++ /dev/null @@ -1,96 +0,0 @@ -#!/command/with-contenv sh - -set -euo pipefail -export BF_E=`basename ${0}` - - -#====================================================================================================================== -# Start server. -#====================================================================================================================== - -start () { - - # initialise data directory - bf-debug "Running db-init." - s6-setuidgid postgres initdb -D "${POSTGRESQL_DATA}" - - # generate configuration - db-generate-config - - # start server - bf-echo "Starting PostgreSQL for initialisation." - s6-setuidgid postgres pg_ctl start -D "${POSTGRESQL_DATA}" - -} - - -#====================================================================================================================== -# Stop server. -#====================================================================================================================== - -stop () { - bf-echo "Stopping PostgreSQL." - s6-setuidgid postgres pg_ctl stop -D "${POSTGRESQL_DATA}" -} - - -#====================================================================================================================== -# Check data version against server version. -#====================================================================================================================== - -[[ -f "/data/PG_VERSION" ]] && POSTGRESQL_DATA_VERSION=`cat /data/PG_VERSION` -POSTGRESQL_SERVER_VERSION=`cat /usr/libexec/postgresql/PG_VERSION` - -if [[ -z "${POSTGRESQL_DATA_VERSION-}" ]] || [[ "${POSTGRESQL_DATA_VERSION}" = "${POSTGRESQL_SERVER_VERSION}" ]] ; then - bf-debug "Versions ok." -else - bf-notok "PostgreSQL server (v${POSTGRESQL_SERVER_VERSION}) does not match data (v${POSTGRESQL_DATA_VERSION})." - bf-notok "You must upgrade the data or use a version of this image that matches the data version." - bf-notok "Container will now quit." - s6-svscanctl -t ${S6_SERVICES} - exit 1 -fi - - -#====================================================================================================================== -# Check for restore file. -#====================================================================================================================== - -if [ -f "${POSTGRESQL_RESTORE}" ] ; then - - # delete existing files - bf-debug "Deleting existing files." - bf-rmrf "${POSTGRESQL_DATA}/*" - - # run restore - start - bf-debug "Restoring server." - s6-setuidgid postgres psql -f "${POSTGRESQL_RESTORE}" - stop - - # delete restore file - rm "${POSTGRESQL_RESTORE}" - -fi - - -#====================================================================================================================== -# Run library init executable. -#====================================================================================================================== - -if [ ! -f ${POSTGRESQL_DATA}/PG_VERSION ] ; then - - # run init - start - bf-debug "Initialising server." - s6-setuidgid postgres ${POSTGRESQL_LIB}/init - stop - -fi - - -#====================================================================================================================== -# Be friendly. -#====================================================================================================================== - -bf-debug "Server ready." diff --git a/overlay/etc/bf/init.d/12-postgresql-init.nu b/overlay/etc/bf/init.d/12-postgresql-init.nu new file mode 100644 index 0000000..e0b54ab --- /dev/null +++ b/overlay/etc/bf/init.d/12-postgresql-init.nu @@ -0,0 +1,54 @@ +use bf +use bf-postgresql +use bf-s6 +bf env load + +def main [] { + # check data version against server version + let data_version = bf env PG_DATA_VERSION 0 + let server_version = bf env PG_SERVER_VERSION 0 + if $data_version == $server_version { + bf write debug "Versions match." + } else if $data_version > 0 { + bf write notok $"PostgreSQL server v($server_version) does not match data v($data_version)." + bf write notok "You must upgrade the data or use a version of this image that matches the data version." + bf write notok "This container will now quit." + bf-s6 cont terminate + exit 1 + } + + # run restore + bf-postgresql restore + + # create data if it doesn't exist + if (bf env PG_DATA_VERSION_FILE | bf fs is_not_file) { create_empty } + + # ready to go! + bf write ok "Server ready." +} + +# Create empty database(s) +def create_empty [] { + bf write "Initialising empty data." create_empty + + # get variables + let user = bf env PG_USERNAME + let pass = bf env PG_PASSWORD + + # start server + bf-postgresql ctl init + bf-postgresql ctl start + + # create role for user + bf write debug $" .. creating role ($user)" + { $"($pass)\n($pass)" | ^pg createuser --superuser --pwprompt $user } | bf handle create_empty + + # create database(s) + bf env PG_DATABASE | split row "," | each {|x| + bf write debug $" .. creating database ($x)" + { ^pg createdb $"($x)" $"--owner=($user)" } | bf handle create_empty + } + + # stop server + bf-postgresql ctl stop +} diff --git a/overlay/etc/bf/init.d/13-cron b/overlay/etc/bf/init.d/13-cron deleted file mode 100644 index d69ef22..0000000 --- a/overlay/etc/bf/init.d/13-cron +++ /dev/null @@ -1,18 +0,0 @@ -#!/command/with-contenv sh - -set -euo pipefail -export BF_E=`basename ${0}` - - -#====================================================================================================================== -# Generate crontab and append backup task - set the minutes to a random number so multiple containers on one host don't -# all try to backup at the same time. -#====================================================================================================================== - -bf-echo "Generating crontab..." -CRONTAB=/etc/crontabs/root -bf-esh \ - ${BF_TEMPLATES}/crontab.esh \ - ${CRONTAB} -echo "$((1 + ${RANDOM} % 59)) */8 * * * db-backup" >> /etc/crontabs/root >> ${CRONTAB} -bf-done diff --git a/overlay/etc/bf/init.d/13-cron.nu b/overlay/etc/bf/init.d/13-cron.nu new file mode 100644 index 0000000..f23e733 --- /dev/null +++ b/overlay/etc/bf/init.d/13-cron.nu @@ -0,0 +1,6 @@ +use bf +use bf-s6 +bf env load + +# Append backup task to crontab +def main [] { bf-s6 crontab append --min (random int 1..59) --hour "*/8" "pg-dump" } diff --git a/overlay/etc/nu/scripts/bf-postgresql/conf.nu b/overlay/etc/nu/scripts/bf-postgresql/conf.nu new file mode 100644 index 0000000..945b64a --- /dev/null +++ b/overlay/etc/nu/scripts/bf-postgresql/conf.nu @@ -0,0 +1,7 @@ +use bf + +# Generate data configuration files +export def generate [] { + bf esh template (bf env PG_DATA_CONF) + bf esh template (bf env PG_DATA_HBA_CONF) +} diff --git a/overlay/etc/nu/scripts/bf-postgresql/ctl.nu b/overlay/etc/nu/scripts/bf-postgresql/ctl.nu new file mode 100644 index 0000000..812099f --- /dev/null +++ b/overlay/etc/nu/scripts/bf-postgresql/ctl.nu @@ -0,0 +1,28 @@ +use bf +use conf.nu + +# Execute a pg_ctl command as the PostgreSQL user, using the correct data directory +def cmd [ + command: string # The pg_ctl command to run +] { + try { + ^pg pg_ctl $command -D $"(bf env PG_DATA)" + } catch { + bf write error $"There was an error running pg_ctl ($command)." + } +} + +# Use pg_ctl to initialise PostgreSQL server and then regenerate configuration +export def init [] { cmd init ; conf generate } + +# Use pg_ctl to restart PostgreSQL server +export def restart [] { cmd restart } + +# Use pg_ctl to start PostgreSQL status +export def start [] { cmd start } + +# Use pg_ctl to get PostgreSQL server status +export def status [] { cmd status } + +# Use pg_ctl to stop the PostgreSQL server +export def stop [] { cmd stop } diff --git a/overlay/etc/nu/scripts/bf-postgresql/db.nu b/overlay/etc/nu/scripts/bf-postgresql/db.nu new file mode 100644 index 0000000..768f0e3 --- /dev/null +++ b/overlay/etc/nu/scripts/bf-postgresql/db.nu @@ -0,0 +1,34 @@ +use bf + +# Returns true if database $name exists in the cluster +export def exists [ + name: string # Database name +] { + $name in (get_all) +} + +# Dump a database +export def dump [ + name: string # The name of the database to dump + file: string # The path to save the dump script to +] { + # ensure the database exists + if not (exists $name) { bf write error $"Database ($name) does not exist." export } + + # dump database and save to specified file + { ^pg pg_dump --clean --if-exists $name } | bf handle -s {|x| $x | save --force $file } ctl/dump +} + +# Get a list of databases, ignoring system databases +export def get_all [] { + # ignore these database + let ignore = [ + "postgres" + "template0" + "template1" + ] + + # execute SQL and process response + let sql = "SELECT datname FROM pg_database;" + { ^pg psql -c $sql | ^tail -n+3 | ^head -n-2 | ^xargs } | bf handle -d "Selecting PostgreSQL databases" ctl/get_all | split row " " | where {|x| $x not-in $ignore } | compact +} diff --git a/overlay/etc/nu/scripts/bf-postgresql/dump.nu b/overlay/etc/nu/scripts/bf-postgresql/dump.nu new file mode 100644 index 0000000..a9ad8dd --- /dev/null +++ b/overlay/etc/nu/scripts/bf-postgresql/dump.nu @@ -0,0 +1,74 @@ +use bf +use db.nu + +# Backup the cluster to a dump file, compressing if required +export def main [] { + # set variables + bf write $"Dumping data cluster." dump + + # create backup directories + let backup_dir = create_backup_dir + let temp_dir = create_temp_dir + + # dump cluster and save to dump file + let dump_file = $"($temp_dir)/(bf env PG_DUMP_BASENAME).sql" + bf write debug $" .. to ($dump_file)" dump + { ^pg pg_dumpall --clean --if-exists } | bf handle -s {|x| $x | save --force $dump_file } dump + + # compress dump file + if (bf env check PG_BACKUP_COMPRESS_FILES) { + bf write debug " .. compressing dump file" dump + { ^pg bzip2 $dump_file } | bf handle dump + } + + # get list of individual databases and back them up + db get_all | each {|x| + # dump database to backup file + bf write debug $" .. backing up database ($x)" dump + let backup_file = $"($temp_dir)/($x).sql" + db dump $x $backup_file + + # compress backup file + if (bf env check PG_BACKUP_COMPRESS_FILES) { + bf write debug " compressing backup file" dump + { ^pg bzip2 $backup_file } | bf handle dump + } + } + + # move files to backup directory + bf write debug $" .. moving files to ($backup_dir)" dump + mv $"($temp_dir)/*" $backup_dir + + # delete temporary directory + bf write debug $" .. deleting ($temp_dir)" dump + rm -rf $temp_dir + + # cleanup old backup files + bf write debug " .. removing expired backup files" dump + bf del old --type d (bf env PG_BACKUP) (bf env PG_BACKUP_KEEP_FOR | into duration) + + # if we get here there have been no errors + bf write ok "Done." dump +} + +# Create a backup directory +def create_backup_dir [] { + # create temporary directory + let date = date now | format date "%Y%m%d%H%M" + let dir = $"(bf env PG_BACKUP)/($date)" + mkdir $dir + + # return if directory exists + if ($dir | bf fs is_not_dir) { bf write error "Unable to create backup directory." dump/create_backup_dir } + $dir +} + +# Create a temporary directory +def create_temp_dir [] { + # create temporary directory + let dir = { ^mktemp -d -t backup.XXXXXX } | bf handle dump/create_temp_dir + + # return if directory exists + if ($dir | bf fs is_not_dir) { bf write error "Unable to create temporary directory." dump/create_temp_dir } + $dir +} diff --git a/overlay/etc/nu/scripts/bf-postgresql/export.nu b/overlay/etc/nu/scripts/bf-postgresql/export.nu new file mode 100644 index 0000000..40cba47 --- /dev/null +++ b/overlay/etc/nu/scripts/bf-postgresql/export.nu @@ -0,0 +1,17 @@ +use bf +use db.nu + +# Database $name will be exported as a sql file to the root backup directory +export def main [ + name: string # The name of the database to export +] { + # create path to export file + let export_file = $"(bf env PG_BACKUP)/($name).sql" + + # dump database to file + bf write $"Dumping ($name) to ($export_file)." export + db dump $name $export_file + + # if we get here there have been no errors + bf write ok "Done." export +} diff --git a/overlay/etc/nu/scripts/bf-postgresql/import.nu b/overlay/etc/nu/scripts/bf-postgresql/import.nu new file mode 100644 index 0000000..ad6ecf0 --- /dev/null +++ b/overlay/etc/nu/scripts/bf-postgresql/import.nu @@ -0,0 +1,26 @@ +use bf +use db.nu +use ctl.nu + +# A file named $name.sql will be used from the root of the /backup directory +export def main [ + name: string # The name of the database to import +] { + # ensure the file exists + let import_file = $"(bf env PG_BACKUP)/($name).sql" + if ($import_file | bf fs is_not_file) { bf write error $"Cannot find import file ($import_file)." import } + + # ensure the database exists + bf write $"Importing database ($name) from sql file." import + if not (db exists $name) { + bf write debug " .. creating database" + { ^pg createdb $"($name)" $"--owner=(bf env PG_USERNAME)" } | bf handle import + } + + # execute script file using psql + bf write debug " .. executing script file" import + { ^pg psql -f $import_file $name } | bf handle import + + # if we get here there have been no errors + bf write ok "Done." +} diff --git a/overlay/etc/s6-overlay/s6-rc.d/postgres/dependencies.d/init b/overlay/etc/nu/scripts/bf-postgresql/mod.nu similarity index 100% rename from overlay/etc/s6-overlay/s6-rc.d/postgres/dependencies.d/init rename to overlay/etc/nu/scripts/bf-postgresql/mod.nu diff --git a/overlay/etc/nu/scripts/bf-postgresql/restore.nu b/overlay/etc/nu/scripts/bf-postgresql/restore.nu new file mode 100644 index 0000000..298c2db --- /dev/null +++ b/overlay/etc/nu/scripts/bf-postgresql/restore.nu @@ -0,0 +1,94 @@ +use bf +use ctl.nu + +# the name of the restoring environment variable +const restoring = "PG_RESTORING" + +# Returns true if we are restoring a database backup +export def is_restoring [] { bf env check $restoring } + +# Restore the data from a dump file +export def main [] { + # if dump file does not exist, return + let dump_file = check_dump_file + if not $dump_file.exists { + bf write "Dump file not found." restore + return + } + + # mark as restoring so the container is not brought down when we stop the PostgreSQL service + bf write "Restoring cluster from dump file." restore + bf env set $restoring 1 + + # stop the PostgreSQL service + bf write debug " .. stopping PostgreSQL service" restore + ctl stop + + # delete data files + let data = bf env PG_DATA + bf write debug " .. deleting data files" restore + rm -rf $"($data)/*" + + # restart the PostgreSQL service + bf write debug " .. reinitialising cluster" restore + ctl init + ctl start + + # run restore + bf write debug " .. restoring data" restore + { ^pg psql -f $dump_file.path } | bf handle restore + + # stop the PostgreSQL service + bf write debug " .. stopping PostgreSQL service" restore + ctl stop + + # unset restoring variable and delete dump file + bf env unset $restoring + rm -f $dump_file.path + + # if we get here there have been no errors + bf write ok "Done." restore +} + +# Get details of a dump file - returns a record with the following values, having decompressed the file if required +# - exists: bool Whether or not a dump file exists +# - path: string Absolute path to the dump file if it exists, or null +def check_dump_file [] { + # get file paths + let file = bf env PG_DUMP_FILE_WITHOUT_EXT + let compressed_file = $"($file).bz2" + let sql_file = $"($file).sql" + + # if there is a compressed file, decompress it + if ($compressed_file | path exists) { + # Flags: + # -d Decompress + # -f Force + { ^pg bzip2 -d -f $compressed_file } | bf handle restore/check_dump_file + } + + # if the sql file exists, return it + if ($sql_file | path exists) { + return {exists: true, path: $sql_file} + } else { + return {exists: false} + } +} + +# Restore cluster from a backup dump file +export def from [ + backup: string # Restore the dump file this backup directory +] { + # ensure requested backup directory exists + let backup_dir = $"(bf env PG_BACKUP)/($backup)" + if ($backup_dir | bf fs is_not_dir) { bf write error $"Backup directory ($backup_dir) does not exist." restore/from } + + # ensure a dump file exists within requested backup directory + let dump_file = glob $"/backup/($backup)/(bf env PG_DUMP_BASENAME).*" | str join + if ($dump_file | bf fs is_not_file) { bf write error $"Cannot find a dump file in ($backup_dir)." restore/from } + + # copy dump file to backup root and run restore function + bf write $"Copying dump file from backup ($backup)." restore/from + cp --force $dump_file (bf env PG_BACKUP) + main +} diff --git a/overlay/etc/nu/scripts/bf-postgresql/run.nu b/overlay/etc/nu/scripts/bf-postgresql/run.nu new file mode 100644 index 0000000..95b2f17 --- /dev/null +++ b/overlay/etc/nu/scripts/bf-postgresql/run.nu @@ -0,0 +1,22 @@ +use bf +use restore.nu + +# Run preflight checks before executing process +export def preflight [] { + # load environment + bf env load + + # manually set executing script + bf env x_set --override run postgresql + + # exit if we are restoring + if (restore is_restoring) { + let for = 5sec + bf write $"A backup is being restored so sleep for ($for)." + sleep $for + exit 0 + } + + # if we get here we are ready to start PostgreSQL + bf write "Starting PostgreSQL." +} diff --git a/overlay/etc/s6-overlay/s6-rc.d/postgres/finish b/overlay/etc/s6-overlay/s6-rc.d/postgres/finish deleted file mode 100644 index e37c787..0000000 --- a/overlay/etc/s6-overlay/s6-rc.d/postgres/finish +++ /dev/null @@ -1,12 +0,0 @@ -#!/command/with-contenv sh - -set -euo pipefail -export BF_E="${PWD##*/}/$(basename ${0})" - - -#====================================================================================================================== -# Show helpful log message. -#====================================================================================================================== - -s6-setuidgid postgres ${POSTGRESQL_LIB}/finish -bf-svc-finish -t diff --git a/overlay/etc/s6-overlay/s6-rc.d/postgres/run b/overlay/etc/s6-overlay/s6-rc.d/postgres/run deleted file mode 100644 index 4b70b6f..0000000 --- a/overlay/etc/s6-overlay/s6-rc.d/postgres/run +++ /dev/null @@ -1,12 +0,0 @@ -#!/command/with-contenv sh - -set -euo pipefail -export BF_E="${PWD##*/}/$(basename ${0})" - - -#====================================================================================================================== -# Run as PostgreSQL user. -#====================================================================================================================== - -bf-echo "Starting PostgreSQL server." -s6-setuidgid postgres postgres -D "${POSTGRESQL_DATA}" diff --git a/overlay/etc/s6-overlay/s6-rc.d/user/contents.d/postgres b/overlay/etc/s6-overlay/s6-rc.d/postgresql/dependencies.d/init similarity index 100% rename from overlay/etc/s6-overlay/s6-rc.d/user/contents.d/postgres rename to overlay/etc/s6-overlay/s6-rc.d/postgresql/dependencies.d/init diff --git a/overlay/etc/s6-overlay/s6-rc.d/postgresql/finish b/overlay/etc/s6-overlay/s6-rc.d/postgresql/finish new file mode 100644 index 0000000..9b91aa7 --- /dev/null +++ b/overlay/etc/s6-overlay/s6-rc.d/postgresql/finish @@ -0,0 +1,21 @@ +#!/usr/bin/nu + +use bf +use bf-postgresql +use bf-s6 +bf env load -x postgresql + +# Stop server and terminate container, unless we are restoring from a backup +def main [...args] { + # check whether or not we are restoring from a backup + if (bf-postgresql restore is_restoring) { + bf write debug "A restore operation is running: do not stop PostgreSQL or terminate the container." + exit 0 + } + + # stop server gracefully + bf-postgresql ctl stop + + # terminate container + bf-s6 svc finish --terminate +} diff --git a/overlay/usr/bin/bf/db-exists b/overlay/etc/s6-overlay/s6-rc.d/postgresql/run similarity index 65% rename from overlay/usr/bin/bf/db-exists rename to overlay/etc/s6-overlay/s6-rc.d/postgresql/run index c20e246..858026e 100644 --- a/overlay/usr/bin/bf/db-exists +++ b/overlay/etc/s6-overlay/s6-rc.d/postgresql/run @@ -1,19 +1,18 @@ -#!/command/with-contenv sh +#!/bin/withenv sh set -euo pipefail -export BF_E=`basename ${0}` #====================================================================================================================== -# Check arguments. -# 1 Database name +# Run preflight checks #====================================================================================================================== -[[ -z "${1-}" ]] && bf-error "You must provide the name of the database to check." +nu -c "use bf-postgresql run ; run preflight" #====================================================================================================================== -# Query psql to see if database exists. +# Run as PostgreSQL user +# -D path to the data directory #====================================================================================================================== -psql -U postgres -l | grep -w "${1}" | wc -l +pg postgres -D "${BF_PG_DATA}" diff --git a/overlay/etc/s6-overlay/s6-rc.d/postgres/type b/overlay/etc/s6-overlay/s6-rc.d/postgresql/type similarity index 100% rename from overlay/etc/s6-overlay/s6-rc.d/postgres/type rename to overlay/etc/s6-overlay/s6-rc.d/postgresql/type diff --git a/overlay/etc/s6-overlay/s6-rc.d/user/contents.d/postgresql b/overlay/etc/s6-overlay/s6-rc.d/user/contents.d/postgresql new file mode 100644 index 0000000..e69de29 diff --git a/overlay/tmp/install b/overlay/tmp/install index bb3ca96..9fe9497 100644 --- a/overlay/tmp/install +++ b/overlay/tmp/install @@ -1,52 +1,26 @@ -#!/bin/sh +#!/usr/bin/nu -set -euo pipefail -export BF_E=`basename ${0}` +use bf +# Setup and install PostgreSQL +def main [] { + # add PostgreSQL user + bf user add postgres -#====================================================================================================================== -# Add postgres user. -#====================================================================================================================== + # get PostgreSQL version and install + cd /tmp + let version = bf fs read POSTGRESQL_BUILD + let major = $version | split row "." | first + bf write $"Installing PostgreSQL v($version)." + bf pkg install [$"postgresql($major)=($version)"] -bf-adduser postgres + # save PostgreSQL version to build log + bf build add PostgreSQL $version + # create run directory + bf write "Creating PostgreSQL run directory." + mkdir /run/postgresql -#====================================================================================================================== -# Get PostgreSQL version. -#====================================================================================================================== - -cd /tmp - -VERSION=$(cat POSTGRESQL_BUILD) -bf-echo "PostgreSQL version ${VERSION}." - - -#====================================================================================================================== -# Install PostgreSQL and dependencies. -#====================================================================================================================== - -bf-echo "Installing PostgreSQL v${VERSION}..." - -MAJOR_VERSION="$(echo ${VERSION} | cut -c 1-2)" -apk add --no-cache \ - postgresql${MAJOR_VERSION}=${VERSION} - -bf-done - - -#====================================================================================================================== -# Create PostgreSQL directories. -#====================================================================================================================== - -bf-echo "Creating PostgreSQL directories." - -mkdir /data -mkdir /backup -mkdir /run/postgresql - - -#====================================================================================================================== -# Store default crontab as a template. -#====================================================================================================================== - -cp /etc/crontabs/root /etc/bf/templates/crontab.esh + # add bf-postgresql module to config + bf config use bf-postgresql +} diff --git a/overlay/usr/bin/bf/db-backup b/overlay/usr/bin/bf/db-backup deleted file mode 100644 index 6d96302..0000000 --- a/overlay/usr/bin/bf/db-backup +++ /dev/null @@ -1,11 +0,0 @@ -#!/command/with-contenv sh - -set -euo pipefail -export BF_E=`basename ${0}` - - -#====================================================================================================================== -# Run library backup executable. -#====================================================================================================================== - -s6-setuidgid postgres ${POSTGRESQL_LIB}/backup diff --git a/overlay/usr/bin/bf/db-export b/overlay/usr/bin/bf/db-export deleted file mode 100644 index 05c4b2c..0000000 --- a/overlay/usr/bin/bf/db-export +++ /dev/null @@ -1,11 +0,0 @@ -#!/command/with-contenv sh - -set -euo pipefail -export BF_E=`basename ${0}` - - -#====================================================================================================================== -# Run library export executable with first argument. -#====================================================================================================================== - -s6-setuidgid postgres ${POSTGRESQL_LIB}/export "${1-}" diff --git a/overlay/usr/bin/bf/db-generate-config b/overlay/usr/bin/bf/db-generate-config deleted file mode 100644 index 98346cd..0000000 --- a/overlay/usr/bin/bf/db-generate-config +++ /dev/null @@ -1,11 +0,0 @@ -#!/command/with-contenv sh - -set -euo pipefail - - -#====================================================================================================================== -# Run library config executable. -#====================================================================================================================== - -bf-debug "Generating configuration files." "db-generate-config" -s6-setuidgid postgres ${POSTGRESQL_LIB}/generate-config diff --git a/overlay/usr/bin/bf/db-import b/overlay/usr/bin/bf/db-import deleted file mode 100644 index 1f09354..0000000 --- a/overlay/usr/bin/bf/db-import +++ /dev/null @@ -1,11 +0,0 @@ -#!/command/with-contenv sh - -set -euo pipefail -export BF_E=`basename ${0}` - - -#====================================================================================================================== -# Run library import executable. -#====================================================================================================================== - -s6-setuidgid postgres ${POSTGRESQL_LIB}/import diff --git a/overlay/usr/bin/bf/db-restore b/overlay/usr/bin/bf/db-restore deleted file mode 100644 index efafd6d..0000000 --- a/overlay/usr/bin/bf/db-restore +++ /dev/null @@ -1,39 +0,0 @@ -#!/command/with-contenv sh - -set -euo pipefail -export BF_E=`basename ${0}` - - -#====================================================================================================================== -# Check arguments. -# 1 Backup date -#====================================================================================================================== - -[[ -z "${1-}" ]] && bf-error "You must provide the date/time of the backup to restore." -DATE=${1} - - -#====================================================================================================================== -# Look for compressed dump file. -#====================================================================================================================== - -BACKUP_PATH="${POSTGRESQL_BACKUP}/${DATE}" -bf-echo "Looking for backup in ${BACKUP_PATH}..." - -COMPRESSED_DUMP_FILE="${BACKUP_PATH}/${POSTGRESQL_BACKUP_FILENAME}.gz" -if [ -f "${COMPRESSED_DUMP_FILE}" ] ; then - bf-debug " .. decompressing ${COMPRESSED_DUMP_FILE}" - gzip -d "${COMPRESSED_DUMP_FILE}" -fi - -DUMP_FILE="${BACKUP_PATH}/${POSTGRESQL_BACKUP_FILENAME}.sql" -[[ ! -f "${DUMP_FILE}" ]] && bf-error " .. ${DUMP_FILE} does not exist." -bf-ok " .. found ${DUMP_FILE}." - - -#====================================================================================================================== -# Move dump file to restore location and restart. -#====================================================================================================================== - -mv ${DUMP_FILE} ${POSTGRESQL_RESTORE} -bf-cont-terminate diff --git a/overlay/usr/bin/bf/db-stop b/overlay/usr/bin/bf/db-stop deleted file mode 100644 index cc359db..0000000 --- a/overlay/usr/bin/bf/db-stop +++ /dev/null @@ -1,11 +0,0 @@ -#!/command/with-contenv sh - -set -euo pipefail -export BF_E=`basename ${0}` - - -#====================================================================================================================== -# Run library finish executable. -#====================================================================================================================== - -s6-setuidgid postgres ${POSTGRESQL_LIB}/finish diff --git a/overlay/usr/bin/bf/healthcheck b/overlay/usr/bin/bf/healthcheck index f677c5d..1545b9b 100644 --- a/overlay/usr/bin/bf/healthcheck +++ b/overlay/usr/bin/bf/healthcheck @@ -1,14 +1,10 @@ -#!/command/with-contenv sh +#!/bin/withenv sh set -euo pipefail -export BF_E=`basename ${0}` #====================================================================================================================== -# Perform a basic sql command to check the server is running. +# Perform a basic sql command to check the server is running #====================================================================================================================== -CHECK=$(psql -U postgres -c "SELECT 1;" 2> /dev/null | tail -n3 | head -n1 | xargs || echo "0") - -[[ "${CHECK}" == "1" ]] && exit 0 -exit 1 +exit $(psql -U ${BF_PG_USERNAME} -c "SELECT 0;" 2> /dev/null | tail -n3 | head -n1 | xargs || echo "1") diff --git a/overlay/usr/lib/bf/postgresql/finish b/overlay/usr/bin/bf/pg similarity index 77% rename from overlay/usr/lib/bf/postgresql/finish rename to overlay/usr/bin/bf/pg index 7fd3c82..cf66a21 100644 --- a/overlay/usr/lib/bf/postgresql/finish +++ b/overlay/usr/bin/bf/pg @@ -1,10 +1,10 @@ -#!/bin/sh +#!/bin/withenv sh set -euo pipefail #====================================================================================================================== -# Stop the server gracefully. +# Run a command as postgres user #====================================================================================================================== -pg_ctl stop -D ${POSTGRESQL_DATA} +s6-setuidgid postgres "$@" diff --git a/overlay/usr/bin/bf/pg-dump b/overlay/usr/bin/bf/pg-dump new file mode 100644 index 0000000..c3c4936 --- /dev/null +++ b/overlay/usr/bin/bf/pg-dump @@ -0,0 +1,8 @@ +#!/usr/bin/nu + +use bf +use bf-postgresql +bf env load -x + +# Dump data cluster +def main [] { bf-postgresql dump } diff --git a/overlay/usr/bin/bf/pg-export b/overlay/usr/bin/bf/pg-export new file mode 100644 index 0000000..f1f795d --- /dev/null +++ b/overlay/usr/bin/bf/pg-export @@ -0,0 +1,12 @@ +#!/usr/bin/nu + +use bf +use bf-postgresql +bf env load -x + +# Export a database to a script file +def main [ + name: string # The name of the database to export +] { + bf-postgresql export $name +} diff --git a/overlay/usr/bin/bf/pg-import b/overlay/usr/bin/bf/pg-import new file mode 100644 index 0000000..97c9046 --- /dev/null +++ b/overlay/usr/bin/bf/pg-import @@ -0,0 +1,12 @@ +#!/usr/bin/nu + +use bf +use bf-postgresql +bf env load -x + +# Import a database from a script file +def main [ + name: string # The name of the database to import +] { + bf-postgresql import $name +} diff --git a/overlay/usr/bin/bf/pg-restore b/overlay/usr/bin/bf/pg-restore new file mode 100644 index 0000000..92b63c1 --- /dev/null +++ b/overlay/usr/bin/bf/pg-restore @@ -0,0 +1,12 @@ +#!/usr/bin/nu + +use bf +use bf-postgresql +bf env load -x + +# Restore the data from a dump file +def main [ + backup: string # Restore the dump file this backup directory +] { + bf-postgresql restore from $backup +} diff --git a/overlay/usr/lib/bf/postgresql/backup b/overlay/usr/lib/bf/postgresql/backup deleted file mode 100644 index 4a67620..0000000 --- a/overlay/usr/lib/bf/postgresql/backup +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/sh - -set -euo pipefail - - -#====================================================================================================================== -# Set variables. -#====================================================================================================================== - -DATE=$(date '+%Y%m%d%H%M') -bf-debug "Backup: ${DATE}." - - -#====================================================================================================================== -# Create temporary directory for backups. -#====================================================================================================================== - -TEMP_BACKUP_PATH=$(mktemp -d -t backup.XXXXXX) || bf-error "Unable to make temporary backup directory." -bf-echo "Backing up server to ${TEMP_BACKUP_PATH}..." - - -#====================================================================================================================== -# Dump database cluster and compress. -#====================================================================================================================== - -# dump cluster -DUMP_FILE="${TEMP_BACKUP_PATH}/${POSTGRESQL_BACKUP_FILENAME}.sql" -bf-debug " .. dumping cluster" -pg_dumpall > "${DUMP_FILE}" - -# compress file -if [ "${POSTGRESQL_BACKUP_COMPRESS_FILES}" = "1" ] ; then - bf-debug " .. compressing" - gzip ${DUMP_FILE} -fi - - -#====================================================================================================================== -# Get list of individual databases, dump and compress. -#====================================================================================================================== - -# remove header / footer from output -EXCLUDE="postgres|template0|template1" -bf-debug " .. excluding ${EXCLUDE} from individual backups" -DATABASES=$(psql -c "SELECT datname FROM pg_database;" | tail -n+3 | head -n-2 | grep -v -E "(${EXCLUDE})") - -# dump each database -for DATABASE in ${DATABASES} ; do - - # path to this database dump - DUMP_FILE="${TEMP_BACKUP_PATH}/${DATABASE}.sql" - - # dump database and continue on failure - bf-debug " .. dumping database ${DATABASE}" - pg_dump ${DATABASE} > ${DUMP_FILE}|| true - - # compress file - if [ "${POSTGRESQL_BACKUP_COMPRESS_FILES}" = "1" ] ; then - bf-debug " .. compressing" - gzip ${DUMP_FILE} - fi - -done - -bf-done - - -#====================================================================================================================== -# Move backups to backup directory. -#====================================================================================================================== - -BACKUP_PATH=${POSTGRESQL_BACKUP}/${DATE} -bf-echo "Moving backups to ${BACKUP_PATH}..." -mv ${TEMP_BACKUP_PATH} ${BACKUP_PATH} -bf-done - - -#====================================================================================================================== -# Remove old backups. -#====================================================================================================================== - -if [ "${POSTGRESQL_BACKUP_KEEP_FOR_DAYS}" -gt 0 ] ; then - - bf-echo "Deleting backups older than ${POSTGRESQL_BACKUP_KEEP_FOR_DAYS} days..." - MMIN=$((60*24*${POSTGRESQL_BACKUP_KEEP_FOR_DAYS})) - find ${POSTGRESQL_BACKUP}/* -type d -mmin +${MMIN} | xargs rm -rf - bf-done - -fi diff --git a/overlay/usr/lib/bf/postgresql/export b/overlay/usr/lib/bf/postgresql/export deleted file mode 100644 index 9402575..0000000 --- a/overlay/usr/lib/bf/postgresql/export +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -set -euo pipefail - - -#====================================================================================================================== -# Check arguments. -# 1 Database name -#====================================================================================================================== - -[[ -z "${1-}" ]] && bf-error "You must provide the name of the database to export." -DATABASE=${1} - - -#====================================================================================================================== -# Check database exists. -#====================================================================================================================== - -EXISTS=$(db-exists "${DATABASE}") -[[ "${EXISTS}" = "0" ]] && bf-error "Database '${DATABASE}' does not exist." - - -#====================================================================================================================== -# Dump database to file. -#====================================================================================================================== - -EXPORT_FILE="${POSTGRESQL_BACKUP}/${DATABASE}.sql" -bf-echo "Exporting database '${DATABASE}' to ${EXPORT_FILE}..." -pg_dump "${DATABASE}" > "${EXPORT_FILE}" \ - || bf-error " .. unable to export database '${DATABASE}'." -bf-done diff --git a/overlay/usr/lib/bf/postgresql/generate-config b/overlay/usr/lib/bf/postgresql/generate-config deleted file mode 100644 index ef8a250..0000000 --- a/overlay/usr/lib/bf/postgresql/generate-config +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -set -euo pipefail - - -#====================================================================================================================== -# Config is re-written every time in case environment variables have been changed. -#====================================================================================================================== - -bf-echo "Writing PostgreSQL config..." -bf-esh ${BF_TEMPLATES}/pg_hba.conf.esh \ - ${POSTGRESQL_DATA}/pg_hba.conf -bf-esh ${BF_TEMPLATES}/postgresql.conf.esh \ - ${POSTGRESQL_DATA}/postgresql.conf -bf-done diff --git a/overlay/usr/lib/bf/postgresql/import b/overlay/usr/lib/bf/postgresql/import deleted file mode 100644 index 8d23f59..0000000 --- a/overlay/usr/lib/bf/postgresql/import +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -set -euo pipefail - - -#====================================================================================================================== -# Get import files (from backup directory). -#====================================================================================================================== - -bf-echo "Importing SQL files from ${POSTGRESQL_BACKUP}..." -for FILE in ${POSTGRESQL_BACKUP}/*.sql ; do - - # split out database name from file - NAME=$(basename -- "${FILE}") - DATABASE="${NAME%.*}" - - # create database if it does not exist - EXISTS=$(db-exists "${DATABASE}") - if [ "${EXISTS}" = "0" ] ; then - bf-echo " .. creating '${DATABASE}'." - createdb "${DATABASE}" --owner="${POSTGRESQL_USERNAME}"\ - || bf-notok " . something went wrong." - fi - - # execute dump file using psql - bf-echo " .. importing '${DATABASE}'." - psql "${DATABASE}" < ${FILE} \ - || bf-notok " . something went wrong." - -done -bf-done diff --git a/overlay/usr/lib/bf/postgresql/init b/overlay/usr/lib/bf/postgresql/init deleted file mode 100644 index 940da9d..0000000 --- a/overlay/usr/lib/bf/postgresql/init +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/sh - -set -euo pipefail - - -#====================================================================================================================== -# Check for application user and password. -#====================================================================================================================== - -[[ -z "${POSTGRESQL_USERNAME-}" || -z "${POSTGRESQL_PASSWORD-}" ]] \ - && bf-error "POSTGRESQL_USERNAME and POSTGRESQL_PASSWORD must be set." - - -#====================================================================================================================== -# Initialise server, create role and application database(s), enable remote connections. -#====================================================================================================================== - -# create specified role -bf-debug "Creating role ${POSTGRESQL_USERNAME}..." -echo -e "${POSTGRESQL_PASSWORD}\n${POSTGRESQL_PASSWORD}" | createuser --superuser --pwprompt ${POSTGRESQL_USERNAME} - -# create database(s) -bf-debug "Creating..." -if [ ! -z "${POSTGRESQL_DATABASE-}" ] ; then - - bf-debug " .. specified database(s):" - DATABASES=$(echo ${POSTGRESQL_DATABASE} | tr "," "\n") - - for DATABASE in ${DATABASES} ; do - bf-debug " .. ${DATABASE}." - createdb "${DATABASE}" --owner="${POSTGRESQL_USERNAME}" - done - -# no database specified so use username as database name -else - - bf-debug " .. application database: ${POSTGRESQL_USERNAME}." - createdb "${POSTGRESQL_USERNAME}" --owner="${POSTGRESQL_USERNAME}" - -fi diff --git a/run.sh b/run.sh index f41440f..634e57a 100644 --- a/run.sh +++ b/run.sh @@ -5,10 +5,17 @@ POSTGRESQL=${1:-15} docker buildx build \ --load \ + --progress plain \ --build-arg BF_IMAGE=postgresql \ --build-arg BF_VERSION=${IMAGE} \ -f ${POSTGRESQL}/Dockerfile \ -t postgresql${POSTGRESQL}-dev \ . \ && \ - docker run -it -e POSTGRESQL_USERNAME=test -e POSTGRESQL_PASSWORD=test postgresql${POSTGRESQL}-dev sh + docker run -it \ + -e BF_DEBUG=1 \ + -e BF_PG_APPLICATION=test \ + postgresql${POSTGRESQL}-dev \ + sh + + #-v /tmp/pg-data:/data \