Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
c201b0c
feat: draft node 18 -> 24 transition + build system rework
vermorag Sep 20, 2026
669f095
feat: enhance container entrypoint with logging, error handling, and …
vermorag Sep 20, 2026
90e5593
feat: restructure configs for runtime separation, enhance container p…
vermorag Sep 20, 2026
c50b5f9
Merge branch 'main' into task/332-upgrade-nodejs-runtime
vermorag Sep 20, 2026
d129a83
feat: add composer package build to release workflow and adjust build…
vermorag Sep 20, 2026
8cbadcd
feat: upgrade Node.js to 24 and pnpm to 12; update GitLab CI and cont…
vermorag Sep 20, 2026
5d3b131
feat: replace s6-overlay with pebble in release workflow configuration
vermorag Sep 20, 2026
33bfa56
feat: adjust container port to 8080, implement secure pod/container c…
vermorag Sep 20, 2026
ade6934
fix: update backend storage mount path in docker-compose configuration
vermorag Sep 20, 2026
b1017bd
docs: update CONTRIBUTING.md to reflect runtime, build, and deploymen…
vermorag Sep 20, 2026
2c3ef00
feat: add REVERB_APP_SECRET to Dockerfile environment configuration
vermorag Sep 20, 2026
7c855fe
fix: bind MySQL service to localhost in docker-compose configuration
vermorag Sep 20, 2026
35958b7
feat: refactor global Reverb configuration for protocol and port hand…
vermorag Sep 20, 2026
da499aa
fix: correct conditional structure in container-entrypoint.sh for pro…
vermorag Sep 20, 2026
883ca48
fix: use consistent environment variable handling for MELANGE keys in…
vermorag Sep 20, 2026
ccb1da7
fix: enforce APP_KEY validation and remove default value from Dockerfile
vermorag Sep 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 90 additions & 17 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@ env:

RUNTIME_CONFIG: build/base/runtime/apko.yaml
BUILDER_CONFIG: build/base/builder/apko.yaml
PHP_CONFIG: build/packages/php83.yaml
NODEJS_CONFIG: build/packages/nodejs-24.yaml
PEBBLE_CONFIG: build/packages/pebble.yaml
COMPOSER_CONFIG: build/packages/composer.yaml
COREPACK_CONFIG: build/packages/corepack.yaml

# Increment when the base-image build process itself changes in a way
# that should invalidate previously built immutable images.
IMAGE_BUILD_REVISION: '2'
IMAGE_BUILD_REVISION: '6'

# OCI image metadata.
#
Expand All @@ -41,10 +45,10 @@ env:
reports, screenshots, activity tracking and public API

RUNTIME_DESCRIPTION: >-
Cattr server runtime image with PHP 8.2, Nginx and required runtime dependencies
Cattr server runtime image with PHP 8.3, Nginx and Pebble on Wolfi

BUILDER_DESCRIPTION: >-
Cattr server build image with PHP 8.2, Composer, Node.js and Corepack
Cattr server build image with PHP 8.3, Composer, Node.js and Corepack on Wolfi

jobs:
runtime-images:
Expand Down Expand Up @@ -100,6 +104,10 @@ jobs:
for file in \
"${RUNTIME_CONFIG}" \
"${BUILDER_CONFIG}" \
"${PHP_CONFIG}" \
"${NODEJS_CONFIG}" \
"${PEBBLE_CONFIG}" \
"${COMPOSER_CONFIG}" \
"${COREPACK_CONFIG}"
do
if [[ ! -f "${file}" ]]; then
Expand All @@ -110,11 +118,17 @@ jobs:

runtime_files_hash="${{ hashFiles(
'build/base/runtime/**',
'build/packages/php83.yaml',
'build/packages/pebble.yaml',
'build/base/rebuild'
) }}"

builder_files_hash="${{ hashFiles(
'build/base/builder/**',
'build/packages/php83.yaml',
'build/packages/nodejs-24.yaml',
'build/packages/pebble.yaml',
'build/packages/composer.yaml',
'build/packages/corepack.yaml',
'build/base/rebuild'
) }}"
Expand All @@ -141,6 +155,8 @@ jobs:
--format='%H' \
-- \
"${RUNTIME_CONFIG}" \
"${PHP_CONFIG}" \
"${PEBBLE_CONFIG}" \
build/base/rebuild
)"

