diff --git a/.ci/detect_os_arch_package_format b/.ci/detect_os_arch_package_format index dc76376..6b12647 100755 --- a/.ci/detect_os_arch_package_format +++ b/.ci/detect_os_arch_package_format @@ -4,8 +4,10 @@ package_name = ARGV.first DEB_PACKAGE_REGEX = %r!(?[^/]+)/kasmvncserver_.+?_(?.+?).(?deb)! RPM_PACKAGE_REGEX = %r!(?[^/]+)/kasmvncserver-.+?\.(?[^.]+).(?rpm)! +ALPINE_PACKAGE_REGEX = %r!(?[^/]+)/kasmvncserver-(doc-)?.+?-r\d+_(?[^.]+)\.(?apk)! if matches = package_name.match(DEB_PACKAGE_REGEX) +elsif matches = package_name.match(ALPINE_PACKAGE_REGEX) else matches = package_name.match(RPM_PACKAGE_REGEX) end diff --git a/.ci/upload.sh b/.ci/upload.sh index fc6aeb1..cc51e50 100644 --- a/.ci/upload.sh +++ b/.ci/upload.sh @@ -3,7 +3,7 @@ is_kasmvnc() { local package="$1"; - echo "$package" | grep -qP 'kasmvncserver(_|-)[0-9]' + echo "$package" | grep -qP 'kasmvncserver(_|-)(doc-)?[0-9]' } detect_deb_package_arch() { @@ -27,6 +27,13 @@ fetch_xvnc_md5sum() { cat DEBIAN/md5sums | grep bin/Xkasmvnc | cut -d' ' -f 1 } +detect_alpine_doc_package() { + is_alpine_doc_package= + if [[ $package =~ kasmvncserver-doc ]]; then + is_alpine_doc_package=1 + fi +} + function prepare_upload_filename() { local package="$1"; @@ -44,11 +51,13 @@ function prepare_upload_filename() { REVISION="_${REVISION}" fi + detect_alpine_doc_package + if [ -n "$RELEASE_BRANCH" ]; then - export upload_filename="kasmvncserver_${PACKAGE_OS}_${RELEASE_VERSION}${REVISION}_${OS_ARCH}.${PACKAGE_FORMAT}"; + export upload_filename="kasmvncserver${is_alpine_doc_package:+_doc}_${PACKAGE_OS}_${RELEASE_VERSION}${REVISION}_${OS_ARCH}.${PACKAGE_FORMAT}"; else export SANITIZED_BRANCH="$(echo $CI_COMMIT_REF_NAME | sed 's/\//_/g')"; - export upload_filename="kasmvncserver_${PACKAGE_OS}_${RELEASE_VERSION}_${SANITIZED_BRANCH}_${CI_COMMIT_SHA:0:6}${REVISION}_${OS_ARCH}.${PACKAGE_FORMAT}"; + export upload_filename="kasmvncserver${is_alpine_doc_package:+_doc}_${PACKAGE_OS}_${RELEASE_VERSION}_${SANITIZED_BRANCH}_${CI_COMMIT_SHA:0:6}${REVISION}_${OS_ARCH}.${PACKAGE_FORMAT}"; fi }; diff --git a/.gitignore b/.gitignore index bc7e8b5..35ea059 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,7 @@ debian/kasmvncserver.substvars debian/kasmvncserver/ .pc .vscode/ + +alpine/.abuild/kasmvnc_signing_key.rsa +alpine/.abuild/kasmvnc_signing_key.rsa.pub +alpine/packages/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 93d2610..e234c79 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -711,7 +711,7 @@ upload: - export S3_BUILD_DIRECTORY="kasmvnc/${CI_COMMIT_SHA}" - export RELEASE_VERSION=$(.ci/next_release_version "$CI_COMMIT_REF_NAME") - uploaded_files=() - - for package in `find output/ -type f -name '*.deb' -or -name '*.rpm' -or -name '*.tgz'`; do + - for package in `find output/ -type f -name '*.deb' -or -name '*.rpm' -or -name '*.apk'`; do prepare_upload_filename "$package"; upload_filename="${S3_BUILD_DIRECTORY}/$upload_filename"; echo; diff --git a/alpine/.abuild/abuild.conf b/alpine/.abuild/abuild.conf new file mode 100644 index 0000000..4be7a96 --- /dev/null +++ b/alpine/.abuild/abuild.conf @@ -0,0 +1,2 @@ +PACKAGER="Kasm Technologies LLC " +PACKAGER_PRIVKEY="/src/alpine/.abuild/kasmvnc_signing_key.rsa" diff --git a/alpine/alpine-devenv.dockerfile b/alpine/alpine-devenv.dockerfile new file mode 100644 index 0000000..63e2bff --- /dev/null +++ b/alpine/alpine-devenv.dockerfile @@ -0,0 +1,11 @@ +FROM alpine:3.21 + +RUN apk add abuild sudo less +ENV HOME /src +WORKDIR /src/kasmvncserver + +RUN adduser --disabled-password docker +RUN adduser docker abuild +RUN echo "docker ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers + +USER docker diff --git a/alpine/apk-del-add b/alpine/apk-del-add new file mode 100755 index 0000000..f4840cd --- /dev/null +++ b/alpine/apk-del-add @@ -0,0 +1,8 @@ +#!/bin/sh + +set -e + +sudo apk del kasmvncserver || true +rm -r ../packages +abuild -r || true +sudo apk add ../packages/src/x86_64/kasmvncserver-1.3.3-r0.apk --allow-untrusted diff --git a/alpine/build b/alpine/build new file mode 100755 index 0000000..0658148 --- /dev/null +++ b/alpine/build @@ -0,0 +1 @@ +docker build -f alpine-devenv.dockerfile -t alpine-devenv . diff --git a/alpine/kasmvncserver/APKBUILD b/alpine/kasmvncserver/APKBUILD new file mode 100644 index 0000000..b98d00b --- /dev/null +++ b/alpine/kasmvncserver/APKBUILD @@ -0,0 +1,120 @@ +#!/bin/bash + +# Contributor: +# Maintainer: Kasm Technologies LLC +pkgname=kasmvncserver +pkgver=1.3.3 +pkgrel=0 +pkgdesc="KasmVNC provides remote web-based access to a Desktop or application." +url="https://github.com/kasmtech/KasmVNC" +arch="x86_64 aarch64" +license="GPL-2.0-or-later" +depends=" + bash + libgomp + libjpeg-turbo + libwebp + libxfont2 + libxshmfence + libxtst + mcookie + mesa-gbm + openssl + pciutils-libs + perl + perl-datetime + perl-hash-merge-simple + perl-list-moreutils + perl-switch + perl-try-tiny + perl-yaml-tiny + perl-datetime + perl-datetime-timezone + pixman + py3-xdg + setxkbmap + xauth + xf86-video-amdgpu + xf86-video-ati + xf86-video-nouveau + xkbcomp + xkeyboard-config + xterm + " +if [ $(arch) = x86_64 ]; then + depends="$depends xf86-video-intel" +fi +makedepends=" + rsync + binutils + mesa-gl + libxcursor + gzip + " +checkdepends="" +install="$pkgname.post-install $pkgname.post-deinstall" +subpackages="$pkgname-doc" +source="" +builddir="$srcdir/" + + +build() { + local alpine_version=$(cat /etc/alpine-release | awk -F. '{ print $1$2 }') + tar -xzf "/src/builder/build/kasmvnc.alpine_$alpine_version.tar.gz" -C "$srcdir"; +} + +check() { + # Replace with proper check command(s). + # Remove and add !check option if there is no check command. + : +} + +package() { + export SRC="$srcdir/usr/local"; + export SRC_BIN="$SRC/bin"; + export DESTDIR="$pkgdir"; + + echo "installing files"; + mkdir -p $DESTDIR/usr/bin $DESTDIR/usr/lib \ + $DESTDIR/usr/share/perl5/vendor_perl $DESTDIR/etc/kasmvnc; + cp $SRC_BIN/Xvnc $DESTDIR/usr/bin/Xkasmvnc; + cd $DESTDIR/usr/bin/ && ln -s Xkasmvnc Xvnc; + cp $SRC_BIN/vncserver $DESTDIR/usr/bin/kasmvncserver; + cd $DESTDIR/usr/bin/ && ln -s kasmvncserver vncserver; + cp -r $SRC_BIN/KasmVNC $DESTDIR/usr/share/perl5/vendor_perl; + cp $SRC_BIN/vncconfig $DESTDIR/usr/bin/kasmvncconfig; + cp $SRC_BIN/kasmvncpasswd $DESTDIR/usr/bin/; + cd $DESTDIR/usr/bin/ && ln -s kasmvncpasswd vncpasswd; + cp $SRC_BIN/kasmxproxy $DESTDIR/usr/bin/; + cp -r $SRC/lib/kasmvnc/ $DESTDIR/usr/lib/kasmvncserver; + rsync -r --links --safe-links --exclude '.git*' --exclude po2js \ + --exclude xgettext-html --exclude www/utils/ --exclude .eslintrc \ + $SRC/share/kasmvnc $DESTDIR/usr/share; + sed -i -e 's!pem_certificate: .\+$!pem_certificate: /etc/ssl/private/kasmvnc.pem!' \ + $DESTDIR/usr/share/kasmvnc/kasmvnc_defaults.yaml + sed -i -e 's!pem_key: .\+$!pem_key: /etc/ssl/private/kasmvnc.pem!' \ + $DESTDIR/usr/share/kasmvnc/kasmvnc_defaults.yaml + sed -e 's/^\([^#]\)/# \1/' $SRC/share/kasmvnc/kasmvnc_defaults.yaml > \ + $DESTDIR/etc/kasmvnc/kasmvnc.yaml; +} + +doc() { + set -e + export SRC="$srcdir/usr/local"; + export SRC_BIN="$SRC/bin"; + export DESTDIR="$subpkgdir"; + export DST_MAN="$DESTDIR/usr/share/man/man1"; + + mkdir -p $DESTDIR/usr/share/man/man1 \ + $DESTDIR/usr/share/doc/kasmvncserver + cp -r $SRC/share/doc/kasmvnc*/* $DESTDIR/usr/share/doc/kasmvncserver/ + cp $SRC/man/man1/Xvnc.1 $DESTDIR/usr/share/man/man1/Xkasmvnc.1 + cp $SRC/share/man/man1/vncserver.1 $DST_MAN/kasmvncserver.1 + cp $SRC/share/man/man1/kasmxproxy.1 $DST_MAN/kasmxproxy.1 + cp $SRC/share/man/man1/vncpasswd.1 $DST_MAN/kasmvncpasswd.1 + cp $SRC/share/man/man1/vncconfig.1 $DST_MAN/kasmvncconfig.1 + gzip -9 $DST_MAN/* + cd $DST_MAN && ln -s Xkasmvnc.1.gz Xvnc.1.gz && \ + ln -s kasmvncserver.1.gz vncserver.1.gz && \ + ln -s kasmvncpasswd.1.gz vncpasswd.1.gz +} diff --git a/alpine/kasmvncserver/kasmvncserver.post-deinstall b/alpine/kasmvncserver/kasmvncserver.post-deinstall new file mode 100755 index 0000000..b30760c --- /dev/null +++ b/alpine/kasmvncserver/kasmvncserver.post-deinstall @@ -0,0 +1,3 @@ +#!/bin/sh + +rm -f /etc/ssl/private/kasmvnc.pem diff --git a/alpine/kasmvncserver/kasmvncserver.post-install b/alpine/kasmvncserver/kasmvncserver.post-install new file mode 100755 index 0000000..1d9f546 --- /dev/null +++ b/alpine/kasmvncserver/kasmvncserver.post-install @@ -0,0 +1,26 @@ +#!/bin/bash + +set -e + +kasmvnc_group="kasmvnc-cert" + +create_kasmvnc_group() { + if ! getent group "$kasmvnc_group" >/dev/null; then + addgroup --system "$kasmvnc_group" + fi +} + +make_self_signed_certificate() { + local cert_file=/etc/ssl/private/kasmvnc.pem + [ -f "$cert_file" ] && return 0 + + openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \ + -keyout "$cert_file" \ + -out "$cert_file" -subj \ + "/C=US/ST=VA/L=None/O=None/OU=DoFu/CN=kasm/emailAddress=none@none.none" + chgrp "$kasmvnc_group" "$cert_file" + chmod 640 "$cert_file" +} + +create_kasmvnc_group +make_self_signed_certificate diff --git a/builder/build-apk b/builder/build-apk index 73fa677..8b49160 100755 --- a/builder/build-apk +++ b/builder/build-apk @@ -2,16 +2,35 @@ set -e +copy_signing_key_to_user_abuild_dir() { + docker run --rm -v $PWD/alpine/.abuild:/abuild --user $L_UID:$L_GID \ + $builder_image \ + cp /etc/apk/keys/kasmvnc_signing_key.rsa.pub \ + /etc/apk/keys/kasmvnc_signing_key.rsa /abuild +} + . builder/os_ver_cli.sh cd "$(dirname "$0")/.." -docker build -t kasmvnc_apkbuilder_${os}:${os_codename} -f \ - builder/dockerfile.${os}_${os_codename}.apk.build . - -source_dir=$(echo $PWD) L_UID=$(id -u) L_GID=$(id -g) +ABUILD_GID=300 +if [ "$L_UID" = 0 ]; then + L_UID=1000 + L_GID=1000 +fi + +builder_image=kasmvnc_apkbuilder_${os}:${os_codename} +docker build -t $builder_image \ + --build-arg KASMVNC_ALPINE_PRIVATE_KEY \ + --build-arg KASMVNC_ALPINE_PUBLIC_KEY \ + -f builder/dockerfile.${os}_${os_codename}.apk.build . +copy_signing_key_to_user_abuild_dir + +source_dir=$(echo $PWD) docker run --rm -v "$source_dir":/src --user $L_UID:$L_GID \ + --group-add $ABUILD_GID \ + -e CI \ kasmvnc_apkbuilder_${os}:${os_codename} /bin/bash -c \ '/src/builder/build-apk-inside-docker' diff --git a/builder/build-apk-inside-docker b/builder/build-apk-inside-docker index 08617f7..4d7841b 100755 --- a/builder/build-apk-inside-docker +++ b/builder/build-apk-inside-docker @@ -2,10 +2,27 @@ set -e +add_arch_to_apk_package() { + local package_name="$1" + + new_package_name=$(echo "$package_name" | sed -e 's/\(-r[[:digit:]]\+\)/\1_'$(arch)/) + $sudo_cmd mv "$package_name" "$new_package_name" +} + +add_arch_to_apk_packages() { + for package_name in $(ls *.apk); do + add_arch_to_apk_package "$package_name" + done +} + os=alpine os_codename=$(cat /etc/os-release | awk '/VERSION_ID/' | grep -o '[[:digit:]]' | tr -d '\n' | head -c 3) +apkbuild_dir=/src/alpine/kasmvncserver/ -mkdir -p /src/builder/build/${os}_${os_codename} -mv \ - /src/builder/build/kasmvnc.${os}_${os_codename}.tar.gz \ - /src/builder/build/${os}_${os_codename}/kasmvnc.${os}_${os_codename}_$(uname -m).tgz +cd "$apkbuild_dir" && abuild -r + +[ -n "$CI" ] && sudo_cmd=sudo || sudo_cmd= +$sudo_cmd mkdir -p /src/builder/build/${os}_${os_codename} +( cd /src/alpine/packages/alpine/$(arch)/ && add_arch_to_apk_packages ) +$sudo_cmd mv \ + /src/alpine/packages/alpine/$(arch)/*.apk /src/builder/build/${os}_${os_codename}/ diff --git a/builder/bump-package-version b/builder/bump-package-version index 4e09e42..6f6824e 100755 --- a/builder/bump-package-version +++ b/builder/bump-package-version @@ -7,6 +7,11 @@ update_version_to_meet_packaging_standards() { sed -e 's/\([0-9]\)-\([a-zA-Z]\)/\1~\2/') } +bump_apk() { + builder/bump-package-version-apk "$new_version" +} + + bump_rpm() { builder/bump-package-version-rpm "$new_version" } @@ -33,3 +38,4 @@ update_version_to_meet_packaging_standards bump_xvnc_binary bump_rpm bump_deb +bump_apk diff --git a/builder/bump-package-version-apk b/builder/bump-package-version-apk new file mode 100755 index 0000000..adf77fe --- /dev/null +++ b/builder/bump-package-version-apk @@ -0,0 +1,13 @@ +#!/bin/bash + +set -eo pipefail + +new_version="$1" +spec_file=alpine/kasmvncserver/APKBUILD + +bump_version() { + sed -i "s/^pkgver=.\+/pkgver=$new_version/" "$1" + sed -i "s/^pkgrel=.\+/pkgver=0/" "$1" +} + +bump_version $spec_file diff --git a/builder/dockerfile.alpine_317.apk.build b/builder/dockerfile.alpine_317.apk.build new file mode 100644 index 0000000..c0294c0 --- /dev/null +++ b/builder/dockerfile.alpine_317.apk.build @@ -0,0 +1,19 @@ +FROM alpine:3.17 + +RUN apk add shadow bash +RUN apk add abuild sudo less + +ENV HOME /src/alpine +WORKDIR $HOME/kasmvncserver + +ARG KASMVNC_ALPINE_PRIVATE_KEY +ARG KASMVNC_ALPINE_PUBLIC_KEY + +ENV SCRIPTS_DIR=/tmp/scripts +COPY builder/scripts $SCRIPTS_DIR +RUN $SCRIPTS_DIR/install_alpine_signing_keys + +RUN useradd -m docker && echo "docker:docker" | chpasswd +RUN echo 'docker ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers + +USER docker diff --git a/builder/dockerfile.alpine_318.apk.build b/builder/dockerfile.alpine_318.apk.build index 9504897..f55ac41 100644 --- a/builder/dockerfile.alpine_318.apk.build +++ b/builder/dockerfile.alpine_318.apk.build @@ -1,7 +1,19 @@ FROM alpine:3.18 RUN apk add shadow bash +RUN apk add abuild sudo less + +ENV HOME /src/alpine +WORKDIR $HOME/kasmvncserver + +ARG KASMVNC_ALPINE_PRIVATE_KEY +ARG KASMVNC_ALPINE_PUBLIC_KEY + +ENV SCRIPTS_DIR=/tmp/scripts +COPY builder/scripts $SCRIPTS_DIR +RUN $SCRIPTS_DIR/install_alpine_signing_keys RUN useradd -m docker && echo "docker:docker" | chpasswd +RUN echo 'docker ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers USER docker diff --git a/builder/dockerfile.alpine_319.apk.build b/builder/dockerfile.alpine_319.apk.build index a0930b4..95b6bc6 100644 --- a/builder/dockerfile.alpine_319.apk.build +++ b/builder/dockerfile.alpine_319.apk.build @@ -1,7 +1,19 @@ FROM alpine:3.19 RUN apk add shadow bash +RUN apk add abuild sudo less + +ENV HOME /src/alpine +WORKDIR $HOME/kasmvncserver + +ARG KASMVNC_ALPINE_PRIVATE_KEY +ARG KASMVNC_ALPINE_PUBLIC_KEY + +ENV SCRIPTS_DIR=/tmp/scripts +COPY builder/scripts $SCRIPTS_DIR +RUN $SCRIPTS_DIR/install_alpine_signing_keys RUN useradd -m docker && echo "docker:docker" | chpasswd +RUN echo 'docker ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers USER docker diff --git a/builder/dockerfile.alpine_320.apk.build b/builder/dockerfile.alpine_320.apk.build index d99e67e..8791c8b 100644 --- a/builder/dockerfile.alpine_320.apk.build +++ b/builder/dockerfile.alpine_320.apk.build @@ -1,7 +1,19 @@ FROM alpine:3.20 RUN apk add shadow bash +RUN apk add abuild sudo less + +ENV HOME /src/alpine +WORKDIR $HOME/kasmvncserver + +ARG KASMVNC_ALPINE_PRIVATE_KEY +ARG KASMVNC_ALPINE_PUBLIC_KEY + +ENV SCRIPTS_DIR=/tmp/scripts +COPY builder/scripts $SCRIPTS_DIR +RUN $SCRIPTS_DIR/install_alpine_signing_keys RUN useradd -m docker && echo "docker:docker" | chpasswd +RUN echo 'docker ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers USER docker diff --git a/builder/dockerfile.alpine_321.apk.build b/builder/dockerfile.alpine_321.apk.build index b67ef79..2bc1af0 100644 --- a/builder/dockerfile.alpine_321.apk.build +++ b/builder/dockerfile.alpine_321.apk.build @@ -1,7 +1,19 @@ FROM alpine:3.21 RUN apk add shadow bash +RUN apk add abuild sudo less + +ENV HOME /src/alpine +WORKDIR $HOME/kasmvncserver + +ARG KASMVNC_ALPINE_PRIVATE_KEY +ARG KASMVNC_ALPINE_PUBLIC_KEY + +ENV SCRIPTS_DIR=/tmp/scripts +COPY builder/scripts $SCRIPTS_DIR +RUN $SCRIPTS_DIR/install_alpine_signing_keys RUN useradd -m docker && echo "docker:docker" | chpasswd +RUN echo 'docker ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers USER docker diff --git a/builder/scripts/install_alpine_signing_keys b/builder/scripts/install_alpine_signing_keys new file mode 100755 index 0000000..63c3630 --- /dev/null +++ b/builder/scripts/install_alpine_signing_keys @@ -0,0 +1,30 @@ +#!/bin/bash + +set -e + +install_private_signing_key() { + if echo "$KASMVNC_ALPINE_PRIVATE_KEY" | grep -q -- "$BEGIN_PRIVATE_KEY"; then + echo "$KASMVNC_ALPINE_PRIVATE_KEY" > $APK_KEYS_DIR/kasmvnc_signing_key.rsa + else + echo -e "$BEGIN_PRIVATE_KEY\n$KASMVNC_ALPINE_PRIVATE_KEY\n$END_PRIVATE_KEY" > \ + $APK_KEYS_DIR/kasmvnc_signing_key.rsa + fi +} + +install_public_signing_key() { + if echo "$KASMVNC_ALPINE_PUBLIC_KEY" | grep -q -- "$BEGIN_PUBLIC_KEY"; then \ + echo "$KASMVNC_ALPINE_PUBLIC_KEY" > $APK_KEYS_DIR/kasmvnc_signing_key.rsa.pub + else + echo -e "$BEGIN_PUBLIC_KEY\n$KASMVNC_ALPINE_PUBLIC_KEY\n$END_PUBLIC_KEY" > \ + $APK_KEYS_DIR/kasmvnc_signing_key.rsa.pub + fi +} + +APK_KEYS_DIR=/etc/apk/keys +BEGIN_PRIVATE_KEY='-----BEGIN PRIVATE KEY-----' +END_PRIVATE_KEY='-----END PRIVATE KEY-----' +BEGIN_PUBLIC_KEY='-----BEGIN PUBLIC KEY-----' +END_PUBLIC_KEY='-----END PUBLIC KEY-----' + +install_private_signing_key +install_public_signing_key