Compare commits

...

51 Commits

Author SHA1 Message Date
chris db06578537 port patches
dockers/pixelfed/pipeline/head There was a failure building this commit Details
2024-04-20 16:23:22 +02:00
chris 045ac9469b disable config cache on composer install
dockers/pixelfed/pipeline/head This commit looks good Details
2024-04-13 11:52:49 +02:00
chris 1f8db65cbc port patches
dockers/pixelfed/pipeline/head There was a failure building this commit Details
2024-04-06 11:47:38 +02:00
chris dd3488fa0c hcloud build script
dockers/pixelfed/pipeline/head There was a failure building this commit Details
2024-03-17 12:52:29 +01:00
chris 71d13451f1 port patches
dockers/pixelfed/pipeline/head This commit looks good Details
2024-03-12 17:11:50 +01:00
chris 910de7b38c use debian 12 + php 8.2
dockers/pixelfed/pipeline/head There was a failure building this commit Details
2024-02-29 15:49:43 +01:00
chris 81d52e8dcd rebase patches against current source
dockers/pixelfed/pipeline/head This commit looks good Details
2024-01-24 13:20:14 +01:00
chris 07117affc1 specify TMPDIR
dockers/pixelfed/pipeline/head There was a failure building this commit Details
2023-12-08 21:02:02 +01:00
chris 130738d005 add schedule:work-er
dockers/pixelfed/pipeline/head There was a failure building this commit Details
2023-10-26 11:44:40 +02:00
chris c3d91f05f1 update patches 2023-10-25 11:41:40 +02:00
chris d7d3fb47f6 fix ownership
dockers/pixelfed/pipeline/head This commit looks good Details
2023-10-22 21:47:07 +02:00
chris c63b418ea5 persist public directory in fpm image
dockers/pixelfed/pipeline/head This commit looks good Details
2023-10-22 00:29:51 +02:00
chris 98e1a60d35 drop zknt registry 2023-10-18 13:21:05 +02:00
chris 257f3c19d5 multiarch build
dockers/pixelfed/pipeline/head This commit looks good Details
2023-10-17 21:06:14 +02:00
chris f47bb68477 add pgsql extension, fixes #13
dockers/pixelfed/pipeline/head This commit looks good Details
2023-10-09 11:10:01 +02:00
chris 8ad1f9b8a2 include patches
dockers/pixelfed/pipeline/head This commit looks good Details
2023-10-08 18:42:07 +02:00
chris 6d9842c969 redo timestamp tags
dockers/pixelfed/pipeline/head This commit looks good Details
2023-10-07 15:27:17 +02:00
chris 5a0c5f317e retag
dockers/pixelfed/pipeline/head There was a failure building this commit Details
2023-10-07 15:08:30 +02:00
chris 835689c269 Merge branch 'rebase_on_official' 2023-10-07 15:02:27 +02:00
chris f2ffbf9716 support building versions
dockers/pixelfed/pipeline/head Something is wrong with the build of this commit Details
2023-10-07 14:55:37 +02:00
chris 7bd7efe307 move git hosts
dockers/pixelfed/pipeline/head This commit looks good Details
2023-09-18 18:51:53 +02:00
chris acfee084c6 copy public/ to volume
dockers/pixelfed/pipeline/head This commit looks good Details
2023-08-10 16:47:22 +02:00
chris f7db2ef12f build fpm image
dockers/pixelfed/pipeline/head This commit looks good Details
2023-08-09 13:28:08 +02:00
chris 05dddc8df3 port patches
dockers/pixelfed/pipeline/head This commit looks good Details
2023-08-01 09:48:41 +02:00
chris a6cbb0683c port patches
dockers/pixelfed/pipeline/head This commit looks good Details
2023-08-01 09:48:14 +02:00
chris 65e3f2e0f2 add username patch
dockers/pixelfed/pipeline/head This commit looks good Details
2023-07-27 12:49:45 +02:00
chris 916641315c integrate beagle patch
dockers/pixelfed/pipeline/head This commit looks good Details
2023-07-17 10:50:20 +02:00
chris dcdeac6f8c add timestamp
dockers/pixelfed/pipeline/head This commit looks good Details
2023-07-17 10:49:42 +02:00
chris cd501d26b1 integrate beagle patch
dockers/pixelfed/pipeline/head This commit looks good Details
2023-07-17 10:49:06 +02:00
chris 03efdb0ba1 enable prod config
dockers/pixelfed/pipeline/head This commit looks good Details
2023-06-20 21:13:41 +02:00
chris 5827e9189e enable opcache 2023-06-20 20:43:34 +02:00
chris 343be959f0 chown www-data 2023-06-20 20:43:15 +02:00
chris 73dde44afe clean string interpolation
dockers/pixelfed/pipeline/head This commit looks good Details
2023-06-09 19:55:53 +02:00
chris b5299e8a6f compat old buildah
dockers/pixelfed/pipeline/head This commit looks good Details
2023-06-07 04:34:44 +02:00
chris f624545dfd rebase on php:8.1
dockers/pixelfed/pipeline/head There was a failure building this commit Details
2023-06-06 21:03:46 +02:00
chris a9c16f41ea port ip patch
dockers/pixelfed/pipeline/head This commit looks good Details
2023-05-27 11:35:13 +02:00
chris 9add15087f Composer 2.2
dockers/pixelfed/pipeline/head There was a failure building this commit Details
2023-04-20 13:58:57 +02:00
chris 19115d6125 new patches
dockers/pixelfed/pipeline/head There was a failure building this commit Details
2023-04-10 18:36:34 +02:00
chris 6111fd726c check for new migrations
dockers/pixelfed/pipeline/head This commit looks good Details
2023-01-09 20:36:09 +01:00
chris a385f624f9 remove old deps
dockers/pixelfed/pipeline/head This commit looks good Details
2022-11-14 13:20:16 +01:00
chris 748bbe9512 autoload
dockers/pixelfed/pipeline/head There was a failure building this commit Details
2022-11-14 12:13:04 +01:00
chris cc8ea24f8b php81
dockers/pixelfed/pipeline/head This commit looks good Details
2022-11-12 23:36:41 +01:00
chris f564fd6c24 skip self-diagnosis
dockers/pixelfed/pipeline/head This commit looks good Details
2022-11-11 14:23:19 +01:00
chris 9fa079fac9 bump php
dockers/pixelfed/pipeline/head There was a failure building this commit Details
2022-11-11 14:16:15 +01:00
chris 125d37d3b4 fix startup
dockers/pixelfed/pipeline/head There was a failure building this commit Details
2022-10-17 12:01:51 +02:00
chris 820d54772c default to rich discovery patch
dockers/pixelfed/pipeline/head This commit looks good Details
2022-09-11 14:10:21 +02:00
chris c6b9df7773 websockets
dockers/pixelfed/pipeline/head This commit looks good Details
2022-07-08 14:10:55 +02:00
chris f1232be0e9 remove hirak/prestissimo
dockers/pixelfed/pipeline/head This commit looks good Details
2022-04-01 17:04:44 +02:00
chris c8a596bc08 Merge branch 'master' of ssh://git.zknt.org:2222/dockers/pixelfed
dockers/pixelfed/pipeline/head There was a failure building this commit Details
2022-02-28 19:31:57 +01:00
chris 4c94f3a087 remove impressum from public image 2022-02-28 19:31:50 +01:00
chris 9093af18da Merge pull request 'added support for postgres' (#1) from samuel-p/pixelfed:master into master
dockers/pixelfed/pipeline/head This commit looks good Details
Reviewed-on: dockers/pixelfed#1
2022-02-28 15:45:46 +00:00
17 changed files with 781 additions and 77 deletions

73
Containerfile Normal file
View File

@ -0,0 +1,73 @@
FROM docker.io/php:8.2-apache-bookworm as builder
ARG VERSION=dev
ARG DATE
RUN set -xe;\
apt-get update &&\
apt-get install --no-install-recommends -y git locales libcurl4-openssl-dev libzip-dev libicu-dev libxml2-dev libjpeg62-turbo-dev libpng-dev libmagickwand-dev libpq-dev libxpm-dev libwebp-dev zip libpq-dev &&\
apt-get clean all &&\
rm -rf /var/lib/apt/lists/*
RUN set -xe;\
docker-php-ext-configure mbstring --disable-mbregex &&\
docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp --with-xpm &&\
docker-php-ext-install -j$(nproc) curl zip bcmath intl mbstring xml pcntl gd mysqli pdo_mysql pdo_pgsql opcache &&\
docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql && docker-php-ext-install pdo_pgsql pgsql &&\
pecl install imagick &&\
pecl install redis &&\
docker-php-ext-enable imagick redis
RUN set -xe;\
curl https://raw.githubusercontent.com/composer/getcomposer.org/0a51b6fe383f7f61cf1d250c742ec655aa044c94/web/installer | php -- --quiet --2.2 &&\
mv composer.phar /usr/local/bin/composer
COPY patches/ /patches/
RUN set -xe;\
cd /var && rm -rf www &&\
git clone https://github.com/pixelfed/pixelfed.git www &&\
cd www &&\
git checkout $VERSION &&\
git apply /patches/0001-remove-IP-logging.patch &&\
git apply /patches/0002-hardcode-discovery-settings.patch &&\
git apply /patches/0003-point-to-modified-sourcecode.patch &&\
git apply /patches/0004-disable-beagle-service.patch &&\
git apply /patches/0005-allow-30-char-usernames.patch &&\
ENABLE_CONFIG_CACHE=false composer install --prefer-dist --no-interaction --no-ansi --no-dev --optimize-autoloader &&\
ln -s public html &&\
chown -R www-data:www-data /var/www &&\
cp -r storage storage.skel &&\
rm -rf .git tests contrib CHANGELOG.md LICENSE .circleci .dependabot .github CODE_OF_CONDUCT.md .env.docker CONTRIBUTING.md README.md docker-compose.yml .env.testing phpunit.xml .env.example .gitignore .editorconfig .gitattributes .dockerignore /patches
FROM docker.io/php:8.2-apache-bookworm
ARG DATE
ARG VERSION=dev
COPY --from=builder /var/www /var/www
COPY entrypoint.sh /entrypoint.sh
COPY worker-entrypoint.sh /worker-entrypoint.sh
COPY websockets-entrypoint.sh /websockets-entrypoint.sh
COPY schedule-entrypoint.sh /schedule-entrypoint.sh
COPY wait-for-db.php /wait-for-db.php
COPY --from=builder /usr/local/lib/php/extensions/no-debug-non-zts-20220829 /usr/local/lib/php/extensions/no-debug-non-zts-20220829
COPY --from=builder /usr/local/etc/php/conf.d /usr/local/etc/php/conf.d
RUN set -xe;\
apt-get update &&\
apt-get install --no-install-recommends -y libzip4 libpq5 libmagickwand-6.q16-6 libxpm4 libwebp7 &&\
apt-get install --no-install-recommends -y optipng pngquant jpegoptim gifsicle ffmpeg locales gosu dumb-init zip &&\
apt-get clean all &&\
rm -rf /var/lib/apt/lists/*
RUN set -xe;\
a2enmod rewrite &&\
sed -i 's/AllowOverride None/AllowOverride All/g' /etc/apache2/apache2.conf &&\
sed -i 's/^post_max_size.*/post_max_size = 100M/g' "$PHP_INI_DIR"/php.ini* &&\
sed -i 's/^upload_max_filesize.*/upload_max_filesize = 100M/g' "$PHP_INI_DIR"/php.ini* &&\
mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
WORKDIR /var/www
VOLUME /var/www/storage /var/www/bootstrap
ENTRYPOINT /entrypoint.sh
LABEL build.date=$DATE version.pixelfed=$VERSION

74
Containerfile.fpm Normal file
View File

@ -0,0 +1,74 @@
FROM docker.io/php:8.2-fpm-bookworm as builder
ARG VERSION=dev
ARG DATE
RUN set -xe;\
apt-get update &&\
apt-get install --no-install-recommends -y git locales libcurl4-openssl-dev libzip-dev libicu-dev libxml2-dev libjpeg62-turbo-dev libpng-dev libmagickwand-dev libpq-dev libxpm-dev libwebp-dev zip libpq-dev &&\
apt-get clean all &&\
rm -rf /var/lib/apt/lists/*
RUN set -xe;\
docker-php-ext-configure mbstring --disable-mbregex &&\
docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp --with-xpm &&\
docker-php-ext-install -j$(nproc) curl zip bcmath intl mbstring xml pcntl gd mysqli pdo_mysql pdo_pgsql opcache &&\
docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql && docker-php-ext-install pdo_pgsql pgsql &&\
pecl install imagick &&\
pecl install redis &&\
docker-php-ext-enable imagick redis
RUN set -xe;\
curl https://raw.githubusercontent.com/composer/getcomposer.org/0a51b6fe383f7f61cf1d250c742ec655aa044c94/web/installer | php -- --quiet --2.2 &&\
mv composer.phar /usr/local/bin/composer
COPY patches/ /patches/
RUN set -xe;\
cd /var && rm -rf www &&\
git clone https://github.com/pixelfed/pixelfed.git www &&\
cd www &&\
git checkout $VERSION &&\
git apply /patches/0001-remove-IP-logging.patch &&\
git apply /patches/0002-hardcode-discovery-settings.patch &&\
git apply /patches/0003-point-to-modified-sourcecode.patch &&\
git apply /patches/0004-disable-beagle-service.patch &&\
git apply /patches/0005-allow-30-char-usernames.patch &&\
ENABLE_CONFIG_CACHE=false composer install --prefer-dist --no-interaction --no-ansi --no-dev --optimize-autoloader &&\
chown -R www-data:www-data /var/www &&\
cp -r storage storage.skel &&\
cp -r public public.skel &&\
chown -R www-data:www-data public.skel storage.skel &&\
rm -rf .git tests contrib CHANGELOG.md LICENSE .circleci .dependabot .github CODE_OF_CONDUCT.md .env.docker CONTRIBUTING.md README.md docker-compose.yml .env.testing phpunit.xml .env.example .gitignore .editorconfig .gitattributes .dockerignore
FROM docker.io/php:8.2-fpm-bookworm
ARG VERSION=dev
ARG DATE
COPY --from=builder /var/www /var/www
COPY entrypoint.fpm.sh /entrypoint.sh
COPY worker-entrypoint.sh /worker-entrypoint.sh
COPY schedule-entrypoint.sh /schedule-entrypoint.sh
COPY websockets-entrypoint.sh /websockets-entrypoint.sh
COPY wait-for-db.php /wait-for-db.php
COPY --from=builder /usr/local/lib/php/extensions/no-debug-non-zts-20220829 /usr/local/lib/php/extensions/no-debug-non-zts-20220829
COPY --from=builder /usr/local/etc/php/conf.d /usr/local/etc/php/conf.d
RUN set -xe;\
apt-get update &&\
apt-get upgrade -y &&\
apt-get install --no-install-recommends -y libzip4 libpq5 libmagickwand-6.q16-6 libxpm4 libwebp7 &&\
apt-get install --no-install-recommends -y optipng pngquant jpegoptim gifsicle ffmpeg locales gosu dumb-init rsync zip &&\
apt-get clean all &&\
rm -rf /var/lib/apt/lists/*
RUN set -xe;\
# a2enmod rewrite &&\
# sed -i 's/AllowOverride None/AllowOverride All/g' /etc/apache2/apache2.conf &&\
sed -i 's/^post_max_size.*/post_max_size = 100M/g' "$PHP_INI_DIR"/php.ini* &&\
sed -i 's/^upload_max_filesize.*/upload_max_filesize = 100M/g' "$PHP_INI_DIR"/php.ini* &&\
mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
WORKDIR /var/www
VOLUME /var/www/storage /var/www/bootstrap /var/www/public
ENTRYPOINT /entrypoint.sh
LABEL build.date=$DATE version.pixelfev=$VERSION

View File

@ -1,39 +0,0 @@
FROM reg.zknt.org/zknt/debian-php:7.4 as builder
ARG DATE
ENV PHPVER=7.4
ENV IP_PATCH=2722da0c4749b726bfb87ac56ba055940c2d2fc7
ENV IMPRESSUM_PATCH=dbb47aa7ef59f83e9f88d71992b928b618b4bc03
RUN set -xe;\
apt-install git unzip php${PHPVER}-curl php${PHPVER}-zip php${PHPVER}-bcmath php${PHPVER}-intl php${PHPVER}-mbstring php${PHPVER}-xml composer &&\
composer global require hirak/prestissimo --no-interaction --no-suggest --prefer-dist &&\
cd /var && rm -rf www &&\
git clone https://github.com/pixelfed/pixelfed.git www &&\
cd www &&\
curl -L https://github.com/hnrd/pixelfed/commit/${IP_PATCH}.patch | git apply &&\
curl -L https://github.com/hnrd/pixelfed/commit/${IMPRESSUM_PATCH}.patch | git apply &&\
composer require beyondcode/laravel-self-diagnosis &&\
composer install --prefer-dist --no-interaction --no-ansi --no-dev --optimize-autoloader &&\
ln -s public html &&\
chown -R www-data:www-data /var/www &&\
cp -r storage storage.skel &&\
rm -rf .git tests contrib CHANGELOG.md LICENSE .circleci .dependabot .github CODE_OF_CONDUCT.md .env.docker CONTRIBUTING.md README.md docker-compose.yml .env.testing phpunit.xml .env.example .gitignore .editorconfig .gitattributes .dockerignore
FROM reg.zknt.org/zknt/debian-php:7.4
ENV PHPVER=7.4
COPY --from=builder /var/www /var/www
COPY entrypoint.sh /entrypoint.sh
COPY worker-entrypoint.sh /worker-entrypoint.sh
COPY wait-for-db.php /wait-for-db.php
RUN apt-install php${PHPVER}-curl php${PHPVER}-zip php${PHPVER}-bcmath php${PHPVER}-intl php${PHPVER}-mbstring php${PHPVER}-xml optipng pngquant jpegoptim gifsicle ffmpeg php${PHPVER}-imagick php${PHPVER}-gd php${PHPVER}-redis php${PHPVER}-mysql php${PHPVER}-pgsql &&\
a2enmod rewrite &&\
sed -i 's/AllowOverride None/AllowOverride All/g' /etc/apache2/apache2.conf &&\
sed -i 's/^post_max_size.*/post_max_size = 100M/g' /etc/php/${PHPVER}/apache2/php.ini &&\
sed -i 's/^upload_max_filesize.*/upload_max_filesize = 100M/g' /etc/php/${PHPVER}/apache2/php.ini
WORKDIR /var/www
VOLUME /var/www/storage /var/www/bootstrap
ENTRYPOINT /entrypoint.sh
LABEL build.date=$DATE

99
Jenkinsfile vendored
View File

@ -1,42 +1,74 @@
version = ""
project = "pixelfed"
repo = "zknt"
registry = "reg.zknt.org"
registry_credentials = "6ff44976-23cd-4cc2-902c-de8c340e65e5"
timeStamp = Calendar.getInstance().getTime().format('YYYY-MM-dd',TimeZone.getTimeZone('UTC'))
pipeline {
agent any
triggers {
upstream(upstreamProjects: "../debian-php-74/trunk", threshold: hudson.model.Result.SUCCESS)
environment {
IO_CRED = credentials("3deeee3d-6fce-4430-98dd-9b4db56f43f7")
QUAY_CRED = credentials("18fb6f7e-c6bc-4d06-9bf9-08c2af6bfc1a")
}
stages {
stage('Build image') {
stage('Prepare') {
steps {
withDockerRegistry([ credentialsId: registry_credentials, url: "https://"+registry ]) {
script {
version = timeStamp
def customImage = docker.build(registry+'/'+repo+'/'+project, "--pull --build-arg VERSION=$version --build-arg DATE=$timeStamp .")
customImage.push(version)
customImage.push("latest")
def io_registry_credentials = "3deeee3d-6fce-4430-98dd-9b4db56f43f7"
withDockerRegistry([ credentialsId: io_registry_credentials ]) {
def io_registry_image = repo + '/' + project + ':' + version
sh "docker image tag " + registry+'/'+repo+'/'+project+':'+version + ' ' + io_registry_image
sh "docker push " + io_registry_image
sh "docker image tag " + registry+'/'+repo+'/'+project+':'+version + ' ' + io_registry_image.split(/\:/)[0] + ":latest"
sh "docker push " + io_registry_image.split(/\:/)[0] + ":latest"
}
def quay_credentials= "18fb6f7e-c6bc-4d06-9bf9-08c2af6bfc1a"
withDockerRegistry([ credentialsId: quay_credentials, url: "https://quay.io" ]) {
def quay_image = 'quay.io/' + repo + '/' + project + ':' + version
sh "docker image tag " + registry+'/'+repo+'/'+project+':'+version + ' ' + quay_image
sh "docker push " + quay_image
sh "docker image tag " + registry+'/'+repo+'/'+project+':'+version + ' ' + quay_image.split(/\:/)[0] + ":latest"
sh "docker push " + quay_image.split(/\:/)[0] + ":latest"
}
}
script {
sh "buildah login -u " + IO_CRED_USR+ " -p " + IO_CRED_PSW + " docker.io"
sh "buildah login -u " + QUAY_CRED_USR+ " -p " + QUAY_CRED_PSW + " quay.io"
sh "buildah manifest create pixelfed-dev"
sh "buildah manifest create pixelfed-dev-fpm"
}
}
}
stage('Build dev amd64') {
steps {
script {
sh "TMPDIR=/buildah/tmp buildah bud -f Containerfile --build-arg DATE=$timeStamp --manifest pixelfed-dev --arch amd64"
}
}
}
stage('Build dev arm64') {
steps {
script {
sh "TMPDIR=/buildah/tmp buildah bud -f Containerfile --build-arg DATE=$timeStamp --manifest pixelfed-dev --arch arm64"
}
}
}
stage('Build dev-fpm amd64') {
steps {
script {
sh "TMPDIR=/buildah/tmp buildah bud -f Containerfile.fpm --build-arg DATE=$timeStamp --manifest pixelfed-dev-fpm --arch amd64"
}
}
}
stage('Build dev-fpm arm64') {
steps {
script {
sh "TMPDIR=/buildah/tmp buildah bud -f Containerfile.fpm --build-arg DATE=$timeStamp --manifest pixelfed-dev-fpm --arch arm64"
}
}
}
stage('Upload to quay.io') {
steps {
script {
sh "buildah manifest push --all pixelfed-dev docker://quay.io/zknt/pixelfed:dev"
sh "buildah manifest push --all pixelfed-dev docker://quay.io/zknt/pixelfed:latest"
sh "buildah manifest push --all pixelfed-dev docker://quay.io/zknt/pixelfed:$timeStamp"
sh "buildah manifest push --all pixelfed-dev-fpm docker://quay.io/zknt/pixelfed:dev-fpm"
sh "buildah manifest push --all pixelfed-dev-fpm docker://quay.io/zknt/pixelfed:fpm"
sh "buildah manifest push --all pixelfed-dev-fpm docker://quay.io/zknt/pixelfed:$timeStamp-fpm"
}
}
}
stage('Upload to docker.io') {
steps {
script {
sh "buildah manifest push --all pixelfed-dev docker://docker.io/zknt/pixelfed:dev"
sh "buildah manifest push --all pixelfed-dev docker://docker.io/zknt/pixelfed:latest"
sh "buildah manifest push --all pixelfed-dev docker://docker.io/zknt/pixelfed:$timeStamp"
sh "buildah manifest push --all pixelfed-dev-fpm docker://docker.io/zknt/pixelfed:dev-fpm"
sh "buildah manifest push --all pixelfed-dev-fpm docker://docker.io/zknt/pixelfed:fpm"
sh "buildah manifest push --all pixelfed-dev-fpm docker://docker.io/zknt/pixelfed:$timeStamp-fpm"
}
}
}
@ -44,11 +76,8 @@ pipeline {
post {
always {
sh """docker container prune -f"""
sh """docker image prune -f"""
sh """docker rmi -f \$(docker images -q $registry/$repo/$project:$version)"""
sh """for image in \$(grep FROM Dockerfile | cut -d ' ' -f 2 | grep -vi -e SCRATCH -e bootstrapped | uniq); do docker rmi -f \$(docker images -q \${image}); done"""
emailext body: 'build finished', subject: '[jenkins] docker '+project+'('+version+'): ' + currentBuild.result, to: 'cg@zknt.org', from: 'sysadm@zknt.org', attachLog: true
sh """buildah rmi -af"""
emailext body: 'build finished', subject: '[jenkins] docker '+project+'('+timeStamp+'): ' + currentBuild.result, to: 'cg@zknt.org', from: 'sysadm@zknt.org', attachLog: true
}
}
options {
@ -75,4 +104,4 @@ pipeline {
]
]))
}
}
}

View File

@ -1,7 +1,7 @@
---
version: ""
project: pixelfed
trigger_upstream: ../debian-php-74/trunk
trigger_upstream: ../debian-php-81/trunk
timestamp_version: true
additional_tags:
- latest

40
entrypoint.fpm.sh Executable file
View File

@ -0,0 +1,40 @@
#!/usr/bin/env bash
set -xeo pipefail
rsync -a --delete storage.skel/* storage/
rsync -a --delete public.skel/ public/
chown -R www-data:www-data storage/ bootstrap/
php /wait-for-db.php
if [[ ! -e storage/.docker.init ]]
then
echo "Fresh installation, initializing database..."
gosu www-data php artisan key:generate
gosu www-data php artisan migrate:fresh --force
gosu www-data php artisan passport:keys
echo completed > storage/.docker.init
fi
gosu www-data php artisan storage:link
gosu www-data php artisan horizon:publish
gosu www-data php artisan config:cache
gosu www-data php artisan cache:clear
gosu www-data php artisan route:cache
gosu www-data php artisan view:cache
rsync --archive --delete public/ /public/
echo "++++ Check for needed migrations... ++++"
# check for migrations
gosu www-data php artisan migrate:status | grep No && migrations=yes || migrations=no
gosu www-data php artisan migrate:status | grep Pending && migrations=yes || migrations=no
if [ "$migrations" = "yes" ];
then
gosu www-data php artisan migrate --force
fi
# create instance actor
gosu www-data php artisan instance:actor
dumb-init docker-php-entrypoint -F

View File

@ -7,6 +7,7 @@ then
fi
cp -r storage.skel/* storage/
chown -R www-data:www-data storage/ bootstrap/
php /wait-for-db.php
@ -21,14 +22,15 @@ fi
gosu www-data php artisan storage:link
gosu www-data php artisan horizon:publish
gosu www-data php artisan config:cache
gosu www-data php artisan cache:clear
gosu www-data php artisan route:cache
gosu www-data php artisan view:cache
gosu www-data php artisan config:cache
echo "++++ Check for needed migrations... ++++"
# check for migrations
gosu www-data php artisan migrate:status | grep No && migrations=yes || migrations=no
gosu www-data php artisan migrate:status | grep Pending && migrations=yes || migrations=no
if [ $migrations = "yes" ];
then
gosu www-data php artisan migrate --force
@ -39,4 +41,4 @@ gosu www-data php artisan instance:actor
echo "++++ Start apache... ++++"
source /etc/apache2/envvars
/usr/local/sbin/dumb-init apache2 -DFOREGROUND
dumb-init apache2 -DFOREGROUND

34
hcloud-build.sh Executable file
View File

@ -0,0 +1,34 @@
#!/usr/bin/env bash
hcloud server create --datacenter nbg1-dc3 --image "debian-12" --type cpx41 --ssh-key cg@melpomene --ssh-key jenkins@toolbox --name pixelbuild
pixelbuild_ip=$(hcloud server ip pixelbuild)
ssh_cmd="ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null root@${pixelbuild_ip}"
timeStamp=$(date -I)
$ssh_cmd apt update
$ssh_cmd apt install -y --no-install-recommends buildah qemu-user-static podman
rsync -av -e "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" . root@"${pixelbuild_ip}":zknt-pixelfed
$ssh_cmd buildah login -u "${IO_CRED_USR}" -p "${IO_CRED_PSW}" docker.io
$ssh_cmd buildah login -u "${QUAY_CRED_USR}" -p "${QUAY_CRED_PSW}" quay.io
$ssh_cmd buildah manifest create pixelfed-dev
$ssh_cmd buildah manifest create pixelfed-dev-fpm
$ssh_cmd buildah bud -f Containerfile --build-arg DATE="$timeStamp" --manifest pixelfed-dev --arch amd64
$ssh_cmd buildah bud -f Containerfile --build-arg DATE="$timeStamp" --manifest pixelfed-dev --arch arm64
$ssh_cmd buildah bud -f Containerfile.fpm --build-arg DATE="$timeStamp" --manifest pixelfed-dev-fpm --arch amd64
$ssh_cmd buildah bud -f Containerfile.fpm --build-arg DATE="$timeStamp" --manifest pixelfed-dev-fpm --arch arm64
$ssh_cmd buildah manifest push --all pixelfed-dev docker://quay.io/zknt/pixelfed:dev
$ssh_cmd buildah manifest push --all pixelfed-dev docker://quay.io/zknt/pixelfed:latest
$ssh_cmd buildah manifest push --all pixelfed-dev docker://quay.io/zknt/pixelfed:"$timeStamp"
$ssh_cmd buildah manifest push --all pixelfed-dev-fpm docker://quay.io/zknt/pixelfed:dev-fpm
$ssh_cmd buildah manifest push --all pixelfed-dev-fpm docker://quay.io/zknt/pixelfed:fpm
$ssh_cmd buildah manifest push --all pixelfed-dev-fpm docker://quay.io/zknt/pixelfed:"$timeStamp-fpm"
$ssh_cmd buildah manifest push --all pixelfed-dev docker://docker.io/zknt/pixelfed:dev
$ssh_cmd buildah manifest push --all pixelfed-dev docker://docker.io/zknt/pixelfed:latest
$ssh_cmd buildah manifest push --all pixelfed-dev docker://docker.io/zknt/pixelfed:"$timeStamp"
$ssh_cmd buildah manifest push --all pixelfed-dev-fpm docker://docker.io/zknt/pixelfed:dev-fpm
$ssh_cmd buildah manifest push --all pixelfed-dev-fpm docker://docker.io/zknt/pixelfed:fpm
$ssh_cmd buildah manifest push --all pixelfed-dev-fpm docker://docker.io/zknt/pixelfed:"$timeStamp-fpm"
hcloud server delete pixelbuild

View File

@ -0,0 +1,222 @@
From 624eaa7e48699566497bfe45e8e40ea3285f9cad Mon Sep 17 00:00:00 2001
From: chris <cg@zknt.org>
Date: Sat, 20 Apr 2024 16:19:49 +0200
Subject: [PATCH 1/6] remove IP logging
Replace unneeded logging of IPs and User-Agent strings with hashed data.
---
app/Http/Controllers/Api/ApiV1Dot1Controller.php | 12 ++++++------
app/Http/Controllers/Auth/LoginController.php | 4 ++--
app/Http/Controllers/Auth/RegisterController.php | 2 +-
app/Http/Controllers/CuratedRegisterController.php | 2 +-
app/Http/Controllers/RemoteAuthController.php | 4 ++--
app/Http/Controllers/SeasonalController.php | 4 ++--
app/Http/Controllers/Settings/HomeSettings.php | 8 ++++----
app/Http/Controllers/UserEmailForgotController.php | 4 ++--
app/Listeners/AuthLogin.php | 4 ++--
app/Listeners/LogFailedLogin.php | 4 ++--
10 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/app/Http/Controllers/Api/ApiV1Dot1Controller.php b/app/Http/Controllers/Api/ApiV1Dot1Controller.php
index 6d051866..7c2e0b9d 100644
--- a/app/Http/Controllers/Api/ApiV1Dot1Controller.php
+++ b/app/Http/Controllers/Api/ApiV1Dot1Controller.php
@@ -285,8 +285,8 @@ class ApiV1Dot1Controller extends Controller
$log->action = 'account.edit.password';
$log->message = 'Password changed';
$log->link = null;
- $log->ip_address = $request->ip();
- $log->user_agent = $request->userAgent();
+ $log->ip_address = sha1($request->ip());
+ $log->user_agent = sha1($request->userAgent());
$log->save();
Mail::to($request->user())->send(new PasswordChange($user));
@@ -310,7 +310,7 @@ class ApiV1Dot1Controller extends Controller
abort_if(BouncerService::checkIp($request->ip()), 404);
}
$agent = new Agent();
- $currentIp = $request->ip();
+ $currentIp = sha1($request->ip());
$activity = AccountLog::whereUserId($user->id)
->whereAction('auth.login')
@@ -487,7 +487,7 @@ class ApiV1Dot1Controller extends Controller
abort_if(BouncerService::checkIp($request->ip()), 404);
}
- $rl = RateLimiter::attempt('pf:apiv1.1:iar:'.$request->ip(), config('pixelfed.app_registration_rate_limit_attempts', 3), function(){}, config('pixelfed.app_registration_rate_limit_decay', 1800));
+ $rl = RateLimiter::attempt('pf:apiv1.1:iar:'.sha1($request->ip()), config('pixelfed.app_registration_rate_limit_attempts', 3), function(){}, config('pixelfed.app_registration_rate_limit_decay', 1800));
abort_if(!$rl, 400, 'Too many requests');
$this->validate($request, [
@@ -559,7 +559,7 @@ class ApiV1Dot1Controller extends Controller
$user->email = $email;
$user->password = Hash::make($password);
$user->register_source = 'app';
- $user->app_register_ip = $request->ip();
+ $user->app_register_ip = sha1($request->ip());
$user->app_register_token = Str::random(40);
$user->save();
@@ -616,7 +616,7 @@ class ApiV1Dot1Controller extends Controller
abort_if(BouncerService::checkIp($request->ip()), 404);
}
- $rl = RateLimiter::attempt('pf:apiv1.1:iarc:'.$request->ip(), config('pixelfed.app_registration_confirm_rate_limit_attempts', 20), function(){}, config('pixelfed.app_registration_confirm_rate_limit_decay', 1800));
+ $rl = RateLimiter::attempt('pf:apiv1.1:iarc:'.sha1($request->ip()), config('pixelfed.app_registration_confirm_rate_limit_attempts', 20), function(){}, config('pixelfed.app_registration_confirm_rate_limit_decay', 1800));
abort_if(!$rl, 429, 'Too many requests');
$this->validate($request, [
diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php
index 86ee52c8..3e6a9c4f 100644
--- a/app/Http/Controllers/Auth/LoginController.php
+++ b/app/Http/Controllers/Auth/LoginController.php
@@ -109,8 +109,8 @@ class LoginController extends Controller
$log->action = 'auth.login';
$log->message = 'Account Login';
$log->link = null;
- $log->ip_address = $request->ip();
- $log->user_agent = $request->userAgent();
+ $log->ip_address = sha1($request->ip());
+ $log->user_agent = sha1($request->userAgent());
$log->save();
}
diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php
index 7568fca0..72c8b741 100644
--- a/app/Http/Controllers/Auth/RegisterController.php
+++ b/app/Http/Controllers/Auth/RegisterController.php
@@ -163,7 +163,7 @@ class RegisterController extends Controller
'username' => $data['username'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
- 'app_register_ip' => request()->ip()
+ 'app_register_ip' => sha1(request()->ip())
]);
}
diff --git a/app/Http/Controllers/CuratedRegisterController.php b/app/Http/Controllers/CuratedRegisterController.php
index 58bddb49..83e2e120 100644
--- a/app/Http/Controllers/CuratedRegisterController.php
+++ b/app/Http/Controllers/CuratedRegisterController.php
@@ -389,7 +389,7 @@ class CuratedRegisterController extends Controller
$cr->email = $request->email;
$cr->username = $request->session()->get('cur-reg.form-username');
$cr->password = bcrypt($request->session()->get('cur-reg.form-password'));
- $cr->ip_address = $request->ip();
+ $cr->ip_address = sha1($request->ip());
$cr->reason_to_join = $request->session()->get('cur-reg.form-reason');
$cr->verify_code = Str::random(40);
$cr->save();
diff --git a/app/Http/Controllers/RemoteAuthController.php b/app/Http/Controllers/RemoteAuthController.php
index e0afd82e..7e58eec5 100644
--- a/app/Http/Controllers/RemoteAuthController.php
+++ b/app/Http/Controllers/RemoteAuthController.php
@@ -329,7 +329,7 @@ class RemoteAuthController extends Controller
'webfinger' => $res['_webfinger'],
], [
'software' => 'mastodon',
- 'ip_address' => $request->ip(),
+ 'ip_address' => sha1($request->ip()),
'bearer_token' => $token,
'verify_credentials' => $res,
'last_verify_credentials_at' => now(),
@@ -712,7 +712,7 @@ class RemoteAuthController extends Controller
'email' => $data['email'],
'password' => Hash::make($data['password']),
'email_verified_at' => config('remote-auth.mastodon.contraints.skip_email_verification') ? now() : null,
- 'app_register_ip' => request()->ip(),
+ 'app_register_ip' => sha1(request()->ip()),
'register_source' => 'mastodon',
])));
diff --git a/app/Http/Controllers/SeasonalController.php b/app/Http/Controllers/SeasonalController.php
index a9f1f98c..352eb102 100644
--- a/app/Http/Controllers/SeasonalController.php
+++ b/app/Http/Controllers/SeasonalController.php
@@ -230,8 +230,8 @@ class SeasonalController extends Controller
'action' => 'seasonal.my2020.view'
],
[
- 'ip_address' => $request->ip(),
- 'user_agent' => $request->userAgent()
+ 'ip_address' => sha1($request->ip()),
+ 'user_agent' => sha1($request->userAgent())
]
]);
return response()->json(200);
diff --git a/app/Http/Controllers/Settings/HomeSettings.php b/app/Http/Controllers/Settings/HomeSettings.php
index 99326c09..1434cf66 100644
--- a/app/Http/Controllers/Settings/HomeSettings.php
+++ b/app/Http/Controllers/Settings/HomeSettings.php
@@ -139,8 +139,8 @@ trait HomeSettings
$log->action = 'account.edit.password';
$log->message = 'Password changed';
$log->link = null;
- $log->ip_address = $request->ip();
- $log->user_agent = $request->userAgent();
+ $log->ip_address = sha1($request->ip());
+ $log->user_agent = sha1($request->userAgent());
$log->save();
Mail::to($request->user())->send(new PasswordChange($user));
@@ -186,8 +186,8 @@ trait HomeSettings
$log->action = 'account.edit.email';
$log->message = 'Email changed';
$log->link = null;
- $log->ip_address = $request->ip();
- $log->user_agent = $request->userAgent();
+ $log->ip_address = sha1($request->ip());
+ $log->user_agent = sha1($request->userAgent());
$log->save();
}
diff --git a/app/Http/Controllers/UserEmailForgotController.php b/app/Http/Controllers/UserEmailForgotController.php
index 3889b980..c2622d10 100644
--- a/app/Http/Controllers/UserEmailForgotController.php
+++ b/app/Http/Controllers/UserEmailForgotController.php
@@ -80,8 +80,8 @@ class UserEmailForgotController extends Controller
{
UserEmailForgot::create([
'user_id' => $user->id,
- 'ip_address' => $request->ip(),
- 'user_agent' => $request->userAgent(),
+ 'ip_address' => sha1($request->ip()),
+ 'user_agent' => sha1($request->userAgent()),
'email_sent_at' => now()
]);
diff --git a/app/Listeners/AuthLogin.php b/app/Listeners/AuthLogin.php
index 90806965..90d6591b 100644
--- a/app/Listeners/AuthLogin.php
+++ b/app/Listeners/AuthLogin.php
@@ -122,8 +122,8 @@ class AuthLogin
$device = DB::transaction(function() use($user) {
return UserDevice::firstOrCreate([
'user_id' => $user->id,
- 'ip' => request()->ip(),
- 'user_agent' => str_limit(request()->userAgent(), 180),
+ 'ip' => sha1(request()->ip()),
+ 'user_agent' => sha1(request()->userAgent()),
]);
});
}
diff --git a/app/Listeners/LogFailedLogin.php b/app/Listeners/LogFailedLogin.php
index c6ba3305..eff0cf71 100644
--- a/app/Listeners/LogFailedLogin.php
+++ b/app/Listeners/LogFailedLogin.php
@@ -41,8 +41,8 @@ class LogFailedLogin
$log->action = 'auth.failed';
$log->message = 'Failed login attempt';
$log->link = null;
- $log->ip_address = $request->ip();
- $log->user_agent = $request->userAgent();
+ $log->ip_address = sha1($request->ip());
+ $log->user_agent = sha1($request->userAgent());
$log->save();
}
}
--
2.44.0

View File

@ -0,0 +1,38 @@
From d23c34e13c340d7181306edb85de456d3c3dc8fd Mon Sep 17 00:00:00 2001
From: chris <cg@zknt.org>
Date: Sat, 20 Apr 2024 16:20:10 +0200
Subject: [PATCH 2/6] hardcode discovery settings
force enable discovery (as dynamic settings are not saved properly)
---
app/Http/Controllers/DiscoverController.php | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/app/Http/Controllers/DiscoverController.php b/app/Http/Controllers/DiscoverController.php
index c9e93eec..ffeb34b4 100644
--- a/app/Http/Controllers/DiscoverController.php
+++ b/app/Http/Controllers/DiscoverController.php
@@ -291,16 +291,16 @@ class DiscoverController extends Controller
return [
'hashtags' => [
- 'enabled' => false,
+ 'enabled' => true,
],
'memories' => [
- 'enabled' => false,
+ 'enabled' => true,
],
'insights' => [
- 'enabled' => false,
+ 'enabled' => true,
],
'friends' => [
- 'enabled' => false,
+ 'enabled' => true,
],
'server' => [
'enabled' => false,
--
2.44.0

View File

@ -0,0 +1,46 @@
From 507d1947f4a006edf3b0698ef63a7537be9bf739 Mon Sep 17 00:00:00 2001
From: chris <cg@zknt.org>
Date: Sat, 20 Apr 2024 16:20:26 +0200
Subject: [PATCH 3/6] point to modified sourcecode
as per AGPL license of original source, modifications must be disclosed.
---
.gitattributes | 12 ------------
resources/views/site/opensource.blade.php | 2 +-
2 files changed, 1 insertion(+), 13 deletions(-)
delete mode 100644 .gitattributes
diff --git a/.gitattributes b/.gitattributes
deleted file mode 100644
index 25c1b1b6..00000000
--- a/.gitattributes
+++ /dev/null
@@ -1,12 +0,0 @@
-* text=auto
-*.css linguist-vendored
-*.scss linguist-vendored
-*.js linguist-vendored
-CHANGELOG.md export-ignore
-
-# Collapse diffs for generated files:
-public/**/*.js text -diff
-public/**/*.json text -diff
-public/**/*.css text -diff
-public/img/* binary -diff
-public/fonts/* binary -diff
diff --git a/resources/views/site/opensource.blade.php b/resources/views/site/opensource.blade.php
index cb2e7c77..63645f0c 100644
--- a/resources/views/site/opensource.blade.php
+++ b/resources/views/site/opensource.blade.php
@@ -7,7 +7,7 @@
</div>
<hr>
<section>
- <p class="lead">The software that powers this website is called <a href="https://pixelfed.org">Pixelfed</a> and anyone can <a href="https://github.com/pixelfed/pixelfed">download</a> or <a href="https://github.com/pixelfed/pixelfed">view</a> the source code and run their own instance!</p>
+ <p class="lead">This website runs a modified version of the Pixelfed software, which you can find on <a href="https://git.zknt.org/chris/pixelfed/">Git</a> (original, unmodified software: <a href="https://github.com/pixelfed/pixelfed/">here on Github</a></p>
</section>
@endsection
--
2.44.0

View File

@ -0,0 +1,62 @@
From ff60dcd7310d164900ab6d667a74e0514143eff2 Mon Sep 17 00:00:00 2001
From: chris <cg@zknt.org>
Date: Sat, 20 Apr 2024 16:20:41 +0200
Subject: [PATCH 4/6] disable beagle service
beagle is a remote API service provided by dansup and used for centralised lookups.
Using the beagle service without users explicit consent violates GDPR.
As it's not configurable at the moment this patch disables remote communication with beagle.
---
app/Services/Account/RemoteAuthService.php | 4 ++++
app/Services/Internal/BeagleService.php | 1 +
2 files changed, 5 insertions(+)
diff --git a/app/Services/Account/RemoteAuthService.php b/app/Services/Account/RemoteAuthService.php
index 4412352a..0c69959f 100644
--- a/app/Services/Account/RemoteAuthService.php
+++ b/app/Services/Account/RemoteAuthService.php
@@ -115,11 +115,13 @@ class RemoteAuthService
public static function isDomainCompatible($domain = false)
{
+ return true;
if(!$domain) {
return false;
}
return Cache::remember(self::CACHE_KEY . 'domain-compatible:' . $domain, 14400, function() use($domain) {
+ return true;
try {
$res = Http::timeout(20)->retry(3, 750)->get('https://beagle.pixelfed.net/api/v1/raa/domain?domain=' . $domain);
if(!$res->ok()) {
@@ -144,6 +146,7 @@ class RemoteAuthService
public static function lookupWebfingerUses($wf)
{
+ return 0;
try {
$res = Http::timeout(20)->retry(3, 750)->get('https://beagle.pixelfed.net/api/v1/raa/lookup?webfinger=' . $wf);
if(!$res->ok()) {
@@ -166,6 +169,7 @@ class RemoteAuthService
public static function submitToBeagle($ow, $ou, $dw, $du)
{
+ return;
try {
$url = 'https://beagle.pixelfed.net/api/v1/raa/submit';
$res = Http::throw()->timeout(10)->get($url, [
diff --git a/app/Services/Internal/BeagleService.php b/app/Services/Internal/BeagleService.php
index 60a4f78e..f8c9442c 100644
--- a/app/Services/Internal/BeagleService.php
+++ b/app/Services/Internal/BeagleService.php
@@ -13,6 +13,7 @@ class BeagleService
public static function getDefaultRules()
{
+ return [];
return Cache::remember(self::DEFAULT_RULES_CACHE_KEY, now()->addDays(7), function() {
try {
$res = Http::withOptions(['allow_redirects' => false])
--
2.44.0

View File

@ -0,0 +1,26 @@
From 069e9cbab95d94aa77e7fd6436896a5e3e60b068 Mon Sep 17 00:00:00 2001
From: chris <cg@zknt.org>
Date: Sat, 20 Apr 2024 16:21:03 +0200
Subject: [PATCH 5/6] allow 30 char usernames
raise maximum username length, because why not?
---
app/Http/Controllers/Auth/RegisterController.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php
index 72c8b741..2c8a26b4 100644
--- a/app/Http/Controllers/Auth/RegisterController.php
+++ b/app/Http/Controllers/Auth/RegisterController.php
@@ -70,7 +70,7 @@ class RegisterController extends Controller
$usernameRules = [
'required',
'min:2',
- 'max:15',
+ 'max:30',
'unique:users',
function ($attribute, $value, $fail) {
$dash = substr_count($value, '-');
--
2.44.0

File diff suppressed because one or more lines are too long

3
patches/README.md Normal file
View File

@ -0,0 +1,3 @@
Various patches against [https://github.com/pixelfed/pixelfed](dansups pixelfed).
All patches except for patch 006 (adding legal notice links to the frontpage) are included in my prebuilt images, zknt/pixelfed on docker hub and quay.io.

21
schedule-entrypoint.sh Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -xeo pipefail
php /wait-for-db.php
if [[ ! -e storage/.docker.init ]];
then
echo "Database is not initialized yet, exiting..."
sleep 5
exit 1
fi
gosu www-data php artisan migrate:status | grep No && migrations=yes || migrations=no
if [ $migrations = "yes" ];
then
echo "Database needs migrations, exiting..."
sleep 5
exit 1
fi
gosu www-data php artisan schedule:work

21
websockets-entrypoint.sh Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -xeo pipefail
php /wait-for-db.php
if [[ ! -e storage/.docker.init ]];
then
echo "Database is not initialized yet, exiting..."
sleep 5
exit 1
fi
gosu www-data php artisan migrate:status | grep No && migrations=yes || migrations=no
if [ $migrations = "yes" ];
then
echo "Database needs migrations, exiting..."
sleep 5
exit 1
fi
gosu www-data php artisan websockets:serve