Compare commits

...
5 Commits
Author SHA1 Message Date
Bernd-Rodler b01ba5397e chore: retag product images to vnclagoon/* (#2)
Build + push image / build-and-push (push) Successful in 4m48s
2026-08-20 09:19:20 +00:00
macanhhuy 97e6fb83b5 build: migrate CI to Gitea Actions, drop GitLab/Jenkins/GCP
Build + push image / build-and-push (push) Failing after 16s
2026-08-19 19:44:14 +07:00
Stefan-Sanger 9a1d260afe fix: upgrade deprecated nodejs usage
Part-of: <http://gitlab.vnc.biz/uxf/vnc-hybridauth2/-/merge_requests/23>
2026-06-29 11:20:00 +02:00
Stefan-Sanger d4c9b722d2 fix: remove unused deb build stage 2026-06-11 15:03:50 +02:00
marge f7b5a35bee Merge branch 'rootless' into 'master'
fix: upgrade alpine, prepare rootless op

See merge request uxf/vnc-hybridauth2!22
2026-06-11 12:59:48 +00:00
9 changed files with 124 additions and 295 deletions
+10
View File
@@ -0,0 +1,10 @@
.git
.gitlab-ci.yml
Jenkinsfile.deprecated
startgcpdevapi.sh
.gitea
node_modules
scan
debian
tools
*.tgz
+61
View File
@@ -0,0 +1,61 @@
name: Build + push image
on:
push:
branches: [master]
workflow_dispatch:
env:
REGISTRY: gitea.saas.vnc.biz
IMAGE: gitea.saas.vnc.biz/vnclagoon/vnc-hybridauth-api
jobs:
build-and-push:
runs-on: ubuntu-latest
env:
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
steps:
- uses: actions/checkout@v4
- name: Compute image tag
run: |
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-8)
echo "SHORT_SHA=${SHORT_SHA}" >> $GITHUB_ENV
# kaniko builds straight from a Dockerfile and pushes to the registry, running
# as a static binary inside the job container — the runner has no Docker daemon.
- name: Fetch kaniko (daemon-less image builder)
run: |
set -euo pipefail
curl -fsSL -o /tmp/crane.tgz \
https://github.com/google/go-containerregistry/releases/download/v0.21.9/go-containerregistry_Linux_x86_64.tar.gz
tar -xzf /tmp/crane.tgz -C /usr/local/bin crane
mkdir -p /tmp/kaniko-root
crane export gcr.io/kaniko-project/executor:debug /tmp/kaniko-fs.tar
tar -xf /tmp/kaniko-fs.tar -C /tmp/kaniko-root
cp /tmp/kaniko-root/kaniko/executor /usr/local/bin/kaniko-executor
chmod +x /usr/local/bin/kaniko-executor
/usr/local/bin/kaniko-executor version
# kaniko's push auth reads $DOCKER_CONFIG/config.json (go-containerregistry
# authn.DefaultKeychain). Write to both locations and export DOCKER_CONFIG so
# auth is picked up regardless of how $HOME resolves.
- name: Configure registry auth for push
run: |
AUTH=$(printf '%s:%s' "${REGISTRY_USER}" "${REGISTRY_TOKEN}" | base64 -w0)
CFG=$(printf '{"auths":{"%s":{"auth":"%s"}}}' "${REGISTRY}" "${AUTH}")
mkdir -p /kaniko/.docker "$HOME/.docker"
printf '%s' "$CFG" > /kaniko/.docker/config.json
printf '%s' "$CFG" > "$HOME/.docker/config.json"
echo "DOCKER_CONFIG=/kaniko/.docker" >> "$GITHUB_ENV"
# The Dockerfile lives at the repo root; its ADD/COPY paths (app/, package.json,
# yarn.lock, config.js) are relative to the root.
- name: Build + push image
run: |
/usr/local/bin/kaniko-executor \
--context "dir://${GITHUB_WORKSPACE}" \
--dockerfile Dockerfile \
--skip-tls-verify-registry="${REGISTRY}" \
--destination "${IMAGE}:sha-${SHORT_SHA}" \
--destination "${IMAGE}:latest"
-133
View File
@@ -1,133 +0,0 @@
image: docker:20.10.17
variables:
DOCKER_HOST: tcp://localhost:2375
DOCKER_TLS_CERTDIR: ''
DEV_CONTAINER_REGISTRY: eu.gcr.io/vnc-development/vnc-hybridauth-api:development
IMAGE_TAG: eu.gcr.io/vnc-development/vnc-hybridauth-api:development-$CI_COMMIT_SHORT_SHA
IMAGE_TAG_PROD: eu.gcr.io/vnc-dev-275609/vnc-hybridauth-api:production
IMAGE_TAG_STABLE: eu.gcr.io/vnc-stable/vnc-hybridauth-api:stable
services:
- name: docker:20.10.17-dind
alias: docker
stages:
- build_deb
- docker
- scan
- notification
deb:
image: eu.gcr.io/vnc-development/docker-vnc-deb-builder:latest
stage: build_deb
script:
- yarn cache clean
- yarn install
- echo 'Packaging deb'
- ls -la
- git fetch --tags
- makechangelog.uxf > debian/changelog && cat debian/changelog
- sed -n 1p debian/changelog | grep -oP '\(.*?\)' > version.txt
- echo '####################################################'
- cat version.txt
- echo '####################################################'
- rm config/vnc-hybrid-authenticator.js
- cp -P conf.template/vnc-hybridauth2.js config/vnc-hybrid-authenticator.js
- (cd debian; debuild --check-dirname-level 0 --no-tgz-check --no-lintian -us -uc)
- ls -la ../
- scp ../*.deb repo@newpackages.vnc.biz:/srv/repo/apt/incoming/
- ssh repo@newpackages.vnc.biz /srv/repo/bin/import-new-packages.sh
only:
- master
dev_deploy:
before_script:
- until docker info; do sleep 1; done
- base64 -d $SA_Development | docker login -u _json_key --password-stdin https://eu.gcr.io
stage: docker
artifacts:
public: false
expire_in: 12h
paths:
- scan
script:
- docker build -t $IMAGE_TAG .
- docker push $IMAGE_TAG
- docker image save $IMAGE_TAG -o scan/hybridauth.tgz
only:
- master
dev_trivy:
image: eu.gcr.io/vnc-development/docker-vnc-runner:nogsdk
stage: scan
script:
- apt -y update
- apt -y install wget apt-transport-https gnupg lsb-release
- wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | apt-key add -
- echo "deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" >> /etc/apt/sources.list.d/trivy.list
- apt -y update
- apt -y install trivy
- trivy image --input scan/hybridauth.tgz
only:
- master
prod_deploy:
before_script:
- until docker info; do sleep 1; done
- base64 -d $SA_Production | docker login -u _json_key --password-stdin https://eu.gcr.io
stage: docker
script:
- echo $CI_COMMIT_TAG
- COMMIT_VERSION=$(echo $CI_COMMIT_TAG | awk -F'prod-' '{print $2}')
- echo $COMMIT_VERSION
- DEV_TAG=$DEV_CONTAINER_REGISTRY-$COMMIT_VERSION
- echo $DEV_TAG
- docker pull $DEV_TAG
- PROD_IMAGE=$IMAGE_TAG_PROD-$COMMIT_VERSION
- docker tag $DEV_TAG $PROD_IMAGE
- docker push $PROD_IMAGE
rules:
- if: $CI_COMMIT_TAG =~ /^prod-.*/
stable_deploy:
before_script:
- until docker info; do sleep 1; done
- base64 -d $SA_Production | docker login -u _json_key --password-stdin https://eu.gcr.io
stage: docker
script:
- echo $CI_COMMIT_TAG
- COMMIT_VERSION=$(echo $CI_COMMIT_TAG | awk -F'stable-' '{print $2}')
- echo $COMMIT_VERSION
- DEV_TAG=$DEV_CONTAINER_REGISTRY-$COMMIT_VERSION
- echo $DEV_TAG
- docker pull $DEV_TAG
- STABLE_IMAGE=$IMAGE_TAG_STABLE-$COMMIT_VERSION
- docker tag $DEV_TAG $STABLE_IMAGE
- docker push $STABLE_IMAGE
rules:
- if: $CI_COMMIT_TAG =~ /^stable-.*/
successful-results:
image: eu.gcr.io/vnc-development/docker-vnc-deb-builder:latest
stage: notification
script:
- echo "SUCCESS" > result.txt
- ./tools/nagnotify.sh || echo "done"
rules:
- if: '$CI_COMMIT_BRANCH == "master"'
when: on_success
failed-results:
image: eu.gcr.io/vnc-development/docker-vnc-deb-builder:latest
stage: notification
script:
- echo "FAILURE" > result.txt
- ./tools/nagnotify.sh || echo "done"
rules:
- if: '$CI_COMMIT_BRANCH == "master"'
when: on_failure
-90
View File
@@ -1,90 +0,0 @@
#!groovy
pipeline {
agent none
environment {
git_commit_message = ''
git_commit_diff = ''
git_commit_author = ''
git_commit_author_name = ''
git_commit_author_email = ''
ANDROID_HOME = '/opt/android-sdk/'
}
stages {
// --- BUILD ---
stage('Build') {
agent {
label 'vncportal'
}
steps {
parallel(
'frontend': {
node('vncportal') {
deleteDir()
checkout scm
sh 'yarn cache clean'
sh 'yarn install'
sh "tar cfz frontend.tgz node_modules"
stash includes: 'frontend.tgz', name: 'frontend'
deleteDir()
}
},
)
}
}
stage('Packaging') {
agent {
label 'master'
}
steps {
sh "echo 'Packaging'"
deleteDir()
checkout scm
sh "git fetch --tags"
sh "makechangelog.uxf > debian/changelog"
sh "cat debian/changelog"
sh "mkdir src"
sh "sed -n 1p debian/changelog | grep -oP '\\((.*?)\\)' > src/version.txt"
sh "echo '####################################################'"
sh "cat src/version.txt"
sh "echo '####################################################'"
sh 'rm config/vnc-hybrid-authenticator.js'
sh 'cp -P conf.template/vnc-hybridauth2.js config/vnc-hybrid-authenticator.js'
// yarn fails on node4 with kurento stuff
unstash 'frontend'
sh 'tar xfz frontend.tgz'
lock('debianbuild') {
sh "cd debian; debuild --check-dirname-level 0 --no-tgz-check --no-lintian -kjenkins@vnc.biz -p'gpg --no-tty --passphrase q3tx65wurstbrot'; cd .."
}
sh "mkdir -p ../pkgarchive/"
// Import to GCP deb repository
sh "scp ../*.deb repo@34.89.202.54:/srv/repo/apt/incoming/"
sh "ssh repo@34.89.202.54 /srv/repo/bin/import-new-packages.sh"
sh "mv ../*.deb ../pkgarchive/"
sh "rm ../*.dsc"
sh "rm ../*amd64.build"
sh "rm ../*amd64.changes"
}
}
}
post {
always {
emailext (
to: 'stefan.saenger@vnc.biz',
subject: "${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: "Build URL: ${env.BUILD_URL}.",
attachLog: false,
)
}
}
}
+41
View File
@@ -0,0 +1,41 @@
# vnc-hybridauth2 (vnctalk-hybrid-authenticator2)
Hybrid authenticator for VNCtalk / VNCmail. An Express service that sits between the
auth-proxy's `hybridAuthURL` and the directory backends: it authenticates users against
**LDAP** and the **VNCdirectory** PostgreSQL DB, and issues/verifies the XMPP JWT
(`xmppToken`) that Prosody and the mail/talk APIs share for SSO.
Prosody's `mod_auth_http_async` points `hybridaAuthUrl` at this service's HTTP-basic
endpoint (default port `9544`).
## Build & image
Built by Gitea Actions (`.gitea/workflows/deploy.yml`) on every push to `master`, using
kaniko (no Docker daemon on the runner). The image is pushed to the Gitea registry:
- `gitea.saas.vnc.biz/vnclagoon/vnc-hybridauth-api:latest`
- `gitea.saas.vnc.biz/vnclagoon/vnc-hybridauth-api:sha-<short-sha>`
Registry auth uses the `REGISTRY_USER` / `REGISTRY_TOKEN` Actions secrets. The image runs
as the non-root `vncuser` (uid 1001) and starts `node /usr/share/vnctalk-hybrid-authenticator2/app/app.js`.
## Configuration
`config.js` (copied into the image as `config/vnc-hybrid-authenticator.js`) is env-driven;
the `development` profile reads `NODE_ENV`-scoped values from `process.env` (LDAP URI/bind,
Postgres host/port/name/user/pass, `xmppToken`, `domain`). Provide them via the deployment
(ArgoCD in the `vnc-iac-env` GitOps repo), sourced from Infisical — do **not** commit
secrets to this repo.
## Deploy
Deployed by the ArgoCD application in `vnc-iac-env` (the hybrid-auth service that Prosody
and the mail/talk APIs call). This repo has no live deploy manifest; the image tag is pinned
in that GitOps repo.
## Legacy removed
The GitLab CI (`.gitlab-ci.yml`), `Jenkinsfile.deprecated`, and the GCP dev bootstrap
(`startgcpdevapi.sh`) were removed during the GitLab → Gitea migration. The old
`eu.gcr.io/vnc-development/vnc-hybridauth-api` promotion flow (`prod-*` / `stable-*` tags)
is not carried over; the current build pushes a single `master``sha-*` + `latest`.
+2 -2
View File
@@ -435,7 +435,7 @@ app.get('/', async function (req, res) {
if (req.headers.authorization && req.headers.authorization.startsWith("Basic")) {
try {
var b64input = req.headers.authorization.split(" ")[1];
var decodedInput = new Buffer(b64input, 'base64').toString('ascii');
var decodedInput = Buffer.from(b64input, 'base64').toString('ascii');
var username = decodedInput.split(":")[0];
var passwordArray = decodedInput.split(":");
var password = "";
@@ -554,7 +554,7 @@ app.get('/login2fa', async function (req, res) {
if (req.headers.authorization && req.headers.authorization.startsWith("Basic")) {
try {
var b64input = req.headers.authorization.split(" ")[1];
var decodedInput = new Buffer(b64input, 'base64').toString('ascii');
var decodedInput = Buffer.from(b64input, 'base64').toString('ascii');
var username = decodedInput.split(":")[0];
var passwordArray = decodedInput.split(":");
var password = "";
+2 -1
View File
@@ -5,7 +5,7 @@
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "sh startgcpdevapi.sh",
"start": "node app/app.js",
"start:gr13": "NODE_ENV=gr13 node app/app.js"
},
"author": "VNC Software AG",
@@ -27,6 +27,7 @@
},
"resolutions": {
"brace-expansion": "5.0.6",
"form-data": "4.0.6",
"lodash": "4.18.1",
"minimatch": "10.2.4",
"qs": "6.15.2",
-61
View File
@@ -1,61 +0,0 @@
#!/bin/bash
USERNAME=$USER;
RSA_FILE=~/.ssh/id_rsa
if [ -n "$ID_RSA" ]; then
RSA_FILE=$ID_RSA
fi
echo "RSA_FILE = $RSA_FILE"
RSA_FILE=~/.ssh/id_rsa
if [ -n "$ID_RSA" ]; then
RSA_FILE=$ID_RSA
fi
echo "RSA_FILE = $RSA_FILE"
if [ -f ~/.vnc-gcp-user ]; then
echo "found username config..."
USERNAME=$(cat ~/.vnc-gcp-user | grep "^USERNAME" | awk -F "=" '{print $2}');
echo "using username $USERNAME for gcp ssh tunnels"
fi
if [ -S "/tmp/vncddb.sock" ]; then
echo "Socket for vncdirectory database already active - skipping"
else
echo "starting tunnel for vncdirectory db"
ssh -i $RSA_FILE "$USERNAME@10.0.201.44" -o "proxycommand ssh -W %h:%p $USERNAME@34.107.1.238" -f -N -M -S /tmp/vncddb.sock -L 54322:127.0.0.1:5432
sleep 3
fi
echo "starting..."
export NODE_ENV=development
export PORT=8000
node app/app.js 2>&1 | tee -a /tmp/vncha-api.log &
echo "waiting for api service to start..."
sleep 10
osslug=$(uname);
serverup="1";
while [ "$serverup" = 1 ]; do
serverup="0";
if [ "$osslug" = "Linux" ]; then
serverup=$(netstat -nlp 2>/dev/null | grep -c "9544");
fi
if [ "$osslug" = "Darwin" ]; then
serverup=$(netstat -an -ptcp 2>/dev/null | grep LISTEN | grep -c "9544");
fi
sleep 10
done
echo "api service no longer running - closing tunnels"
ssh -S /tmp/vncddb.sock -O exit "$USER@10.0.201.44"
+8 -8
View File
@@ -429,16 +429,16 @@ forever-agent@~0.6.1:
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==
form-data@~4.0.4:
version "4.0.5"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.5.tgz#b49e48858045ff4cbf6b03e1805cebcad3679053"
integrity sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==
form-data@4.0.6, form-data@~4.0.4:
version "4.0.6"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.6.tgz#28e864e1b786dbebb68db1f452f9635278665827"
integrity sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
es-set-tostringtag "^2.1.0"
hasown "^2.0.2"
mime-types "^2.1.12"
hasown "^2.0.4"
mime-types "^2.1.35"
forwarded@0.2.0:
version "0.2.0"
@@ -519,7 +519,7 @@ has-tostringtag@^1.0.2:
dependencies:
has-symbols "^1.0.3"
hasown@^2.0.2:
hasown@^2.0.2, hasown@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.4.tgz#8c62d8cb90beb2aad5d0a5b67581ad9854c3f003"
integrity sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==
@@ -758,7 +758,7 @@ mime-db@1.52.0:
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34:
mime-types@^2.1.35, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34:
version "2.1.35"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==