mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-07 19:22:14 +09:00
refactor(self-hosting): forward every setting, drop dead config (#3047)
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -238,12 +238,12 @@ The desktop client opens the hosted web app for its release channel, so reach yo
|
||||
|
||||
Recovery requires `.env`, a database dump and a backup of `seaweedfs-data`, which holds uploads, avatars, reports and harvests. See [Volumes and buckets](/operator/configuration/#volumes-and-buckets) for everything that needs backing up.
|
||||
|
||||
The dump costs no downtime, so run it on a schedule while the stack serves:
|
||||
The dump costs no downtime, so run it on a schedule while the stack serves. It runs inside the `postgres` container and takes the role and database from that container's environment, which follows `FLUXER_POSTGRES_USERNAME` and `FLUXER_POSTGRES_DATABASE`. It is for the bundled database. A database outside the stack is backed up with its own tools:
|
||||
|
||||
```bash
|
||||
cd ~/fluxer
|
||||
mkdir -p backups
|
||||
docker compose exec -T postgres pg_dump -U fluxer -d fluxer --format=custom \
|
||||
docker compose exec -T postgres sh -c 'pg_dump -U $POSTGRES_USER -d $POSTGRES_DB --format=custom' \
|
||||
> "backups/fluxer-$(date -u +%Y%m%dT%H%M%SZ).dump"
|
||||
```
|
||||
|
||||
@@ -251,7 +251,7 @@ PowerShell writes UTF-16 through `>`, which corrupts a binary dump. On Windows,
|
||||
|
||||
```powershell
|
||||
mkdir -Force backups
|
||||
docker compose exec -T postgres pg_dump -U fluxer -d fluxer --format=custom -f /tmp/fluxer.dump
|
||||
docker compose exec -T postgres sh -c 'pg_dump -U $POSTGRES_USER -d $POSTGRES_DB --format=custom -f /tmp/fluxer.dump'
|
||||
docker compose cp postgres:/tmp/fluxer.dump backups/fluxer.dump
|
||||
docker compose exec -T postgres rm /tmp/fluxer.dump
|
||||
```
|
||||
|
||||
@@ -396,7 +396,7 @@ Forward every path and query string unchanged. The edge handles routing:
|
||||
| `/.well-known/assetlinks.json` | Android app association |
|
||||
| `/version.json` | Client version metadata |
|
||||
|
||||
All other paths serve the web app.
|
||||
All other paths serve the web app. The admin path follows `FLUXER_ADMIN_BASE_PATH`, `/admin` by default.
|
||||
|
||||
Pass the query string on `/gateway` through untouched. Clients always send `?v=`, `?encoding=`, `?compress=` and `?stream=`, and `1` is the only version the Gateway accepts.
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ The images come from `FLUXER_IMAGE_TAG` in `.env`. The stack files come from a g
|
||||
|
||||
The repository holds no ref by the name of a pinned image tag. A release tags each image on its own, as `[email protected]`, so pass `--ref` with that tag or with the commit it points at. Without that override the download fails with exit 4.
|
||||
|
||||
The stack files on `main` can run ahead of the `v1` images. The current `docker-compose.yml` passes an optional setting with no Compose default through empty when `.env` leaves it out, and only images built from the same change or later read an empty value as unset. Older images reject some of those empty values and `api`, `worker` and `media-proxy` fail to start. Refresh the stack files only once the images the tag names are at least as new, or pin both with `--ref`.
|
||||
|
||||
## What the script does
|
||||
|
||||
`--update` runs these steps in this order, and stops on the first one that fails:
|
||||
@@ -195,6 +197,10 @@ Within minutes of the upgrade, `worker` starts deleting existing data that is pa
|
||||
|
||||
Instances on Cassandra already behave this way.
|
||||
|
||||
## Check the svc request ceiling
|
||||
|
||||
`docker-compose.yml` used to pass `FLUXER_SVC_MAX_CONCURRENT_REQUESTS` only to the `users` and `messages` routers and shards. It now reaches every svc container, so a value set in `.env` also caps `snowflakes`, `gifs` and `unfurl`. Unset, `snowflakes` allows `320` requests in flight, `messages` `192` and the rest `64`. An instance that sets the name either raises it to at least `320` or removes it from `.env`, then runs `docker compose up -d`.
|
||||
|
||||
## Add the passkey columns on Cassandra
|
||||
|
||||
An instance on the Postgres backend needs nothing here. An instance on Cassandra or Scylla adds two columns to `webauthn_credentials` before it starts the new `api` and `worker` images. Replace `fluxer` with the value of `FLUXER_CASSANDRA_KEYSPACE`.
|
||||
@@ -229,7 +235,7 @@ Nothing else is copied. The dump covers `postgres-data`. The other volumes eithe
|
||||
Put a dump on a timer as well. On Linux and macOS, this crontab line writes one a night and keeps two weeks of them:
|
||||
|
||||
```cron
|
||||
15 3 * * * cd /srv/fluxer && docker compose exec -T postgres pg_dump -U fluxer -d fluxer --format=custom > "backups/fluxer-$(date -u +\%Y\%m\%dT\%H\%M\%SZ).dump" && find backups -name 'fluxer-*.dump' -mtime +14 -delete
|
||||
15 3 * * * cd /srv/fluxer && docker compose exec -T postgres sh -c 'pg_dump -U $POSTGRES_USER -d $POSTGRES_DB --format=custom' > "backups/fluxer-$(date -u +\%Y\%m\%dT\%H\%M\%SZ).dump" && find backups -name 'fluxer-*.dump' -mtime +14 -delete
|
||||
```
|
||||
|
||||
`/srv/fluxer` stands for the directory holding `.env`. Write it as an absolute path, because cron does not expand `~`. An unescaped `%` in a crontab is a newline, which is why every one above has a backslash.
|
||||
@@ -269,7 +275,7 @@ The `seaweedfs-data` volume stays until you delete it. Copy its objects to the n
|
||||
|
||||
The other bundled services have no shipped overlay. Take one out with an override file listed in `COMPOSE_FILE`, which [Keep a local compose change](#keep-a-local-compose-change) describes, rather than by editing `docker-compose.yml`, which the Place step replaces on every upgrade.
|
||||
|
||||
The installer backs up only the bundled database and object store. Arrange separate backups for external stores before upgrading, and keep them with the release's backup record.
|
||||
The installer backs up only the bundled database and object store. It skips the database dump when the stack defines no `postgres` service, and when `FLUXER_POSTGRES_HOST` or the host in `FLUXER_POSTGRES_URL` names anything other than `postgres`. The bundled service is idle in that shape, and its data directory still holds the role and database it was first started with, so the by-hand dump and restore commands on this page do not work against it either. Arrange separate backups for external stores before upgrading, and keep them with the release's backup record.
|
||||
|
||||
## Roll back
|
||||
|
||||
@@ -295,12 +301,12 @@ The database restores from the custom-format dump:
|
||||
```bash
|
||||
docker compose stop
|
||||
docker compose up -d --wait postgres
|
||||
docker compose exec -T postgres pg_restore -U fluxer -d fluxer --clean --if-exists \
|
||||
docker compose exec -T postgres sh -c 'pg_restore -U $POSTGRES_USER -d $POSTGRES_DB --clean --if-exists' \
|
||||
< backups/record-20260831T120000Z/fluxer.dump
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
`--clean` prints notices about objects that do not exist yet, which is expected against a fresh directory.
|
||||
`--clean` prints notices about objects that do not exist yet, which is expected against a fresh directory. The role and database come from the `postgres` container's environment, which follows `FLUXER_POSTGRES_USERNAME` and `FLUXER_POSTGRES_DATABASE`, the same way the installer's dump reads them. These commands are for the bundled database. A database outside the stack restores with its own tools.
|
||||
|
||||
PowerShell has no `<` redirection. On Windows, copy the dump into the container and name it as a file:
|
||||
|
||||
@@ -308,7 +314,7 @@ PowerShell has no `<` redirection. On Windows, copy the dump into the container
|
||||
docker compose stop
|
||||
docker compose up -d --wait postgres
|
||||
docker compose cp backups\record-20260831T120000Z\fluxer.dump postgres:/tmp/fluxer.dump
|
||||
docker compose exec -T postgres pg_restore -U fluxer -d fluxer --clean --if-exists /tmp/fluxer.dump
|
||||
docker compose exec -T postgres sh -c 'pg_restore -U $POSTGRES_USER -d $POSTGRES_DB --clean --if-exists /tmp/fluxer.dump'
|
||||
docker compose exec -T postgres rm /tmp/fluxer.dump
|
||||
docker compose up -d
|
||||
```
|
||||
@@ -327,12 +333,12 @@ For a `seaweedfs-data.tar`, write `tar xf` in place of `tar xzf`. `tar` extracts
|
||||
|
||||
## Move to a new Postgres major version
|
||||
|
||||
`docker-compose.yml` pins `postgres:16-alpine`. A newer major does not read the data directory an older major wrote, so the data moves across through a dump. The upgrade refuses when the refreshed compose file changes that pin, because the move destroys the volume holding the database.
|
||||
`docker-compose.yml` runs `postgres:16-alpine` unless `FLUXER_POSTGRES_IMAGE` in `.env` names another image. A newer major does not read the data directory an older major wrote, so the data moves across through a dump. The upgrade refuses when the refreshed compose file would run a different major from the current one, because the move destroys the volume holding the database. It reads the current major from the image the old file names, and takes `FLUXER_POSTGRES_IMAGE` into account only for a file that reads it.
|
||||
|
||||
Take the dump while the old major is still serving, then stop everything and drop the volume:
|
||||
|
||||
```bash
|
||||
docker compose exec -T postgres pg_dump -U fluxer -d fluxer --format=custom \
|
||||
docker compose exec -T postgres sh -c 'pg_dump -U $POSTGRES_USER -d $POSTGRES_DB --format=custom' \
|
||||
> backups/pre-major.dump
|
||||
docker compose down
|
||||
docker volume rm fluxer_postgres-data
|
||||
@@ -342,16 +348,18 @@ On Windows, run `pg_dump` inside the container with `-f /tmp/pre-major.dump` and
|
||||
|
||||
Once that volume is removed, the dump is the only copy of the database.
|
||||
|
||||
Put the new `postgres` tag in `docker-compose.yml`, start the database on its own, and restore into the empty directory:
|
||||
`FLUXER_POSTGRES_IMAGE` takes effect only once `docker-compose.yml` reads it. An instance on older stack files runs `sh install.sh --update` first, or edits the tag in its `docker-compose.yml` as before.
|
||||
|
||||
Set `FLUXER_POSTGRES_IMAGE` in `.env` to the new tag, such as `postgres:17-alpine`, start the database on its own, and restore into the empty directory:
|
||||
|
||||
```bash
|
||||
docker compose up -d --wait postgres
|
||||
docker compose exec -T postgres pg_restore -U fluxer -d fluxer --clean --if-exists \
|
||||
docker compose exec -T postgres sh -c 'pg_restore -U $POSTGRES_USER -d $POSTGRES_DB --clean --if-exists' \
|
||||
< backups/pre-major.dump
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Run `sh install.sh --update` afterwards to finish the move on the refreshed files.
|
||||
Run `sh install.sh --update` afterwards to finish the move on the refreshed files. Remove the `FLUXER_POSTGRES_IMAGE` line once the refreshed `docker-compose.yml` runs the same major by default.
|
||||
|
||||
## Pin a release
|
||||
|
||||
@@ -359,11 +367,11 @@ Run `sh install.sh --update` afterwards to finish the move on the refreshed file
|
||||
|
||||
A pinned instance also pins its stack files. [Match the images to the stack files](#match-the-images-to-the-stack-files) has the `--ref` a pinned tag needs.
|
||||
|
||||
The tag applies only to the Fluxer images. `caddy`, `postgres`, `valkey`, `nats`, `meilisearch`, `seaweedfs` and `livekit` are pinned in `docker-compose.yml`, and they move only when an upgrade refreshes that file.
|
||||
The tag applies only to the Fluxer images. `caddy`, `postgres`, `valkey`, `nats`, `meilisearch`, `seaweedfs` and `livekit` take their tags from `docker-compose.yml`, and move when an upgrade refreshes that file. An image name in `.env`, such as `FLUXER_POSTGRES_IMAGE`, holds one of them in place instead. [Images](/operator/configuration/#images) lists the names.
|
||||
|
||||
## Change the domain or the passkey relying party
|
||||
|
||||
`FLUXER_DOMAIN` supplies the default `FLUXER_PASSKEY_RP_ID`, which is the domain a passkey is tied to. A passkey works only under the identifier it was created with.
|
||||
`FLUXER_DOMAIN` supplies the default `FLUXER_PASSKEY_RP_ID`, which is the domain a passkey is tied to. `FLUXER_PUBLIC_ORIGIN` does not move it. A passkey works only under the identifier it was created with.
|
||||
|
||||
:::danger[Changing either value invalidates every passkey]
|
||||
Passkeys registered under the old `FLUXER_PASSKEY_RP_ID` stop working and cannot be recovered. Every user has to register a new one, so keep another sign-in method working before you change it.
|
||||
|
||||
@@ -435,8 +435,8 @@ function Get-FluxerRefForTag([string]$Tag) {
|
||||
}
|
||||
|
||||
# The images come from FLUXER_IMAGE_TAG and the stack files come from a git ref. A release tags its
|
||||
# images and its commit with the same CalVer string, so a pinned tag names the commit that carries
|
||||
# its compose files. The moving tags v1 and latest track main.
|
||||
# images and its commit with the same CalVer string, so a pinned tag names the commit that holds its
|
||||
# compose files. The moving tags v1 and latest map to main, which can run ahead of the v1 images.
|
||||
function Assert-FluxerDerivedRef([string]$Value, [string]$EnvPath) {
|
||||
if ($Value.Length -eq 0) {
|
||||
Stop-Fluxer "$EnvPath declares no FLUXER_IMAGE_TAG, so no ref can be derived. Pass -Ref." $FluxerExitRefused
|
||||
@@ -631,8 +631,10 @@ function Remove-FluxerStagingDirectory([string]$Path) {
|
||||
# Invoke-WebRequest -Uri https://raw.githubusercontent.com/fluxerapp/fluxer/main/deploy/self-hosting/docker-compose.yml -OutFile docker-compose.yml
|
||||
#
|
||||
# The files come from a git ref and the images come from FLUXER_IMAGE_TAG. The ref is derived from
|
||||
# the tag unless -Ref names one, which is the pairing rule that stops a compose file from asking for
|
||||
# a variable the running images do not read.
|
||||
# the tag unless -Ref names one. A pinned CalVer tag names the commit its images were built from, so
|
||||
# its compose file asks only for variables those images read. The moving tags v1 and latest map to
|
||||
# main, and main's compose file can run ahead of the v1 images until the image builds are dispatched
|
||||
# again.
|
||||
#
|
||||
# Everything lands in a staging directory first, so a failed download leaves the working directory
|
||||
# on the set it already had, and so the upgrade can compare old against new before replacing.
|
||||
@@ -995,15 +997,34 @@ function Get-FluxerRunningImageId($Running, [string]$Reference) {
|
||||
return ''
|
||||
}
|
||||
|
||||
function Get-FluxerPostgresMajor([string]$Path) {
|
||||
function Get-FluxerPostgresMajor([string]$Path, [string]$EnvPath) {
|
||||
if (-not (Test-Path -LiteralPath $Path)) {
|
||||
return ''
|
||||
}
|
||||
$image = ''
|
||||
foreach ($line in [System.IO.File]::ReadAllText($Path).Split("`n")) {
|
||||
if ($line -match '^\s*image:\s*postgres:(\d+)') {
|
||||
return $Matches[1]
|
||||
if ($line -match '^\s*image:\s*(postgres:\S*)') {
|
||||
$image = $Matches[1]
|
||||
break
|
||||
}
|
||||
}
|
||||
if ($image.Length -eq 0) {
|
||||
foreach ($line in [System.IO.File]::ReadAllText($Path).Split("`n")) {
|
||||
if ($line -match '^\s*image:\s*\$\{FLUXER_POSTGRES_IMAGE:-([^}]*)\}') {
|
||||
$image = $Matches[1]
|
||||
$configured = Get-FluxerComposeValue $EnvPath 'FLUXER_POSTGRES_IMAGE'
|
||||
if ($configured.Length -gt 0) {
|
||||
$image = $configured
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
$name = ($image -split '@')[0]
|
||||
$name = ($name -split '/')[-1]
|
||||
if ($name -match ':(\d+)[^:]*$') {
|
||||
return $Matches[1]
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
@@ -1297,9 +1318,12 @@ function Test-FluxerDumpHeader([string]$Path) {
|
||||
# schema change.
|
||||
#
|
||||
# By hand:
|
||||
# docker compose exec -T postgres pg_dump -U fluxer -d fluxer --format=custom > backups\fluxer.dump
|
||||
# docker compose exec -T postgres sh -c 'pg_dump -U $POSTGRES_USER -d $POSTGRES_DB --format=custom -f /tmp/fluxer.dump'
|
||||
# docker compose cp postgres:/tmp/fluxer.dump backups\fluxer.dump
|
||||
# docker compose exec -T postgres rm /tmp/fluxer.dump
|
||||
#
|
||||
# The database and the role are both named fluxer and are fixed in docker-compose.yml. Keep -T.
|
||||
# The postgres container's POSTGRES_USER and POSTGRES_DB follow FLUXER_POSTGRES_USERNAME and
|
||||
# FLUXER_POSTGRES_DATABASE, so the command needs no names. Keep -T.
|
||||
# Without it Docker attaches a terminal to the command and the dump arrives corrupted, which is
|
||||
# why the first five bytes are checked against the custom-format magic rather than only the size.
|
||||
#
|
||||
@@ -1327,11 +1351,44 @@ function Test-FluxerStackDefinesService([string]$Name, [string]$TargetDir) {
|
||||
return $script:FluxerStackServices -contains $Name
|
||||
}
|
||||
|
||||
# The bundled postgres container takes POSTGRES_USER and POSTGRES_DB from FLUXER_POSTGRES_USERNAME
|
||||
# and FLUXER_POSTGRES_DATABASE, and the image applies them only to an empty data directory. When
|
||||
# those names point the apps at a database outside the stack, the bundled directory still holds the
|
||||
# role and database it was first started with, so a dump that reads the container env asks for a
|
||||
# role that is not there. The bundled service is idle in that shape and the dump skips it.
|
||||
function Test-FluxerPostgresExternal([string]$TargetDir) {
|
||||
$envPath = Join-Path $TargetDir '.env'
|
||||
$pgHost = Get-FluxerComposeValue $envPath 'FLUXER_POSTGRES_HOST'
|
||||
if ($pgHost.Length -gt 0 -and $pgHost -ne 'postgres') {
|
||||
return $true
|
||||
}
|
||||
$url = Get-FluxerComposeValue $envPath 'FLUXER_POSTGRES_URL'
|
||||
if ($url.Length -eq 0) {
|
||||
return $false
|
||||
}
|
||||
$urlHost = $url
|
||||
$scheme = $urlHost.IndexOf('://')
|
||||
if ($scheme -ge 0) {
|
||||
$urlHost = $urlHost.Substring($scheme + 3)
|
||||
}
|
||||
$urlHost = ($urlHost -split '[/?]', 2)[0]
|
||||
$at = $urlHost.LastIndexOf('@')
|
||||
if ($at -ge 0) {
|
||||
$urlHost = $urlHost.Substring($at + 1)
|
||||
}
|
||||
$urlHost = ($urlHost -split ':', 2)[0]
|
||||
return $urlHost -ne 'postgres'
|
||||
}
|
||||
|
||||
function Backup-FluxerDatabase([string]$Record, [string]$TargetDir) {
|
||||
if (-not (Test-FluxerStackDefinesService 'postgres' $TargetDir)) {
|
||||
Write-FluxerLine 'Skipping the database dump. This stack defines no postgres service, so its database runs outside the stack and only the operator of that database can dump it.'
|
||||
return
|
||||
}
|
||||
if (Test-FluxerPostgresExternal $TargetDir) {
|
||||
Write-FluxerLine 'Skipping the database dump. FLUXER_POSTGRES_HOST or FLUXER_POSTGRES_URL points the stack at a database outside it, so the bundled postgres service is idle and only the operator of that database can dump it.'
|
||||
return
|
||||
}
|
||||
if (-not (Test-FluxerPostgresRunning)) {
|
||||
Write-FluxerLine 'Postgres is not running. Starting it for the dump.'
|
||||
if ((Invoke-FluxerDocker @('compose', 'up', '-d', '--wait', 'postgres')) -ne 0) {
|
||||
@@ -1340,7 +1397,7 @@ function Backup-FluxerDatabase([string]$Record, [string]$TargetDir) {
|
||||
}
|
||||
$dump = Join-Path $Record $FluxerDumpFile
|
||||
Write-FluxerLine 'Dumping the database.'
|
||||
$code = Invoke-FluxerDockerToFile @('compose', 'exec', '-T', 'postgres', 'pg_dump', '-U', 'fluxer', '-d', 'fluxer', '--format=custom') $dump $TargetDir
|
||||
$code = Invoke-FluxerDockerToFile @('compose', 'exec', '-T', 'postgres', 'sh', '-c', '"exec pg_dump -U $POSTGRES_USER -d $POSTGRES_DB --format=custom"') $dump $TargetDir
|
||||
if ($code -ne 0) {
|
||||
Remove-FluxerTemporary $dump
|
||||
Stop-Fluxer 'pg_dump failed. The instance is untouched.' $FluxerExitBackup
|
||||
@@ -1462,8 +1519,9 @@ function Backup-FluxerInstance([string]$Record, [string]$TargetDir, [string]$Pro
|
||||
# The refreshed file is still staged when this runs, so a refusal here leaves the instance exactly
|
||||
# as it was.
|
||||
function Assert-FluxerPostgresMajor([string]$TargetDir, [string]$StagingDir) {
|
||||
$old = Get-FluxerPostgresMajor (Join-Path $TargetDir $script:FluxerComposeBase)
|
||||
$new = Get-FluxerPostgresMajor (Join-Path $StagingDir 'docker-compose.yml')
|
||||
$envPath = Join-Path $TargetDir '.env'
|
||||
$old = Get-FluxerPostgresMajor (Join-Path $TargetDir $script:FluxerComposeBase) $envPath
|
||||
$new = Get-FluxerPostgresMajor (Join-Path $StagingDir 'docker-compose.yml') $envPath
|
||||
if ($old.Length -eq 0 -or $new.Length -eq 0 -or $old -eq $new) {
|
||||
return
|
||||
}
|
||||
@@ -1569,8 +1627,8 @@ function Show-FluxerUpdatePlan([string]$TargetDir, [string]$EnvPath, [string]$Ba
|
||||
if ($changed -eq 0) {
|
||||
Write-FluxerLine " Note: ref $Ref moves no stack file"
|
||||
}
|
||||
$old = Get-FluxerPostgresMajor (Join-Path $TargetDir $script:FluxerComposeBase)
|
||||
$new = Get-FluxerPostgresMajor (Join-Path $staging 'docker-compose.yml')
|
||||
$old = Get-FluxerPostgresMajor (Join-Path $TargetDir $script:FluxerComposeBase) $EnvPath
|
||||
$new = Get-FluxerPostgresMajor (Join-Path $staging 'docker-compose.yml') $EnvPath
|
||||
if ($old.Length -gt 0 -and $new.Length -gt 0 -and $old -ne $new) {
|
||||
Write-FluxerLine " Refusal: postgres moves from $old to $new, which this script does not do"
|
||||
Write-FluxerLine ' Outcome: the run stops at that refusal and changes nothing'
|
||||
@@ -1823,6 +1881,14 @@ function Get-FluxerEnvScalar([string]$EnvPath, [string]$Name) {
|
||||
return $raw
|
||||
}
|
||||
|
||||
function Get-FluxerComposeValue([string]$EnvPath, [string]$Name) {
|
||||
$value = [string][Environment]::GetEnvironmentVariable($Name)
|
||||
if ($value.Length -eq 0 -and (Test-Path -LiteralPath $EnvPath)) {
|
||||
$value = Get-FluxerEnvScalar $EnvPath $Name
|
||||
}
|
||||
return $value
|
||||
}
|
||||
|
||||
function Get-FluxerComposeSetting([string]$EnvPath) {
|
||||
$value = ''
|
||||
$source = 'the environment'
|
||||
|
||||
@@ -711,8 +711,8 @@ fluxer_ref_for_tag() {
|
||||
|
||||
# The images come from FLUXER_IMAGE_TAG and the stack files come from a git ref.
|
||||
# A release tags its images and its commit with the same CalVer string, so a
|
||||
# pinned tag names the commit that carries its compose files. The moving tags v1
|
||||
# and latest track main.
|
||||
# pinned tag names the commit that holds its compose files. The moving tags v1
|
||||
# and latest map to main, which can run ahead of the v1 images.
|
||||
fluxer_resolve_ref() {
|
||||
[ -z "$opt_ref" ] || return 0
|
||||
if [ "$opt_update" -eq 1 ] || [ "$opt_rollback" -eq 1 ]; then
|
||||
@@ -763,9 +763,11 @@ fluxer_open_scratch() {
|
||||
# curl -fsSL https://raw.githubusercontent.com/fluxerapp/fluxer/main/deploy/self-hosting/docker-compose.yml -o docker-compose.yml
|
||||
#
|
||||
# The files come from a git ref and the images come from FLUXER_IMAGE_TAG. The
|
||||
# ref is derived from the tag unless --ref names one, which is the pairing rule
|
||||
# that stops a compose file from asking for a variable the running images do not
|
||||
# read, or from pinning a service image the release never built.
|
||||
# ref is derived from the tag unless --ref names one. A pinned CalVer tag names
|
||||
# the commit its images were built from, so its compose file asks only for
|
||||
# variables those images read and pins only images the release built. The moving
|
||||
# tags v1 and latest map to main, and main's compose file can run ahead of the v1
|
||||
# images until the image builds are dispatched again.
|
||||
fluxer_fetch_stack() {
|
||||
fluxer_say "Downloading the stack files from ref $opt_ref."
|
||||
fluxer_stack_files > "$fluxer_scratch/files"
|
||||
@@ -1237,6 +1239,14 @@ fluxer_env_scalar() {
|
||||
printf '%s' "$fluxer_scalar"
|
||||
}
|
||||
|
||||
fluxer_compose_value() {
|
||||
eval "fluxer_cv=\${$1:-}"
|
||||
if [ -z "$fluxer_cv" ]; then
|
||||
fluxer_cv=$(fluxer_env_scalar "$1")
|
||||
fi
|
||||
printf '%s' "$fluxer_cv"
|
||||
}
|
||||
|
||||
fluxer_read_compose_setting() {
|
||||
fluxer_compose_file=${COMPOSE_FILE:-}
|
||||
fluxer_compose_from="the environment"
|
||||
@@ -1469,12 +1479,13 @@ fluxer_postgres_running() {
|
||||
# the pull is the only way back across a schema change.
|
||||
#
|
||||
# By hand:
|
||||
# docker compose exec -T postgres pg_dump -U fluxer -d fluxer --format=custom > backups/fluxer.dump
|
||||
# docker compose exec -T postgres sh -c 'exec pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" --format=custom' > backups/fluxer.dump
|
||||
#
|
||||
# The database and the role are both named fluxer and are fixed in
|
||||
# docker-compose.yml. Keep -T. Without it Docker attaches a terminal to the
|
||||
# command and the dump arrives corrupted, which is why the first five bytes are
|
||||
# checked against the custom-format magic below rather than only the size.
|
||||
# The postgres container's POSTGRES_USER and POSTGRES_DB follow
|
||||
# FLUXER_POSTGRES_USERNAME and FLUXER_POSTGRES_DATABASE, so the command needs no
|
||||
# names. Keep -T. Without it Docker attaches a terminal to the command and the
|
||||
# dump arrives corrupted, which is why the first five bytes are checked against
|
||||
# the custom-format magic below rather than only the size.
|
||||
#
|
||||
# The dump runs against the live stack. pg_dump reads inside one transaction, so
|
||||
# it sees a consistent database without stopping anything. The volume copy below
|
||||
@@ -1501,11 +1512,39 @@ $(fluxer_compose_error ' ')"
|
||||
grep -qxF "$1" "$fluxer_scratch/all-services"
|
||||
}
|
||||
|
||||
# The bundled postgres container takes POSTGRES_USER and POSTGRES_DB from
|
||||
# FLUXER_POSTGRES_USERNAME and FLUXER_POSTGRES_DATABASE, and the image applies
|
||||
# them only to an empty data directory. When those names point the apps at a
|
||||
# database outside the stack, the bundled directory still holds the role and
|
||||
# database it was first started with, so a dump that reads the container env asks
|
||||
# for a role that is not there. The bundled service is idle in that shape and the
|
||||
# dump skips it.
|
||||
#
|
||||
# By hand:
|
||||
# grep -E '^FLUXER_POSTGRES_(HOST|URL)=' .env
|
||||
fluxer_postgres_external() {
|
||||
fluxer_pg_host=$(fluxer_compose_value FLUXER_POSTGRES_HOST)
|
||||
if [ -n "$fluxer_pg_host" ] && [ "$fluxer_pg_host" != postgres ]; then
|
||||
return 0
|
||||
fi
|
||||
fluxer_pg_url=$(fluxer_compose_value FLUXER_POSTGRES_URL)
|
||||
[ -n "$fluxer_pg_url" ] || return 1
|
||||
fluxer_pg_url_host=${fluxer_pg_url#*://}
|
||||
fluxer_pg_url_host=${fluxer_pg_url_host%%[/?]*}
|
||||
fluxer_pg_url_host=${fluxer_pg_url_host##*@}
|
||||
fluxer_pg_url_host=${fluxer_pg_url_host%%:*}
|
||||
[ "$fluxer_pg_url_host" != postgres ]
|
||||
}
|
||||
|
||||
fluxer_dump_postgres() {
|
||||
if ! fluxer_stack_defines_service postgres; then
|
||||
fluxer_say 'Skipping the database dump. This stack defines no postgres service, so its database runs outside the stack and only the operator of that database can dump it.'
|
||||
return 0
|
||||
fi
|
||||
if fluxer_postgres_external; then
|
||||
fluxer_say 'Skipping the database dump. FLUXER_POSTGRES_HOST or FLUXER_POSTGRES_URL points the stack at a database outside it, so the bundled postgres service is idle and only the operator of that database can dump it.'
|
||||
return 0
|
||||
fi
|
||||
if ! fluxer_postgres_running; then
|
||||
fluxer_say 'Postgres is not running. Starting it for the dump.'
|
||||
if ! $fluxer_engine compose up -d --wait postgres; then
|
||||
@@ -1514,7 +1553,7 @@ fluxer_dump_postgres() {
|
||||
fi
|
||||
fluxer_dump_path="$fluxer_record/$FLUXER_DUMP_FILE"
|
||||
fluxer_say 'Dumping the database.'
|
||||
if ! $fluxer_engine compose exec -T postgres pg_dump -U fluxer -d fluxer --format=custom > "$fluxer_dump_path"; then
|
||||
if ! $fluxer_engine compose exec -T postgres sh -c 'exec pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" --format=custom' > "$fluxer_dump_path"; then
|
||||
rm -f "$fluxer_dump_path"
|
||||
fluxer_fail 7 'pg_dump failed. The instance is untouched.'
|
||||
fi
|
||||
@@ -1627,7 +1666,17 @@ fluxer_backup() {
|
||||
}
|
||||
|
||||
fluxer_postgres_major() {
|
||||
sed -n 's/^[[:space:]]*image:[[:space:]]*postgres:\([0-9][0-9]*\).*/\1/p' "$1" | head -n 1
|
||||
fluxer_pg_image=$(sed -n 's/^[[:space:]]*image:[[:space:]]*\(postgres:[^[:space:]]*\).*/\1/p' "$1" | head -n 1)
|
||||
if [ -z "$fluxer_pg_image" ]; then
|
||||
fluxer_pg_image=$(sed -n 's/^[[:space:]]*image:[[:space:]]*${FLUXER_POSTGRES_IMAGE:-\([^}]*\)}.*/\1/p' "$1" | head -n 1)
|
||||
if [ -n "$fluxer_pg_image" ] && [ -n "$(fluxer_compose_value FLUXER_POSTGRES_IMAGE)" ]; then
|
||||
fluxer_pg_image=$(fluxer_compose_value FLUXER_POSTGRES_IMAGE)
|
||||
fi
|
||||
fi
|
||||
fluxer_pg_image=${fluxer_pg_image%%@*}
|
||||
case ${fluxer_pg_image##*/} in
|
||||
*:*) printf '%s\n' "${fluxer_pg_image##*:}" | sed -n 's/^\([0-9][0-9]*\).*/\1/p' ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# A newer Postgres major does not read the data directory an older major wrote,
|
||||
|
||||
Reference in New Issue
Block a user