/admin/settings, linked from the administrator section of the
preferences page and refused to everybody else, edits the settings the
fork added: the playlists behind the Popular and Trending feeds, and the
whole trusted-header block.
- The playlists are picked from the instance's public playlists with a
tick box each and a number beside it for the position, so no ordering
has to be typed. A text area takes IDs that are not local playlists.
Unticking everything restores the stock feed for that feed.
- A playlist that is missing or not public is reported as a warning and
still saved: the feed skips it the same way, and an admin may be
listing a playlist they are about to create.
- The trusted-header block is refused whole when anything in it is
wrong, so a half-applied block can never reach the running config. A
CIDR range and an empty proxy list with the feature on are the two the
page exists to catch.
- A save writes the rows and applies the values to the running CONFIG,
so it needs no restart, and it survives one.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A client behind the same authenticating proxy - Materialious behind
Authelia - still had to click through the token consent page, although
the proxy had just authenticated the same person for the same origin.
trusted_header_auth.auto_approve_token_callbacks lists exact origins.
When /authorize_token is reached with a callback on one of them, and the
trusted header asserts the session user on that very request, the token
is issued with the requested scopes and the browser is sent back to the
callback exactly as the consent POST would have sent it.
Every rail is a whole-value check:
- the callback origin is normalized (scheme and host lowercased, default
port dropped) and compared whole against normalized entries, so
neither "https://yt.example.com.evil.tld" nor a path can match;
- a URL carrying credentials is refused outright, which is what stops
"https://yt.example.com@evil.tld";
- a password-login session never qualifies, header auth must be on, and
an empty list (the default) leaves the consent page exactly as it was.
The redirect URL is now built in one place, shared with the consent POST,
so both hand the client the identical URL.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The waiver that lets a trusted-header session set a password without the
current one was unconditional. It is the right default — those accounts
were provisioned with a random password nobody ever saw — but an admin
who wants the current password from everybody had no way to say so.
Both call sites now go through TrustedHeaderAuth.password_self_service?,
which folds the flag into the identity check.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Production feeds the config through INVIDIOUS_CONFIG, so a config.yml
written at runtime is thrown away on the next restart. The fork's own
settings therefore need a home the admin can write to: a key/value table
arik_settings, one row per setting.
- The environment config is parsed and validated first and seeds every
value; a stored row then overrides the value of its own key. A key
without a row keeps the environment value.
- Applied at boot right after the table integrity check, so Config.check
still fails closed on a bad environment config while a bad database
row only loses its own override: decoding reports the reason and the
environment value stands.
- Validation lives in ArikSettings and is pure, so the admin UI can
refuse an entry before it is stored. It refuses what hurts later: a
CIDR range in trusted_proxies (Config.check exits on it at the next
boot), header auth enabled with no trusted proxy at all, and callback
origins that are not a bare scheme+host+port.
- Two new trusted_header_auth fields are declared here and wired up in
the commits that follow: password_self_service and
auto_approve_token_callbacks.
The table is created both by a migration and by check_integrity, so
instances on either path get it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The playlist tables store no views, so Trending/Popular reported 0 for
every item. The companion suggestion bot already caches YouTube metadata
in suggest.video_meta in the same database: look the counts up in one
query per feed and fall back to 0 when the row or the whole schema is
missing, so instances without the bot are unaffected.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Accounts provisioned by trusted-header SSO get a random password the user
never saw, so /change_password was unusable for them. When the trusted
header asserts the same email as the session user, waive the current
password check and hide the field, so native clients (Yattee) can be given
a password to log in with.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New config lists trending_playlists / popular_playlists. When set,
the feed serves the merged content of those local PUBLIC playlists
instead of the stock feed:
- Swap at the data layer (fetch_trending, popular_videos), so the
HTML views and /api/v1/trending|popular emit the same items and
API clients (Yattee, Materialious) need no changes.
- Playlists merge in config order, each in its own order,
duplicates dropped. Missing or non-public entries are skipped
and logged, never fatal.
- One local Postgres query per playlist — no YouTube call.
- PlaylistVideo converts to SearchVideo with neutral defaults for
metadata a playlist row lacks (views, description, thumbnails).
- Trending category tabs and region are ignored while set. With a
single trending playlist, 'View as playlist' links to it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Update mocks submodule to use the upstream iv-org repository
(https://github.com/iv-org/mocks) instead of the inaccessible
NeskireDK fork path.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Remove submodules: true from actions/checkout since the mocks
submodule is not accessible and not needed for the build.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Gate first: crystal spec + format-strict build on 1.20.3 (mirrors
upstream ci.yml). Then a linux/amd64 image build pushed as
ghcr.io/neskiredk/invidious:latest + :sha-<commit>. No expiry label.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New config block trusted_header_auth. When enabled, before_all
resolves the session from the proxy-asserted header (default
Remote-User) instead of only the SID cookie:
- The header is honored only when the direct TCP peer is in
trusted_proxies (literal IPs, IPv4-mapped IPv6 normalized).
X-Forwarded-For is never consulted. Duplicated headers reject.
- /api/ is excluded: token clients (Yattee) are unaffected.
- Unknown users are provisioned like manual registration, with the
subscriptions materialized view and a random bcrypt password.
Both statements tolerate concurrent provisioning.
- A session cookie is set and reused; a cookie that belongs to a
different user is dropped (identity-switch guard).
- Boot fails closed: enabled without valid trusted_proxies exits.
- Optional logout_url replaces the local sign-out form so logout
ends the proxy session, not just the Invidious one.
The reverse proxy MUST strip the header on routes that bypass its
authentication (see config.example.yml warning).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Header/homepage brand text becomes 'ArikTube' with an inline
play-button logo. Everything else keeps the Invidious name --
this fork extends Invidious, it does not rebrand it.
Blue accents (rgb 0,182,240 / #075A9E / #008bec) become a red
scheme (#cc0000 fills, #ff5252 dark-theme text, red seekbar).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* CI: Exclude development dependencies from build job
* use --production and then install spectator to skip building of Ameba
* this should prevent ameba from building
* Revert "Fix disappearing end of the comments with emoji (#5587)"
This reverts commit 86c425b43f75dd1f22034bbfbd99476651661348.
* fix: fix rendered links and timestamps in video descriptions
* Add error message when comments are disabled
* Add btn to try reddit comments when yt is disabled
* Escape warning messages for disabled comments
* Add missing semicolons
* Update comment detection to not use msg renderer
* Use short syntax for comment entry-point detection
Co-authored-by: Samantaz Fox <coding@samantaz.fr>
* Condense try-reddit-comments-link HTML in player.js
Co-authored-by: Samantaz Fox <coding@samantaz.fr>
* Improve locale keys for comments disabled messages
Co-authored-by: Samantaz Fox <coding@samantaz.fr>
* Remove extra whitespace
* Use button instead of anchor for try reddit link
* Request Reddit comm when yt disabled during nojs=1
* Change order of commentsEnabled in parse results
* Lint
* Rebase error
* update the naming of the comments section in Innertube
Downstreamed from 36ac67610d
---------
Co-authored-by: Samantaz Fox <coding@samantaz.fr>
Co-authored-by: Fijxu <fijxu@nadeko.net>
Community posts comments still preserve the old author thumbnails
format that has an Array of thumbnails. I forgot to check that as I had
no idea `comments_youtube.cr` was also used for community posts comments
```json
"authorThumbnail": {
"thumbnails": [
{
"url": "//yt3.googleusercontent.com/ytc/AIdro_m9CJFVl3bEWvGnNnN4G9ErBO2lTpKePWCjx_FQtLWaDww=s32-c-k-c0x00ffffff-no-rj-mo",
"width": 32,
"height": 32
},
{
"url": "//yt3.googleusercontent.com/ytc/AIdro_m9CJFVl3bEWvGnNnN4G9ErBO2lTpKePWCjx_FQtLWaDww=s48-c-k-c0x00ffffff-no-rj-mo",
"width": 48,
"height": 48
},
{
"url": "//yt3.googleusercontent.com/ytc/AIdro_m9CJFVl3bEWvGnNnN4G9ErBO2lTpKePWCjx_FQtLWaDww=s76-c-k-c0x00ffffff-no-rj-mo",
"width": 76,
"height": 76
}
],
"accessibility": {
"accessibilityData": {
"label": "SomeOrdinaryGamers"
}
}
},
```
This package makes it conflict with the dependencies needed to build
Invidious (openssl, libpcre, etc). crystalline can work perfectly
without it tho, but it was added in the first place because crystalline
was trying to invoke it.
Crystal 1.21.0 now features execution contexts, they do not longer support (and recommend) the -Dpreview_mt build flag. -Dpreview_mt also worked really bad and it made Invidious to hang on high load, so it was never useful.
https://crystal-lang.org/2026/07/16/1.21.0-released/#execution-contexts
Crystal 1.21.0 now features execution contexts, they do not longer support (and recommend) the `-Dpreview_mt` build flag. It also worked really bad and it made Invidious to hang on high load.
Update Chinese (Simplified Han script) translation
Update Chinese (Simplified Han script) translation
Update Chinese (Simplified Han script) translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: 大王叫我来巡山 <hamburger2048@users.noreply.hosted.weblate.org>
Update Chinese (Traditional Han script) translation
Update Chinese (Traditional Han script) translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Jeff Huang <s8321414@gmail.com>
Update Swedish translation
Update Swedish translation
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Joel A <joeax910@student.liu.se>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>