macanhhuy 8493d8b09b
Build + push avatar image / build-and-push (push) Failing after 20s
Add Gitea Actions build workflow and README for vnctalk-avatar
2026-08-22 00:05:04 +07:00
2023-09-17 09:53:25 +02:00
2019-05-07 05:43:10 +02:00
2024-03-04 16:37:16 +01:00
2019-05-06 14:01:43 +02:00
2023-09-17 07:24:58 +02:00
2024-10-16 08:27:54 +02:00
2026-06-13 07:08:13 +02:00
2023-06-28 06:36:13 +02:00
2021-07-09 10:41:27 +00:00
2022-08-17 11:04:35 +02:00

vnctalk-avatar

The VNCtalk avatar service — a small Node/nginx service that preprocesses (GraphicsMagick resize) and serves user avatars. This is the code that backs avatar.vnc.biz; deployed in-cluster it becomes the dev cluster's avatar store.

What it does

On PUT /avatarupload/<jid> it receives raw image bytes, resizes them to a fixed set of resolutions, and writes them to outputDir keyed by md5(jid):

<outputDir>/<md5(jid)>.jpg            # default resolution (80)
<outputDir>/<md5(jid)>-<res>.jpg      # 46, 47, 57, 80, 420, 800

The frontend reads these back via avatarServiceUrl + "/" + md5(jid) + "-<size>.jpg". Prosody's vnc_vcard_avatar module is what PUTs the photo here on every vCard avatar change (avatar_upload_url<avatar-host>/avatarupload/).

API

Method Path Purpose
PUT /avatarupload/:jid Upload avatar bytes (Content-Type: image/*); returns md5(jid).
DELETE /avatarupload/:jid Remove all of a jid's avatar files.
GET /avatarupload/health {"status":"OK"}.
POST /avatarupload/info Batch ctime lookup for a list of md5 ids.

Static image serving (GET /<md5>.jpg) is not handled by app.js — it is served by an nginx that shares the outputDir volume. The container installs nginx but the static-serving server config must be supplied at deploy time (see Deploy below).

Auth

PUT/DELETE require either:

  • the legacy global Basic credentials (avatar / the shared avatar-server password), or
  • a JWT (Bearer/basic-password slot) signed with config.jwtsecret whose vncdomain claim matches the jid's domain.

Open item: both the global Basic credential hash and jwtsecret are hardcoded in app/app.js / config/vnc-avatarservice.js. These are shared service credentials already committed elsewhere (vncdirectory/vncproject). For a clean in-cluster deploy they should move to env vars / Infisical — tracked separately.

Config (config/vnc-avatarservice.js)

Key Default Purpose
servicePort 3896 Node upload API port.
outputDir /var/opt/out Avatar filesystem store (needs a persistent volume).
defaultresolution 80 .jpg (no suffix) resolution.
resolutions [46,47,57,80,420,800] All sizes written on upload.
jwtsecret hardcoded JWT verification secret (move to env).

NODE_ENV selects the config block (development / development2 / gr13).

Build

docker build -t vnctalk-avatar .
# CI: push to main → .gitea/workflows/build.yml → kaniko

Deploy

Not yet declared in vnc-iac-env. Two prerequisites for a working in-cluster deploy (tracked separately):

  1. Persistent outputDir (/var/opt/out) — otherwise avatars are lost on pod restart.
  2. nginx static serving — a server block (or ingress) that serves the outputDir files at avatarServiceUrl, plus the CORS headers the browser needs.

Once deployed, point vnctalk-prosody's avatar_upload_url at it (https://<avatar-host>/avatarupload/) and set avatar_upload_user / avatar_upload_pass (from Infisical AVATAR_PASSWORD, not git).

Layout

Path Purpose
app/app.js Express upload API (PUT /avatarupload/:jid, health, info).
config/vnc-avatarservice.js Env-selected config (port, outputDir, resolutions, jwtsecret).
Dockerfile Alpine multi-stage, non-root (vnc, uid 1001), gm + nginx + node.
Dockerfile.ubuntu Legacy GCP base-image variant (pm2 + deb vnc-avatarservice).
debian/ Legacy Debian packaging (used by the GCP-era image).
conf.template/ Legacy passenger/nginx templates (mostly notification-proxy leftovers).
.gitea/workflows/build.yml kaniko build → vnclagoon/vnctalk-avatar:{sha-…,latest}.
S
Description
VNCtalk avatar service (preprocess + serve user avatars)
Readme
137 KiB
Languages
JavaScript 37.7%
Shell 32%
Groovy 21%
Dockerfile 8.8%
HTML 0.5%