Expand All @@ -150,6 +166,10 @@ jobs:
--format='%H' \
-- \
"${BUILDER_CONFIG}" \
"${PHP_CONFIG}" \
"${NODEJS_CONFIG}" \
"${PEBBLE_CONFIG}" \
"${COMPOSER_CONFIG}" \
"${COREPACK_CONFIG}" \
build/base/rebuild
)"
Expand All @@ -167,9 +187,10 @@ jobs:
# Static OCI metadata is part of the image identity as changing it
# changes the resulting OCI manifest/config digest.
runtime_hash="$(
printf '%s\n%s\n%s\n%s\n%s\n%s\n' \
printf '%s\n%s\n%s\n%s\n%s\n%s\n%s\n' \
"${IMAGE_BUILD_REVISION}" \
"${apko_version}" \
"${melange_version}" \
"${runtime_files_hash}" \
"${OCI_SOURCE}" \
"${OCI_VENDOR}" \
Expand Down Expand Up @@ -232,32 +253,78 @@ jobs:
echo "builder_exists=false" >> "${GITHUB_OUTPUT}"
fi

- name: Build Corepack APK repository
if: steps.check.outputs.builder_exists != 'true'
- name: Build local APK repository
if: steps.check.outputs.runtime_exists != 'true' || steps.check.outputs.builder_exists != 'true'
env:
MELANGE_PRIVATE_KEY: ${{ runner.temp }}/melange.rsa
PACKAGE_REPOSITORY: ${{ github.workspace }}/packages
run: |
set -euo pipefail

MELANGE_PRIVATE_KEY="${RUNNER_TEMP}/melange.rsa"
MELANGE_PUBLIC_KEY="${RUNNER_TEMP}/melange.rsa.pub"

rm -rf "${PACKAGE_REPOSITORY}"

rm -f \
"${MELANGE_PRIVATE_KEY}" \
"${MELANGE_PRIVATE_KEY}.pub"
"${MELANGE_PUBLIC_KEY}"

melange keygen "${MELANGE_PRIVATE_KEY}"

melange build \
"${COREPACK_CONFIG}" \
--runner bubblewrap \
# Build the packages that depend only on Wolfi or upstream release
# artifacts first. Composer and Corepack are intentionally built in
# the next phase because their metapackage dependencies must be
# available in the local repository.
for config in \
"${PHP_CONFIG}" \
"${NODEJS_CONFIG}" \
"${PEBBLE_CONFIG}"
do
melange build \
"${config}" \
--runner bubblewrap \
--arch x86_64 \
--out-dir "${PACKAGE_REPOSITORY}" \
--signing-key "${MELANGE_PRIVATE_KEY}" \
--generate-index=false \
--namespace cattr \
--license MIT \
--git-repo-url "${OCI_SOURCE}" \
--git-commit "${GITHUB_SHA}"
done

# Make the first-phase packages available to dependent builds.
melange index \
--arch x86_64 \
--out-dir "${PACKAGE_REPOSITORY}" \
--output "${PACKAGE_REPOSITORY}/x86_64/APKINDEX.tar.gz" \
--signing-key "${MELANGE_PRIVATE_KEY}" \
--namespace cattr \
--license MIT \
--git-repo-url "${OCI_SOURCE}" \
--git-commit "${GITHUB_SHA}"
"${PACKAGE_REPOSITORY}/x86_64/"*.apk

for config in \
"${COMPOSER_CONFIG}" \
"${COREPACK_CONFIG}"
do
melange build \
"${config}" \
--runner bubblewrap \
--arch x86_64 \
--out-dir "${PACKAGE_REPOSITORY}" \
--repository-append "${PACKAGE_REPOSITORY}" \
--keyring-append "${MELANGE_PUBLIC_KEY}" \
--signing-key "${MELANGE_PRIVATE_KEY}" \
--generate-index=false \
--namespace cattr \
--license MIT \
--git-repo-url "${OCI_SOURCE}" \
--git-commit "${GITHUB_SHA}"
done

# Rebuild one signed index containing all local packages.
melange index \
--arch x86_64 \
--output "${PACKAGE_REPOSITORY}/x86_64/APKINDEX.tar.gz" \
--signing-key "${MELANGE_PRIVATE_KEY}" \
"${PACKAGE_REPOSITORY}/x86_64/"*.apk

