Compare commits

...
Author SHA1 Message Date
HampusandGitHub bd88c7b04b fix(desktop): don't fail startup on inconclusive native probe (#2114) 2026-08-30 15:22:48 +02:00
HampusandGitHub 03641f622f refactor(voice): flatten participant context menu and extract stream menus (#2112) 2026-08-30 03:02:30 +02:00
HampusandGitHub 3b1eb56713 fix(voice): never auto-select AV1 or HEVC for screen sharing (#2111) 2026-08-30 02:05:21 +02:00
HampusandGitHub 059bcc6c53 chore(app): regenerate theme variable manifest for font fallbacks (#2110) 2026-08-30 01:30:00 +02:00
HampusandGitHub 82043ce2a8 fix(guild): show duplicated role in its final spot without flicker (#2109) 2026-08-30 01:25:34 +02:00
HampusandGitHub 470e752fba chore(i18n): refresh catalogs for role and permission menus (#2108) 2026-08-30 00:17:31 +02:00
HampusandGitHub 3cc7b9050c fix(app): clear stuck spellcheck reload banner (#2107) 2026-08-30 00:12:48 +02:00
HampusandGitHub b1f7c78c7e fix(app): overwrite context menu hover and delete danger item (#2106) 2026-08-30 00:12:41 +02:00
HampusandGitHub 8f20b29b16 feat(guild): duplicate role, plus delete and hover in roles sidebar (#2105) 2026-08-30 00:12:36 +02:00
HampusandGitHub 19efbd3d61 fix(app): scope the show-send-button toggle to the main composer (#2104) 2026-08-30 00:12:31 +02:00
HampusandGitHub f35c0effa2 chore(i18n): drop unused gift redemption string (#2102) 2026-08-29 23:31:28 +02:00
HampusandGitHub 8363cc0844 fix(app): send only the gift link when gifting to a friend (#2101) 2026-08-29 23:29:49 +02:00
HampusandGitHub 5a11cacbae chore(i18n): refresh catalogs for spellcheck copy (#2100) 2026-08-29 23:03:01 +02:00
HampusandGitHub 27151a9487 fix(desktop): restore Linux spellcheck, prefer OS engine (#2099) 2026-08-29 22:58:48 +02:00
HampusandGitHub c152b25deb chore(i18n): refresh catalogs for global shortcut string (#2098) 2026-08-29 22:57:18 +02:00
HampusandGitHub 04d3afaf7b fix(app): default voice shortcuts to global and add a toggle (#2097) 2026-08-29 22:46:30 +02:00
HampusandGitHub dbc63e9ef7 fix(voice): surface stream audio volume for screen-share viewers (#2095) 2026-08-29 22:05:06 +02:00
HampusandGitHub ce91ff95ab fix(app): render raw unicode emoji with OS color emoji fonts (#2094) 2026-08-29 21:09:08 +02:00
HampusandGitHub d75a29f099 feat(app): composer send-button toggle and active button hover (#2093) 2026-08-29 20:25:49 +02:00
HampusandGitHub cb889b1160 fix(api): correct apns clear payload and badge handling (#2092) 2026-08-29 20:07:18 +02:00
HampusandGitHub 8db4f5cb63 feat(app): full-Unicode font fallback with self-hosted Noto (#2091) 2026-08-29 19:27:47 +02:00
HampusandGitHub d297dc5805 feat(api): exempt APP_STORE_REVIEWER accounts from captcha (#2090) 2026-08-29 18:00:52 +02:00
HampusandGitHub 9b8659a40b fix(desktop): stop the updater button flickering after download (#2089) 2026-08-29 17:44:43 +02:00
HampusandGitHub 96c5db3f5d fix(markdown): open code blocks for fences after text (#2088) 2026-08-29 17:32:43 +02:00
HampusandGitHub 78e403819e fix(admin): set delete_message_seconds on ban request (#2087) 2026-08-29 16:35:40 +02:00
HampusandGitHub 805acf4e5e feat(ban): accept delete_message_seconds and app options (#2086) 2026-08-29 16:22:12 +02:00
HampusandGitHub 9f099a9127 fix(api): keep the saved placeholder on sent memes (#2085) 2026-08-29 16:04:58 +02:00
HampusandGitHub 4d15c39cd7 fix(app): give mature media blur the real media dimensions (#2084) 2026-08-29 16:04:55 +02:00
HampusandGitHub 827451d12d fix(unfurl): trust curated klipy media without rescanning (#2083) 2026-08-29 16:04:52 +02:00
HampusandGitHub 03603662c6 fix(media-proxy): require corroborating frames for nsfw (#2082) 2026-08-29 16:04:48 +02:00
HampusandGitHub 34eb10cd88 fix(markdown): only open code fences at line start (#2081) 2026-08-29 15:59:04 +02:00
HampusandGitHub 82941c08c9 fix(api): enforce single-role MFA, fix reindex and NCMEC scans (#2080) 2026-08-29 15:31:42 +02:00
HampusandGitHub 8d21c97d08 fix(admin): sort session imports to satisfy rustfmt (#2079) 2026-08-29 15:05:04 +02:00
HampusandGitHub 71a56f590d fix(ci): read dependent load flags at the pe32+ offset (#2078) 2026-08-29 15:00:38 +02:00
HampusandGitHub 38297c4fe7 chore(api): drop knip-unused search and SSO exports (#2077) 2026-08-29 15:00:09 +02:00
HampusandGitHub cf7ec06d85 fix(api): enforce scoped perms, age gates, audit logs (#2076) 2026-08-29 14:55:13 +02:00
HampusandGitHub f2ea10f951 fix(api): harden ratelimit, SSRF, uploads and DM guards (#2074) 2026-08-29 14:55:09 +02:00
HampusandGitHub bbd93df239 fix(api): expire auth tokens and harden login checks (#2073) 2026-08-29 14:55:04 +02:00
HampusandGitHub 9a6ab93e01 fix(media-proxy): bound GIF decode and BMFF box walking (#2075) 2026-08-29 14:55:00 +02:00
HampusandGitHub 38eed7cce6 fix(gateway): restrict /_metrics to loopback callers (#2072) 2026-08-29 14:54:56 +02:00
HampusandGitHub 79064c3399 fix(admin): sign CSRF tokens and escape them in scripts (#2071) 2026-08-29 14:54:51 +02:00
HampusandGitHub 0496b2f530 fix(ci): reject path traversal in S3 prefix downloads (#2070) 2026-08-29 14:54:37 +02:00
HampusandGitHub 9d0be1ebd1 fix(desktop): drop game capture injection and pin dll search (#2069) 2026-08-29 14:26:28 +02:00
HampusandGitHub 9ad026b8ce fix(app): repair theme CSS sync persistence and data loss (#2067) 2026-08-29 03:37:41 +02:00
HampusandGitHub 14de5971d5 chore(api): drop unused ELEVATED_MFA_PERMISSIONS export (#2066) 2026-08-29 03:12:24 +02:00
HampusandGitHub 5474be3efa fix(api): close auth, billing and authorization bypasses (#2065) 2026-08-29 02:59:38 +02:00
fluxer-ci[bot]andGitHub 9a54bbba2d chore(i18n): update public marketing catalogs (#2064) 2026-08-29 01:52:48 +02:00
fluxer-ci[bot]andGitHub 5a0110ccc8 chore(marketing): advance pointer 0c78170 → 5908507 (#2063) 2026-08-29 01:52:44 +02:00
HampusandGitHub d032d577bf fix(app-proxy): drop leaked canary debug cert from assetlinks (#2062) 2026-08-29 01:43:26 +02:00
HampusandGitHub 243954c9c5 test(api): use a future baseline in invoice-skip premium tests (#2061) 2026-08-29 01:22:29 +02:00
HampusandGitHub ba1be73389 fix(media-proxy): cap ISO-BMFF box walker recursion depth (#2059) 2026-08-29 01:04:46 +02:00
HampusandGitHub af3ad02962 fix(voice): default noise suppression to standard 2026-08-28 20:43:22 +02:00
HampusandGitHub 53ddca725e fix(desktop): deduplicate macOS release feeds (#2056) 2026-08-28 19:16:35 +02:00
HampusandGitHub 094fb0d1c8 feat(downloads): route desktop releases through GitHub 2026-08-28 18:19:08 +02:00
HampusandGitHub dc230926a4 fix(desktop): skip glibc check for directory packs 2026-08-28 15:09:00 +02:00
HampusandGitHub 026ace6747 fix(ci): publish draft releases by ID (#2050) 2026-08-28 00:38:09 +02:00
HampusandGitHub 374db9ed2b fix(desktop): harden capture and release packaging (#2049) 2026-08-27 23:54:38 +02:00
5ee59c4675 chore(i18n): update public marketing catalogs (#2047)
Co-authored-by: Jiralite <[email protected]>
2026-08-27 17:49:52 +01:00
33605171a8 chore(marketing): advance pointer 530c44e → 0c78170 (#2046)
Co-authored-by: Jiralite <[email protected]>
2026-08-27 17:49:38 +01:00
HampusandGitHub 89fac5b088 fix(api): use webhook ID for mention author (#2045) 2026-08-27 17:01:26 +02:00
HampusandGitHub 4a34b942b7 fix(api): key mention chunks by content (#2044) 2026-08-27 16:02:24 +02:00
HampusandGitHub fc3065ebe4 fix(desktop): build with compatible PipeWire headers (#2043) 2026-08-27 15:18:15 +02:00
HampusandGitHub 23493b4ac2 fix(desktop): build libfido2 on Linux runners (#2042) 2026-08-27 14:44:44 +02:00
HampusandGitHub 13344096b7 fix(desktop): keep Linux builds compatible with glibc 2.35 (#2041) 2026-08-27 13:41:08 +02:00
HampusandGitHub a800430997 fix(app): sort interface languages by locale code (#2040) 2026-08-27 13:30:39 +02:00
HampusandGitHub 509562e6da feat(app): delete attachments from the media viewer (#2039) 2026-08-27 13:26:18 +02:00
HampusandGitHub 88d85919f1 fix(app): trim pasted friend tags (#2038) 2026-08-27 13:12:12 +02:00
HampusandGitHub 154e223284 fix(app): keep sticker sizes fixed while resizing the expression picker 2026-08-27 12:59:38 +02:00
HampusandGitHub 58732f7770 fix(api): configure email app base URL separately 2026-08-27 03:26:11 +02:00
HampusandGitHub cb4c847d41 fix(app): separate unread state from unread counts 2026-08-27 02:35:56 +02:00
HampusandGitHub d3976e33f8 fix(app): keep unread channel opens anchored to the divider 2026-08-27 02:02:45 +02:00
HampusandGitHub 8e17970632 fix(app): submit message edits in background 2026-08-26 23:54:28 +02:00
HampusandGitHub c0048504db fix(gifs): bound shard cache memory 2026-08-26 23:22:46 +02:00
HampusandGitHub 5015452280 fix(search): respect scope in channel suggestions 2026-08-26 23:06:07 +02:00
HampusandGitHub c504b68354 fix(api): store administrator user archives separately (#2025) 2026-08-26 21:40:57 +02:00
HampusandGitHub 5d2e5932a4 fix(workspace): stabilise the development stack (#2024) 2026-08-26 18:52:53 +02:00
HampusandGitHub cf1a7d7a8a fix(api): mask Tor blocks as administrator IP bans (#2023) 2026-08-26 16:07:19 +02:00
HampusandGitHub 14a935db81 feat(settings): add mobile camera upload preference 2026-08-26 15:31:53 +02:00
HampusandGitHub f98a40062a fix(markdown): render default-presentation emoji without variation selectors 2026-08-26 14:19:28 +02:00
HampusandGitHub f7ebc1492c fix(app): recover active session after Electron downgrade 2026-08-26 01:33:26 +02:00
HampusandGitHub da3922586a fix(desktop): restore Windows canary builds (#2017) 2026-08-25 23:54:33 +02:00
HampusandGitHub 28184f8d4d chore(desktop): downgrade Electron to 42.10.0 (#2016) 2026-08-25 23:21:20 +02:00
a4e7522ca0 chore(i18n): update public marketing catalogs (#2015)
Co-authored-by: hampus-fluxer <[email protected]>
2026-08-25 21:42:18 +02:00
59b3d30323 chore(marketing): advance pointer 1915e59 → 530c44e (#2014)
Co-authored-by: hampus-fluxer <[email protected]>
2026-08-25 21:41:56 +02:00
HampusandGitHub 53cac0b614 style(markdown): format the escaped emoji branch (#2012) 2026-08-25 14:48:30 +02:00
HampusandGitHub 82c29398d3 fix(markdown): render an escaped raw emoji as a plain glyph (#2011) 2026-08-25 14:24:20 +02:00
HampusandGitHub 6d289e31c7 fix(app): make a backslash before an emoji node keep it literal (#2010) 2026-08-25 14:23:52 +02:00
HampusandGitHub 5ec02c3089 fix(tools): stop the wasm clang test depending on an executable tempfile (#2009) 2026-08-25 14:23:18 +02:00
HampusandGitHub 9940273cd9 docs: drop the release status notices from the readme (#2008) 2026-08-25 14:09:54 +02:00
HampusandGitHub 21c7b9872e fix(app): show composer autocomplete above modal surfaces (#2007) 2026-08-25 13:48:59 +02:00
HampusandGitHub fa99ec6f8f fix(app): keep a backslash-escaped emoji literal in the composer (#2006) 2026-08-25 13:45:53 +02:00
HampusandGitHub 78f7db9250 fix(app): convert pasted and edited unicode emoji in the composer (#2005) 2026-08-25 13:44:26 +02:00
HampusandGitHub c101610c46 fix(markdown): render an escaped emoji shortcode as its raw glyph (#2004) 2026-08-25 13:42:51 +02:00
HampusandGitHub 6d383c7d0a chore(i18n): translate the new bio and resize handle strings (#2003) 2026-08-25 13:07:08 +02:00
HampusandGitHub 2ca756d219 feat(app): give the topic and bio composers channel-aware autocomplete (#2002) 2026-08-25 12:57:18 +02:00
HampusandGitHub 1153327c75 feat(app): follow the newest forward target for mention autocomplete (#2001) 2026-08-25 12:57:06 +02:00
HampusandGitHub 42e45a0e3a fix(app): honour silent and emoticon settings on forward comments (#2000) 2026-08-25 12:56:53 +02:00
HampusandGitHub 9f5a5b16d3 fix(app): resolve custom emoji before gating the edit length (#1999) 2026-08-25 12:56:39 +02:00
HampusandGitHub 44ecd928f0 fix(app): measure emoji inserts by the sent length, not the shortcode (#1998) 2026-08-25 12:56:26 +02:00
HampusandGitHub 3f5c8d8d0a fix(app): move the caret to the line edges on home and end (#1997) 2026-08-25 12:56:13 +02:00
HampusandGitHub e32c5b73a7 fix(app): send default emoji as unicode instead of shortcodes (#1996) 2026-08-25 12:56:01 +02:00
HampusandGitHub 21e806b991 fix(api): keep premium through cancellation and refund pix exactly (#1995) 2026-08-25 00:57:09 +02:00
HampusandGitHub 29e244d4eb chore(deploy): remove the outdated helm charts and cluster manifests (#1994) 2026-08-25 00:19:07 +02:00
HampusandGitHub 0b6edf5690 fix(api): stop exporting the pix refund shortfall constant (#1993) 2026-08-24 23:48:49 +02:00
HampusandGitHub 9af7719d34 chore(i18n): drop the unused obtainium body string from the catalogs (#1992) 2026-08-24 23:40:41 +02:00
HampusandGitHub 9e5b4da954 fix(i18n): correct hebrew, korean and turkish download strings (#1990) 2026-08-24 23:32:09 +02:00
HampusandGitHub b807234806 chore(i18n): translate the new marketing download strings (#1987) 2026-08-24 23:26:07 +02:00
HampusandGitHub 3445b94af3 fix(api): end premium at the real cancellation time and unstick pix refunds (#1985) 2026-08-24 22:43:52 +02:00
HampusandGitHub c226eb7211 perf(repo): parallelise api tests and cache image builds in ghcr (#1984) 2026-08-24 21:24:39 +02:00
HampusandGitHub 3afad20e36 refactor(api): remove the pneumatic post system dm system (#1983) 2026-08-24 19:56:13 +02:00
HampusandGitHub 86497155cd fix(app): keep avatars round in webkit browsers (#1982) 2026-08-24 17:57:19 +02:00
HampusandGitHub af82974c8a fix(api): keep the harvest download route literal for schema generation (#1980) 2026-08-24 14:55:11 +02:00
HampusandGitHub bd4117fa0a feat(api): stream harvest downloads from the configured s3 bucket (#1979) 2026-08-24 14:39:05 +02:00
HampusandGitHub f004685424 fix(repo): make the workspace lint, typecheck and test clean (#1978) 2026-08-24 13:35:22 +02:00
HampusandGitHub b268320406 chore(i18n): re-extract the message catalogs for the new strings (#1977) 2026-08-24 12:56:47 +02:00
HampusandGitHub 7a33b3198a fix(app): stop reprobing image format support on every build (#1976) 2026-08-24 12:56:26 +02:00
HampusandGitHub 66791d3ca2 fix(app): stop fetching a tiny avatar for the large voice tile (#1975) 2026-08-24 12:56:16 +02:00
HampusandGitHub a0d4a33fd4 fix(app): write the first voice session restore snapshot on startup (#1974) 2026-08-24 12:56:04 +02:00
HampusandGitHub fdd12194b1 fix(app): record voice messages in a widely playable container (#1973) 2026-08-24 12:55:53 +02:00
HampusandGitHub bf11445299 fix(app): terminate the voice e2ee worker with the room that owns it (#1972) 2026-08-24 12:55:42 +02:00
HampusandGitHub 61bf8f6ad3 perf(app): load voice background tiles only near the viewport (#1971) 2026-08-24 12:55:32 +02:00
HampusandGitHub 52282bfccf refactor(app): collapse the wrapped voice avatar render branches into one (#1970) 2026-08-24 12:55:22 +02:00
HampusandGitHub cf3a31ac42 perf(app): keep more twemoji urls cached instead of dropping them all (#1969) 2026-08-24 12:55:11 +02:00
HampusandGitHub f56ccf5ef5 fix(app): keep tooltips inside the fullscreen element (#1968) 2026-08-24 12:55:00 +02:00
HampusandGitHub 51e2eee15a fix(app): stop aborting shared uploads when cancelling one attachment (#1967) 2026-08-24 12:54:50 +02:00
HampusandGitHub de97bf908d fix(app): accept tenor links with a regional locale prefix (#1966) 2026-08-24 12:54:39 +02:00
HampusandGitHub 099fb80da2 perf(app): stop double-loading stream previews into the image cache (#1965) 2026-08-24 12:54:29 +02:00
HampusandGitHub 022ccc794d perf(app): render guild stickers only near the modal viewport (#1964) 2026-08-24 12:54:19 +02:00
HampusandGitHub 987768e8dc fix(app): only animate stickers that actually have animation (#1963) 2026-08-24 12:54:08 +02:00
HampusandGitHub a3ffe963c3 fix(app): inherit the parent gap inside stepped carousel panes (#1962) 2026-08-24 12:53:58 +02:00
HampusandGitHub b51562d0e3 fix(app): keep focus and its ring on a spoiler after it is revealed (#1961) 2026-08-24 12:53:47 +02:00
HampusandGitHub 38e86acffe fix(app): let a sound restart immediately after being stopped (#1960) 2026-08-24 12:53:34 +02:00
HampusandGitHub 38a299d852 fix(app): show community avatars in the search user filter (#1959) 2026-08-24 12:53:20 +02:00
HampusandGitHub 55b25c919d fix(app): announce search result counts to screen readers (#1958) 2026-08-24 12:53:10 +02:00
HampusandGitHub 2af4cc98fd feat(app): suggest filters and people while typing search text (#1957) 2026-08-24 12:52:58 +02:00
HampusandGitHub e68b5b8b5a fix(app): stop animations running under reduced motion (#1956) 2026-08-24 12:52:47 +02:00
HampusandGitHub 317b4e26c0 fix(app): stop the pointer hijacking quick switcher selection (#1955) 2026-08-24 12:52:36 +02:00
HampusandGitHub af5bee9149 fix(app): stop refetching profile art when menus appear (#1954) 2026-08-24 12:52:26 +02:00
HampusandGitHub 26939eccce fix(app): let the profile popout banner fill its header (#1953) 2026-08-24 12:52:16 +02:00
HampusandGitHub 54360708d9 fix(app): stop rewriting profile bio emoji urls on hover (#1952) 2026-08-24 12:52:06 +02:00
HampusandGitHub e441c7229c fix(app): version profile badge assets so they refresh (#1951) 2026-08-24 12:51:56 +02:00
HampusandGitHub 54e5fe6ef9 fix(app): stop premium upsell preview emoji from stretching (#1950) 2026-08-24 12:51:45 +02:00
HampusandGitHub 6fc0f1ccd7 fix(app): remove popout stylesheets when the main document drops them (#1949) 2026-08-24 12:51:35 +02:00
HampusandGitHub 6cd30d893a feat(app): let the pinned messages popout be resized (#1948) 2026-08-24 12:51:25 +02:00
HampusandGitHub dceb9061d9 perf(app): recompute picker grid layout in scroll chunks (#1947) 2026-08-24 12:51:13 +02:00
HampusandGitHub 21438b2d8f fix(app): fade the picker thumbhash out instead of fading images in (#1946) 2026-08-24 12:50:59 +02:00
HampusandGitHub 793e853eb3 fix(app): fit media to its real box and gate the zoom buttons (#1945) 2026-08-24 12:50:48 +02:00
HampusandGitHub 9cbe0efbbb fix(app): rank permission override member search by the worker order (#1944) 2026-08-24 12:50:27 +02:00
HampusandGitHub 9219b886fe fix(app): add a quick modal motion preset and settle instant modals (#1943) 2026-08-24 12:50:16 +02:00
HampusandGitHub 2377a4c9d0 fix(app): honour motion settings in the mobile meme picker (#1942) 2026-08-24 12:50:06 +02:00
HampusandGitHub 986c586683 fix(app): show message actions only on keyboard focus (#1941) 2026-08-24 12:49:52 +02:00
HampusandGitHub 7be52fa9fc perf(app): stop redundant member list presence updates (#1940) 2026-08-24 12:49:40 +02:00
HampusandGitHub 32d7ae3eef fix(app): track member list width with a media query (#1939) 2026-08-24 12:49:29 +02:00
HampusandGitHub ef6fb4903f perf(app): redraw the media timestamp only when the second changes (#1938) 2026-08-24 12:49:19 +02:00
HampusandGitHub 0fe3f7523d fix(app): leave fullscreen when the video player unmounts (#1937) 2026-08-24 12:49:08 +02:00
HampusandGitHub 9991534c83 perf(app): reuse parsed markdown across message renders (#1936) 2026-08-24 12:48:57 +02:00
HampusandGitHub 455681b24c fix(app): build settings preview state lazily at first use (#1935) 2026-08-24 12:48:47 +02:00
HampusandGitHub 14e63085dd feat(app): resize the inbox popout from any edge (#1934) 2026-08-24 12:48:36 +02:00
HampusandGitHub e8cb1cefbd fix(app): reject oversized images before cropping an emoji or sticker (#1933) 2026-08-24 12:48:23 +02:00
HampusandGitHub 919e890011 fix(app): show guild initials until the guild icon has painted (#1932) 2026-08-24 12:48:11 +02:00
HampusandGitHub 299172c8aa fix(app): animate guild icons through the shared motion gate (#1931) 2026-08-24 12:47:59 +02:00
HampusandGitHub 6cac93ef39 fix(app): use guild initials for community picker rows (#1930) 2026-08-24 12:47:49 +02:00
HampusandGitHub e5c8ef7d60 perf(app): stop loading the animated guild banner where it is hidden (#1929) 2026-08-24 12:47:37 +02:00
HampusandGitHub d0b4688a6c perf(app): reuse pooled gif videos instead of caching blobs (#1928) 2026-08-24 12:47:13 +02:00
HampusandGitHub e0464ee5be fix(app): pick gif picker previews by format and skip empty sources (#1927) 2026-08-24 12:47:01 +02:00
HampusandGitHub cbcd299bd9 fix(app): keep a child's own data-flx when wrapped in a focus ring (#1926) 2026-08-24 12:46:51 +02:00
HampusandGitHub 1300e5a690 fix(app): refresh favorite gif previews that point at a provider page (#1925) 2026-08-24 12:46:40 +02:00
HampusandGitHub fbd653d8e0 feat(app): resize the expression picker and snap to emoji columns (#1924) 2026-08-24 12:46:30 +02:00
HampusandGitHub eb4f41e80c perf(app): preload picker images through the shared image cache (#1923) 2026-08-24 12:46:19 +02:00
HampusandGitHub 589a01a2da fix(app): load expression grid images only when they scroll into view (#1922) 2026-08-24 12:46:08 +02:00
HampusandGitHub aae6b99761 fix(app): stop the skin tone selector listening while closed (#1921) 2026-08-24 12:45:57 +02:00
HampusandGitHub 5d35047734 fix(app): reserve emoji picker cells while their image loads (#1920) 2026-08-24 12:45:47 +02:00
HampusandGitHub 98d10215d6 fix(app): blur mature embed images and videos (#1919) 2026-08-24 12:45:36 +02:00
HampusandGitHub 6656628bba fix(app): load small list avatars eagerly (#1918) 2026-08-24 12:45:24 +02:00
HampusandGitHub 37f46fc62d fix(app): hide decorative country and region flags from screen readers (#1917) 2026-08-24 12:45:13 +02:00
HampusandGitHub 9efd2b0a73 fix(app): replace the whole +: token when picking a reaction emoji (#1916) 2026-08-24 12:45:02 +02:00
HampusandGitHub b1fb2c14a1 fix(app): keep composer markdown highlighting aligned on long messages (#1915) 2026-08-24 12:44:51 +02:00
HampusandGitHub c5d910425e fix(app): honour the animation setting for composer custom emoji (#1914) 2026-08-24 12:44:40 +02:00
HampusandGitHub 0a9e64d36a fix(app): keep the character counter inside the composer box (#1913) 2026-08-24 12:44:30 +02:00
HampusandGitHub 7d02b7959f fix(app): honour motion settings in composer autocomplete previews (#1912) 2026-08-24 12:44:19 +02:00
HampusandGitHub 0670380360 fix(app): reuse highlighted code instead of flashing plain text (#1911) 2026-08-24 12:44:09 +02:00
HampusandGitHub 904987795a fix(app): let custom branding override the built-in meta description (#1910) 2026-08-24 12:43:58 +02:00
HampusandGitHub 4ee1b2294a fix(app): show a still ban image under reduced motion or data saver (#1909) 2026-08-24 12:43:47 +02:00
HampusandGitHub 97eb84fd46 fix(app): keep avatar stack entries keyed by user across re-renders (#1908) 2026-08-24 12:43:37 +02:00
HampusandGitHub 5eb7822691 fix(app): show cached auth splash art without a fade-in flash (#1907) 2026-08-24 12:43:26 +02:00
HampusandGitHub 79cf57abe4 perf(app): keep gateway and layer manager off the auth session path (#1906) 2026-08-24 12:43:15 +02:00
HampusandGitHub 075bdb5128 fix(app): size auth entity icons to their reserved box (#1905) 2026-08-24 12:43:04 +02:00
HampusandGitHub 65698051ac fix(app): keep paging when the jumped-to message is missing (#1904) 2026-08-24 12:42:54 +02:00
HampusandGitHub 95559f17d8 fix(app): drive the message list window from one load state machine (#1903) 2026-08-24 12:42:42 +02:00
HampusandGitHub aabc13e3cb perf(app): window sticker picker rows by offset instead of observers (#1902) 2026-08-24 12:42:31 +02:00
HampusandGitHub b71ced9b2e fix(app): tell the user when a search query has nothing to search (#1901) 2026-08-24 12:42:20 +02:00
HampusandGitHub bb34c73069 perf(app): load sheet and popout media against their own scrollers (#1900) 2026-08-24 12:42:09 +02:00
HampusandGitHub 94bbbd1021 fix(app): only track hover on reactions that have an animated emoji (#1899) 2026-08-24 12:41:58 +02:00
HampusandGitHub 670a3a970e fix(app): stop pickers re-slicing their grid on first paint (#1898) 2026-08-24 12:41:47 +02:00
HampusandGitHub 7a938c85f6 fix(app): stop rewriting message emoji urls to toggle animation (#1897) 2026-08-24 12:41:36 +02:00
HampusandGitHub 3a6bc4bc7b perf(app): show the message action bar from css not remounting (#1896) 2026-08-24 12:41:24 +02:00
HampusandGitHub c54d7bcc88 perf(app): render member list rows in scroll chunks (#1895) 2026-08-24 12:41:14 +02:00
HampusandGitHub b81bfc80fd fix(app): stop the inbox reshuffling unread channels as you read them (#1894) 2026-08-24 12:41:03 +02:00
HampusandGitHub d8bad50eec perf(app): defer video embed metadata probes until hover (#1893) 2026-08-24 12:40:53 +02:00
HampusandGitHub 3fe6217809 fix(app): keep animated embed images animated (#1892) 2026-08-24 12:40:41 +02:00
HampusandGitHub 50a947a722 fix(app): fade image embed placeholders out instead of images in (#1891) 2026-08-24 12:40:29 +02:00
HampusandGitHub 7fe5aad16e feat(app): suggest recent speakers and stop autocomplete list flicker (#1890) 2026-08-24 12:40:19 +02:00
HampusandGitHub 97d559f749 fix(app): label pending composer attachments for screen readers (#1889) 2026-08-24 12:40:07 +02:00
HampusandGitHub 188f783fae fix(app): request attachment images at their real mosaic tile size (#1888) 2026-08-24 12:39:56 +02:00
HampusandGitHub 3a064dd728 feat(app): render search filters as inline tokens you can type through (#1887) 2026-08-24 12:39:45 +02:00
HampusandGitHub 202856c0f7 feat(app): keep search history per conversation and allow in: in DMs (#1886) 2026-08-24 12:39:34 +02:00
HampusandGitHub 406340fa65 fix(app): open channels at the unread divider and settle jump scrolling (#1885) 2026-08-24 12:39:23 +02:00
HampusandGitHub 735ecc1cca fix(api): distinguish a deleted reply target from no reply (#1884) 2026-08-24 12:39:11 +02:00
HampusandGitHub 7b646f891e fix(app): animate reaction emoji only while hovering them (#1883) 2026-08-24 12:37:48 +02:00
HampusandGitHub 19264d7f81 perf(app): preload reaction menu emoji at the size they render (#1882) 2026-08-24 12:37:38 +02:00
HampusandGitHub 76ce060d13 fix(app): stop the quick switcher list rebuilding while you navigate (#1881) 2026-08-24 12:37:27 +02:00
HampusandGitHub 9b3dc19037 perf(app): load the keyboard mode intro modal only when it is shown (#1880) 2026-08-24 12:37:12 +02:00
HampusandGitHub 5821a68816 fix(app): show the server avatar on message notifications (#1879) 2026-08-24 12:37:01 +02:00
HampusandGitHub e21544eac2 fix(app): order member mention results by search relevance (#1878) 2026-08-24 12:36:50 +02:00
HampusandGitHub 1f0f7d1222 perf(app): play gif embeds from the viewport not a js decoder (#1877) 2026-08-24 12:36:38 +02:00
HampusandGitHub 69e0086144 feat(app): warm full-size media while hovering an attachment (#1876) 2026-08-24 12:36:27 +02:00
HampusandGitHub 61ce8729de fix(app): stop overlaying a sharpening canvas in the media viewer (#1875) 2026-08-24 12:36:15 +02:00
HampusandGitHub 44869b0ce4 fix(app): stop seeking and hidden tabs from stranding playback (#1874) 2026-08-24 12:35:58 +02:00
HampusandGitHub 213dd53ee8 fix(app): size youtube embeds with the shared embed limits (#1873) 2026-08-24 12:35:42 +02:00
HampusandGitHub 844952db51 feat(app): drop the compact attachments media size preference (#1872) 2026-08-24 12:35:28 +02:00
HampusandGitHub eda29c0e34 fix(app): contain embedded media inside its box instead of overflowing (#1871) 2026-08-24 12:35:15 +02:00
HampusandGitHub 5834e32aa5 perf(app): window emoji picker rows by offset instead of observers (#1870) 2026-08-24 12:35:02 +02:00
HampusandGitHub a59f3d0d0c fix(app): animate message emoji only while hovering the message (#1869) 2026-08-24 12:34:52 +02:00
HampusandGitHub 5b8a46d087 fix(app): draw the mention badge cutout from the badge itself (#1868) 2026-08-24 12:34:37 +02:00
HampusandGitHub 677e6e5d6e fix(app): stop animating emoji and stickers that have no animation (#1867) 2026-08-24 12:34:26 +02:00
HampusandGitHub 62f40116be fix(app): stop discovery animating on first render (#1866) 2026-08-24 12:34:15 +02:00
HampusandGitHub d2d199e136 perf(app): fetch text attachment previews only when they scroll near (#1865) 2026-08-24 12:34:04 +02:00
HampusandGitHub 39e2c89d5c fix(app): only animate media that has an animated variant (#1864) 2026-08-24 12:33:53 +02:00
HampusandGitHub 15f4417c68 fix(app): scope near-viewport loading to the surrounding scroller (#1863) 2026-08-24 12:33:39 +02:00
HampusandGitHub 943b948de7 fix(app): keep hydrated state across gateway session resumes (#1862) 2026-08-24 12:33:27 +02:00
HampusandGitHub b7f75e25ad fix(app): keep unsent messages and stop the unread jump on reconnect (#1861) 2026-08-24 12:33:17 +02:00
HampusandGitHub 2af0405317 fix(app): keep the chat scroller pinned to the end while it resizes (#1860) 2026-08-24 12:33:06 +02:00
HampusandGitHub a2099fb0e2 refactor(app): name mute and unread state accessors by intent (#1859) 2026-08-24 12:32:55 +02:00
HampusandGitHub 52781cfa2d refactor(app): drop the unread jump anchor now the scroller finds it (#1858) 2026-08-24 12:32:44 +02:00
HampusandGitHub af7469fa1f fix(app): request custom emoji at one canonical image size (#1857) 2026-08-24 12:32:28 +02:00
HampusandGitHub 4c14ba0a5e fix(app): paint avatars from a real image with a fading placeholder (#1856) 2026-08-24 12:32:14 +02:00
HampusandGitHub b49cf349a8 perf(app): load images immediately instead of queueing four at a time (#1855) 2026-08-24 12:32:02 +02:00
HampusandGitHub 02406925d7 refactor(app): collapse the duplicate emoji shortcode matchers into one (#1854) 2026-08-24 12:31:51 +02:00
HampusandGitHub aad7e1a551 fix(app): freeze embed author and footer icons under motion settings (#1853) 2026-08-24 12:31:40 +02:00
HampusandGitHub a98a9fe6a9 feat(app): understand date words and DM channels in search filters (#1852) 2026-08-24 12:31:29 +02:00
HampusandGitHub ac6fcc8c40 fix(app): close the modal you opened, not whatever is on top (#1851) 2026-08-24 12:31:14 +02:00
HampusandGitHub b0e882645e fix(app): match member search on accents, display names and ids (#1850) 2026-08-24 12:31:02 +02:00
HampusandGitHub 8c431c7562 fix(app): retry hydrating message authors after a reconnect (#1849) 2026-08-24 12:30:50 +02:00
HampusandGitHub 3e267b8104 fix(app): keep the member list in sync when switching channels (#1848) 2026-08-24 12:30:38 +02:00
HampusandGitHub 7c5cab2144 fix(app): make the media volume slider track loudness (#1847) 2026-08-24 12:30:13 +02:00
HampusandGitHub 5cb893245f fix(app): hide the video controls again after a few idle seconds (#1846) 2026-08-24 12:30:01 +02:00
HampusandGitHub aa1c636cc2 fix(app): keep local image previews from disappearing before upload (#1845) 2026-08-24 12:29:49 +02:00
HampusandGitHub c285854b71 refactor(app): rename ComponentDispatch to ComponentBus (#1844) 2026-08-24 12:29:38 +02:00
HampusandGitHub 01a29d629b fix(app): size the chat skeleton from the remembered viewport height (#1843) 2026-08-24 12:29:26 +02:00
HampusandGitHub bd381ccc74 fix(app): request avatar and banner sizes the media proxy serves (#1842) 2026-08-24 12:29:16 +02:00
HampusandGitHub c3e747aaa4 fix(media-proxy): stop re-encoding jpeg and video frames losslessly (#1841) 2026-08-24 12:29:05 +02:00
HampusandGitHub 480d56125d fix(admin): render sticker previews at 320px instead of 160px (#1840) 2026-08-24 12:28:54 +02:00
HampusandGitHub 7ec155eac1 fix(desktop): stop reading whole voice backgrounds to classify them (#1839) 2026-08-24 12:28:43 +02:00
HampusandGitHub c8ff177f85 fix(unfurl): cache empty results briefly and key entries by provider (#1838) 2026-08-24 12:28:32 +02:00
HampusandGitHub f276bb1cd2 perf(app): stop the service worker caching static assets (#1837) 2026-08-24 12:28:21 +02:00
HampusandGitHub 208632e648 fix(common): stop advertising static assets as immutable (#1836) 2026-08-24 12:28:10 +02:00
HampusandGitHub 8cfac127f5 fix(media-proxy): stop proxy paths carrying fragments or credentials (#1835) 2026-08-24 12:27:58 +02:00
HampusandGitHub ac76bee5a3 fix(media-proxy): clamp the webp effort override to the encoder maximum (#1834) 2026-08-24 12:27:46 +02:00
HampusandGitHub 171dc7e5b7 fix(media-proxy): serve and request images on one size ladder (#1833) 2026-08-24 12:27:33 +02:00
HampusandGitHub 051985b767 fix(media-proxy): stop marking cached media immutable (#1832) 2026-08-24 12:27:21 +02:00
HampusandGitHub 1eb85410bf fix(common): keep the text after a block spoiler's closing pipes (#1831) 2026-08-24 12:27:08 +02:00
HampusandGitHub 6697db7cf8 build(app): minify css with lightningcss in production builds (#1830) 2026-08-24 12:26:55 +02:00
HampusandGitHub 56f6009390 feat(gifs): serve every medium, tiny and nano variant klipy offers (#1829) 2026-08-24 12:26:44 +02:00
HampusandGitHub d339b82f8e fix(api): give desktop downloads a lifetime that follows the key (#1828) 2026-08-24 12:26:33 +02:00
HampusandGitHub 82eb87bc47 perf(app-proxy): preconnect the media origin and revalidate the app shell (#1827) 2026-08-24 12:26:21 +02:00
HampusandGitHub 991be1c5a2 fix(api): log every error once and keep the cause chain (#1826) 2026-08-24 12:11:42 +02:00
HampusandGitHub 0d96a4574a fix(api): read the log level and environment from the process env (#1824) 2026-08-23 21:44:32 +02:00
HampusandGitHub 61b4511ae4 fix(schema): group category channels text before voice when ordering (#1823) 2026-08-23 17:49:26 +02:00
HampusandGitHub 137edc7cfb fix(app): share stream audio by default and reset the opt-out per stream (#1819) 2026-08-22 10:14:45 +02:00
HampusandGitHub 14e772a751 fix(api): serialise elapsed temp bans as null for the admin panel (#1817) 2026-08-21 20:34:43 +02:00
HampusandGitHub 32afbf12d6 fix(api): stop treating accounts pending deletion as already deleted (#1816) 2026-08-21 20:31:32 +02:00
HampusandGitHub ffaf5119d8 fix(app): only warn about software encoding when no layer is accelerated (#1815) 2026-08-21 18:49:51 +02:00
HampusandGitHub 10bc8c1efa fix(desktop): stop the windows audio probe timing out against its own budget (#1814) 2026-08-21 17:29:12 +02:00
HampusandGitHub 85a03a9e39 fix(app): apply the screen share audio toggle to the surface being shared (#1813) 2026-08-21 17:04:22 +02:00
51ee6567b4 chore(i18n): update public marketing catalogs (#1812)
Co-authored-by: hampus-fluxer <[email protected]>
2026-08-21 16:31:01 +02:00
090220a29d chore(marketing): advance pointer f39eced → 02e3a2c (#1811)
Co-authored-by: hampus-fluxer <[email protected]>
2026-08-21 16:30:54 +02:00
HampusandGitHub e7973b8be0 fix(api): derive voice reconciliation candidate ttl from real sweep spacing (#1810) 2026-08-21 15:49:50 +02:00
HampusandGitHub b5324c9223 perf(gateway): stop materializing all members on the guild connect path (#1809) 2026-08-21 14:00:19 +02:00
HampusandGitHub edb8d80077 ci: source the s3 provider for downloads and static from repo variables (#1803) 2026-08-20 21:46:26 +02:00
HampusandGitHub ddee116339 feat(api): route downloads through the configured downloads provider (#1802) 2026-08-20 21:44:53 +02:00
HampusandGitHub bdacaea4a8 feat(config): add an optional separate s3 provider for downloads (#1801) 2026-08-20 21:34:19 +02:00
HampusandGitHub 9e28e02b5d ci(rust): pin the floating toolchains to the version images build with (#1800) 2026-08-20 21:27:12 +02:00
HampusandGitHub 3527dc95a2 fix(rust): silence result_large_err on axum response error paths (#1799) 2026-08-20 21:18:18 +02:00
HampusandGitHub 27c7b2722d chore(admin): regenerate openapi schemas for the admin acl cap (#1798) 2026-08-20 21:17:04 +02:00
HampusandGitHub ba96f52ed6 fix(schema): allow assigning every admin ACL to a user (#1797) 2026-08-20 21:09:56 +02:00
HampusandGitHub 2c8b3ff45c fix(build): build the messages and users images with scylla support (#1796) 2026-08-20 20:30:16 +02:00
HampusandGitHub 631bc2307a fix(slowmode): stop the local cooldown from outgrowing the channel setting (#1795) 2026-08-20 19:56:02 +02:00
HampusandGitHub 8f4f9a8601 refactor(media): share one external proxy url codec across every service (#1794) 2026-08-20 19:55:40 +02:00
HampusandGitHub 1c920f966e feat(media): emit external proxy urls with a readable path and extension (#1793) 2026-08-20 18:44:45 +02:00
HampusandGitHub 2b1de38949 chore(i18n): regenerate catalogs after the voice engine removal (#1791) 2026-08-20 17:45:49 +02:00
HampusandGitHub d5daf61dbd fix(voice): recalibrate stored participant and stream volumes too (#1790) 2026-08-20 17:45:17 +02:00
HampusandGitHub 06c42ce02f refactor(desktop): delete the unused rust voice module (#1789) 2026-08-20 17:44:55 +02:00
HampusandGitHub 4f21430880 refactor(voice): drop the native only surface from voice_engine_v2 and narrow the desktop bridge (#1788) 2026-08-20 17:44:37 +02:00
HampusandGitHub 9731bac40f refactor(voice): remove the native voice engine from the renderer (#1787) 2026-08-20 17:43:38 +02:00
HampusandGitHub b144e650f2 fix(voice): make deafen reach watched screen share audio (#1786) 2026-08-20 17:43:19 +02:00
HampusandGitHub ef6536644c fix(voice): stop the in call speaker slider clamping a boosted output volume (#1785) 2026-08-20 17:42:59 +02:00
HampusandGitHub 17eab43245 fix(voice): retune the remote playback leveller and measure it in float (#1784) 2026-08-20 17:42:40 +02:00
HampusandGitHub fbd7f1e3b8 fix(voice): compose participant gain in linear space and split the ceilings (#1783) 2026-08-20 17:42:21 +02:00
HampusandGitHub 25af7516a4 fix(voice): widen the volume boost leg and add a master soft clip limiter (#1782) 2026-08-20 17:42:02 +02:00
HampusandGitHub c020eded31 fix(voice): stop forcing automatic gain control off on every capture profile (#1781) 2026-08-20 17:41:44 +02:00
HampusandGitHub 5331c0216a fix(voice): keep a remote track pinned at zero volume across re-attach (#1780) 2026-08-20 17:40:53 +02:00
HampusandGitHub 528777926c fix(api): stop one unreachable community from breaking bookmarks (#1779) 2026-08-20 15:50:51 +02:00
HampusandGitHub 47b5c3d4f0 fix(app): expose the guild id on guild list items again (#1778) 2026-08-20 14:39:24 +02:00
HampusandGitHub d9bfca66d6 fix(app): keep search results in server order instead of per channel (#1777) 2026-08-20 13:10:47 +02:00
HampusandGitHub ded51b65d3 fix(app): restore the mobile voice message recorder (#1776) 2026-08-20 04:33:24 +02:00
HampusandGitHub ddc8837d4f fix(app): scale embed and attachment width caps with zoom (#1775) 2026-08-20 04:33:17 +02:00
HampusandGitHub df16957c95 fix(app): scale tooltip max-width with app zoom (#1774) 2026-08-20 04:33:10 +02:00
HampusandGitHub f38b19d4bd fix(app): let the caret move past emoji and mentions in the composer (#1768) 2026-08-19 23:41:05 +02:00
HampusandGitHub f7cd4f2c74 docs(operator): explain how to reclaim space after upgrades (#1767) 2026-08-19 23:31:15 +02:00
a078392888 chore(i18n): update public marketing catalogs (#1719)
Co-authored-by: hampus-fluxer <[email protected]>
2026-08-19 22:46:33 +02:00
HampusandGitHub 3060f23f8c chore(marketing): bump the marketing submodule pointer (#1766) 2026-08-19 22:29:10 +02:00
HampusandGitHub 6a5f0d4d29 fix(i18n): simplify the marketing translation and saved media strings (#1764) 2026-08-19 22:25:01 +02:00
HampusandGitHub 91d989dc7c fix(app): point the language notice at Weblate instead of email (#1763) 2026-08-19 22:05:39 +02:00
HampusandGitHub 7c82804df6 fix(app): stop sensitive content options overlapping in long locales (#1762) 2026-08-19 19:53:46 +02:00
HampusandGitHub b7de83f7fc fix(app): stop the Firefox microphone failure and self-mute storm (#1761) 2026-08-19 19:32:41 +02:00
HampusandGitHub 97bd022bee fix(app): render the discovery language icon at bold weight (#1760) 2026-08-19 19:08:48 +02:00
HampusandGitHub 62324df039 feat(app): add a language filter button to the discovery navbar (#1759) 2026-08-19 18:46:39 +02:00
HampusandGitHub 9f78b3d9a6 feat(app): retry failed image loads with escalating delay and connectivity waits (#1758) 2026-08-19 18:25:34 +02:00
HampusandGitHub 362a89f2b2 fix(app): keep embed icons mounted so they reserve space while loading (#1757) 2026-08-19 18:00:08 +02:00
HampusandGitHub ce41960fcd perf(app): load embed author and footer icons through the image cache (#1756) 2026-08-19 17:38:00 +02:00
HampusandGitHub 2083eaddd6 feat(app): wrap pasted links in every composer that allows masked links (#1755) 2026-08-19 17:19:39 +02:00
HampusandGitHub d398ebc44b test: drop desktop test files that no runner executes (#1753) 2026-08-19 14:58:59 +02:00
HampusandGitHub 59887ad404 fix(app): wrap pasted links from any source, not just Fluxer's own clipboard (#1752) 2026-08-19 14:57:13 +02:00
HampusandGitHub 5aa283e8e0 fix(desktop): repair a stale Linux .desktop entry instead of preserving it (#1751) 2026-08-19 14:56:29 +02:00
HampusandGitHub d9ed256a4b fix(desktop): pin Electron to 43.4.0 to restore KDE and XFCE tray icons (#1750) 2026-08-19 14:45:58 +02:00
HampusandGitHub a297f89b83 fix(markdown): parse a table that follows a text line without a blank line (#1749) 2026-08-19 14:24:33 +02:00
HampusandGitHub 4a16921242 fix(app): stop macOS window chrome from swallowing clicks below the titlebar (#1748) 2026-08-19 13:05:42 +02:00
HampusandGitHub a6f83c4fb1 feat(app): wrap the selection in a link when pasting a URL (#1747) 2026-08-19 12:55:15 +02:00
HampusandGitHub 7b5c82c6cf fix(app): keep quick switcher focus when results are recomputed (#1746) 2026-08-19 12:55:04 +02:00
HampusandGitHub 30a61ce90f chore(i18n): refresh catalogs and translate new strings (#1745) 2026-08-19 12:46:51 +02:00
HampusandGitHub 22bc2cab74 fix(app): offset toasts below the window chrome on macOS (#1744) 2026-08-19 12:42:08 +02:00
HampusandGitHub 53df9a0d6d fix(app): include remainder seconds in slowmode durations (#1743) 2026-08-19 12:41:56 +02:00
HampusandGitHub f9b7ec4d0b fix(app): stop the bio editor placeholder from overflowing (#1742) 2026-08-19 12:41:44 +02:00
HampusandGitHub 569abf57b7 fix(app): keep the edited marker on attachment-only messages (#1741) 2026-08-19 12:41:31 +02:00
HampusandGitHub ae8e32d809 fix(app): render modals above a fullscreen voice call (#1740) 2026-08-19 12:41:19 +02:00
HampusandGitHub a81b1abec7 fix(api): reject alt text edits on forwarded messages (#1739) 2026-08-19 12:41:07 +02:00
HampusandGitHub 8836565c32 fix(app): keep the guild verification timer stable across switches (#1738) 2026-08-19 12:40:55 +02:00
HampusandGitHub a1b595d52f fix(app): apply the current system theme when relaunching (#1737) 2026-08-19 12:40:43 +02:00
HampusandGitHub abb71ed558 fix(app): prompt for a restart when the system titlebar toggle changes (#1736) 2026-08-19 12:40:32 +02:00
HampusandGitHub c006d413ac fix(desktop): bump Electron to 43.4.1 to restore the Linux tray icon (#1735) 2026-08-19 12:40:20 +02:00
HampusandGitHub fa11acae15 fix(desktop): use the masked icon for AppImage desktop integration (#1734) 2026-08-19 12:40:09 +02:00
HampusandGitHub 300f467ad0 fix(desktop): stop the AppImage adding a duplicate menu entry each launch (#1733) 2026-08-19 12:39:57 +02:00
1436 changed files with 81418 additions and 100815 deletions
+10 -32
View File
@@ -7,7 +7,6 @@ ARG USER_UID=1000
ARG USER_GID=1000
ARG NODE_MAJOR=24
ARG ELP_VERSION=2026-02-27
ARG HELM_VERSION=4.2.0
ARG PNPM_VERSION=10.29.3
ARG WASM_BINDGEN_VERSION=0.2.122
@@ -15,8 +14,8 @@ ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
acl \
bash \
brotli \
build-essential \
ca-certificates \
clang \
@@ -42,13 +41,13 @@ RUN apt-get update \
libfido2-dev \
libgbm1 \
libgtk-3-0 \
libimage-exiftool-perl \
libnotify4 \
libnss3 \
libpipewire-0.3-dev \
libpulse-dev \
libsecret-1-0 \
libudev-dev \
libuv1-dev \
libcurl4-openssl-dev \
libswresample-dev \
libswscale-dev \
@@ -71,14 +70,12 @@ RUN apt-get update \
ninja-build \
openssh-client \
pkg-config \
protobuf-compiler \
python3 \
python3-pip \
rsync \
python3-venv \
sudo \
rpm \
unzip \
webp \
xz-utils \
xdg-utils \
zstd \
@@ -90,6 +87,7 @@ RUN apt-get update \
bat \
btop \
docker-cli \
docker-compose \
dnsutils \
fd-find \
gdb \
@@ -122,24 +120,12 @@ RUN apt-get update \
&& ln -sf /usr/bin/batcat /usr/local/bin/bat \
&& rm -rf /var/lib/apt/lists/*
RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_MAJOR}.x | bash - \
RUN curl --retry 5 --retry-delay 2 --retry-all-errors -fsSL https://deb.nodesource.com/setup_${NODE_MAJOR}.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& rm -rf /var/lib/apt/lists/* \
&& corepack enable
RUN ARCH="$(dpkg --print-architecture)" \
&& case "$ARCH" in \
amd64) HELM_ARCH="amd64" ;; \
arm64) HELM_ARCH="arm64" ;; \
*) echo "Unsupported architecture for Helm: $ARCH" >&2; exit 1 ;; \
esac \
&& curl -fsSL "https://get.helm.sh/helm-v${HELM_VERSION}-linux-${HELM_ARCH}.tar.gz" -o /tmp/helm.tgz \
&& tar -C /tmp -xzf /tmp/helm.tgz "linux-${HELM_ARCH}/helm" \
&& mv "/tmp/linux-${HELM_ARCH}/helm" /usr/local/bin/helm \
&& chmod +x /usr/local/bin/helm \
&& rm -rf /tmp/helm.tgz "/tmp/linux-${HELM_ARCH}"
RUN python3 -m pip install --break-system-packages --no-cache-dir awscli cqlsh
RUN python3 -m pip install --break-system-packages --no-cache-dir awscli
COPY tools/fonts/requirements.txt /tmp/fluxer-fonts-requirements.txt
RUN python3 -m pip install --break-system-packages --no-cache-dir -r /tmp/fluxer-fonts-requirements.txt \
@@ -147,18 +133,13 @@ RUN python3 -m pip install --break-system-packages --no-cache-dir -r /tmp/fluxer
&& pyftsubset --help >/dev/null \
&& python3 -c "import fontTools, brotli"
RUN if ! command -v rebar3 >/dev/null 2>&1; then \
curl -fsSL https://s3.amazonaws.com/rebar3/rebar3 -o /usr/local/bin/rebar3 \
&& chmod +x /usr/local/bin/rebar3; \
fi
RUN ARCH="$(dpkg --print-architecture)" \
&& case "$ARCH" in \
amd64) ELP_ARCH="x86_64" ;; \
arm64) ELP_ARCH="aarch64" ;; \
*) echo "Unsupported architecture for ELP: $ARCH" >&2; exit 1 ;; \
esac \
&& curl -fsSL "https://github.com/WhatsApp/erlang-language-platform/releases/download/${ELP_VERSION}/elp-linux-${ELP_ARCH}-unknown-linux-gnu-otp-28.tar.gz" -o /tmp/elp.tgz \
&& curl --retry 5 --retry-delay 2 --retry-all-errors -fsSL "https://github.com/WhatsApp/erlang-language-platform/releases/download/${ELP_VERSION}/elp-linux-${ELP_ARCH}-unknown-linux-gnu-otp-28.tar.gz" -o /tmp/elp.tgz \
&& tar -C /usr/local/bin -xzf /tmp/elp.tgz elp \
&& chmod +x /usr/local/bin/elp \
&& rm /tmp/elp.tgz
@@ -179,16 +160,13 @@ ENV DOCKER_HOST="unix:///var/run/docker.sock" \
ENV CC_wasm32_unknown_unknown="clang" \
AR_wasm32_unknown_unknown="llvm-ar"
RUN curl -fsSL https://sh.rustup.rs | sh -s -- -y --profile default --component clippy,rustfmt \
RUN curl --retry 5 --retry-delay 2 --retry-all-errors -fsSL https://sh.rustup.rs | sh -s -- -y --profile minimal --component clippy,rustfmt \
&& rustup target add wasm32-unknown-unknown \
&& cargo install cargo-watch --locked \
&& cargo install wasm-bindgen-cli --version "${WASM_BINDGEN_VERSION}" --locked
&& cargo install wasm-bindgen-cli --version "${WASM_BINDGEN_VERSION}" --locked \
&& rm -rf "/home/${USERNAME}/.cargo/registry" "/home/${USERNAME}/.cargo/git"
RUN corepack prepare "pnpm@${PNPM_VERSION}" --activate \
&& pnpm --version
RUN sudo apt-get update \
&& sudo apt-get install -y --no-install-recommends python3-venv \
&& sudo rm -rf /var/lib/apt/lists/*
WORKDIR /workspaces/fluxer
+11 -35
View File
@@ -5,20 +5,17 @@
"workspaceFolder": "/workspaces/fluxer",
"shutdownAction": "stopCompose",
"remoteUser": "vscode",
"hostRequirements": {
"cpus": 4,
"memory": "8gb",
"storage": "32gb"
},
"remoteEnv": {
"DOCKER_HOST": "unix:///var/run/docker.sock"
},
"runServices": ["workspace", "postgres", "valkey", "nats", "livekit", "meilisearch", "mailpit"],
"forwardPorts": [
3000, 8088, 8080, 8771, 8082, 3010, 3020, 8100, 8101, 8102, 8103, 8104, 8105, 8106, 8107, 8108, 8109, 8110, 8111,
8112, 8113, 8114, 8115, 8116, 8117, 8118, 8119, 8120, 8121, 8122, 8123, 8124, 8125, 3900, 8888, 9333, 9340, 23646,
4222, 7700, 7880, 7900, 9200, 8000
],
"forwardPorts": [3000, 8088, 8080, 8771, 8082, 8773, 3010, 3020, 8333],
"portsAttributes": {
"8000": {
"label": "Zensical docs",
"onAutoForward": "openBrowserOnce"
},
"8088": {
"label": "Fluxer dev proxy",
"onAutoForward": "notify"
@@ -29,36 +26,15 @@
"3020": {
"label": "Fluxer admin"
},
"8100": {
"label": "Fluxer Rust service health"
},
"3900": {
"8333": {
"label": "SeaweedFS S3"
},
"8888": {
"label": "SeaweedFS filer"
},
"9333": {
"label": "SeaweedFS master"
},
"9340": {
"label": "SeaweedFS volume"
},
"23646": {
"label": "SeaweedFS admin"
},
"7880": {
"label": "LiveKit"
},
"7700": {
"label": "Meilisearch"
},
"9200": {
"label": "Elasticsearch"
"8773": {
"label": "Fluxer app proxy"
}
},
"postCreateCommand": "sudo chown -R vscode:vscode /workspaces/fluxer/target && find /workspaces/fluxer -maxdepth 4 -type d -name node_modules -prune -exec sudo chown -R vscode:vscode {} + && sudo chown -R vscode:vscode /home/vscode/.local/share/pnpm && cargo run -p fluxer-dev -- bootstrap",
"postStartCommand": "bash /workspaces/fluxer/.devcontainer/fix-docker-socket.sh && cargo run -p fluxer-dev -- post-start && bash /workspaces/fluxer/fluxer_docs/serve.sh --daemon",
"postCreateCommand": "bash /workspaces/fluxer/.devcontainer/fix-docker-socket.sh && bash /workspaces/fluxer/.devcontainer/fix-workspace-permissions.sh && cargo run -p fluxer-dev -- bootstrap",
"postStartCommand": "bash /workspaces/fluxer/.devcontainer/fix-docker-socket.sh && bash /workspaces/fluxer/.devcontainer/fix-workspace-permissions.sh && cargo run -p fluxer-dev -- post-start",
"customizations": {
"vscode": {
"settings": {
+68 -69
View File
@@ -1,5 +1,3 @@
name: fluxer-dev
services:
workspace:
build:
@@ -7,15 +5,29 @@ services:
dockerfile: .devcontainer/Dockerfile
command: sleep infinity
init: true
env_file:
- ../config/env/development.env
environment:
FLUXER_SEARCH_ENGINE: meilisearch
FLUXER_SEARCH_URL: http://meilisearch:7700
FLUXER_SEARCH_API_KEY: fluxer-dev-meilisearch
FLUXER_POSTGRES_HOST: postgres
FLUXER_SELF_HOSTED: "true"
DOCKER_HOST: unix:///var/run/docker.sock
npm_config_store_dir: /home/vscode/.local/share/pnpm/store
FLUXER_PUBLIC_PORT: "${FLUXER_DEV_PROXY_PORT:-8088}"
FLUXER_PUBLIC_URL: "http://localhost:${FLUXER_DEV_PROXY_PORT:-8088}"
FLUXER_API_ENDPOINT: "http://localhost:${FLUXER_DEV_PROXY_PORT:-8088}/api"
FLUXER_API_CLIENT_ENDPOINT: "http://localhost:${FLUXER_DEV_PROXY_PORT:-8088}/api"
FLUXER_APP_ENDPOINT: "http://localhost:${FLUXER_DEV_PROXY_PORT:-8088}"
FLUXER_GATEWAY_ENDPOINT: "ws://localhost:${FLUXER_DEV_PROXY_PORT:-8088}/gateway"
FLUXER_MEDIA_ENDPOINT: "http://localhost:${FLUXER_DEV_PROXY_PORT:-8088}/media"
FLUXER_STATIC_CDN_ENDPOINT: "http://localhost:${FLUXER_DEV_PROXY_PORT:-8088}"
FLUXER_ADMIN_ENDPOINT: "http://localhost:${FLUXER_DEV_PROXY_PORT:-8088}/admin"
FLUXER_MEDIA_PROXY_PUBLIC_ENDPOINT: "http://localhost:${FLUXER_DEV_PROXY_PORT:-8088}/media"
FLUXER_S3_PUBLIC_ENDPOINT: "http://localhost:${FLUXER_DEV_PROXY_PORT:-8088}"
FLUXER_LIVEKIT_URL: "ws://localhost:${FLUXER_DEV_PROXY_PORT:-8088}/livekit"
FLUXER_LIVEKIT_INTERNAL_URL: "http://livekit:7880"
FLUXER_LIVEKIT_WEBHOOK_URL: "http://localhost:${FLUXER_DEV_PROXY_PORT:-8088}/api/webhooks/livekit"
FLUXER_MEDIA_PROXY_UPLOAD_RELAY_ENDPOINT: "http://localhost:${FLUXER_DEV_PROXY_PORT:-8088}/media"
FLUXER_GATEWAY_MEDIA_PROXY_ENDPOINT: "http://localhost:${FLUXER_DEV_PROXY_PORT:-8088}/media"
FLUXER_GATEWAY_STATIC_CDN_ENDPOINT: "http://localhost:${FLUXER_DEV_PROXY_PORT:-8088}"
FLUXER_ADMIN_OAUTH_REDIRECT_URI: "http://localhost:${FLUXER_DEV_PROXY_PORT:-8088}/admin/oauth2_callback"
FLUXER_PASSKEY_ADDITIONAL_ALLOWED_ORIGINS: "http://localhost,http://localhost:${FLUXER_DEV_PROXY_PORT:-8088}"
PUBLIC_BOOTSTRAP_API_PUBLIC_ENDPOINT: "http://localhost:${FLUXER_DEV_PROXY_PORT:-8088}/api"
volumes:
- ..:/workspaces/fluxer:cached
- type: volume
@@ -229,6 +241,7 @@ services:
volume:
nocopy: true
- pnpm-store:/home/vscode/.local/share/pnpm/store
- docs-venv:/workspaces/fluxer/fluxer_docs/.venv
- cargo-registry:/home/vscode/.cargo/registry
- cargo-git:/home/vscode/.cargo/git
- rust-target:/workspaces/fluxer/target
@@ -236,45 +249,31 @@ services:
source: ${FLUXER_DOCKER_SOCKET:-/var/run/docker.sock}
target: /var/run/docker.sock
ports:
- "${FLUXER_DEV_DOCS_PORT:-8000}:8000"
- "${FLUXER_DEV_RSPACK_PORT:-3000}:3000"
- "${FLUXER_DEV_PROXY_PORT:-8088}:8088"
- "${FLUXER_DEV_APP_PROXY_PORT:-8080}:8080"
- "${FLUXER_DEV_API_PORT:-8771}:8771"
- "${FLUXER_DEV_GATEWAY_PORT:-8082}:8082"
- "${FLUXER_DEV_MARKETING_PORT:-3010}:3010"
- "${FLUXER_DEV_ADMIN_PORT:-3020}:3020"
- "${FLUXER_DEV_RUST_SERVICE_PORTS:-8100-8125}:8100-8125"
- "${FLUXER_DEV_SEAWEEDFS_S3_PORT:-3900}:8333"
- "${FLUXER_DEV_SEAWEEDFS_FILER_PORT:-8888}:8888"
- "${FLUXER_DEV_SEAWEEDFS_MASTER_PORT:-9333}:9333"
- "${FLUXER_DEV_SEAWEEDFS_VOLUME_PORT:-9340}:9340"
- "${FLUXER_DEV_SEAWEEDFS_ADMIN_PORT:-23646}:23646"
- "127.0.0.1:${FLUXER_DEV_RSPACK_PORT:-3000}:3000"
- "127.0.0.1:${FLUXER_DEV_PROXY_PORT:-8088}:8088"
- "127.0.0.1:${FLUXER_DEV_API_PORT:-8080}:8080"
- "127.0.0.1:${FLUXER_DEV_GATEWAY_PORT:-8771}:8771"
- "127.0.0.1:${FLUXER_DEV_MEDIA_PROXY_PORT:-8082}:8082"
- "127.0.0.1:${FLUXER_DEV_APP_PROXY_PORT:-8773}:8773"
- "127.0.0.1:${FLUXER_DEV_MARKETING_PORT:-3010}:3010"
- "127.0.0.1:${FLUXER_DEV_ADMIN_PORT:-3020}:3020"
- "127.0.0.1:${FLUXER_DEV_SEAWEEDFS_S3_PORT:-3900}:8333"
depends_on:
- postgres
- valkey
- nats
- livekit
- meilisearch
- mailpit
postgres:
condition: service_healthy
valkey:
condition: service_started
nats:
condition: service_started
livekit:
condition: service_started
meilisearch:
condition: service_healthy
mailpit:
condition: service_started
extra_hosts:
- "host.docker.internal:host-gateway"
cassandra:
image: cassandra:5.0.8
profiles:
- full
environment:
CASSANDRA_CLUSTER_NAME: fluxer-dev
CASSANDRA_DC: datacenter1
CASSANDRA_ENDPOINT_SNITCH: GossipingPropertyFileSnitch
HEAP_NEWSIZE: 128M
MAX_HEAP_SIZE: 768M
volumes:
- cassandra-data:/var/lib/cassandra
ports:
- "${FLUXER_DEV_CASSANDRA_PORT:-9042}:9042"
postgres:
image: postgres:16-alpine
environment:
@@ -284,13 +283,19 @@ services:
volumes:
- postgres-data:/var/lib/postgresql/data
ports:
- "${FLUXER_DEV_POSTGRES_PORT:-5432}:5432"
- "127.0.0.1:${FLUXER_DEV_POSTGRES_PORT:-5432}:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U fluxer -d fluxer"]
interval: 2s
timeout: 5s
retries: 30
start_period: 5s
valkey:
image: valkey/valkey:8.1.7-alpine
command: ["valkey-server", "--save", "", "--appendonly", "no"]
ports:
- "${FLUXER_DEV_VALKEY_PORT:-6379}:6379"
- "127.0.0.1:${FLUXER_DEV_VALKEY_PORT:-6379}:6379"
nats:
image: nats:2.14.2-alpine
@@ -298,33 +303,22 @@ services:
volumes:
- nats-data:/data
ports:
- "${FLUXER_DEV_NATS_PORT:-4222}:4222"
- "${FLUXER_DEV_NATS_MONITOR_PORT:-8222}:8222"
- "127.0.0.1:${FLUXER_DEV_NATS_PORT:-4222}:4222"
- "127.0.0.1:${FLUXER_DEV_NATS_MONITOR_PORT:-8222}:8222"
livekit:
image: livekit/livekit-server:v1.12.0
command: ["--config", "/etc/livekit.yaml", "--bind", "0.0.0.0"]
environment:
LIVEKIT_RTC_TCP_PORT: "${FLUXER_DEV_LIVEKIT_TCP_PORT:-7881}"
LIVEKIT_RTC_UDP_PORT_START: "${FLUXER_DEV_LIVEKIT_UDP_PORT:-7882}"
LIVEKIT_RTC_UDP_PORT_END: "${FLUXER_DEV_LIVEKIT_UDP_PORT:-7882}"
volumes:
- ./livekit.yaml:/etc/livekit.yaml:ro
ports:
- "${FLUXER_DEV_LIVEKIT_PORT:-7880}:7880"
- "${FLUXER_DEV_LIVEKIT_TCP_PORT:-7881}:7881"
- "${FLUXER_DEV_LIVEKIT_UDP_PORTS:-7882-7892}:7882-7892/udp"
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:9.3.2
profiles:
- full
environment:
discovery.type: single-node
xpack.security.enabled: "true"
xpack.security.http.ssl.enabled: "false"
ELASTIC_PASSWORD: fluxer-dev-elasticsearch
ES_JAVA_OPTS: "-Xms512m -Xmx512m"
volumes:
- elasticsearch-data:/usr/share/elasticsearch/data
ports:
- "${FLUXER_DEV_ELASTICSEARCH_PORT:-9200}:9200"
- "127.0.0.1:${FLUXER_DEV_LIVEKIT_PORT:-7880}:7880"
- "127.0.0.1:${FLUXER_DEV_LIVEKIT_TCP_PORT:-7881}:${FLUXER_DEV_LIVEKIT_TCP_PORT:-7881}"
- "127.0.0.1:${FLUXER_DEV_LIVEKIT_UDP_PORT:-7882}:${FLUXER_DEV_LIVEKIT_UDP_PORT:-7882}/udp"
meilisearch:
image: getmeili/meilisearch:v1.12
@@ -334,7 +328,13 @@ services:
volumes:
- meilisearch-data:/meili_data
ports:
- "${FLUXER_DEV_MEILISEARCH_PORT:-7700}:7700"
- "127.0.0.1:${FLUXER_DEV_MEILISEARCH_PORT:-7700}:7700"
healthcheck:
test: ["CMD", "curl", "--fail", "--silent", "http://127.0.0.1:7700/health"]
interval: 2s
timeout: 5s
retries: 30
start_period: 5s
mailpit:
image: axllent/mailpit:v1.30
@@ -349,6 +349,7 @@ services:
volumes:
pnpm-store:
docs-venv:
root-node-modules:
fluxer-api-node-modules:
fluxer-app-node-modules:
@@ -394,9 +395,7 @@ volumes:
cargo-registry:
cargo-git:
rust-target:
cassandra-data:
nats-data:
elasticsearch-data:
meilisearch-data:
mailpit-data:
postgres-data:
+6 -26
View File
@@ -1,10 +1,10 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: AGPL-3.0-or-later
set -uo pipefail
set -euo pipefail
SOCKET="${DOCKER_SOCKET:-/var/run/docker.sock}"
USER_NAME="${USER:-vscode}"
USER_NAME="$(id -un)"
if [ ! -S "$SOCKET" ]; then
echo "fix-docker-socket: no socket at $SOCKET; skipping (Docker-in-devcontainer will not work)"
@@ -16,31 +16,11 @@ if docker version --format '{{.Server.Version}}' >/dev/null 2>&1; then
exit 0
fi
socket_gid="$(stat -c '%g' "$SOCKET" 2>/dev/null || echo "")"
if [ -z "$socket_gid" ]; then
echo "fix-docker-socket: could not stat $SOCKET; skipping" >&2
exit 0
fi
sudo sh -c '
set -e
gid="$1"
user="$2"
socket="$3"
if ! getent group "$gid" >/dev/null 2>&1; then
groupadd --gid "$gid" docker-host
fi
group_name="$(getent group "$gid" | cut -d: -f1)"
usermod --append --groups "$group_name" "$user"
chgrp "$gid" "$socket"
chmod g+rw "$socket"
' sh "$socket_gid" "$USER_NAME" "$SOCKET" || {
echo "fix-docker-socket: could not adjust $SOCKET; run docker with sudo" >&2
exit 0
}
sudo setfacl --modify "user:${USER_NAME}:rw" "$SOCKET"
if docker version --format '{{.Server.Version}}' >/dev/null 2>&1; then
echo "fix-docker-socket: $SOCKET is now usable as $USER_NAME (gid $socket_gid)"
echo "fix-docker-socket: $SOCKET is now usable as $USER_NAME"
else
echo "fix-docker-socket: $SOCKET still unreachable as $USER_NAME; run docker with sudo" >&2
echo "fix-docker-socket: $SOCKET is still unreachable as $USER_NAME" >&2
exit 1
fi
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: AGPL-3.0-or-later
set -euo pipefail
owner="$(id -u):$(id -g)"
repair_tree() {
local path="$1"
local unwritable
if [ ! -d "$path" ]; then
echo "fix-workspace-permissions: expected mount is missing: $path" >&2
exit 1
fi
unwritable="$(find "$path" -xdev \( -type d -o -type f \) ! -writable -print -quit 2>/dev/null || true)"
if [ ! -w "$path" ] || [ -n "$unwritable" ]; then
sudo find "$path" -xdev \( -type d -o -type f \) -exec chown "$owner" {} +
fi
unwritable="$(find "$path" -xdev \( -type d -o -type f \) ! -writable -print -quit 2>/dev/null || true)"
if [ ! -w "$path" ] || [ -n "$unwritable" ]; then
echo "fix-workspace-permissions: $path is not writable as $(id -un)" >&2
exit 1
fi
}
for path in \
/workspaces/fluxer/target \
/home/vscode/.cargo/registry \
/home/vscode/.cargo/git \
/home/vscode/.local \
/home/vscode/.local/share/pnpm/store \
/workspaces/fluxer/fluxer_docs/.venv; do
repair_tree "$path"
done
while IFS= read -r -d '' path; do
if mountpoint -q "$path"; then
repair_tree "$path"
fi
done < <(find /workspaces/fluxer -maxdepth 4 -type d -name node_modules -prune -print0)
+1 -2
View File
@@ -1,11 +1,10 @@
port: 7880
keys:
devkey: secret
devkey: fluxer-livekit-development-secret
rtc:
tcp_port: 7881
udp_port: 7882-7892
node_ip: 127.0.0.1
use_mdns: true
stun_servers:
-2
View File
@@ -52,8 +52,6 @@
/s3_payload/
/upload_staging/
/deploy/helm/**/Chart.lock
/deploy/helm/**/charts/
/fluxer_desktop/
-5
View File
@@ -1,10 +1,5 @@
self-hosted-runner:
labels:
- blacksmith-4vcpu-ubuntu-2404
- blacksmith-4vcpu-ubuntu-2404-arm
- blacksmith-32vcpu-ubuntu-2404
- blacksmith-32vcpu-ubuntu-2404-arm
- blacksmith-32vcpu-windows-2025
- fluxer-desktop-macos-arm64
config-variables: null
+6 -6
View File
@@ -80,7 +80,7 @@ jobs:
GH_TOKEN: ${{ steps.create-token.outputs.token }}
FLUXER_BUILD_VERSION: ${{ inputs['build-version'] }}
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- resolve-calver
tools/ci/run.sh resolve-calver
--github-output
build:
@@ -97,9 +97,9 @@ jobs:
matrix:
include:
- platform: amd64
runner: blacksmith-4vcpu-ubuntu-2404
runner: ubuntu-24.04
- platform: arm64
runner: blacksmith-4vcpu-ubuntu-2404-arm
runner: ubuntu-24.04-arm
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
env:
@@ -121,8 +121,8 @@ jobs:
build-args: |
BUILD_VERSION=${{ needs.meta.outputs.build_version }}
${{ inputs.extra-build-args }}
cache-from: type=gha,scope=${{ inputs.image }}-${{ matrix.platform }}
cache-to: type=gha,scope=${{ inputs.image }}-${{ matrix.platform }},mode=max,ignore-error=true
cache-from: type=registry,ref=ghcr.io/${{ env.GHCR_OWNER }}/${{ inputs.image }}:buildcache-${{ matrix.platform }}
cache-to: type=registry,ref=ghcr.io/${{ env.GHCR_OWNER }}/${{ inputs.image }}:buildcache-${{ matrix.platform }},mode=max,image-manifest=true,oci-mediatypes=true,ignore-error=true
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false
@@ -176,7 +176,7 @@ jobs:
VERSION: ${{ needs.meta.outputs.build_version }}
RELEASE_BASELINE_SHA: ${{ vars.RELEASE_BASELINE_SHA }}
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- release
tools/ci/run.sh release
publish
--component "${{ inputs.image }}"
--build-version "${VERSION}"
+17 -17
View File
@@ -53,14 +53,14 @@ jobs:
- name: set variables
id: vars
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-app-proxy
tools/ci/run.sh build-app-proxy
--step set_metadata
--build-version "${{ inputs['build-version'] }}"
build:
name: build app-proxy (amd64)
needs: meta
runs-on: blacksmith-4vcpu-ubuntu-2404
runs-on: ubuntu-24.04
timeout-minutes: 45
permissions:
actions: read
@@ -76,7 +76,7 @@ jobs:
toolchain: "1.93.0"
- name: prepare docker config
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-app-proxy
tools/ci/run.sh build-app-proxy
--step prepare_docker_config
- uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5
- name: configure ghcr auth
@@ -84,40 +84,40 @@ jobs:
GHCR_USERNAME: ${{ github.actor }}
GHCR_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-app-proxy
tools/ci/run.sh build-app-proxy
--step configure_ghcr_auth
- name: build and push image + extract assets
env:
BUILD_VERSION: ${{ needs.meta.outputs.build_version }}
PUBLIC_ASSET_BASE_URL: https://fluxerstatic.com
CACHE_FROM: type=gha,scope=fluxer-app-proxy
CACHE_TO: type=gha,scope=fluxer-app-proxy,mode=max
CACHE_FROM: type=registry,ref=ghcr.io/${{ env.GHCR_OWNER }}/fluxer-app-proxy:buildcache-amd64
CACHE_TO: type=registry,ref=ghcr.io/${{ env.GHCR_OWNER }}/fluxer-app-proxy:buildcache-amd64,mode=max,image-manifest=true,oci-mediatypes=true,ignore-error=true
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-app-proxy
tools/ci/run.sh build-app-proxy
--step build_and_extract
- name: generate asset manifest
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-app-proxy
tools/ci/run.sh build-app-proxy
--step generate_asset_manifest
- name: upload assets to S3 static bucket
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
S3_ENDPOINT: https://ewr1.vultrobjects.com
STATIC_BUCKET: fluxer-static
AWS_ACCESS_KEY_ID: ${{ secrets.STATIC_AWS_ACCESS_KEY_ID || secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.STATIC_AWS_SECRET_ACCESS_KEY || secrets.AWS_SECRET_ACCESS_KEY }}
S3_ENDPOINT: ${{ vars.STATIC_S3_ENDPOINT }}
STATIC_BUCKET: ${{ vars.STATIC_S3_BUCKET }}
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-app-proxy
tools/ci/run.sh build-app-proxy
--step upload_assets
build-arm64:
name: build app-proxy (arm64)
needs: meta
runs-on: blacksmith-4vcpu-ubuntu-2404-arm
runs-on: ubuntu-24.04-arm
timeout-minutes: 60
permissions:
actions: read
@@ -145,8 +145,8 @@ jobs:
BUILD_VERSION=${{ needs.meta.outputs.build_version }}
PUBLIC_ASSET_BASE_URL=https://fluxerstatic.com
BUNDLE_LOCAL_ASSETS=false
cache-from: type=gha,scope=fluxer-app-proxy-arm64
cache-to: type=gha,scope=fluxer-app-proxy-arm64,mode=max,ignore-error=true
cache-from: type=registry,ref=ghcr.io/${{ env.GHCR_OWNER }}/fluxer-app-proxy:buildcache-arm64
cache-to: type=registry,ref=ghcr.io/${{ env.GHCR_OWNER }}/fluxer-app-proxy:buildcache-arm64,mode=max,image-manifest=true,oci-mediatypes=true,ignore-error=true
env:
DOCKER_BUILD_SUMMARY: false
DOCKER_BUILD_RECORD_UPLOAD: false
@@ -203,7 +203,7 @@ jobs:
VERSION: ${{ needs.meta.outputs.build_version }}
RELEASE_BASELINE_SHA: ${{ vars.RELEASE_BASELINE_SHA }}
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- release
tools/ci/run.sh release
publish
--component fluxer-app-proxy
--build-version "${VERSION}"
+52 -11
View File
@@ -119,7 +119,7 @@ jobs:
- matrix
runs-on: ${{ matrix.os }}
environment: desktop-releases
timeout-minutes: 60
timeout-minutes: 180
permissions:
actions: read
contents: read
@@ -139,10 +139,10 @@ jobs:
SOURCE_SHA: ${{ needs.meta.outputs.source_sha }}
S3_DESKTOP_PREFIX: ${{ needs.meta.outputs.s3_prefix }}
DESKTOP_HANDOFF_PREFIX: _handoff/desktop/${{ needs.meta.outputs.build_channel }}/${{ needs.meta.outputs.version }}/${{ needs.meta.outputs.source_sha }}
S3_ENDPOINT: https://ewr1.vultrobjects.com
S3_BUCKET: fluxer-downloads
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
S3_ENDPOINT: ${{ vars.DOWNLOADS_S3_ENDPOINT }}
S3_BUCKET: ${{ vars.DOWNLOADS_S3_BUCKET }}
AWS_ACCESS_KEY_ID: ${{ secrets.DOWNLOADS_AWS_ACCESS_KEY_ID || secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.DOWNLOADS_AWS_SECRET_ACCESS_KEY || secrets.AWS_SECRET_ACCESS_KEY }}
DESKTOP_PLATFORM: ${{ matrix.platform }}
DESKTOP_ARCH: ${{ matrix.arch }}
DESKTOP_VARIANT: ${{ matrix.desktop_variant }}
@@ -508,7 +508,7 @@ jobs:
- build
runs-on: ubuntu-24.04-arm
environment: desktop-releases
timeout-minutes: 60
timeout-minutes: 180
permissions:
contents: read
env:
@@ -524,11 +524,12 @@ jobs:
SOURCE_SHA: ${{ needs.meta.outputs.source_sha }}
S3_DESKTOP_PREFIX: ${{ needs.meta.outputs.s3_prefix }}
DESKTOP_HANDOFF_PREFIX: _handoff/desktop/${{ needs.meta.outputs.build_channel }}/${{ needs.meta.outputs.version }}/${{ needs.meta.outputs.source_sha }}
S3_ENDPOINT: https://ewr1.vultrobjects.com
S3_BUCKET: fluxer-downloads
DESKTOP_RELEASE_ASSETS_PREFIX: _handoff/desktop-release-assets/${{ needs.meta.outputs.build_channel }}/${{ needs.meta.outputs.version }}/${{ needs.meta.outputs.source_sha }}
S3_ENDPOINT: ${{ vars.DOWNLOADS_S3_ENDPOINT }}
S3_BUCKET: ${{ vars.DOWNLOADS_S3_BUCKET }}
PUBLIC_DL_BASE: https://api.fluxer.app/dl
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_ACCESS_KEY_ID: ${{ secrets.DOWNLOADS_AWS_ACCESS_KEY_ID || secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.DOWNLOADS_AWS_SECRET_ACCESS_KEY || secrets.AWS_SECRET_ACCESS_KEY }}
steps:
- name: Checkout source
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
@@ -553,11 +554,29 @@ jobs:
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
--step build_payload
- name: Prepare GitHub release assets
if: needs.meta.outputs.test_build != 'true'
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
--step prepare_release_assets
- name: Publish GitHub release descriptor
if: needs.meta.outputs.test_build != 'true'
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
--step publish_release_descriptor
- name: Upload payload to S3
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
--step upload_payload
- name: Upload GitHub release asset handoff
if: needs.meta.outputs.test_build != 'true'
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
--step upload_release_assets
- name: Build summary
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
@@ -577,9 +596,17 @@ jobs:
- upload
runs-on: ubuntu-24.04-arm
environment: desktop-releases
timeout-minutes: 10
timeout-minutes: 60
permissions:
contents: write
env:
CHANNEL: ${{ needs.meta.outputs.build_channel }}
VERSION: ${{ needs.meta.outputs.version }}
DESKTOP_RELEASE_ASSETS_PREFIX: _handoff/desktop-release-assets/${{ needs.meta.outputs.build_channel }}/${{ needs.meta.outputs.version }}/${{ needs.meta.outputs.source_sha }}
S3_ENDPOINT: ${{ vars.DOWNLOADS_S3_ENDPOINT }}
S3_BUCKET: ${{ vars.DOWNLOADS_S3_BUCKET }}
AWS_ACCESS_KEY_ID: ${{ secrets.DOWNLOADS_AWS_ACCESS_KEY_ID || secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.DOWNLOADS_AWS_SECRET_ACCESS_KEY || secrets.AWS_SECRET_ACCESS_KEY }}
steps:
- name: Checkout source
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
@@ -590,6 +617,12 @@ jobs:
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9
with:
toolchain: "1.93.0"
- name: Download GitHub release assets
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
--step download_release_assets
- name: Create token
id: create-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1
@@ -614,8 +647,16 @@ jobs:
--build-version "${VERSION}"
--source-sha "${SOURCE_SHA}"
--previous-sha "${RELEASE_BASELINE_SHA}"
--asset-dir release_assets
)
if [[ "${CHANNEL}" == "canary" ]]; then
release_args+=(--prerelease)
fi
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- "${release_args[@]}"
- name: Publish GitHub release readiness marker
env:
SOURCE_SHA: ${{ needs.meta.outputs.source_sha }}
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- build-desktop
--step publish_release_marker
+1 -1
View File
@@ -39,7 +39,7 @@ jobs:
- name: Install dependencies
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
tools/ci/run.sh ci
--step install_dependencies
- name: Generate OpenAPI schemas
+1 -1
View File
@@ -57,7 +57,7 @@ jobs:
- name: Install dependencies
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
tools/ci/run.sh ci
--step install_dependencies
- name: Refresh source catalogs
+1 -1
View File
@@ -63,7 +63,7 @@ jobs:
- name: Install dependencies
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
tools/ci/run.sh ci
--step install_dependencies
- name: Compile translated catalogs
+203 -186
View File
@@ -3,21 +3,29 @@ name: Tests
on:
pull_request:
push:
branches:
- main
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
GHCR_REGISTRY: ghcr.io/${{ github.repository_owner }}
CARGO_PROFILE_DEV_DEBUG: none
CARGO_PROFILE_TEST_DEBUG: none
CARGO_INCREMENTAL: '0'
jobs:
typecheck:
runs-on: ubuntu-24.04
timeout-minutes: 25
env:
FLUXER_CI_BIN: ${{ github.workspace }}/target/debug/fluxer-ci
steps:
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
@@ -28,6 +36,28 @@ jobs:
toolchain: "1.93.0"
targets: wasm32-unknown-unknown
- name: Restore ci helper
id: ci-helper
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
path: target/debug/fluxer-ci
key: >-
fluxer-ci-bin-${{ runner.os }}-1.93.0-${{ hashFiles('Cargo.lock', 'Cargo.toml',
'tools/ci/Cargo.toml', 'tools/ci/src/**', 'tools/ci/templates/**') }}
- name: Build ci helper
if: steps.ci-helper.outputs.cache-hit != 'true'
run: cargo build --locked --package fluxer-ci
- name: Save ci helper
if: github.ref == 'refs/heads/main' && steps.ci-helper.outputs.cache-hit != 'true'
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
path: target/debug/fluxer-ci
key: >-
fluxer-ci-bin-${{ runner.os }}-1.93.0-${{ hashFiles('Cargo.lock', 'Cargo.toml',
'tools/ci/Cargo.toml', 'tools/ci/src/**', 'tools/ci/templates/**') }}
- name: Install pnpm
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271
@@ -38,18 +68,19 @@ jobs:
cache: 'pnpm'
- name: Install dependencies
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
--step install_dependencies
run: |
"$FLUXER_CI_BIN" ci --step install_dependencies
- name: Run typecheck
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
--step typecheck
run: |
"$FLUXER_CI_BIN" ci --step typecheck
test:
runs-on: ubuntu-24.04
timeout-minutes: 25
env:
FLUXER_CI_BIN: ${{ github.workspace }}/target/debug/fluxer-ci
PNPM_TEST_WORKSPACE_CONCURRENCY: '2'
steps:
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
@@ -60,6 +91,19 @@ jobs:
toolchain: "1.93.0"
targets: wasm32-unknown-unknown
- name: Restore ci helper
id: ci-helper
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
path: target/debug/fluxer-ci
key: >-
fluxer-ci-bin-${{ runner.os }}-1.93.0-${{ hashFiles('Cargo.lock', 'Cargo.toml',
'tools/ci/Cargo.toml', 'tools/ci/src/**', 'tools/ci/templates/**') }}
- name: Build ci helper
if: steps.ci-helper.outputs.cache-hit != 'true'
run: cargo build --locked --package fluxer-ci
- name: Install pnpm
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271
@@ -70,17 +114,45 @@ jobs:
cache: 'pnpm'
- name: Install dependencies
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
--step install_dependencies
run: |
"$FLUXER_CI_BIN" ci --step install_dependencies
- name: Restore fluxer_app wasm artifacts
id: app-wasm
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
path: |
fluxer_app/pkgs/libfluxcore
fluxer_app/src/features/messaging/utils/markdown/parser/MarkdownParserWasmBytes.ts
key: >-
app-wasm-${{ runner.os }}-1.93.0-${{ hashFiles('Cargo.lock', 'tools/ci/src/app_wasm.rs',
'tools/ci/templates/libfluxcore_wrapper.js', 'tools/ci/templates/libfluxcore_wrapper.d.ts',
'fluxer_app/rust/libfluxcore/Cargo.toml', 'fluxer_app/rust/libfluxcore/Cargo.lock',
'fluxer_app/rust/libfluxcore/.cargo/config.toml', 'fluxer_app/rust/libfluxcore/src/**',
'packages/markdown_parser/rust/Cargo.toml', 'packages/markdown_parser/rust/.cargo/config.toml',
'packages/markdown_parser/rust/src/**') }}
- name: Run tests
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
--step test
run: |
"$FLUXER_CI_BIN" ci --step test
- name: Save fluxer_app wasm artifacts
if: always() && github.ref == 'refs/heads/main' && steps.app-wasm.outputs.cache-hit != 'true'
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
path: |
fluxer_app/pkgs/libfluxcore
fluxer_app/src/features/messaging/utils/markdown/parser/MarkdownParserWasmBytes.ts
key: >-
app-wasm-${{ runner.os }}-1.93.0-${{ hashFiles('Cargo.lock', 'tools/ci/src/app_wasm.rs',
'tools/ci/templates/libfluxcore_wrapper.js', 'tools/ci/templates/libfluxcore_wrapper.d.ts',
'fluxer_app/rust/libfluxcore/Cargo.toml', 'fluxer_app/rust/libfluxcore/Cargo.lock',
'fluxer_app/rust/libfluxcore/.cargo/config.toml', 'fluxer_app/rust/libfluxcore/src/**',
'packages/markdown_parser/rust/Cargo.toml', 'packages/markdown_parser/rust/.cargo/config.toml',
'packages/markdown_parser/rust/src/**') }}
rust:
runs-on: blacksmith-4vcpu-ubuntu-2404
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- name: Checkout code
@@ -89,7 +161,7 @@ jobs:
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9
with:
toolchain: stable
toolchain: "1.93.0"
components: clippy, rustfmt
- name: Install pnpm
@@ -102,15 +174,12 @@ jobs:
cache: 'pnpm'
- name: Cache cargo
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: rust-${{ runner.os }}-${{ hashFiles('Cargo.lock') }}
restore-keys: |
rust-${{ runner.os }}-
workspaces: |
. -> target
fluxer_desktop/native/rust -> target
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Install native dependencies
run: |
@@ -130,15 +199,23 @@ jobs:
- name: Check formatting
run: cargo fmt --all -- --check
- name: Check formatting (desktop native)
run: cargo fmt --manifest-path fluxer_desktop/native/rust/Cargo.toml --all -- --check
- name: Clippy (warnings as errors)
run: cargo clippy --workspace -- -D warnings
- name: Run tests
run: cargo test --workspace
- name: Run desktop native tests
run: cargo test --manifest-path fluxer_desktop/native/rust/Cargo.toml
gateway:
runs-on: ubuntu-24.04
timeout-minutes: 25
env:
FLUXER_CI_BIN: ${{ github.workspace }}/target/debug/fluxer-ci
steps:
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
@@ -148,45 +225,82 @@ jobs:
with:
toolchain: "1.93.0"
- name: Cache cargo (gateway NIFs)
uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6
with:
workspaces: |
fluxer_gateway/native/guild_member_list_oset_nif -> target
fluxer_gateway/native/push_markdown_plaintext_nif -> target
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Restore ci helper
id: ci-helper
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
path: target/debug/fluxer-ci
key: >-
fluxer-ci-bin-${{ runner.os }}-1.93.0-${{ hashFiles('Cargo.lock', 'Cargo.toml',
'tools/ci/Cargo.toml', 'tools/ci/src/**', 'tools/ci/templates/**') }}
- name: Build ci helper
if: steps.ci-helper.outputs.cache-hit != 'true'
run: cargo build --locked --package fluxer-ci
- name: Set up Erlang
uses: erlef/setup-beam@54075bcc5e249e4758d363f27d099f55d843f124
with:
otp-version: '28'
rebar3-version: '3.24.0'
- name: Cache rebar3 dependencies
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
- name: Restore rebar3 dependencies
id: rebar3-cache
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
path: |
fluxer_gateway/_build
~/.cache/rebar3
key: rebar3-${{ runner.os }}-${{ hashFiles('fluxer_gateway/rebar.lock') }}
fluxer_gateway/_build
!fluxer_gateway/_build/default/lib/fluxer_gateway
!fluxer_gateway/_build/test/lib/fluxer_gateway
key: >-
rebar3-${{ runner.os }}-otp28-rebar3.24.0-${{ hashFiles('fluxer_gateway/rebar.lock',
'fluxer_gateway/rebar.config') }}
restore-keys: |
rebar3-${{ runner.os }}-
rebar3-${{ runner.os }}-otp28-rebar3.24.0-
- name: Check formatting
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
--step gateway_fmt
run: |
"$FLUXER_CI_BIN" ci --step gateway_fmt
- name: Compile
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
--step gateway_compile
run: |
"$FLUXER_CI_BIN" ci --step gateway_compile
- name: Run dialyzer
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
--step gateway_dialyzer
run: |
"$FLUXER_CI_BIN" ci --step gateway_dialyzer
- name: Run eunit tests
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
--step gateway_eunit
run: |
"$FLUXER_CI_BIN" ci --step gateway_eunit
- name: Save rebar3 dependencies
if: always() && github.ref == 'refs/heads/main' && steps.rebar3-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
path: |
~/.cache/rebar3
fluxer_gateway/_build
!fluxer_gateway/_build/default/lib/fluxer_gateway
!fluxer_gateway/_build/test/lib/fluxer_gateway
key: >-
rebar3-${{ runner.os }}-otp28-rebar3.24.0-${{ hashFiles('fluxer_gateway/rebar.lock',
'fluxer_gateway/rebar.config') }}
knip:
runs-on: ubuntu-24.04
timeout-minutes: 25
env:
FLUXER_CI_BIN: ${{ github.workspace }}/target/debug/fluxer-ci
steps:
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
@@ -197,6 +311,19 @@ jobs:
toolchain: "1.93.0"
targets: wasm32-unknown-unknown
- name: Restore ci helper
id: ci-helper
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
path: target/debug/fluxer-ci
key: >-
fluxer-ci-bin-${{ runner.os }}-1.93.0-${{ hashFiles('Cargo.lock', 'Cargo.toml',
'tools/ci/Cargo.toml', 'tools/ci/src/**', 'tools/ci/templates/**') }}
- name: Build ci helper
if: steps.ci-helper.outputs.cache-hit != 'true'
run: cargo build --locked --package fluxer-ci
- name: Install pnpm
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271
@@ -207,14 +334,42 @@ jobs:
cache: 'pnpm'
- name: Install dependencies
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
--step install_dependencies
run: |
"$FLUXER_CI_BIN" ci --step install_dependencies
- name: Restore fluxer_app wasm artifacts
id: app-wasm
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
path: |
fluxer_app/pkgs/libfluxcore
fluxer_app/src/features/messaging/utils/markdown/parser/MarkdownParserWasmBytes.ts
key: >-
app-wasm-${{ runner.os }}-1.93.0-${{ hashFiles('Cargo.lock', 'tools/ci/src/app_wasm.rs',
'tools/ci/templates/libfluxcore_wrapper.js', 'tools/ci/templates/libfluxcore_wrapper.d.ts',
'fluxer_app/rust/libfluxcore/Cargo.toml', 'fluxer_app/rust/libfluxcore/Cargo.lock',
'fluxer_app/rust/libfluxcore/.cargo/config.toml', 'fluxer_app/rust/libfluxcore/src/**',
'packages/markdown_parser/rust/Cargo.toml', 'packages/markdown_parser/rust/.cargo/config.toml',
'packages/markdown_parser/rust/src/**') }}
- name: Run knip
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
--step knip
run: |
"$FLUXER_CI_BIN" ci --step knip
- name: Save fluxer_app wasm artifacts
if: always() && github.ref == 'refs/heads/main' && steps.app-wasm.outputs.cache-hit != 'true'
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
with:
path: |
fluxer_app/pkgs/libfluxcore
fluxer_app/src/features/messaging/utils/markdown/parser/MarkdownParserWasmBytes.ts
key: >-
app-wasm-${{ runner.os }}-1.93.0-${{ hashFiles('Cargo.lock', 'tools/ci/src/app_wasm.rs',
'tools/ci/templates/libfluxcore_wrapper.js', 'tools/ci/templates/libfluxcore_wrapper.d.ts',
'fluxer_app/rust/libfluxcore/Cargo.toml', 'fluxer_app/rust/libfluxcore/Cargo.lock',
'fluxer_app/rust/libfluxcore/.cargo/config.toml', 'fluxer_app/rust/libfluxcore/src/**',
'packages/markdown_parser/rust/Cargo.toml', 'packages/markdown_parser/rust/.cargo/config.toml',
'packages/markdown_parser/rust/src/**') }}
i18n:
runs-on: ubuntu-24.04
@@ -223,12 +378,6 @@ jobs:
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
- name: Set up Rust toolchain (CI helpers)
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9
with:
toolchain: "1.93.0"
targets: wasm32-unknown-unknown
- name: Install pnpm
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271
@@ -239,9 +388,7 @@ jobs:
cache: 'pnpm'
- name: Install dependencies
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci
--step install_dependencies
run: pnpm install --frozen-lockfile
- name: Compile locale catalogs
run: pnpm i18n:compile
@@ -275,133 +422,3 @@ jobs:
- name: Verify shipped fonts match the lockfile
run: python3 tools/fonts/build_fonts.py --verify
ci-scripts:
runs-on: ubuntu-24.04
timeout-minutes: 25
steps:
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9
with:
toolchain: stable
components: rustfmt
- name: Sync ci helper dependencies
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci-scripts
--step sync
- name: Run ci helper tests
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- ci-scripts
--step test
helm-and-scripts:
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
- name: Set up Rust toolchain (CI helpers)
uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9
with:
toolchain: "1.93.0"
- name: Install helm
uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310
- name: Resolve Helm test build version
run: >-
cargo run --locked --quiet --manifest-path tools/ci/Cargo.toml -- resolve-calver
--github-env
--env-name HELM_TEST_BUILD_VERSION
- name: Helm dependency update (all charts)
run: |
set -euo pipefail
for chart_dir in deploy/helm/*/; do
if [[ -f "${chart_dir}Chart.yaml" ]]; then
helm dependency update "$chart_dir"
fi
done
- name: Helm lint (all charts)
run: |
set -euo pipefail
FAILED=0
for chart_dir in deploy/helm/*/; do
if [[ -f "${chart_dir}Chart.yaml" ]]; then
echo "--- Linting ${chart_dir} ---"
VALUES_ARGS=()
if [[ -f "${chart_dir}values.yaml" ]]; then
VALUES_ARGS=(-f "${chart_dir}values.yaml")
fi
EXTRA_SETS=(--set-string "global.registry=${GHCR_REGISTRY}")
case "${chart_dir}" in
*gateway*)
EXTRA_SETS+=(--set-string "gateway.tag=${HELM_TEST_BUILD_VERSION}" --set-string "gateway.build.version=${HELM_TEST_BUILD_VERSION}")
;;
*api*)
EXTRA_SETS+=(--set-string app.name=api --set-string "app.tag=${HELM_TEST_BUILD_VERSION}" --set-string app.config=stable --set-string "app.build.version=${HELM_TEST_BUILD_VERSION}")
;;
*app-proxy*)
EXTRA_SETS+=(--set-string app.name=app-proxy --set-string "app.tag=${HELM_TEST_BUILD_VERSION}" --set-string app.config=stable --set-string "app.build.version=${HELM_TEST_BUILD_VERSION}")
;;
*admin*)
EXTRA_SETS+=(--set-string app.name=admin --set-string "app.tag=${HELM_TEST_BUILD_VERSION}" --set-string app.config=stable --set-string "app.build.version=${HELM_TEST_BUILD_VERSION}")
;;
*marketing*)
EXTRA_SETS+=(--set-string app.name=marketing --set-string "app.tag=${HELM_TEST_BUILD_VERSION}" --set-string app.config=stable --set-string "app.build.version=${HELM_TEST_BUILD_VERSION}")
;;
*docs*)
EXTRA_SETS+=(--set-string app.name=docs --set-string "app.tag=${HELM_TEST_BUILD_VERSION}" --set-string app.config=stable --set-string "app.build.version=${HELM_TEST_BUILD_VERSION}")
;;
*media-proxy*)
EXTRA_SETS+=(--set-string "mediaProxy.tag=${HELM_TEST_BUILD_VERSION}" --set-string "staticProxy.tag=${HELM_TEST_BUILD_VERSION}" --set-string "mediaProxy.build.version=${HELM_TEST_BUILD_VERSION}" --set-string "staticProxy.build.version=${HELM_TEST_BUILD_VERSION}")
;;
*uploads*)
EXTRA_SETS+=(--set-string app.name=uploads --set-string "app.tag=${HELM_TEST_BUILD_VERSION}" --set-string app.config=stable --set-string "app.build.version=${HELM_TEST_BUILD_VERSION}")
;;
*worker*)
EXTRA_SETS+=(--set-string "workerRealtime.tag=${HELM_TEST_BUILD_VERSION}" --set-string "workerUnfurl.tag=${HELM_TEST_BUILD_VERSION}" --set-string "workerLifecycle.tag=${HELM_TEST_BUILD_VERSION}" --set-string "workerBatch.tag=${HELM_TEST_BUILD_VERSION}" --set-string "workerRealtime.build.version=${HELM_TEST_BUILD_VERSION}" --set-string "workerUnfurl.build.version=${HELM_TEST_BUILD_VERSION}" --set-string "workerLifecycle.build.version=${HELM_TEST_BUILD_VERSION}" --set-string "workerBatch.build.version=${HELM_TEST_BUILD_VERSION}")
;;
*gifs*|*messages*|*snowflakes*|*unfurl*|*users*)
EXTRA_SETS+=(--set-string "svc.tag=${HELM_TEST_BUILD_VERSION}" --set-string "svc.build.version=${HELM_TEST_BUILD_VERSION}" --set-string svc.build.channel=stable)
;;
esac
if ! helm lint "$chart_dir" "${VALUES_ARGS[@]}" "${EXTRA_SETS[@]}" --strict; then
FAILED=1
fi
fi
done
if [[ "$FAILED" -ne 0 ]]; then
echo "::error::One or more Helm charts failed linting"
exit 1
fi
- name: Helm template (gateway)
run: |
set -euo pipefail
helm template fluxer-gateway deploy/helm/gateway \
-f deploy/helm/gateway/values.yaml \
--set-string "global.registry=${GHCR_REGISTRY}" \
--set-string "gateway.tag=${HELM_TEST_BUILD_VERSION}" \
--set-string "gateway.build.version=${HELM_TEST_BUILD_VERSION}" \
-n fluxer > /dev/null
echo "Gateway chart templates render successfully."
- name: Validate gateway manifests with kubeconform
run: |
set -euo pipefail
helm template fluxer-gateway deploy/helm/gateway \
-f deploy/helm/gateway/values.yaml \
--set-string "global.registry=${GHCR_REGISTRY}" \
--set-string "gateway.tag=${HELM_TEST_BUILD_VERSION}" \
--set-string "gateway.build.version=${HELM_TEST_BUILD_VERSION}" \
-n fluxer \
| docker run -i --rm ghcr.io/yannh/kubeconform:v0.6.7 \
-strict -summary -kubernetes-version 1.31.0
-2
View File
@@ -45,8 +45,6 @@
/s3_payload/
/upload_staging/
/deploy/helm/**/Chart.lock
/deploy/helm/**/charts/
**/.idea/
**/*.iml
Generated
+10
View File
@@ -1777,6 +1777,7 @@ dependencies = [
"axum",
"base64",
"clap",
"fluxer_common",
"hmac 0.13.0",
"hyper 1.10.1",
"hyper-util",
@@ -1800,6 +1801,7 @@ dependencies = [
"anyhow",
"base64",
"fluxer-svc",
"fluxer_common",
"hmac 0.13.0",
"moka",
"reqwest",
@@ -1836,6 +1838,7 @@ dependencies = [
"cc",
"clap",
"criterion",
"fluxer_common",
"hex",
"hmac 0.13.0",
"http 1.4.2",
@@ -1875,6 +1878,7 @@ dependencies = [
"chrono",
"criterion",
"fluxer-svc",
"fluxer_common",
"fluxer_markdown_parser",
"futures",
"hmac 0.13.0",
@@ -1943,6 +1947,7 @@ dependencies = [
"encoding_rs",
"entities",
"fluxer-svc",
"fluxer_common",
"hmac 0.13.0",
"infer",
"moka",
@@ -2038,12 +2043,17 @@ dependencies = [
"aws-credential-types",
"aws-sigv4",
"axum",
"base64",
"hmac 0.13.0",
"maxminddb",
"moka",
"reqwest",
"serde_json",
"sha2 0.11.0",
"thiserror",
"time",
"tracing",
"url",
"urlencoding",
]
-12
View File
@@ -1,15 +1,3 @@
> [!CAUTION]
> As of this writing (15 June 2026), we are working to finalise the API and self-hosting documentation over the next few days.
>
> We apologise for the brief delay in open-source releases. We paused after spam waves created safety concerns while we built out Fluxer's trust and safety infrastructure. During that same stretch, we have been fixing hundreds of bugs, adding new features, and preparing a much improved audio and video system.
>
> You can already try that work in the Fluxer Canary client: [download Canary](https://canary.fluxer.app/download) or [open Canary on the web](https://web.canary.fluxer.app). The latest stable client remains out of date for now, but over the coming weeks we are finalising the remaining work needed to stabilise the current latest code out in the open.
> [!NOTE]
> Learn about the developer behind Fluxer, the goals of the project, the tech stack, and what's coming next.
>
> [Read the launch blog post](https://blog.fluxer.app/how-i-built-fluxer-a-discord-like-chat-app/) | [View full roadmap](https://blog.fluxer.app/roadmap-2026/)
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="./fluxer_static/marketing/branding/logo-white.svg">
+8 -1
View File
@@ -145,7 +145,14 @@
"!fluxer_static",
"!packages/fonts",
"!fluxer_admin/static/htmx.min.js",
"!fluxer_api/src/api/openapi/openapi.json"
"!fluxer_api/src/api/openapi/openapi.json",
"!fluxer_api/pkgs/email/src/email_i18n/locales",
"!fluxer_api/pkgs/email/src/email_i18n/weblate",
"!fluxer_api/src/api/content_i18n/locales",
"!fluxer_api/src/api/content_i18n/weblate",
"!packages/errors/src/i18n/locales",
"!packages/errors/src/i18n/weblate",
"!**/auto-i18n-reviewed-unchanged.json"
],
"ignoreUnknown": true
}
+2 -7
View File
@@ -30,12 +30,6 @@ FLUXER_POSTGRES_PASSWORD=fluxer
FLUXER_POSTGRES_SSL=false
FLUXER_POSTGRES_MAX_CONNECTIONS=20
FLUXER_POSTGRES_KV_TABLE=fluxer_kv
FLUXER_CASSANDRA_HOSTS=cassandra
FLUXER_CASSANDRA_PORT=9042
FLUXER_CASSANDRA_KEYSPACE=fluxer
FLUXER_CASSANDRA_LOCAL_DC=datacenter1
FLUXER_CASSANDRA_USERNAME=fluxer
FLUXER_CASSANDRA_PASSWORD=fluxer
FLUXER_KV_URL=redis://valkey:6379/0
FLUXER_NATS_URL=nats://nats:4222
FLUXER_NATS_JETSTREAM_URL=nats://nats:4222
@@ -66,8 +60,9 @@ FLUXER_S3_BUCKET_STATIC=fluxer-static
FLUXER_LIVEKIT_ENABLED=true
FLUXER_LIVEKIT_URL=ws://localhost:8088/livekit
FLUXER_LIVEKIT_INTERNAL_URL=http://localhost:7880
FLUXER_LIVEKIT_API_KEY=devkey
FLUXER_LIVEKIT_API_SECRET=secret
FLUXER_LIVEKIT_API_SECRET=fluxer-livekit-development-secret
FLUXER_LIVEKIT_WEBHOOK_URL=http://localhost:8088/api/webhooks/livekit
FLUXER_LIVEKIT_DEFAULT_REGION={"id":"local","name":"Local","emoji":"LC","latitude":59.3293,"longitude":18.0686}
-11
View File
@@ -1,11 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: v2
name: admin
description: Fluxer admin service
type: application
version: 0.1.0
dependencies:
- name: common
version: 0.1.0
repository: file://../common
@@ -1,3 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{include "fluxer.deployment" (dict "name" .Values.app.name "values" .Values.app "context" .)}}
-3
View File
@@ -1,3 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{include "fluxer.pdb" (dict "name" .Values.app.name "minAvailable" .Values.pdb.minAvailable "context" .)}}
-3
View File
@@ -1,3 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{include "fluxer.service" (dict "name" .Values.app.name "values" .Values.app "context" .)}}
-41
View File
@@ -1,41 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Live user-supplied values for the fluxer-admin-canary release as of 2026-05-17T20:42:36Z.
# Captured via: helm -n fluxer get values fluxer-admin-canary
# Apply with: helm upgrade fluxer-admin-canary deploy/helm/admin -f deploy/helm/admin/values.yaml -f deploy/helm/admin/values.canary.prod.yaml
app:
build:
channel: canary
version: ""
image: fluxer-admin
name: admin-canary
port: 8080
replicas: 2
minReadySeconds: 10
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
terminationGracePeriodSeconds: 60
startupProbe:
enabled: true
path: /_health
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 24
resources:
limits:
memory: 512Mi
requests:
cpu: 100m
memory: 256Mi
tag: ""
global:
imagePullSecret: ghcr-pull-secret
namespace: fluxer
registry: ""
envFrom:
- secretRef:
name: fluxer-runtime-env-canary
pdb:
minAvailable: 50%
-41
View File
@@ -1,41 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Live user-supplied values for the fluxer-admin-stable release as of 2026-06-03T19:37:50Z.
# Captured via: helm -n fluxer get values fluxer-admin-stable
# Apply with: helm upgrade fluxer-admin-stable deploy/helm/admin -f deploy/helm/admin/values.yaml -f deploy/helm/admin/values.stable.prod.yaml
app:
build:
channel: stable
version: ""
image: fluxer-admin
name: admin
port: 8080
replicas: 2
minReadySeconds: 10
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
terminationGracePeriodSeconds: 60
startupProbe:
enabled: true
path: /_health
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 24
resources:
limits:
memory: 512Mi
requests:
cpu: 100m
memory: 256Mi
tag: ""
global:
imagePullSecret: ghcr-pull-secret
namespace: fluxer
registry: ""
envFrom:
- secretRef:
name: fluxer-runtime-env-stable
pdb:
minAvailable: 50%
-34
View File
@@ -1,34 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
global:
namespace: fluxer
imagePullSecret: ghcr-pull-secret
registry: ""
app:
name: ''
image: ''
tag: ''
replicas: 2
port: 8080
config: ''
minReadySeconds: 10
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
terminationGracePeriodSeconds: 60
startupProbe:
enabled: true
path: /_health
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 24
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 512Mi
pdb:
minAvailable: '50%'
-11
View File
@@ -1,11 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: v2
name: api
description: Fluxer API service
type: application
version: 0.1.0
dependencies:
- name: common
version: 0.1.0
repository: file://../common
@@ -1,3 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{include "fluxer.deployment" (dict "name" .Values.app.name "values" .Values.app "context" .)}}
-3
View File
@@ -1,3 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{include "fluxer.pdb" (dict "name" .Values.app.name "minAvailable" .Values.pdb.minAvailable "context" .)}}
-3
View File
@@ -1,3 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{include "fluxer.service" (dict "name" .Values.app.name "values" .Values.app "context" .)}}
-105
View File
@@ -1,105 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Live user-supplied values for the fluxer-api-canary release as of 2026-05-23T21:25:52Z.
# Captured via: helm -n fluxer get values fluxer-api-canary
# Apply with: helm upgrade fluxer-api-canary deploy/helm/api -f deploy/helm/api/values.yaml -f deploy/helm/api/values.canary.prod.yaml
app:
build:
channel: canary
version: ""
env:
- name: NODE_TLS_REJECT_UNAUTHORIZED
value: "0"
- name: FLUXER_SNOWFLAKE_SERVICE_BATCH_SIZE
value: "128"
- name: FLUXER_SNOWFLAKE_SERVICE_LOW_WATERMARK
value: "32"
- name: FLUXER_SNOWFLAKE_SERVICE_MAX_BUFFER_AGE_MS
value: "5000"
- name: FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64
valueFrom:
secretKeyRef:
key: relay_secret_base64
name: fluxer-upload-relay
image: fluxer-api
name: api-canary
port: 8080
replicas: 4
minReadySeconds: 15
terminationGracePeriodSeconds: 90
preStopDrain:
enabled: true
path: /_health
sleepSeconds: 25
timeoutSeconds: 2
retryCount: 3
retryIntervalSeconds: 1
resources:
limits:
memory: 4Gi
requests:
cpu: 200m
memory: 512Mi
startupProbe:
enabled: true
failureThreshold: 24
path: /_health
periodSeconds: 5
timeoutSeconds: 2
rollingUpdate:
maxSurge: 0
maxUnavailable: 1
tag: ""
canary:
env:
- name: NODE_TLS_REJECT_UNAUTHORIZED
value: "0"
- name: FLUXER_SNOWFLAKE_SERVICE_BATCH_SIZE
value: "128"
- name: FLUXER_SNOWFLAKE_SERVICE_LOW_WATERMARK
value: "32"
- name: FLUXER_SNOWFLAKE_SERVICE_MAX_BUFFER_AGE_MS
value: "5000"
- name: FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64
valueFrom:
secretKeyRef:
key: relay_secret_base64
name: fluxer-upload-relay
image: fluxer-api
port: 8080
replicas: 2
minReadySeconds: 15
terminationGracePeriodSeconds: 90
preStopDrain:
enabled: true
path: /_health
sleepSeconds: 25
timeoutSeconds: 2
retryCount: 3
retryIntervalSeconds: 1
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
resources:
limits:
memory: 4Gi
requests:
cpu: 200m
memory: 512Mi
startupProbe:
enabled: true
failureThreshold: 24
path: /_health
periodSeconds: 5
timeoutSeconds: 2
tag: ""
global:
imagePullSecret: ghcr-pull-secret
namespace: fluxer
registry: ""
envFrom:
- secretRef:
name: fluxer-runtime-env-canary
pdb:
minAvailable: 75%
-107
View File
@@ -1,107 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Live user-supplied values for the fluxer-api-stable release as of 2026-06-03T19:37:50Z.
# Captured via: helm -n fluxer get values fluxer-api-stable
# Apply with: helm upgrade fluxer-api-stable deploy/helm/api -f deploy/helm/api/values.yaml -f deploy/helm/api/values.stable.prod.yaml
app:
build:
channel: stable
version: ""
env:
- name: NODE_TLS_REJECT_UNAUTHORIZED
value: "0"
- name: FLUXER_SNOWFLAKE_SERVICE_BATCH_SIZE
value: "128"
- name: FLUXER_SNOWFLAKE_SERVICE_LOW_WATERMARK
value: "32"
- name: FLUXER_SNOWFLAKE_SERVICE_MAX_BUFFER_AGE_MS
value: "5000"
- name: FLUXER_USERS_SERVICE_TIMEOUT_MS
value: "6000"
- name: FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64
valueFrom:
secretKeyRef:
key: relay_secret_base64
name: fluxer-upload-relay
image: fluxer-api
name: api
port: 8080
replicas: 31
minReadySeconds: 15
terminationGracePeriodSeconds: 90
preStopDrain:
enabled: true
path: /_health
sleepSeconds: 25
timeoutSeconds: 2
retryCount: 3
retryIntervalSeconds: 1
resources:
limits:
memory: 4Gi
requests:
cpu: 200m
memory: 512Mi
startupProbe:
enabled: true
failureThreshold: 24
path: /_health
periodSeconds: 5
timeoutSeconds: 2
rollingUpdate:
maxSurge: 0
maxUnavailable: 1
tag: ""
canary:
env:
- name: NODE_TLS_REJECT_UNAUTHORIZED
value: "0"
- name: FLUXER_SNOWFLAKE_SERVICE_BATCH_SIZE
value: "128"
- name: FLUXER_SNOWFLAKE_SERVICE_LOW_WATERMARK
value: "32"
- name: FLUXER_SNOWFLAKE_SERVICE_MAX_BUFFER_AGE_MS
value: "5000"
- name: FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64
valueFrom:
secretKeyRef:
key: relay_secret_base64
name: fluxer-upload-relay
image: fluxer-api
port: 8080
replicas: 2
minReadySeconds: 15
terminationGracePeriodSeconds: 90
preStopDrain:
enabled: true
path: /_health
sleepSeconds: 25
timeoutSeconds: 2
retryCount: 3
retryIntervalSeconds: 1
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
resources:
limits:
memory: 4Gi
requests:
cpu: 200m
memory: 512Mi
startupProbe:
enabled: true
failureThreshold: 24
path: /_health
periodSeconds: 5
timeoutSeconds: 2
tag: ""
global:
imagePullSecret: ghcr-pull-secret
namespace: fluxer
registry: ""
envFrom:
- secretRef:
name: fluxer-runtime-env-stable
pdb:
minAvailable: 75%
-98
View File
@@ -1,98 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
global:
namespace: fluxer
imagePullSecret: ghcr-pull-secret
registry: ""
app:
name: ''
image: ''
tag: ''
replicas: 2
port: 8080
minReadySeconds: 15
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
terminationGracePeriodSeconds: 90
preStopDrain:
enabled: true
path: /_health
sleepSeconds: 25
timeoutSeconds: 2
retryCount: 3
retryIntervalSeconds: 1
startupProbe:
enabled: true
path: /_health
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 24
env:
- name: NODE_TLS_REJECT_UNAUTHORIZED
value: '0'
- name: FLUXER_SNOWFLAKE_SERVICE_BATCH_SIZE
value: '128'
- name: FLUXER_SNOWFLAKE_SERVICE_LOW_WATERMARK
value: '32'
- name: FLUXER_SNOWFLAKE_SERVICE_MAX_BUFFER_AGE_MS
value: '5000'
- name: FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64
valueFrom:
secretKeyRef:
name: fluxer-upload-relay
key: relay_secret_base64
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
memory: 4Gi
canary:
image: fluxer-api
tag: ''
replicas: 2
port: 8080
minReadySeconds: 15
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
terminationGracePeriodSeconds: 90
preStopDrain:
enabled: true
path: /_health
sleepSeconds: 25
timeoutSeconds: 2
retryCount: 3
retryIntervalSeconds: 1
startupProbe:
enabled: true
path: /_health
periodSeconds: 5
timeoutSeconds: 2
failureThreshold: 24
env:
- name: NODE_TLS_REJECT_UNAUTHORIZED
value: '0'
- name: FLUXER_SNOWFLAKE_SERVICE_BATCH_SIZE
value: '128'
- name: FLUXER_SNOWFLAKE_SERVICE_LOW_WATERMARK
value: '32'
- name: FLUXER_SNOWFLAKE_SERVICE_MAX_BUFFER_AGE_MS
value: '5000'
- name: FLUXER_MEDIA_PROXY_UPLOAD_RELAY_SECRET_BASE64
valueFrom:
secretKeyRef:
name: fluxer-upload-relay
key: relay_secret_base64
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
memory: 4Gi
pdb:
minAvailable: '75%'
-11
View File
@@ -1,11 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: v2
name: app-proxy
description: Fluxer app proxy service
type: application
version: 0.1.0
dependencies:
- name: common
version: 0.1.0
repository: file://../common
@@ -1,3 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{include "fluxer.deployment" (dict "name" .Values.app.name "values" .Values.app "context" .)}}
-3
View File
@@ -1,3 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{include "fluxer.pdb" (dict "name" .Values.app.name "minAvailable" .Values.pdb.minAvailable "context" .)}}
@@ -1,3 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{include "fluxer.service" (dict "name" .Values.app.name "values" .Values.app "context" .)}}
@@ -1,35 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Live user-supplied values for the fluxer-app-proxy-canary release as of 2026-05-17T20:42:38Z.
# Captured via: helm -n fluxer get values fluxer-app-proxy-canary
# Apply with: helm upgrade fluxer-app-proxy-canary deploy/helm/app-proxy -f deploy/helm/app-proxy/values.yaml -f deploy/helm/app-proxy/values.canary.prod.yaml
app:
build:
channel: canary
version: ""
env:
- name: PUBLIC_BOOTSTRAP_API_ENDPOINT
value: /api
- name: PUBLIC_BOOTSTRAP_API_PUBLIC_ENDPOINT
value: https://api.canary.fluxer.app
image: fluxer-app-proxy
name: app-proxy-canary
port: 8080
replicas: 2
resources:
limits:
memory: 512Mi
requests:
cpu: 100m
memory: 256Mi
tag: ""
global:
imagePullSecret: ghcr-pull-secret
namespace: fluxer
registry: ""
envFrom:
- secretRef:
name: fluxer-runtime-env-canary
pdb:
minAvailable: 50%
@@ -1,35 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Live user-supplied values for the fluxer-app-proxy-stable release as of 2026-05-17T20:42:39Z.
# Captured via: helm -n fluxer get values fluxer-app-proxy-stable
# Apply with: helm upgrade fluxer-app-proxy-stable deploy/helm/app-proxy -f deploy/helm/app-proxy/values.yaml -f deploy/helm/app-proxy/values.stable.prod.yaml
app:
build:
channel: stable
version: ""
env:
- name: PUBLIC_BOOTSTRAP_API_ENDPOINT
value: /api
- name: PUBLIC_BOOTSTRAP_API_PUBLIC_ENDPOINT
value: https://api.fluxer.app
image: fluxer-app-proxy
name: app-proxy
port: 8080
replicas: 2
resources:
limits:
memory: 512Mi
requests:
cpu: 100m
memory: 256Mi
tag: ""
global:
imagePullSecret: ghcr-pull-secret
namespace: fluxer
registry: ""
envFrom:
- secretRef:
name: fluxer-runtime-env-stable
pdb:
minAvailable: 50%
-31
View File
@@ -1,31 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
global:
namespace: fluxer
imagePullSecret: ghcr-pull-secret
registry: ""
app:
name: ''
image: ''
tag: ''
replicas: 2
port: 8080
config: ''
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 512Mi
env:
- name: PUBLIC_BOOTSTRAP_API_ENDPOINT
value: '/api'
pdb:
minAvailable: '50%'
-7
View File
@@ -1,7 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: v2
name: common
description: Shared Helm templates for Fluxer services
type: library
version: 0.1.0
-356
View File
@@ -1,356 +0,0 @@
{{/* SPDX-License-Identifier: AGPL-3.0-or-later */}}
{{- define "fluxer.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "fluxer.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "fluxer.labels" -}}
helm.sh/chart: {{ include "fluxer.chart" . }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/part-of: fluxer
{{- end }}
{{- define "fluxer.selectorLabels" -}}
app.kubernetes.io/name: {{ .name }}
app.kubernetes.io/instance: {{ .context.Release.Name }}
{{- end }}
{{- define "fluxer.imagePullSecrets" -}}
imagePullSecrets:
- name: {{ .Values.global.imagePullSecret }}
{{- end }}
{{- define "fluxer.image" -}}
{{- $tag := required (printf ".tag is required (image: %s)" .image) .tag -}}
{{- $registry := required "global.registry is required" .context.Values.global.registry -}}
{{ $registry }}/{{ .image }}:{{ $tag }}
{{- end }}
{{- define "fluxer.replicas" -}}
{{- $name := .name -}}
{{- $v := .values -}}
{{- $ctx := .context -}}
{{- $desired := int (required (printf ".replicas is required for %s" $name) $v.replicas) -}}
{{- $preserveLiveReplicas := dig "preserveLiveReplicas" true $v -}}
{{- if not $preserveLiveReplicas -}}
{{- $desired -}}
{{- else -}}
{{- $existing := lookup "apps/v1" "Deployment" $ctx.Values.global.namespace $name -}}
{{- if $existing -}}
{{- $current := int (dig "spec" "replicas" 0 $existing) -}}
{{- if gt $current 0 -}}
{{- $current -}}
{{- else -}}
{{- $desired -}}
{{- end -}}
{{- else -}}
{{- $desired -}}
{{- end -}}
{{- end -}}
{{- end }}
{{- define "fluxer.deployment" -}}
{{- $name := .name -}}
{{- $v := .values -}}
{{- $ctx := .context -}}
{{- $isGateway := eq $name "gateway" -}}
{{- $defaultMaxSurge := 1 -}}
{{- $defaultMaxUnavailable := 0 -}}
{{- $defaultMinReadySeconds := 10 -}}
{{- $defaultTerminationGracePeriodSeconds := ternary 90 60 $isGateway -}}
{{- $defaultReadinessPath := ternary "/_health/ready" "/_health" $isGateway -}}
{{- $defaultReadinessTimeoutSeconds := ternary 5 2 $isGateway -}}
{{- $configuredMaxSurge := dig "rollingUpdate" "maxSurge" $defaultMaxSurge $v -}}
{{- $configuredMaxUnavailable := dig "rollingUpdate" "maxUnavailable" $defaultMaxUnavailable $v -}}
{{- $maxSurge := $configuredMaxSurge -}}
{{- $maxUnavailable := $configuredMaxUnavailable -}}
{{- $minReadySeconds := int (dig "minReadySeconds" $defaultMinReadySeconds $v) -}}
{{- $terminationGracePeriodSeconds := int (dig "terminationGracePeriodSeconds" $defaultTerminationGracePeriodSeconds $v) -}}
{{- $readinessPath := dig "readinessProbe" "path" $defaultReadinessPath $v -}}
{{- $readinessExecEnabled := dig "readinessProbe" "execEnabled" $isGateway $v -}}
{{- $readinessTimeoutSeconds := int (dig "readinessProbe" "timeoutSeconds" $defaultReadinessTimeoutSeconds $v) -}}
{{- $readinessExecCommand := printf "curl -fsS --max-time %d http://127.0.0.1:%d%s >/dev/null 2>&1 || exit 1" $readinessTimeoutSeconds (int $v.port) $readinessPath -}}
{{- $readinessInitialDelaySeconds := int (dig "readinessProbe" "initialDelaySeconds" 5 $v) -}}
{{- $readinessPeriodSeconds := int (dig "readinessProbe" "periodSeconds" 5 $v) -}}
{{- $readinessFailureThreshold := int (dig "readinessProbe" "failureThreshold" 2 $v) -}}
{{- $livenessPath := dig "livenessProbe" "path" "/_health" $v -}}
{{- $livenessInitialDelaySeconds := int (dig "livenessProbe" "initialDelaySeconds" 10 $v) -}}
{{- $livenessPeriodSeconds := int (dig "livenessProbe" "periodSeconds" 15 $v) -}}
{{- $livenessFailureThreshold := int (dig "livenessProbe" "failureThreshold" 3 $v) -}}
{{- $livenessTimeoutSeconds := int (dig "livenessProbe" "timeoutSeconds" 5 $v) -}}
{{- $startupProbeEnabled := dig "startupProbe" "enabled" $isGateway $v -}}
{{- $startupProbePath := dig "startupProbe" "path" "/_health" $v -}}
{{- $startupProbeInitialDelaySeconds := int (dig "startupProbe" "initialDelaySeconds" 0 $v) -}}
{{- $startupProbePeriodSeconds := int (dig "startupProbe" "periodSeconds" 5 $v) -}}
{{- $startupProbeFailureThreshold := int (dig "startupProbe" "failureThreshold" 30 $v) -}}
{{- $startupProbeTimeoutSeconds := int (dig "startupProbe" "timeoutSeconds" 5 $v) -}}
{{- $preStopDrainEnabled := dig "preStopDrain" "enabled" $isGateway $v -}}
{{- $preStopDrainPath := dig "preStopDrain" "path" "/_health/drain" $v -}}
{{- $preStopDrainSleepSeconds := int (dig "preStopDrain" "sleepSeconds" 20 $v) -}}
{{- $preStopDrainTimeoutSeconds := int (dig "preStopDrain" "timeoutSeconds" 2 $v) -}}
{{- $preStopDrainRetryCount := int (dig "preStopDrain" "retryCount" 6 $v) -}}
{{- $preStopDrainRetryIntervalSeconds := int (dig "preStopDrain" "retryIntervalSeconds" 1 $v) -}}
{{- $preStopDrainCommand := printf "attempt=0; while [ \"$attempt\" -lt %d ]; do curl -fsS --max-time %d http://127.0.0.1:%d%s >/dev/null 2>&1 && break; attempt=$((attempt+1)); sleep %d; done; sleep %d" $preStopDrainRetryCount $preStopDrainTimeoutSeconds (int $v.port) $preStopDrainPath $preStopDrainRetryIntervalSeconds $preStopDrainSleepSeconds -}}
{{- $build := get $v "build" | default (dict) -}}
{{- $buildVersion := get $build "version" | default $v.tag -}}
{{- $buildSha := get $build "sha" | default "" -}}
{{- $buildChannel := get $build "channel" | default "" -}}
{{- $nsfwServiceEndpoint := get $v "nsfwServiceEndpoint" | default "" -}}
{{- $cluster := get $ctx.Values "cluster" | default (dict) -}}
{{- $gatewayClusterEnabled := and $isGateway (eq (get $cluster "enabled" | default false) true) -}}
{{- $erlangDistribution := get $cluster "erlangDistribution" | default (dict) -}}
{{- $erlangDistPort := int (get $erlangDistribution "port" | default 8081) -}}
{{- $erlangEpmdPort := int (get $erlangDistribution "epmdPort" | default 4369) -}}
{{- $erlangCookieSecret := get $cluster "erlangCookieSecret" | default (dict) -}}
{{- $erlangCookieSecretName := get $erlangCookieSecret "name" | default "fluxer-gateway-erlang-cookie" -}}
{{- $erlangCookieSecretKey := get $erlangCookieSecret "key" | default "cookie" -}}
{{- $gatewayNodeBasename := get $cluster "discoveryNodeBasename" | default "fluxer_gateway" -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ $name }}
namespace: {{ $ctx.Values.global.namespace }}
labels:
{{- include "fluxer.labels" $ctx | nindent 4 }}
{{- include "fluxer.selectorLabels" (dict "name" $name "context" $ctx) | nindent 4 }}
spec:
replicas: {{ include "fluxer.replicas" (dict "name" $name "values" $v "context" $ctx) }}
minReadySeconds: {{ $minReadySeconds }}
selector:
matchLabels:
{{- include "fluxer.selectorLabels" (dict "name" $name "context" $ctx) | nindent 6 }}
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: {{ $maxSurge | toJson }}
maxUnavailable: {{ $maxUnavailable | toJson }}
template:
metadata:
labels:
{{- include "fluxer.labels" $ctx | nindent 8 }}
{{- include "fluxer.selectorLabels" (dict "name" $name "context" $ctx) | nindent 8 }}
spec:
{{- include "fluxer.imagePullSecrets" $ctx | nindent 6 }}
terminationGracePeriodSeconds: {{ $terminationGracePeriodSeconds }}
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
{{- if $v.affinity }}
affinity:
{{- toYaml $v.affinity | nindent 8 }}
{{- else if $isGateway }}
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app.kubernetes.io/name: gateway
app.kubernetes.io/instance: {{ $ctx.Release.Name }}
topologyKey: kubernetes.io/hostname
{{- end }}
{{- if $v.topologySpreadConstraints }}
topologySpreadConstraints:
{{- toYaml $v.topologySpreadConstraints | nindent 8 }}
{{- else if $isGateway }}
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/name: gateway
app.kubernetes.io/instance: {{ $ctx.Release.Name }}
{{- else }}
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
nodeAffinityPolicy: Honor
nodeTaintsPolicy: Honor
labelSelector:
matchLabels:
app.kubernetes.io/name: {{ $name }}
app.kubernetes.io/instance: {{ $ctx.Release.Name }}
{{- end }}
{{- if $v.nodeSelector }}
nodeSelector:
{{- toYaml $v.nodeSelector | nindent 8 }}
{{- end }}
{{- if $v.tolerations }}
tolerations:
{{- toYaml $v.tolerations | nindent 8 }}
{{- end }}
containers:
- name: {{ $name }}
image: {{ include "fluxer.image" (dict "image" $v.image "tag" $v.tag "context" $ctx) }}
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: false
{{- if $v.command }}
command: {{ $v.command | toJson }}
{{- end }}
ports:
- name: http
containerPort: {{ $v.port }}
protocol: TCP
{{- if $gatewayClusterEnabled }}
- name: epmd
containerPort: {{ $erlangEpmdPort }}
protocol: TCP
- name: erl-dist
containerPort: {{ $erlangDistPort }}
protocol: TCP
{{- end }}
env:
- name: NODE_ENV
value: production
- name: FLUXER_ENV
value: production
{{- if $gatewayClusterEnabled }}
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: FLUXER_ERLANG_NODE_NAME
value: {{ printf "%s@$(POD_IP)" $gatewayNodeBasename | quote }}
- name: FLUXER_ERLANG_DIST_PORT
value: {{ printf "%d" $erlangDistPort | quote }}
- name: FLUXER_ERLANG_COOKIE
valueFrom:
secretKeyRef:
name: {{ $erlangCookieSecretName }}
key: {{ $erlangCookieSecretKey }}
{{- end }}
{{- if $buildVersion }}
- name: BUILD_VERSION
value: {{ $buildVersion | quote }}
{{- end }}
{{- if $buildSha }}
- name: BUILD_SHA
value: {{ $buildSha | quote }}
{{- end }}
{{- if $buildChannel }}
- name: RELEASE_CHANNEL
value: {{ $buildChannel | quote }}
{{- end }}
{{- if $nsfwServiceEndpoint }}
- name: FLUXER_NSFW_SERVICE_ENDPOINT
value: {{ $nsfwServiceEndpoint | quote }}
{{- end }}
{{- if $ctx.Values.global.env }}
{{- toYaml $ctx.Values.global.env | nindent 12 }}
{{- end }}
{{- if $v.env }}
{{- toYaml $v.env | nindent 12 }}
{{- end }}
{{- if or $ctx.Values.global.envFrom $v.envFrom }}
envFrom:
{{- if $ctx.Values.global.envFrom }}
{{- toYaml $ctx.Values.global.envFrom | nindent 12 }}
{{- end }}
{{- if $v.envFrom }}
{{- toYaml $v.envFrom | nindent 12 }}
{{- end }}
{{- end }}
{{- if $preStopDrainEnabled }}
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- {{ $preStopDrainCommand | quote }}
{{- end }}
volumeMounts:
- name: keys
mountPath: /etc/fluxer/keys
readOnly: true
{{- if not $v.noHealthCheck }}
livenessProbe:
httpGet:
path: {{ $livenessPath | quote }}
port: http
initialDelaySeconds: {{ $livenessInitialDelaySeconds }}
periodSeconds: {{ $livenessPeriodSeconds }}
timeoutSeconds: {{ $livenessTimeoutSeconds }}
failureThreshold: {{ $livenessFailureThreshold }}
readinessProbe:
{{- if $readinessExecEnabled }}
exec:
command:
- /bin/sh
- -c
- {{ $readinessExecCommand | quote }}
{{- else }}
httpGet:
path: {{ $readinessPath | quote }}
port: http
{{- end }}
initialDelaySeconds: {{ $readinessInitialDelaySeconds }}
periodSeconds: {{ $readinessPeriodSeconds }}
timeoutSeconds: {{ $readinessTimeoutSeconds }}
failureThreshold: {{ $readinessFailureThreshold }}
{{- if $startupProbeEnabled }}
startupProbe:
httpGet:
path: {{ $startupProbePath | quote }}
port: http
initialDelaySeconds: {{ $startupProbeInitialDelaySeconds }}
periodSeconds: {{ $startupProbePeriodSeconds }}
timeoutSeconds: {{ $startupProbeTimeoutSeconds }}
failureThreshold: {{ $startupProbeFailureThreshold }}
{{- end }}
{{- end }}
resources:
{{- toYaml $v.resources | nindent 12 }}
volumes:
- name: keys
secret:
secretName: fluxer-keys
optional: true
{{- end }}
{{- define "fluxer.service" -}}
{{- $name := .name -}}
{{- $selectorName := .selectorName | default $name -}}
{{- $v := .values -}}
{{- $ctx := .context -}}
apiVersion: v1
kind: Service
metadata:
name: {{ $name }}
namespace: {{ $ctx.Values.global.namespace }}
labels:
{{- include "fluxer.labels" $ctx | nindent 4 }}
{{- include "fluxer.selectorLabels" (dict "name" $name "context" $ctx) | nindent 4 }}
spec:
type: ClusterIP
ports:
- port: {{ $v.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "fluxer.selectorLabels" (dict "name" $selectorName "context" $ctx) | nindent 4 }}
{{- end }}
{{- define "fluxer.pdb" -}}
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: {{ .name }}-pdb
namespace: {{ .context.Values.global.namespace }}
labels:
{{- include "fluxer.labels" .context | nindent 4 }}
spec:
minAvailable: {{ .minAvailable }}
selector:
matchLabels:
{{- include "fluxer.selectorLabels" (dict "name" .name "context" .context) | nindent 6 }}
{{- end }}
-11
View File
@@ -1,11 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: v2
name: docs
description: Fluxer documentation service
type: application
version: 0.1.0
dependencies:
- name: common
version: 0.1.0
repository: file://../common
-3
View File
@@ -1,3 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{include "fluxer.deployment" (dict "name" .Values.app.name "values" .Values.app "context" .)}}
-3
View File
@@ -1,3 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{include "fluxer.pdb" (dict "name" .Values.app.name "minAvailable" .Values.pdb.minAvailable "context" .)}}
-3
View File
@@ -1,3 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{include "fluxer.service" (dict "name" .Values.app.name "values" .Values.app "context" .)}}
-23
View File
@@ -1,23 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
app:
build:
channel: stable
version: ""
image: fluxer-docs
name: docs
port: 8080
replicas: 2
resources:
limits:
memory: 128Mi
requests:
cpu: 50m
memory: 64Mi
tag: ""
global:
imagePullSecret: ghcr-pull-secret
namespace: fluxer
registry: ""
pdb:
minAvailable: 50%
-22
View File
@@ -1,22 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
global:
namespace: fluxer
imagePullSecret: ghcr-pull-secret
registry: ""
app:
name: ''
image: ''
tag: ''
replicas: 2
port: 8080
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
memory: 128Mi
pdb:
minAvailable: '50%'
-11
View File
@@ -1,11 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: v2
name: gateway
description: Fluxer WebSocket gateway service
type: application
version: 0.1.0
dependencies:
- name: common
version: 0.1.0
repository: file://../common
@@ -1,40 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{ $gatewayValues := .Values.gateway -}}
{{- $cluster := .Values.cluster | default dict -}}
{{- if dig "enabled" false $cluster -}}
{{- $clusterEnv := list
(dict "name" "FLUXER_GATEWAY_CLUSTER_ENABLED" "value" "true")
(dict "name" "FLUXER_GATEWAY_CLUSTER_DISCOVERY_DNS_NAME" "value" (dig "discoveryDnsName" "" $cluster))
(dict "name" "FLUXER_GATEWAY_CLUSTER_DISCOVERY_NODE_BASENAME" "value" (dig "discoveryNodeBasename" "fluxer_gateway" $cluster))
(dict "name" "FLUXER_GATEWAY_CLUSTER_DISCOVERY_POLL_INTERVAL_MS" "value" (printf "%d" (int (dig "discoveryPollIntervalMs" 5000 $cluster))))
-}}
{{- if dig "enabled" false .Values.roles -}}
{{- $clusterEnv = concat (list (dict "name" "FLUXER_GATEWAY_ROLE" "value" (dig "websocket" "role" "websocket" .Values.roles))) $clusterEnv -}}
{{- end -}}
{{- $gatewayValues = mergeOverwrite (deepCopy .Values.gateway) (dict "env" (concat $clusterEnv (get .Values.gateway "env" | default (list)))) -}}
{{- end }}
{{- $hotpatch := get .Values.gateway "hotpatch" | default dict -}}
{{- if dig "enabled" false $hotpatch -}}
{{- $hotpatchEnv := list
(dict "name" "FLUXER_GATEWAY_HOTPATCH_ENABLED" "value" "true")
(dict "name" "FLUXER_GATEWAY_HOTPATCH_CASSANDRA_PORT" "value" (printf "%d" (int (get $hotpatch "cassandraPort" | default 9042))))
(dict "name" "FLUXER_GATEWAY_HOTPATCH_CASSANDRA_KEYSPACE" "value" (get $hotpatch "cassandraKeyspace" | default "fluxer"))
(dict "name" "FLUXER_GATEWAY_HOTPATCH_POLL_INTERVAL_MS" "value" (printf "%d" (int (get $hotpatch "pollIntervalMs" | default 5000))))
(dict "name" "FLUXER_GATEWAY_HOTPATCH_STARTUP_SYNC_TIMEOUT_MS" "value" (printf "%d" (int (get $hotpatch "startupSyncTimeoutMs" | default 30000))))
-}}
{{- if get $hotpatch "cassandraHosts" -}}
{{- $hotpatchEnv = append $hotpatchEnv (dict "name" "FLUXER_GATEWAY_HOTPATCH_CASSANDRA_HOSTS" "value" (get $hotpatch "cassandraHosts")) -}}
{{- end -}}
{{- $publicKeysSecret := get $hotpatch "publicKeysSecret" | default dict -}}
{{- if get $publicKeysSecret "name" -}}
{{- $hotpatchEnv = append $hotpatchEnv (dict "name" "FLUXER_GATEWAY_HOTPATCH_PUBLIC_KEYS" "valueFrom" (dict "secretKeyRef" (dict "name" (get $publicKeysSecret "name") "key" (get $publicKeysSecret "key" | default "public_keys")))) -}}
{{- end -}}
{{- $credentialsSecret := get $hotpatch "cassandraCredentialsSecret" | default dict -}}
{{- if get $credentialsSecret "name" -}}
{{- $hotpatchEnv = append $hotpatchEnv (dict "name" "FLUXER_GATEWAY_HOTPATCH_CASSANDRA_USERNAME" "valueFrom" (dict "secretKeyRef" (dict "name" (get $credentialsSecret "name") "key" (get $credentialsSecret "usernameKey" | default "username")))) -}}
{{- $hotpatchEnv = append $hotpatchEnv (dict "name" "FLUXER_GATEWAY_HOTPATCH_CASSANDRA_PASSWORD" "valueFrom" (dict "secretKeyRef" (dict "name" (get $credentialsSecret "name") "key" (get $credentialsSecret "passwordKey" | default "password")))) -}}
{{- end -}}
{{- $gatewayValues = mergeOverwrite (deepCopy $gatewayValues) (dict "env" (concat $hotpatchEnv (get $gatewayValues "env" | default (list)))) -}}
{{- end }}
{{ include "fluxer.deployment" (dict "name" "gateway" "values" $gatewayValues "context" .) }}
@@ -1,70 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{- $clusterEnabled := dig "enabled" false .Values.cluster -}}
{{- $distPort := int (dig "erlangDistribution" "port" 8081 .Values.cluster) }}
{{- $epmdPort := int (dig "erlangDistribution" "epmdPort" 4369 .Values.cluster) }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: gateway
namespace: {{.Values.global.namespace}}
labels: {{- include "fluxer.labels" . | nindent 4}}
spec:
podSelector:
matchLabels:
{{- if dig "enabled" false .Values.roles }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/part-of: fluxer
{{- else }}
{{- include "fluxer.selectorLabels" (dict "name" "gateway" "context" .) | nindent 6 }}
{{- end }}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
ports:
- port: {{.Values.gateway.port}}
protocol: TCP
- from:
- podSelector:
matchLabels:
app.kubernetes.io/name: api
- podSelector:
matchLabels:
app.kubernetes.io/name: api-canary
- podSelector:
matchLabels:
app.kubernetes.io/name: worker-realtime
- podSelector:
matchLabels:
app.kubernetes.io/name: worker-lifecycle
- podSelector:
matchLabels:
app.kubernetes.io/name: worker-batch
ports:
- port: {{.Values.gateway.port}}
protocol: TCP
- from:
- podSelector:
matchLabels:
{{- if dig "enabled" false .Values.roles }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/part-of: fluxer
{{- else }}
{{- include "fluxer.selectorLabels" (dict "name" "gateway" "context" .) | nindent 14 }}
{{- end }}
ports:
- port: {{.Values.gateway.port}}
protocol: TCP
{{- if $clusterEnabled }}
- port: {{ $epmdPort }}
protocol: TCP
- port: {{ $distPort }}
protocol: TCP
{{- end }}
egress:
- {}
-5
View File
@@ -1,5 +0,0 @@
{{- if and .Values.pdb.enabled (gt (int .Values.gateway.replicas) 1) }}
# SPDX-License-Identifier: AGPL-3.0-or-later
{{ include "fluxer.pdb" (dict "name" "gateway" "minAvailable" .Values.pdb.minAvailable "context" .) }}
{{- end }}
@@ -1,40 +0,0 @@
{{- $clusterEnabled := dig "enabled" false .Values.cluster -}}
{{- $distPort := int (dig "erlangDistribution" "port" 8081 .Values.cluster) -}}
{{- $epmdPort := int (dig "erlangDistribution" "epmdPort" 4369 .Values.cluster) -}}
# SPDX-License-Identifier: AGPL-3.0-or-later
{{include "fluxer.service" (dict "name" "gateway" "values" .Values.gateway "context" .)}}
---
apiVersion: v1
kind: Service
metadata:
name: fluxer-gateway-headless
namespace: {{ .Values.global.namespace }}
labels:
{{- include "fluxer.labels" . | nindent 4 }}
{{- include "fluxer.selectorLabels" (dict "name" "gateway" "context" .) | nindent 4 }}
spec:
type: ClusterIP
clusterIP: None
ports:
- port: {{ .Values.gateway.port }}
targetPort: http
protocol: TCP
name: http
{{- if $clusterEnabled }}
- port: {{ $epmdPort }}
targetPort: epmd
protocol: TCP
name: epmd
- port: {{ $distPort }}
targetPort: erl-dist
protocol: TCP
name: erl-dist
{{- end }}
selector:
{{- if dig "enabled" false .Values.roles }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/part-of: fluxer
{{- else }}
{{- include "fluxer.selectorLabels" (dict "name" "gateway" "context" .) | nindent 4 }}
{{- end }}
@@ -1,255 +0,0 @@
{{- if dig "enabled" false .Values.roles }}
{{- $cluster := .Values.cluster | default dict -}}
{{- $distPort := int (dig "erlangDistribution" "port" 8081 $cluster) -}}
{{- $epmdPort := int (dig "erlangDistribution" "epmdPort" 4369 $cluster) -}}
{{- $cookie := dig "erlangCookieSecret" (dict) $cluster -}}
{{- $cookieName := get $cookie "name" | default "fluxer-gateway-erlang-cookie" -}}
{{- $cookieKey := get $cookie "key" | default "cookie" -}}
{{- $nodeBasename := dig "discoveryNodeBasename" "fluxer_gateway" $cluster -}}
{{- $dnsName := dig "discoveryDnsName" "" $cluster -}}
{{- if not $dnsName }}
{{- fail "cluster.discoveryDnsName is required when roles.enabled=true" }}
{{- end }}
{{- $pollIntervalMs := int (dig "discoveryPollIntervalMs" 5000 $cluster) -}}
{{- $gateway := .Values.gateway -}}
{{- $common := .Values.roles.common | default dict -}}
{{- $build := get $gateway "build" | default dict -}}
{{- $hotpatch := get $gateway "hotpatch" | default dict -}}
{{- $hotpatchPublicKeysSecret := get $hotpatch "publicKeysSecret" | default dict -}}
{{- $hotpatchCredentialsSecret := get $hotpatch "cassandraCredentialsSecret" | default dict -}}
{{- $roles := list "sessions" "presence" "guilds" "calls" "push" -}}
{{- range $role := $roles }}
{{- $roleValues := get $.Values.roles $role | default dict -}}
{{- if dig "enabled" true $roleValues }}
{{- $name := printf "gateway-%s" $role -}}
{{- $replicas := int (dig "replicas" (dig "replicas" 1 $common) $roleValues) -}}
{{- $resources := get $roleValues "resources" | default (get $common "resources" | default $gateway.resources) -}}
{{- $nodeSelector := get $roleValues "nodeSelector" | default (get $common "nodeSelector" | default $gateway.nodeSelector) -}}
{{- $tolerations := get $roleValues "tolerations" | default (get $common "tolerations" | default $gateway.tolerations) -}}
{{- $affinity := get $roleValues "affinity" | default (get $common "affinity" | default dict) -}}
{{- $topologySpreadConstraints := get $roleValues "topologySpreadConstraints" | default (get $common "topologySpreadConstraints" | default list) -}}
---
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ $name }}
namespace: {{ $.Values.global.namespace }}
labels:
{{- include "fluxer.labels" $ | nindent 4 }}
{{- include "fluxer.selectorLabels" (dict "name" $name "context" $) | nindent 4 }}
spec:
serviceName: fluxer-gateway-headless
replicas: {{ $replicas }}
selector:
matchLabels:
{{- include "fluxer.selectorLabels" (dict "name" $name "context" $) | nindent 6 }}
updateStrategy:
type: RollingUpdate
template:
metadata:
labels:
{{- include "fluxer.labels" $ | nindent 8 }}
{{- include "fluxer.selectorLabels" (dict "name" $name "context" $) | nindent 8 }}
app.kubernetes.io/gateway-role: {{ $role | quote }}
spec:
{{- include "fluxer.imagePullSecrets" $ | nindent 6 }}
terminationGracePeriodSeconds: {{ int (dig "terminationGracePeriodSeconds" 45 $roleValues) }}
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
{{- if $affinity }}
affinity:
{{- toYaml $affinity | nindent 8 }}
{{- end }}
{{- if $topologySpreadConstraints }}
topologySpreadConstraints:
{{- toYaml $topologySpreadConstraints | nindent 8 }}
{{- else }}
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app.kubernetes.io/name: {{ $name }}
app.kubernetes.io/instance: {{ $.Release.Name }}
{{- end }}
{{- if $nodeSelector }}
nodeSelector:
{{- toYaml $nodeSelector | nindent 8 }}
{{- end }}
{{- if $tolerations }}
tolerations:
{{- toYaml $tolerations | nindent 8 }}
{{- end }}
containers:
- name: gateway
image: {{ include "fluxer.image" (dict "image" $gateway.image "tag" $gateway.tag "context" $) }}
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: false
ports:
- name: http
containerPort: {{ $gateway.port }}
protocol: TCP
- name: epmd
containerPort: {{ $epmdPort }}
protocol: TCP
- name: erl-dist
containerPort: {{ $distPort }}
protocol: TCP
env:
- name: NODE_ENV
value: production
- name: FLUXER_ENV
value: production
- name: FLUXER_GATEWAY_ROLE
value: {{ $role | quote }}
- name: FLUXER_GATEWAY_CLUSTER_ENABLED
value: "true"
- name: FLUXER_GATEWAY_CLUSTER_DISCOVERY_DNS_NAME
value: {{ $dnsName | quote }}
- name: FLUXER_GATEWAY_CLUSTER_DISCOVERY_NODE_BASENAME
value: {{ $nodeBasename | quote }}
- name: FLUXER_GATEWAY_CLUSTER_DISCOVERY_POLL_INTERVAL_MS
value: {{ printf "%d" $pollIntervalMs | quote }}
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: FLUXER_ERLANG_NODE_NAME
value: {{ printf "%s@$(POD_IP)" $nodeBasename | quote }}
- name: FLUXER_ERLANG_DIST_PORT
value: {{ printf "%d" $distPort | quote }}
- name: FLUXER_ERLANG_COOKIE
valueFrom:
secretKeyRef:
name: {{ $cookieName }}
key: {{ $cookieKey }}
{{- if get $build "sha" }}
- name: BUILD_SHA
value: {{ get $build "sha" | quote }}
{{- end }}
{{- if get $build "number" }}
- name: BUILD_NUMBER
value: {{ get $build "number" | quote }}
{{- end }}
{{- if get $build "timestamp" }}
- name: BUILD_TIMESTAMP
value: {{ get $build "timestamp" | quote }}
{{- end }}
{{- if get $build "channel" }}
- name: RELEASE_CHANNEL
value: {{ get $build "channel" | quote }}
{{- end }}
{{- if dig "enabled" false $hotpatch }}
- name: FLUXER_GATEWAY_HOTPATCH_ENABLED
value: "true"
{{- if get $hotpatch "cassandraHosts" }}
- name: FLUXER_GATEWAY_HOTPATCH_CASSANDRA_HOSTS
value: {{ get $hotpatch "cassandraHosts" | quote }}
{{- end }}
- name: FLUXER_GATEWAY_HOTPATCH_CASSANDRA_PORT
value: {{ printf "%d" (int (get $hotpatch "cassandraPort" | default 9042)) | quote }}
- name: FLUXER_GATEWAY_HOTPATCH_CASSANDRA_KEYSPACE
value: {{ get $hotpatch "cassandraKeyspace" | default "fluxer" | quote }}
- name: FLUXER_GATEWAY_HOTPATCH_POLL_INTERVAL_MS
value: {{ printf "%d" (int (get $hotpatch "pollIntervalMs" | default 5000)) | quote }}
- name: FLUXER_GATEWAY_HOTPATCH_STARTUP_SYNC_TIMEOUT_MS
value: {{ printf "%d" (int (get $hotpatch "startupSyncTimeoutMs" | default 30000)) | quote }}
{{- if get $hotpatchPublicKeysSecret "name" }}
- name: FLUXER_GATEWAY_HOTPATCH_PUBLIC_KEYS
valueFrom:
secretKeyRef:
name: {{ get $hotpatchPublicKeysSecret "name" | quote }}
key: {{ get $hotpatchPublicKeysSecret "key" | default "public_keys" | quote }}
{{- end }}
{{- if get $hotpatchCredentialsSecret "name" }}
- name: FLUXER_GATEWAY_HOTPATCH_CASSANDRA_USERNAME
valueFrom:
secretKeyRef:
name: {{ get $hotpatchCredentialsSecret "name" | quote }}
key: {{ get $hotpatchCredentialsSecret "usernameKey" | default "username" | quote }}
- name: FLUXER_GATEWAY_HOTPATCH_CASSANDRA_PASSWORD
valueFrom:
secretKeyRef:
name: {{ get $hotpatchCredentialsSecret "name" | quote }}
key: {{ get $hotpatchCredentialsSecret "passwordKey" | default "password" | quote }}
{{- end }}
{{- end }}
{{- if $.Values.global.env }}
{{- toYaml $.Values.global.env | nindent 12 }}
{{- end }}
{{- if $gateway.env }}
{{- toYaml $gateway.env | nindent 12 }}
{{- end }}
{{- if $common.env }}
{{- toYaml $common.env | nindent 12 }}
{{- end }}
{{- if $roleValues.env }}
{{- toYaml $roleValues.env | nindent 12 }}
{{- end }}
{{- if or $.Values.global.envFrom $gateway.envFrom $common.envFrom $roleValues.envFrom }}
envFrom:
{{- if $.Values.global.envFrom }}
{{- toYaml $.Values.global.envFrom | nindent 12 }}
{{- end }}
{{- if $gateway.envFrom }}
{{- toYaml $gateway.envFrom | nindent 12 }}
{{- end }}
{{- if $common.envFrom }}
{{- toYaml $common.envFrom | nindent 12 }}
{{- end }}
{{- if $roleValues.envFrom }}
{{- toYaml $roleValues.envFrom | nindent 12 }}
{{- end }}
{{- end }}
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- {{ printf "curl -fsS --max-time 2 http://127.0.0.1:%d/_health/drain >/dev/null 2>&1 || true; sleep 20" (int $gateway.port) | quote }}
volumeMounts:
- name: keys
mountPath: /etc/fluxer/keys
readOnly: true
livenessProbe:
httpGet:
path: "/_health"
port: http
initialDelaySeconds: 10
periodSeconds: 15
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
exec:
command:
- /bin/sh
- -c
- {{ printf "curl -fsS --max-time 5 http://127.0.0.1:%d/_health/ready >/dev/null 2>&1 || exit 1" (int $gateway.port) | quote }}
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 3
startupProbe:
httpGet:
path: "/_health"
port: http
initialDelaySeconds: 0
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 30
resources:
{{- toYaml $resources | nindent 12 }}
volumes:
- name: keys
secret:
secretName: fluxer-keys
optional: true
{{ end }}
{{ end }}
{{ end }}
-164
View File
@@ -1,164 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Live user-supplied values for the fluxer-gateway release as of 2026-05-23T21:25:52Z.
# Captured via: helm -n fluxer get values fluxer-gateway
# Apply with: helm upgrade fluxer-gateway deploy/helm/gateway -f deploy/helm/gateway/values.yaml -f deploy/helm/gateway/values.prod.yaml
cluster:
discoveryDnsName: fluxer-gateway-headless.fluxer.svc.cluster.local
discoveryNodeBasename: fluxer_gateway
discoveryPollIntervalMs: 5000
enabled: true
erlangCookieSecret:
key: cookie
name: fluxer-gateway-erlang-cookie
erlangDistribution:
epmdPort: 4369
port: 8081
gateway:
build:
channel: stable
version: ""
env:
- name: FLUXER_GATEWAY_STATIC_CDN_ENDPOINT
value: "https://fluxerstatic.com"
- name: FLUXER_GATEWAY_PRESENCE_PUSH_BUFFER_MAX_ENTRIES
value: "128"
- name: FLUXER_GATEWAY_PRESENCE_PUSH_BUFFER_MAX_BYTES
value: "1048576"
image: fluxer-gateway
hotpatch:
enabled: true
cassandraHosts: int.flx-nyc-db1.srv.fluxer.dev
cassandraPort: 9041
cassandraKeyspace: fluxer
pollIntervalMs: 5000
startupSyncTimeoutMs: 30000
publicKeysSecret:
name: fluxer-gateway-hotpatch-public-keys
key: public_keys
cassandraCredentialsSecret:
name: fluxer-runtime-env-shared
usernameKey: FLUXER_CASSANDRA_USERNAME
passwordKey: FLUXER_CASSANDRA_PASSWORD
livenessProbe:
timeoutSeconds: 5
minReadySeconds: 0
nodeSelector: null
port: 8080
preStopDrain:
enabled: true
retryCount: 6
retryIntervalSeconds: 1
sleepSeconds: 30
timeoutSeconds: 2
preserveLiveReplicas: false
readinessProbe:
execEnabled: true
failureThreshold: 3
initialDelaySeconds: 5
path: /_health/ready
periodSeconds: 5
timeoutSeconds: 5
replicas: 16
resources:
limits:
memory: 16Gi
requests:
cpu: 500m
memory: 512Mi
rollingUpdate:
maxSurge: 0
maxUnavailable: 1
startupProbe:
enabled: true
failureThreshold: 30
initialDelaySeconds: 0
path: /_health
periodSeconds: 5
timeoutSeconds: 5
tag: ""
terminationGracePeriodSeconds: 45
tolerations:
- effect: NoSchedule
key: dedicated
operator: Equal
value: gateway
roles:
enabled: true
websocket:
role: websocket
common:
nodeSelector: null
resources:
requests:
cpu: 500m
memory: 768Mi
limits:
memory: 12Gi
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 60
preference:
matchExpressions:
- key: node.kubernetes.io/instance-type
operator: In
values:
- vhf-16c-58gb
sessions:
enabled: true
replicas: 12
resources:
requests:
cpu: 750m
memory: 2Gi
limits:
memory: 16Gi
presence:
enabled: true
replicas: 6
resources:
requests:
cpu: 500m
memory: 768Mi
limits:
memory: 6Gi
guilds:
enabled: true
replicas: 12
resources:
requests:
cpu: 750m
memory: 1Gi
limits:
memory: 8Gi
calls:
enabled: true
replicas: 4
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
memory: 4Gi
push:
enabled: true
replicas: 4
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
memory: 4Gi
global:
imagePullSecret: ghcr-pull-secret
namespace: fluxer
registry: ""
envFrom:
- secretRef:
name: fluxer-runtime-env-shared
pdb:
enabled: false
minAvailable: 1
-118
View File
@@ -1,118 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
global:
namespace: fluxer
imagePullSecret: ghcr-pull-secret
registry: ""
gateway:
image: fluxer-gateway
tag: ''
replicas: 1
preserveLiveReplicas: false
port: 8080
rollingUpdate:
maxSurge: 0
maxUnavailable: 1
minReadySeconds: 0
terminationGracePeriodSeconds: 45
readinessProbe:
path: /_health/ready
execEnabled: true
timeoutSeconds: 5
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3
livenessProbe:
timeoutSeconds: 5
startupProbe:
enabled: true
path: /_health
initialDelaySeconds: 0
periodSeconds: 5
failureThreshold: 30
timeoutSeconds: 5
preStopDrain:
enabled: true
sleepSeconds: 30
timeoutSeconds: 2
retryCount: 6
retryIntervalSeconds: 1
nodeSelector:
kubernetes.io/hostname: flx-nyc-k8s-worker-efd1167e6219
tolerations:
- key: dedicated
operator: Equal
value: gateway
effect: NoSchedule
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
memory: 16Gi
env:
- name: FLUXER_GATEWAY_STATIC_CDN_ENDPOINT
value: "https://fluxerstatic.com"
- name: FLUXER_GATEWAY_PRESENCE_PUSH_BUFFER_MAX_ENTRIES
value: "128"
- name: FLUXER_GATEWAY_PRESENCE_PUSH_BUFFER_MAX_BYTES
value: "1048576"
hotpatch:
enabled: false
cassandraHosts: ''
cassandraPort: 9042
cassandraKeyspace: fluxer
pollIntervalMs: 5000
startupSyncTimeoutMs: 30000
publicKeysSecret:
name: ''
key: public_keys
cassandraCredentialsSecret:
name: ''
usernameKey: username
passwordKey: password
cluster:
enabled: false
discoveryDnsName: ''
discoveryNodeBasename: fluxer_gateway
discoveryPollIntervalMs: 5000
erlangDistribution:
port: 8081
epmdPort: 4369
erlangCookieSecret:
name: fluxer-gateway-erlang-cookie
key: cookie
roles:
enabled: false
websocket:
role: websocket
common:
replicas: 1
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
memory: 8Gi
sessions:
enabled: true
replicas: 1
presence:
enabled: true
replicas: 1
guilds:
enabled: true
replicas: 1
calls:
enabled: true
replicas: 1
push:
enabled: true
replicas: 1
pdb:
enabled: false
minAvailable: 1
-9
View File
@@ -1,9 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: v2
name: gifs
version: 0.1.0
dependencies:
- name: svc-common
version: 0.1.0
repository: file://../svc-common
-13
View File
@@ -1,13 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{ include "svc-common.statefulset" . }}
---
{{ include "svc-common.deployment" . }}
---
{{ include "svc-common.headless-service" . }}
---
{{ include "svc-common.service" . }}
---
{{ include "svc-common.pdb" . }}
---
{{ include "svc-common.router-pdb" . }}
-32
View File
@@ -1,32 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
svc:
shard:
replicas: 4
resources:
requests:
cpu: 100m
memory: 512Mi
limits:
memory: 1Gi
router:
replicas: 3
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 512Mi
cache:
maxEntries: 500000
ttlMs: '30000'
extraEnv:
- name: FLUXER_MEDIA_PROXY_ENDPOINT
value: http://media-proxy:8080
- name: FLUXER_MEDIA_PROXY_PUBLIC_ENDPOINT
value: https://fluxerusercontent.com
- name: FLUXER_MEDIA_PROXY_SECRET_KEY
valueFrom:
secretKeyRef:
name: fluxer-media-proxy-v2-env
key: FLUXER_MEDIA_PROXY_SECRET_KEY
-55
View File
@@ -1,55 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
global:
namespace: fluxer
imagePullSecret: ghcr-pull-secret
registry: ""
svc:
name: gifs
image: fluxer-gifs
tag: ''
shard:
replicas: 2
port: 8090
minReadySeconds: 10
terminationGracePeriodSeconds: 60
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 512Mi
router:
replicas: 2
port: 8090
minReadySeconds: 10
maxSurge: 1
maxUnavailable: 0
terminationGracePeriodSeconds: 60
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
memory: 256Mi
nats:
url: nats://nats-core:4222
cache:
maxEntries: 250000
ttlMs: '30000'
extraEnv:
- name: FLUXER_MEDIA_PROXY_ENDPOINT
value: http://media-proxy:8080
- name: FLUXER_MEDIA_PROXY_PUBLIC_ENDPOINT
value: https://fluxerusercontent.com
- name: FLUXER_MEDIA_PROXY_SECRET_KEY
valueFrom:
secretKeyRef:
name: fluxer-media-proxy-v2-env
key: FLUXER_MEDIA_PROXY_SECRET_KEY
nodeSelector: {}
tolerations: []
pdb:
minAvailable: '50%'
-11
View File
@@ -1,11 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: v2
name: infra
description: Fluxer infrastructure (NATS, Valkey, Ingress)
type: application
version: 0.1.0
dependencies:
- name: common
version: 0.1.0
repository: file://../common
@@ -1,133 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Daily sync of the MaxMind GeoLite2 City and ASN MMDB files into S3.
# Runtime services read these out of the CDN bucket. Adopted into helm
# from a previously hand-applied kubectl manifest.
apiVersion: batch/v1
kind: CronJob
metadata:
name: geoip-sync
namespace: {{ .Values.global.namespace }}
labels:
app.kubernetes.io/name: geoip-sync
{{- include "fluxer.labels" . | nindent 4 }}
spec:
schedule: {{ .Values.geoipSync.schedule | quote }}
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 1
failedJobsHistoryLimit: 3
jobTemplate:
spec:
activeDeadlineSeconds: {{ .Values.geoipSync.activeDeadlineSeconds }}
backoffLimit: {{ .Values.geoipSync.backoffLimit }}
template:
metadata:
labels:
app.kubernetes.io/name: geoip-sync
app.kubernetes.io/part-of: fluxer
spec:
restartPolicy: OnFailure
terminationGracePeriodSeconds: 60
imagePullSecrets:
- name: {{ .Values.global.imagePullSecret }}
containers:
- name: sync
image: {{ .Values.geoipSync.image }}
imagePullPolicy: IfNotPresent
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: false
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
capabilities:
drop: ["ALL"]
seccompProfile:
type: RuntimeDefault
env:
- name: GEOIP_BUCKET
value: {{ .Values.geoipSync.bucket | quote }}
- name: GEOIP_CITY_UPSTREAM_URL
value: {{ .Values.geoipSync.cityUpstreamUrl | quote }}
- name: GEOIP_ASN_UPSTREAM_URL
value: {{ .Values.geoipSync.asnUpstreamUrl | quote }}
envFrom:
- secretRef:
name: {{ .Values.geoipSync.envSecret }}
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 512Mi
command:
- sh
- -c
- |
set -eu
: "${GEOIP_BUCKET:?missing GEOIP_BUCKET}"
: "${GEOIP_CITY_UPSTREAM_URL:?missing GEOIP_CITY_UPSTREAM_URL}"
: "${GEOIP_ASN_UPSTREAM_URL:?missing GEOIP_ASN_UPSTREAM_URL}"
: "${FLUXER_S3_ACCESS_KEY_ID:?missing FLUXER_S3_ACCESS_KEY_ID}"
: "${FLUXER_S3_SECRET_ACCESS_KEY:?missing FLUXER_S3_SECRET_ACCESS_KEY}"
: "${FLUXER_S3_ENDPOINT:?missing FLUXER_S3_ENDPOINT}"
: "${FLUXER_S3_REGION:?missing FLUXER_S3_REGION}"
export AWS_ACCESS_KEY_ID="$FLUXER_S3_ACCESS_KEY_ID"
export AWS_SECRET_ACCESS_KEY="$FLUXER_S3_SECRET_ACCESS_KEY"
export AWS_DEFAULT_REGION="$FLUXER_S3_REGION"
WORKDIR=$(mktemp -d)
trap 'rm -rf "$WORKDIR"' EXIT
# MMDB files end with the ASCII string "MaxMind.com" after
# their metadata marker. Verifying this tail before upload
# catches the case where an upstream returns an HTML error
# page or a zero-byte body.
fetch_and_verify() {
local url="$1"
local dest="$2"
echo "-> fetching $url"
curl --fail --location --silent --show-error \
--user-agent 'fluxer-geoip-sync/1.0' \
--max-time 120 \
--output "$dest" \
"$url"
local size
size=$(wc -c < "$dest")
if [ "$size" -lt 1024 ]; then
echo "refusing to upload ${dest}: file is ${size} bytes, too small" >&2
return 1
fi
if ! tail -c 2048 "$dest" | grep -q "MaxMind.com"; then
echo "refusing to upload ${dest}: MaxMind.com marker not found in trailer" >&2
return 1
fi
echo " ok (${size} bytes)"
}
fetch_and_verify "$GEOIP_CITY_UPSTREAM_URL" "$WORKDIR/GeoLite2-City.mmdb"
fetch_and_verify "$GEOIP_ASN_UPSTREAM_URL" "$WORKDIR/GeoLite2-ASN.mmdb"
# Atomic-ish replacement: upload to a versioned side-key
# first, then copy to the canonical key. If the final copy
# fails the previous canonical file is untouched.
STAMP=$(date -u +%Y%m%dT%H%M%SZ)
aws --endpoint-url "$FLUXER_S3_ENDPOINT" s3 cp \
"$WORKDIR/GeoLite2-City.mmdb" \
"s3://${GEOIP_BUCKET}/archive/GeoLite2-City-${STAMP}.mmdb"
aws --endpoint-url "$FLUXER_S3_ENDPOINT" s3 cp \
"$WORKDIR/GeoLite2-ASN.mmdb" \
"s3://${GEOIP_BUCKET}/archive/GeoLite2-ASN-${STAMP}.mmdb"
aws --endpoint-url "$FLUXER_S3_ENDPOINT" s3 cp \
"$WORKDIR/GeoLite2-City.mmdb" \
"s3://${GEOIP_BUCKET}/GeoLite2-City.mmdb"
aws --endpoint-url "$FLUXER_S3_ENDPOINT" s3 cp \
"$WORKDIR/GeoLite2-ASN.mmdb" \
"s3://${GEOIP_BUCKET}/GeoLite2-ASN.mmdb"
echo "geoip-sync complete: city=${STAMP} asn=${STAMP}"
-278
View File
@@ -1,278 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{ $hosts := .Values.ingress.hosts -}}
{{ $ports := .Values.ports -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: fluxer-ingress
namespace: {{ .Values.global.namespace }}
labels:
{{- include "fluxer.labels" . | nindent 4 }}
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
ingressClassName: {{ .Values.ingress.className }}
rules:
- host: {{ $hosts.api }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api
port:
number: {{ $ports.api }}
- host: {{ $hosts.apiCanary }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-canary
port:
number: {{ $ports.apiCanary }}
- host: {{ $hosts.appProxy }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-proxy
port:
number: {{ $ports.appProxy }}
- host: {{ $hosts.appProxyCanary }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-proxy-canary
port:
number: {{ $ports.appProxyCanary }}
- host: {{ $hosts.admin }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin
port:
number: {{ $ports.admin }}
- host: {{ $hosts.adminCanary }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-canary
port:
number: {{ $ports.adminCanary }}
- host: {{ $hosts.marketing }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: marketing
port:
number: {{ $ports.marketing }}
{{- with $hosts.help }}
- host: {{ . }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: marketing
port:
number: {{ $ports.marketing }}
{{- end }}
{{- with $hosts.blog }}
- host: {{ . }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: marketing
port:
number: {{ $ports.marketing }}
{{- end }}
{{- with $hosts.docs }}
- host: {{ . }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: docs
port:
number: {{ $ports.docs }}
{{- end }}
{{- range $hosts.marketingAliases }}
- host: {{ . }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: marketing
port:
number: {{ $ports.marketing }}
{{- end }}
- host: {{ $hosts.marketingCanary }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: marketing-canary
port:
number: {{ $ports.marketingCanary }}
- host: {{ $hosts.mediaProxy }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: media-proxy
port:
number: {{ $ports.mediaProxy }}
- host: {{ $hosts.staticProxy }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: static-proxy
port:
number: {{ $ports.staticProxy }}
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: fluxer-ingress-gateway
namespace: {{ .Values.global.namespace }}
labels:
{{- include "fluxer.labels" . | nindent 4 }}
annotations:
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/upstream-hash-by: "$remote_addr"
nginx.ingress.kubernetes.io/websocket-services: gateway
spec:
ingressClassName: {{ .Values.ingress.className }}
rules:
- host: {{ $hosts.gateway }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: gateway
port:
number: {{ $ports.gateway }}
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: fluxer-ingress-api-proxy
namespace: {{ .Values.global.namespace }}
labels:
{{- include "fluxer.labels" . | nindent 4 }}
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: {{ .Values.ingress.className }}
rules:
- host: {{ $hosts.appProxy }}
http:
paths:
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api
port:
number: {{ $ports.api }}
- host: {{ $hosts.appProxyCanary }}
http:
paths:
- path: /api(/|$)(.*)
pathType: ImplementationSpecific
backend:
service:
name: api-canary
port:
number: {{ $ports.apiCanary }}
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: fluxer-ingress-uploads
namespace: {{ .Values.global.namespace }}
labels:
{{- include "fluxer.labels" . | nindent 4 }}
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "500m"
nginx.ingress.kubernetes.io/proxy-request-buffering: "off"
nginx.ingress.kubernetes.io/proxy-buffering: "off"
nginx.ingress.kubernetes.io/proxy-read-timeout: "900"
nginx.ingress.kubernetes.io/proxy-send-timeout: "900"
nginx.ingress.kubernetes.io/client-body-buffer-size: "1m"
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
ingressClassName: {{ .Values.ingress.className }}
rules:
- host: {{ $hosts.uploads }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: uploads
port:
number: {{ $ports.uploads }}
@@ -1,26 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: v1
kind: ConfigMap
metadata:
name: nats-config
namespace: {{.Values.global.namespace}}
labels: {{- include "fluxer.labels" . | nindent 4}}
data:
nats.conf: |
listen: 0.0.0.0:{{ .Values.nats.clientPort }}
http: 0.0.0.0:{{ .Values.nats.monitorPort }}
max_payload: {{ .Values.nats.maxPayload | default "64MB" }}
max_pending: {{ .Values.nats.maxPending | default "128MB" }}
max_connections: {{ .Values.nats.maxConnections | default 2048 }}
cluster {
name: fluxer-nats
listen: 0.0.0.0:{{ .Values.nats.clusterPort }}
routes = [
{{- range $i := until (int .Values.nats.replicas) }}
nats-route://nats-{{ $i }}.nats-headless.{{ $.Values.global.namespace }}.svc.cluster.local:{{ $.Values.nats.clusterPort }}
{{- end }}
]
}
@@ -1,44 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: v1
kind: Service
metadata:
name: nats-headless
namespace: {{ .Values.global.namespace }}
labels:
{{- include "fluxer.labels" . | nindent 4 }}
app.kubernetes.io/name: nats
spec:
type: ClusterIP
clusterIP: None
ports:
- name: client
port: {{ .Values.nats.clientPort }}
targetPort: client
- name: cluster
port: {{ .Values.nats.clusterPort }}
targetPort: cluster
- name: monitor
port: {{ .Values.nats.monitorPort }}
targetPort: monitor
selector:
app.kubernetes.io/name: nats
app.kubernetes.io/instance: {{ .Release.Name }}
---
apiVersion: v1
kind: Service
metadata:
name: nats-core
namespace: {{ .Values.global.namespace }}
labels:
{{- include "fluxer.labels" . | nindent 4 }}
app.kubernetes.io/name: nats
spec:
type: ClusterIP
ports:
- name: client
port: {{ .Values.nats.clientPort }}
targetPort: client
selector:
app.kubernetes.io/name: nats
app.kubernetes.io/instance: {{ .Release.Name }}
@@ -1,63 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nats
namespace: {{ .Values.global.namespace }}
labels:
{{- include "fluxer.labels" . | nindent 4 }}
app.kubernetes.io/name: nats
spec:
serviceName: nats-headless
replicas: {{ .Values.nats.replicas }}
selector:
matchLabels:
app.kubernetes.io/name: nats
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
{{- include "fluxer.labels" . | nindent 8 }}
app.kubernetes.io/name: nats
app.kubernetes.io/instance: {{ .Release.Name }}
annotations:
checksum/config: {{ include (print $.Template.BasePath "/nats-configmap.yaml") . | sha256sum }}
spec:
terminationGracePeriodSeconds: 30
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: nats
image: {{ .Values.nats.image }}:{{ .Values.nats.tag }}
args: ["-c", "/etc/nats/nats.conf"]
ports:
- name: client
containerPort: {{ .Values.nats.clientPort }}
- name: cluster
containerPort: {{ .Values.nats.clusterPort }}
- name: monitor
containerPort: {{ .Values.nats.monitorPort }}
livenessProbe:
httpGet:
path: /healthz
port: monitor
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /healthz?js-enabled-only=true
port: monitor
initialDelaySeconds: 5
periodSeconds: 5
volumeMounts:
- name: config
mountPath: /etc/nats
resources:
{{- toYaml .Values.nats.resources | nindent 12 }}
volumes:
- name: config
configMap:
name: nats-config
-14
View File
@@ -1,14 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: nats-pdb
namespace: {{.Values.global.namespace}}
labels: {{- include "fluxer.labels" . | nindent 4}}
spec:
minAvailable: 2
selector:
matchLabels:
app.kubernetes.io/name: nats
app.kubernetes.io/instance: {{.Release.Name}}
@@ -1,39 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: v1
kind: Service
metadata:
name: valkey-headless
namespace: {{ .Values.global.namespace }}
labels:
{{- include "fluxer.labels" . | nindent 4 }}
app.kubernetes.io/name: valkey
spec:
type: ClusterIP
clusterIP: None
publishNotReadyAddresses: true
ports:
- name: valkey
port: {{ .Values.valkey.port }}
targetPort: valkey
selector:
app.kubernetes.io/name: valkey
app.kubernetes.io/instance: {{ .Release.Name }}
---
apiVersion: v1
kind: Service
metadata:
name: valkey
namespace: {{ .Values.global.namespace }}
labels:
{{- include "fluxer.labels" . | nindent 4 }}
app.kubernetes.io/name: valkey
spec:
type: ClusterIP
ports:
- name: valkey
port: {{ .Values.valkey.port }}
targetPort: valkey
selector:
app.kubernetes.io/name: valkey
app.kubernetes.io/instance: {{ .Release.Name }}
@@ -1,60 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: valkey
namespace: {{ .Values.global.namespace }}
labels:
{{- include "fluxer.labels" . | nindent 4 }}
app.kubernetes.io/name: valkey
spec:
serviceName: valkey-headless
replicas: {{ .Values.valkey.replicas }}
selector:
matchLabels:
app.kubernetes.io/name: valkey
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
{{- include "fluxer.labels" . | nindent 8 }}
app.kubernetes.io/name: valkey
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
terminationGracePeriodSeconds: 15
securityContext:
runAsNonRoot: true
runAsUser: 999
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: valkey
image: {{ .Values.valkey.image }}:{{ .Values.valkey.tag }}
command:
- valkey-server
- --save
- ""
- --appendonly
- "no"
- --maxmemory
- {{ .Values.valkey.maxmemory | quote }}
- --maxmemory-policy
- allkeys-lru
ports:
- name: valkey
containerPort: {{ .Values.valkey.port }}
livenessProbe:
exec:
command: ["valkey-cli", "ping"]
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
exec:
command: ["valkey-cli", "ping"]
initialDelaySeconds: 3
periodSeconds: 5
resources:
{{- toYaml .Values.valkey.resources | nindent 12 }}
-74
View File
@@ -1,74 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Live user-supplied values for the infra release as of 2026-05-17T20:42:44Z.
# Captured via: helm -n fluxer get values infra
# Apply with: helm upgrade infra deploy/helm/infra -f deploy/helm/infra/values.yaml -f deploy/helm/infra/values.prod.yaml
global:
imagePullSecret: ghcr-pull-secret
namespace: fluxer
registry: ""
ingress:
className: nginx
hosts:
admin: admin.fluxer.app
adminCanary: admin.canary.fluxer.app
api: api.fluxer.app
apiCanary: api.canary.fluxer.app
appProxy: web.fluxer.app
appProxyCanary: web.canary.fluxer.app
gateway: gateway.fluxer.app
help: help.fluxer.app
blog: blog.fluxer.app
docs: docs.fluxer.app
marketing: fluxer.app
marketingAliases:
- www.fluxer.app
- fluxerapp.com
- www.fluxerapp.com
- fluxer.gg
- fluxer.gift
- fluxer.dev
- www.fluxer.dev
- every.day.im.fluxer.ing
marketingCanary: canary.fluxer.app
mediaProxy: fluxerusercontent.com
staticProxy: fluxerstatic.com
nats:
clientPort: 4222
clusterPort: 6222
image: nats
maxConnections: 2048
monitorPort: 8222
replicas: 5
resources:
limits:
memory: 2Gi
requests:
cpu: 100m
memory: 512Mi
tag: 2-alpine
ports:
admin: 8080
adminCanary: 8080
api: 8080
apiCanary: 8080
appProxy: 8080
appProxyCanary: 8080
gateway: 8080
marketing: 8080
marketingCanary: 8080
docs: 8080
mediaProxy: 8080
staticProxy: 8080
valkey:
image: valkey/valkey
port: 6379
replicas: 1
resources:
limits:
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
tag: 8-alpine
-91
View File
@@ -1,91 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
global:
namespace: fluxer
imagePullSecret: ghcr-pull-secret
registry: ""
nats:
replicas: 3
image: nats
tag: 2-alpine
clientPort: 4222
clusterPort: 6222
monitorPort: 8222
maxPayload: 64MB
maxPending: 128MB
maxConnections: 2048
resources:
requests:
cpu: 100m
memory: 512Mi
limits:
memory: 2Gi
valkey:
replicas: 1
image: valkey/valkey
tag: 8-alpine
port: 6379
maxmemory: 1600mb
resources:
requests:
cpu: 100m
memory: 512Mi
limits:
memory: 2Gi
ingress:
className: nginx
hosts:
api: api.fluxer.app
apiCanary: api.canary.fluxer.app
appProxy: web.fluxer.app
appProxyCanary: web.canary.fluxer.app
admin: admin.fluxer.app
adminCanary: admin.canary.fluxer.app
marketing: fluxer.app
marketingCanary: canary.fluxer.app
mediaProxy: fluxerusercontent.com
staticProxy: fluxerstatic.com
gateway: gateway.fluxer.app
help: help.fluxer.app
blog: blog.fluxer.app
docs: docs.fluxer.app
marketingAliases:
- www.fluxer.app
- fluxerapp.com
- www.fluxerapp.com
- fluxer.gg
- fluxer.gift
- fluxer.dev
- www.fluxer.dev
- every.day.im.fluxer.ing
uploads: uploads.fluxer.app
ports:
api: 8080
apiCanary: 8080
appProxy: 8080
appProxyCanary: 8080
admin: 8080
adminCanary: 8080
marketing: 8080
marketingCanary: 8080
docs: 8080
mediaProxy: 8080
staticProxy: 8080
gateway: 8080
uploads: 8080
# MaxMind GeoLite2 sync — daily at 05:17 UTC. Runtime services read
# these mmdb files out of the CDN bucket.
geoipSync:
image: amazon/aws-cli:2.17.12
schedule: '17 5 * * *'
activeDeadlineSeconds: 1800
backoffLimit: 2
bucket: fluxer-geoip
cityUpstreamUrl: https://git.io/GeoLite2-City.mmdb
asnUpstreamUrl: https://git.io/GeoLite2-ASN.mmdb
envSecret: fluxer-env-shared
-11
View File
@@ -1,11 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: v2
name: marketing
description: Fluxer marketing service
type: application
version: 0.1.0
dependencies:
- name: common
version: 0.1.0
repository: file://../common
@@ -1,3 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{include "fluxer.deployment" (dict "name" .Values.app.name "values" .Values.app "context" .)}}
-3
View File
@@ -1,3 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{include "fluxer.pdb" (dict "name" .Values.app.name "minAvailable" .Values.pdb.minAvailable "context" .)}}
@@ -1,3 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{include "fluxer.service" (dict "name" .Values.app.name "values" .Values.app "context" .)}}
@@ -1,30 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Live user-supplied values for the fluxer-marketing-canary release as of 2026-05-17T20:42:39Z.
# Captured via: helm -n fluxer get values fluxer-marketing-canary
# Apply with: helm upgrade fluxer-marketing-canary deploy/helm/marketing -f deploy/helm/marketing/values.yaml -f deploy/helm/marketing/values.canary.prod.yaml
app:
build:
channel: canary
version: ""
image: fluxer-marketing
name: marketing-canary
port: 8080
replicas: 2
resources:
limits:
memory: 512Mi
requests:
cpu: 100m
memory: 256Mi
tag: ""
global:
imagePullSecret: ghcr-pull-secret
namespace: fluxer
registry: ""
envFrom:
- secretRef:
name: fluxer-runtime-env-canary
pdb:
minAvailable: 50%
@@ -1,30 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Live user-supplied values for the fluxer-marketing-stable release as of 2026-06-03T19:37:50Z.
# Captured via: helm -n fluxer get values fluxer-marketing-stable
# Apply with: helm upgrade fluxer-marketing-stable deploy/helm/marketing -f deploy/helm/marketing/values.yaml -f deploy/helm/marketing/values.stable.prod.yaml
app:
build:
channel: stable
version: ""
image: fluxer-marketing
name: marketing
port: 8080
replicas: 2
resources:
limits:
memory: 512Mi
requests:
cpu: 100m
memory: 256Mi
tag: ""
global:
imagePullSecret: ghcr-pull-secret
namespace: fluxer
registry: ""
envFrom:
- secretRef:
name: fluxer-runtime-env-stable
pdb:
minAvailable: 50%
-23
View File
@@ -1,23 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
global:
namespace: fluxer
imagePullSecret: ghcr-pull-secret
registry: ""
app:
name: ''
image: ''
tag: ''
replicas: 2
port: 8080
config: ''
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 512Mi
pdb:
minAvailable: '50%'
-11
View File
@@ -1,11 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: v2
name: media-proxy
description: Fluxer media proxy and static proxy services
type: application
version: 0.1.0
dependencies:
- name: common
version: 0.1.0
repository: file://../common
@@ -1,5 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{include "fluxer.deployment" (dict "name" "media-proxy" "values" .Values.mediaProxy "context" .)}}
---
{{include "fluxer.deployment" (dict "name" "static-proxy" "values" .Values.staticProxy "context" .)}}
@@ -1,20 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{- range $name, $cfg := .Values.pdb }}
{{- if (dig "enabled" true $cfg) }}
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: {{ $name }}-pdb
namespace: {{ $.Values.global.namespace }}
labels:
{{- include "fluxer.labels" $ | nindent 4 }}
{{- include "fluxer.selectorLabels" (dict "name" $name "context" $) | nindent 4 }}
spec:
minAvailable: {{ $cfg.minAvailable | quote }}
selector:
matchLabels:
{{- include "fluxer.selectorLabels" (dict "name" $name "context" $) | nindent 6 }}
---
{{- end }}
{{- end }}
@@ -1,5 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{include "fluxer.service" (dict "name" "media-proxy" "values" .Values.mediaProxy "context" .)}}
---
{{include "fluxer.service" (dict "name" "static-proxy" "values" .Values.staticProxy "context" .)}}
-88
View File
@@ -1,88 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# Live user-supplied values for the fluxer-media-proxy release as of 2026-05-17T20:42:42Z.
# Captured via: helm -n fluxer get values fluxer-media-proxy
# Apply with: helm upgrade fluxer-media-proxy deploy/helm/media-proxy -f deploy/helm/media-proxy/values.yaml -f deploy/helm/media-proxy/values.prod.yaml
global:
imagePullSecret: ghcr-pull-secret
namespace: fluxer
registry: ""
envFrom:
- secretRef:
name: fluxer-runtime-env-shared
mediaProxy:
build:
channel: canary
version: ""
env:
- name: FLUXER_MEDIA_PROXY_MODE
value: mp
- name: FLUXER_MEDIA_PROXY_NSFW_THRESHOLD
value: "0.95"
- name: FLUXER_MEDIA_PROXY_STORAGE_BACKEND
value: s3
- name: FLUXER_MEDIA_PROXY_READ_ONLY
value: "true"
- name: FLUXER_MEDIA_PROXY_MAX_NATIVE_TRANSFORMS
value: "4"
- name: FLUXER_MEDIA_PROXY_WORKER_QUEUE_CAPACITY
value: "128"
- name: FLUXER_MEDIA_PROXY_TRANSFORM_TIMEOUT_MS
value: "30000"
- name: FLUXER_MEDIA_PROXY_MAX_ENCODE_FRAMES
value: "4096"
- name: FLUXER_MEDIA_PROXY_MAX_ENCODE_DURATION_MS
value: "30000"
- name: FLUXER_MEDIA_PROXY_TRANSFORM_CACHE_BYTES
value: "1073741824"
- name: FLUXER_MEDIA_PROXY_TRANSFORM_CACHE_MAX_ENTRY_BYTES
value: "134217728"
- name: FLUXER_MEDIA_PROXY_TRANSFORM_CACHE_TTL_MS
value: "1800000"
- name: FLUXER_MEDIA_PROXY_SOCKET_IO_TIMEOUT_MS
value: "30000"
image: fluxer-media-proxy
nsfwServiceEndpoint: http://int.flx-nyc-misc1.srv.fluxer.dev:8000
port: 8080
preserveLiveReplicas: false
replicas: 16
resources:
limits:
cpu: 4000m
memory: 4Gi
requests:
cpu: 300m
memory: 768Mi
tag: ""
pdb:
media-proxy:
enabled: true
minAvailable: 50%
static-proxy:
enabled: true
minAvailable: 50%
staticProxy:
build:
channel: canary
version: ""
env:
- name: FLUXER_MEDIA_PROXY_MODE
value: static
- name: FLUXER_MEDIA_PROXY_STORAGE_BACKEND
value: s3
- name: FLUXER_MEDIA_PROXY_READ_ONLY
value: "true"
- name: FLUXER_MEDIA_PROXY_SOCKET_IO_TIMEOUT_MS
value: "30000"
image: fluxer-media-proxy
port: 8080
preserveLiveReplicas: false
replicas: 4
resources:
limits:
memory: 512Mi
requests:
cpu: 50m
memory: 256Mi
tag: ""
-78
View File
@@ -1,78 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
global:
namespace: fluxer
imagePullSecret: ghcr-pull-secret
registry: ""
mediaProxy:
image: fluxer-media-proxy
tag: ""
replicas: 16
preserveLiveReplicas: false
port: 8080
nsfwServiceEndpoint: 'http://int.flx-nyc-misc1.srv.fluxer.dev:8000'
env:
- name: FLUXER_MEDIA_PROXY_MODE
value: mp
- name: FLUXER_MEDIA_PROXY_NSFW_THRESHOLD
value: '0.95'
- name: FLUXER_MEDIA_PROXY_STORAGE_BACKEND
value: s3
- name: FLUXER_MEDIA_PROXY_READ_ONLY
value: 'true'
- name: FLUXER_MEDIA_PROXY_MAX_NATIVE_TRANSFORMS
value: '4'
- name: FLUXER_MEDIA_PROXY_WORKER_QUEUE_CAPACITY
value: '128'
- name: FLUXER_MEDIA_PROXY_TRANSFORM_TIMEOUT_MS
value: '30000'
- name: FLUXER_MEDIA_PROXY_MAX_ENCODE_FRAMES
value: '4096'
- name: FLUXER_MEDIA_PROXY_MAX_ENCODE_DURATION_MS
value: '30000'
- name: FLUXER_MEDIA_PROXY_TRANSFORM_CACHE_BYTES
value: '1073741824'
- name: FLUXER_MEDIA_PROXY_TRANSFORM_CACHE_MAX_ENTRY_BYTES
value: '134217728'
- name: FLUXER_MEDIA_PROXY_TRANSFORM_CACHE_TTL_MS
value: '1800000'
- name: FLUXER_MEDIA_PROXY_SOCKET_IO_TIMEOUT_MS
value: '30000'
resources:
requests:
cpu: 300m
memory: 768Mi
limits:
cpu: 4000m
memory: 4Gi
staticProxy:
image: fluxer-media-proxy
tag: ""
replicas: 4
preserveLiveReplicas: false
port: 8080
env:
- name: FLUXER_MEDIA_PROXY_MODE
value: static
- name: FLUXER_MEDIA_PROXY_STORAGE_BACKEND
value: s3
- name: FLUXER_MEDIA_PROXY_READ_ONLY
value: 'true'
- name: FLUXER_MEDIA_PROXY_SOCKET_IO_TIMEOUT_MS
value: '30000'
resources:
requests:
cpu: 50m
memory: 256Mi
limits:
memory: 512Mi
pdb:
media-proxy:
enabled: true
minAvailable: '50%'
static-proxy:
enabled: true
minAvailable: '50%'
-9
View File
@@ -1,9 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: v2
name: messages
version: 0.1.0
dependencies:
- name: svc-common
version: 0.1.0
repository: file://../svc-common
-13
View File
@@ -1,13 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{ include "svc-common.statefulset" . }}
---
{{ include "svc-common.deployment" . }}
---
{{ include "svc-common.headless-service" . }}
---
{{ include "svc-common.service" . }}
---
{{ include "svc-common.pdb" . }}
---
{{ include "svc-common.router-pdb" . }}
-26
View File
@@ -1,26 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
svc:
shard:
replicas: 4
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 512Mi
router:
replicas: 8
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
memory: 256Mi
cassandra:
hosts:
- int.flx-nyc-db1.srv.fluxer.dev:9041
credentialsSecret: fluxer-cassandra-credentials
cache:
maxEntries: 250000
ttlMs: 30000
-44
View File
@@ -1,44 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
global:
namespace: fluxer
imagePullSecret: ghcr-pull-secret
registry: ""
svc:
name: messages
image: fluxer-messages
tag: ''
shard:
replicas: 4
port: 8090
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
memory: 256Mi
router:
replicas: 2
port: 8090
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
memory: 128Mi
nats:
url: nats://nats-core:4222
cassandra:
hosts:
- cassandra:9042
keyspace: fluxer
cache:
maxEntries: 100000
ttlMs: 30000
extraEnv: []
nodeSelector: {}
tolerations: []
pdb:
minAvailable: '50%'
-9
View File
@@ -1,9 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: v2
name: snowflakes
version: 0.1.0
dependencies:
- name: svc-common
version: 0.1.0
repository: file://../svc-common
-13
View File
@@ -1,13 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
{{ include "svc-common.statefulset" . }}
---
{{ include "svc-common.deployment" . }}
---
{{ include "svc-common.headless-service" . }}
---
{{ include "svc-common.service" . }}
---
{{ include "svc-common.pdb" . }}
---
{{ include "svc-common.router-pdb" . }}
-20
View File
@@ -1,20 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
svc:
shard:
replicas: 4
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
memory: 256Mi
router:
replicas: 3
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
memory: 256Mi
maxConcurrentRequests: 256
-41
View File
@@ -1,41 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
global:
namespace: fluxer
imagePullSecret: ghcr-pull-secret
registry: ""
svc:
name: snowflakes
image: fluxer-snowflakes
tag: ''
shard:
replicas: 4
port: 8090
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
memory: 128Mi
router:
replicas: 2
port: 8090
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
memory: 128Mi
nats:
url: nats://nats-core:4222
cache:
maxEntries: 100000
ttlMs: 30000
maxConcurrentRequests: 128
extraEnv: []
nodeSelector: {}
tolerations: []
pdb:
minAvailable: '50%'
-7
View File
@@ -1,7 +0,0 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
apiVersion: v2
name: svc-common
type: library
version: 0.1.0
description: Shared templates for fluxer microservice fleet
@@ -1,96 +0,0 @@
{{/*
SPDX-License-Identifier: AGPL-3.0-or-later
*/}}
{{- define "svc-common.deployment" -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.svc.name }}
namespace: {{ .Values.global.namespace }}
labels:
{{- include "svc-common.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.svc.router.replicas }}
minReadySeconds: {{ default 10 .Values.svc.router.minReadySeconds }}
selector:
matchLabels:
app: {{ .Values.svc.name }}
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: {{ default 1 .Values.svc.router.maxSurge }}
maxUnavailable: {{ default 0 .Values.svc.router.maxUnavailable }}
template:
metadata:
labels:
app: {{ .Values.svc.name }}
{{- include "svc-common.labels" . | nindent 8 }}
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "{{ .Values.svc.router.port }}"
prometheus.io/path: "/_metrics"
spec:
terminationGracePeriodSeconds: {{ default 60 .Values.svc.router.terminationGracePeriodSeconds }}
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: router
image: {{ include "svc-common.image" . }}
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: false
ports:
- name: http
containerPort: {{ .Values.svc.router.port }}
env:
- name: FLUXER_SVC_MODE
value: "router"
- name: FLUXER_SVC_NAME
value: {{ .Values.svc.name }}
- name: FLUXER_SVC_SHARD_COUNT
value: {{ .Values.svc.shard.replicas | quote }}
- name: FLUXER_SVC_PORT
value: {{ .Values.svc.router.port | quote }}
- name: FLUXER_SVC_NATS_URL
value: {{ .Values.svc.nats.url }}
- name: FLUXER_SVC_CACHE_MAX_ENTRIES
value: {{ .Values.svc.cache.maxEntries | quote }}
- name: FLUXER_SVC_CACHE_TTL_MS
value: {{ .Values.svc.cache.ttlMs | quote }}
{{- if .Values.svc.build }}
- name: BUILD_VERSION
value: {{ .Values.svc.build.version | default .Values.svc.tag | quote }}
- name: RELEASE_CHANNEL
value: {{ .Values.svc.build.channel | default "stable" | quote }}
{{- end }}
{{- range .Values.svc.extraEnv }}
- name: {{ .name }}
{{- if .valueFrom }}
valueFrom:
{{- toYaml .valueFrom | nindent 16 }}
{{- else }}
value: {{ .value | quote }}
{{- end }}
{{- end }}
readinessProbe:
httpGet:
path: /_health
port: http
initialDelaySeconds: 1
periodSeconds: 5
livenessProbe:
httpGet:
path: /_healthz
port: http
initialDelaySeconds: 2
periodSeconds: 15
resources:
{{- toYaml .Values.svc.router.resources | nindent 12 }}
{{- if .Values.global.imagePullSecret }}
imagePullSecrets:
- name: {{ .Values.global.imagePullSecret }}
{{- end }}
{{- end -}}
@@ -1,19 +0,0 @@
{{/*
SPDX-License-Identifier: AGPL-3.0-or-later
*/}}
{{- define "svc-common.headless-service" -}}
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.svc.name }}-shard-headless
namespace: {{ .Values.global.namespace }}
spec:
clusterIP: None
publishNotReadyAddresses: true
selector:
app: {{ .Values.svc.name }}-shard
ports:
- port: {{ .Values.svc.shard.port }}
name: http
{{- end -}}
@@ -1,30 +0,0 @@
{{/*
SPDX-License-Identifier: AGPL-3.0-or-later
*/}}
{{/*
Standard labels for all resources.
*/}}
{{- define "svc-common.labels" -}}
app.kubernetes.io/name: {{ .Values.svc.name }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Values.svc.tag | default .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end -}}
{{/*
Selector labels (subset of standard labels).
*/}}
{{- define "svc-common.selectorLabels" -}}
app.kubernetes.io/name: {{ .Values.svc.name }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}
{{/*
Construct full image path from registry + image name + tag.
*/}}
{{- define "svc-common.image" -}}
{{- $registry := required "global.registry is required" .Values.global.registry -}}
{{- $tag := required (printf "svc.tag is required (image: %s)" .Values.svc.image) .Values.svc.tag -}}
{{ $registry }}/{{ .Values.svc.image }}:{{ $tag }}
{{- end -}}
-29
View File
@@ -1,29 +0,0 @@
{{/*
SPDX-License-Identifier: AGPL-3.0-or-later
*/}}
{{- define "svc-common.pdb" -}}
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: {{ .Values.svc.name }}-shard
namespace: {{ .Values.global.namespace }}
spec:
minAvailable: {{ .Values.pdb.minAvailable | quote }}
selector:
matchLabels:
app: {{ .Values.svc.name }}-shard
{{- end -}}
{{- define "svc-common.router-pdb" -}}
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: {{ .Values.svc.name }}
namespace: {{ .Values.global.namespace }}
spec:
minAvailable: {{ .Values.pdb.minAvailable | quote }}
selector:
matchLabels:
app: {{ .Values.svc.name }}
{{- end -}}
@@ -1,17 +0,0 @@
{{/*
SPDX-License-Identifier: AGPL-3.0-or-later
*/}}
{{- define "svc-common.service" -}}
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.svc.name }}
namespace: {{ .Values.global.namespace }}
spec:
selector:
app: {{ .Values.svc.name }}
ports:
- port: {{ .Values.svc.router.port }}
name: http
{{- end -}}
@@ -1,167 +0,0 @@
{{/*
SPDX-License-Identifier: AGPL-3.0-or-later
*/}}
{{- define "svc-common.statefulset" -}}
{{- $persistence := .Values.svc.shard.persistence | default dict -}}
{{- $ephemeral := .Values.svc.shard.ephemeral | default dict -}}
{{- $dataMountEnabled := or $persistence.enabled $ephemeral.enabled -}}
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ .Values.svc.name }}-shard
namespace: {{ .Values.global.namespace }}
labels:
{{- include "svc-common.labels" . | nindent 4 }}
spec:
serviceName: {{ .Values.svc.name }}-shard-headless
replicas: {{ .Values.svc.shard.replicas }}
minReadySeconds: {{ default 10 .Values.svc.shard.minReadySeconds }}
podManagementPolicy: Parallel
updateStrategy:
type: RollingUpdate
selector:
matchLabels:
app: {{ .Values.svc.name }}-shard
template:
metadata:
labels:
app: {{ .Values.svc.name }}-shard
{{- include "svc-common.labels" . | nindent 8 }}
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "{{ .Values.svc.shard.port }}"
prometheus.io/path: "/_metrics"
spec:
terminationGracePeriodSeconds: {{ default 60 .Values.svc.shard.terminationGracePeriodSeconds }}
securityContext:
runAsNonRoot: true
fsGroup: 65532
seccompProfile:
type: RuntimeDefault
containers:
- name: shard
image: {{ include "svc-common.image" . }}
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: false
ports:
- name: http
containerPort: {{ .Values.svc.shard.port }}
env:
- name: FLUXER_SVC_MODE
value: "shard"
- name: FLUXER_SVC_NAME
value: {{ .Values.svc.name }}
- name: FLUXER_SVC_SHARD_COUNT
value: {{ .Values.svc.shard.replicas | quote }}
- name: FLUXER_SVC_PORT
value: {{ .Values.svc.shard.port | quote }}
- name: FLUXER_SVC_NATS_URL
value: {{ .Values.svc.nats.url }}
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
{{- if .Values.svc.cassandra }}
- name: FLUXER_CASSANDRA_HOSTS
value: {{ join "," .Values.svc.cassandra.hosts }}
- name: FLUXER_CASSANDRA_KEYSPACE
value: {{ .Values.svc.cassandra.keyspace }}
{{- if .Values.svc.cassandra.credentialsSecret }}
- name: FLUXER_CASSANDRA_USERNAME
valueFrom:
secretKeyRef:
name: {{ .Values.svc.cassandra.credentialsSecret }}
key: username
- name: FLUXER_CASSANDRA_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.svc.cassandra.credentialsSecret }}
key: password
{{- end }}
{{- end }}
- name: FLUXER_SVC_CACHE_MAX_ENTRIES
value: {{ .Values.svc.cache.maxEntries | quote }}
- name: FLUXER_SVC_CACHE_TTL_MS
value: {{ .Values.svc.cache.ttlMs | quote }}
- name: FLUXER_SVC_MAX_CONCURRENT_REQUESTS
value: {{ default 64 .Values.svc.maxConcurrentRequests | quote }}
{{- if .Values.svc.build }}
- name: BUILD_VERSION
value: {{ .Values.svc.build.version | default .Values.svc.tag | quote }}
- name: RELEASE_CHANNEL
value: {{ .Values.svc.build.channel | default "stable" | quote }}
{{- end }}
{{- range .Values.svc.extraEnv }}
- name: {{ .name }}
{{- if .valueFrom }}
valueFrom:
{{- toYaml .valueFrom | nindent 16 }}
{{- else }}
value: {{ .value | quote }}
{{- end }}
{{- end }}
readinessProbe:
httpGet:
path: /_health
port: http
initialDelaySeconds: 2
periodSeconds: 5
failureThreshold: 2
livenessProbe:
httpGet:
path: /_healthz
port: http
initialDelaySeconds: 5
periodSeconds: 15
failureThreshold: 3
startupProbe:
httpGet:
path: /_healthz
port: http
initialDelaySeconds: 1
periodSeconds: 5
failureThreshold: 60
resources:
{{- toYaml .Values.svc.shard.resources | nindent 12 }}
{{- if $dataMountEnabled }}
volumeMounts:
- name: data
mountPath: {{ default (default "/var/lib/fluxer-svc" $persistence.mountPath) $ephemeral.mountPath }}
{{- end }}
{{- with .Values.svc.nodeSelector }}
nodeSelector: {{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.svc.tolerations }}
tolerations: {{- toYaml . | nindent 8 }}
{{- end }}
{{- if and (not $persistence.enabled) $ephemeral.enabled }}
volumes:
- name: data
emptyDir:
{{- if $ephemeral.sizeLimit }}
sizeLimit: {{ $ephemeral.sizeLimit | quote }}
{{- else }}
{}
{{- end }}
{{- end }}
{{- if .Values.global.imagePullSecret }}
imagePullSecrets:
- name: {{ .Values.global.imagePullSecret }}
{{- end }}
{{- if $persistence.enabled }}
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes:
- {{ default "ReadWriteOnce" $persistence.accessMode | quote }}
{{- if $persistence.storageClassName }}
storageClassName: {{ $persistence.storageClassName | quote }}
{{- end }}
resources:
requests:
storage: {{ default "10Gi" $persistence.size | quote }}
{{- end }}
{{- end -}}

Some files were not shown because too many files have changed in this diff Show More