Why are custom-config.js and custom-interface_config.js ignored?

Short answer

stable-11146 did not remove custom-config.js support: overrides still belong in ${CONFIG}/web and are appended to generated files inside /run/web/config. [S3][S4] Make them readable by UID 1000, recreate the web container and inspect the JavaScript served over HTTP. [S2][S4][S9] Issue #2291 resolved after rewriting the custom interface file, with a possible syntax error discussed but never proven. [S1]

Symptoms

After upgrading Docker to stable-11146, old branding or UI overrides appear to vanish. Issue #2291 reports a missing custom home-page title. It does not establish a universal error message. The reporter’s custom content was already appended to the generated interface file, and the web logs did not explain the failure. [S1]

Do not treat a missing title alone as proof that the files were ignored. Confirm the served content first, as the maintainer requested. [S1]

Cause

PR #2258 changed containers to the unprivileged s6 user, UID/GID 1000, and moved runtime configuration away from the host-mounted input directory. Writable storage needs UID 1000 access; input files need to be readable by that user. Changing the host username does not change these numeric container IDs. [S2]

In both checked Docker tags, startup copies /config/. into /run/web/config, generates config.js, then appends custom-config.js. It also appends custom-interface_config.js to interface_config.js. Nginx serves the generated files. A stale host-side config.js is therefore not evidence of what clients receive. [S4][S5]

The reporter rewrote the interface customization and recovered. The maintainer agreed that a missing comment opener could explain it. This remains a possible syntax error, not a confirmed rootless regression. No fix release or PR was identified for #2291 as of 2026-10-05. fixed_in is n/a because no upstream defect was established. stable-11248, published 2026-09-14, is still the latest release checked on that date. [S1][S6]

Fix

Docker first: stable-11146 and stable-11248

  1. Locate the actual input directory. Work from your existing Compose project. Read CONFIG in .env; the default is ~/.jitsi-meet-cfg. Put the files in its web subdirectory, not directly in the parent. The Compose mount maps ${CONFIG}/web to /config. [S3][S5]

    Default host paths: [S3]

    Text
    ~/.jitsi-meet-cfg/web/custom-config.js
    ~/.jitsi-meet-cfg/web/custom-interface_config.js
  2. Give UID 1000 access. On a Linux host using that default directory, run this for each file that exists. These commands set owner/group 1000 and owner-readable mode 0644; parent directories also need traversal access. Custom inputs do not need world-write permissions. Substitute your actual CONFIG path if different. [S2][S13]

    Terminal
    sudo chown 1000:1000 ~/.jitsi-meet-cfg/web/custom-config.js
    sudo chmod 0644 ~/.jitsi-meet-cfg/web/custom-config.js
    sudo chown 1000:1000 ~/.jitsi-meet-cfg/web/custom-interface_config.js
    sudo chmod 0644 ~/.jitsi-meet-cfg/web/custom-interface_config.js

    Ownership is one way to grant access, not a reason to recursively change unrelated host data. The rootless migration separately requires writable storage directories. [S2]

  3. Prefer supported .env controls. The following mappings exist in both checked tags. Move these settings out of old interface overrides and use one source of truth. This is a maintenance recommendation, not a new requirement to abandon custom files. [S7]

    Setting Docker variable Generated key
    Prejoin ENABLE_PREJOIN_PAGE config.prejoinConfig.enabled
    Welcome page ENABLE_WELCOME_PAGE config.welcomePage.disabled, inverted
    Toolbar TOOLBAR_BUTTONS config.toolbarButtons
    Initially mute audio START_WITH_AUDIO_MUTED config.startWithAudioMuted
    Initially mute video START_WITH_VIDEO_MUTED config.startWithVideoMuted

    Example .env entries, merge into your existing file: [S7]

    dotenv
    ENABLE_PREJOIN_PAGE=1
    ENABLE_WELCOME_PAGE=1
    START_WITH_AUDIO_MUTED=1
    START_WITH_VIDEO_MUTED=0
    TOOLBAR_BUTTONS=microphone,camera,desktop,chat,hangup
  4. Keep remaining overrides small. For a setting without a suitable Docker variable, use assignments to the existing object. Avoid copying an entire old configuration. Startup appends this code last, so later assignments win. [S4]

    Example content for custom-config.js: [S4][S7]

    JavaScript
    config.startWithAudioMuted = true;

    This demonstrates the syntax; prefer its .env equivalent above. For the application name, APP_NAME still exists in Jitsi Meet’s interface file at release 11248. Example content for custom-interface_config.js: [S14]

    JavaScript
    interfaceConfig.APP_NAME = 'Example Meetings';

    The upstream interface file is deprecated and explicitly says toolbar buttons moved to config.js. Deprecation does not mean every interface option stopped working. Do not assume APP_NAME controls every visible heading. [S14]

  5. Recreate the web container. This reruns generation and applies changed environment values. Use the same Compose files and project selection as your normal deployment. [S4][S9]

    Terminal
    docker compose up -d --no-deps --force-recreate web

Debian/Ubuntu packages: Jitsi Meet 2.0.11248

The Docker custom-file append mechanism and UID 1000 migration do not apply. The package installer creates a domain-specific configuration, and the Nginx template serves that file. For meet.example.com, append a small assignment after the existing configuration, with a backup first. [S8][S13]

Terminal
sudo cp -p /etc/jitsi/meet/meet.example.com-config.js /etc/jitsi/meet/meet.example.com-config.js.bak
printf '\nconfig.startWithAudioMuted = true;\n' | sudo tee -a /etc/jitsi/meet/meet.example.com-config.js