echo "Generated APK repository:"

Expand All @@ -272,13 +339,18 @@ jobs:
env:
RUNTIME_TAG: ${{ steps.meta.outputs.runtime_tag }}
RUNTIME_REVISION: ${{ steps.meta.outputs.runtime_revision }}
PACKAGE_REPOSITORY: ${{ github.workspace }}/packages
run: |
set -euo pipefail

MELANGE_PUBLIC_KEY="${RUNNER_TEMP}/melange.rsa.pub"

echo "Publishing ${RUNTIME_IMAGE}:${RUNTIME_TAG}"

apko publish \
--vcs=false \
--repository-append "${PACKAGE_REPOSITORY}" \
--keyring-append "${MELANGE_PUBLIC_KEY}" \
--annotations "\"org.opencontainers.image.source:${OCI_SOURCE}\"" \
--annotations "\"org.opencontainers.image.revision:${RUNTIME_REVISION}\"" \
--annotations "\"org.opencontainers.image.version:${RUNTIME_TAG}\"" \
Expand Down Expand Up @@ -309,11 +381,12 @@ jobs:
env:
BUILDER_TAG: ${{ steps.meta.outputs.builder_tag }}
BUILDER_REVISION: ${{ steps.meta.outputs.builder_revision }}
MELANGE_PUBLIC_KEY: ${{ runner.temp }}/melange.rsa.pub
PACKAGE_REPOSITORY: ${{ github.workspace }}/packages
run: |
set -euo pipefail

MELANGE_PUBLIC_KEY="${RUNNER_TEMP}/melange.rsa.pub"

echo "Publishing ${RUNTIME_IMAGE}:${BUILDER_TAG}"

apko publish \
Expand Down
4 changes: 2 additions & 2 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ stages:
pages :
stage: pages
when: manual
image: node:18-alpine
image: node:24-alpine
only:
- tags
before_script:
- corepack enable
- pnpm install
- pnpm install --frozen-lockfile
- rm -rf public
- mkdir public
script:
Expand Down
10 changes: 5 additions & 5 deletions .helm/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ spec:
{{- end }}
ports:
- name: http
containerPort: 80
containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
Expand Down Expand Up @@ -111,16 +111,16 @@ spec:
- name: tmp
mountPath: /tmp
- name: cache
mountPath: /app/storage/framework/cache
mountPath: /opt/cattr/app/storage/framework/cache
- name: sessions
mountPath: /app/storage/framework/sessions
mountPath: /opt/cattr/app/storage/framework/sessions
{{- if .Values.persistence.screenshots.enabled }}
- name: screenshots
mountPath: /app/storage/app/uploads/screenshots
mountPath: /opt/cattr/app/storage/app/uploads/screenshots
{{- end }}
{{- if .Values.persistence.attachments.enabled }}
- name: attachments
mountPath: /app/storage/app/uploads/attachments
mountPath: /opt/cattr/app/storage/app/uploads/attachments
{{- end }}
{{- with .Values.extraVolumeMounts }}
{{- toYaml . | nindent 12 }}
Expand Down
19 changes: 16 additions & 3 deletions .helm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,21 @@ mysql:
failureThreshold: 3

## @section Cattr deployment parameters
podSecurityContext: {}
containerSecurityContext: {}
podSecurityContext:
## Run the pod as the non-root UID/GID used by the runtime image.
runAsUser: 10000
runAsGroup: 10000
fsGroup: 10000
fsGroupChangePolicy: OnRootMismatch
containerSecurityContext:
## The runtime image is rootless and does not require privilege escalation.
runAsNonRoot: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
seccompProfile:
type: RuntimeDefault

## Cattr resource requests and limits
resources:
Expand All @@ -117,7 +130,7 @@ resources:
cpu: "1"
memory: 1Gi

## Cattr startup probe (generous for s6-overlay + migrations)
## Cattr startup probe (generous for Pebble + migrations)
startupProbe:
enabled: true
initialDelaySeconds: 30
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18.20
24.21
2 changes: 1 addition & 1 deletion .php-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8.2
8.3
1 change: 0 additions & 1 deletion .root-fs/crontab

This file was deleted.

60 changes: 0 additions & 60 deletions .root-fs/etc/nginx/conf.d/app.conf

This file was deleted.

Loading
Loading