diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000..1063b3b --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# Pre-commit hook: warn when assets.json is staged but generated/ and README.md +# look out of sync. The CI `update-repo` job will fix drift automatically after +# publish, but catching it locally gives faster feedback. +# +# Enable with: git config core.hooksPath .githooks +# Skip once with: git commit --no-verify + +set -e + +if ! git diff --cached --name-only | grep -qx 'assets.json'; then + exit 0 +fi + +if ! command -v pwsh >/dev/null 2>&1; then + echo "pre-commit: pwsh not found; skipping generated-file check." >&2 + exit 0 +fi + +echo "pre-commit: assets.json is staged; regenerating Dockerfiles + README to check for drift..." +pwsh -NoProfile -Command "Invoke-Build Prepare; Invoke-Build Update-Readme" >/dev/null + +stale=$(git status --porcelain -- generated/ README.md) +if [ -n "$stale" ]; then + echo "pre-commit: regeneration changed files not in this commit:" >&2 + echo "$stale" >&2 + echo >&2 + echo "Stage them with: git add generated/ README.md" >&2 + echo "Or skip this check: git commit --no-verify" >&2 + exit 1 +fi diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index cc93cff..2d21e75 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,15 +1 @@ -# These are supported funding model platforms - -github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] -patreon: # Replace with a single Patreon username -open_collective: # Replace with a single Open Collective username -ko_fi: # Replace with a single Ko-fi username -tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel -community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry -liberapay: # Replace with a single Liberapay username -issuehunt: # Replace with a single IssueHunt username -lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry -polar: # Replace with a single Polar username -buy_me_a_coffee: # Replace with a single Buy Me a Coffee username -thanks_dev: # Replace with a single thanks.dev username custom: https://firebirdsql.org/en/donate/ diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7a0fe76..9fbb578 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -3,6 +3,9 @@ name: ci # Build and run all tests. # - Triggers: All pushes and pull requests on any branch. # - Runs on: All repositories (including forks) +# +# Forks (non-dispatch): build only the latest release per major Firebird version. +# Official repo or workflow_dispatch: full build of all versions. on: push: @@ -11,46 +14,85 @@ on: pull_request: branches: ['**'] - workflow_dispatch: # Allows manual dispatch + workflow_dispatch: + inputs: + version-filter: + description: 'Version filter (e.g. 5, 4.0, 5.0.3). Empty = all.' + required: false + type: string + distro-filter: + description: 'Distro filter (e.g. trixie). Empty = all.' + required: false + type: string # Prevents overlapping runs of this workflow on the same branch. -# If multiple commits are pushed in quick succession, only the most recent run will complete. concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: + determine-scope: + runs-on: ubuntu-latest + outputs: + latest-per-major: ${{ steps.scope.outputs.latest-per-major }} + steps: + - name: Determine build scope + id: scope + run: | + IS_OFFICIAL="${{ github.repository == 'FirebirdSQL/firebird-docker' }}" + IS_DISPATCH="${{ github.event_name == 'workflow_dispatch' }}" + if [[ "$IS_OFFICIAL" == "true" || "$IS_DISPATCH" == "true" ]]; then + echo "latest-per-major=false" >> $GITHUB_OUTPUT + else + echo "latest-per-major=true" >> $GITHUB_OUTPUT + fi + build-and-test: if: ${{ !(github.repository == 'FirebirdSQL/firebird-docker' && github.ref == 'refs/heads/master') }} - runs-on: ubuntu-latest + needs: determine-scope + strategy: + fail-fast: false + matrix: + arch: [amd64, arm64] + include: + - arch: amd64 + runner: ubuntu-latest + - arch: arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 10 - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: actions/checkout@v6 - name: Install tools shell: pwsh run: | Install-Module InvokeBuild -Force + Install-Module PSFirebird -MinimumVersion '1.0.0' -Force - name: Build shell: pwsh run: | - Invoke-Build + $params = @{} + if ('${{ inputs.version-filter }}') { $params['VersionFilter'] = '${{ inputs.version-filter }}' } + if ('${{ inputs.distro-filter }}') { $params['DistributionFilter'] = '${{ inputs.distro-filter }}' } + if ('${{ needs.determine-scope.outputs.latest-per-major }}' -eq 'true') { $params['LatestPerMajor'] = $true } + Invoke-Build Build @params - name: Test shell: pwsh run: | - Invoke-Build Test - - - name: Upload logs - uses: actions/upload-artifact@v4 - if: always() - with: - name: ci-logs-${{ github.run_id }} - path: generated/logs - retention-days: 7 # Short log retention for CI runs + $params = @{} + if ('${{ inputs.version-filter }}') { $params['VersionFilter'] = '${{ inputs.version-filter }}' } + if ('${{ inputs.distro-filter }}') { $params['DistributionFilter'] = '${{ inputs.distro-filter }}' } + if ('${{ needs.determine-scope.outputs.latest-per-major }}' -eq 'true') { $params['LatestPerMajor'] = $true } + Invoke-Build Test @params + + - name: Run tag unit tests + # Verifies Get-ImageTags produces correct Docker tags (pure logic, no Docker required). + # Tag logic is arch-independent — run once on amd64 to avoid duplication. + if: matrix.arch == 'amd64' + shell: pwsh + run: | + Install-Module Pester -Force -SkipPublisherCheck + Invoke-Pester src/tags.tests.ps1 -Output Detailed -CI diff --git a/.github/workflows/publish-fork.yaml b/.github/workflows/publish-fork.yaml new file mode 100644 index 0000000..3a38503 --- /dev/null +++ b/.github/workflows/publish-fork.yaml @@ -0,0 +1,300 @@ +name: publish-fork + +# Build, test and publish Docker images to GitHub Container Registry (ghcr.io). +# - Triggers: Manual dispatch only (workflow_dispatch) +# - Runs on: Any fork (uses built-in GITHUB_TOKEN — no extra secrets required) +# +# Images are published to ghcr.io//firebird +# Default scope: latest Firebird version + trixie (fast, ~2 minutes) +# Default result: ONE package — ghcr.io//firebird — with all expected tags. +# +# With include-arm64=true: publishes ghcr.io//firebird as a multi-arch image. +# Images are pushed by digest (no staging tags) and assembled via +# `docker buildx imagetools create`. +# +# Usage: +# Go to Actions → publish-fork → Run workflow +# Pull with: docker pull ghcr.io//firebird: + +on: + workflow_dispatch: + inputs: + version-filter: + description: 'Version filter (e.g. 5, 5.0.3). Empty = latest only.' + required: false + type: string + distro-filter: + description: 'Distro filter (e.g. trixie, bookworm, jammy). Empty = default distro (trixie).' + required: false + type: string + include-arm64: + description: 'Also build ARM64 images (takes ~2x longer).' + required: false + type: boolean + default: false + include-snapshots: + description: 'Also build and publish snapshot images (6-snapshot, 5-snapshot).' + required: false + type: boolean + default: false + +# Only one run at a time per fork. +concurrency: + group: ${{ github.workflow }}-${{ github.repository }} + cancel-in-progress: true + +env: + REGISTRY: ghcr.io/${{ github.repository_owner }} + IMAGE_NAME: firebird + +jobs: + determine-scope: + runs-on: ubuntu-latest + outputs: + version-filter: ${{ steps.scope.outputs.version-filter }} + distro-filter: ${{ steps.scope.outputs.distro-filter }} + matrix: ${{ steps.scope.outputs.matrix }} + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Determine build scope + id: scope + shell: pwsh + run: | + $assets = Get-Content -Raw ./assets.json | ConvertFrom-Json + + # Use input or default to latest version + default distro + $vf = '${{ inputs.version-filter }}' + $df = '${{ inputs.distro-filter }}' + if (-not $vf) { $vf = $assets.versions[0].version } + if (-not $df) { $df = $assets.config.defaultDistro } + + "version-filter=$vf" >> $env:GITHUB_OUTPUT + "distro-filter=$df" >> $env:GITHUB_OUTPUT + + # Build arch matrix based on input + $includeArm64 = '${{ inputs.include-arm64 }}' -eq 'true' + $matrix = if ($includeArm64) { + '{"arch":["amd64","arm64"],"include":[{"arch":"amd64","runner":"ubuntu-latest"},{"arch":"arm64","runner":"ubuntu-24.04-arm"}]}' + } else { + '{"arch":["amd64"],"include":[{"arch":"amd64","runner":"ubuntu-latest"}]}' + } + "matrix=$matrix" >> $env:GITHUB_OUTPUT + + build-and-push: + needs: determine-scope + permissions: + packages: write + strategy: + fail-fast: false + matrix: ${{ fromJSON(needs.determine-scope.outputs.matrix) }} + runs-on: ${{ matrix.runner }} + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Install tools + shell: pwsh + run: | + Install-Module InvokeBuild -Force + Install-Module PSFirebird -MinimumVersion '1.0.0' -Force + + - name: Build + shell: pwsh + run: | + Invoke-Build Build ` + -VersionFilter '${{ needs.determine-scope.outputs.version-filter }}' ` + -DistributionFilter '${{ needs.determine-scope.outputs.distro-filter }}' ` + -Registry '${{ env.REGISTRY }}' + + - name: Test + shell: pwsh + run: | + Invoke-Build Test ` + -VersionFilter '${{ needs.determine-scope.outputs.version-filter }}' ` + -DistributionFilter '${{ needs.determine-scope.outputs.distro-filter }}' ` + -Registry '${{ env.REGISTRY }}' + + - name: Login to GitHub Container Registry + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + # amd64-only: push as the final image name — produces exactly ONE package. + - name: Push (amd64 only — final name, no staging) + if: ${{ !inputs.include-arm64 }} + shell: pwsh + run: | + Invoke-Build Publish-Direct ` + -VersionFilter '${{ needs.determine-scope.outputs.version-filter }}' ` + -DistributionFilter '${{ needs.determine-scope.outputs.distro-filter }}' ` + -Registry '${{ env.REGISTRY }}' + + # multi-arch: push images by digest (no staging tags created). + - name: Push image digests + if: ${{ inputs.include-arm64 }} + shell: pwsh + run: | + Invoke-Build Push-Digests ` + -VersionFilter '${{ needs.determine-scope.outputs.version-filter }}' ` + -DistributionFilter '${{ needs.determine-scope.outputs.distro-filter }}' ` + -Registry '${{ env.REGISTRY }}' + + - name: Upload digests + if: ${{ inputs.include-arm64 }} + uses: actions/upload-artifact@v7 + with: + name: digests-${{ matrix.arch }} + path: generated/digests-*.json + if-no-files-found: error + retention-days: 1 + + - name: Build and push snapshot images + if: ${{ inputs.include-snapshots && matrix.arch == 'amd64' }} + shell: pwsh + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + $assets = Get-Content -Raw ./assets.json | ConvertFrom-Json + $defaultDistro = $assets.config.defaultDistro + foreach ($branch in @('master', 'v5.0-release')) { + Invoke-Build Build-Snapshot -Branch $branch -Registry '${{ env.REGISTRY }}' + $tag = if ($branch -eq 'master') { '6-snapshot' } else { '5-snapshot' } + docker push "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$tag" + docker push "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$tag-$defaultDistro" + } + + # Summary only for the amd64-only case (multi-arch summary is in create-manifests). + - name: Summary + if: ${{ !inputs.include-arm64 && matrix.arch == 'amd64' }} + shell: pwsh + run: | + $vf = '${{ needs.determine-scope.outputs.version-filter }}' + $df = '${{ needs.determine-scope.outputs.distro-filter }}' + $registry = '${{ env.REGISTRY }}' + $imageName = '${{ env.IMAGE_NAME }}' + + $assets = Get-Content -Raw ./assets.json | ConvertFrom-Json + $filtered = $assets.versions | Where-Object { $_.version -like "$vf*" } + $tags = $filtered | ForEach-Object { $_.tags.$df } | Select-Object -First 5 + + @" + ## Published to GitHub Container Registry + + **Registry:** ``$registry/$imageName`` + + ### Pull commands + `````` + $(($tags | ForEach-Object { "docker pull $registry/${imageName}:$_" }) -join "`n") + `````` + "@ >> $env:GITHUB_STEP_SUMMARY + + # Only runs when include-arm64=true. Creates multi-arch OCI manifests from image digests. + create-manifests: + if: ${{ inputs.include-arm64 }} + needs: [determine-scope, build-and-push] + permissions: + packages: write + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Download digests + uses: actions/download-artifact@v8 + with: + path: generated + pattern: digests-* + merge-multiple: true + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Install tools + shell: pwsh + run: | + Install-Module InvokeBuild -Force + Install-Module PSFirebird -MinimumVersion '1.0.0' -Force + + - name: Login to GitHub Container Registry + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Create and push multi-arch manifests + shell: pwsh + run: | + Invoke-Build Publish-Manifests ` + -VersionFilter '${{ needs.determine-scope.outputs.version-filter }}' ` + -DistributionFilter '${{ needs.determine-scope.outputs.distro-filter }}' ` + -Registry '${{ env.REGISTRY }}' + + - name: Summary + shell: pwsh + run: | + $vf = '${{ needs.determine-scope.outputs.version-filter }}' + $df = '${{ needs.determine-scope.outputs.distro-filter }}' + $registry = '${{ env.REGISTRY }}' + $imageName = '${{ env.IMAGE_NAME }}' + + $assets = Get-Content -Raw ./assets.json | ConvertFrom-Json + $filtered = $assets.versions | Where-Object { $_.version -like "$vf*" } + $tags = $filtered | ForEach-Object { $_.tags.$df } | Select-Object -First 5 + + @" + ## Published to GitHub Container Registry (multi-arch) + + **Registry:** ``$registry/$imageName`` + + ### Pull commands + `````` + $(($tags | ForEach-Object { "docker pull $registry/${imageName}:$_" }) -join "`n") + `````` + "@ >> $env:GITHUB_STEP_SUMMARY + + # Generates all Dockerfiles and updates README.md, then commits them back to the repo. + # This ensures Dockerfile links in README.md are always valid on GitHub. + update-repo: + needs: [build-and-push, create-manifests] + if: | + always() && + needs.build-and-push.result == 'success' && + (needs.create-manifests.result == 'success' || needs.create-manifests.result == 'skipped') + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Install tools + shell: pwsh + run: | + Install-Module InvokeBuild -Force + Install-Module PSFirebird -MinimumVersion '1.0.0' -Force + + - name: Generate Dockerfiles and update README + shell: pwsh + run: | + Invoke-Build Prepare + Invoke-Build Update-Readme -Registry '${{ env.REGISTRY }}' + + - name: Commit and push changes + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add generated/ README.md + if git diff --cached --quiet; then + echo "No changes to commit" + else + git commit -m "chore: update generated Dockerfiles and README [skip ci]" + git push + fi diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 827c36d..aa9bfad 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -3,6 +3,10 @@ name: publish # Build, test and publish official Docker images. # - Triggers: Pushes to master and scheduled weekly runs. # - Runs on: Only the official repository (FirebirdSQL/firebird-docker) +# +# Multi-arch: builds amd64 and arm64 natively on separate runners, +# pushes images by digest (no staging tags), then assembles multi-arch +# manifests via `docker buildx imagetools create`. on: push: @@ -19,48 +23,136 @@ concurrency: group: ${{ github.workflow }} jobs: - build-test-and-publish: + build-and-test: if: ${{ github.repository == 'FirebirdSQL/firebird-docker' }} - runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + arch: [amd64, arm64] + include: + - arch: amd64 + runner: ubuntu-latest + - arch: arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 10 + uses: actions/checkout@v6 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 - name: Install tools shell: pwsh run: | Install-Module InvokeBuild -Force + Install-Module PSFirebird -MinimumVersion '1.0.0' -Force - name: Build shell: pwsh run: | - Invoke-Build + Invoke-Build Build - name: Test shell: pwsh run: | Invoke-Build Test + - name: Run tag unit tests + # Verifies Get-ImageTags produces correct Docker tags (pure logic, no Docker required). + # Tag logic is arch-independent — run once on amd64 to avoid duplication. + if: matrix.arch == 'amd64' + shell: pwsh + run: | + Install-Module Pester -Force -SkipPublisherCheck + Invoke-Pester src/tags.tests.ps1 -Output Detailed -CI + - name: Login to Docker Hub - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Publish + - name: Push image digests shell: pwsh run: | - Invoke-Build Publish + Invoke-Build Push-Digests - - name: Upload logs - uses: actions/upload-artifact@v4 - if: always() + - name: Upload digests + uses: actions/upload-artifact@v7 + with: + name: digests-${{ matrix.arch }} + path: generated/digests-*.json + if-no-files-found: error + retention-days: 1 + + create-manifests: + if: ${{ github.repository == 'FirebirdSQL/firebird-docker' }} + needs: build-and-test + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Download digests + uses: actions/download-artifact@v8 + with: + path: generated + pattern: digests-* + merge-multiple: true + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Install tools + shell: pwsh + run: | + Install-Module InvokeBuild -Force + Install-Module PSFirebird -MinimumVersion '1.0.0' -Force + + - name: Login to Docker Hub + uses: docker/login-action@v4 with: - name: publish-logs-${{ github.run_id }} - path: generated/logs - retention-days: 30 # Longer log retention for published images + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Create and push multi-arch manifests + shell: pwsh + run: | + Invoke-Build Publish-Manifests + + # Generates all Dockerfiles and updates README.md, then commits them back to the repo. + # This ensures Dockerfile links in README.md are always valid on GitHub. + update-repo: + if: ${{ github.repository == 'FirebirdSQL/firebird-docker' }} + needs: create-manifests + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Install tools + shell: pwsh + run: | + Install-Module InvokeBuild -Force + Install-Module PSFirebird -MinimumVersion '1.0.0' -Force + + - name: Generate Dockerfiles and update README + shell: pwsh + run: | + Invoke-Build Prepare + Invoke-Build Update-Readme + + - name: Commit and push changes + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add generated/ README.md + if git diff --cached --quiet; then + echo "No changes to commit" + else + git commit -m "chore: update generated Dockerfiles and README [skip ci]" + git push + fi diff --git a/.github/workflows/snapshot.yaml b/.github/workflows/snapshot.yaml new file mode 100644 index 0000000..7de95a1 --- /dev/null +++ b/.github/workflows/snapshot.yaml @@ -0,0 +1,82 @@ +name: snapshot + +# Build and publish snapshot (pre-release) Docker images. +# - Triggers: Scheduled daily and manual dispatch. +# - Runs on: Only the official repository (FirebirdSQL/firebird-docker) +# +# Snapshot images use tags like '6-snapshot', '5-snapshot', '4-snapshot' +# from the FirebirdSQL/snapshots GitHub repository. + +on: + schedule: + - cron: "0 6 * * *" # Daily at 06:00 UTC + + workflow_dispatch: + inputs: + branch: + description: 'Snapshot branch to build' + required: true + type: choice + options: + - master + - v5.0-release + - v4.0 + default: master + +# Only a single instance of this workflow can be in execution at a given time. +concurrency: + group: ${{ github.workflow }} + +jobs: + build-snapshot: + if: ${{ github.repository == 'FirebirdSQL/firebird-docker' }} + strategy: + fail-fast: false + matrix: + branch: ${{ github.event_name == 'workflow_dispatch' && fromJSON(format('["{0}"]', inputs.branch)) || fromJSON('["master", "v5.0-release"]') }} + arch: [amd64, arm64] + include: + - arch: amd64 + runner: ubuntu-latest + - arch: arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Install tools + shell: pwsh + run: | + Install-Module InvokeBuild -Force + Install-Module PSFirebird -MinimumVersion '1.0.0' -Force + + - name: Build snapshot + shell: pwsh + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + Invoke-Build Build-Snapshot -Branch '${{ matrix.branch }}' + + - name: Login to Docker Hub + uses: docker/login-action@v4 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Push snapshot + shell: pwsh + run: | + $branch = '${{ matrix.branch }}' + $tag = switch ($branch) { + 'master' { '6-snapshot' } + 'v5.0-release' { '5-snapshot' } + 'v4.0' { '4-snapshot' } + } + $assets = Get-Content -Raw ./assets.json | ConvertFrom-Json + $defaultDistro = $assets.config.defaultDistro + docker push "firebirdsql/firebird:$tag" + docker push "firebirdsql/firebird:$tag-$defaultDistro" diff --git a/.gitignore b/.gitignore index f7f2006..9ab55e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,5 @@ -# Ignore all files from /generated except Dockerfile and entrypoint.sh -- https://stackoverflow.com/a/72380673 -/generated/* -!/generated/* -/generated/*/* -!/generated/*/* -/generated/*/*/* -!/generated/*/*/Dockerfile -!/generated/*/*/entrypoint.sh +# Temporary files +/tmp/ + +# Logs +*.log diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..cb774d1 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,52 @@ +# AGENTS.md — Guidelines for AI Agents + +## Project +Firebird Docker images. PowerShell (InvokeBuild) build system generating Dockerfiles from templates. + +## Structure +``` +assets.json # Source of truth: versions, URLs, SHA-256, distro config +firebird-docker.build.ps1 # InvokeBuild: Update-Assets, Prepare, Build, Test, Publish +src/Dockerfile.template # Single parameterized Dockerfile ({{VAR}} placeholders) +src/entrypoint.sh # Container entrypoint (bash) +src/image.tests.ps1 # Integration tests (InvokeBuild tasks) +src/README.md.template # README generator +.github/workflows/ # CI, Publish, Snapshot workflows +``` + +## Key Rules +- `assets.json` is the single source of truth. Never hard-code versions or URLs elsewhere. +- Use `{{VAR}}` template syntax (simple string replacement). Never `<% %>` or `ExpandString`. +- PSFirebird v1.0.0+ from PSGallery is a dependency. Do NOT reference `./tmp/PSFirebird/`. +- `./tmp/` is for temporary files only. Never commit or reference in production code. +- Default distro: `bookworm`. Blocked: FB3 + noble (no libncurses5). +- ARM64 only for Firebird 5+. No QEMU — use native ARM64 GitHub runners. +- All tags computed deterministically from version matrix via `Get-ImageTags`. + +## Build Commands +```powershell +Invoke-Build Update-Assets # Refresh assets.json from GitHub +Invoke-Build Prepare # Generate Dockerfiles from template +Invoke-Build Build # Build all images +Invoke-Build Test # Run all tests +Invoke-Build Build -VersionFilter 5 -DistributionFilter bookworm # Filtered +``` + +## Testing +- Tests use `InvokeBuild` tasks in `src/image.tests.ps1` +- Tests require Docker daemon running +- Filter: `-TestFilter 'task_name'` +- PSFirebird used in tests for DB operations via `inet://` protocol + +## Documentation +- `README.md` — End users (auto-generated from template) +- `DEVELOPMENT.md` — Local dev setup, testing, debugging +- `DECISIONS.md` — Architectural Decision Records +- `AGENTS.md` — This file + +## CI/CD +- `ci.yaml` — Build+test on push/PR. Full matrix (amd64 + arm64) on all repos. Forks: latest release per major version only. Official repo or `workflow_dispatch`: all versions. Filtered via workflow_dispatch inputs. +- `publish.yaml` — Official repo only. Build+test+push to Docker Hub. +- `snapshot.yaml` — Snapshot pre-release images from FirebirdSQL/snapshots. + +When pushing commits, use `gh` command to monitor the workflow execution. \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..43eadd0 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,191 @@ +# Contributing + +Thank you for your interest in contributing to Firebird Docker! + +## Prerequisites + +- [Docker](https://docs.docker.com/engine/install/) +- [PowerShell 7.5+](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-linux) +- [Invoke-Build](https://github.com/nightroman/Invoke-Build#install-as-module) +- [PSFirebird](https://www.powershellgallery.com/packages/PSFirebird) (v1.0.0+, installed automatically by build tasks) + + + +## Building + +To generate the source files and build all images from [`assets.json`](assets.json), run: + +```bash +Invoke-Build +``` + +Check all created images with: + +```bash +docker image ls firebirdsql/firebird +``` + +### Filtering builds + +```bash +# Build only Firebird 5.x images +Invoke-Build Build -VersionFilter "5" + +# Build only a specific version +Invoke-Build Build -VersionFilter "5.0.3" + +# Build only bookworm images +Invoke-Build Build -DistributionFilter "bookworm" + +# Combine filters +Invoke-Build Build -VersionFilter "4" -DistributionFilter "jammy" +``` + +### Building for a fork registry + +Use `-Registry` to redirect all image tags to a different registry (e.g. GitHub Container Registry): + +```bash +# Build tagged for ghcr.io (fork testing) +Invoke-Build Build -VersionFilter "5.0.3" -DistributionFilter "bookworm" -Registry "ghcr.io/myusername" +``` + + + +## Testing + +```bash +Invoke-Build Test +``` + +### Filtering tests + +```bash +# Test only Firebird 4.x images +Invoke-Build Test -VersionFilter "4" + +# Test only bullseye images +Invoke-Build Test -DistributionFilter "bullseye" + +# Run a single test by name +Invoke-Build Test -TestFilter "FIREBIRD_USER_can_create_user" + +# Combine filters +Invoke-Build Test -VersionFilter "5" -DistributionFilter "noble" +``` + +### Testing published registry images + +Use `Test-Published` to run the full test suite against images already pushed to a registry (the same final images end users pull). Requires `-Registry`. + +```bash +# Test all images published to a fork's ghcr.io registry +Invoke-Build Test-Published -Registry "ghcr.io/myusername" + +# Narrow down to a specific version + distro +Invoke-Build Test-Published -Registry "ghcr.io/myusername" -VersionFilter "5.0.3" -DistributionFilter "bookworm" + +# Test the official Docker Hub images +Invoke-Build Test-Published -Registry "firebirdsql" +``` + +Unlike `Test` (which tests locally built arch-specific images), `Test-Published` pulls and tests the final multi-arch manifest — exactly what a user would run. + +For snapshot images (not in `assets.json`), set `FULL_IMAGE_NAME` directly: + +```bash +$env:FULL_IMAGE_NAME = "ghcr.io/myusername/firebird:6-snapshot" +Invoke-Build * ./src/image.tests.ps1 +``` + +### Tag unit tests + +```bash +Install-Module Pester -Force -SkipPublisherCheck +Invoke-Pester src/tags.tests.ps1 -Output Detailed +``` + + + +## Maintenance tasks + +```bash +# Refresh assets.json from GitHub releases (requires network) +Invoke-Build Update-Assets + +# Regenerate README.md from assets.json +Invoke-Build Update-Readme + +# Regenerate Dockerfiles from template +Invoke-Build Prepare + +# Delete generated files +Invoke-Build Clean +``` + + + +## Following a new Firebird release + +Once a new Firebird release is published on GitHub: + +```bash +# 1. Refresh assets.json (downloads new URLs and SHA-256 hashes) +Invoke-Build Update-Assets + +# 2. Regenerate README.md +Invoke-Build Update-Readme + +# 3. Regenerate Dockerfiles +Invoke-Build Prepare + +# 4. Stage all changes +git add -u + +# 5. Commit +git commit -m "Add Firebird X.Y.Z" +``` + + + +## Project Structure + +- `assets.json` — Single source of truth for versions, URLs, SHA-256 hashes, and distro config. +- `firebird-docker.build.ps1` — InvokeBuild script with all tasks (Build, Test, Publish, etc.). +- `src/Dockerfile.template` — Single parameterized Dockerfile using `{{VAR}}` placeholders. +- `src/entrypoint.sh` — Container entrypoint script. +- `src/functions.ps1` — Shared functions (tag generation, template expansion, distro config). +- `src/image.tests.ps1` — Integration test suite (Docker required). +- `src/tags.tests.ps1` — Tag unit tests (Pester, no Docker required). +- `src/README.md.template` — README template (`{{SupportedTags}}` is replaced at generation time). +- `generated/` — Output of the `Prepare` task. Auto-generated — do not edit manually. + + + +## Generated files + +The `generated/` directory and `README.md` are produced from `assets.json` + `src/` templates. They are **tracked in git** so the README's per-variant `Dockerfile` links resolve on GitHub. + +- **Do not edit files under `generated/` by hand.** Edit `assets.json` or the templates in `src/`, then run `Invoke-Build Prepare` (Dockerfiles) and `Invoke-Build Update-Readme` (README). +- After a successful publish, the `update-repo` CI job regenerates and auto-commits any drift with `[skip ci]`. Manual commits are still welcome; CI just guarantees the tip of `master` is always in sync. +- A local pre-commit hook (`.githooks/pre-commit`) regenerates when `assets.json` is staged and warns if `generated/` or `README.md` end up out of sync. Enable it once per clone: + +```bash +git config core.hooksPath .githooks +``` + + + +## Key Rules + +1. **`assets.json` is the single source of truth.** Never hard-code versions or URLs elsewhere. +2. **Template syntax is `{{VAR}}`.** Simple string replacement only — never `ExpandString` or `<% %>`. +3. **All tests must pass before submitting a PR.** +4. **ARM64 uses native runners only.** Never QEMU. +5. **Never hand-edit `generated/`.** Regenerate via `Invoke-Build Prepare` and stage the result. + + + +## Reporting Issues + +Please open an issue on [GitHub Issues](https://github.com/fdcastel/firebird-docker-fork/issues). diff --git a/DECISIONS.md b/DECISIONS.md new file mode 100644 index 0000000..46350fb --- /dev/null +++ b/DECISIONS.md @@ -0,0 +1,99 @@ +# Architecture Decisions + +Decisions made during the v2 rewrite, with rationale. + +## D-001: Single Dockerfile.template + +**Decision:** Replace 4 per-distro templates with a single parameterized `src/Dockerfile.template`. + +**Rationale:** The old templates were nearly identical, differing only in base image, ICU package, and extra packages. Distro-specific config is now in `assets.json` `config.distros` and injected via `{{VAR}}` placeholders. + +## D-002: Safe template expansion + +**Decision:** Replace `Expand-Template` (which used `$ExecutionContext.InvokeCommand.ExpandString`) with `{{VAR}}` string replacement. + +**Rationale:** `ExpandString` evaluates arbitrary PowerShell expressions, creating a code injection risk. The new `Expand-TemplateFile` function only replaces `{{KEY}}` with values from a hashtable — no expression evaluation. + +## D-003: Tag algorithm + +**Decision:** Deterministic tag generation via `Get-ImageTags` function with parameters: Version, Distro, IsLatestOfMajor, IsLatestOverall, DefaultDistro. + +**Tags produced:** +- Always: `{version}-{distro}` (e.g. `5.0.3-bookworm`) +- If latest of major: `{major}-{distro}` (e.g. `5-bookworm`) +- If latest overall: `{distro}` (e.g. `bookworm`) +- Default distro only: `{version}`, `{major}`, `latest` + +**Rationale:** Every image has a fully-qualified immutable tag. The `-{distro}` suffix (Issue #34) enables pulling specific OS variants. Only the default distro gets bare tags to avoid confusion. + +## D-004: Tini as PID 1 + +**Decision:** Install `tini` in the image and use `ENTRYPOINT ["tini", "--"]` instead of running entrypoint.sh as PID 1. + +**Rationale:** Shell scripts don't handle signals properly as PID 1 (no zombie reaping, inconsistent SIGTERM forwarding). Tini is the standard solution, weighing ~20KB. + +## D-005: STOPSIGNAL SIGTERM + +**Decision:** Set `STOPSIGNAL SIGTERM` in the Dockerfile. + +**Rationale:** Firebird's fbguard/firebird processes handle SIGTERM for graceful shutdown. Docker's default is also SIGTERM, but being explicit documents the intent. + +## D-006: SQL injection prevention in entrypoint.sh + +**Decision:** Escape single quotes in passwords via `escape_sql_string()` before interpolating into SQL. + +**Rationale:** Passwords like `it's_me` would break SQL syntax or enable injection. The function doubles single quotes (`'` → `''`), which is the standard SQL escape. + +## D-007: blockedVariants in assets.json + +**Decision:** Use a `blockedVariants` config map to exclude incompatible version+distro combinations (e.g. FB3 on Noble). + +**Rationale:** Firebird 3 depends on `libncurses5`, which was removed from Ubuntu Noble. Rather than special-casing in code, we declare blocked combinations in config. + +## D-008: Fork CI scope — latest release per major version + +**Decision:** On forks (non-official repo, non-`workflow_dispatch`), CI builds and tests only the latest release of each major Firebird version (e.g. 5.0.3, 4.0.6, 3.0.13). The official repository always performs a full build of all versions. + +**Rationale:** A full matrix (17 versions × 4 distros × 2 arches) takes 17+ minutes on forks where contributors verify a single change. The latest of each major is sufficient to catch regressions across the version range. The official repo and manual `workflow_dispatch` runs always build everything. Controlled via the `LatestPerMajor` switch in `firebird-docker.build.ps1`. + +## D-009: No QEMU in CI + +**Decision:** Build only the host architecture locally and in CI. Multi-arch manifests are created during publish using native runners. + +**Rationale:** QEMU builds are 5-10x slower and unreliable. When ARM64 runners are available, they build natively. + +## D-010: PSFirebird for release discovery + +**Decision:** Use the `PSFirebird` PowerShell module (`Find-FirebirdRelease`, `Find-FirebirdSnapshotRelease`) instead of custom GitHub API calls. + +**Rationale:** Centralizes Firebird release parsing, SHA256 verification, and snapshot discovery. Published on PSGallery as `PSFirebird` v1.0.0+. + +## D-011: Snapshot images + +**Decision:** Daily snapshot builds from `master` (FB6) and `v5.0-release` branches, tagged as `{major}-snapshot`. + +**Rationale:** Pre-release testing is valuable for the community. Snapshot tags are clearly distinguished and never collide with release tags. + +## D-012: Trixie as default distro + +**Decision:** The `defaultDistro` in `assets.json` is `trixie` (Debian 13). Bare tags (`5.0.4`, `5`, `latest`) resolve to the Trixie variant. + +**Rationale:** Trixie is the current Debian stable — it ships newer library versions (libicu76, OpenSSL 3.x, glibc 2.41) that match what a fresh deployment would pull elsewhere. Bookworm remains available as `*-bookworm` tags for users who prefer the previous LTS for production stability. Users who want to pin should use the explicit `*-bookworm` or `*-bullseye` tags; the bare tags move forward with Debian stable. + +## D-013: Digest-based multi-arch assembly + +**Decision:** Use `docker buildx` with `push-by-digest=true` to push per-arch images without creating any staging tags. Multi-arch manifests are assembled via `docker buildx imagetools create` from raw SHA256 digests. + +**Rationale:** The previous approach pushed staging tags (`firebird:tag-amd64`, `firebird:tag-arm64`) into the main Docker Hub package, polluting it with implementation artifacts. The digest-based approach — used by major projects like `postgres`, `nginx`, and `redis` — keeps the registry clean. Image digests are passed between GitHub Actions jobs via artifacts. + +## D-014: Generated Dockerfiles are tracked in git + +**Decision:** The `generated/` directory is committed to the repository. After a successful publish, a workflow job (`update-repo`) regenerates the Dockerfiles and README and auto-commits any changes with `[skip ci]`. + +**Rationale:** README links to per-variant `Dockerfile`s (e.g. `generated/5.0.4/trixie/Dockerfile`) need valid targets on GitHub. Keeping the output in git guarantees the links work without requiring contributors to regenerate locally. Auto-commit prevents drift: the committed files always reflect the last successful publish. Contributors must not edit `generated/` by hand — run `Invoke-Build Prepare` to regenerate. The `[skip ci]` marker on the auto-commit prevents a trigger loop. + +## D-015: No ARM64 for Firebird 3.x / 4.x + +**Decision:** The ARM64 discovery gate in `Update-Assets` is `$majorVersion -ge 5`. FB3 and FB4 are published as amd64-only, even though `.arm64.tar.gz` assets exist in their GitHub releases. + +**Rationale:** The FB3/FB4 `.arm64.tar.gz` files are **Android builds with a misleading filename**, not Linux ARM64 — confirmed by asfernandes in [FirebirdSQL/firebird-docker#38](https://github.com/FirebirdSQL/firebird-docker/issues/38): "These are Android builds manually built by Alex. Names are very misleading. But better names were introduced in v5 only, as well Linux ARM* packages." Their internal layout reflects this (pre-extracted `firebird/` tree with `AfterUntar.sh`, no `install.sh`), which is why our Dockerfile template cannot consume them — but the deeper reason is that they are fundamentally the wrong binaries for a Linux container. No upstream packaging fix will change this for existing FB3/FB4 releases; any future "teach the template two install paths" workaround would install Android binaries on Linux and must be rejected. When FB3.x or FB4.x ships a future point release with a true Linux ARM64 bundle, the gate can be widened on a per-version basis. diff --git a/README.md b/README.md index 8a13c08..04eae15 100644 --- a/README.md +++ b/README.md @@ -17,75 +17,121 @@ Docker images for Firebird Database. # Supported tags -|`firebirdsql/firebird`|Dockerfile| +|`ghcr.io/fdcastel/firebird`|Dockerfile| |:-|:-:| -|`5`, `5.0.3`, `latest`|[Dockerfile](./generated/5.0.3/bookworm/Dockerfile)| - |`bullseye`, `5-bullseye`, `5.0.3-bullseye`|[Dockerfile](./generated/5.0.3/bullseye/Dockerfile)| - |`jammy`, `5-jammy`, `5.0.3-jammy`|[Dockerfile](./generated/5.0.3/jammy/Dockerfile)| - |`noble`, `5-noble`, `5.0.3-noble`|[Dockerfile](./generated/5.0.3/noble/Dockerfile)| - |`5.0.2`|[Dockerfile](./generated/5.0.2/bookworm/Dockerfile)| - |`5.0.2-bullseye`|[Dockerfile](./generated/5.0.2/bullseye/Dockerfile)| - |`5.0.2-jammy`|[Dockerfile](./generated/5.0.2/jammy/Dockerfile)| - |`5.0.2-noble`|[Dockerfile](./generated/5.0.2/noble/Dockerfile)| - |`5.0.1`|[Dockerfile](./generated/5.0.1/bookworm/Dockerfile)| - |`5.0.1-bullseye`|[Dockerfile](./generated/5.0.1/bullseye/Dockerfile)| - |`5.0.1-jammy`|[Dockerfile](./generated/5.0.1/jammy/Dockerfile)| - |`5.0.1-noble`|[Dockerfile](./generated/5.0.1/noble/Dockerfile)| - |`5.0.0`|[Dockerfile](./generated/5.0.0/bookworm/Dockerfile)| - |`5.0.0-bullseye`|[Dockerfile](./generated/5.0.0/bullseye/Dockerfile)| - |`5.0.0-jammy`|[Dockerfile](./generated/5.0.0/jammy/Dockerfile)| - |`5.0.0-noble`|[Dockerfile](./generated/5.0.0/noble/Dockerfile)| - |`4`, `4.0.6`|[Dockerfile](./generated/4.0.6/bookworm/Dockerfile)| - |`4-bullseye`, `4.0.6-bullseye`|[Dockerfile](./generated/4.0.6/bullseye/Dockerfile)| - |`4-jammy`, `4.0.6-jammy`|[Dockerfile](./generated/4.0.6/jammy/Dockerfile)| - |`4-noble`, `4.0.6-noble`|[Dockerfile](./generated/4.0.6/noble/Dockerfile)| - |`4.0.5`|[Dockerfile](./generated/4.0.5/bookworm/Dockerfile)| - |`4.0.5-bullseye`|[Dockerfile](./generated/4.0.5/bullseye/Dockerfile)| - |`4.0.5-jammy`|[Dockerfile](./generated/4.0.5/jammy/Dockerfile)| - |`4.0.5-noble`|[Dockerfile](./generated/4.0.5/noble/Dockerfile)| - |`4.0.4`|[Dockerfile](./generated/4.0.4/bookworm/Dockerfile)| - |`4.0.4-bullseye`|[Dockerfile](./generated/4.0.4/bullseye/Dockerfile)| - |`4.0.4-jammy`|[Dockerfile](./generated/4.0.4/jammy/Dockerfile)| - |`4.0.4-noble`|[Dockerfile](./generated/4.0.4/noble/Dockerfile)| - |`4.0.3`|[Dockerfile](./generated/4.0.3/bookworm/Dockerfile)| - |`4.0.3-bullseye`|[Dockerfile](./generated/4.0.3/bullseye/Dockerfile)| - |`4.0.3-jammy`|[Dockerfile](./generated/4.0.3/jammy/Dockerfile)| - |`4.0.3-noble`|[Dockerfile](./generated/4.0.3/noble/Dockerfile)| - |`4.0.2`|[Dockerfile](./generated/4.0.2/bookworm/Dockerfile)| - |`4.0.2-bullseye`|[Dockerfile](./generated/4.0.2/bullseye/Dockerfile)| - |`4.0.2-jammy`|[Dockerfile](./generated/4.0.2/jammy/Dockerfile)| - |`4.0.2-noble`|[Dockerfile](./generated/4.0.2/noble/Dockerfile)| - |`4.0.1`|[Dockerfile](./generated/4.0.1/bookworm/Dockerfile)| - |`4.0.1-bullseye`|[Dockerfile](./generated/4.0.1/bullseye/Dockerfile)| - |`4.0.1-jammy`|[Dockerfile](./generated/4.0.1/jammy/Dockerfile)| - |`4.0.1-noble`|[Dockerfile](./generated/4.0.1/noble/Dockerfile)| - |`4.0.0`|[Dockerfile](./generated/4.0.0/bookworm/Dockerfile)| - |`4.0.0-bullseye`|[Dockerfile](./generated/4.0.0/bullseye/Dockerfile)| - |`4.0.0-jammy`|[Dockerfile](./generated/4.0.0/jammy/Dockerfile)| - |`4.0.0-noble`|[Dockerfile](./generated/4.0.0/noble/Dockerfile)| - |`3`, `3.0.13`|[Dockerfile](./generated/3.0.13/bookworm/Dockerfile)| - |`3-bullseye`, `3.0.13-bullseye`|[Dockerfile](./generated/3.0.13/bullseye/Dockerfile)| - |`3-jammy`, `3.0.13-jammy`|[Dockerfile](./generated/3.0.13/jammy/Dockerfile)| - |`3.0.12`|[Dockerfile](./generated/3.0.12/bookworm/Dockerfile)| - |`3.0.12-bullseye`|[Dockerfile](./generated/3.0.12/bullseye/Dockerfile)| - |`3.0.12-jammy`|[Dockerfile](./generated/3.0.12/jammy/Dockerfile)| - |`3.0.11`|[Dockerfile](./generated/3.0.11/bookworm/Dockerfile)| - |`3.0.11-bullseye`|[Dockerfile](./generated/3.0.11/bullseye/Dockerfile)| - |`3.0.11-jammy`|[Dockerfile](./generated/3.0.11/jammy/Dockerfile)| - |`3.0.10`|[Dockerfile](./generated/3.0.10/bookworm/Dockerfile)| - |`3.0.10-bullseye`|[Dockerfile](./generated/3.0.10/bullseye/Dockerfile)| - |`3.0.10-jammy`|[Dockerfile](./generated/3.0.10/jammy/Dockerfile)| - |`3.0.9`|[Dockerfile](./generated/3.0.9/bookworm/Dockerfile)| - |`3.0.9-bullseye`|[Dockerfile](./generated/3.0.9/bullseye/Dockerfile)| - |`3.0.9-jammy`|[Dockerfile](./generated/3.0.9/jammy/Dockerfile)| - |`3.0.8`|[Dockerfile](./generated/3.0.8/bookworm/Dockerfile)| - |`3.0.8-bullseye`|[Dockerfile](./generated/3.0.8/bullseye/Dockerfile)| - |`3.0.8-jammy`|[Dockerfile](./generated/3.0.8/jammy/Dockerfile)| +|`5.0.4-bookworm`, `5-bookworm`, `bookworm`|[Dockerfile](./generated/5.0.4/bookworm/Dockerfile)| +|`5.0.4-bullseye`, `5-bullseye`, `bullseye`|[Dockerfile](./generated/5.0.4/bullseye/Dockerfile)| +|`5.0.4-jammy`, `5-jammy`, `jammy`|[Dockerfile](./generated/5.0.4/jammy/Dockerfile)| +|`5.0.4-noble`, `5-noble`, `noble`|[Dockerfile](./generated/5.0.4/noble/Dockerfile)| +|`5.0.4-trixie`, `5-trixie`, `trixie`, `5.0.4`, `5`, `latest`|[Dockerfile](./generated/5.0.4/trixie/Dockerfile)| +|`5.0.3-bookworm`|[Dockerfile](./generated/5.0.3/bookworm/Dockerfile)| +|`5.0.3-bullseye`|[Dockerfile](./generated/5.0.3/bullseye/Dockerfile)| +|`5.0.3-jammy`|[Dockerfile](./generated/5.0.3/jammy/Dockerfile)| +|`5.0.3-noble`|[Dockerfile](./generated/5.0.3/noble/Dockerfile)| +|`5.0.3-trixie`, `5.0.3`|[Dockerfile](./generated/5.0.3/trixie/Dockerfile)| +|`5.0.2-bookworm`|[Dockerfile](./generated/5.0.2/bookworm/Dockerfile)| +|`5.0.2-bullseye`|[Dockerfile](./generated/5.0.2/bullseye/Dockerfile)| +|`5.0.2-jammy`|[Dockerfile](./generated/5.0.2/jammy/Dockerfile)| +|`5.0.2-noble`|[Dockerfile](./generated/5.0.2/noble/Dockerfile)| +|`5.0.2-trixie`, `5.0.2`|[Dockerfile](./generated/5.0.2/trixie/Dockerfile)| +|`5.0.1-bookworm`|[Dockerfile](./generated/5.0.1/bookworm/Dockerfile)| +|`5.0.1-bullseye`|[Dockerfile](./generated/5.0.1/bullseye/Dockerfile)| +|`5.0.1-jammy`|[Dockerfile](./generated/5.0.1/jammy/Dockerfile)| +|`5.0.1-noble`|[Dockerfile](./generated/5.0.1/noble/Dockerfile)| +|`5.0.1-trixie`, `5.0.1`|[Dockerfile](./generated/5.0.1/trixie/Dockerfile)| +|`5.0.0-bookworm`|[Dockerfile](./generated/5.0.0/bookworm/Dockerfile)| +|`5.0.0-bullseye`|[Dockerfile](./generated/5.0.0/bullseye/Dockerfile)| +|`5.0.0-jammy`|[Dockerfile](./generated/5.0.0/jammy/Dockerfile)| +|`5.0.0-noble`|[Dockerfile](./generated/5.0.0/noble/Dockerfile)| +|`5.0.0-trixie`, `5.0.0`|[Dockerfile](./generated/5.0.0/trixie/Dockerfile)| +|`4.0.7-bookworm`, `4-bookworm`|[Dockerfile](./generated/4.0.7/bookworm/Dockerfile)| +|`4.0.7-bullseye`, `4-bullseye`|[Dockerfile](./generated/4.0.7/bullseye/Dockerfile)| +|`4.0.7-jammy`, `4-jammy`|[Dockerfile](./generated/4.0.7/jammy/Dockerfile)| +|`4.0.7-noble`, `4-noble`|[Dockerfile](./generated/4.0.7/noble/Dockerfile)| +|`4.0.7-trixie`, `4-trixie`, `4.0.7`, `4`|[Dockerfile](./generated/4.0.7/trixie/Dockerfile)| +|`4.0.6-bookworm`|[Dockerfile](./generated/4.0.6/bookworm/Dockerfile)| +|`4.0.6-bullseye`|[Dockerfile](./generated/4.0.6/bullseye/Dockerfile)| +|`4.0.6-jammy`|[Dockerfile](./generated/4.0.6/jammy/Dockerfile)| +|`4.0.6-noble`|[Dockerfile](./generated/4.0.6/noble/Dockerfile)| +|`4.0.6-trixie`, `4.0.6`|[Dockerfile](./generated/4.0.6/trixie/Dockerfile)| +|`4.0.5-bookworm`|[Dockerfile](./generated/4.0.5/bookworm/Dockerfile)| +|`4.0.5-bullseye`|[Dockerfile](./generated/4.0.5/bullseye/Dockerfile)| +|`4.0.5-jammy`|[Dockerfile](./generated/4.0.5/jammy/Dockerfile)| +|`4.0.5-noble`|[Dockerfile](./generated/4.0.5/noble/Dockerfile)| +|`4.0.5-trixie`, `4.0.5`|[Dockerfile](./generated/4.0.5/trixie/Dockerfile)| +|`4.0.4-bookworm`|[Dockerfile](./generated/4.0.4/bookworm/Dockerfile)| +|`4.0.4-bullseye`|[Dockerfile](./generated/4.0.4/bullseye/Dockerfile)| +|`4.0.4-jammy`|[Dockerfile](./generated/4.0.4/jammy/Dockerfile)| +|`4.0.4-noble`|[Dockerfile](./generated/4.0.4/noble/Dockerfile)| +|`4.0.4-trixie`, `4.0.4`|[Dockerfile](./generated/4.0.4/trixie/Dockerfile)| +|`4.0.3-bookworm`|[Dockerfile](./generated/4.0.3/bookworm/Dockerfile)| +|`4.0.3-bullseye`|[Dockerfile](./generated/4.0.3/bullseye/Dockerfile)| +|`4.0.3-jammy`|[Dockerfile](./generated/4.0.3/jammy/Dockerfile)| +|`4.0.3-noble`|[Dockerfile](./generated/4.0.3/noble/Dockerfile)| +|`4.0.3-trixie`, `4.0.3`|[Dockerfile](./generated/4.0.3/trixie/Dockerfile)| +|`4.0.2-bookworm`|[Dockerfile](./generated/4.0.2/bookworm/Dockerfile)| +|`4.0.2-bullseye`|[Dockerfile](./generated/4.0.2/bullseye/Dockerfile)| +|`4.0.2-jammy`|[Dockerfile](./generated/4.0.2/jammy/Dockerfile)| +|`4.0.2-noble`|[Dockerfile](./generated/4.0.2/noble/Dockerfile)| +|`4.0.2-trixie`, `4.0.2`|[Dockerfile](./generated/4.0.2/trixie/Dockerfile)| +|`4.0.1-bookworm`|[Dockerfile](./generated/4.0.1/bookworm/Dockerfile)| +|`4.0.1-bullseye`|[Dockerfile](./generated/4.0.1/bullseye/Dockerfile)| +|`4.0.1-jammy`|[Dockerfile](./generated/4.0.1/jammy/Dockerfile)| +|`4.0.1-noble`|[Dockerfile](./generated/4.0.1/noble/Dockerfile)| +|`4.0.1-trixie`, `4.0.1`|[Dockerfile](./generated/4.0.1/trixie/Dockerfile)| +|`4.0.0-bookworm`|[Dockerfile](./generated/4.0.0/bookworm/Dockerfile)| +|`4.0.0-bullseye`|[Dockerfile](./generated/4.0.0/bullseye/Dockerfile)| +|`4.0.0-jammy`|[Dockerfile](./generated/4.0.0/jammy/Dockerfile)| +|`4.0.0-noble`|[Dockerfile](./generated/4.0.0/noble/Dockerfile)| +|`4.0.0-trixie`, `4.0.0`|[Dockerfile](./generated/4.0.0/trixie/Dockerfile)| +|`3.0.14-bookworm`, `3-bookworm`|[Dockerfile](./generated/3.0.14/bookworm/Dockerfile)| +|`3.0.14-bullseye`, `3-bullseye`|[Dockerfile](./generated/3.0.14/bullseye/Dockerfile)| +|`3.0.14-jammy`, `3-jammy`|[Dockerfile](./generated/3.0.14/jammy/Dockerfile)| +|`3.0.13-bookworm`|[Dockerfile](./generated/3.0.13/bookworm/Dockerfile)| +|`3.0.13-bullseye`|[Dockerfile](./generated/3.0.13/bullseye/Dockerfile)| +|`3.0.13-jammy`|[Dockerfile](./generated/3.0.13/jammy/Dockerfile)| +|`3.0.12-bookworm`|[Dockerfile](./generated/3.0.12/bookworm/Dockerfile)| +|`3.0.12-bullseye`|[Dockerfile](./generated/3.0.12/bullseye/Dockerfile)| +|`3.0.12-jammy`|[Dockerfile](./generated/3.0.12/jammy/Dockerfile)| +|`3.0.11-bookworm`|[Dockerfile](./generated/3.0.11/bookworm/Dockerfile)| +|`3.0.11-bullseye`|[Dockerfile](./generated/3.0.11/bullseye/Dockerfile)| +|`3.0.11-jammy`|[Dockerfile](./generated/3.0.11/jammy/Dockerfile)| +|`3.0.10-bookworm`|[Dockerfile](./generated/3.0.10/bookworm/Dockerfile)| +|`3.0.10-bullseye`|[Dockerfile](./generated/3.0.10/bullseye/Dockerfile)| +|`3.0.10-jammy`|[Dockerfile](./generated/3.0.10/jammy/Dockerfile)| +|`3.0.9-bookworm`|[Dockerfile](./generated/3.0.9/bookworm/Dockerfile)| +|`3.0.9-bullseye`|[Dockerfile](./generated/3.0.9/bullseye/Dockerfile)| +|`3.0.9-jammy`|[Dockerfile](./generated/3.0.9/jammy/Dockerfile)| > _Firebird 3 does not have an image for Ubuntu 24.04 LTS (Noble Numbat) due to a dependency (`libncurses5`) missing from Ubuntu sources._ +## Snapshot (pre-release) images + +Pre-release builds from the Firebird development branches are available as snapshot images: + +| Tag | Source Branch | Description | +|-----|---------------|-------------| +| `6-snapshot` | `master` | Firebird 6.x development builds | +| `5-snapshot` | `v5.0-release` | Firebird 5.x next-patch builds | + +> **Warning:** Snapshot images are built from unreleased code and may be unstable. They are rebuilt daily and replaced on each build. Do not use in production. + +```bash +# Pull latest Firebird 6.x development snapshot +docker pull firebirdsql/firebird:6-snapshot + +# Pull latest Firebird 5.x patch snapshot +docker pull firebirdsql/firebird:5-snapshot +``` + + +## Architectures + +Images for Firebird 5.x and later are available for both `linux/amd64` and `linux/arm64`. Firebird 3.x and 4.x images are `linux/amd64` only. + + # How to use this image @@ -302,120 +348,3 @@ More information: - [Quick Guide for Gbak Backup-Restore](https://ib-aid.com/articles/firebird-gbak-backup-tips-and-tricks) from IBSurgeon. - -# Development notes - -## Prerequisites - - - [Docker](https://docs.docker.com/engine/install/) - - [Powershell 7.5+](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-linux) - - [Invoke-Build](https://github.com/nightroman/Invoke-Build#install-as-module) - - - -## Building - -To generate the source files and build each image from [`assets.json`](assets.json) configuration file, run: - -```bash -Invoke-Build -``` - -You can then check all created images with: - -```bash -docker image ls firebirdsql/firebird -``` - -### Filtering builds - -> You can filter builds by **version** or **distribution**: - -```bash -# Build only Firebird 5.x images -Invoke-Build Build -VersionFilter "5" - -# Build only specific version -Invoke-Build Build -VersionFilter "5.0.2" - -# Build only bookworm distribution images -Invoke-Build Build -DistributionFilter "bookworm" - -# Combine filters -Invoke-Build Build -VersionFilter "4" -DistributionFilter "jammy" -``` - - - -## Testing - -To run the test suite for each image, use: - -```bash -Invoke-Build Test -``` - -### Filtering tests - -You can filter tests by **version**, **distribution**, or a specific **test name**: - -```bash -# Test only Firebird 4.x images -Invoke-Build Test -VersionFilter "4" - -# Test only bullseye distribution images -Invoke-Build Test -DistributionFilter "bullseye" - -# Run specific test -Invoke-Build Test -TestFilter "FIREBIRD_USER_can_create_user" - -# Combine filters -Invoke-Build Test -VersionFilter "5" -DistributionFilter "noble" -``` - - - -## Maintenance tasks - -The build script includes additional tasks dedicated to maintaining this project. - -```bash -# Update assets.json from GitHub releases -Invoke-Build Update-Assets - -# Update README.md from assets.json -Invoke-Build Update-Readme - -# Regenerate source files -Invoke-Build Prepare - -# Clean up generated files -Invoke-Build Clean -``` - - - -## Following a new Firebird release - -Once a new Firebird release is published, follow these steps to update all relevant files in this repository: - -```bash -# Update assets.json from GitHub releases -Invoke-Build Update-Assets - -# Update README.md from assets.json -Invoke-Build Update-Readme - -# Regenerate source files -Invoke-Build Prepare - -# Adds all untracked files -git add -u - -# Remove logs from staging area -git reset -- generated/logs/ - -# Commit -git commit -M "Adds Firebird ..." -``` - diff --git a/assets.json b/assets.json index ff0dace..c0f826b 100644 --- a/assets.json +++ b/assets.json @@ -1,422 +1,434 @@ -[ - { - "version": "5.0.3", - "releases": [ - { - "arm64": { - "url": "https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-arm64.tar.gz", - "sha256": "e375341466e625bf17e4416723c1465a646d44903011ac4b89f84afe1df3633e" - } +{ + "config": { + "defaultDistro": "trixie", + "distros": { + "bookworm": { + "baseImage": "debian:bookworm-slim", + "icuPackage": "libicu72", + "extraPackages": "" }, - { - "amd64": { - "url": "https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-x64.tar.gz", - "sha256": "ef281c53f85756288151a86831375c9ae668caaeccd1b18103d523ba8f444779" - } + "bullseye": { + "baseImage": "debian:bullseye-slim", + "icuPackage": "libicu67", + "extraPackages": "" + }, + "jammy": { + "baseImage": "ubuntu:jammy", + "icuPackage": "libicu70", + "extraPackages": "tzdata" + }, + "noble": { + "baseImage": "ubuntu:noble", + "icuPackage": "libicu74", + "extraPackages": "" + }, + "trixie": { + "baseImage": "debian:trixie-slim", + "icuPackage": "libicu76", + "extraPackages": "" } - ], - "tags": { - "bookworm": [ - "5", - "5.0.3", - "latest" - ], - "bullseye": [ - "bullseye", - "5-bullseye", - "5.0.3-bullseye" - ], - "jammy": [ - "jammy", - "5-jammy", - "5.0.3-jammy" - ], - "noble": [ + }, + "blockedVariants": { + "3": [ "noble", - "5-noble", - "5.0.3-noble" + "trixie" ] } }, - { - "version": "5.0.2", - "releases": [ - { + "versions": [ + { + "version": "5.0.4", + "releases": { + "amd64": { + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v5.0.4/Firebird-5.0.4.1812-0-linux-x64.tar.gz", + "sha256": "ab6a15a0258f38b022be496bb5e038c14e8628ce9acd0f9a06288a3baedd917b" + }, "arm64": { - "url": "https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-arm64.tar.gz", - "sha256": "216edb3594d3318690bd3f2ae9979a9a52efb512eb1bf799c0bace50106a0a69" + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v5.0.4/Firebird-5.0.4.1812-0-linux-arm64.tar.gz", + "sha256": "1a3eb3d46b82e96c784800aeec37287d4c47acec4d8caed6c7897beb4ff6cee0" + } + }, + "tags": { + "bookworm": [ + "5.0.4-bookworm", + "5-bookworm", + "bookworm" + ], + "bullseye": [ + "5.0.4-bullseye", + "5-bullseye", + "bullseye" + ], + "jammy": [ + "5.0.4-jammy", + "5-jammy", + "jammy" + ], + "noble": [ + "5.0.4-noble", + "5-noble", + "noble" + ], + "trixie": [ + "5.0.4-trixie", + "5-trixie", + "trixie", + "5.0.4", + "5", + "latest" + ] + } + }, + { + "version": "5.0.3", + "releases": { + "amd64": { + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-x64.tar.gz", + "sha256": "ef281c53f85756288151a86831375c9ae668caaeccd1b18103d523ba8f444779" + }, + "arm64": { + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-arm64.tar.gz", + "sha256": "e375341466e625bf17e4416723c1465a646d44903011ac4b89f84afe1df3633e" } }, - { + "tags": { + "bookworm": "5.0.3-bookworm", + "bullseye": "5.0.3-bullseye", + "jammy": "5.0.3-jammy", + "noble": "5.0.3-noble", + "trixie": [ + "5.0.3-trixie", + "5.0.3" + ] + } + }, + { + "version": "5.0.2", + "releases": { "amd64": { "url": "https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-x64.tar.gz", "sha256": "23d6e0522f32fb13c288f67c98105014c3186ecf3f930f96ca9af1897b9565bf" - } - } - ], - "tags": { - "bookworm": [ - "5.0.2" - ], - "bullseye": [ - "5.0.2-bullseye" - ], - "jammy": [ - "5.0.2-jammy" - ], - "noble": [ - "5.0.2-noble" - ] - } - }, - { - "version": "5.0.1", - "releases": [ - { + }, "arm64": { - "url": "https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-arm64.tar.gz", - "sha256": "46b3f4f170458a93365c67118c062ba8509903fe8293bf8a62e7bd8a388e2d06" + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-arm64.tar.gz", + "sha256": "216edb3594d3318690bd3f2ae9979a9a52efb512eb1bf799c0bace50106a0a69" } }, - { + "tags": { + "bookworm": "5.0.2-bookworm", + "bullseye": "5.0.2-bullseye", + "jammy": "5.0.2-jammy", + "noble": "5.0.2-noble", + "trixie": [ + "5.0.2-trixie", + "5.0.2" + ] + } + }, + { + "version": "5.0.1", + "releases": { "amd64": { "url": "https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-x64.tar.gz", "sha256": "e1023b005e5d6db8f717af032e91f0f94aa7a8dbe0e78f250931214ca0a21e57" + }, + "arm64": { + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-arm64.tar.gz", + "sha256": "46b3f4f170458a93365c67118c062ba8509903fe8293bf8a62e7bd8a388e2d06" } + }, + "tags": { + "bookworm": "5.0.1-bookworm", + "bullseye": "5.0.1-bullseye", + "jammy": "5.0.1-jammy", + "noble": "5.0.1-noble", + "trixie": [ + "5.0.1-trixie", + "5.0.1" + ] } - ], - "tags": { - "bookworm": [ - "5.0.1" - ], - "bullseye": [ - "5.0.1-bullseye" - ], - "jammy": [ - "5.0.1-jammy" - ], - "noble": [ - "5.0.1-noble" - ] - } - }, - { - "version": "5.0.0", - "releases": [ - { + }, + { + "version": "5.0.0", + "releases": { + "amd64": { + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-x64.tar.gz", + "sha256": "137b356ea464e224b6ed1241e6dba95b6b950ff1feef91696d4071d4da880768" + }, "arm64": { "url": "https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-arm64.tar.gz", "sha256": "bdb62abc91a4c26a86b9377256529622e3046f4ec4f66fbdcf46747688d45033" } }, - { + "tags": { + "bookworm": "5.0.0-bookworm", + "bullseye": "5.0.0-bullseye", + "jammy": "5.0.0-jammy", + "noble": "5.0.0-noble", + "trixie": [ + "5.0.0-trixie", + "5.0.0" + ] + } + }, + { + "version": "4.0.7", + "releases": { "amd64": { - "url": "https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-x64.tar.gz", - "sha256": "137b356ea464e224b6ed1241e6dba95b6b950ff1feef91696d4071d4da880768" + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v4.0.7/Firebird-4.0.7.3271-0.amd64.tar.gz", + "sha256": "d2964dfb190d7b0ec57271b53e6539f715ecc119f1cb8cd10339662eed9a7dea" } - } - ], - "tags": { - "bookworm": [ - "5.0.0" - ], - "bullseye": [ - "5.0.0-bullseye" - ], - "jammy": [ - "5.0.0-jammy" - ], - "noble": [ - "5.0.0-noble" - ] - } - }, - { - "version": "4.0.6", - "releases": { - "amd64": { - "url": "https://github.com/FirebirdSQL/firebird/releases/download/v4.0.6/Firebird-4.0.6.3221-0.amd64.tar.gz", - "sha256": "6ff5f672e10ee38ec5fc5394012ac83fe19872543dd2fefa249c1ccf62bc0075" + }, + "tags": { + "bookworm": [ + "4.0.7-bookworm", + "4-bookworm" + ], + "bullseye": [ + "4.0.7-bullseye", + "4-bullseye" + ], + "jammy": [ + "4.0.7-jammy", + "4-jammy" + ], + "noble": [ + "4.0.7-noble", + "4-noble" + ], + "trixie": [ + "4.0.7-trixie", + "4-trixie", + "4.0.7", + "4" + ] } }, - "tags": { - "bookworm": [ - "4", - "4.0.6" - ], - "bullseye": [ - "4-bullseye", - "4.0.6-bullseye" - ], - "jammy": [ - "4-jammy", - "4.0.6-jammy" - ], - "noble": [ - "4-noble", - "4.0.6-noble" - ] - } - }, - { - "version": "4.0.5", - "releases": { - "amd64": { - "url": "https://github.com/FirebirdSQL/firebird/releases/download/v4.0.5/Firebird-4.0.5.3140-0.amd64.tar.gz", - "sha256": "6ae43e4fa31ddc99220575023b7d954fb218c063375bb589b16fbe9fcdfdcaa6" + { + "version": "4.0.6", + "releases": { + "amd64": { + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v4.0.6/Firebird-4.0.6.3221-0.amd64.tar.gz", + "sha256": "6ff5f672e10ee38ec5fc5394012ac83fe19872543dd2fefa249c1ccf62bc0075" + } + }, + "tags": { + "bookworm": "4.0.6-bookworm", + "bullseye": "4.0.6-bullseye", + "jammy": "4.0.6-jammy", + "noble": "4.0.6-noble", + "trixie": [ + "4.0.6-trixie", + "4.0.6" + ] } }, - "tags": { - "bookworm": [ - "4.0.5" - ], - "bullseye": [ - "4.0.5-bullseye" - ], - "jammy": [ - "4.0.5-jammy" - ], - "noble": [ - "4.0.5-noble" - ] - } - }, - { - "version": "4.0.4", - "releases": { - "amd64": { - "url": "https://github.com/FirebirdSQL/firebird/releases/download/v4.0.4/Firebird-4.0.4.3010-0.amd64.tar.gz", - "sha256": "ef589301c5e13a1f8481e1e38c453641ef5082344bf69edb51f8aa9f036bcaca" + { + "version": "4.0.5", + "releases": { + "amd64": { + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v4.0.5/Firebird-4.0.5.3140-0.amd64.tar.gz", + "sha256": "6ae43e4fa31ddc99220575023b7d954fb218c063375bb589b16fbe9fcdfdcaa6" + } + }, + "tags": { + "bookworm": "4.0.5-bookworm", + "bullseye": "4.0.5-bullseye", + "jammy": "4.0.5-jammy", + "noble": "4.0.5-noble", + "trixie": [ + "4.0.5-trixie", + "4.0.5" + ] } }, - "tags": { - "bookworm": [ - "4.0.4" - ], - "bullseye": [ - "4.0.4-bullseye" - ], - "jammy": [ - "4.0.4-jammy" - ], - "noble": [ - "4.0.4-noble" - ] - } - }, - { - "version": "4.0.3", - "releases": { - "amd64": { - "url": "https://github.com/FirebirdSQL/firebird/releases/download/v4.0.3/Firebird-4.0.3.2975-0.amd64.tar.gz", - "sha256": "bd439c3c8f74fd03a592eafd20de37ce028c424fbe023352f1bd17db54c3257d" + { + "version": "4.0.4", + "releases": { + "amd64": { + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v4.0.4/Firebird-4.0.4.3010-0.amd64.tar.gz", + "sha256": "ef589301c5e13a1f8481e1e38c453641ef5082344bf69edb51f8aa9f036bcaca" + } + }, + "tags": { + "bookworm": "4.0.4-bookworm", + "bullseye": "4.0.4-bullseye", + "jammy": "4.0.4-jammy", + "noble": "4.0.4-noble", + "trixie": [ + "4.0.4-trixie", + "4.0.4" + ] } }, - "tags": { - "bookworm": [ - "4.0.3" - ], - "bullseye": [ - "4.0.3-bullseye" - ], - "jammy": [ - "4.0.3-jammy" - ], - "noble": [ - "4.0.3-noble" - ] - } - }, - { - "version": "4.0.2", - "releases": { - "amd64": { - "url": "https://github.com/FirebirdSQL/firebird/releases/download/v4.0.2/Firebird-4.0.2.2816-0.amd64.tar.gz", - "sha256": "70108f9854a522ac6eb7b2bdc1bda9780aab97dbfbf358ced90c0db13b8af9fa" + { + "version": "4.0.3", + "releases": { + "amd64": { + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v4.0.3/Firebird-4.0.3.2975-0.amd64.tar.gz", + "sha256": "bd439c3c8f74fd03a592eafd20de37ce028c424fbe023352f1bd17db54c3257d" + } + }, + "tags": { + "bookworm": "4.0.3-bookworm", + "bullseye": "4.0.3-bullseye", + "jammy": "4.0.3-jammy", + "noble": "4.0.3-noble", + "trixie": [ + "4.0.3-trixie", + "4.0.3" + ] } }, - "tags": { - "bookworm": [ - "4.0.2" - ], - "bullseye": [ - "4.0.2-bullseye" - ], - "jammy": [ - "4.0.2-jammy" - ], - "noble": [ - "4.0.2-noble" - ] - } - }, - { - "version": "4.0.1", - "releases": { - "amd64": { - "url": "https://github.com/FirebirdSQL/firebird/releases/download/v4.0.1/Firebird-4.0.1.2692-0.amd64.tar.gz", - "sha256": "90b6727b8366b3674fc30ba13d0f52ab0b419c3bb3a4224c8d3f480143538998" + { + "version": "4.0.2", + "releases": { + "amd64": { + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v4.0.2/Firebird-4.0.2.2816-0.amd64.tar.gz", + "sha256": "70108f9854a522ac6eb7b2bdc1bda9780aab97dbfbf358ced90c0db13b8af9fa" + } + }, + "tags": { + "bookworm": "4.0.2-bookworm", + "bullseye": "4.0.2-bullseye", + "jammy": "4.0.2-jammy", + "noble": "4.0.2-noble", + "trixie": [ + "4.0.2-trixie", + "4.0.2" + ] } }, - "tags": { - "bookworm": [ - "4.0.1" - ], - "bullseye": [ - "4.0.1-bullseye" - ], - "jammy": [ - "4.0.1-jammy" - ], - "noble": [ - "4.0.1-noble" - ] - } - }, - { - "version": "4.0.0", - "releases": { - "amd64": { - "url": "https://github.com/FirebirdSQL/firebird/releases/download/v4.0.0/Firebird-4.0.0.2496-0.amd64.tar.gz", - "sha256": "06f6e00b9657a1967f21b34bea8150d5a3e5b1d1b1313bb6455e16878b42d63e" + { + "version": "4.0.1", + "releases": { + "amd64": { + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v4.0.1/Firebird-4.0.1.2692-0.amd64.tar.gz", + "sha256": "90b6727b8366b3674fc30ba13d0f52ab0b419c3bb3a4224c8d3f480143538998" + } + }, + "tags": { + "bookworm": "4.0.1-bookworm", + "bullseye": "4.0.1-bullseye", + "jammy": "4.0.1-jammy", + "noble": "4.0.1-noble", + "trixie": [ + "4.0.1-trixie", + "4.0.1" + ] } }, - "tags": { - "bookworm": [ - "4.0.0" - ], - "bullseye": [ - "4.0.0-bullseye" - ], - "jammy": [ - "4.0.0-jammy" - ], - "noble": [ - "4.0.0-noble" - ] - } - }, - { - "version": "3.0.13", - "releases": { - "amd64": { - "url": "https://github.com/FirebirdSQL/firebird/releases/download/v3.0.13/Firebird-3.0.13.33818-0.amd64.tar.gz", - "sha256": "677e19d6308869d5dd0836a342157c7bd1e4b5a873aa385832da01d81db444dd" + { + "version": "4.0.0", + "releases": { + "amd64": { + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v4.0.0/Firebird-4.0.0.2496-0.amd64.tar.gz", + "sha256": "06f6e00b9657a1967f21b34bea8150d5a3e5b1d1b1313bb6455e16878b42d63e" + } + }, + "tags": { + "bookworm": "4.0.0-bookworm", + "bullseye": "4.0.0-bullseye", + "jammy": "4.0.0-jammy", + "noble": "4.0.0-noble", + "trixie": [ + "4.0.0-trixie", + "4.0.0" + ] } }, - "tags": { - "bookworm": [ - "3", - "3.0.13" - ], - "bullseye": [ - "3-bullseye", - "3.0.13-bullseye" - ], - "jammy": [ - "3-jammy", - "3.0.13-jammy" - ] - } - }, - { - "version": "3.0.12", - "releases": { - "amd64": { - "url": "https://github.com/FirebirdSQL/firebird/releases/download/v3.0.12/Firebird-3.0.12.33787-0.amd64.tar.gz", - "sha256": "406a8887ab318a5d8a20781fc1d38a0ca30acdbddbc1558b077646bb2e2e283f" + { + "version": "3.0.14", + "releases": { + "amd64": { + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v3.0.14/Firebird-3.0.14.33856-0.amd64.tar.gz", + "sha256": "d6fedba1108a46cea2b5f753674046fff0e43c6af27ba01657511635cbc9670f" + } + }, + "tags": { + "bookworm": [ + "3.0.14-bookworm", + "3-bookworm" + ], + "bullseye": [ + "3.0.14-bullseye", + "3-bullseye" + ], + "jammy": [ + "3.0.14-jammy", + "3-jammy" + ] } }, - "tags": { - "bookworm": [ - "3.0.12" - ], - "bullseye": [ - "3.0.12-bullseye" - ], - "jammy": [ - "3.0.12-jammy" - ] - } - }, - { - "version": "3.0.11", - "releases": { - "amd64": { - "url": "https://github.com/FirebirdSQL/firebird/releases/download/v3.0.11/Firebird-3.0.11.33703-0.amd64.tar.gz", - "sha256": "713757e09b40b2631d800dacd9b80179b7eb75693a72089136055a7154413a3e" + { + "version": "3.0.13", + "releases": { + "amd64": { + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v3.0.13/Firebird-3.0.13.33818-0.amd64.tar.gz", + "sha256": "677e19d6308869d5dd0836a342157c7bd1e4b5a873aa385832da01d81db444dd" + } + }, + "tags": { + "bookworm": "3.0.13-bookworm", + "bullseye": "3.0.13-bullseye", + "jammy": "3.0.13-jammy" } }, - "tags": { - "bookworm": [ - "3.0.11" - ], - "bullseye": [ - "3.0.11-bullseye" - ], - "jammy": [ - "3.0.11-jammy" - ] - } - }, - { - "version": "3.0.10", - "releases": { - "amd64": { - "url": "https://github.com/FirebirdSQL/firebird/releases/download/v3.0.10/Firebird-3.0.10.33601-0.amd64.tar.gz", - "sha256": "5e0db3b9312c5bed3eccd1855ec07df5a50176dbff35b8ebf998360b59561cf0" + { + "version": "3.0.12", + "releases": { + "amd64": { + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v3.0.12/Firebird-3.0.12.33787-0.amd64.tar.gz", + "sha256": "406a8887ab318a5d8a20781fc1d38a0ca30acdbddbc1558b077646bb2e2e283f" + } + }, + "tags": { + "bookworm": "3.0.12-bookworm", + "bullseye": "3.0.12-bullseye", + "jammy": "3.0.12-jammy" } }, - "tags": { - "bookworm": [ - "3.0.10" - ], - "bullseye": [ - "3.0.10-bullseye" - ], - "jammy": [ - "3.0.10-jammy" - ] - } - }, - { - "version": "3.0.9", - "releases": { - "amd64": { - "url": "https://github.com/FirebirdSQL/firebird/releases/download/v3.0.9/Firebird-3.0.9.33560-0.amd64.tar.gz", - "sha256": "0a80a5dc507f388e96adf9b64584c0b568d94a8f3df19d7baec494c5f98ba5a4" + { + "version": "3.0.11", + "releases": { + "amd64": { + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v3.0.11/Firebird-3.0.11.33703-0.amd64.tar.gz", + "sha256": "713757e09b40b2631d800dacd9b80179b7eb75693a72089136055a7154413a3e" + } + }, + "tags": { + "bookworm": "3.0.11-bookworm", + "bullseye": "3.0.11-bullseye", + "jammy": "3.0.11-jammy" } }, - "tags": { - "bookworm": [ - "3.0.9" - ], - "bullseye": [ - "3.0.9-bullseye" - ], - "jammy": [ - "3.0.9-jammy" - ] - } - }, - { - "version": "3.0.8", - "releases": { - "amd64": { - "url": "https://github.com/FirebirdSQL/firebird/releases/download/v3.0.8/Firebird-3.0.8.33535-0.amd64.tar.gz", - "sha256": "fbf154244d3568f4de4ee68769ed71a0699845197ae1c02c2029dc4d0f1af5f9" + { + "version": "3.0.10", + "releases": { + "amd64": { + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v3.0.10/Firebird-3.0.10.33601-0.amd64.tar.gz", + "sha256": "5e0db3b9312c5bed3eccd1855ec07df5a50176dbff35b8ebf998360b59561cf0" + } + }, + "tags": { + "bookworm": "3.0.10-bookworm", + "bullseye": "3.0.10-bullseye", + "jammy": "3.0.10-jammy" } }, - "tags": { - "bookworm": [ - "3.0.8" - ], - "bullseye": [ - "3.0.8-bullseye" - ], - "jammy": [ - "3.0.8-jammy" - ] + { + "version": "3.0.9", + "releases": { + "amd64": { + "url": "https://github.com/FirebirdSQL/firebird/releases/download/v3.0.9/Firebird-3.0.9.33560-0.amd64.tar.gz", + "sha256": "0a80a5dc507f388e96adf9b64584c0b568d94a8f3df19d7baec494c5f98ba5a4" + } + }, + "tags": { + "bookworm": "3.0.9-bookworm", + "bullseye": "3.0.9-bullseye", + "jammy": "3.0.9-jammy" + } } - } -] + ] +} diff --git a/doc/ARM64-BUILDS.md b/doc/ARM64-BUILDS.md new file mode 100644 index 0000000..a27f4b3 --- /dev/null +++ b/doc/ARM64-BUILDS.md @@ -0,0 +1,73 @@ +## How ARM64 builds work + +### 1. Build phase — on each arch runner independently + +The `Build` task runs on **both** the `ubuntu-latest` (amd64) and the `ubuntu-24.04-arm` (arm64) GitHub Actions runners in parallel via a matrix job. + +On each runner, `Build` detects the host architecture at runtime: + +```powershell +$hostArch = if ($IsLinux) { (dpkg --print-architecture 2>$null) ?? 'amd64' } else { 'amd64' } +``` + +It then calls `docker buildx build --load` and tags the produced image with an arch suffix: + +- **amd64 runner** → `firebirdsql/firebird-amd64:` (e.g. `firebirdsql/firebird-amd64:5.0.3-bookworm`) +- **arm64 runner** → `firebirdsql/firebird-arm64:` (e.g. `firebirdsql/firebird-arm64:5.0.3-bookworm`) + +These are local-only tags in the runner's Docker daemon, used for testing. They are **never pushed** to any registry. + +For Firebird 3.x and 4.x, which have no upstream ARM64 binary, `Build` checks `assets.json` for an `arm64` key. If it is absent, the arm64 build is skipped on the arm64 runner. The `Test` task similarly skips those versions on arm64. + +### 2. Push-Digests — push by digest, no tags created (runs on each arch runner) + +After the build and tests, `Push-Digests` pushes each image to the registry **by digest** — no tag is created. This uses `docker buildx build --push` with `push-by-digest=true`: + +```powershell +docker buildx build --push ` + --output "type=image,name=$imagePrefix/firebird,push-by-digest=true,name-canonical=true,push=true" ` + --metadata-file $metadataFile ` + $distributionFolder +``` + +The digest (e.g. `sha256:abc123…`) is captured from the metadata file and saved to `generated/digests-{arch}.json`. This file is uploaded as a GitHub Actions artifact. + +No staging tags, no staging repos — only raw image layers addressed by digest exist in the registry at this point. + +### 3. Publish-Manifests — create OCI multi-arch manifests (runs once, on ubuntu-latest) + +The `create-manifests` job in `publish.yaml` runs after all `build-and-test` matrix jobs succeed (`needs: build-and-test`). It downloads the digest artifacts from both runners, then calls `Publish-Manifests`: + +```powershell +docker buildx imagetools create --tag "$imagePrefix/firebird:$tag" ` + "$imagePrefix/firebird@$amd64Digest" ` + "$imagePrefix/firebird@$arm64Digest" +``` + +This assembles the per-arch digests into a single OCI manifest list (multi-arch image). After this, `docker pull firebirdsql/firebird:5.0.3-bookworm` on any machine automatically pulls the correct architecture. + +For **amd64-only** versions (Firebird 3.x, 4.x), `Publish-Manifests` creates a single-arch manifest from the amd64 digest only. + +--- + +## Summary diagram + +``` +ubuntu-latest (amd64) ubuntu-24.04-arm (arm64) +───────────────────── ───────────────────────── +Build Build + → firebird-amd64: (local) → firebird-arm64: (local) +Test Test (skips FB3/FB4) +Push-Digests Push-Digests + → push by digest (no tag) → push by digest (no tag) + → save sha256 to artifact → save sha256 to artifact + ↘ ↙ + create-manifests (ubuntu-latest) + download digest artifacts + Publish-Manifests + docker buildx imagetools create firebird: + ← firebird@sha256: + ← firebird@sha256: + → final multi-arch tag published +``` + diff --git a/firebird-docker.build.ps1 b/firebird-docker.build.ps1 index 1d97e8d..cf2e189 100644 --- a/firebird-docker.build.ps1 +++ b/firebird-docker.build.ps1 @@ -1,8 +1,15 @@ param( [string]$VersionFilter, # Filter by version (e.g. '3', '4.0', '5.0.2'). [string]$DistributionFilter, # Filter by image distribution (e.g. 'bookworm', 'bullseye', 'jammy'). + [switch]$LatestPerMajor, # Build/test only the latest release of each major Firebird version. - [string]$TestFilter # Filter by test name (e.g., 'FIREBIRD_USER_can_create_user'). Used only in the 'Test' task. + [string]$TestFilter, # Filter by test name (e.g., 'FIREBIRD_USER_can_create_user'). Used only in the 'Test' task. + + [ValidateSet('master', 'v5.0-release', 'v4.0')] + [string]$Branch, # Snapshot branch. Used only in the 'Build-Snapshot' task. + + [string]$Registry # Image registry/owner prefix. Defaults to 'firebirdsql' (Docker Hub). + # Override for forks: e.g. 'ghcr.io/myusername' ) # @@ -11,219 +18,210 @@ param( $outputFolder = './generated' -$defaultVariant = 'bookworm' +# Effective image prefix: Registry overrides the default Docker Hub org +$script:imagePrefix = if ($Registry) { $Registry } else { 'firebirdsql' } -$blockedVariants = @{'3' = @('noble') } # Ubuntu 24.04 doesn't have libncurses5. +# Source shared functions +. "$PSScriptRoot/src/functions.ps1" # -# Functions +# Tasks # -function Expand-Template([Parameter(ValueFromPipeline = $true)]$Template) { - $evaluator = { - $innerTemplate = $args[0].Groups[1].Value - $ExecutionContext.InvokeCommand.ExpandString($innerTemplate) +# Synopsis: Rebuild "assets.json" from GitHub releases using PSFirebird. +task Update-Assets { + # PSFirebird is required for this task + if (-not (Get-Module PSFirebird -ListAvailable)) { + Install-Module PSFirebird -MinimumVersion '1.0.0' -Force -Scope CurrentUser } - $regex = [regex]"\<\%(.*?)\%\>" - $regex.Replace($Template, $evaluator) -} + Import-Module PSFirebird -MinimumVersion '1.0.0' + + # Load current config section (distros, blocked variants, default distro) + $currentData = Get-Content -Raw -Path './assets.json' | ConvertFrom-Json + $script:assetsData = $currentData + $config = $currentData.config + + $defaultDistro = $config.defaultDistro + $allDistros = $config.distros | Get-Member -MemberType NoteProperty | ForEach-Object { $_.Name } + + # Query GitHub for all Firebird releases + $allReleases = @() + foreach ($majorVersion in @(5, 4, 3)) { + Write-Output "Querying releases for Firebird $majorVersion..." + + # Find all patch versions for this major + $apiUrl = 'https://api.github.com/repos/FirebirdSQL/firebird/releases?per_page=100' + $headers = @{ 'User-Agent' = 'PSFirebird' } + if ($env:GITHUB_TOKEN) { + $headers['Authorization'] = "Bearer $($env:GITHUB_TOKEN)" + } + $releases = Invoke-RestMethod -Uri $apiUrl -Headers $headers + + $matchingReleases = $releases | + Where-Object { ($_.tag_name -like "v$majorVersion.*") -and (-not $_.prerelease) } | + ForEach-Object { + $v = [version]($_.tag_name.TrimStart('v')) + [PSCustomObject]@{ Version = $v; TagName = $_.tag_name } + } | + Sort-Object { $_.Version } -Descending + + foreach ($rel in $matchingReleases) { + $version = $rel.Version + if ($version -lt [version]'3.0.9') { continue } + + Write-Output " Processing $version..." + + # Get amd64 release + $amd64 = Find-FirebirdRelease -Version ([semver]"$version") -RuntimeIdentifier 'linux-x64' + $releaseInfo = [ordered]@{ + amd64 = [ordered]@{ + url = $amd64.Url + sha256 = $amd64.Sha256 + } + } -function Copy-TemplateItem([string]$Path, [string]$Destination) { - if (Test-Path $Destination) { - # File already exists: Remove readonly flag (if set). - $outputFile = Get-Item $Destination - $outputFile | Set-ItemProperty -Name IsReadOnly -Value $false - } + # Get arm64 release (FB5+ only). FB3/FB4 `.arm64.tar.gz` assets are + # Android builds with a misleading name (per asfernandes, FirebirdSQL/firebird-docker#38), + # not Linux ARM64 — Linux ARM* packaging starts at FB5. See DECISIONS.md D-015. + if ($majorVersion -ge 5) { + try { + $arm64 = Find-FirebirdRelease -Version ([semver]"$version") -RuntimeIdentifier 'linux-arm64' + $releaseInfo['arm64'] = [ordered]@{ + url = $arm64.Url + sha256 = $arm64.Sha256 + } + } catch { + Write-Warning " No arm64 release for $version" + } + } - # Add header - $fileExtension = $Destination.Split('.')[-1] - $header = if ($fileExtension -eq 'md') { - @' + # If SHA-256 is null (pre-July 2025 releases), download to compute + foreach ($arch in @('amd64', 'arm64')) { + if ($releaseInfo.Contains($arch) -and -not $releaseInfo[$arch].sha256) { + Write-Output " Downloading $arch asset to compute SHA-256..." + $tempFile = [System.IO.Path]::GetTempFileName() + try { + $ProgressPreference = 'SilentlyContinue' + Invoke-WebRequest $releaseInfo[$arch].url -OutFile $tempFile + $releaseInfo[$arch].sha256 = (Get-FileHash $tempFile -Algorithm SHA256).Hash.ToLower() + } finally { + Remove-Item $tempFile -Force -ErrorAction SilentlyContinue + } + } + } -[//]: # (This file was auto-generated. Do not edit. See /src.) + $allReleases += [PSCustomObject]@{ + Version = $version + Major = $majorVersion + Releases = $releaseInfo + } + } + } -'@ - } else { - @' -# -# This file was auto-generated. Do not edit. See /src. -# + # Sort: by major desc, then version desc + $allReleases = $allReleases | Sort-Object { $_.Major }, { $_.Version } -Descending -'@ - } - $header | Set-Content $Destination -Encoding UTF8 + # Group by major to determine latest-of-major + $byMajor = $allReleases | Group-Object Major + $latestOverallVersion = $allReleases[0].Version - # Expand template - Get-Content $Path -Raw -Encoding UTF8 | - Expand-Template | - Add-Content $Destination -Encoding UTF8 + # Build tags + $versions = @() + foreach ($group in ($byMajor | Sort-Object Name -Descending)) { + $isFirstInGroup = $true + foreach ($rel in $group.Group) { + $validDistros = Get-ValidDistros -Major $rel.Major + $tags = [ordered]@{} - # Set readonly flag (another reminder to not edit the file) - $outputFile = Get-Item $Destination - $outputFile | Set-ItemProperty -Name IsReadOnly -Value $true -} + foreach ($distro in $validDistros) { + $distroTags = Get-ImageTags ` + -Version "$($rel.Version)" ` + -Distro $distro ` + -IsLatestOfMajor $isFirstInGroup ` + -IsLatestOverall ($rel.Version -eq $latestOverallVersion) ` + -DefaultDistro $defaultDistro + $tags[$distro] = $distroTags + } -function Use-CachedResponse { - param( - [Parameter(Mandatory = $true)] - [string]$JsonFile, + $versions += [ordered]@{ + version = "$($rel.Version)" + releases = $rel.Releases + tags = $tags + } - [scriptblock]$ScriptBlock - ) + $isFirstInGroup = $false + } + } - if (Test-Path $JsonFile) { - return Get-Content $JsonFile | ConvertFrom-Json + # Write assets.json + $output = [ordered]@{ + config = $config + versions = $versions } - $result = Invoke-Command -ScriptBlock $ScriptBlock - return $result | ConvertTo-Json -Depth 10 | Out-File $JsonFile -Encoding utf8 + $output | ConvertTo-Json -Depth 10 | Out-File './assets.json' -Encoding UTF8 + Write-Output "assets.json updated with $($versions.Count) versions." } +# Synopsis: Load the assets from "assets.json". +task LoadAssets { + $script:assetsData = Get-Content -Raw -Path './assets.json' | ConvertFrom-Json +} +# Synopsis: Load the assets from "assets.json", optionally filtering by command-line parameters. +task FilteredAssets LoadAssets, { + $result = $script:assetsData.versions -# -# Tasks -# - -# Synopsis: Rebuild "assets.json" from GitHub releases. -task Update-Assets { - $tempFolder = [System.IO.Path]::GetTempPath() - - $releasesFile = Join-Path $tempFolder 'github-releases.json' - $assetsFolder = Join-Path $tempFolder 'firebird-assets' - New-Item $assetsFolder -ItemType Directory -Force > $null - - # All github releases - $releases = Use-CachedResponse -JsonFile $releasesFile { Invoke-RestMethod -Uri "https://api.github.com/repos/FirebirdSQL/firebird/releases" -UseBasicParsing } - - # Ignore legacy and prerelease - $currentReleases = $releases | Where-Object { ($_.tag_name -like 'v*') -and (-not $_.prerelease) } - - # Select only amd64/arm64 and non-debug assets - $currentAssets = $currentReleases | - Select-Object -Property @{ Name='version'; Expression={ [version]$_.tag_name.TrimStart("v") } }, - @{ Name='download_url'; Expression={ $_.assets.browser_download_url | Where-Object { ( $_ -like '*amd64*' -or $_ -like '*linux-x64*' -or $_ -like '*linux-arm64*') -and ($_ -notlike '*debug*') } } } | - Sort-Object -Property version -Descending - - # Group by major version - $groupedAssets = $currentAssets | - Select-Object -Property @{ Name='major'; Expression={ $_.version.Major } }, 'version', 'download_url' | - Group-Object -Property 'major' | - Sort-Object -Property Name -Descending - - # Get Variants - $dockerFiles = Get-Item './src/Dockerfile.*.template' - $allOtherVariants = $dockerFiles.Name | - Select-String -Pattern 'Dockerfile.(.+).template' | - ForEach-Object { $_.Matches.Groups[1].Value } | - Where-Object { $_ -ne $defaultVariant } - $allVariants = @($defaultVariant) + $otherVariants - - # For each asset - $groupedAssets | ForEach-Object -Begin { $groupIndex = 0 } -Process { - # For each major version - $_.Group | ForEach-Object -Begin { $index = 0 } -Process { - $asset = $_ - - # Remove blocked variants - - $otherVariants = $allOtherVariants | Where-Object { $_ -notin $blockedVariants."$($asset.major)" } - $variants = $allVariants | Where-Object { $_ -notin $blockedVariants."$($asset.major)" } - - $releases = $asset.download_url | ForEach-Object { - $url = [uri]$_ - $assetFileName = $url.Segments[-1] - $assetLocalFile = Join-Path $assetsFolder $assetFileName - if (-not (Test-Path $assetLocalFile)) { - $ProgressPreference = 'SilentlyContinue' # How NOT to implement a progress bar -- https://stackoverflow.com/a/43477248 - Invoke-WebRequest $url -OutFile $assetLocalFile - } - - $sha256 = (Get-FileHash $assetLocalFile -Algorithm SHA256).Hash.ToLower() - - if ($url -like '*arm64*') { - [ordered]@{ - arm64 = - [ordered]@{ - url = $url - sha256 = $sha256 - } - } - } else { - [ordered]@{ - amd64 = - [ordered]@{ - url = $url - sha256 = $sha256 - } - } - } - } - - $tags = [ordered]@{} - - $tags[$defaultVariant] = @("$($asset.version)") - $otherVariants | ForEach-Object { - $tags[$_] = @("$($asset.version)-$_") - } + # Filter assets by command-line arguments + if ($VersionFilter) { + $result = $result | Where-Object { $_.version -like "$VersionFilter*" } + } - if ($index -eq 0) { - # latest of this major version - $tags[$defaultVariant] = @("$($asset.major)") + $tags[$defaultVariant] - $otherVariants | ForEach-Object { - $tags[$_] = @("$($asset.major)-$_") + $tags[$_] - } - } + if ($DistributionFilter) { + $result = $result | Where-Object { $_.tags.$DistributionFilter -ne $null } | + Select-Object -Property 'version','releases',@{Name = 'tags'; Expression = { [PSCustomObject]@{ "$DistributionFilter" = $_.tags.$DistributionFilter } } } + } - if (($groupIndex -eq 0) -and ($index -eq 0)) { - # latest of all - $tags[$defaultVariant] += 'latest' - $otherVariants | ForEach-Object { - $tags[$_] = @("$_") + $tags[$_] - } - } + if ($LatestPerMajor) { + # Keep only the first (latest) entry per major version + $result = $result | Group-Object { ([version]$_.version).Major } | ForEach-Object { $_.Group[0] } + } - Write-Output ([ordered]@{ - 'version' = "$($asset.version)" - 'releases' = $releases - 'tags' = $tags - }) + if (-not $result) { + Write-Error "No assets found matching the specified filters." + exit 1 + } - $index++ - } - $groupIndex++ - } | ConvertTo-Json -Depth 10 | Out-File './assets.json' -Encoding ascii + $script:assets = $result } # Synopsis: Rebuild "README.md" from "assets.json". -task Update-Readme { - # For each asset - $assets = Get-Content -Raw -Path '.\assets.json' | ConvertFrom-Json +task Update-Readme LoadAssets, { + $assets = $script:assetsData.versions $TSupportedTags = $assets | ForEach-Object { $asset = $_ - $version = [version]$asset.version $versionFolder = Join-Path $outputFolder $version - # For each image $asset.tags | Get-Member -MemberType NoteProperty | ForEach-Object { $image = $_.Name - $TImageTags = $asset.tags.$image if ($TImageTags) { - # https://stackoverflow.com/a/73073678 $TImageTags = "``{0}``" -f ($TImageTags -join "``, ``") } - $variantFolder = (Join-Path $versionFolder $image).Replace('\', '/') - Write-Output "|$TImageTags|[Dockerfile]($variantFolder/Dockerfile)|`n" } } - Copy-TemplateItem "./src/README.md.template" './README.md' + $imageFullName = "$script:imagePrefix/firebird" + + $template = Get-Content './src/README.md.template' -Raw -Encoding UTF8 + $content = $template.Replace('{{SupportedTags}}', ($TSupportedTags -join '')) + $content = $content.Replace('{{IMAGE_FULL_NAME}}', $imageFullName) + Write-GeneratedFile -Content $content -Destination './README.md' } # Synopsis: Clean up the output folder. @@ -231,34 +229,12 @@ task Clean { Remove-Item -Path $outputFolder -Recurse -Force -ErrorAction SilentlyContinue } -# Synopsis: Load the assets from "assets.json", optionally filtering it by command-line parameters. -task FilteredAssets { - $result = Get-Content -Raw -Path '.\assets.json' | ConvertFrom-Json - - # Filter assets by command-line arguments - if ($VersionFilter) { - $result = $result | Where-Object { $_.version -like "$VersionFilter*" } - } - - if ($DistributionFilter) { - $result = $result | Where-Object { $_.tags.$DistributionFilter -ne $null } | - # Remove tags that do not match the distribution filter - Select-Object -Property 'version','releases',@{Name = 'tags'; Expression = { [PSCustomObject]@{ "$DistributionFilter" = $_.tags.$DistributionFilter } } } - } - - if (-not $result) { - Write-Error "No assets found matching the specified filters." - exit 1 - } - - $script:assets = $result -} - # Synopsis: Invoke preprocessor to generate the image source files (can be filtered using command-line options). task Prepare FilteredAssets, { # Create output folders if they do not exist New-Item -ItemType Directory $outputFolder -Force > $null - New-Item -ItemType Directory (Join-Path $outputFolder 'logs') -Force > $null + + $config = $script:assetsData.config # For each asset $assets | ForEach-Object { @@ -268,116 +244,425 @@ task Prepare FilteredAssets, { $versionFolder = Join-Path $outputFolder $version New-Item -ItemType Directory $versionFolder -Force > $null - # For each tag + # For each tag/distro $asset.tags | Get-Member -MemberType NoteProperty | ForEach-Object { $distribution = $_.Name $distributionFolder = Join-Path $versionFolder $distribution New-Item -ItemType Directory $distributionFolder -Force > $null - # Set variables for the template - $THasArchARM64 = ($asset.releases.arm64.url -ne $null -and $distribution -ne 'bullseye' -and $distribution -ne 'jammy' ? - '$true' : '$false') - - $TUrlArchAMD64 = $asset.releases.amd64.url - $TSha256ArchAMD64 = $asset.releases.amd64.sha256 - - $TUrlArchARM64 = $asset.releases.arm64.url - $TSha256ArchARM64 = $asset.releases.arm64.sha256 + $distroConfig = Get-DistroConfig -Distro $distribution + + # Template variables + $hasArm64 = ($null -ne $asset.releases.arm64) + $variables = @{ + 'BASE_IMAGE' = $distroConfig.baseImage + 'ICU_PACKAGE' = $distroConfig.icuPackage + 'EXTRA_PACKAGES' = if ($distroConfig.extraPackages) { " $($distroConfig.extraPackages) \`n" } else { '' } + 'URL_AMD64' = "$($asset.releases.amd64.url)" + 'SHA256_AMD64' = "$($asset.releases.amd64.sha256)" + 'URL_ARM64' = if ($hasArm64) { "$($asset.releases.arm64.url)" } else { '' } + 'SHA256_ARM64' = if ($hasArm64) { "$($asset.releases.arm64.sha256)" } else { '' } + 'FIREBIRD_VERSION' = "$($asset.version)" + 'FIREBIRD_MAJOR' = "$($version.Major)" + } - $TMajor = $version.Major - $TImageVersion = $version + # Render template + $dockerfile = Expand-TemplateFile -Path './src/Dockerfile.template' -Variables $variables - $TImageTags = $asset.tags.$distribution - if ($TImageTags) { - # https://stackoverflow.com/a/73073678 - $TImageTags = "'{0}'" -f ($TImageTags -join "', '") + # For amd64-only versions, remove the arm64 case from the Dockerfile + if (-not $hasArm64) { + $dockerfile = $dockerfile -replace "(?ms)\s+arm64\)\s*\\.*?;;\s*\\", '' } - # Render templates into the distribution folder - Copy-TemplateItem "./src/Dockerfile.$distribution.template" "$distributionFolder/Dockerfile" + Write-GeneratedFile -Content $dockerfile -Destination "$distributionFolder/Dockerfile" Copy-Item './src/entrypoint.sh' $distributionFolder - Copy-TemplateItem "./src/image.build.ps1.template" "$distributionFolder/image.build.ps1" - Copy-Item './src/image.tests.ps1' $distributionFolder } } } # Synopsis: Build all docker images (can be filtered using command-line options). task Build Prepare, { - $taskName = "Build" - $PSStyle.OutputRendering = 'PlainText' - $logFolder = Join-Path $outputFolder 'logs' + $config = $script:assetsData.config + $imagePrefix = $script:imagePrefix + $imageName = 'firebird' - $builds = $assets | ForEach-Object { - $asset = $_ + # Detect host architecture + $hostArch = if ($IsLinux) { (dpkg --print-architecture 2>$null) ?? 'amd64' } else { 'amd64' } + $assets | ForEach-Object { + $asset = $_ $version = [version]$asset.version $versionFolder = Join-Path $outputFolder $version $asset.tags | Get-Member -MemberType NoteProperty | ForEach-Object { $distribution = $_.Name $distributionFolder = Join-Path $versionFolder $distribution - @{ - File = "$distributionFolder/image.build.ps1" - Task = $taskName - Log = "$logFolder/$taskName-$version-$distribution.log" + $imageTags = $asset.tags.$distribution + $hasArm64 = ($null -ne $asset.releases.arm64) + + # Build for host architecture + if ($hostArch -eq 'amd64') { + $tagsAmd64 = $imageTags | ForEach-Object { '--tag', "$imagePrefix/${imageName}-amd64:$_" } + $buildArgs = @( + 'buildx', 'build', '--load' + $tagsAmd64 + '--label', 'org.opencontainers.image.description=Firebird Database' + '--label', "org.opencontainers.image.version=$($asset.version)" + '--progress=plain' + $distributionFolder + ) + Write-Build Cyan "----- [$($asset.version) / $distribution / amd64] -----" + exec { & docker $buildArgs *>&1 } + } - # Parameters passed to Invoke-Build - Verbose = $PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent + if ($hasArm64 -and $hostArch -eq 'arm64') { + $tagsArm64 = $imageTags | ForEach-Object { '--tag', "$imagePrefix/${imageName}-arm64:$_" } + $buildArgs = @( + 'buildx', 'build', '--load' + $tagsArm64 + '--label', 'org.opencontainers.image.description=Firebird Database' + '--label', "org.opencontainers.image.version=$($asset.version)" + '--progress=plain' + $distributionFolder + ) + Write-Build Cyan "----- [$($asset.version) / $distribution / arm64] -----" + exec { & docker $buildArgs *>&1 } } } } - - Build-Parallel $builds } # Synopsis: Run all tests (can be filtered using command-line options). task Test FilteredAssets, { - $taskName = "Test" + $imagePrefix = $script:imagePrefix + $imageName = 'firebird' + $testFile = './src/image.tests.ps1' - $PSStyle.OutputRendering = 'PlainText' - $logFolder = Join-Path $outputFolder 'logs' + # Detect host architecture + $hostArch = if ($IsLinux) { (dpkg --print-architecture 2>$null) ?? 'amd64' } else { 'amd64' } + + if ($TestFilter) { + Write-Verbose "Running single test '$TestFilter'..." + } else { + Write-Verbose "Running all tests..." + $TestFilter = '*' + } + + $assets | ForEach-Object { + $asset = $_ + $hasArm64 = ($null -ne $asset.releases.arm64) + $tag = $asset.tags | Get-Member -MemberType NoteProperty | Select-Object -First 1 | ForEach-Object { + $asset.tags.($_.Name) | Select-Object -First 1 + } + + # Skip versions not supported on the current host architecture + if ($hostArch -eq 'arm64' -and -not $hasArm64) { + Write-Build Yellow "----- [$($asset.version)] skipped (no arm64 build) -----" + return + } + + Write-Build Magenta "----- [$($asset.version)] -----" + + # Test host architecture + $env:FULL_IMAGE_NAME = "$imagePrefix/${imageName}-${hostArch}:${tag}" + Write-Verbose " Image: $($env:FULL_IMAGE_NAME)" + Invoke-Build $TestFilter $testFile + } +} + +# Synopsis: Test published images pulled directly from a registry (requires -Registry). +# Unlike Test (which uses locally built arch-specific images), this task tests the final +# published images — the same ones end users pull. +# +# Examples: +# Invoke-Build Test-Published -Registry 'ghcr.io/myusername' +# Invoke-Build Test-Published -Registry 'ghcr.io/myusername' -VersionFilter '5.0.3' -DistributionFilter 'bookworm' +# Invoke-Build Test-Published -Registry 'firebirdsql' +task Test-Published FilteredAssets, { + $imagePrefix = $script:imagePrefix + $imageName = 'firebird' + $testFile = './src/image.tests.ps1' + + if (-not $imagePrefix) { + Write-Error "Use -Registry to specify which registry to test. Example: Invoke-Build Test-Published -Registry 'ghcr.io/myusername'" + exit 1 + } + + if ($TestFilter) { + Write-Verbose "Running single test '$TestFilter'..." + } else { + Write-Verbose "Running all tests..." + $TestFilter = '*' + } + + $assets | ForEach-Object { + $asset = $_ + + $asset.tags | Get-Member -MemberType NoteProperty | ForEach-Object { + $distribution = $_.Name + # Use the most-specific tag (first in list, e.g. '5.0.3-bookworm') to avoid + # accidentally re-testing the same image under an alias tag. + $tag = $asset.tags.$distribution | Select-Object -First 1 + + Write-Build Magenta "----- [$($asset.version) / $distribution] -----" + + $env:FULL_IMAGE_NAME = "$imagePrefix/${imageName}:$tag" + Write-Build Cyan " Pulling $($env:FULL_IMAGE_NAME)..." + docker pull $env:FULL_IMAGE_NAME *>&1 | Select-String 'Status:|Error' | Write-Build DarkGray + Invoke-Build $TestFilter $testFile + } + } +} + + +# Synopsis: Retag and push images using the final name (no -arch suffix). Use for single-arch publishing. +# Produces only one package (e.g. ghcr.io/owner/firebird) with no staging intermediates. +task Publish-Direct FilteredAssets, { + $imagePrefix = $script:imagePrefix + $imageName = 'firebird' + + $hostArch = if ($IsLinux) { (dpkg --print-architecture 2>$null) ?? 'amd64' } else { 'amd64' } - $tests = $assets | ForEach-Object { + $assets | ForEach-Object { $asset = $_ + Write-Build Magenta "----- [$($asset.version) / direct] -----" + + $asset.tags | Get-Member -MemberType NoteProperty | ForEach-Object { + $distribution = $_.Name + $imageTags = $asset.tags.$distribution + + $imageTags | ForEach-Object { + $tag = $_ + docker tag "$imagePrefix/${imageName}-${hostArch}:$tag" "$imagePrefix/${imageName}:$tag" + docker push "$imagePrefix/${imageName}:$tag" + } + } + } +} + +# Synopsis: Push images by digest — no tags created in registry. Saves digest mapping to file. +# Run on each arch runner after Build and Test. Upload generated/digests-*.json as artifact. +task Push-Digests FilteredAssets, { + $imagePrefix = $script:imagePrefix + $imageName = 'firebird' + $hostArch = if ($IsLinux) { (dpkg --print-architecture 2>$null) ?? 'amd64' } else { 'amd64' } + + $digests = [ordered]@{} + + $assets | ForEach-Object { + $asset = $_ $version = [version]$asset.version $versionFolder = Join-Path $outputFolder $version + $hasArm64 = ($null -ne $asset.releases.arm64) + + # Skip if this arch can't build this version + if ($hostArch -eq 'arm64' -and -not $hasArm64) { + Write-Build Yellow "----- [$($asset.version)] skipped (no arm64 build) -----" + return + } $asset.tags | Get-Member -MemberType NoteProperty | ForEach-Object { $distribution = $_.Name $distributionFolder = Join-Path $versionFolder $distribution - @{ - File = "$distributionFolder/image.build.ps1" - Task = $taskName - Log = "$logFolder/$taskName-$version-$distribution.log" - - # Parameters passed to Invoke-Build - Verbose = $PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent - TestFilter = $TestFilter + $key = "$($asset.version)/$distribution" + + # Push once per version+distro (all tags share the same image) + if (-not $digests.Contains($key)) { + Write-Build Cyan "----- [$($asset.version) / $distribution / $hostArch → push-by-digest] -----" + + $metadataFile = Join-Path ([System.IO.Path]::GetTempPath()) "metadata-$($asset.version)-$distribution.json" + + $buildArgs = @( + 'buildx', 'build' + '--output', "type=image,name=$imagePrefix/$imageName,push-by-digest=true,name-canonical=true,push=true" + '--metadata-file', $metadataFile + '--label', 'org.opencontainers.image.description=Firebird Database' + '--label', "org.opencontainers.image.version=$($asset.version)" + '--progress=plain' + $distributionFolder + ) + exec { & docker $buildArgs *>&1 } + + $metadata = Get-Content $metadataFile -Raw | ConvertFrom-Json + $digest = $metadata.'containerimage.digest' + $digests[$key] = $digest + + Write-Build Green " → $digest" } } } - Build-Parallel $tests + # Save digests to file for artifact upload + $digestFile = Join-Path $outputFolder "digests-$hostArch.json" + New-Item -ItemType Directory (Split-Path $digestFile) -Force > $null + $digests | ConvertTo-Json | Out-File $digestFile -Encoding UTF8 + Write-Build Green "Digests saved to $digestFile ($($digests.Count) images)" } -# Synopsis: Publish all images. -task Publish { - $PSStyle.OutputRendering = 'PlainText' - $logFolder = Join-Path $outputFolder 'logs' - $builds = Get-ChildItem "$outputFolder/**/image.build.ps1" -Recurse | ForEach-Object { - $version = $_.Directory.Parent.Name - $variant = $_.Directory.Name - $taskName = "Publish" - @{ - File = $_.FullName - Task = $taskName - Log = (Join-Path $logFolder "$taskName-$version-$variant.log") +# Synopsis: Create and push multi-arch manifests from digest files (run once after all arch builds complete). +# Requires digest files in generated/digests-{arch}.json (uploaded as artifacts by Push-Digests). +task Publish-Manifests FilteredAssets, { + $imagePrefix = $script:imagePrefix + $imageName = 'firebird' + + # Load digests from artifact files. Validate up-front so we fail fast with a + # clear message instead of a cryptic Docker error downstream. + $amd64DigestFile = Join-Path $outputFolder 'digests-amd64.json' + $arm64DigestFile = Join-Path $outputFolder 'digests-arm64.json' + + function Read-DigestFile($path, $required) { + if (-not (Test-Path $path)) { + if ($required) { + throw "Digest file not found: $path. Run Push-Digests first (or download artifacts)." + } + return $null + } + try { + $parsed = Get-Content $path -Raw | ConvertFrom-Json -ErrorAction Stop + } catch { + throw "Digest file '$path' is not valid JSON: $($_.Exception.Message)" + } + $keys = $parsed.PSObject.Properties.Name + if (-not $keys -or $keys.Count -eq 0) { + throw "Digest file '$path' is empty — no digests to assemble." + } + $sampleKey = $keys[0] + $sampleValue = $parsed.$sampleKey + if ($sampleValue -notmatch '^sha256:[0-9a-f]{64}$') { + throw "Digest file '$path' has malformed digest for key '$sampleKey': '$sampleValue'. Expected 'sha256:<64 hex>'." + } + Write-Build DarkGray "Loaded $($keys.Count) digests from $path (sample: $sampleKey → $sampleValue)" + return $parsed + } + + $amd64Digests = Read-DigestFile $amd64DigestFile -required $true + $arm64Digests = Read-DigestFile $arm64DigestFile -required $false + + $assets | ForEach-Object { + $asset = $_ + $hasArm64 = ($null -ne $asset.releases.arm64) + + Write-Build Magenta "----- [$($asset.version)] -----" + + $asset.tags | Get-Member -MemberType NoteProperty | ForEach-Object { + $distribution = $_.Name + $imageTags = $asset.tags.$distribution + $key = "$($asset.version)/$distribution" + + $amd64Digest = $amd64Digests.$key + if (-not $amd64Digest) { + Write-Build Yellow " Skipping $key (no amd64 digest found)" + return + } + + $sources = @("$imagePrefix/${imageName}@$amd64Digest") + + if ($hasArm64 -and $arm64Digests) { + $arm64Digest = $arm64Digests.$key + if ($arm64Digest) { + $sources += "$imagePrefix/${imageName}@$arm64Digest" + } + } + + $imageTags | ForEach-Object { + $tag = $_ + Write-Build Cyan " $tag → manifest ($($sources.Count) arch)" + $tagArgs = @('buildx', 'imagetools', 'create', '--tag', "$imagePrefix/${imageName}:$tag") + $sources + exec { & docker $tagArgs *>&1 } + } } } - Build-Parallel $builds +} + +# Synopsis: Build a snapshot image from a Firebird pre-release branch. +task Build-Snapshot LoadAssets, { + if (-not $Branch) { + throw "The -Branch parameter is required for Build-Snapshot. Use: Invoke-Build Build-Snapshot -Branch master" + } + + # PSFirebird is required for this task + if (-not (Get-Module PSFirebird -ListAvailable)) { + Install-Module PSFirebird -MinimumVersion '1.0.0' -Force -Scope CurrentUser + } + Import-Module PSFirebird -MinimumVersion '1.0.0' + + $PSStyle.OutputRendering = 'PlainText' + $imagePrefix = $script:imagePrefix + $imageName = 'firebird' + $defaultDistro = $script:assetsData.config.defaultDistro + + # Detect host architecture + $hostArch = if ($IsLinux) { (dpkg --print-architecture 2>$null) ?? 'amd64' } else { 'amd64' } + $rid = if ($hostArch -eq 'amd64') { 'linux-x64' } else { 'linux-arm64' } + + Write-Build Cyan "Querying snapshot for branch '$Branch' ($rid)..." + $snapshot = Find-FirebirdSnapshotRelease -Branch $Branch -RuntimeIdentifier $rid + + Write-Build Cyan "Found: $($snapshot.FileName) (uploaded: $($snapshot.UploadedAt))" + + # Determine version tag from branch + $snapshotTag = switch ($Branch) { + 'master' { '6-snapshot' } + 'v5.0-release' { '5-snapshot' } + 'v4.0' { '4-snapshot' } + } + + # Determine major version for Dockerfile template + $major = switch ($Branch) { + 'master' { '6' } + 'v5.0-release' { '5' } + 'v4.0' { '4' } + } + + # Prepare snapshot Dockerfile + $snapshotFolder = Join-Path $outputFolder "snapshot-$Branch" $defaultDistro + New-Item -ItemType Directory $snapshotFolder -Force > $null + + $distroConfig = Get-DistroConfig -Distro $defaultDistro + $variables = @{ + 'BASE_IMAGE' = $distroConfig.baseImage + 'ICU_PACKAGE' = $distroConfig.icuPackage + 'EXTRA_PACKAGES' = '' + 'URL_AMD64' = if ($hostArch -eq 'amd64') { "$($snapshot.Url)" } else { '' } + 'SHA256_AMD64' = if ($hostArch -eq 'amd64') { "$($snapshot.Sha256)" } else { '' } + 'URL_ARM64' = if ($hostArch -eq 'arm64') { "$($snapshot.Url)" } else { '' } + 'SHA256_ARM64' = if ($hostArch -eq 'arm64') { "$($snapshot.Sha256)" } else { '' } + 'FIREBIRD_VERSION' = "$snapshotTag" + 'FIREBIRD_MAJOR' = $major + } + + $dockerfile = Expand-TemplateFile -Path './src/Dockerfile.template' -Variables $variables + + # Remove the unused arch case + if ($hostArch -eq 'amd64') { + $dockerfile = $dockerfile -replace "(?ms)\s+arm64\)\s*\\.*?;;\s*\\", '' + } else { + $dockerfile = $dockerfile -replace "(?ms)\s+amd64\)\s*\\.*?;;\s*\\", '' + } + + Write-GeneratedFile -Content $dockerfile -Destination "$snapshotFolder/Dockerfile" + Copy-Item './src/entrypoint.sh' $snapshotFolder + + # Tag with both the bare alias (e.g. `6-snapshot`) and the base-qualified form + # (e.g. `6-snapshot-trixie`) so users can tell which distro the snapshot was built on. + $snapshotTagWithDistro = "$snapshotTag-$defaultDistro" + + # Build + $buildArgs = @( + 'buildx', 'build', '--load' + '--tag', "$imagePrefix/${imageName}:$snapshotTag" + '--tag', "$imagePrefix/${imageName}:$snapshotTagWithDistro" + '--label', 'org.opencontainers.image.description=Firebird Database (snapshot)' + '--label', "org.opencontainers.image.version=$snapshotTag" + '--progress=plain' + $snapshotFolder + ) + Write-Build Cyan "----- [snapshot / $Branch / $defaultDistro / $hostArch] -----" + exec { & docker $buildArgs *>&1 } + + Write-Build Green "Snapshot image built: $imagePrefix/${imageName}:$snapshotTag (also tagged $snapshotTagWithDistro)" } # Synopsis: Default task. diff --git a/generated/3.0.10/bookworm/Dockerfile b/generated/3.0.10/bookworm/Dockerfile index 6434104..b1c41f7 100644 --- a/generated/3.0.10/bookworm/Dockerfile +++ b/generated/3.0.10/bookworm/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v3.0.10/Firebird-3.0.10.33601-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-5e0db3b9312c5bed3eccd1855ec07df5a50176dbff35b8ebf998360b59561cf0} - ENV FIREBIRD_VERSION=3.0.10 ENV FIREBIRD_MAJOR=3 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=3 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu72 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v3.0.10/Firebird-3.0.10.33601-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='5e0db3b9312c5bed3eccd1855ec07df5a50176dbff35b8ebf998360b59561cf0'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/3.0.10/bookworm/entrypoint.sh b/generated/3.0.10/bookworm/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/3.0.10/bookworm/entrypoint.sh +++ b/generated/3.0.10/bookworm/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/3.0.10/bullseye/Dockerfile b/generated/3.0.10/bullseye/Dockerfile index e850023..515282c 100644 --- a/generated/3.0.10/bullseye/Dockerfile +++ b/generated/3.0.10/bullseye/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bullseye-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v3.0.10/Firebird-3.0.10.33601-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-5e0db3b9312c5bed3eccd1855ec07df5a50176dbff35b8ebf998360b59561cf0} - ENV FIREBIRD_VERSION=3.0.10 ENV FIREBIRD_MAJOR=3 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=3 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu67 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v3.0.10/Firebird-3.0.10.33601-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='5e0db3b9312c5bed3eccd1855ec07df5a50176dbff35b8ebf998360b59561cf0'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/3.0.10/bullseye/entrypoint.sh b/generated/3.0.10/bullseye/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/3.0.10/bullseye/entrypoint.sh +++ b/generated/3.0.10/bullseye/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/3.0.10/jammy/Dockerfile b/generated/3.0.10/jammy/Dockerfile index 27efbd4..e779865 100644 --- a/generated/3.0.10/jammy/Dockerfile +++ b/generated/3.0.10/jammy/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:jammy ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v3.0.10/Firebird-3.0.10.33601-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-5e0db3b9312c5bed3eccd1855ec07df5a50176dbff35b8ebf998360b59561cf0} - ENV FIREBIRD_VERSION=3.0.10 ENV FIREBIRD_MAJOR=3 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=3 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu70 \ @@ -41,16 +31,25 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ tzdata \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v3.0.10/Firebird-3.0.10.33601-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='5e0db3b9312c5bed3eccd1855ec07df5a50176dbff35b8ebf998360b59561cf0'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -71,7 +70,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -81,15 +82,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/3.0.10/jammy/entrypoint.sh b/generated/3.0.10/jammy/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/3.0.10/jammy/entrypoint.sh +++ b/generated/3.0.10/jammy/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/3.0.11/bookworm/Dockerfile b/generated/3.0.11/bookworm/Dockerfile index 6a5bfcf..36048e8 100644 --- a/generated/3.0.11/bookworm/Dockerfile +++ b/generated/3.0.11/bookworm/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v3.0.11/Firebird-3.0.11.33703-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-713757e09b40b2631d800dacd9b80179b7eb75693a72089136055a7154413a3e} - ENV FIREBIRD_VERSION=3.0.11 ENV FIREBIRD_MAJOR=3 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=3 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu72 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v3.0.11/Firebird-3.0.11.33703-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='713757e09b40b2631d800dacd9b80179b7eb75693a72089136055a7154413a3e'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/3.0.11/bookworm/entrypoint.sh b/generated/3.0.11/bookworm/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/3.0.11/bookworm/entrypoint.sh +++ b/generated/3.0.11/bookworm/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/3.0.11/bullseye/Dockerfile b/generated/3.0.11/bullseye/Dockerfile index 5fbc3b2..532d178 100644 --- a/generated/3.0.11/bullseye/Dockerfile +++ b/generated/3.0.11/bullseye/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bullseye-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v3.0.11/Firebird-3.0.11.33703-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-713757e09b40b2631d800dacd9b80179b7eb75693a72089136055a7154413a3e} - ENV FIREBIRD_VERSION=3.0.11 ENV FIREBIRD_MAJOR=3 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=3 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu67 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v3.0.11/Firebird-3.0.11.33703-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='713757e09b40b2631d800dacd9b80179b7eb75693a72089136055a7154413a3e'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/3.0.11/bullseye/entrypoint.sh b/generated/3.0.11/bullseye/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/3.0.11/bullseye/entrypoint.sh +++ b/generated/3.0.11/bullseye/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/3.0.11/jammy/Dockerfile b/generated/3.0.11/jammy/Dockerfile index ef38dea..2b4c85d 100644 --- a/generated/3.0.11/jammy/Dockerfile +++ b/generated/3.0.11/jammy/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:jammy ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v3.0.11/Firebird-3.0.11.33703-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-713757e09b40b2631d800dacd9b80179b7eb75693a72089136055a7154413a3e} - ENV FIREBIRD_VERSION=3.0.11 ENV FIREBIRD_MAJOR=3 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=3 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu70 \ @@ -41,16 +31,25 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ tzdata \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v3.0.11/Firebird-3.0.11.33703-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='713757e09b40b2631d800dacd9b80179b7eb75693a72089136055a7154413a3e'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -71,7 +70,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -81,15 +82,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/3.0.11/jammy/entrypoint.sh b/generated/3.0.11/jammy/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/3.0.11/jammy/entrypoint.sh +++ b/generated/3.0.11/jammy/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/3.0.12/bookworm/Dockerfile b/generated/3.0.12/bookworm/Dockerfile index 9608500..7ef07d8 100644 --- a/generated/3.0.12/bookworm/Dockerfile +++ b/generated/3.0.12/bookworm/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v3.0.12/Firebird-3.0.12.33787-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-406a8887ab318a5d8a20781fc1d38a0ca30acdbddbc1558b077646bb2e2e283f} - ENV FIREBIRD_VERSION=3.0.12 ENV FIREBIRD_MAJOR=3 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=3 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu72 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v3.0.12/Firebird-3.0.12.33787-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='406a8887ab318a5d8a20781fc1d38a0ca30acdbddbc1558b077646bb2e2e283f'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/3.0.12/bookworm/entrypoint.sh b/generated/3.0.12/bookworm/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/3.0.12/bookworm/entrypoint.sh +++ b/generated/3.0.12/bookworm/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/3.0.12/bullseye/Dockerfile b/generated/3.0.12/bullseye/Dockerfile index 791ccf9..7d90579 100644 --- a/generated/3.0.12/bullseye/Dockerfile +++ b/generated/3.0.12/bullseye/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bullseye-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v3.0.12/Firebird-3.0.12.33787-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-406a8887ab318a5d8a20781fc1d38a0ca30acdbddbc1558b077646bb2e2e283f} - ENV FIREBIRD_VERSION=3.0.12 ENV FIREBIRD_MAJOR=3 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=3 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu67 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v3.0.12/Firebird-3.0.12.33787-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='406a8887ab318a5d8a20781fc1d38a0ca30acdbddbc1558b077646bb2e2e283f'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/3.0.12/bullseye/entrypoint.sh b/generated/3.0.12/bullseye/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/3.0.12/bullseye/entrypoint.sh +++ b/generated/3.0.12/bullseye/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/3.0.12/jammy/Dockerfile b/generated/3.0.12/jammy/Dockerfile index 2a50339..89ab9ed 100644 --- a/generated/3.0.12/jammy/Dockerfile +++ b/generated/3.0.12/jammy/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:jammy ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v3.0.12/Firebird-3.0.12.33787-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-406a8887ab318a5d8a20781fc1d38a0ca30acdbddbc1558b077646bb2e2e283f} - ENV FIREBIRD_VERSION=3.0.12 ENV FIREBIRD_MAJOR=3 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=3 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu70 \ @@ -41,16 +31,25 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ tzdata \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v3.0.12/Firebird-3.0.12.33787-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='406a8887ab318a5d8a20781fc1d38a0ca30acdbddbc1558b077646bb2e2e283f'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -71,7 +70,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -81,15 +82,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/3.0.12/jammy/entrypoint.sh b/generated/3.0.12/jammy/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/3.0.12/jammy/entrypoint.sh +++ b/generated/3.0.12/jammy/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/3.0.13/bookworm/Dockerfile b/generated/3.0.13/bookworm/Dockerfile index a8852ec..0d5da42 100644 --- a/generated/3.0.13/bookworm/Dockerfile +++ b/generated/3.0.13/bookworm/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v3.0.13/Firebird-3.0.13.33818-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-677e19d6308869d5dd0836a342157c7bd1e4b5a873aa385832da01d81db444dd} - ENV FIREBIRD_VERSION=3.0.13 ENV FIREBIRD_MAJOR=3 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=3 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu72 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v3.0.13/Firebird-3.0.13.33818-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='677e19d6308869d5dd0836a342157c7bd1e4b5a873aa385832da01d81db444dd'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/3.0.13/bookworm/entrypoint.sh b/generated/3.0.13/bookworm/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/3.0.13/bookworm/entrypoint.sh +++ b/generated/3.0.13/bookworm/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/3.0.13/bullseye/Dockerfile b/generated/3.0.13/bullseye/Dockerfile index ef2d5e7..12b4bbc 100644 --- a/generated/3.0.13/bullseye/Dockerfile +++ b/generated/3.0.13/bullseye/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bullseye-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v3.0.13/Firebird-3.0.13.33818-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-677e19d6308869d5dd0836a342157c7bd1e4b5a873aa385832da01d81db444dd} - ENV FIREBIRD_VERSION=3.0.13 ENV FIREBIRD_MAJOR=3 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=3 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu67 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v3.0.13/Firebird-3.0.13.33818-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='677e19d6308869d5dd0836a342157c7bd1e4b5a873aa385832da01d81db444dd'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/3.0.13/bullseye/entrypoint.sh b/generated/3.0.13/bullseye/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/3.0.13/bullseye/entrypoint.sh +++ b/generated/3.0.13/bullseye/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/3.0.13/jammy/Dockerfile b/generated/3.0.13/jammy/Dockerfile index 66031f0..6f7a31c 100644 --- a/generated/3.0.13/jammy/Dockerfile +++ b/generated/3.0.13/jammy/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:jammy ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v3.0.13/Firebird-3.0.13.33818-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-677e19d6308869d5dd0836a342157c7bd1e4b5a873aa385832da01d81db444dd} - ENV FIREBIRD_VERSION=3.0.13 ENV FIREBIRD_MAJOR=3 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=3 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu70 \ @@ -41,16 +31,25 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ tzdata \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v3.0.13/Firebird-3.0.13.33818-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='677e19d6308869d5dd0836a342157c7bd1e4b5a873aa385832da01d81db444dd'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -71,7 +70,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -81,15 +82,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/3.0.13/jammy/entrypoint.sh b/generated/3.0.13/jammy/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/3.0.13/jammy/entrypoint.sh +++ b/generated/3.0.13/jammy/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/3.0.8/bookworm/Dockerfile b/generated/3.0.14/bookworm/Dockerfile similarity index 66% rename from generated/3.0.8/bookworm/Dockerfile rename to generated/3.0.14/bookworm/Dockerfile index e0d6586..6cde251 100644 --- a/generated/3.0.8/bookworm/Dockerfile +++ b/generated/3.0.14/bookworm/Dockerfile @@ -10,17 +10,7 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v3.0.8/Firebird-3.0.8.33535-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-fbf154244d3568f4de4ee68769ed71a0699845197ae1c02c2029dc4d0f1af5f9} - -ENV FIREBIRD_VERSION=3.0.8 +ENV FIREBIRD_VERSION=3.0.14 ENV FIREBIRD_MAJOR=3 # https://linuxcommand.org/lc3_man_pages/seth.html @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=3 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu72 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v3.0.14/Firebird-3.0.14.33856-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='d6fedba1108a46cea2b5f753674046fff0e43c6af27ba01657511635cbc9670f'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/3.0.8/jammy/entrypoint.sh b/generated/3.0.14/bookworm/entrypoint.sh similarity index 81% rename from generated/3.0.8/jammy/entrypoint.sh rename to generated/3.0.14/bookworm/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/3.0.8/jammy/entrypoint.sh +++ b/generated/3.0.14/bookworm/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/3.0.8/bullseye/Dockerfile b/generated/3.0.14/bullseye/Dockerfile similarity index 66% rename from generated/3.0.8/bullseye/Dockerfile rename to generated/3.0.14/bullseye/Dockerfile index 3e521cb..284cda6 100644 --- a/generated/3.0.8/bullseye/Dockerfile +++ b/generated/3.0.14/bullseye/Dockerfile @@ -10,17 +10,7 @@ FROM debian:bullseye-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v3.0.8/Firebird-3.0.8.33535-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-fbf154244d3568f4de4ee68769ed71a0699845197ae1c02c2029dc4d0f1af5f9} - -ENV FIREBIRD_VERSION=3.0.8 +ENV FIREBIRD_VERSION=3.0.14 ENV FIREBIRD_MAJOR=3 # https://linuxcommand.org/lc3_man_pages/seth.html @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=3 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu67 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v3.0.14/Firebird-3.0.14.33856-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='d6fedba1108a46cea2b5f753674046fff0e43c6af27ba01657511635cbc9670f'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/3.0.8/bookworm/entrypoint.sh b/generated/3.0.14/bullseye/entrypoint.sh similarity index 81% rename from generated/3.0.8/bookworm/entrypoint.sh rename to generated/3.0.14/bullseye/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/3.0.8/bookworm/entrypoint.sh +++ b/generated/3.0.14/bullseye/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/3.0.8/jammy/Dockerfile b/generated/3.0.14/jammy/Dockerfile similarity index 66% rename from generated/3.0.8/jammy/Dockerfile rename to generated/3.0.14/jammy/Dockerfile index 8d4ab3c..2290450 100644 --- a/generated/3.0.8/jammy/Dockerfile +++ b/generated/3.0.14/jammy/Dockerfile @@ -10,17 +10,7 @@ FROM ubuntu:jammy ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v3.0.8/Firebird-3.0.8.33535-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-fbf154244d3568f4de4ee68769ed71a0699845197ae1c02c2029dc4d0f1af5f9} - -ENV FIREBIRD_VERSION=3.0.8 +ENV FIREBIRD_VERSION=3.0.14 ENV FIREBIRD_MAJOR=3 # https://linuxcommand.org/lc3_man_pages/seth.html @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=3 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu70 \ @@ -41,16 +31,25 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ tzdata \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v3.0.14/Firebird-3.0.14.33856-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='d6fedba1108a46cea2b5f753674046fff0e43c6af27ba01657511635cbc9670f'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -71,7 +70,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -81,15 +82,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/3.0.8/bullseye/entrypoint.sh b/generated/3.0.14/jammy/entrypoint.sh similarity index 81% rename from generated/3.0.8/bullseye/entrypoint.sh rename to generated/3.0.14/jammy/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/3.0.8/bullseye/entrypoint.sh +++ b/generated/3.0.14/jammy/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/3.0.9/bookworm/Dockerfile b/generated/3.0.9/bookworm/Dockerfile index 792c554..b9b1d7d 100644 --- a/generated/3.0.9/bookworm/Dockerfile +++ b/generated/3.0.9/bookworm/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v3.0.9/Firebird-3.0.9.33560-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-0a80a5dc507f388e96adf9b64584c0b568d94a8f3df19d7baec494c5f98ba5a4} - ENV FIREBIRD_VERSION=3.0.9 ENV FIREBIRD_MAJOR=3 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=3 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu72 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v3.0.9/Firebird-3.0.9.33560-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='0a80a5dc507f388e96adf9b64584c0b568d94a8f3df19d7baec494c5f98ba5a4'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/3.0.9/bookworm/entrypoint.sh b/generated/3.0.9/bookworm/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/3.0.9/bookworm/entrypoint.sh +++ b/generated/3.0.9/bookworm/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/3.0.9/bullseye/Dockerfile b/generated/3.0.9/bullseye/Dockerfile index 9e1f7b6..240659c 100644 --- a/generated/3.0.9/bullseye/Dockerfile +++ b/generated/3.0.9/bullseye/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bullseye-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v3.0.9/Firebird-3.0.9.33560-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-0a80a5dc507f388e96adf9b64584c0b568d94a8f3df19d7baec494c5f98ba5a4} - ENV FIREBIRD_VERSION=3.0.9 ENV FIREBIRD_MAJOR=3 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=3 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu67 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v3.0.9/Firebird-3.0.9.33560-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='0a80a5dc507f388e96adf9b64584c0b568d94a8f3df19d7baec494c5f98ba5a4'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/3.0.9/bullseye/entrypoint.sh b/generated/3.0.9/bullseye/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/3.0.9/bullseye/entrypoint.sh +++ b/generated/3.0.9/bullseye/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/3.0.9/jammy/Dockerfile b/generated/3.0.9/jammy/Dockerfile index 39093f5..584992a 100644 --- a/generated/3.0.9/jammy/Dockerfile +++ b/generated/3.0.9/jammy/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:jammy ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v3.0.9/Firebird-3.0.9.33560-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-0a80a5dc507f388e96adf9b64584c0b568d94a8f3df19d7baec494c5f98ba5a4} - ENV FIREBIRD_VERSION=3.0.9 ENV FIREBIRD_MAJOR=3 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=3 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu70 \ @@ -41,16 +31,25 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ tzdata \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v3.0.9/Firebird-3.0.9.33560-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='0a80a5dc507f388e96adf9b64584c0b568d94a8f3df19d7baec494c5f98ba5a4'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -71,7 +70,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -81,15 +82,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/3.0.9/jammy/entrypoint.sh b/generated/3.0.9/jammy/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/3.0.9/jammy/entrypoint.sh +++ b/generated/3.0.9/jammy/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.0/bookworm/Dockerfile b/generated/4.0.0/bookworm/Dockerfile index 0b644d2..a6efc81 100644 --- a/generated/4.0.0/bookworm/Dockerfile +++ b/generated/4.0.0/bookworm/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.0/Firebird-4.0.0.2496-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-06f6e00b9657a1967f21b34bea8150d5a3e5b1d1b1313bb6455e16878b42d63e} - ENV FIREBIRD_VERSION=4.0.0 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu72 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.0/Firebird-4.0.0.2496-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='06f6e00b9657a1967f21b34bea8150d5a3e5b1d1b1313bb6455e16878b42d63e'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.0/bookworm/entrypoint.sh b/generated/4.0.0/bookworm/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.0/bookworm/entrypoint.sh +++ b/generated/4.0.0/bookworm/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.0/bullseye/Dockerfile b/generated/4.0.0/bullseye/Dockerfile index 4d4a93d..5268a65 100644 --- a/generated/4.0.0/bullseye/Dockerfile +++ b/generated/4.0.0/bullseye/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bullseye-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.0/Firebird-4.0.0.2496-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-06f6e00b9657a1967f21b34bea8150d5a3e5b1d1b1313bb6455e16878b42d63e} - ENV FIREBIRD_VERSION=4.0.0 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu67 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.0/Firebird-4.0.0.2496-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='06f6e00b9657a1967f21b34bea8150d5a3e5b1d1b1313bb6455e16878b42d63e'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.0/bullseye/entrypoint.sh b/generated/4.0.0/bullseye/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.0/bullseye/entrypoint.sh +++ b/generated/4.0.0/bullseye/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.0/jammy/Dockerfile b/generated/4.0.0/jammy/Dockerfile index 7aacfc4..bf5f936 100644 --- a/generated/4.0.0/jammy/Dockerfile +++ b/generated/4.0.0/jammy/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:jammy ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.0/Firebird-4.0.0.2496-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-06f6e00b9657a1967f21b34bea8150d5a3e5b1d1b1313bb6455e16878b42d63e} - ENV FIREBIRD_VERSION=4.0.0 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu70 \ @@ -41,16 +31,25 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ tzdata \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.0/Firebird-4.0.0.2496-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='06f6e00b9657a1967f21b34bea8150d5a3e5b1d1b1313bb6455e16878b42d63e'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -71,7 +70,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -81,15 +82,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.0/jammy/entrypoint.sh b/generated/4.0.0/jammy/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.0/jammy/entrypoint.sh +++ b/generated/4.0.0/jammy/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.0/noble/Dockerfile b/generated/4.0.0/noble/Dockerfile index 2a69918..7615168 100644 --- a/generated/4.0.0/noble/Dockerfile +++ b/generated/4.0.0/noble/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:noble ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.0/Firebird-4.0.0.2496-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-06f6e00b9657a1967f21b34bea8150d5a3e5b1d1b1313bb6455e16878b42d63e} - ENV FIREBIRD_VERSION=4.0.0 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu74 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.0/Firebird-4.0.0.2496-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='06f6e00b9657a1967f21b34bea8150d5a3e5b1d1b1313bb6455e16878b42d63e'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.0/noble/entrypoint.sh b/generated/4.0.0/noble/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.0/noble/entrypoint.sh +++ b/generated/4.0.0/noble/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.0/trixie/Dockerfile b/generated/4.0.0/trixie/Dockerfile new file mode 100644 index 0000000..04a8e6e --- /dev/null +++ b/generated/4.0.0/trixie/Dockerfile @@ -0,0 +1,100 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + +# Best practices for Dockerfile instructions +# https://docs.docker.com/develop/develop-images/instructions/ + +FROM debian:trixie-slim + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +ENV FIREBIRD_VERSION=4.0.0 +ENV FIREBIRD_MAJOR=4 + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -x Print commands and their arguments as they are executed. + +# Prerequisites +# FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 +RUN set -eux; \ + apt-get update; \ + # Install prerequisites + tini + curl/ca-certificates for download + apt-get install -y --no-install-recommends \ + libatomic1 \ + libicu76 \ + $([ $FIREBIRD_MAJOR -eq 3 ] && echo 'libncurses5' || echo 'libncurses6') \ + libtomcrypt1 \ + libtommath1 \ + netbase \ + procps \ + tini \ + ca-certificates \ + curl; \ + \ + # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.0/Firebird-4.0.0.2496-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='06f6e00b9657a1967f21b34bea8150d5a3e5b1d1b1313bb6455e16878b42d63e'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ + mkdir -p /tmp/firebird_install; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + \ + # Extract, install, clean + cd /tmp/firebird_install; \ + tar --extract --file=firebird-bundle.tar.gz --gunzip --verbose --strip-components=1; \ + ./install.sh -silent; \ + rm -rf /tmp/firebird_install; \ + # Remove unnecessary files + rm -rf /opt/firebird/doc \ + /opt/firebird/examples \ + /opt/firebird/help \ + /opt/firebird/include; \ + # Remove 'employee' sample database from 'databases.conf' + sed -i '/^employee/d' /opt/firebird/databases.conf; \ + \ + # Clean up temporary packages (curl, ca-certificates) and apt lists + apt-get purge -y --auto-remove curl ca-certificates; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true + +# System path +ENV PATH=/opt/firebird/bin:$PATH + +# Data directory +ENV FIREBIRD_DATA=/var/lib/firebird/data +RUN set -eux; \ + mkdir -p "$FIREBIRD_DATA"; \ + chown -R firebird:firebird "$FIREBIRD_DATA"; \ + chmod 755 "$FIREBIRD_DATA" +VOLUME $FIREBIRD_DATA + +# Entrypoint +COPY entrypoint.sh /usr/local/bin/ +RUN set -eux; \ + chmod +x /usr/local/bin/entrypoint.sh +ENTRYPOINT ["tini", "--", "entrypoint.sh"] + +STOPSIGNAL SIGTERM +EXPOSE 3050/tcp + +# Fix terminfo location +ENV TERMINFO=/lib/terminfo/ + +CMD ["firebird"] + diff --git a/generated/4.0.0/trixie/entrypoint.sh b/generated/4.0.0/trixie/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/4.0.0/trixie/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/generated/4.0.1/bookworm/Dockerfile b/generated/4.0.1/bookworm/Dockerfile index cb44736..446987d 100644 --- a/generated/4.0.1/bookworm/Dockerfile +++ b/generated/4.0.1/bookworm/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.1/Firebird-4.0.1.2692-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-90b6727b8366b3674fc30ba13d0f52ab0b419c3bb3a4224c8d3f480143538998} - ENV FIREBIRD_VERSION=4.0.1 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu72 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.1/Firebird-4.0.1.2692-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='90b6727b8366b3674fc30ba13d0f52ab0b419c3bb3a4224c8d3f480143538998'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.1/bookworm/entrypoint.sh b/generated/4.0.1/bookworm/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.1/bookworm/entrypoint.sh +++ b/generated/4.0.1/bookworm/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.1/bullseye/Dockerfile b/generated/4.0.1/bullseye/Dockerfile index 2ca0546..3caadfc 100644 --- a/generated/4.0.1/bullseye/Dockerfile +++ b/generated/4.0.1/bullseye/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bullseye-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.1/Firebird-4.0.1.2692-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-90b6727b8366b3674fc30ba13d0f52ab0b419c3bb3a4224c8d3f480143538998} - ENV FIREBIRD_VERSION=4.0.1 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu67 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.1/Firebird-4.0.1.2692-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='90b6727b8366b3674fc30ba13d0f52ab0b419c3bb3a4224c8d3f480143538998'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.1/bullseye/entrypoint.sh b/generated/4.0.1/bullseye/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.1/bullseye/entrypoint.sh +++ b/generated/4.0.1/bullseye/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.1/jammy/Dockerfile b/generated/4.0.1/jammy/Dockerfile index 676a1e0..bfaca1c 100644 --- a/generated/4.0.1/jammy/Dockerfile +++ b/generated/4.0.1/jammy/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:jammy ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.1/Firebird-4.0.1.2692-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-90b6727b8366b3674fc30ba13d0f52ab0b419c3bb3a4224c8d3f480143538998} - ENV FIREBIRD_VERSION=4.0.1 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu70 \ @@ -41,16 +31,25 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ tzdata \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.1/Firebird-4.0.1.2692-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='90b6727b8366b3674fc30ba13d0f52ab0b419c3bb3a4224c8d3f480143538998'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -71,7 +70,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -81,15 +82,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.1/jammy/entrypoint.sh b/generated/4.0.1/jammy/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.1/jammy/entrypoint.sh +++ b/generated/4.0.1/jammy/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.1/noble/Dockerfile b/generated/4.0.1/noble/Dockerfile index cf4733e..702e513 100644 --- a/generated/4.0.1/noble/Dockerfile +++ b/generated/4.0.1/noble/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:noble ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.1/Firebird-4.0.1.2692-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-90b6727b8366b3674fc30ba13d0f52ab0b419c3bb3a4224c8d3f480143538998} - ENV FIREBIRD_VERSION=4.0.1 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu74 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.1/Firebird-4.0.1.2692-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='90b6727b8366b3674fc30ba13d0f52ab0b419c3bb3a4224c8d3f480143538998'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.1/noble/entrypoint.sh b/generated/4.0.1/noble/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.1/noble/entrypoint.sh +++ b/generated/4.0.1/noble/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.1/trixie/Dockerfile b/generated/4.0.1/trixie/Dockerfile new file mode 100644 index 0000000..cc88527 --- /dev/null +++ b/generated/4.0.1/trixie/Dockerfile @@ -0,0 +1,100 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + +# Best practices for Dockerfile instructions +# https://docs.docker.com/develop/develop-images/instructions/ + +FROM debian:trixie-slim + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +ENV FIREBIRD_VERSION=4.0.1 +ENV FIREBIRD_MAJOR=4 + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -x Print commands and their arguments as they are executed. + +# Prerequisites +# FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 +RUN set -eux; \ + apt-get update; \ + # Install prerequisites + tini + curl/ca-certificates for download + apt-get install -y --no-install-recommends \ + libatomic1 \ + libicu76 \ + $([ $FIREBIRD_MAJOR -eq 3 ] && echo 'libncurses5' || echo 'libncurses6') \ + libtomcrypt1 \ + libtommath1 \ + netbase \ + procps \ + tini \ + ca-certificates \ + curl; \ + \ + # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.1/Firebird-4.0.1.2692-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='90b6727b8366b3674fc30ba13d0f52ab0b419c3bb3a4224c8d3f480143538998'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ + mkdir -p /tmp/firebird_install; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + \ + # Extract, install, clean + cd /tmp/firebird_install; \ + tar --extract --file=firebird-bundle.tar.gz --gunzip --verbose --strip-components=1; \ + ./install.sh -silent; \ + rm -rf /tmp/firebird_install; \ + # Remove unnecessary files + rm -rf /opt/firebird/doc \ + /opt/firebird/examples \ + /opt/firebird/help \ + /opt/firebird/include; \ + # Remove 'employee' sample database from 'databases.conf' + sed -i '/^employee/d' /opt/firebird/databases.conf; \ + \ + # Clean up temporary packages (curl, ca-certificates) and apt lists + apt-get purge -y --auto-remove curl ca-certificates; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true + +# System path +ENV PATH=/opt/firebird/bin:$PATH + +# Data directory +ENV FIREBIRD_DATA=/var/lib/firebird/data +RUN set -eux; \ + mkdir -p "$FIREBIRD_DATA"; \ + chown -R firebird:firebird "$FIREBIRD_DATA"; \ + chmod 755 "$FIREBIRD_DATA" +VOLUME $FIREBIRD_DATA + +# Entrypoint +COPY entrypoint.sh /usr/local/bin/ +RUN set -eux; \ + chmod +x /usr/local/bin/entrypoint.sh +ENTRYPOINT ["tini", "--", "entrypoint.sh"] + +STOPSIGNAL SIGTERM +EXPOSE 3050/tcp + +# Fix terminfo location +ENV TERMINFO=/lib/terminfo/ + +CMD ["firebird"] + diff --git a/generated/4.0.1/trixie/entrypoint.sh b/generated/4.0.1/trixie/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/4.0.1/trixie/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/generated/4.0.2/bookworm/Dockerfile b/generated/4.0.2/bookworm/Dockerfile index 236f0d7..84dbc20 100644 --- a/generated/4.0.2/bookworm/Dockerfile +++ b/generated/4.0.2/bookworm/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.2/Firebird-4.0.2.2816-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-70108f9854a522ac6eb7b2bdc1bda9780aab97dbfbf358ced90c0db13b8af9fa} - ENV FIREBIRD_VERSION=4.0.2 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu72 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.2/Firebird-4.0.2.2816-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='70108f9854a522ac6eb7b2bdc1bda9780aab97dbfbf358ced90c0db13b8af9fa'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.2/bookworm/entrypoint.sh b/generated/4.0.2/bookworm/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.2/bookworm/entrypoint.sh +++ b/generated/4.0.2/bookworm/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.2/bullseye/Dockerfile b/generated/4.0.2/bullseye/Dockerfile index 598caf1..9a2accf 100644 --- a/generated/4.0.2/bullseye/Dockerfile +++ b/generated/4.0.2/bullseye/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bullseye-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.2/Firebird-4.0.2.2816-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-70108f9854a522ac6eb7b2bdc1bda9780aab97dbfbf358ced90c0db13b8af9fa} - ENV FIREBIRD_VERSION=4.0.2 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu67 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.2/Firebird-4.0.2.2816-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='70108f9854a522ac6eb7b2bdc1bda9780aab97dbfbf358ced90c0db13b8af9fa'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.2/bullseye/entrypoint.sh b/generated/4.0.2/bullseye/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.2/bullseye/entrypoint.sh +++ b/generated/4.0.2/bullseye/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.2/jammy/Dockerfile b/generated/4.0.2/jammy/Dockerfile index fbd0a27..5335fea 100644 --- a/generated/4.0.2/jammy/Dockerfile +++ b/generated/4.0.2/jammy/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:jammy ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.2/Firebird-4.0.2.2816-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-70108f9854a522ac6eb7b2bdc1bda9780aab97dbfbf358ced90c0db13b8af9fa} - ENV FIREBIRD_VERSION=4.0.2 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu70 \ @@ -41,16 +31,25 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ tzdata \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.2/Firebird-4.0.2.2816-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='70108f9854a522ac6eb7b2bdc1bda9780aab97dbfbf358ced90c0db13b8af9fa'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -71,7 +70,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -81,15 +82,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.2/jammy/entrypoint.sh b/generated/4.0.2/jammy/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.2/jammy/entrypoint.sh +++ b/generated/4.0.2/jammy/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.2/noble/Dockerfile b/generated/4.0.2/noble/Dockerfile index 36cf074..81ed713 100644 --- a/generated/4.0.2/noble/Dockerfile +++ b/generated/4.0.2/noble/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:noble ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.2/Firebird-4.0.2.2816-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-70108f9854a522ac6eb7b2bdc1bda9780aab97dbfbf358ced90c0db13b8af9fa} - ENV FIREBIRD_VERSION=4.0.2 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu74 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.2/Firebird-4.0.2.2816-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='70108f9854a522ac6eb7b2bdc1bda9780aab97dbfbf358ced90c0db13b8af9fa'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.2/noble/entrypoint.sh b/generated/4.0.2/noble/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.2/noble/entrypoint.sh +++ b/generated/4.0.2/noble/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.2/trixie/Dockerfile b/generated/4.0.2/trixie/Dockerfile new file mode 100644 index 0000000..c7c18ad --- /dev/null +++ b/generated/4.0.2/trixie/Dockerfile @@ -0,0 +1,100 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + +# Best practices for Dockerfile instructions +# https://docs.docker.com/develop/develop-images/instructions/ + +FROM debian:trixie-slim + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +ENV FIREBIRD_VERSION=4.0.2 +ENV FIREBIRD_MAJOR=4 + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -x Print commands and their arguments as they are executed. + +# Prerequisites +# FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 +RUN set -eux; \ + apt-get update; \ + # Install prerequisites + tini + curl/ca-certificates for download + apt-get install -y --no-install-recommends \ + libatomic1 \ + libicu76 \ + $([ $FIREBIRD_MAJOR -eq 3 ] && echo 'libncurses5' || echo 'libncurses6') \ + libtomcrypt1 \ + libtommath1 \ + netbase \ + procps \ + tini \ + ca-certificates \ + curl; \ + \ + # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.2/Firebird-4.0.2.2816-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='70108f9854a522ac6eb7b2bdc1bda9780aab97dbfbf358ced90c0db13b8af9fa'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ + mkdir -p /tmp/firebird_install; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + \ + # Extract, install, clean + cd /tmp/firebird_install; \ + tar --extract --file=firebird-bundle.tar.gz --gunzip --verbose --strip-components=1; \ + ./install.sh -silent; \ + rm -rf /tmp/firebird_install; \ + # Remove unnecessary files + rm -rf /opt/firebird/doc \ + /opt/firebird/examples \ + /opt/firebird/help \ + /opt/firebird/include; \ + # Remove 'employee' sample database from 'databases.conf' + sed -i '/^employee/d' /opt/firebird/databases.conf; \ + \ + # Clean up temporary packages (curl, ca-certificates) and apt lists + apt-get purge -y --auto-remove curl ca-certificates; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true + +# System path +ENV PATH=/opt/firebird/bin:$PATH + +# Data directory +ENV FIREBIRD_DATA=/var/lib/firebird/data +RUN set -eux; \ + mkdir -p "$FIREBIRD_DATA"; \ + chown -R firebird:firebird "$FIREBIRD_DATA"; \ + chmod 755 "$FIREBIRD_DATA" +VOLUME $FIREBIRD_DATA + +# Entrypoint +COPY entrypoint.sh /usr/local/bin/ +RUN set -eux; \ + chmod +x /usr/local/bin/entrypoint.sh +ENTRYPOINT ["tini", "--", "entrypoint.sh"] + +STOPSIGNAL SIGTERM +EXPOSE 3050/tcp + +# Fix terminfo location +ENV TERMINFO=/lib/terminfo/ + +CMD ["firebird"] + diff --git a/generated/4.0.2/trixie/entrypoint.sh b/generated/4.0.2/trixie/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/4.0.2/trixie/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/generated/4.0.3/bookworm/Dockerfile b/generated/4.0.3/bookworm/Dockerfile index 1244457..141e75b 100644 --- a/generated/4.0.3/bookworm/Dockerfile +++ b/generated/4.0.3/bookworm/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.3/Firebird-4.0.3.2975-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-bd439c3c8f74fd03a592eafd20de37ce028c424fbe023352f1bd17db54c3257d} - ENV FIREBIRD_VERSION=4.0.3 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu72 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.3/Firebird-4.0.3.2975-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='bd439c3c8f74fd03a592eafd20de37ce028c424fbe023352f1bd17db54c3257d'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.3/bookworm/entrypoint.sh b/generated/4.0.3/bookworm/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.3/bookworm/entrypoint.sh +++ b/generated/4.0.3/bookworm/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.3/bullseye/Dockerfile b/generated/4.0.3/bullseye/Dockerfile index 6b0b178..901428a 100644 --- a/generated/4.0.3/bullseye/Dockerfile +++ b/generated/4.0.3/bullseye/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bullseye-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.3/Firebird-4.0.3.2975-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-bd439c3c8f74fd03a592eafd20de37ce028c424fbe023352f1bd17db54c3257d} - ENV FIREBIRD_VERSION=4.0.3 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu67 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.3/Firebird-4.0.3.2975-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='bd439c3c8f74fd03a592eafd20de37ce028c424fbe023352f1bd17db54c3257d'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.3/bullseye/entrypoint.sh b/generated/4.0.3/bullseye/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.3/bullseye/entrypoint.sh +++ b/generated/4.0.3/bullseye/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.3/jammy/Dockerfile b/generated/4.0.3/jammy/Dockerfile index a26e25f..6d5862e 100644 --- a/generated/4.0.3/jammy/Dockerfile +++ b/generated/4.0.3/jammy/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:jammy ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.3/Firebird-4.0.3.2975-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-bd439c3c8f74fd03a592eafd20de37ce028c424fbe023352f1bd17db54c3257d} - ENV FIREBIRD_VERSION=4.0.3 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu70 \ @@ -41,16 +31,25 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ tzdata \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.3/Firebird-4.0.3.2975-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='bd439c3c8f74fd03a592eafd20de37ce028c424fbe023352f1bd17db54c3257d'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -71,7 +70,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -81,15 +82,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.3/jammy/entrypoint.sh b/generated/4.0.3/jammy/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.3/jammy/entrypoint.sh +++ b/generated/4.0.3/jammy/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.3/noble/Dockerfile b/generated/4.0.3/noble/Dockerfile index a5434a8..40bc342 100644 --- a/generated/4.0.3/noble/Dockerfile +++ b/generated/4.0.3/noble/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:noble ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.3/Firebird-4.0.3.2975-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-bd439c3c8f74fd03a592eafd20de37ce028c424fbe023352f1bd17db54c3257d} - ENV FIREBIRD_VERSION=4.0.3 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu74 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.3/Firebird-4.0.3.2975-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='bd439c3c8f74fd03a592eafd20de37ce028c424fbe023352f1bd17db54c3257d'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.3/noble/entrypoint.sh b/generated/4.0.3/noble/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.3/noble/entrypoint.sh +++ b/generated/4.0.3/noble/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.3/trixie/Dockerfile b/generated/4.0.3/trixie/Dockerfile new file mode 100644 index 0000000..06a5a93 --- /dev/null +++ b/generated/4.0.3/trixie/Dockerfile @@ -0,0 +1,100 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + +# Best practices for Dockerfile instructions +# https://docs.docker.com/develop/develop-images/instructions/ + +FROM debian:trixie-slim + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +ENV FIREBIRD_VERSION=4.0.3 +ENV FIREBIRD_MAJOR=4 + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -x Print commands and their arguments as they are executed. + +# Prerequisites +# FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 +RUN set -eux; \ + apt-get update; \ + # Install prerequisites + tini + curl/ca-certificates for download + apt-get install -y --no-install-recommends \ + libatomic1 \ + libicu76 \ + $([ $FIREBIRD_MAJOR -eq 3 ] && echo 'libncurses5' || echo 'libncurses6') \ + libtomcrypt1 \ + libtommath1 \ + netbase \ + procps \ + tini \ + ca-certificates \ + curl; \ + \ + # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.3/Firebird-4.0.3.2975-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='bd439c3c8f74fd03a592eafd20de37ce028c424fbe023352f1bd17db54c3257d'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ + mkdir -p /tmp/firebird_install; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + \ + # Extract, install, clean + cd /tmp/firebird_install; \ + tar --extract --file=firebird-bundle.tar.gz --gunzip --verbose --strip-components=1; \ + ./install.sh -silent; \ + rm -rf /tmp/firebird_install; \ + # Remove unnecessary files + rm -rf /opt/firebird/doc \ + /opt/firebird/examples \ + /opt/firebird/help \ + /opt/firebird/include; \ + # Remove 'employee' sample database from 'databases.conf' + sed -i '/^employee/d' /opt/firebird/databases.conf; \ + \ + # Clean up temporary packages (curl, ca-certificates) and apt lists + apt-get purge -y --auto-remove curl ca-certificates; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true + +# System path +ENV PATH=/opt/firebird/bin:$PATH + +# Data directory +ENV FIREBIRD_DATA=/var/lib/firebird/data +RUN set -eux; \ + mkdir -p "$FIREBIRD_DATA"; \ + chown -R firebird:firebird "$FIREBIRD_DATA"; \ + chmod 755 "$FIREBIRD_DATA" +VOLUME $FIREBIRD_DATA + +# Entrypoint +COPY entrypoint.sh /usr/local/bin/ +RUN set -eux; \ + chmod +x /usr/local/bin/entrypoint.sh +ENTRYPOINT ["tini", "--", "entrypoint.sh"] + +STOPSIGNAL SIGTERM +EXPOSE 3050/tcp + +# Fix terminfo location +ENV TERMINFO=/lib/terminfo/ + +CMD ["firebird"] + diff --git a/generated/4.0.3/trixie/entrypoint.sh b/generated/4.0.3/trixie/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/4.0.3/trixie/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/generated/4.0.4/bookworm/Dockerfile b/generated/4.0.4/bookworm/Dockerfile index 0f844f0..a3b0f23 100644 --- a/generated/4.0.4/bookworm/Dockerfile +++ b/generated/4.0.4/bookworm/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.4/Firebird-4.0.4.3010-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-ef589301c5e13a1f8481e1e38c453641ef5082344bf69edb51f8aa9f036bcaca} - ENV FIREBIRD_VERSION=4.0.4 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu72 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.4/Firebird-4.0.4.3010-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='ef589301c5e13a1f8481e1e38c453641ef5082344bf69edb51f8aa9f036bcaca'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.4/bookworm/entrypoint.sh b/generated/4.0.4/bookworm/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.4/bookworm/entrypoint.sh +++ b/generated/4.0.4/bookworm/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.4/bullseye/Dockerfile b/generated/4.0.4/bullseye/Dockerfile index 7181b0a..908ed19 100644 --- a/generated/4.0.4/bullseye/Dockerfile +++ b/generated/4.0.4/bullseye/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bullseye-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.4/Firebird-4.0.4.3010-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-ef589301c5e13a1f8481e1e38c453641ef5082344bf69edb51f8aa9f036bcaca} - ENV FIREBIRD_VERSION=4.0.4 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu67 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.4/Firebird-4.0.4.3010-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='ef589301c5e13a1f8481e1e38c453641ef5082344bf69edb51f8aa9f036bcaca'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.4/bullseye/entrypoint.sh b/generated/4.0.4/bullseye/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.4/bullseye/entrypoint.sh +++ b/generated/4.0.4/bullseye/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.4/jammy/Dockerfile b/generated/4.0.4/jammy/Dockerfile index 08d7ee6..2b7e1d5 100644 --- a/generated/4.0.4/jammy/Dockerfile +++ b/generated/4.0.4/jammy/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:jammy ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.4/Firebird-4.0.4.3010-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-ef589301c5e13a1f8481e1e38c453641ef5082344bf69edb51f8aa9f036bcaca} - ENV FIREBIRD_VERSION=4.0.4 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu70 \ @@ -41,16 +31,25 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ tzdata \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.4/Firebird-4.0.4.3010-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='ef589301c5e13a1f8481e1e38c453641ef5082344bf69edb51f8aa9f036bcaca'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -71,7 +70,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -81,15 +82,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.4/jammy/entrypoint.sh b/generated/4.0.4/jammy/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.4/jammy/entrypoint.sh +++ b/generated/4.0.4/jammy/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.4/noble/Dockerfile b/generated/4.0.4/noble/Dockerfile index bc328aa..48ad5eb 100644 --- a/generated/4.0.4/noble/Dockerfile +++ b/generated/4.0.4/noble/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:noble ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.4/Firebird-4.0.4.3010-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-ef589301c5e13a1f8481e1e38c453641ef5082344bf69edb51f8aa9f036bcaca} - ENV FIREBIRD_VERSION=4.0.4 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu74 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.4/Firebird-4.0.4.3010-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='ef589301c5e13a1f8481e1e38c453641ef5082344bf69edb51f8aa9f036bcaca'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.4/noble/entrypoint.sh b/generated/4.0.4/noble/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.4/noble/entrypoint.sh +++ b/generated/4.0.4/noble/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.4/trixie/Dockerfile b/generated/4.0.4/trixie/Dockerfile new file mode 100644 index 0000000..e30e1fd --- /dev/null +++ b/generated/4.0.4/trixie/Dockerfile @@ -0,0 +1,100 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + +# Best practices for Dockerfile instructions +# https://docs.docker.com/develop/develop-images/instructions/ + +FROM debian:trixie-slim + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +ENV FIREBIRD_VERSION=4.0.4 +ENV FIREBIRD_MAJOR=4 + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -x Print commands and their arguments as they are executed. + +# Prerequisites +# FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 +RUN set -eux; \ + apt-get update; \ + # Install prerequisites + tini + curl/ca-certificates for download + apt-get install -y --no-install-recommends \ + libatomic1 \ + libicu76 \ + $([ $FIREBIRD_MAJOR -eq 3 ] && echo 'libncurses5' || echo 'libncurses6') \ + libtomcrypt1 \ + libtommath1 \ + netbase \ + procps \ + tini \ + ca-certificates \ + curl; \ + \ + # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.4/Firebird-4.0.4.3010-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='ef589301c5e13a1f8481e1e38c453641ef5082344bf69edb51f8aa9f036bcaca'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ + mkdir -p /tmp/firebird_install; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + \ + # Extract, install, clean + cd /tmp/firebird_install; \ + tar --extract --file=firebird-bundle.tar.gz --gunzip --verbose --strip-components=1; \ + ./install.sh -silent; \ + rm -rf /tmp/firebird_install; \ + # Remove unnecessary files + rm -rf /opt/firebird/doc \ + /opt/firebird/examples \ + /opt/firebird/help \ + /opt/firebird/include; \ + # Remove 'employee' sample database from 'databases.conf' + sed -i '/^employee/d' /opt/firebird/databases.conf; \ + \ + # Clean up temporary packages (curl, ca-certificates) and apt lists + apt-get purge -y --auto-remove curl ca-certificates; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true + +# System path +ENV PATH=/opt/firebird/bin:$PATH + +# Data directory +ENV FIREBIRD_DATA=/var/lib/firebird/data +RUN set -eux; \ + mkdir -p "$FIREBIRD_DATA"; \ + chown -R firebird:firebird "$FIREBIRD_DATA"; \ + chmod 755 "$FIREBIRD_DATA" +VOLUME $FIREBIRD_DATA + +# Entrypoint +COPY entrypoint.sh /usr/local/bin/ +RUN set -eux; \ + chmod +x /usr/local/bin/entrypoint.sh +ENTRYPOINT ["tini", "--", "entrypoint.sh"] + +STOPSIGNAL SIGTERM +EXPOSE 3050/tcp + +# Fix terminfo location +ENV TERMINFO=/lib/terminfo/ + +CMD ["firebird"] + diff --git a/generated/4.0.4/trixie/entrypoint.sh b/generated/4.0.4/trixie/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/4.0.4/trixie/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/generated/4.0.5/bookworm/Dockerfile b/generated/4.0.5/bookworm/Dockerfile index 5603627..71a860f 100644 --- a/generated/4.0.5/bookworm/Dockerfile +++ b/generated/4.0.5/bookworm/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.5/Firebird-4.0.5.3140-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-6ae43e4fa31ddc99220575023b7d954fb218c063375bb589b16fbe9fcdfdcaa6} - ENV FIREBIRD_VERSION=4.0.5 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu72 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.5/Firebird-4.0.5.3140-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='6ae43e4fa31ddc99220575023b7d954fb218c063375bb589b16fbe9fcdfdcaa6'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.5/bookworm/entrypoint.sh b/generated/4.0.5/bookworm/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.5/bookworm/entrypoint.sh +++ b/generated/4.0.5/bookworm/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.5/bullseye/Dockerfile b/generated/4.0.5/bullseye/Dockerfile index ed50cee..bba0a1e 100644 --- a/generated/4.0.5/bullseye/Dockerfile +++ b/generated/4.0.5/bullseye/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bullseye-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.5/Firebird-4.0.5.3140-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-6ae43e4fa31ddc99220575023b7d954fb218c063375bb589b16fbe9fcdfdcaa6} - ENV FIREBIRD_VERSION=4.0.5 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu67 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.5/Firebird-4.0.5.3140-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='6ae43e4fa31ddc99220575023b7d954fb218c063375bb589b16fbe9fcdfdcaa6'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.5/bullseye/entrypoint.sh b/generated/4.0.5/bullseye/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.5/bullseye/entrypoint.sh +++ b/generated/4.0.5/bullseye/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.5/jammy/Dockerfile b/generated/4.0.5/jammy/Dockerfile index 01f15a4..66db1e8 100644 --- a/generated/4.0.5/jammy/Dockerfile +++ b/generated/4.0.5/jammy/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:jammy ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.5/Firebird-4.0.5.3140-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-6ae43e4fa31ddc99220575023b7d954fb218c063375bb589b16fbe9fcdfdcaa6} - ENV FIREBIRD_VERSION=4.0.5 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu70 \ @@ -41,16 +31,25 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ tzdata \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.5/Firebird-4.0.5.3140-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='6ae43e4fa31ddc99220575023b7d954fb218c063375bb589b16fbe9fcdfdcaa6'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -71,7 +70,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -81,15 +82,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.5/jammy/entrypoint.sh b/generated/4.0.5/jammy/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.5/jammy/entrypoint.sh +++ b/generated/4.0.5/jammy/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.5/noble/Dockerfile b/generated/4.0.5/noble/Dockerfile index 86885b0..0975dec 100644 --- a/generated/4.0.5/noble/Dockerfile +++ b/generated/4.0.5/noble/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:noble ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.5/Firebird-4.0.5.3140-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-6ae43e4fa31ddc99220575023b7d954fb218c063375bb589b16fbe9fcdfdcaa6} - ENV FIREBIRD_VERSION=4.0.5 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu74 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.5/Firebird-4.0.5.3140-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='6ae43e4fa31ddc99220575023b7d954fb218c063375bb589b16fbe9fcdfdcaa6'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.5/noble/entrypoint.sh b/generated/4.0.5/noble/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.5/noble/entrypoint.sh +++ b/generated/4.0.5/noble/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.5/trixie/Dockerfile b/generated/4.0.5/trixie/Dockerfile new file mode 100644 index 0000000..6069295 --- /dev/null +++ b/generated/4.0.5/trixie/Dockerfile @@ -0,0 +1,100 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + +# Best practices for Dockerfile instructions +# https://docs.docker.com/develop/develop-images/instructions/ + +FROM debian:trixie-slim + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +ENV FIREBIRD_VERSION=4.0.5 +ENV FIREBIRD_MAJOR=4 + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -x Print commands and their arguments as they are executed. + +# Prerequisites +# FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 +RUN set -eux; \ + apt-get update; \ + # Install prerequisites + tini + curl/ca-certificates for download + apt-get install -y --no-install-recommends \ + libatomic1 \ + libicu76 \ + $([ $FIREBIRD_MAJOR -eq 3 ] && echo 'libncurses5' || echo 'libncurses6') \ + libtomcrypt1 \ + libtommath1 \ + netbase \ + procps \ + tini \ + ca-certificates \ + curl; \ + \ + # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.5/Firebird-4.0.5.3140-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='6ae43e4fa31ddc99220575023b7d954fb218c063375bb589b16fbe9fcdfdcaa6'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ + mkdir -p /tmp/firebird_install; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + \ + # Extract, install, clean + cd /tmp/firebird_install; \ + tar --extract --file=firebird-bundle.tar.gz --gunzip --verbose --strip-components=1; \ + ./install.sh -silent; \ + rm -rf /tmp/firebird_install; \ + # Remove unnecessary files + rm -rf /opt/firebird/doc \ + /opt/firebird/examples \ + /opt/firebird/help \ + /opt/firebird/include; \ + # Remove 'employee' sample database from 'databases.conf' + sed -i '/^employee/d' /opt/firebird/databases.conf; \ + \ + # Clean up temporary packages (curl, ca-certificates) and apt lists + apt-get purge -y --auto-remove curl ca-certificates; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true + +# System path +ENV PATH=/opt/firebird/bin:$PATH + +# Data directory +ENV FIREBIRD_DATA=/var/lib/firebird/data +RUN set -eux; \ + mkdir -p "$FIREBIRD_DATA"; \ + chown -R firebird:firebird "$FIREBIRD_DATA"; \ + chmod 755 "$FIREBIRD_DATA" +VOLUME $FIREBIRD_DATA + +# Entrypoint +COPY entrypoint.sh /usr/local/bin/ +RUN set -eux; \ + chmod +x /usr/local/bin/entrypoint.sh +ENTRYPOINT ["tini", "--", "entrypoint.sh"] + +STOPSIGNAL SIGTERM +EXPOSE 3050/tcp + +# Fix terminfo location +ENV TERMINFO=/lib/terminfo/ + +CMD ["firebird"] + diff --git a/generated/4.0.5/trixie/entrypoint.sh b/generated/4.0.5/trixie/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/4.0.5/trixie/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/generated/4.0.6/bookworm/Dockerfile b/generated/4.0.6/bookworm/Dockerfile index 19d797e..5128e45 100644 --- a/generated/4.0.6/bookworm/Dockerfile +++ b/generated/4.0.6/bookworm/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.6/Firebird-4.0.6.3221-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-6ff5f672e10ee38ec5fc5394012ac83fe19872543dd2fefa249c1ccf62bc0075} - ENV FIREBIRD_VERSION=4.0.6 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu72 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.6/Firebird-4.0.6.3221-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='6ff5f672e10ee38ec5fc5394012ac83fe19872543dd2fefa249c1ccf62bc0075'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.6/bookworm/entrypoint.sh b/generated/4.0.6/bookworm/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.6/bookworm/entrypoint.sh +++ b/generated/4.0.6/bookworm/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.6/bullseye/Dockerfile b/generated/4.0.6/bullseye/Dockerfile index 72eb9ed..272a871 100644 --- a/generated/4.0.6/bullseye/Dockerfile +++ b/generated/4.0.6/bullseye/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bullseye-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.6/Firebird-4.0.6.3221-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-6ff5f672e10ee38ec5fc5394012ac83fe19872543dd2fefa249c1ccf62bc0075} - ENV FIREBIRD_VERSION=4.0.6 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu67 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.6/Firebird-4.0.6.3221-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='6ff5f672e10ee38ec5fc5394012ac83fe19872543dd2fefa249c1ccf62bc0075'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.6/bullseye/entrypoint.sh b/generated/4.0.6/bullseye/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.6/bullseye/entrypoint.sh +++ b/generated/4.0.6/bullseye/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.6/jammy/Dockerfile b/generated/4.0.6/jammy/Dockerfile index 6586ea6..c471fd6 100644 --- a/generated/4.0.6/jammy/Dockerfile +++ b/generated/4.0.6/jammy/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:jammy ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.6/Firebird-4.0.6.3221-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-6ff5f672e10ee38ec5fc5394012ac83fe19872543dd2fefa249c1ccf62bc0075} - ENV FIREBIRD_VERSION=4.0.6 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu70 \ @@ -41,16 +31,25 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ tzdata \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.6/Firebird-4.0.6.3221-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='6ff5f672e10ee38ec5fc5394012ac83fe19872543dd2fefa249c1ccf62bc0075'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -71,7 +70,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -81,15 +82,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.6/jammy/entrypoint.sh b/generated/4.0.6/jammy/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.6/jammy/entrypoint.sh +++ b/generated/4.0.6/jammy/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.6/noble/Dockerfile b/generated/4.0.6/noble/Dockerfile index afb4da5..ea813f0 100644 --- a/generated/4.0.6/noble/Dockerfile +++ b/generated/4.0.6/noble/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:noble ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v4.0.6/Firebird-4.0.6.3221-0.amd64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-6ff5f672e10ee38ec5fc5394012ac83fe19872543dd2fefa249c1ccf62bc0075} - ENV FIREBIRD_VERSION=4.0.6 ENV FIREBIRD_MAJOR=4 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=4 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu74 \ @@ -41,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.6/Firebird-4.0.6.3221-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='6ff5f672e10ee38ec5fc5394012ac83fe19872543dd2fefa249c1ccf62bc0075'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +81,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/4.0.6/noble/entrypoint.sh b/generated/4.0.6/noble/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/4.0.6/noble/entrypoint.sh +++ b/generated/4.0.6/noble/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/4.0.6/trixie/Dockerfile b/generated/4.0.6/trixie/Dockerfile new file mode 100644 index 0000000..afef149 --- /dev/null +++ b/generated/4.0.6/trixie/Dockerfile @@ -0,0 +1,100 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + +# Best practices for Dockerfile instructions +# https://docs.docker.com/develop/develop-images/instructions/ + +FROM debian:trixie-slim + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +ENV FIREBIRD_VERSION=4.0.6 +ENV FIREBIRD_MAJOR=4 + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -x Print commands and their arguments as they are executed. + +# Prerequisites +# FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 +RUN set -eux; \ + apt-get update; \ + # Install prerequisites + tini + curl/ca-certificates for download + apt-get install -y --no-install-recommends \ + libatomic1 \ + libicu76 \ + $([ $FIREBIRD_MAJOR -eq 3 ] && echo 'libncurses5' || echo 'libncurses6') \ + libtomcrypt1 \ + libtommath1 \ + netbase \ + procps \ + tini \ + ca-certificates \ + curl; \ + \ + # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.6/Firebird-4.0.6.3221-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='6ff5f672e10ee38ec5fc5394012ac83fe19872543dd2fefa249c1ccf62bc0075'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ + mkdir -p /tmp/firebird_install; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + \ + # Extract, install, clean + cd /tmp/firebird_install; \ + tar --extract --file=firebird-bundle.tar.gz --gunzip --verbose --strip-components=1; \ + ./install.sh -silent; \ + rm -rf /tmp/firebird_install; \ + # Remove unnecessary files + rm -rf /opt/firebird/doc \ + /opt/firebird/examples \ + /opt/firebird/help \ + /opt/firebird/include; \ + # Remove 'employee' sample database from 'databases.conf' + sed -i '/^employee/d' /opt/firebird/databases.conf; \ + \ + # Clean up temporary packages (curl, ca-certificates) and apt lists + apt-get purge -y --auto-remove curl ca-certificates; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true + +# System path +ENV PATH=/opt/firebird/bin:$PATH + +# Data directory +ENV FIREBIRD_DATA=/var/lib/firebird/data +RUN set -eux; \ + mkdir -p "$FIREBIRD_DATA"; \ + chown -R firebird:firebird "$FIREBIRD_DATA"; \ + chmod 755 "$FIREBIRD_DATA" +VOLUME $FIREBIRD_DATA + +# Entrypoint +COPY entrypoint.sh /usr/local/bin/ +RUN set -eux; \ + chmod +x /usr/local/bin/entrypoint.sh +ENTRYPOINT ["tini", "--", "entrypoint.sh"] + +STOPSIGNAL SIGTERM +EXPOSE 3050/tcp + +# Fix terminfo location +ENV TERMINFO=/lib/terminfo/ + +CMD ["firebird"] + diff --git a/generated/4.0.6/trixie/entrypoint.sh b/generated/4.0.6/trixie/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/4.0.6/trixie/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/src/Dockerfile.bookworm.template b/generated/4.0.7/bookworm/Dockerfile similarity index 64% rename from src/Dockerfile.bookworm.template rename to generated/4.0.7/bookworm/Dockerfile index e8482e2..07d1390 100644 --- a/src/Dockerfile.bookworm.template +++ b/generated/4.0.7/bookworm/Dockerfile @@ -1,3 +1,7 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + # Best practices for Dockerfile instructions # https://docs.docker.com/develop/develop-images/instructions/ @@ -6,18 +10,8 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+<%$TUrlArchARM64%>} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+<%$TSha256ArchARM64%>} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-<%$TUrlArchAMD64%>} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-<%$TSha256ArchAMD64%>} - -ENV FIREBIRD_VERSION=<%$TImageVersion%> -ENV FIREBIRD_MAJOR=<%$TMajor%> +ENV FIREBIRD_VERSION=4.0.7 +ENV FIREBIRD_MAJOR=4 # https://linuxcommand.org/lc3_man_pages/seth.html # -e Exit immediately if a command exits with a non-zero status. @@ -28,7 +22,7 @@ ENV FIREBIRD_MAJOR=<%$TMajor%> # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu72 \ @@ -37,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.7/Firebird-4.0.7.3271-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='d2964dfb190d7b0ec57271b53e6539f715ecc119f1cb8cd10339662eed9a7dea'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -66,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -76,18 +81,20 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location ENV TERMINFO=/lib/terminfo/ CMD ["firebird"] + diff --git a/generated/4.0.7/bookworm/entrypoint.sh b/generated/4.0.7/bookworm/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/4.0.7/bookworm/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/src/Dockerfile.bullseye.template b/generated/4.0.7/bullseye/Dockerfile similarity index 64% rename from src/Dockerfile.bullseye.template rename to generated/4.0.7/bullseye/Dockerfile index 7c18ddf..679d660 100644 --- a/src/Dockerfile.bullseye.template +++ b/generated/4.0.7/bullseye/Dockerfile @@ -1,3 +1,7 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + # Best practices for Dockerfile instructions # https://docs.docker.com/develop/develop-images/instructions/ @@ -6,18 +10,8 @@ FROM debian:bullseye-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+<%$TUrlArchARM64%>} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+<%$TSha256ArchARM64%>} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-<%$TUrlArchAMD64%>} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-<%$TSha256ArchAMD64%>} - -ENV FIREBIRD_VERSION=<%$TImageVersion%> -ENV FIREBIRD_MAJOR=<%$TMajor%> +ENV FIREBIRD_VERSION=4.0.7 +ENV FIREBIRD_MAJOR=4 # https://linuxcommand.org/lc3_man_pages/seth.html # -e Exit immediately if a command exits with a non-zero status. @@ -28,7 +22,7 @@ ENV FIREBIRD_MAJOR=<%$TMajor%> # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu67 \ @@ -37,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.7/Firebird-4.0.7.3271-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='d2964dfb190d7b0ec57271b53e6539f715ecc119f1cb8cd10339662eed9a7dea'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -66,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -76,18 +81,20 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location ENV TERMINFO=/lib/terminfo/ CMD ["firebird"] + diff --git a/generated/4.0.7/bullseye/entrypoint.sh b/generated/4.0.7/bullseye/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/4.0.7/bullseye/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/src/Dockerfile.jammy.template b/generated/4.0.7/jammy/Dockerfile similarity index 64% rename from src/Dockerfile.jammy.template rename to generated/4.0.7/jammy/Dockerfile index b691fbd..f335c22 100644 --- a/src/Dockerfile.jammy.template +++ b/generated/4.0.7/jammy/Dockerfile @@ -1,3 +1,7 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + # Best practices for Dockerfile instructions # https://docs.docker.com/develop/develop-images/instructions/ @@ -6,18 +10,8 @@ FROM ubuntu:jammy ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+<%$TUrlArchARM64%>} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+<%$TSha256ArchARM64%>} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-<%$TUrlArchAMD64%>} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-<%$TSha256ArchAMD64%>} - -ENV FIREBIRD_VERSION=<%$TImageVersion%> -ENV FIREBIRD_MAJOR=<%$TMajor%> +ENV FIREBIRD_VERSION=4.0.7 +ENV FIREBIRD_MAJOR=4 # https://linuxcommand.org/lc3_man_pages/seth.html # -e Exit immediately if a command exits with a non-zero status. @@ -28,7 +22,7 @@ ENV FIREBIRD_MAJOR=<%$TMajor%> # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu70 \ @@ -37,16 +31,25 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ tzdata \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.7/Firebird-4.0.7.3271-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='d2964dfb190d7b0ec57271b53e6539f715ecc119f1cb8cd10339662eed9a7dea'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -67,7 +70,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -77,18 +82,20 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location ENV TERMINFO=/lib/terminfo/ CMD ["firebird"] + diff --git a/generated/4.0.7/jammy/entrypoint.sh b/generated/4.0.7/jammy/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/4.0.7/jammy/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/src/Dockerfile.noble.template b/generated/4.0.7/noble/Dockerfile similarity index 63% rename from src/Dockerfile.noble.template rename to generated/4.0.7/noble/Dockerfile index 30f685b..a26e361 100644 --- a/src/Dockerfile.noble.template +++ b/generated/4.0.7/noble/Dockerfile @@ -1,3 +1,7 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + # Best practices for Dockerfile instructions # https://docs.docker.com/develop/develop-images/instructions/ @@ -6,18 +10,8 @@ FROM ubuntu:noble ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+<%$TUrlArchARM64%>} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+<%$TSha256ArchARM64%>} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-<%$TUrlArchAMD64%>} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-<%$TSha256ArchAMD64%>} - -ENV FIREBIRD_VERSION=<%$TImageVersion%> -ENV FIREBIRD_MAJOR=<%$TMajor%> +ENV FIREBIRD_VERSION=4.0.7 +ENV FIREBIRD_MAJOR=4 # https://linuxcommand.org/lc3_man_pages/seth.html # -e Exit immediately if a command exits with a non-zero status. @@ -28,7 +22,7 @@ ENV FIREBIRD_MAJOR=<%$TMajor%> # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu74 \ @@ -37,15 +31,24 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.7/Firebird-4.0.7.3271-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='d2964dfb190d7b0ec57271b53e6539f715ecc119f1cb8cd10339662eed9a7dea'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -66,7 +69,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -76,18 +81,20 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location ENV TERMINFO=/lib/terminfo/ CMD ["firebird"] + diff --git a/generated/4.0.7/noble/entrypoint.sh b/generated/4.0.7/noble/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/4.0.7/noble/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/generated/4.0.7/trixie/Dockerfile b/generated/4.0.7/trixie/Dockerfile new file mode 100644 index 0000000..9bf26e5 --- /dev/null +++ b/generated/4.0.7/trixie/Dockerfile @@ -0,0 +1,100 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + +# Best practices for Dockerfile instructions +# https://docs.docker.com/develop/develop-images/instructions/ + +FROM debian:trixie-slim + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +ENV FIREBIRD_VERSION=4.0.7 +ENV FIREBIRD_MAJOR=4 + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -x Print commands and their arguments as they are executed. + +# Prerequisites +# FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 +RUN set -eux; \ + apt-get update; \ + # Install prerequisites + tini + curl/ca-certificates for download + apt-get install -y --no-install-recommends \ + libatomic1 \ + libicu76 \ + $([ $FIREBIRD_MAJOR -eq 3 ] && echo 'libncurses5' || echo 'libncurses6') \ + libtomcrypt1 \ + libtommath1 \ + netbase \ + procps \ + tini \ + ca-certificates \ + curl; \ + \ + # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v4.0.7/Firebird-4.0.7.3271-0.amd64.tar.gz'; \ + FIREBIRD_SHA256='d2964dfb190d7b0ec57271b53e6539f715ecc119f1cb8cd10339662eed9a7dea'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ + mkdir -p /tmp/firebird_install; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + \ + # Extract, install, clean + cd /tmp/firebird_install; \ + tar --extract --file=firebird-bundle.tar.gz --gunzip --verbose --strip-components=1; \ + ./install.sh -silent; \ + rm -rf /tmp/firebird_install; \ + # Remove unnecessary files + rm -rf /opt/firebird/doc \ + /opt/firebird/examples \ + /opt/firebird/help \ + /opt/firebird/include; \ + # Remove 'employee' sample database from 'databases.conf' + sed -i '/^employee/d' /opt/firebird/databases.conf; \ + \ + # Clean up temporary packages (curl, ca-certificates) and apt lists + apt-get purge -y --auto-remove curl ca-certificates; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true + +# System path +ENV PATH=/opt/firebird/bin:$PATH + +# Data directory +ENV FIREBIRD_DATA=/var/lib/firebird/data +RUN set -eux; \ + mkdir -p "$FIREBIRD_DATA"; \ + chown -R firebird:firebird "$FIREBIRD_DATA"; \ + chmod 755 "$FIREBIRD_DATA" +VOLUME $FIREBIRD_DATA + +# Entrypoint +COPY entrypoint.sh /usr/local/bin/ +RUN set -eux; \ + chmod +x /usr/local/bin/entrypoint.sh +ENTRYPOINT ["tini", "--", "entrypoint.sh"] + +STOPSIGNAL SIGTERM +EXPOSE 3050/tcp + +# Fix terminfo location +ENV TERMINFO=/lib/terminfo/ + +CMD ["firebird"] + diff --git a/generated/4.0.7/trixie/entrypoint.sh b/generated/4.0.7/trixie/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/4.0.7/trixie/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/generated/5.0.0/bookworm/Dockerfile b/generated/5.0.0/bookworm/Dockerfile index 57a408d..65cf179 100644 --- a/generated/5.0.0/bookworm/Dockerfile +++ b/generated/5.0.0/bookworm/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-arm64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+bdb62abc91a4c26a86b9377256529622e3046f4ec4f66fbdcf46747688d45033} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-x64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-137b356ea464e224b6ed1241e6dba95b6b950ff1feef91696d4071d4da880768} - ENV FIREBIRD_VERSION=5.0.0 ENV FIREBIRD_MAJOR=5 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=5 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu72 \ @@ -41,15 +31,28 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='137b356ea464e224b6ed1241e6dba95b6b950ff1feef91696d4071d4da880768'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='bdb62abc91a4c26a86b9377256529622e3046f4ec4f66fbdcf46747688d45033'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +73,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +85,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/5.0.0/bookworm/entrypoint.sh b/generated/5.0.0/bookworm/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/5.0.0/bookworm/entrypoint.sh +++ b/generated/5.0.0/bookworm/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/5.0.0/bullseye/Dockerfile b/generated/5.0.0/bullseye/Dockerfile index 0ca4396..23fea34 100644 --- a/generated/5.0.0/bullseye/Dockerfile +++ b/generated/5.0.0/bullseye/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bullseye-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-arm64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+bdb62abc91a4c26a86b9377256529622e3046f4ec4f66fbdcf46747688d45033} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-x64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-137b356ea464e224b6ed1241e6dba95b6b950ff1feef91696d4071d4da880768} - ENV FIREBIRD_VERSION=5.0.0 ENV FIREBIRD_MAJOR=5 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=5 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu67 \ @@ -41,15 +31,28 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='137b356ea464e224b6ed1241e6dba95b6b950ff1feef91696d4071d4da880768'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='bdb62abc91a4c26a86b9377256529622e3046f4ec4f66fbdcf46747688d45033'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +73,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +85,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/5.0.0/bullseye/entrypoint.sh b/generated/5.0.0/bullseye/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/5.0.0/bullseye/entrypoint.sh +++ b/generated/5.0.0/bullseye/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/5.0.0/jammy/Dockerfile b/generated/5.0.0/jammy/Dockerfile index 2b9de5a..5f809dc 100644 --- a/generated/5.0.0/jammy/Dockerfile +++ b/generated/5.0.0/jammy/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:jammy ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-arm64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+bdb62abc91a4c26a86b9377256529622e3046f4ec4f66fbdcf46747688d45033} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-x64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-137b356ea464e224b6ed1241e6dba95b6b950ff1feef91696d4071d4da880768} - ENV FIREBIRD_VERSION=5.0.0 ENV FIREBIRD_MAJOR=5 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=5 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu70 \ @@ -41,16 +31,29 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ tzdata \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='137b356ea464e224b6ed1241e6dba95b6b950ff1feef91696d4071d4da880768'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='bdb62abc91a4c26a86b9377256529622e3046f4ec4f66fbdcf46747688d45033'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -71,7 +74,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -81,15 +86,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/5.0.0/jammy/entrypoint.sh b/generated/5.0.0/jammy/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/5.0.0/jammy/entrypoint.sh +++ b/generated/5.0.0/jammy/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/5.0.0/noble/Dockerfile b/generated/5.0.0/noble/Dockerfile index 799bb49..07abd34 100644 --- a/generated/5.0.0/noble/Dockerfile +++ b/generated/5.0.0/noble/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:noble ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-arm64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+bdb62abc91a4c26a86b9377256529622e3046f4ec4f66fbdcf46747688d45033} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-x64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-137b356ea464e224b6ed1241e6dba95b6b950ff1feef91696d4071d4da880768} - ENV FIREBIRD_VERSION=5.0.0 ENV FIREBIRD_MAJOR=5 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=5 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu74 \ @@ -41,15 +31,28 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='137b356ea464e224b6ed1241e6dba95b6b950ff1feef91696d4071d4da880768'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='bdb62abc91a4c26a86b9377256529622e3046f4ec4f66fbdcf46747688d45033'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +73,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +85,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/5.0.0/noble/entrypoint.sh b/generated/5.0.0/noble/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/5.0.0/noble/entrypoint.sh +++ b/generated/5.0.0/noble/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/5.0.0/trixie/Dockerfile b/generated/5.0.0/trixie/Dockerfile new file mode 100644 index 0000000..5363dea --- /dev/null +++ b/generated/5.0.0/trixie/Dockerfile @@ -0,0 +1,104 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + +# Best practices for Dockerfile instructions +# https://docs.docker.com/develop/develop-images/instructions/ + +FROM debian:trixie-slim + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +ENV FIREBIRD_VERSION=5.0.0 +ENV FIREBIRD_MAJOR=5 + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -x Print commands and their arguments as they are executed. + +# Prerequisites +# FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 +RUN set -eux; \ + apt-get update; \ + # Install prerequisites + tini + curl/ca-certificates for download + apt-get install -y --no-install-recommends \ + libatomic1 \ + libicu76 \ + $([ $FIREBIRD_MAJOR -eq 3 ] && echo 'libncurses5' || echo 'libncurses6') \ + libtomcrypt1 \ + libtommath1 \ + netbase \ + procps \ + tini \ + ca-certificates \ + curl; \ + \ + # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='137b356ea464e224b6ed1241e6dba95b6b950ff1feef91696d4071d4da880768'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.0/Firebird-5.0.0.1306-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='bdb62abc91a4c26a86b9377256529622e3046f4ec4f66fbdcf46747688d45033'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ + mkdir -p /tmp/firebird_install; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + \ + # Extract, install, clean + cd /tmp/firebird_install; \ + tar --extract --file=firebird-bundle.tar.gz --gunzip --verbose --strip-components=1; \ + ./install.sh -silent; \ + rm -rf /tmp/firebird_install; \ + # Remove unnecessary files + rm -rf /opt/firebird/doc \ + /opt/firebird/examples \ + /opt/firebird/help \ + /opt/firebird/include; \ + # Remove 'employee' sample database from 'databases.conf' + sed -i '/^employee/d' /opt/firebird/databases.conf; \ + \ + # Clean up temporary packages (curl, ca-certificates) and apt lists + apt-get purge -y --auto-remove curl ca-certificates; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true + +# System path +ENV PATH=/opt/firebird/bin:$PATH + +# Data directory +ENV FIREBIRD_DATA=/var/lib/firebird/data +RUN set -eux; \ + mkdir -p "$FIREBIRD_DATA"; \ + chown -R firebird:firebird "$FIREBIRD_DATA"; \ + chmod 755 "$FIREBIRD_DATA" +VOLUME $FIREBIRD_DATA + +# Entrypoint +COPY entrypoint.sh /usr/local/bin/ +RUN set -eux; \ + chmod +x /usr/local/bin/entrypoint.sh +ENTRYPOINT ["tini", "--", "entrypoint.sh"] + +STOPSIGNAL SIGTERM +EXPOSE 3050/tcp + +# Fix terminfo location +ENV TERMINFO=/lib/terminfo/ + +CMD ["firebird"] + diff --git a/generated/5.0.0/trixie/entrypoint.sh b/generated/5.0.0/trixie/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/5.0.0/trixie/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/generated/5.0.1/bookworm/Dockerfile b/generated/5.0.1/bookworm/Dockerfile index de915cc..62ae1db 100644 --- a/generated/5.0.1/bookworm/Dockerfile +++ b/generated/5.0.1/bookworm/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-arm64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+46b3f4f170458a93365c67118c062ba8509903fe8293bf8a62e7bd8a388e2d06} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-x64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-e1023b005e5d6db8f717af032e91f0f94aa7a8dbe0e78f250931214ca0a21e57} - ENV FIREBIRD_VERSION=5.0.1 ENV FIREBIRD_MAJOR=5 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=5 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu72 \ @@ -41,15 +31,28 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='e1023b005e5d6db8f717af032e91f0f94aa7a8dbe0e78f250931214ca0a21e57'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='46b3f4f170458a93365c67118c062ba8509903fe8293bf8a62e7bd8a388e2d06'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +73,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +85,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/5.0.1/bookworm/entrypoint.sh b/generated/5.0.1/bookworm/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/5.0.1/bookworm/entrypoint.sh +++ b/generated/5.0.1/bookworm/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/5.0.1/bullseye/Dockerfile b/generated/5.0.1/bullseye/Dockerfile index 0a638ee..dda03bb 100644 --- a/generated/5.0.1/bullseye/Dockerfile +++ b/generated/5.0.1/bullseye/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bullseye-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-arm64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+46b3f4f170458a93365c67118c062ba8509903fe8293bf8a62e7bd8a388e2d06} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-x64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-e1023b005e5d6db8f717af032e91f0f94aa7a8dbe0e78f250931214ca0a21e57} - ENV FIREBIRD_VERSION=5.0.1 ENV FIREBIRD_MAJOR=5 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=5 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu67 \ @@ -41,15 +31,28 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='e1023b005e5d6db8f717af032e91f0f94aa7a8dbe0e78f250931214ca0a21e57'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='46b3f4f170458a93365c67118c062ba8509903fe8293bf8a62e7bd8a388e2d06'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +73,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +85,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/5.0.1/bullseye/entrypoint.sh b/generated/5.0.1/bullseye/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/5.0.1/bullseye/entrypoint.sh +++ b/generated/5.0.1/bullseye/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/5.0.1/jammy/Dockerfile b/generated/5.0.1/jammy/Dockerfile index 0bf9b26..81b555e 100644 --- a/generated/5.0.1/jammy/Dockerfile +++ b/generated/5.0.1/jammy/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:jammy ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-arm64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+46b3f4f170458a93365c67118c062ba8509903fe8293bf8a62e7bd8a388e2d06} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-x64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-e1023b005e5d6db8f717af032e91f0f94aa7a8dbe0e78f250931214ca0a21e57} - ENV FIREBIRD_VERSION=5.0.1 ENV FIREBIRD_MAJOR=5 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=5 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu70 \ @@ -41,16 +31,29 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ tzdata \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='e1023b005e5d6db8f717af032e91f0f94aa7a8dbe0e78f250931214ca0a21e57'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='46b3f4f170458a93365c67118c062ba8509903fe8293bf8a62e7bd8a388e2d06'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -71,7 +74,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -81,15 +86,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/5.0.1/jammy/entrypoint.sh b/generated/5.0.1/jammy/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/5.0.1/jammy/entrypoint.sh +++ b/generated/5.0.1/jammy/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/5.0.1/noble/Dockerfile b/generated/5.0.1/noble/Dockerfile index ac4a75c..d150ffd 100644 --- a/generated/5.0.1/noble/Dockerfile +++ b/generated/5.0.1/noble/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:noble ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-arm64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+46b3f4f170458a93365c67118c062ba8509903fe8293bf8a62e7bd8a388e2d06} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-x64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-e1023b005e5d6db8f717af032e91f0f94aa7a8dbe0e78f250931214ca0a21e57} - ENV FIREBIRD_VERSION=5.0.1 ENV FIREBIRD_MAJOR=5 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=5 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu74 \ @@ -41,15 +31,28 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='e1023b005e5d6db8f717af032e91f0f94aa7a8dbe0e78f250931214ca0a21e57'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='46b3f4f170458a93365c67118c062ba8509903fe8293bf8a62e7bd8a388e2d06'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +73,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +85,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/5.0.1/noble/entrypoint.sh b/generated/5.0.1/noble/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/5.0.1/noble/entrypoint.sh +++ b/generated/5.0.1/noble/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/5.0.1/trixie/Dockerfile b/generated/5.0.1/trixie/Dockerfile new file mode 100644 index 0000000..3d8879d --- /dev/null +++ b/generated/5.0.1/trixie/Dockerfile @@ -0,0 +1,104 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + +# Best practices for Dockerfile instructions +# https://docs.docker.com/develop/develop-images/instructions/ + +FROM debian:trixie-slim + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +ENV FIREBIRD_VERSION=5.0.1 +ENV FIREBIRD_MAJOR=5 + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -x Print commands and their arguments as they are executed. + +# Prerequisites +# FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 +RUN set -eux; \ + apt-get update; \ + # Install prerequisites + tini + curl/ca-certificates for download + apt-get install -y --no-install-recommends \ + libatomic1 \ + libicu76 \ + $([ $FIREBIRD_MAJOR -eq 3 ] && echo 'libncurses5' || echo 'libncurses6') \ + libtomcrypt1 \ + libtommath1 \ + netbase \ + procps \ + tini \ + ca-certificates \ + curl; \ + \ + # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='e1023b005e5d6db8f717af032e91f0f94aa7a8dbe0e78f250931214ca0a21e57'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.1/Firebird-5.0.1.1469-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='46b3f4f170458a93365c67118c062ba8509903fe8293bf8a62e7bd8a388e2d06'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ + mkdir -p /tmp/firebird_install; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + \ + # Extract, install, clean + cd /tmp/firebird_install; \ + tar --extract --file=firebird-bundle.tar.gz --gunzip --verbose --strip-components=1; \ + ./install.sh -silent; \ + rm -rf /tmp/firebird_install; \ + # Remove unnecessary files + rm -rf /opt/firebird/doc \ + /opt/firebird/examples \ + /opt/firebird/help \ + /opt/firebird/include; \ + # Remove 'employee' sample database from 'databases.conf' + sed -i '/^employee/d' /opt/firebird/databases.conf; \ + \ + # Clean up temporary packages (curl, ca-certificates) and apt lists + apt-get purge -y --auto-remove curl ca-certificates; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true + +# System path +ENV PATH=/opt/firebird/bin:$PATH + +# Data directory +ENV FIREBIRD_DATA=/var/lib/firebird/data +RUN set -eux; \ + mkdir -p "$FIREBIRD_DATA"; \ + chown -R firebird:firebird "$FIREBIRD_DATA"; \ + chmod 755 "$FIREBIRD_DATA" +VOLUME $FIREBIRD_DATA + +# Entrypoint +COPY entrypoint.sh /usr/local/bin/ +RUN set -eux; \ + chmod +x /usr/local/bin/entrypoint.sh +ENTRYPOINT ["tini", "--", "entrypoint.sh"] + +STOPSIGNAL SIGTERM +EXPOSE 3050/tcp + +# Fix terminfo location +ENV TERMINFO=/lib/terminfo/ + +CMD ["firebird"] + diff --git a/generated/5.0.1/trixie/entrypoint.sh b/generated/5.0.1/trixie/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/5.0.1/trixie/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/generated/5.0.2/bookworm/Dockerfile b/generated/5.0.2/bookworm/Dockerfile index f05a86e..05520c7 100644 --- a/generated/5.0.2/bookworm/Dockerfile +++ b/generated/5.0.2/bookworm/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-arm64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+216edb3594d3318690bd3f2ae9979a9a52efb512eb1bf799c0bace50106a0a69} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-x64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-23d6e0522f32fb13c288f67c98105014c3186ecf3f930f96ca9af1897b9565bf} - ENV FIREBIRD_VERSION=5.0.2 ENV FIREBIRD_MAJOR=5 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=5 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu72 \ @@ -41,15 +31,28 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='23d6e0522f32fb13c288f67c98105014c3186ecf3f930f96ca9af1897b9565bf'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='216edb3594d3318690bd3f2ae9979a9a52efb512eb1bf799c0bace50106a0a69'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +73,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +85,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/5.0.2/bookworm/entrypoint.sh b/generated/5.0.2/bookworm/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/5.0.2/bookworm/entrypoint.sh +++ b/generated/5.0.2/bookworm/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/5.0.2/bullseye/Dockerfile b/generated/5.0.2/bullseye/Dockerfile index 8bf4e05..e2fa618 100644 --- a/generated/5.0.2/bullseye/Dockerfile +++ b/generated/5.0.2/bullseye/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bullseye-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-arm64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+216edb3594d3318690bd3f2ae9979a9a52efb512eb1bf799c0bace50106a0a69} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-x64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-23d6e0522f32fb13c288f67c98105014c3186ecf3f930f96ca9af1897b9565bf} - ENV FIREBIRD_VERSION=5.0.2 ENV FIREBIRD_MAJOR=5 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=5 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu67 \ @@ -41,15 +31,28 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='23d6e0522f32fb13c288f67c98105014c3186ecf3f930f96ca9af1897b9565bf'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='216edb3594d3318690bd3f2ae9979a9a52efb512eb1bf799c0bace50106a0a69'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +73,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +85,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/5.0.2/bullseye/entrypoint.sh b/generated/5.0.2/bullseye/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/5.0.2/bullseye/entrypoint.sh +++ b/generated/5.0.2/bullseye/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/5.0.2/jammy/Dockerfile b/generated/5.0.2/jammy/Dockerfile index 417cd21..3c32685 100644 --- a/generated/5.0.2/jammy/Dockerfile +++ b/generated/5.0.2/jammy/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:jammy ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-arm64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+216edb3594d3318690bd3f2ae9979a9a52efb512eb1bf799c0bace50106a0a69} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-x64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-23d6e0522f32fb13c288f67c98105014c3186ecf3f930f96ca9af1897b9565bf} - ENV FIREBIRD_VERSION=5.0.2 ENV FIREBIRD_MAJOR=5 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=5 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu70 \ @@ -41,16 +31,29 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ tzdata \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='23d6e0522f32fb13c288f67c98105014c3186ecf3f930f96ca9af1897b9565bf'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='216edb3594d3318690bd3f2ae9979a9a52efb512eb1bf799c0bace50106a0a69'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -71,7 +74,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -81,15 +86,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/5.0.2/jammy/entrypoint.sh b/generated/5.0.2/jammy/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/5.0.2/jammy/entrypoint.sh +++ b/generated/5.0.2/jammy/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/5.0.2/noble/Dockerfile b/generated/5.0.2/noble/Dockerfile index ebee33d..66799ba 100644 --- a/generated/5.0.2/noble/Dockerfile +++ b/generated/5.0.2/noble/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:noble ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-arm64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+216edb3594d3318690bd3f2ae9979a9a52efb512eb1bf799c0bace50106a0a69} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-x64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-23d6e0522f32fb13c288f67c98105014c3186ecf3f930f96ca9af1897b9565bf} - ENV FIREBIRD_VERSION=5.0.2 ENV FIREBIRD_MAJOR=5 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=5 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu74 \ @@ -41,15 +31,28 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='23d6e0522f32fb13c288f67c98105014c3186ecf3f930f96ca9af1897b9565bf'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='216edb3594d3318690bd3f2ae9979a9a52efb512eb1bf799c0bace50106a0a69'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +73,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +85,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/5.0.2/noble/entrypoint.sh b/generated/5.0.2/noble/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/5.0.2/noble/entrypoint.sh +++ b/generated/5.0.2/noble/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/5.0.2/trixie/Dockerfile b/generated/5.0.2/trixie/Dockerfile new file mode 100644 index 0000000..551c4c1 --- /dev/null +++ b/generated/5.0.2/trixie/Dockerfile @@ -0,0 +1,104 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + +# Best practices for Dockerfile instructions +# https://docs.docker.com/develop/develop-images/instructions/ + +FROM debian:trixie-slim + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +ENV FIREBIRD_VERSION=5.0.2 +ENV FIREBIRD_MAJOR=5 + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -x Print commands and their arguments as they are executed. + +# Prerequisites +# FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 +RUN set -eux; \ + apt-get update; \ + # Install prerequisites + tini + curl/ca-certificates for download + apt-get install -y --no-install-recommends \ + libatomic1 \ + libicu76 \ + $([ $FIREBIRD_MAJOR -eq 3 ] && echo 'libncurses5' || echo 'libncurses6') \ + libtomcrypt1 \ + libtommath1 \ + netbase \ + procps \ + tini \ + ca-certificates \ + curl; \ + \ + # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='23d6e0522f32fb13c288f67c98105014c3186ecf3f930f96ca9af1897b9565bf'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.2/Firebird-5.0.2.1613-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='216edb3594d3318690bd3f2ae9979a9a52efb512eb1bf799c0bace50106a0a69'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ + mkdir -p /tmp/firebird_install; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + \ + # Extract, install, clean + cd /tmp/firebird_install; \ + tar --extract --file=firebird-bundle.tar.gz --gunzip --verbose --strip-components=1; \ + ./install.sh -silent; \ + rm -rf /tmp/firebird_install; \ + # Remove unnecessary files + rm -rf /opt/firebird/doc \ + /opt/firebird/examples \ + /opt/firebird/help \ + /opt/firebird/include; \ + # Remove 'employee' sample database from 'databases.conf' + sed -i '/^employee/d' /opt/firebird/databases.conf; \ + \ + # Clean up temporary packages (curl, ca-certificates) and apt lists + apt-get purge -y --auto-remove curl ca-certificates; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true + +# System path +ENV PATH=/opt/firebird/bin:$PATH + +# Data directory +ENV FIREBIRD_DATA=/var/lib/firebird/data +RUN set -eux; \ + mkdir -p "$FIREBIRD_DATA"; \ + chown -R firebird:firebird "$FIREBIRD_DATA"; \ + chmod 755 "$FIREBIRD_DATA" +VOLUME $FIREBIRD_DATA + +# Entrypoint +COPY entrypoint.sh /usr/local/bin/ +RUN set -eux; \ + chmod +x /usr/local/bin/entrypoint.sh +ENTRYPOINT ["tini", "--", "entrypoint.sh"] + +STOPSIGNAL SIGTERM +EXPOSE 3050/tcp + +# Fix terminfo location +ENV TERMINFO=/lib/terminfo/ + +CMD ["firebird"] + diff --git a/generated/5.0.2/trixie/entrypoint.sh b/generated/5.0.2/trixie/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/5.0.2/trixie/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/generated/5.0.3/bookworm/Dockerfile b/generated/5.0.3/bookworm/Dockerfile index 428523e..805944f 100644 --- a/generated/5.0.3/bookworm/Dockerfile +++ b/generated/5.0.3/bookworm/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bookworm-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-arm64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+e375341466e625bf17e4416723c1465a646d44903011ac4b89f84afe1df3633e} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-x64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-ef281c53f85756288151a86831375c9ae668caaeccd1b18103d523ba8f444779} - ENV FIREBIRD_VERSION=5.0.3 ENV FIREBIRD_MAJOR=5 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=5 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu72 \ @@ -41,15 +31,28 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='ef281c53f85756288151a86831375c9ae668caaeccd1b18103d523ba8f444779'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='e375341466e625bf17e4416723c1465a646d44903011ac4b89f84afe1df3633e'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +73,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +85,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/5.0.3/bookworm/entrypoint.sh b/generated/5.0.3/bookworm/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/5.0.3/bookworm/entrypoint.sh +++ b/generated/5.0.3/bookworm/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/5.0.3/bullseye/Dockerfile b/generated/5.0.3/bullseye/Dockerfile index bc2b8e8..0215bc9 100644 --- a/generated/5.0.3/bullseye/Dockerfile +++ b/generated/5.0.3/bullseye/Dockerfile @@ -10,16 +10,6 @@ FROM debian:bullseye-slim ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-arm64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+e375341466e625bf17e4416723c1465a646d44903011ac4b89f84afe1df3633e} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-x64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-ef281c53f85756288151a86831375c9ae668caaeccd1b18103d523ba8f444779} - ENV FIREBIRD_VERSION=5.0.3 ENV FIREBIRD_MAJOR=5 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=5 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu67 \ @@ -41,15 +31,28 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='ef281c53f85756288151a86831375c9ae668caaeccd1b18103d523ba8f444779'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='e375341466e625bf17e4416723c1465a646d44903011ac4b89f84afe1df3633e'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +73,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +85,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/5.0.3/bullseye/entrypoint.sh b/generated/5.0.3/bullseye/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/5.0.3/bullseye/entrypoint.sh +++ b/generated/5.0.3/bullseye/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/5.0.3/jammy/Dockerfile b/generated/5.0.3/jammy/Dockerfile index 93bba77..0f79230 100644 --- a/generated/5.0.3/jammy/Dockerfile +++ b/generated/5.0.3/jammy/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:jammy ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-arm64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+e375341466e625bf17e4416723c1465a646d44903011ac4b89f84afe1df3633e} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-x64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-ef281c53f85756288151a86831375c9ae668caaeccd1b18103d523ba8f444779} - ENV FIREBIRD_VERSION=5.0.3 ENV FIREBIRD_MAJOR=5 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=5 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu70 \ @@ -41,16 +31,29 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ tzdata \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='ef281c53f85756288151a86831375c9ae668caaeccd1b18103d523ba8f444779'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='e375341466e625bf17e4416723c1465a646d44903011ac4b89f84afe1df3633e'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -71,7 +74,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -81,15 +86,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/5.0.3/jammy/entrypoint.sh b/generated/5.0.3/jammy/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/5.0.3/jammy/entrypoint.sh +++ b/generated/5.0.3/jammy/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/5.0.3/noble/Dockerfile b/generated/5.0.3/noble/Dockerfile index 4de0462..103d518 100644 --- a/generated/5.0.3/noble/Dockerfile +++ b/generated/5.0.3/noble/Dockerfile @@ -10,16 +10,6 @@ FROM ubuntu:noble ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 -ARG ARCH_ARM64 - -# ARM64 arch -ENV FIREBIRD_RELEASE_URL=${ARCH_ARM64:+https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-arm64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${ARCH_ARM64:+e375341466e625bf17e4416723c1465a646d44903011ac4b89f84afe1df3633e} - -# AMD64 arch -ENV FIREBIRD_RELEASE_URL=${FIREBIRD_RELEASE_URL:-https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-x64.tar.gz} -ENV FIREBIRD_RELEASE_SHA256=${FIREBIRD_RELEASE_SHA256:-ef281c53f85756288151a86831375c9ae668caaeccd1b18103d523ba8f444779} - ENV FIREBIRD_VERSION=5.0.3 ENV FIREBIRD_MAJOR=5 @@ -32,7 +22,7 @@ ENV FIREBIRD_MAJOR=5 # FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 RUN set -eux; \ apt-get update; \ - # Install prerequisites + curl, ca-certificates for download + # Install prerequisites + tini + curl/ca-certificates for download apt-get install -y --no-install-recommends \ libatomic1 \ libicu74 \ @@ -41,15 +31,28 @@ RUN set -eux; \ libtommath1 \ netbase \ procps \ + tini \ ca-certificates \ curl; \ \ # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='ef281c53f85756288151a86831375c9ae668caaeccd1b18103d523ba8f444779'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='e375341466e625bf17e4416723c1465a646d44903011ac4b89f84afe1df3633e'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ mkdir -p /tmp/firebird_install; \ - echo "Downloading Firebird from $FIREBIRD_RELEASE_URL"; \ - curl -fSL "$FIREBIRD_RELEASE_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ - echo "Verifying checksum: $FIREBIRD_RELEASE_SHA256 for downloaded file"; \ - echo "$FIREBIRD_RELEASE_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ \ # Extract, install, clean cd /tmp/firebird_install; \ @@ -70,7 +73,9 @@ RUN set -eux; \ rm -rf /var/lib/apt/lists/* # Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 -RUN [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 || true +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true # System path ENV PATH=/opt/firebird/bin:$PATH @@ -80,15 +85,16 @@ ENV FIREBIRD_DATA=/var/lib/firebird/data RUN set -eux; \ mkdir -p "$FIREBIRD_DATA"; \ chown -R firebird:firebird "$FIREBIRD_DATA"; \ - chmod 644 "$FIREBIRD_DATA" + chmod 755 "$FIREBIRD_DATA" VOLUME $FIREBIRD_DATA # Entrypoint COPY entrypoint.sh /usr/local/bin/ RUN set -eux; \ chmod +x /usr/local/bin/entrypoint.sh -ENTRYPOINT ["entrypoint.sh"] +ENTRYPOINT ["tini", "--", "entrypoint.sh"] +STOPSIGNAL SIGTERM EXPOSE 3050/tcp # Fix terminfo location diff --git a/generated/5.0.3/noble/entrypoint.sh b/generated/5.0.3/noble/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/generated/5.0.3/noble/entrypoint.sh +++ b/generated/5.0.3/noble/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/generated/5.0.3/trixie/Dockerfile b/generated/5.0.3/trixie/Dockerfile new file mode 100644 index 0000000..4c2d2f7 --- /dev/null +++ b/generated/5.0.3/trixie/Dockerfile @@ -0,0 +1,104 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + +# Best practices for Dockerfile instructions +# https://docs.docker.com/develop/develop-images/instructions/ + +FROM debian:trixie-slim + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +ENV FIREBIRD_VERSION=5.0.3 +ENV FIREBIRD_MAJOR=5 + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -x Print commands and their arguments as they are executed. + +# Prerequisites +# FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 +RUN set -eux; \ + apt-get update; \ + # Install prerequisites + tini + curl/ca-certificates for download + apt-get install -y --no-install-recommends \ + libatomic1 \ + libicu76 \ + $([ $FIREBIRD_MAJOR -eq 3 ] && echo 'libncurses5' || echo 'libncurses6') \ + libtomcrypt1 \ + libtommath1 \ + netbase \ + procps \ + tini \ + ca-certificates \ + curl; \ + \ + # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='ef281c53f85756288151a86831375c9ae668caaeccd1b18103d523ba8f444779'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.3/Firebird-5.0.3.1683-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='e375341466e625bf17e4416723c1465a646d44903011ac4b89f84afe1df3633e'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ + mkdir -p /tmp/firebird_install; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + \ + # Extract, install, clean + cd /tmp/firebird_install; \ + tar --extract --file=firebird-bundle.tar.gz --gunzip --verbose --strip-components=1; \ + ./install.sh -silent; \ + rm -rf /tmp/firebird_install; \ + # Remove unnecessary files + rm -rf /opt/firebird/doc \ + /opt/firebird/examples \ + /opt/firebird/help \ + /opt/firebird/include; \ + # Remove 'employee' sample database from 'databases.conf' + sed -i '/^employee/d' /opt/firebird/databases.conf; \ + \ + # Clean up temporary packages (curl, ca-certificates) and apt lists + apt-get purge -y --auto-remove curl ca-certificates; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true + +# System path +ENV PATH=/opt/firebird/bin:$PATH + +# Data directory +ENV FIREBIRD_DATA=/var/lib/firebird/data +RUN set -eux; \ + mkdir -p "$FIREBIRD_DATA"; \ + chown -R firebird:firebird "$FIREBIRD_DATA"; \ + chmod 755 "$FIREBIRD_DATA" +VOLUME $FIREBIRD_DATA + +# Entrypoint +COPY entrypoint.sh /usr/local/bin/ +RUN set -eux; \ + chmod +x /usr/local/bin/entrypoint.sh +ENTRYPOINT ["tini", "--", "entrypoint.sh"] + +STOPSIGNAL SIGTERM +EXPOSE 3050/tcp + +# Fix terminfo location +ENV TERMINFO=/lib/terminfo/ + +CMD ["firebird"] + diff --git a/generated/5.0.3/trixie/entrypoint.sh b/generated/5.0.3/trixie/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/5.0.3/trixie/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/generated/5.0.4/bookworm/Dockerfile b/generated/5.0.4/bookworm/Dockerfile new file mode 100644 index 0000000..5c15f24 --- /dev/null +++ b/generated/5.0.4/bookworm/Dockerfile @@ -0,0 +1,104 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + +# Best practices for Dockerfile instructions +# https://docs.docker.com/develop/develop-images/instructions/ + +FROM debian:bookworm-slim + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +ENV FIREBIRD_VERSION=5.0.4 +ENV FIREBIRD_MAJOR=5 + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -x Print commands and their arguments as they are executed. + +# Prerequisites +# FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 +RUN set -eux; \ + apt-get update; \ + # Install prerequisites + tini + curl/ca-certificates for download + apt-get install -y --no-install-recommends \ + libatomic1 \ + libicu72 \ + $([ $FIREBIRD_MAJOR -eq 3 ] && echo 'libncurses5' || echo 'libncurses6') \ + libtomcrypt1 \ + libtommath1 \ + netbase \ + procps \ + tini \ + ca-certificates \ + curl; \ + \ + # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.4/Firebird-5.0.4.1812-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='ab6a15a0258f38b022be496bb5e038c14e8628ce9acd0f9a06288a3baedd917b'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.4/Firebird-5.0.4.1812-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='1a3eb3d46b82e96c784800aeec37287d4c47acec4d8caed6c7897beb4ff6cee0'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ + mkdir -p /tmp/firebird_install; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + \ + # Extract, install, clean + cd /tmp/firebird_install; \ + tar --extract --file=firebird-bundle.tar.gz --gunzip --verbose --strip-components=1; \ + ./install.sh -silent; \ + rm -rf /tmp/firebird_install; \ + # Remove unnecessary files + rm -rf /opt/firebird/doc \ + /opt/firebird/examples \ + /opt/firebird/help \ + /opt/firebird/include; \ + # Remove 'employee' sample database from 'databases.conf' + sed -i '/^employee/d' /opt/firebird/databases.conf; \ + \ + # Clean up temporary packages (curl, ca-certificates) and apt lists + apt-get purge -y --auto-remove curl ca-certificates; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true + +# System path +ENV PATH=/opt/firebird/bin:$PATH + +# Data directory +ENV FIREBIRD_DATA=/var/lib/firebird/data +RUN set -eux; \ + mkdir -p "$FIREBIRD_DATA"; \ + chown -R firebird:firebird "$FIREBIRD_DATA"; \ + chmod 755 "$FIREBIRD_DATA" +VOLUME $FIREBIRD_DATA + +# Entrypoint +COPY entrypoint.sh /usr/local/bin/ +RUN set -eux; \ + chmod +x /usr/local/bin/entrypoint.sh +ENTRYPOINT ["tini", "--", "entrypoint.sh"] + +STOPSIGNAL SIGTERM +EXPOSE 3050/tcp + +# Fix terminfo location +ENV TERMINFO=/lib/terminfo/ + +CMD ["firebird"] + diff --git a/generated/5.0.4/bookworm/entrypoint.sh b/generated/5.0.4/bookworm/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/5.0.4/bookworm/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/generated/5.0.4/bullseye/Dockerfile b/generated/5.0.4/bullseye/Dockerfile new file mode 100644 index 0000000..18391b2 --- /dev/null +++ b/generated/5.0.4/bullseye/Dockerfile @@ -0,0 +1,104 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + +# Best practices for Dockerfile instructions +# https://docs.docker.com/develop/develop-images/instructions/ + +FROM debian:bullseye-slim + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +ENV FIREBIRD_VERSION=5.0.4 +ENV FIREBIRD_MAJOR=5 + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -x Print commands and their arguments as they are executed. + +# Prerequisites +# FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 +RUN set -eux; \ + apt-get update; \ + # Install prerequisites + tini + curl/ca-certificates for download + apt-get install -y --no-install-recommends \ + libatomic1 \ + libicu67 \ + $([ $FIREBIRD_MAJOR -eq 3 ] && echo 'libncurses5' || echo 'libncurses6') \ + libtomcrypt1 \ + libtommath1 \ + netbase \ + procps \ + tini \ + ca-certificates \ + curl; \ + \ + # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.4/Firebird-5.0.4.1812-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='ab6a15a0258f38b022be496bb5e038c14e8628ce9acd0f9a06288a3baedd917b'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.4/Firebird-5.0.4.1812-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='1a3eb3d46b82e96c784800aeec37287d4c47acec4d8caed6c7897beb4ff6cee0'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ + mkdir -p /tmp/firebird_install; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + \ + # Extract, install, clean + cd /tmp/firebird_install; \ + tar --extract --file=firebird-bundle.tar.gz --gunzip --verbose --strip-components=1; \ + ./install.sh -silent; \ + rm -rf /tmp/firebird_install; \ + # Remove unnecessary files + rm -rf /opt/firebird/doc \ + /opt/firebird/examples \ + /opt/firebird/help \ + /opt/firebird/include; \ + # Remove 'employee' sample database from 'databases.conf' + sed -i '/^employee/d' /opt/firebird/databases.conf; \ + \ + # Clean up temporary packages (curl, ca-certificates) and apt lists + apt-get purge -y --auto-remove curl ca-certificates; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true + +# System path +ENV PATH=/opt/firebird/bin:$PATH + +# Data directory +ENV FIREBIRD_DATA=/var/lib/firebird/data +RUN set -eux; \ + mkdir -p "$FIREBIRD_DATA"; \ + chown -R firebird:firebird "$FIREBIRD_DATA"; \ + chmod 755 "$FIREBIRD_DATA" +VOLUME $FIREBIRD_DATA + +# Entrypoint +COPY entrypoint.sh /usr/local/bin/ +RUN set -eux; \ + chmod +x /usr/local/bin/entrypoint.sh +ENTRYPOINT ["tini", "--", "entrypoint.sh"] + +STOPSIGNAL SIGTERM +EXPOSE 3050/tcp + +# Fix terminfo location +ENV TERMINFO=/lib/terminfo/ + +CMD ["firebird"] + diff --git a/generated/5.0.4/bullseye/entrypoint.sh b/generated/5.0.4/bullseye/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/5.0.4/bullseye/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/generated/5.0.4/jammy/Dockerfile b/generated/5.0.4/jammy/Dockerfile new file mode 100644 index 0000000..708f65e --- /dev/null +++ b/generated/5.0.4/jammy/Dockerfile @@ -0,0 +1,105 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + +# Best practices for Dockerfile instructions +# https://docs.docker.com/develop/develop-images/instructions/ + +FROM ubuntu:jammy + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +ENV FIREBIRD_VERSION=5.0.4 +ENV FIREBIRD_MAJOR=5 + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -x Print commands and their arguments as they are executed. + +# Prerequisites +# FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 +RUN set -eux; \ + apt-get update; \ + # Install prerequisites + tini + curl/ca-certificates for download + apt-get install -y --no-install-recommends \ + libatomic1 \ + libicu70 \ + $([ $FIREBIRD_MAJOR -eq 3 ] && echo 'libncurses5' || echo 'libncurses6') \ + libtomcrypt1 \ + libtommath1 \ + netbase \ + procps \ + tini \ + tzdata \ + ca-certificates \ + curl; \ + \ + # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.4/Firebird-5.0.4.1812-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='ab6a15a0258f38b022be496bb5e038c14e8628ce9acd0f9a06288a3baedd917b'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.4/Firebird-5.0.4.1812-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='1a3eb3d46b82e96c784800aeec37287d4c47acec4d8caed6c7897beb4ff6cee0'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ + mkdir -p /tmp/firebird_install; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + \ + # Extract, install, clean + cd /tmp/firebird_install; \ + tar --extract --file=firebird-bundle.tar.gz --gunzip --verbose --strip-components=1; \ + ./install.sh -silent; \ + rm -rf /tmp/firebird_install; \ + # Remove unnecessary files + rm -rf /opt/firebird/doc \ + /opt/firebird/examples \ + /opt/firebird/help \ + /opt/firebird/include; \ + # Remove 'employee' sample database from 'databases.conf' + sed -i '/^employee/d' /opt/firebird/databases.conf; \ + \ + # Clean up temporary packages (curl, ca-certificates) and apt lists + apt-get purge -y --auto-remove curl ca-certificates; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true + +# System path +ENV PATH=/opt/firebird/bin:$PATH + +# Data directory +ENV FIREBIRD_DATA=/var/lib/firebird/data +RUN set -eux; \ + mkdir -p "$FIREBIRD_DATA"; \ + chown -R firebird:firebird "$FIREBIRD_DATA"; \ + chmod 755 "$FIREBIRD_DATA" +VOLUME $FIREBIRD_DATA + +# Entrypoint +COPY entrypoint.sh /usr/local/bin/ +RUN set -eux; \ + chmod +x /usr/local/bin/entrypoint.sh +ENTRYPOINT ["tini", "--", "entrypoint.sh"] + +STOPSIGNAL SIGTERM +EXPOSE 3050/tcp + +# Fix terminfo location +ENV TERMINFO=/lib/terminfo/ + +CMD ["firebird"] + diff --git a/generated/5.0.4/jammy/entrypoint.sh b/generated/5.0.4/jammy/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/5.0.4/jammy/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/generated/5.0.4/noble/Dockerfile b/generated/5.0.4/noble/Dockerfile new file mode 100644 index 0000000..ab92074 --- /dev/null +++ b/generated/5.0.4/noble/Dockerfile @@ -0,0 +1,104 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + +# Best practices for Dockerfile instructions +# https://docs.docker.com/develop/develop-images/instructions/ + +FROM ubuntu:noble + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +ENV FIREBIRD_VERSION=5.0.4 +ENV FIREBIRD_MAJOR=5 + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -x Print commands and their arguments as they are executed. + +# Prerequisites +# FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 +RUN set -eux; \ + apt-get update; \ + # Install prerequisites + tini + curl/ca-certificates for download + apt-get install -y --no-install-recommends \ + libatomic1 \ + libicu74 \ + $([ $FIREBIRD_MAJOR -eq 3 ] && echo 'libncurses5' || echo 'libncurses6') \ + libtomcrypt1 \ + libtommath1 \ + netbase \ + procps \ + tini \ + ca-certificates \ + curl; \ + \ + # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.4/Firebird-5.0.4.1812-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='ab6a15a0258f38b022be496bb5e038c14e8628ce9acd0f9a06288a3baedd917b'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.4/Firebird-5.0.4.1812-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='1a3eb3d46b82e96c784800aeec37287d4c47acec4d8caed6c7897beb4ff6cee0'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ + mkdir -p /tmp/firebird_install; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + \ + # Extract, install, clean + cd /tmp/firebird_install; \ + tar --extract --file=firebird-bundle.tar.gz --gunzip --verbose --strip-components=1; \ + ./install.sh -silent; \ + rm -rf /tmp/firebird_install; \ + # Remove unnecessary files + rm -rf /opt/firebird/doc \ + /opt/firebird/examples \ + /opt/firebird/help \ + /opt/firebird/include; \ + # Remove 'employee' sample database from 'databases.conf' + sed -i '/^employee/d' /opt/firebird/databases.conf; \ + \ + # Clean up temporary packages (curl, ca-certificates) and apt lists + apt-get purge -y --auto-remove curl ca-certificates; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true + +# System path +ENV PATH=/opt/firebird/bin:$PATH + +# Data directory +ENV FIREBIRD_DATA=/var/lib/firebird/data +RUN set -eux; \ + mkdir -p "$FIREBIRD_DATA"; \ + chown -R firebird:firebird "$FIREBIRD_DATA"; \ + chmod 755 "$FIREBIRD_DATA" +VOLUME $FIREBIRD_DATA + +# Entrypoint +COPY entrypoint.sh /usr/local/bin/ +RUN set -eux; \ + chmod +x /usr/local/bin/entrypoint.sh +ENTRYPOINT ["tini", "--", "entrypoint.sh"] + +STOPSIGNAL SIGTERM +EXPOSE 3050/tcp + +# Fix terminfo location +ENV TERMINFO=/lib/terminfo/ + +CMD ["firebird"] + diff --git a/generated/5.0.4/noble/entrypoint.sh b/generated/5.0.4/noble/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/5.0.4/noble/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/generated/5.0.4/trixie/Dockerfile b/generated/5.0.4/trixie/Dockerfile new file mode 100644 index 0000000..ee0d80e --- /dev/null +++ b/generated/5.0.4/trixie/Dockerfile @@ -0,0 +1,104 @@ +# +# This file was auto-generated. Do not edit. See /src. +# + +# Best practices for Dockerfile instructions +# https://docs.docker.com/develop/develop-images/instructions/ + +FROM debian:trixie-slim + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +ENV FIREBIRD_VERSION=5.0.4 +ENV FIREBIRD_MAJOR=5 + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -x Print commands and their arguments as they are executed. + +# Prerequisites +# FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 +RUN set -eux; \ + apt-get update; \ + # Install prerequisites + tini + curl/ca-certificates for download + apt-get install -y --no-install-recommends \ + libatomic1 \ + libicu76 \ + $([ $FIREBIRD_MAJOR -eq 3 ] && echo 'libncurses5' || echo 'libncurses6') \ + libtomcrypt1 \ + libtommath1 \ + netbase \ + procps \ + tini \ + ca-certificates \ + curl; \ + \ + # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.4/Firebird-5.0.4.1812-0-linux-x64.tar.gz'; \ + FIREBIRD_SHA256='ab6a15a0258f38b022be496bb5e038c14e8628ce9acd0f9a06288a3baedd917b'; \ + ;; \ + arm64) \ + FIREBIRD_URL='https://github.com/FirebirdSQL/firebird/releases/download/v5.0.4/Firebird-5.0.4.1812-0-linux-arm64.tar.gz'; \ + FIREBIRD_SHA256='1a3eb3d46b82e96c784800aeec37287d4c47acec4d8caed6c7897beb4ff6cee0'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ + mkdir -p /tmp/firebird_install; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + \ + # Extract, install, clean + cd /tmp/firebird_install; \ + tar --extract --file=firebird-bundle.tar.gz --gunzip --verbose --strip-components=1; \ + ./install.sh -silent; \ + rm -rf /tmp/firebird_install; \ + # Remove unnecessary files + rm -rf /opt/firebird/doc \ + /opt/firebird/examples \ + /opt/firebird/help \ + /opt/firebird/include; \ + # Remove 'employee' sample database from 'databases.conf' + sed -i '/^employee/d' /opt/firebird/databases.conf; \ + \ + # Clean up temporary packages (curl, ca-certificates) and apt lists + apt-get purge -y --auto-remove curl ca-certificates; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true + +# System path +ENV PATH=/opt/firebird/bin:$PATH + +# Data directory +ENV FIREBIRD_DATA=/var/lib/firebird/data +RUN set -eux; \ + mkdir -p "$FIREBIRD_DATA"; \ + chown -R firebird:firebird "$FIREBIRD_DATA"; \ + chmod 755 "$FIREBIRD_DATA" +VOLUME $FIREBIRD_DATA + +# Entrypoint +COPY entrypoint.sh /usr/local/bin/ +RUN set -eux; \ + chmod +x /usr/local/bin/entrypoint.sh +ENTRYPOINT ["tini", "--", "entrypoint.sh"] + +STOPSIGNAL SIGTERM +EXPOSE 3050/tcp + +# Fix terminfo location +ENV TERMINFO=/lib/terminfo/ + +CMD ["firebird"] + diff --git a/generated/5.0.4/trixie/entrypoint.sh b/generated/5.0.4/trixie/entrypoint.sh new file mode 100644 index 0000000..b4a5ea2 --- /dev/null +++ b/generated/5.0.4/trixie/entrypoint.sh @@ -0,0 +1,320 @@ +#!/usr/bin/env bash + +# +# Docker entrypoint for firebird-docker images. +# +# Based on works of Jacob Alberty and The PostgreSQL Development Group. +# + +# +# About the [Tabs ahead] marker: +# Some sections of this file use tabs for better readability. +# When using bash here strings the - option suppresses leading tabs but not spaces. +# + + + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -E If set, the ERR trap is inherited by shell functions. +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -o Set the variable corresponding to option-name: +# pipefail the return value of a pipeline is the status of +# the last command to exit with a non-zero status, +# or zero if no command exited with a non-zero status +set -Eeuo pipefail + +# usage: read_from_file_or_env VAR [DEFAULT] +# ie: read_from_file_or_env 'DB_PASSWORD' 'example' +# If $(VAR)_FILE var is set, sets VAR value from file contents. Otherwise, uses DEFAULT value if VAR is not set. +read_from_file_or_env() { + local var="$1" + local fileVar="${var}_FILE" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: Both $var and $fileVar are set. + + Variables $var and $fileVar are mutually exclusive. Remove either one. + ----- + EOL + exit 1 + fi + + local def="${2:-}" + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + +# usage: firebird_config_set KEY VALUE +# ie: firebird_config_set 'WireCrypt' 'Enabled' +# Set configuration key KEY to VALUE in 'firebird.conf' +firebird_config_set() { + # Uncomment line + sed -i "s/^#${1}/${1}/g" /opt/firebird/firebird.conf + + # Set KEY to VALUE + sed -i "s~^\(${1}\s*=\s*\).*$~\1${2}~" /opt/firebird/firebird.conf +} + +# Indent multi-line string -- https://stackoverflow.com/a/29779745 +indent() { + sed 's/^/ /'; +} + +# Set Firebird configuration parameters from environment variables. +set_config() { + read_from_file_or_env 'FIREBIRD_USE_LEGACY_AUTH' + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + echo 'Using Legacy_Auth.' + + # Firebird 4+: Uses 'Srp256' before 'Srp'. + local srp256='' + [ "$FIREBIRD_MAJOR" -ge "4" ] && srp256='Srp256, ' + + # Adds Legacy_Auth and Legacy_UserManager as first options. + firebird_config_set AuthServer "Legacy_Auth, ${srp256}Srp" + firebird_config_set AuthClient "Legacy_Auth, ${srp256}Srp" + firebird_config_set UserManager 'Legacy_UserManager, Srp' + + # Default setting is 'Required'. Reduces it to 'Enabled'. + firebird_config_set WireCrypt 'Enabled' + fi + + # FIREBIRD_CONF_* variables: set key in 'firebird.conf' + local v + for v in $(compgen -A variable | grep 'FIREBIRD_CONF_'); do + local key=${v/FIREBIRD_CONF_/} + firebird_config_set "$key" "${!v}" + done + + # Output changed settings + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true + if [ -n "$changed_settings" ]; then + echo "Using settings:" + echo "$changed_settings" | indent + fi +} + +# Changes SYSDBA password if FIREBIRD_ROOT_PASSWORD variable is set. +set_sysdba() { + read_from_file_or_env 'FIREBIRD_ROOT_PASSWORD' + if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then + echo 'Changing SYSDBA password.' + + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Srp; + EXIT; + EOL + + if [ "$FIREBIRD_USE_LEGACY_AUTH" == 'true' ]; then + # [Tabs ahead] + /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL + CREATE OR ALTER USER SYSDBA + PASSWORD '${escaped_password}' + USING PLUGIN Legacy_UserManager; + EXIT; + EOL + fi + + rm -rf /opt/firebird/SYSDBA.password + fi +} + +# Requires FIREBIRD_PASSWORD if FIREBIRD_USER is set. +requires_user_password() { + if [ -n "$FIREBIRD_USER" ] && [ -z "$FIREBIRD_PASSWORD" ]; then + # [Tabs ahead] + cat >&2 <<-EOL + ----- + ERROR: FIREBIRD_PASSWORD variable is not set. + + When using FIREBIRD_USER you must also set FIREBIRD_PASSWORD variable. + ----- + EOL + exit 1 + fi +} + +# Create Firebird user. +create_user() { + read_from_file_or_env 'FIREBIRD_USER' + read_from_file_or_env 'FIREBIRD_PASSWORD' + + if [ -n "$FIREBIRD_USER" ]; then + requires_user_password + echo "Creating user '$FIREBIRD_USER'..." + + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + + # [Tabs ahead] + /opt/firebird/bin/isql -b security.db <<-EOL + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' + GRANT ADMIN ROLE; + EXIT; + EOL + fi +} + +# Run isql +process_sql() { + local isql_command=( /opt/firebird/bin/isql -b ) + + if [ -n "$FIREBIRD_USER" ]; then + isql_command+=( -u "$FIREBIRD_USER" -p "$FIREBIRD_PASSWORD" ) + fi + + if [ -n "$FIREBIRD_DATABASE" ]; then + isql_command+=( "$FIREBIRD_DATABASE" ) + fi + + "${isql_command[@]}" "$@" +} + +# Execute database initialization scripts +init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + + local f + for f; do + case "$f" in + *.sh) + if [ -x "$f" ]; then + # Script is executable. Run it. + printf ' running %s\n' "$f" + "$f" + else + # Script is not executable. Source it. + printf ' sourcing %s\n' "$f" + . "$f" + fi + ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; + *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; + *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; + *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; + *) printf ' ignoring %s\n' "$f" ;; + esac + printf '\n' + done +} + +# Create user database. +create_db() { + read_from_file_or_env 'FIREBIRD_DATABASE' + if [ -n "$FIREBIRD_DATABASE" ]; then + # Expand FIREBIRD_DATABASE to full path + cd "$FIREBIRD_DATA" + export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") + + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env + + # Create database only if not exists. + if [ ! -f "$FIREBIRD_DATABASE" ]; then + echo "Creating database '$FIREBIRD_DATABASE'..." + + read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' + read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + + local user_and_password='' + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi + + local page_size='' + [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" + + local default_charset='' + [ -n "$FIREBIRD_DATABASE_DEFAULT_CHARSET" ] && default_charset="DEFAULT CHARACTER SET $FIREBIRD_DATABASE_DEFAULT_CHARSET" + + # [Tabs ahead] + /opt/firebird/bin/isql -b -q <<-EOL + CREATE DATABASE '${escaped_database}' + $user_and_password + $page_size + $default_charset; + EXIT; + EOL + + init_db /docker-entrypoint-initdb.d/* + fi + fi +} + +sigint_handler() { + echo "Stopping Firebird... [SIGINT received]" +} + +sigterm_handler() { + echo "Stopping Firebird... [SIGTERM received]" +} + +run_daemon_and_wait() { + # Traps SIGINT (handles Ctrl-C in interactive mode) + trap sigint_handler SIGINT + + # Traps SIGTERM (polite shutdown) + trap sigterm_handler SIGTERM + + # Firebird version + echo -n 'Starting ' + /opt/firebird/bin/firebird -z + + # Run fbguard and wait + /opt/firebird/bin/fbguard & + wait $! +} + + + +# +# main() +# +if [ "$1" = 'firebird' ]; then + set_config + set_sysdba + + create_user + create_db + + run_daemon_and_wait +else + exec "$@" +fi diff --git a/src/Dockerfile.template b/src/Dockerfile.template new file mode 100644 index 0000000..d188931 --- /dev/null +++ b/src/Dockerfile.template @@ -0,0 +1,99 @@ +# Best practices for Dockerfile instructions +# https://docs.docker.com/develop/develop-images/instructions/ + +FROM {{BASE_IMAGE}} + +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +ENV FIREBIRD_VERSION={{FIREBIRD_VERSION}} +ENV FIREBIRD_MAJOR={{FIREBIRD_MAJOR}} + +# https://linuxcommand.org/lc3_man_pages/seth.html +# -e Exit immediately if a command exits with a non-zero status. +# -u Treat unset variables as an error when substituting +# -x Print commands and their arguments as they are executed. + +# Prerequisites +# FB 3.0 uses libncurses5: https://github.com/FirebirdSQL/firebird/issues/6418#issuecomment-826245785 +RUN set -eux; \ + apt-get update; \ + # Install prerequisites + tini + curl/ca-certificates for download + apt-get install -y --no-install-recommends \ + libatomic1 \ + {{ICU_PACKAGE}} \ + $([ $FIREBIRD_MAJOR -eq 3 ] && echo 'libncurses5' || echo 'libncurses6') \ + libtomcrypt1 \ + libtommath1 \ + netbase \ + procps \ + tini \ +{{EXTRA_PACKAGES}} ca-certificates \ + curl; \ + \ + # Download + ARCH=$(dpkg --print-architecture); \ + case "$ARCH" in \ + amd64) \ + FIREBIRD_URL='{{URL_AMD64}}'; \ + FIREBIRD_SHA256='{{SHA256_AMD64}}'; \ + ;; \ + arm64) \ + FIREBIRD_URL='{{URL_ARM64}}'; \ + FIREBIRD_SHA256='{{SHA256_ARM64}}'; \ + ;; \ + *) echo "Unsupported architecture: $ARCH" >&2; exit 1 ;; \ + esac; \ + mkdir -p /tmp/firebird_install; \ + echo "Downloading Firebird from $FIREBIRD_URL"; \ + curl -fSL "$FIREBIRD_URL" -o /tmp/firebird_install/firebird-bundle.tar.gz; \ + echo "Verifying checksum: $FIREBIRD_SHA256 for downloaded file"; \ + echo "$FIREBIRD_SHA256 /tmp/firebird_install/firebird-bundle.tar.gz" | sha256sum -c -; \ + \ + # Extract, install, clean + cd /tmp/firebird_install; \ + tar --extract --file=firebird-bundle.tar.gz --gunzip --verbose --strip-components=1; \ + ./install.sh -silent; \ + rm -rf /tmp/firebird_install; \ + # Remove unnecessary files + rm -rf /opt/firebird/doc \ + /opt/firebird/examples \ + /opt/firebird/help \ + /opt/firebird/include; \ + # Remove 'employee' sample database from 'databases.conf' + sed -i '/^employee/d' /opt/firebird/databases.conf; \ + \ + # Clean up temporary packages (curl, ca-certificates) and apt lists + apt-get purge -y --auto-remove curl ca-certificates; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* + +# Fix libtommath for FB 3.0 -- https://github.com/FirebirdSQL/firebird/issues/5716#issuecomment-826239174 +RUN set -eux; \ + ARCH=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2>/dev/null || echo "$(uname -m)-linux-gnu"); \ + [ $FIREBIRD_MAJOR -eq 3 ] && ln -sf /usr/lib/$ARCH/libtommath.so.1 /usr/lib/$ARCH/libtommath.so.0 || true + +# System path +ENV PATH=/opt/firebird/bin:$PATH + +# Data directory +ENV FIREBIRD_DATA=/var/lib/firebird/data +RUN set -eux; \ + mkdir -p "$FIREBIRD_DATA"; \ + chown -R firebird:firebird "$FIREBIRD_DATA"; \ + chmod 755 "$FIREBIRD_DATA" +VOLUME $FIREBIRD_DATA + +# Entrypoint +COPY entrypoint.sh /usr/local/bin/ +RUN set -eux; \ + chmod +x /usr/local/bin/entrypoint.sh +ENTRYPOINT ["tini", "--", "entrypoint.sh"] + +STOPSIGNAL SIGTERM +EXPOSE 3050/tcp + +# Fix terminfo location +ENV TERMINFO=/lib/terminfo/ + +CMD ["firebird"] diff --git a/src/README.md.template b/src/README.md.template index c5c13ed..3d2b193 100644 --- a/src/README.md.template +++ b/src/README.md.template @@ -14,13 +14,38 @@ Docker images for Firebird Database. # Supported tags -|`firebirdsql/firebird`|Dockerfile| +|`{{IMAGE_FULL_NAME}}`|Dockerfile| |:-|:-:| -<%$TSupportedTags%> +{{SupportedTags}} > _Firebird 3 does not have an image for Ubuntu 24.04 LTS (Noble Numbat) due to a dependency (`libncurses5`) missing from Ubuntu sources._ +## Snapshot (pre-release) images + +Pre-release builds from the Firebird development branches are available as snapshot images: + +| Tag | Source Branch | Description | +|-----|---------------|-------------| +| `6-snapshot` | `master` | Firebird 6.x development builds | +| `5-snapshot` | `v5.0-release` | Firebird 5.x next-patch builds | + +> **Warning:** Snapshot images are built from unreleased code and may be unstable. They are rebuilt daily and replaced on each build. Do not use in production. + +```bash +# Pull latest Firebird 6.x development snapshot +docker pull firebirdsql/firebird:6-snapshot + +# Pull latest Firebird 5.x patch snapshot +docker pull firebirdsql/firebird:5-snapshot +``` + + +## Architectures + +Images for Firebird 5.x and later are available for both `linux/amd64` and `linux/arm64`. Firebird 3.x and 4.x images are `linux/amd64` only. + + # How to use this image @@ -236,120 +261,3 @@ More information: - [Firebird’s gbak Backup and Restore Utility](https://firebirdsql.org/file/documentation/html/en/firebirddocs/gbak/firebird-gbak.html) from Norman Dunbar and Mark Rotteveel. - [Quick Guide for Gbak Backup-Restore](https://ib-aid.com/articles/firebird-gbak-backup-tips-and-tricks) from IBSurgeon. - - -# Development notes - -## Prerequisites - - - [Docker](https://docs.docker.com/engine/install/) - - [Powershell 7.5+](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-linux) - - [Invoke-Build](https://github.com/nightroman/Invoke-Build#install-as-module) - - - -## Building - -To generate the source files and build each image from [`assets.json`](assets.json) configuration file, run: - -```bash -Invoke-Build -``` - -You can then check all created images with: - -```bash -docker image ls firebirdsql/firebird -``` - -### Filtering builds - -> You can filter builds by **version** or **distribution**: - -```bash -# Build only Firebird 5.x images -Invoke-Build Build -VersionFilter "5" - -# Build only specific version -Invoke-Build Build -VersionFilter "5.0.2" - -# Build only bookworm distribution images -Invoke-Build Build -DistributionFilter "bookworm" - -# Combine filters -Invoke-Build Build -VersionFilter "4" -DistributionFilter "jammy" -``` - - - -## Testing - -To run the test suite for each image, use: - -```bash -Invoke-Build Test -``` - -### Filtering tests - -You can filter tests by **version**, **distribution**, or a specific **test name**: - -```bash -# Test only Firebird 4.x images -Invoke-Build Test -VersionFilter "4" - -# Test only bullseye distribution images -Invoke-Build Test -DistributionFilter "bullseye" - -# Run specific test -Invoke-Build Test -TestFilter "FIREBIRD_USER_can_create_user" - -# Combine filters -Invoke-Build Test -VersionFilter "5" -DistributionFilter "noble" -``` - - - -## Maintenance tasks - -The build script includes additional tasks dedicated to maintaining this project. - -```bash -# Update assets.json from GitHub releases -Invoke-Build Update-Assets - -# Update README.md from assets.json -Invoke-Build Update-Readme - -# Regenerate source files -Invoke-Build Prepare - -# Clean up generated files -Invoke-Build Clean -``` - - - -## Following a new Firebird release - -Once a new Firebird release is published, follow these steps to update all relevant files in this repository: - -```bash -# Update assets.json from GitHub releases -Invoke-Build Update-Assets - -# Update README.md from assets.json -Invoke-Build Update-Readme - -# Regenerate source files -Invoke-Build Prepare - -# Adds all untracked files -git add -u - -# Remove logs from staging area -git reset -- generated/logs/ - -# Commit -git commit -M "Adds Firebird ..." -``` diff --git a/src/entrypoint.sh b/src/entrypoint.sh index e9fa133..b4a5ea2 100644 --- a/src/entrypoint.sh +++ b/src/entrypoint.sh @@ -36,7 +36,7 @@ read_from_file_or_env() { ----- ERROR: Both $var and $fileVar are set. - Variables %s and %s are mutually exclusive. Remove either one. + Variables $var and $fileVar are mutually exclusive. Remove either one. ----- EOL exit 1 @@ -54,6 +54,13 @@ read_from_file_or_env() { unset "$fileVar" } +# usage: escape_sql_string STR +# ie: escape_sql_string "it's_me" +# Escapes single quotes for safe SQL interpolation. +escape_sql_string() { + printf '%s' "${1//\'/\'\'}" +} + # usage: firebird_config_set KEY VALUE # ie: firebird_config_set 'WireCrypt' 'Enabled' # Set configuration key KEY to VALUE in 'firebird.conf' @@ -97,7 +104,8 @@ set_config() { done # Output changed settings - local changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) + local changed_settings + changed_settings=$(grep -o '^[^#]*' /opt/firebird/firebird.conf) || true if [ -n "$changed_settings" ]; then echo "Using settings:" echo "$changed_settings" | indent @@ -110,10 +118,13 @@ set_sysdba() { if [ -n "$FIREBIRD_ROOT_PASSWORD" ]; then echo 'Changing SYSDBA password.' + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_ROOT_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Srp; EXIT; EOL @@ -122,7 +133,7 @@ set_sysdba() { # [Tabs ahead] /opt/firebird/bin/isql -b -user SYSDBA security.db <<-EOL CREATE OR ALTER USER SYSDBA - PASSWORD '$FIREBIRD_ROOT_PASSWORD' + PASSWORD '${escaped_password}' USING PLUGIN Legacy_UserManager; EXIT; EOL @@ -156,10 +167,15 @@ create_user() { requires_user_password echo "Creating user '$FIREBIRD_USER'..." + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + # [Tabs ahead] /opt/firebird/bin/isql -b security.db <<-EOL - CREATE OR ALTER USER $FIREBIRD_USER - PASSWORD '$FIREBIRD_PASSWORD' + CREATE OR ALTER USER ${escaped_user} + PASSWORD '${escaped_password}' GRANT ADMIN ROLE; EXIT; EOL @@ -178,11 +194,16 @@ process_sql() { isql_command+=( "$FIREBIRD_DATABASE" ) fi - ${isql_command[@]} "$@" + "${isql_command[@]}" "$@" } # Execute database initialization scripts init_db() { + # Guard against empty glob (no files match) + if ! compgen -G "$1" > /dev/null 2>&1; then + return + fi + local f for f; do case "$f" in @@ -197,7 +218,7 @@ init_db() { . "$f" fi ;; - *.sql) printf ' running %s\n' "$f"; cat "$f" | process_sql; printf '\n' ;; + *.sql) printf ' running %s\n' "$f"; process_sql < "$f"; printf '\n' ;; *.sql.gz) printf ' running %s\n' "$f"; gunzip -c "$f" | process_sql; printf '\n' ;; *.sql.xz) printf ' running %s\n' "$f"; xzcat "$f" | process_sql; printf '\n' ;; *.sql.zst) printf ' running %s\n' "$f"; zstd -dc "$f" | process_sql; printf '\n' ;; @@ -205,7 +226,6 @@ init_db() { esac printf '\n' done - } # Create user database. @@ -216,8 +236,8 @@ create_db() { cd "$FIREBIRD_DATA" export FIREBIRD_DATABASE=$(realpath --canonicalize-missing "$FIREBIRD_DATABASE") - # Store it for other sessions of this instance - echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" > ~/.bashrc + # Store it for other sessions of this instance (append, do not overwrite) + echo "export FIREBIRD_DATABASE='$FIREBIRD_DATABASE'" >> /opt/firebird/.firebird_env # Create database only if not exists. if [ ! -f "$FIREBIRD_DATABASE" ]; then @@ -226,8 +246,17 @@ create_db() { read_from_file_or_env 'FIREBIRD_DATABASE_PAGE_SIZE' read_from_file_or_env 'FIREBIRD_DATABASE_DEFAULT_CHARSET' + local escaped_database + escaped_database=$(escape_sql_string "$FIREBIRD_DATABASE") + local user_and_password='' - [ -n "$FIREBIRD_USER" ] && user_and_password=" USER '$FIREBIRD_USER' PASSWORD '$FIREBIRD_PASSWORD'" + if [ -n "$FIREBIRD_USER" ]; then + local escaped_user + escaped_user=$(escape_sql_string "$FIREBIRD_USER") + local escaped_password + escaped_password=$(escape_sql_string "$FIREBIRD_PASSWORD") + user_and_password=" USER '${escaped_user}' PASSWORD '${escaped_password}'" + fi local page_size='' [ -n "$FIREBIRD_DATABASE_PAGE_SIZE" ] && page_size="PAGE_SIZE $FIREBIRD_DATABASE_PAGE_SIZE" @@ -237,7 +266,7 @@ create_db() { # [Tabs ahead] /opt/firebird/bin/isql -b -q <<-EOL - CREATE DATABASE '$FIREBIRD_DATABASE' + CREATE DATABASE '${escaped_database}' $user_and_password $page_size $default_charset; diff --git a/src/functions.ps1 b/src/functions.ps1 new file mode 100644 index 0000000..a3a4035 --- /dev/null +++ b/src/functions.ps1 @@ -0,0 +1,107 @@ +# +# Shared functions for firebird-docker build system. +# Sourced by both firebird-docker.build.ps1 and tests. +# + +# Returns distro configuration from assets.json config section. +function Get-DistroConfig([string]$Distro) { + $config = $script:assetsData.config.distros.$Distro + if (-not $config) { + throw "Unknown distro: $Distro. Valid distros: $($script:assetsData.config.distros | Get-Member -MemberType NoteProperty | ForEach-Object Name)" + } + return $config +} + +# Returns all valid distros for a given major version (excludes blocked variants). +function Get-ValidDistros([int]$Major) { + $allDistros = @($script:assetsData.config.distros | Get-Member -MemberType NoteProperty | ForEach-Object { $_.Name }) + $blocked = $script:assetsData.config.blockedVariants."$Major" + if ($blocked) { + $allDistros = $allDistros | Where-Object { $_ -notin $blocked } + } + return $allDistros +} + +# Deterministic tag generation. See DECISIONS.md for rationale. +function Get-ImageTags { + param( + [Parameter(Mandatory)][string]$Version, + [Parameter(Mandatory)][string]$Distro, + [Parameter(Mandatory)][bool]$IsLatestOfMajor, + [Parameter(Mandatory)][bool]$IsLatestOverall, + [Parameter(Mandatory)][string]$DefaultDistro + ) + + $v = [version]$Version + $major = "$($v.Major)" + $tags = @() + + # Always: {version}-{distro} + $tags += "$Version-$Distro" + + # If latest of major: {major}-{distro} + if ($IsLatestOfMajor) { + $tags += "$major-$Distro" + } + + # If latest overall: {distro} + if ($IsLatestOverall) { + $tags += $Distro + } + + # Default distro gets additional bare tags + if ($Distro -eq $DefaultDistro) { + # Always: {version} + $tags += $Version + + # If latest of major: {major} + if ($IsLatestOfMajor) { + $tags += $major + } + + # If latest overall: latest + if ($IsLatestOverall) { + $tags += 'latest' + } + } + + return $tags +} + +# Expand a template file using {{VAR}} syntax (safe string replacement). +function Expand-TemplateFile([string]$Path, [hashtable]$Variables) { + $content = Get-Content $Path -Raw -Encoding UTF8 + foreach ($key in $Variables.Keys) { + $content = $content.Replace("{{$key}}", $Variables[$key]) + } + return $content +} + +# Write content to file with auto-generated header. +function Write-GeneratedFile([string]$Content, [string]$Destination) { + if (Test-Path $Destination) { + $outputFile = Get-Item $Destination + $outputFile | Set-ItemProperty -Name IsReadOnly -Value $false + } + + $fileExtension = [System.IO.Path]::GetExtension($Destination) + $header = if ($fileExtension -eq '.md') { + @' + +[//]: # (This file was auto-generated. Do not edit. See /src.) + +'@ + } else { + @' +# +# This file was auto-generated. Do not edit. See /src. +# + +'@ + } + $header | Set-Content $Destination -Encoding UTF8 + $Content | Add-Content $Destination -Encoding UTF8 + + $outputFile = Get-Item $Destination + $outputFile | Set-ItemProperty -Name IsReadOnly -Value $true +} diff --git a/src/image.build.ps1.template b/src/image.build.ps1.template deleted file mode 100644 index 7dafc94..0000000 --- a/src/image.build.ps1.template +++ /dev/null @@ -1,105 +0,0 @@ -param( - [switch]$NoCache, - [string]$TestFilter # Filter by test name, e.g. 'FIREBIRD_USER_can_create_user'. -- Used only in 'Test' task. -) - -# Synopsis: Build docker images. -task Build { - $script:BUILDER_HAS_ARCH_ARM64 = <%$THasArchARM64%> - $script:BUILDER_IMAGE_PREFIX = 'firebirdsql' - $script:BUILDER_IMAGE_NAME = 'firebird' - $script:BUILDER_IMAGE_VERSION = '<%$TImageVersion%>' - $script:BUILDER_IMAGE_TAGS = @(<%$TImageTags%>) - - $progressPlainParameter = if ($PSStyle.OutputRendering -eq 'PlainText') { '--progress=plain' } else { $null } - $noCacheParameter = if ($NoCache) { '--no-cache' } else { $null } - - $tagsArchAMD64 = $BUILDER_IMAGE_TAGS | ForEach-Object { '--tag', "$BUILDER_IMAGE_PREFIX/${BUILDER_IMAGE_NAME}-amd64:$_" } - $tagsArchARM64 = $BUILDER_IMAGE_TAGS | ForEach-Object { '--tag', "$BUILDER_IMAGE_PREFIX/${BUILDER_IMAGE_NAME}-arm64:$_" } - - $allParameters = @( - 'build'; - $progressPlainParameter - '--platform', 'linux/amd64'; - $tagsArchAMD64; - $noCacheParameter, - '--label', 'org.opencontainers.image.description=Firebird Database', - '--label', 'org.opencontainers.image.source=https://github.com/FirebirdSQL/firebird-docker', - '--label', 'org.opencontainers.image.version=<%$TImageVersion%>', - '.' - ) - Write-Output "`n`n----- [linux/amd64] -----" - Write-Output "Running: docker $allParameters" - exec { & docker $allParameters *>&1 } - - if ($BUILDER_HAS_ARCH_ARM64) { - $allParameters = @( - 'build'; - $progressPlainParameter - '--platform', 'linux/arm64'; - '--build-arg', 'ARCH_ARM64=1'; - $tagsArchARM64; - $noCacheParameter, - '--label', 'org.opencontainers.image.description=Firebird Database', - '--label', 'org.opencontainers.image.source=https://github.com/FirebirdSQL/firebird-docker', - '--label', 'org.opencontainers.image.version=<%$TImageVersion%>', - '.' - ) - Write-Output "`n`n----- [linux/arm64] -----" - Write-Output "Running: docker $allParameters" - exec { & docker $allParameters *>&1 } - } -} - -# Synopsis: Run tests. -task Test Build, { - Write-Build Magenta "----- [$BUILDER_IMAGE_VERSION] ---------------------" - $tag = $BUILDER_IMAGE_TAGS[0] - - if ($TestFilter) { - Write-Verbose "Running single test '$TestFilter'..." - } else { - Write-Verbose "Running all tests..." - $TestFilter = '*' - } - - $env:FULL_IMAGE_NAME = "$BUILDER_IMAGE_PREFIX/${BUILDER_IMAGE_NAME}-amd64:${tag}" - Write-Verbose " Image: $($env:FULL_IMAGE_NAME)" - Invoke-Build $TestFilter image.tests.ps1 - - if ($BUILDER_HAS_ARCH_ARM64) { - $env:FULL_IMAGE_NAME = "$BUILDER_IMAGE_PREFIX/${BUILDER_IMAGE_NAME}-arm64:${tag}" - Write-Verbose " Image: $($env:FULL_IMAGE_NAME)" - Invoke-Build $TestFilter image.tests.ps1 - } -} - -# Synopsis: Publish image. -task Publish Build, { - Write-Build Magenta "----- [$BUILDER_IMAGE_VERSION] ---------------------" - - $BUILDER_IMAGE_TAGS | ForEach-Object { - docker push "$BUILDER_IMAGE_PREFIX/${BUILDER_IMAGE_NAME}-amd64:$_" - - if ($BUILDER_HAS_ARCH_ARM64) { - docker push "$BUILDER_IMAGE_PREFIX/${BUILDER_IMAGE_NAME}-arm64:$_" - - docker manifest create --amend "$BUILDER_IMAGE_PREFIX/${BUILDER_IMAGE_NAME}:$_" ` - "$BUILDER_IMAGE_PREFIX/${BUILDER_IMAGE_NAME}-amd64:$_" ` - "$BUILDER_IMAGE_PREFIX/${BUILDER_IMAGE_NAME}-arm64:$_" - - docker manifest annotate "$BUILDER_IMAGE_PREFIX/${BUILDER_IMAGE_NAME}:$_" ` - "$BUILDER_IMAGE_PREFIX/${BUILDER_IMAGE_NAME}-amd64:$_" --os linux --arch amd64 - docker manifest annotate "$BUILDER_IMAGE_PREFIX/${BUILDER_IMAGE_NAME}:$_" ` - "$BUILDER_IMAGE_PREFIX/${BUILDER_IMAGE_NAME}-arm64:$_" --os linux --arch arm64 - - docker manifest push "$BUILDER_IMAGE_PREFIX/${BUILDER_IMAGE_NAME}:$_" - } - else { - docker image tag "$BUILDER_IMAGE_PREFIX/${BUILDER_IMAGE_NAME}-amd64:$_" ` - "$BUILDER_IMAGE_PREFIX/${BUILDER_IMAGE_NAME}:$_" - - docker push "$BUILDER_IMAGE_PREFIX/${BUILDER_IMAGE_NAME}:$_" - } - } -} diff --git a/src/image.tests.ps1 b/src/image.tests.ps1 index 465625c..fff7821 100644 --- a/src/image.tests.ps1 +++ b/src/image.tests.ps1 @@ -28,7 +28,6 @@ function Use-Container([string[]]$Parameters, [Parameter(Mandatory)][ScriptBlock $cId = docker $allParameters try { Write-Verbose " container id = $cId" - Start-Sleep -Seconds 0.5 Wait-Port -ContainerName $cId -Port 3050 # Last check before execute @@ -52,7 +51,7 @@ function Use-Container([string[]]$Parameters, [Parameter(Mandatory)][ScriptBlock # Wait for a port to be open in a container. function Wait-Port([string]$ContainerName, [int]$Port) { - while (-not (Test-Port -ContainerName $cId -Port 3050)) { + while (-not (Test-Port -ContainerName $ContainerName -Port $Port)) { Start-Sleep -Seconds 0.2 } } @@ -215,12 +214,12 @@ task FIREBIRD_DATABASE_can_create_database_with_unicode_characters { } task FIREBIRD_DATABASE_PAGE_SIZE_can_set_page_size_on_database_creation { - Use-Container -Parameters '-e', 'FIREBIRD_DATABASE=test.fdb', '-e', 'FIREBIRD_DATABASE_PAGE_SIZE=4096' { + Use-Container -Parameters '-e', 'FIREBIRD_DATABASE=test.fdb', '-e', 'FIREBIRD_DATABASE_PAGE_SIZE=8192' { param($cId) 'SET LIST ON; SELECT mon$page_size FROM mon$database;' | docker exec -i $cId isql -b -q /var/lib/firebird/data/test.fdb | - Contains -Pattern 'MON\$PAGE_SIZE(\s+)4096' -ErrorMessage "Expected database page size to be 4096." + Contains -Pattern 'MON\$PAGE_SIZE(\s+)8192' -ErrorMessage "Expected database page size to be 8192." } Use-Container -Parameters '-e', 'FIREBIRD_DATABASE=test.fdb', '-e', 'FIREBIRD_DATABASE_PAGE_SIZE=16384' { @@ -320,12 +319,14 @@ task FIREBIRD_USE_LEGACY_AUTH_enables_legacy_auth { } task FIREBIRD_CONF_can_change_any_setting { - Use-Container -Parameters '-e', 'FIREBIRD_CONF_DefaultDbCachePages=64K', '-e', 'FIREBIRD_CONF_DefaultDbCachePages=64K', '-e', 'FIREBIRD_CONF_FileSystemCacheThreshold=100M' { + # DefaultDbCachePages and TempCacheLimit exist in all supported Firebird versions (3, 4, 5, 6). + # FileSystemCacheThreshold was removed in Firebird 6 so we intentionally avoid it. + Use-Container -Parameters '-e', 'FIREBIRD_CONF_DefaultDbCachePages=64K', '-e', 'FIREBIRD_CONF_TempCacheLimit=100M' { param($cId) $logs = docker logs $cId $logs | Contains -Pattern "DefaultDbCachePages = 64K" -ErrorMessage "Expected log message 'DefaultDbCachePages = 64K'." - $logs | Contains -Pattern "FileSystemCacheThreshold = 100M" -ErrorMessage "Expected log message 'FileSystemCacheThreshold = 100M'." + $logs | Contains -Pattern "TempCacheLimit = 100M" -ErrorMessage "Expected log message 'TempCacheLimit = 100M'." } } @@ -419,3 +420,127 @@ task TZ_can_change_system_timezone { $actual | IsAdjacent -ExpectedValue $expected } } + +task FIREBIRD_ROOT_PASSWORD_with_special_characters { + # Test SQL injection resistance: passwords with single quotes, semicolons, etc. + Use-Container -Parameters '-e', 'FIREBIRD_DATABASE=test.fdb', '-e', "FIREBIRD_ROOT_PASSWORD=it's;a--test" { + param($cId) + + # Correct password + 'SELECT 1 FROM rdb$database;' | + docker exec -i $cId isql -b -q -u SYSDBA -p "it's;a--test" inet:///var/lib/firebird/data/test.fdb | + ExitCodeIs -ExpectedValue 0 -ErrorMessage "Expected successful login with special character SYSDBA password." + + docker logs $cId | + Contains -Pattern 'Changing SYSDBA password' -ErrorMessage "Expected log message for SYSDBA password change with special characters." + } +} + +task FIREBIRD_USER_PASSWORD_with_special_characters { + # Test that user passwords with quotes work (SQL injection vector) + Use-Container -Parameters '-e', 'FIREBIRD_DATABASE=test.fdb', '-e', "FIREBIRD_USER=alice", '-e', "FIREBIRD_PASSWORD=p@ss'word" { + param($cId) + + 'SELECT 1 FROM rdb$database;' | + docker exec -i $cId isql -b -q -u alice -p "p@ss'word" inet:///var/lib/firebird/data/test.fdb | + ExitCodeIs -ExpectedValue 0 -ErrorMessage "Expected successful login with special character user password." + + docker logs $cId | + Contains -Pattern "Creating user 'alice'" -ErrorMessage "Expected log message indicating creation of user 'alice' with special password." + } +} + +task Graceful_shutdown_via_SIGTERM { + Use-Container -ScriptBlock { + param($cId) + + # Send SIGTERM (same as docker stop) + docker kill --signal SIGTERM $cId > $null + Start-Sleep -Seconds 3 + + # Container should have exited cleanly + $state = docker inspect --format '{{.State.Status}}' $cId 2>$null + if ($state -eq 'running') { + # Give it a bit more time + Start-Sleep -Seconds 3 + } + + $logs = docker logs $cId + $logs | Contains -Pattern 'Stopping Firebird' -ErrorMessage "Expected 'Stopping Firebird' log on SIGTERM." + } +} + +task Tini_is_PID_1 { + Use-Container -ScriptBlock { + param($cId) + + $pid1 = docker exec $cId cat /proc/1/comm + assert ($pid1.Trim() -eq 'tini') "Expected PID 1 to be 'tini', got '$($pid1.Trim())'." + } +} + +task FIREBIRD_ROOT_PASSWORD_FILE_can_set_password_from_file { + $secretDir = New-TemporaryDirectory + try { + 'secretpass123' | Out-File "$secretDir/password.txt" -NoNewline + + Use-Container -Parameters '-e', 'FIREBIRD_DATABASE=test.fdb', '-e', 'FIREBIRD_ROOT_PASSWORD_FILE=/run/secrets/password.txt', '-v', "$($secretDir):/run/secrets/" { + param($cId) + + # Correct password from file + 'SELECT 1 FROM rdb$database;' | + docker exec -i $cId isql -b -q -u SYSDBA -p secretpass123 inet:///var/lib/firebird/data/test.fdb | + ExitCodeIs -ExpectedValue 0 -ErrorMessage "Expected successful login with password loaded from _FILE." + + docker logs $cId | + Contains -Pattern 'Changing SYSDBA password' -ErrorMessage "Expected SYSDBA password change log when using _FILE." + } + } + finally { + Remove-Item $secretDir -Force -Recurse + } +} + +task FIREBIRD_PASSWORD_FILE_can_set_user_password_from_file { + $secretDir = New-TemporaryDirectory + try { + 'userpass456' | Out-File "$secretDir/user_password.txt" -NoNewline + + Use-Container -Parameters '-e', 'FIREBIRD_DATABASE=test.fdb', '-e', 'FIREBIRD_USER=bob', '-e', 'FIREBIRD_PASSWORD_FILE=/run/secrets/user_password.txt', '-v', "$($secretDir):/run/secrets/" { + param($cId) + + 'SELECT 1 FROM rdb$database;' | + docker exec -i $cId isql -b -q -u bob -p userpass456 inet:///var/lib/firebird/data/test.fdb | + ExitCodeIs -ExpectedValue 0 -ErrorMessage "Expected successful login with user password loaded from _FILE." + + docker logs $cId | + Contains -Pattern "Creating user 'bob'" -ErrorMessage "Expected log for user creation with _FILE password." + } + } + finally { + Remove-Item $secretDir -Force -Recurse + } +} + +task FILE_and_env_var_are_mutually_exclusive { + $secretDir = New-TemporaryDirectory + try { + 'filepass' | Out-File "$secretDir/password.txt" -NoNewline + + # Setting both FIREBIRD_ROOT_PASSWORD and FIREBIRD_ROOT_PASSWORD_FILE should fail + $($stdout = Invoke-Container -DockerParameters '-e', 'FIREBIRD_ROOT_PASSWORD=envpass', '-e', 'FIREBIRD_ROOT_PASSWORD_FILE=/run/secrets/password.txt', '-v', "$($secretDir):/run/secrets/") 2>&1 | + Contains -Pattern 'Both FIREBIRD_ROOT_PASSWORD and FIREBIRD_ROOT_PASSWORD_FILE are set' -ErrorMessage "Expected error when both _FILE and env var are set." + } + finally { + Remove-Item $secretDir -Force -Recurse + } +} + +task Tag_correctness_via_docker_inspect { + # Verify the image has the correct version label + $labels = docker inspect --format '{{json .Config.Labels}}' $env:FULL_IMAGE_NAME | ConvertFrom-Json + $version = $labels.'org.opencontainers.image.version' + assert ($null -ne $version) "Expected 'org.opencontainers.image.version' label to be set." + # Accept either a semver release (e.g. '5.0.3') or a snapshot tag (e.g. '5-snapshot', '6-snapshot') + assert ($version -match '^\d+\.\d+\.\d+$' -or $version -match '^\d+-snapshot$') "Expected version label '$version' to be semver or snapshot format." +} \ No newline at end of file diff --git a/src/tags.tests.ps1 b/src/tags.tests.ps1 new file mode 100644 index 0000000..9a3d460 --- /dev/null +++ b/src/tags.tests.ps1 @@ -0,0 +1,90 @@ +# +# Unit tests for the Get-ImageTags function in firebird-docker.build.ps1 +# + +BeforeAll { + # Source the shared functions (contains Get-ImageTags) + . $PSScriptRoot/functions.ps1 +} + +Describe 'Get-ImageTags' { + + Context 'Latest overall version on default distro (bookworm)' { + It 'generates all tag types for 5.0.3-bookworm' { + $tags = Get-ImageTags -Version '5.0.3' -Distro 'bookworm' ` + -IsLatestOfMajor $true -IsLatestOverall $true -DefaultDistro 'bookworm' + + $tags | Should -Contain '5.0.3-bookworm' # version-distro + $tags | Should -Contain '5-bookworm' # major-distro + $tags | Should -Contain 'bookworm' # distro (latest overall) + $tags | Should -Contain '5.0.3' # version (default distro) + $tags | Should -Contain '5' # major (default distro) + $tags | Should -Contain 'latest' # latest (default distro) + $tags | Should -HaveCount 6 + } + } + + Context 'Latest overall version on non-default distro (noble)' { + It 'generates distro-qualified tags for 5.0.3-noble' { + $tags = Get-ImageTags -Version '5.0.3' -Distro 'noble' ` + -IsLatestOfMajor $true -IsLatestOverall $true -DefaultDistro 'bookworm' + + $tags | Should -Contain '5.0.3-noble' # version-distro + $tags | Should -Contain '5-noble' # major-distro + $tags | Should -Contain 'noble' # distro (latest overall) + $tags | Should -Not -Contain '5.0.3' # no bare version + $tags | Should -Not -Contain '5' # no bare major + $tags | Should -Not -Contain 'latest' # no latest + $tags | Should -HaveCount 3 + } + } + + Context 'Latest of major but not latest overall' { + It 'generates major tags for 4.0.6-bookworm' { + $tags = Get-ImageTags -Version '4.0.6' -Distro 'bookworm' ` + -IsLatestOfMajor $true -IsLatestOverall $false -DefaultDistro 'bookworm' + + $tags | Should -Contain '4.0.6-bookworm' # version-distro + $tags | Should -Contain '4-bookworm' # major-distro + $tags | Should -Not -Contain 'bookworm' # NOT latest overall + $tags | Should -Contain '4.0.6' # version (default distro) + $tags | Should -Contain '4' # major (default distro) + $tags | Should -Not -Contain 'latest' # NOT latest overall + $tags | Should -HaveCount 4 + } + } + + Context 'Older patch version (not latest of major)' { + It 'generates minimal tags for 5.0.2-bookworm' { + $tags = Get-ImageTags -Version '5.0.2' -Distro 'bookworm' ` + -IsLatestOfMajor $false -IsLatestOverall $false -DefaultDistro 'bookworm' + + $tags | Should -Contain '5.0.2-bookworm' # version-distro + $tags | Should -Contain '5.0.2' # version (default distro) + $tags | Should -Not -Contain '5-bookworm' # NOT latest of major + $tags | Should -Not -Contain '5' # NOT latest of major + $tags | Should -Not -Contain 'latest' # NOT latest + $tags | Should -HaveCount 2 + } + } + + Context 'Older patch version on non-default distro' { + It 'generates only version-distro for 4.0.5-bullseye' { + $tags = Get-ImageTags -Version '4.0.5' -Distro 'bullseye' ` + -IsLatestOfMajor $false -IsLatestOverall $false -DefaultDistro 'bookworm' + + $tags | Should -Contain '4.0.5-bullseye' # version-distro + $tags | Should -Not -Contain '4.0.5' # not default distro + $tags | Should -HaveCount 1 + } + } + + Context 'Tag uniqueness' { + It 'produces no duplicate tags' { + $tags = Get-ImageTags -Version '5.0.3' -Distro 'bookworm' ` + -IsLatestOfMajor $true -IsLatestOverall $true -DefaultDistro 'bookworm' + + $tags | Should -HaveCount ($tags | Sort-Object -Unique | Measure-Object).Count + } + } +}