The key exists in upstream configuration. Packages install the interface file at /usr/share/jitsi-meet/interface_config.js; edit that file for APP_NAME, not a Docker custom file. Recheck package-owned customizations after upgrades. [S8][S14]

Verify

For either install type, request the served JavaScript. These commands use curl’s documented failure, header and output options. [S1][S5][S8][S10]

Terminal
curl -fsS https://meet.example.com/config.js
curl -fsS https://meet.example.com/interface_config.js

For the custom examples, find these exact lines, including any later assignment that could replace them: [S4][S14]

JavaScript
config.startWithAudioMuted = true;
interfaceConfig.APP_NAME = 'Example Meetings';

Their presence proves delivery of the assignments, not successful execution. In browser DevTools, select Network, enable Disable cache, reload, and inspect each response. Check the Console for JavaScript errors. Confirm the intended UI behavior too. [S11]

If a CDN fronts the server, compare against the origin while keeping HTTPS hostname validation. Replace the example IP with your origin address. [S10]

Terminal
curl -fsS --resolve meet.example.com:443:203.0.113.10 https://meet.example.com/config.js

If origin and public responses differ, investigate the proxy/cache route. Cloudflare supports purging individual URLs; purge both configuration URLs when cached. Disabling browser cache does not purge a CDN. [S10][S11][S12]

If it still fails

For both checked Docker tags, inspect input and generated files, then the web startup logs. [S1][S4][S9]

Terminal
docker compose exec web ls -ln /config /run/web/config
docker compose exec web cat /run/web/config/config.js
docker compose exec web cat /run/web/config/interface_config.js
docker compose logs --tail 200 web

Missing input suggests a mount/path problem. Input present but absent from generated output suggests a generation problem. Correct HTTP content with broken behavior suggests syntax, obsolete keys or a later override. These are diagnostic inferences from the loading sequence, not guaranteed error signatures. [S4]

For packages, verify the domain-specific file and Nginx mapping; the template uses /var/log/nginx/access.log for requests. A successful request alone does not prove JavaScript execution. [S8][S11]

FAQ

Were custom files removed in stable-11146?

No. The checked startup scripts still append both files. [S4]

Why does editing the host config.js do nothing?

Docker generates a new runtime file on startup. Edit custom inputs or supported environment variables instead. [S4]

Must every setting move to .env?

No. Prefer available variables; use small custom assignments for other supported keys. [S4][S7]

Is changing ownership enough?

No. Readability, correct mounts, valid JavaScript and fresh HTTP responses must all agree. #2291 already had appended content before it recovered. [S1][S4][S11]

Sources

[S1] Issue #2291 and discussion, August 2026, community report and maintainer comments.

[S2] PR #2258 Rootless containers, merged 2026-06-19, maintainer comment and source code.

[S3] Docker handbook, configuration files, checked 2026-10-05, official doc.

[S4] Web startup scripts: stable-11146, stable-11248, checked 2026-10-05, source code.

[S5] Compose mounts and Nginx mappings, checked 2026-10-05, source code.

[S6] Latest release API and stable-11248, 2026-09-14, checked 2026-10-05, release note.

[S7] Settings templates: stable-11146, stable-11248, checked 2026-10-05, source code.

[S8] Package installer, file manifest, config and Nginx template, release 11248, checked 2026-10-05, source code.

[S9] Docker Compose up, exec, logs, checked 2026-10-05, official doc.

[S10] curl manual, checked 2026-10-05, official doc.

[S11] Chrome DevTools Network reference and Console, checked 2026-10-05, official doc.

[S12] Cloudflare purge by URL, checked 2026-10-05, official doc.

[S13] GNU Coreutils manual, checked 2026-10-05, official doc, ownership, modes, copying and text output.

[S14] interface_config.js at release 11248, checked 2026-10-05, source code.

Open questions

The precise syntax failure in #2291 was never demonstrated. These instructions were checked against sources, not exercised on a real Jitsi server. Verify title behavior on your installed frontend, and inspect the actual browser-requested configuration URL when using subdomains or a custom proxy. [S1][S5][S14]

Collect debug info

These commands gather what an engineer needs to diagnose a Jitsi server. Copy them, run them, and keep the output.

Terminal
# Run on the server, from your docker-jitsi-meet folder

# 1. Every service should be "running" (or "healthy")
docker compose ps

# 2. Which images and release tags are running
docker compose images

# 3. Recent logs from the core services
docker compose logs --tail=200 web prosody jicofo jvb

# 4. The settings most fixes depend on
grep -E '^(PUBLIC_URL|JVB_ADVERTISE_IPS|ENABLE_LETSENCRYPT|ENABLE_AUTH|AUTH_TYPE)=' .env

# 5. Is anything listening for media on UDP 10000?
sudo ss -ulnp | grep 10000

Installed with the Debian packages instead of Docker? Read the service logs with:

Terminal
sudo journalctl -u prosody -u jicofo -u jitsi-videobridge2 --since "1 hour ago"

Remove passwords, secrets and tokens before you share any output.

Send the output to an engineer

Stuck, or would rather not do this by hand?

Deploy it in one click

A private Jitsi server in your own AWS account with SSL, your domain and optional recording, transcription and JWT. Free 15 minute trial.

Start free trial

Talk to a Jitsi engineer

Setup, fixes, branding, recording, scaling. Tell us what is happening and we reply with a plan and a quote.

Get expert help

Related

Recently updated