mirror of
https://github.com/ether/etherpad-lite.git
synced 2026-07-17 16:47:05 +00:00
* docs(updater): PR 2 (Tier 2 manual-click) implementation plan 20-task TDD plan for shipping the manual-click update flow on top of the Tier 1 (notify) work merged in #7601. Covers UpdateExecutor, RollbackHandler, SessionDrainer, lock + trustedKeys, four admin endpoints (apply / cancel / acknowledge / log), admin UI updates, integration tests against a tmp git repo, and a manual smoke runbook for the spec's "before each tier ships" gate. Plan deliberately scopes signature verification to an opt-in stub (updates.requireSignature: false default) to avoid blocking on a separate release-signing project. Plan: docs/superpowers/plans/2026-05-08-auto-update-pr2-manual-click.md Spec: docs/superpowers/specs/2026-04-25-auto-update-design.md Issue: ether/etherpad#7607 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(updater): extend state + settings for Tier 2 manual-click Adds ExecutionStatus discriminated union, bootCount, and lastResult to UpdateState, plus the preApplyGraceMinutes/drainSeconds/diskSpaceMinMB/ requireSignature/trustedKeysPath knobs that Tier 2's executor needs. loadState backfills the new fields on Tier 1 state files so existing installs keep working. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(updater): PID-based update.lock with stale-pid reaping Single-flight guard for Tier 2's UpdateExecutor. Atomic O_CREAT|O_EXCL acquire; on EEXIST, sends signal 0 to the recorded PID and reaps if dead. Unparseable / partially-written lock files are treated as stale rather than fatal so a half-written lock from a SIGKILL'd parent doesn't lock the install out forever. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(updater): verifyReleaseTag — gpg-via-git stub for Tier 2 preflight Default updates.requireSignature=false: log a warning and return ok with reason=signature-not-required. Set true to make preflight refuse a tag whose signature does not verify under the system keyring (or trustedKeysPath via GNUPGHOME). Etherpad's release process does not yet sign tags consistently; turning the check on by default would break Tier 2 for every admin and forcing a release-signing change is out of scope for this PR. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(updater): preflight check pipeline for Tier 2 Pure orchestrator over injected probes for install-method, working tree, disk space, pnpm presence, lock state, remote tag existence and signature verification. Cheap-and-definitive checks run first; first failure short-circuits with a typed reason that the route layer will surface in the preflight-failed admin banner. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(updater): rolling update.log helpers (appendLine + tailLines) Direct file-append + size-based rotation rather than a log4js appender — avoids re-configuring log4js on top of the user's existing logconfig. appendLine creates parents, rotates at 10MB (configurable), keeps 5 backups by default. tailLines reads the last N lines for /admin/update/log. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(updater): SessionDrainer + handshake guard Drainer schedules T-60 / -30 / -10 broadcasts and resolves at T=0; isAcceptingConnections() flips off for the duration. PadMessageHandler consults the flag at the start of CLIENT_READY and disconnects new joiners with reason "updateInProgress" — existing sockets are unaffected. Drains shorter than 30s collapse the early timers to fire ASAP rather than queue past the drain end. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(updater): UpdateExecutor — snapshot, fetch/checkout/install/build, exit 75 Pure-DI orchestrator: spawnFn, copyFile, readSha, saveState, exit are all injected so unit tests run the full pipeline without spawning real children or mutating the real install. Streams stdout/stderr to update.log via the now-best-effort appendLine helper (swallows fs errors so the executor itself never breaks on read-only / unwritable log dirs). Failure paths transition to rolling-back and return — the route layer hands off to RollbackHandler which owns the rollback exit, so we don't double-exit and lose tail lines. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(updater): RollbackHandler — health-check timer + crash-loop guard checkPendingVerification arms a 60s timer at boot when state is pending-verification and increments bootCount; bootCount>2 forces an immediate rollback (crash-loop guard). markVerified persists the verified state and stops the timer. performRollback restores the backup lockfile, runs git checkout <fromSha> and pnpm install, lands on rolled-back or rollback-failed (terminal) on sub-step failure, exits 75 either way so the supervisor restart brings the new state up. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(updater): wire RollbackHandler into boot + UpdatePolicy honours rollback-failed - expressCreateServer now invokes checkPendingVerification before polling starts so a previous boot's pending-verification either re-arms the health-check timer or, when bootCount has climbed past the crash-loop threshold, forces an immediate rollback. - server.ts calls markBootHealthy after state hits RUNNING so /health-being-up is the implicit happy-path signal that cancels the rollback timer. - /admin/update/status surfaces execution + lastResult + lockHeld so the admin UI can render the right Apply / Cancel / Acknowledge state. - UpdatePolicy gains an `executionStatus` input. While it equals 'rollback-failed', canAuto / canAutonomous are denied (reason: rollback-failed-terminal); manual stays on because clicking Apply IS the intervention the terminal state needs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(updater): apply / cancel / acknowledge / log endpoints Strict admin-only POSTs that drive Tier 2's manual-click flow: - POST /admin/update/apply: acquire lock, persist preflight, run preflight, drain $drainSeconds, executeUpdate (which exits 75 on success), or run performRollback on a failure path (also exits 75). - POST /admin/update/cancel: cancel a pre-execute drain/preflight, write cancelled lastResult, release lock. - POST /admin/update/acknowledge: clear terminal states (preflight-failed, rolled-back, rollback-failed) back to idle. lastResult is preserved so the admin still sees what happened. - GET /admin/update/log: tail var/log/update.log (200 lines) for the in- progress UI. Strict admin auth. Also: - socketio hook exports getIo() so the apply endpoint can broadcast the drain shoutMessage outside the regular hook surface. - ep.json registers updateActions after admin/updateStatus. - 11 mocha integration tests cover auth, policy denial, execution-busy, acknowledge-clears-terminal, log content-type. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(updater): admin UI Apply/Cancel/Acknowledge + live log stream UpdatePage renders the right action set based on execution.status: Apply when idle/verified and policy allows, Cancel during preflight/draining, Acknowledge on terminal preflight-failed / rolled-back / rollback-failed. While the executor is in flight (preflight/draining/executing/rolling-back) the page polls /admin/update/log + /admin/update/status once a second and shows the rolling tail; polling stops automatically when the run terminates. lastResult and policy denial reasons surface localised copy. Buttons disable themselves while a network round-trip is in flight to dodge double-clicks. New i18n keys live under update.page.{apply,cancel, acknowledge,log,execution,policy.*,last_result.*}, update.execution.*, update.banner.terminal.rollback-failed, and update.drain.{t60,t30,t10}. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(updater): pad shoutMessage renders update.drain.* via html10n broadcastShout now sends {messageKey, values, sticky} so the existing pad-side shout pipeline can route through html10n.get(). The renderer gains a values pass-through so update.drain.t60 etc. interpolate {{seconds}}, and gives updater shouts a different gritter title (the banner.title localised string) so users know it's a system event rather than a generic admin message. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(updater): rollback uses git checkout -f + integration suite over tmp git repo RollbackHandler now does git checkout -f <fromSha> BEFORE overlaying the backup lockfile. Without -f, git refuses checkout when there are unstaged modifications to files it would overwrite — exactly the case after a partial executor run that mutated the working tree. With -f the partial mutation is discarded and the working tree returns to fromSha cleanly. The backup-lockfile copy is still done (belt-and-braces) but tolerates ENOENT since checkout already restored the right lockfile. The new integration suite at src/tests/backend/specs/updater-integration.ts exercises the full pipeline against a disposable git repo: happy path, install-fail rollback, build-fail rollback, crash-loop guard, and a target-sha-doesn't-exist rollback-failed terminal case. 5 mocha tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(updater): Playwright admin Apply / Cancel / Acknowledge flow Stubs /admin/update/status (and /admin/update/apply for the apply path) at the route level so we can assert UI transitions without actually running an update. Four scenarios: - Apply button POSTs and re-fetches status (>=2 status fetches total). - install-method-not-writable hides the button and shows localised denial copy. - rollback-failed terminal state shows the Acknowledge button and the "Manual intervention required" lastResult copy. - lockHeld=true hides Apply even when policy.canManual is on. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(updater): admin banner shows rollback-failed terminal alert When execution.status === 'rollback-failed' the banner switches to a role=alert with the strong update.banner.terminal.rollback-failed copy and overrides the regular "update available" framing — an admin who left the system in this state needs to fix it before any other admin work matters. Other terminal states (preflight-failed, rolled-back) are informational and surface on the page itself, not the banner. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(updater): Tier 2 admin docs + manual smoke runbook + CHANGELOG doc/admin/updates.md gains a full Tier 2 section: prerequisites (git install + process supervisor with sample systemd unit), Apply flow with timings, every failure mode and the resulting state, the four endpoints, and the signature-verification opt-in. Settings table picks up the new updates.* knobs. docs/superpowers/specs/2026-04-25-auto-update-runbook.md is the manual smoke runbook the design spec calls for: disposable VM, systemd unit, every observable transition (happy path, install/ build-fail rollback, crash-loop guard, rollback-failed terminal, cancel during drain) plus a sign-off checklist for the release cut. CHANGELOG Unreleased section explains the supervisor requirement and points readers at the runbook. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(updater): note docker-friendly update flows as follow-up work Tier 2 refuses Apply on installMethod=docker because in-container mutation doesn't survive a container restart. Adds a future-work note covering the two reasonable paths for an in-product docker Apply button (instructions-only vs deploy-webhook) and explicitly rules out mounting /var/run/docker.sock as a footgun. Watchtower gets a pointer for admins who want fully autonomous docker updates today. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(updater): address Qodo review (1-6) + Playwright strict-mode CI fix 1. Tier 2 endpoints now gate on tier in {manual, auto, autonomous} — notify and off return 404 to match the prior PR-1 behaviour. Gate is evaluated per-request via app.use middleware so a settings.json reload takes effect without a full restart, and so integration tests can flip the tier dynamically. Adds a regression test that exercises 404 at tier=notify across all four endpoints. 2. cancel/apply race fixed: /admin/update/cancel no longer releases the lock — apply's finally block owns it for the request's lifetime. Apply now reloads state after preflight and aborts with 409 cancelled-during- preflight if execution.status is no longer 'preflight' for the same targetTag. Prevents a second apply from sneaking in while the first is still running its slow checks, and prevents the post-cancel apply from continuing into drain/execute. 3. SessionDrainer now restores acceptingConnections=true at drain completion (not just on cancel). The lock + persisted execution.status prevent a fresh apply from racing in — the in-memory flag was redundant safety that turned into a wedge if the executor threw post-drain. Adds a unit test asserting the flag is restored after natural drain end. 4. PadMessageHandler drain guard switched from socket.json.send (a socket.io v2/v3 API that may not exist on v4) to socket.emit('message', ...) for consistency with the other disconnect paths in the file. 5. Spawn 'error' handlers added to runStep helpers in UpdateExecutor and RollbackHandler, plus the gpg verify-tag spawn in trustedKeys. Without them, a missing/unexecutable binary leaves the promise hanging forever and the update flow stuck in-flight. SpawnFn type extended to allow on('error', ...) listeners cleanly. Spawn errors now resolve with code 1 + the error message in stderr, so the existing failure-detection branches fire normally. 6. executeUpdate body wrapped in try/catch. An exception from readSha, saveState, copyFile, or any step now lands in a rolling-back persist + returns failed-checkout, so the route's post-executor rollback path picks it up. State can no longer wedge at 'executing'. The catch's inner saveState is itself try/wrapped so a write-after-write failure doesn't crash the route either. CI: Playwright update-page-actions strict-mode violation fixed. Both the banner and the lastResult <p> contain "Manual intervention required"; selector now scopes to p.last-result-rollback-failed for the lastResult assertion specifically. 129 vitest unit tests + 23 mocha integration tests passing; ts-check clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(updater): address Qodo #7 (status leak) + #8 (short-drain values) #7. /admin/update/status now redacts diagnostic strings for unauth callers even when requireAdminForStatus is left at its default (false). Status enum + outcome enum are kept (the admin banner / pad-side badge need them to render the right UI) but execution.reason / execution.fromSha / execution.targetTag and the same fields on lastResult are stripped. Authed admin sessions still get the full payload — they're looking at their own server's diagnostics. Two new mocha tests cover both paths: "redacts execution.reason / lastResult.reason for unauth callers" and "returns full diagnostic payload to authed admin sessions". #8. SessionDrainer no longer schedules T-30 / T-10 broadcasts when the configured drainSeconds can't honour them. Previously, with drainSeconds < 30 the T-30 timer fired at zero remaining but the broadcast still claimed "30 seconds" — misleading. Now T-30 only schedules when drainSeconds > 30 and T-10 only when > 10. Admins picking a short drain get fewer announcements but each carries an accurate countdown. The opening announcement now reports the configured drain length rather than a hardcoded 60. Two updated unit tests: drainSeconds=15 (skips T-30, still fires T-10) and drainSeconds=5 (skips both). 131 vitest unit + 26 mocha integration tests passing; ts-check clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(updater): address Qodo follow-up — tag injection, rollback rejections, state validation Qodo posted three new concerns after the first fix push. 1. Git tag option injection (security). The release tag from GitHub's tag_name flowed into `git checkout` / `git verify-tag` as a positional arg. A tag starting with '-' would be parsed as an option and could bypass signature verification or change checkout semantics. Mitigated in three layers: - New refSafety helper (isValidTag / assertValidTag / refsTagsForm) enforces a strict subset of git's check-ref-format spec: rejects leading '-' or '.', whitespace, control chars, and ~ ^ : ? * [ \\ and the '..' sequence. - VersionChecker validates tag_name before persisting to state, so a malformed value from a misconfigured githubRepo never lands on disk. - UpdateExecutor calls assertValidTag and uses the refs/tags/<tag> form for git checkout. trustedKeys also validates and adds '--' to git verify-tag for an end-of-options marker. updateActions does an up-front isValidTag check on state.latest.tag so a corrupt state file gets a clean 409 instead of a 500. 2. Unhandled rollback rejections. checkPendingVerification was firing `void deps.saveState(...)` and `void performRollback(...)` without .catch(), so an fs error during boot's rollback path would bubble out as an unhandled rejection. Both callsites now go through fireSaveState / fireRollback helpers that catch and log; rollback rejections fall through to a best-effort terminal-state write + exit 75 so the supervisor can re-try the next boot with bootCount++. 3. Execution state under-validated. isValidExecution previously checked only that `status` was a known enum value, so a hand-edited state file with `{execution: {status: 'pending-verification'}}` (missing fromSha / targetTag / deadlineAt) would pass validation and reach RollbackHandler with undefined refs. The validator now consults a per-status required-fields map mirroring the ExecutionStatus union in types.ts and rejects empty strings as well as missing fields. Same tightening applied to lastResult.outcome (must be in the allowed enum, not just any string). Six new unit tests cover hand-edited corruption. 145 vitest + 26 mocha tests green; ts-check clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
828 lines
30 KiB
Docker
828 lines
30 KiB
Docker
/**
|
|
* THIS IS THE SETTINGS FILE THAT IS COPIED INSIDE THE DOCKER CONTAINER.
|
|
*
|
|
* By default, some runtime customizations are supported (see the
|
|
* documentation).
|
|
*
|
|
* If you need more control, edit this file and rebuild the container.
|
|
*/
|
|
|
|
/*
|
|
* This file must be valid JSON. But comments are allowed
|
|
*
|
|
* Please edit settings.json, not settings.json.template
|
|
*
|
|
* Please note that starting from Etherpad 1.6.0 you can store DB credentials in
|
|
* a separate file (credentials.json).
|
|
*
|
|
*
|
|
* ENVIRONMENT VARIABLE SUBSTITUTION
|
|
* =================================
|
|
*
|
|
* All the configuration values can be read from environment variables using the
|
|
* syntax "${ENV_VAR}" or "${ENV_VAR:default_value}".
|
|
*
|
|
* This is useful, for example, when running in a Docker container.
|
|
*
|
|
* DETAILED RULES:
|
|
* - If the environment variable is set to the string "true" or "false", the
|
|
* value becomes Boolean true or false.
|
|
* - If the environment variable is set to the string "null", the value
|
|
* becomes null.
|
|
* - If the environment variable is set to the string "undefined", the setting
|
|
* is removed entirely, except when used as the member of an array in which
|
|
* case it becomes null.
|
|
* - If the environment variable is set to a string representation of a finite
|
|
* number, the string is converted to that number.
|
|
* - If the environment variable is set to any other string, including the
|
|
* empty string, the value is that string.
|
|
* - If the environment variable is unset and a default value is provided, the
|
|
* value is as if the environment variable was set to the provided default:
|
|
* - "${UNSET_VAR:}" becomes the empty string.
|
|
* - "${UNSET_VAR:foo}" becomes the string "foo".
|
|
* - "${UNSET_VAR:true}" and "${UNSET_VAR:false}" become true and false.
|
|
* - "${UNSET_VAR:null}" becomes null.
|
|
* - "${UNSET_VAR:undefined}" causes the setting to be removed (or be set
|
|
* to null, if used as a member of an array).
|
|
* - If the environment variable is unset and no default value is provided,
|
|
* the value becomes null. THIS BEHAVIOR MAY CHANGE IN A FUTURE VERSION OF
|
|
* ETHERPAD; if you want the default value to be null, you should explicitly
|
|
* specify "null" as the default value.
|
|
*
|
|
* EXAMPLE:
|
|
* "port": "${PORT:9001}"
|
|
* "minify": "${MINIFY}"
|
|
* "skinName": "${SKIN_NAME:colibris}"
|
|
*
|
|
* Would read the configuration values for those items from the environment
|
|
* variables PORT, MINIFY and SKIN_NAME.
|
|
*
|
|
* If PORT and SKIN_NAME variables were not defined, the default values 9001 and
|
|
* "colibris" would be used.
|
|
* The configuration value "minify", on the other hand, does not have a
|
|
* designated default value. Thus, if the environment variable MINIFY were
|
|
* undefined, "minify" would be null.
|
|
*
|
|
* REMARKS:
|
|
* 1) please note that variable substitution always needs to be quoted.
|
|
*
|
|
* "port": 9001, <-- Literal values. When not using
|
|
* "minify": false substitution, only strings must be
|
|
* "skinName": "colibris" quoted. Booleans and numbers must not.
|
|
*
|
|
* "port": "${PORT:9001}" <-- CORRECT: if you want to use a variable
|
|
* "minify": "${MINIFY:true}" substitution, put quotes around its name,
|
|
* "skinName": "${SKIN_NAME}" even if the required value is a number or
|
|
* a boolean.
|
|
* Etherpad will take care of rewriting it
|
|
* to the proper type if necessary.
|
|
*
|
|
* "port": ${PORT:9001} <-- ERROR: this is not valid json. Quotes
|
|
* "minify": ${MINIFY} around variable names are missing.
|
|
* "skinName": ${SKIN_NAME}
|
|
*
|
|
* 2) Beware of undefined variables and default values: nulls and empty strings
|
|
* are different!
|
|
*
|
|
* This is particularly important for user's passwords (see the relevant
|
|
* section):
|
|
*
|
|
* "password": "${PASSW}" // if PASSW is not defined would result in password === null
|
|
* "password": "${PASSW:}" // if PASSW is not defined would result in password === ''
|
|
*
|
|
* If you want to use an empty value (null) as default value for a variable,
|
|
* simply do not set it, without putting any colons: "${SOFFICE}".
|
|
*
|
|
* 3) if you want to use newlines in the default value of a string parameter,
|
|
* use "\n" as usual.
|
|
*
|
|
* "defaultPadText" : "${DEFAULT_PAD_TEXT:Line 1\nLine 2}"
|
|
*/
|
|
{
|
|
/*
|
|
* Name your instance!
|
|
*/
|
|
"title": "${TITLE:Etherpad}",
|
|
|
|
/*
|
|
* Whether to show recent pads on the homepage or not.
|
|
*/
|
|
"showRecentPads": "${SHOW_RECENT_PADS:true}",
|
|
|
|
/*
|
|
* Pathname of the favicon you want to use. If null, the skin's favicon is
|
|
* used if one is provided by the skin, otherwise the default Etherpad favicon
|
|
* is used. If this is a relative path it is interpreted as relative to the
|
|
* Etherpad root directory.
|
|
*/
|
|
"favicon": "${FAVICON:null}",
|
|
|
|
/*
|
|
* Canonical public origin of this Etherpad instance, e.g.
|
|
* "https://pad.example.com" (no trailing slash, must include scheme).
|
|
* Used to build absolute URLs in OG/Twitter link-preview meta tags.
|
|
* When null, falls back to the incoming request's protocol+Host.
|
|
*/
|
|
"publicURL": "${PUBLIC_URL:null}",
|
|
|
|
/*
|
|
* Open Graph / Twitter Card metadata for link previews.
|
|
*
|
|
* SOCIAL_META_DESCRIPTION: when set, this exact text is used as
|
|
* og:description regardless of negotiated language. Most preview crawlers
|
|
* (WhatsApp, Signal, Slack, ...) don't send Accept-Language, so without an
|
|
* override they always hit the English fallback in the i18n catalog.
|
|
* Leave unset (null) to use the catalog (key `pad.social.description`).
|
|
*/
|
|
"socialMeta": {
|
|
"description": "${SOCIAL_META_DESCRIPTION:null}"
|
|
},
|
|
|
|
/*
|
|
* Skin name.
|
|
*
|
|
* Its value has to be an existing directory under src/static/skins.
|
|
* You can write your own, or use one of the included ones:
|
|
*
|
|
* - "no-skin": an empty skin (default). This yields the unmodified,
|
|
* traditional Etherpad theme.
|
|
* - "colibris": the new experimental skin (since Etherpad 1.8), candidate to
|
|
* become the default in Etherpad 2.0
|
|
*/
|
|
"skinName": "${SKIN_NAME:colibris}",
|
|
|
|
/*
|
|
* Skin Variants
|
|
*
|
|
* Use the UI skin variants builder at /p/test#skinvariantsbuilder
|
|
*
|
|
* For the colibris skin only, you can choose how to render the three main
|
|
* containers:
|
|
* - toolbar (top menu with icons)
|
|
* - editor (containing the text of the pad)
|
|
* - background (area outside of editor, mostly visible when using page style)
|
|
*
|
|
* For each of the 3 containers you can choose 4 color combinations:
|
|
* super-light, light, dark, super-dark.
|
|
*
|
|
* For example, to make the toolbar dark, you will include "dark-toolbar" into
|
|
* skinVariants.
|
|
*
|
|
* You can provide multiple skin variants separated by spaces. Default
|
|
* skinVariant is "super-light-toolbar super-light-editor light-background".
|
|
*
|
|
* For the editor container, you can also make it full width by adding
|
|
* "full-width-editor" variant (by default editor is rendered as a page, with
|
|
* a max-width of 900px).
|
|
*/
|
|
"skinVariants": "${SKIN_VARIANTS:super-light-toolbar super-light-editor light-background}",
|
|
|
|
/*
|
|
* IP and port which Etherpad should bind at.
|
|
*
|
|
* Binding to a Unix socket is also supported: just use an empty string for
|
|
* the ip, and put the full path to the socket in the port parameter.
|
|
*
|
|
* EXAMPLE USING UNIX SOCKET:
|
|
* "ip": "", // <-- has to be an empty string
|
|
* "port" : "/somepath/etherpad.socket", // <-- path to a Unix socket
|
|
*/
|
|
"ip": "${IP:0.0.0.0}",
|
|
"port": "${PORT:9001}",
|
|
|
|
/*
|
|
* Option to hide/show the settings.json in admin page.
|
|
*
|
|
* Default option is set to true
|
|
*/
|
|
"showSettingsInAdminPage": "${SHOW_SETTINGS_IN_ADMIN_PAGE:true}",
|
|
|
|
/*
|
|
* Enable/disable the metrics endpoint.
|
|
*
|
|
* This is used by the monitoring plugins to collect metrics about Etherpad.
|
|
* If you do not use any monitoring plugins, you can disable this.
|
|
*/
|
|
"enableMetrics": "${ENABLE_METRICS:true}",
|
|
|
|
/*
|
|
* Self-update subsystem.
|
|
* tier: "off" | "notify" | "manual" | "auto" | "autonomous"
|
|
* Default "notify" shows a banner when an update is available.
|
|
* Docker installs are read-only — tiers above "notify" are not applied even if requested.
|
|
*/
|
|
"updates": {
|
|
"tier": "notify",
|
|
"source": "github",
|
|
"channel": "stable",
|
|
"installMethod": "docker",
|
|
"checkIntervalHours": 6,
|
|
"githubRepo": "ether/etherpad",
|
|
"requireAdminForStatus": false,
|
|
"preApplyGraceMinutes": 0,
|
|
"drainSeconds": 60,
|
|
"rollbackHealthCheckSeconds": 60,
|
|
"diskSpaceMinMB": 500,
|
|
"requireSignature": false,
|
|
"trustedKeysPath": null
|
|
},
|
|
|
|
/*
|
|
* Contact address for admin notifications (updates, security advisories, future features).
|
|
* Set to null to disable outbound mail from the updater.
|
|
*/
|
|
"adminEmail": null,
|
|
|
|
/*
|
|
* Settings for cleanup of pads
|
|
*/
|
|
"cleanup": {
|
|
"enabled": false,
|
|
"keepRevisions": 5
|
|
},
|
|
|
|
/*
|
|
* GDPR Art. 17 author erasure REST endpoint (anonymizeAuthor).
|
|
*
|
|
* Disabled by default — enable only when an operator process exists to
|
|
* authorise erasure requests.
|
|
*/
|
|
"gdprAuthorErasure": {
|
|
"enabled": "${GDPR_AUTHOR_ERASURE_ENABLED:false}"
|
|
},
|
|
|
|
/*
|
|
The authentication method used by the server.
|
|
The default value is sso
|
|
If you want to use the old authentication system, change this to apikey
|
|
*/
|
|
"authenticationMethod": "${AUTHENTICATION_METHOD:sso}",
|
|
|
|
/**
|
|
* Allow setting dark mode for the enduser. This is so if the user has preferred dark mode in their browser, Etherpad will respect that.
|
|
* Of course this overrides all the skin variants and the skinName set by the administrator.
|
|
**/
|
|
"enableDarkMode": "${ENABLE_DARK_MODE:true}",
|
|
|
|
/**
|
|
* Enable creator-owned Pad-wide Settings and new-pad default seeding from My View.
|
|
* The pad creator (revision-0 author) gets the "Pad-wide Settings" section,
|
|
* which lets them set defaults and optionally enforce them for other users.
|
|
* Other users see only "User Settings" (their own view options).
|
|
* Set to false to revert to the legacy single-settings behavior.
|
|
**/
|
|
"enablePadWideSettings": "${ENABLE_PAD_WIDE_SETTINGS:true}",
|
|
|
|
/*
|
|
* Optional privacy banner. See settings.json.template for full field docs.
|
|
*/
|
|
"privacyBanner": {
|
|
"enabled": "${PRIVACY_BANNER_ENABLED:false}",
|
|
"title": "${PRIVACY_BANNER_TITLE:Privacy notice}",
|
|
"body": "${PRIVACY_BANNER_BODY:This instance processes pad content on our servers. See the linked policy for retention and how to request erasure.}",
|
|
"learnMoreUrl": "${PRIVACY_BANNER_LEARN_MORE_URL:null}",
|
|
"dismissal": "${PRIVACY_BANNER_DISMISSAL:dismissible}"
|
|
},
|
|
|
|
/*
|
|
* Node native SSL support
|
|
*
|
|
* This is disabled by default.
|
|
* Make sure to have the minimum and correct file access permissions set so
|
|
* that the Etherpad server can access them
|
|
*/
|
|
|
|
/*
|
|
"ssl" : {
|
|
"key" : "/path-to-your/epl-server.key",
|
|
"cert" : "/path-to-your/epl-server.crt",
|
|
"ca": ["/path-to-your/epl-intermediate-cert1.crt", "/path-to-your/epl-intermediate-cert2.crt"]
|
|
},
|
|
*/
|
|
|
|
|
|
/*
|
|
* Enables the use of a different server. We have a different one that syncs changes from the original server.
|
|
* It is hosted on GitHub and should not be blocked by many firewalls.
|
|
* https://etherpad.org/ep_infos
|
|
*/
|
|
|
|
"updateServer": "https://etherpad.org/ep_infos",
|
|
|
|
/*
|
|
* The type of the database.
|
|
*
|
|
* You can choose between many DB drivers, for example: dirty, postgres,
|
|
* sqlite, mysql.
|
|
*
|
|
* You shouldn't use "dirty" for for anything else than testing or
|
|
* development.
|
|
*
|
|
*
|
|
* Database specific settings are dependent on dbType, and go in dbSettings.
|
|
* Remember that since Etherpad 1.6.0 you can also store this information in
|
|
* credentials.json.
|
|
*
|
|
* For a complete list of the supported drivers, please refer to:
|
|
* https://www.npmjs.com/package/ueberdb2
|
|
*/
|
|
|
|
"dbType": "${DB_TYPE:dirty}",
|
|
"dbSettings": {
|
|
"host": "${DB_HOST:undefined}",
|
|
"port": "${DB_PORT:undefined}",
|
|
"database": "${DB_NAME:undefined}",
|
|
"user": "${DB_USER:undefined}",
|
|
"password": "${DB_PASS:undefined}",
|
|
"charset": "${DB_CHARSET:undefined}",
|
|
"filename": "${DB_FILENAME:var/dirty.db}",
|
|
"collection": "${DB_COLLECTION:undefined}",
|
|
"url": "${DB_URL:undefined}"
|
|
},
|
|
|
|
/*
|
|
* The default text of a pad
|
|
*/
|
|
"defaultPadText" : "${DEFAULT_PAD_TEXT:Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at https:\/\/etherpad.org\n}",
|
|
|
|
/*
|
|
* Default Pad behavior.
|
|
*
|
|
* Change them if you want to override.
|
|
*/
|
|
"padOptions": {
|
|
"noColors": "${PAD_OPTIONS_NO_COLORS:false}",
|
|
"showControls": "${PAD_OPTIONS_SHOW_CONTROLS:true}",
|
|
"showChat": "${PAD_OPTIONS_SHOW_CHAT:true}",
|
|
"showLineNumbers": "${PAD_OPTIONS_SHOW_LINE_NUMBERS:true}",
|
|
"useMonospaceFont": "${PAD_OPTIONS_USE_MONOSPACE_FONT:false}",
|
|
"userName": "${PAD_OPTIONS_USER_NAME:null}",
|
|
"userColor": "${PAD_OPTIONS_USER_COLOR:null}",
|
|
"rtl": "${PAD_OPTIONS_RTL:false}",
|
|
"alwaysShowChat": "${PAD_OPTIONS_ALWAYS_SHOW_CHAT:false}",
|
|
"chatAndUsers": "${PAD_OPTIONS_CHAT_AND_USERS:false}",
|
|
"lang": "${PAD_OPTIONS_LANG:null}",
|
|
"fadeInactiveAuthorColors": "${PAD_OPTIONS_FADE_INACTIVE_AUTHOR_COLORS:true}",
|
|
"enforceReadableAuthorColors": "${PAD_OPTIONS_ENFORCE_READABLE_AUTHOR_COLORS:true}"
|
|
},
|
|
|
|
/*
|
|
* Pad Shortcut Keys
|
|
*/
|
|
"padShortcutEnabled" : {
|
|
"altF9": "${PAD_SHORTCUTS_ENABLED_ALT_F9:true}", /* focus on the File Menu and/or editbar */
|
|
"altC": "${PAD_SHORTCUTS_ENABLED_ALT_C:true}", /* focus on the Chat window */
|
|
"cmdShift2": "${PAD_SHORTCUTS_ENABLED_CMD_SHIFT_2:true}", /* shows a gritter popup showing a line author */
|
|
"delete": "${PAD_SHORTCUTS_ENABLED_DELETE:true}",
|
|
"return": "${PAD_SHORTCUTS_ENABLED_RETURN:true}",
|
|
"esc": "${PAD_SHORTCUTS_ENABLED_ESC:true}", /* in mozilla versions 14-19 avoid reconnecting pad */
|
|
"cmdS": "${PAD_SHORTCUTS_ENABLED_CMD_S:true}", /* save a revision */
|
|
"tab": "${PAD_SHORTCUTS_ENABLED_TAB:true}", /* indent */
|
|
"cmdZ": "${PAD_SHORTCUTS_ENABLED_CMD_Z:true}", /* undo/redo */
|
|
"cmdY": "${PAD_SHORTCUTS_ENABLED_CMD_Y:true}", /* redo */
|
|
"cmdI": "${PAD_SHORTCUTS_ENABLED_CMD_I:true}", /* italic */
|
|
"cmdB": "${PAD_SHORTCUTS_ENABLED_CMD_B:true}", /* bold */
|
|
"cmdU": "${PAD_SHORTCUTS_ENABLED_CMD_U:true}", /* underline */
|
|
"cmd5": "${PAD_SHORTCUTS_ENABLED_CMD_5:true}", /* strike through */
|
|
"cmdShiftL": "${PAD_SHORTCUTS_ENABLED_CMD_SHIFT_L:true}", /* unordered list */
|
|
"cmdShiftN": "${PAD_SHORTCUTS_ENABLED_CMD_SHIFT_N:true}", /* ordered list */
|
|
"cmdShift1": "${PAD_SHORTCUTS_ENABLED_CMD_SHIFT_1:true}", /* ordered list */
|
|
"cmdShiftC": "${PAD_SHORTCUTS_ENABLED_CMD_SHIFT_C:true}", /* clear authorship */
|
|
"cmdH": "${PAD_SHORTCUTS_ENABLED_CMD_H:true}", /* backspace */
|
|
"ctrlHome": "${PAD_SHORTCUTS_ENABLED_CTRL_HOME:true}", /* scroll to top of pad */
|
|
"pageUp": "${PAD_SHORTCUTS_ENABLED_PAGE_UP:true}",
|
|
"pageDown": "${PAD_SHORTCUTS_ENABLED_PAGE_DOWN:true}"
|
|
},
|
|
|
|
/*
|
|
* Should we suppress errors from being visible in the default Pad Text?
|
|
*/
|
|
"suppressErrorsInPadText": "${SUPPRESS_ERRORS_IN_PAD_TEXT:false}",
|
|
|
|
/*
|
|
* If this option is enabled, a user must have a session to access pads.
|
|
* This effectively allows only group pads to be accessed.
|
|
*/
|
|
"requireSession": "${REQUIRE_SESSION:false}",
|
|
|
|
/*
|
|
* Users may edit pads but not create new ones.
|
|
*
|
|
* Pad creation is only via the API.
|
|
* This applies both to group pads and regular pads.
|
|
*/
|
|
"editOnly": "${EDIT_ONLY:false}",
|
|
|
|
/*
|
|
* If true, all css & js will be minified before sending to the client.
|
|
*
|
|
* This will improve the loading performance massively, but makes it difficult
|
|
* to debug the javascript/css
|
|
*/
|
|
"minify": "${MINIFY:true}",
|
|
|
|
/*
|
|
* How long may clients use served javascript code (in seconds)?
|
|
*
|
|
* Not setting this may cause problems during deployment.
|
|
* Set to 0 to disable caching.
|
|
*/
|
|
"maxAge": "${MAX_AGE:21600}", // 60 * 60 * 6 = 6 hours
|
|
|
|
/*
|
|
* Absolute path to the soffice (LibreOffice) executable.
|
|
*
|
|
* When configured, soffice handles all advanced office-format
|
|
* conversions (docx, pdf, odt, doc, rtf -- both directions). When
|
|
* null, Etherpad falls back to pure-JS in-process converters
|
|
* that handle docx export, pdf export, and docx import natively.
|
|
* odt/doc/rtf export and pdf import still require soffice.
|
|
*/
|
|
"soffice": "${SOFFICE:null}",
|
|
|
|
/*
|
|
* When true (the default), the "Microsoft Word" export button
|
|
* downloads a .docx file -- via soffice if it's configured, or via
|
|
* the in-process html-to-docx converter otherwise. Set to false to
|
|
* revert to legacy .doc output (.doc still requires soffice).
|
|
*/
|
|
"docxExport": "${DOCX_EXPORT:true}",
|
|
|
|
/*
|
|
* txt, doc, docx, rtf, odt, html & htm
|
|
*/
|
|
"allowUnknownFileEnds": "${ALLOW_UNKNOWN_FILE_ENDS:true}",
|
|
|
|
/*
|
|
* This setting is used if you require authentication of all users.
|
|
*
|
|
* Note: "/admin" always requires authentication.
|
|
*/
|
|
"requireAuthentication": "${REQUIRE_AUTHENTICATION:false}",
|
|
|
|
/*
|
|
* Require authorization by a module, or a user with is_admin set, see below.
|
|
*/
|
|
"requireAuthorization": "${REQUIRE_AUTHORIZATION:false}",
|
|
|
|
/*
|
|
* When you use NGINX or another proxy/load-balancer set this to true.
|
|
*
|
|
* This is especially necessary when the reverse proxy performs SSL
|
|
* termination, otherwise the cookies will not have the "secure" flag.
|
|
*
|
|
* The other effect will be that the logs will contain the real client's IP,
|
|
* instead of the reverse proxy's IP.
|
|
*/
|
|
"trustProxy": "${TRUST_PROXY:false}",
|
|
|
|
/*
|
|
* Settings controlling the session cookie issued by Etherpad.
|
|
*/
|
|
"cookie": {
|
|
/*
|
|
* How often (in milliseconds) the key used to sign the express_sid cookie
|
|
* should be rotated. Long rotation intervals reduce signature verification
|
|
* overhead (because there are fewer historical keys to check) and database
|
|
* load (fewer historical keys to store, and less frequent queries to
|
|
* get/update the keys). Short rotation intervals are slightly more secure.
|
|
*
|
|
* Multiple Etherpad processes sharing the same database (table) is
|
|
* supported as long as the clock sync error is significantly less than this
|
|
* value.
|
|
*
|
|
* Key rotation can be disabled (not recommended) by setting this to 0 or
|
|
* null, or by disabling session expiration (see sessionLifetime).
|
|
*/
|
|
// 86400000 = 1d * 24h/d * 60m/h * 60s/m * 1000ms/s
|
|
"keyRotationInterval": "${COOKIE_KEY_ROTATION_INTERVAL:86400000}",
|
|
|
|
/*
|
|
* Value of the SameSite cookie property. "Lax" is recommended unless
|
|
* Etherpad will be embedded in an iframe from another site, in which case
|
|
* this must be set to "None". Note: "None" will not work (the browser will
|
|
* not send the cookie to Etherpad) unless https is used to access Etherpad
|
|
* (either directly or via a reverse proxy with "trustProxy" set to true).
|
|
*
|
|
* "Strict" is not recommended because it has few security benefits but
|
|
* significant usability drawbacks vs. "Lax". See
|
|
* https://stackoverflow.com/q/41841880 for discussion.
|
|
*/
|
|
"sameSite": "${COOKIE_SAME_SITE:Lax}",
|
|
|
|
/*
|
|
* How long (in milliseconds) after navigating away from Etherpad before the
|
|
* user is required to log in again. (The express_sid cookie is set to
|
|
* expire at time now + sessionLifetime when first created, and its
|
|
* expiration time is periodically refreshed to a new now + sessionLifetime
|
|
* value.) If requireAuthentication is false then this value does not really
|
|
* matter.
|
|
*
|
|
* The "best" value depends on your users' usage patterns and the amount of
|
|
* convenience you desire. A long lifetime is more convenient (users won't
|
|
* have to log back in as often) but has some drawbacks:
|
|
* - It increases the amount of state kept in the database.
|
|
* - It might weaken security somewhat: The cookie expiration is refreshed
|
|
* indefinitely without consulting authentication or authorization
|
|
* hooks, so once a user has accessed a pad, the user can continue to
|
|
* use the pad until the user leaves for longer than sessionLifetime.
|
|
* - More historical keys (sessionLifetime / keyRotationInterval) must be
|
|
* checked when verifying signatures.
|
|
*
|
|
* Session lifetime can be set to infinity (not recommended) by setting this
|
|
* to null or 0. Note that if the session does not expire, most browsers
|
|
* will delete the cookie when the browser exits, but a session record is
|
|
* kept in the database forever.
|
|
*/
|
|
// 864000000 = 10d * 24h/d * 60m/h * 60s/m * 1000ms/s
|
|
"sessionLifetime": "${COOKIE_SESSION_LIFETIME:864000000}",
|
|
|
|
/*
|
|
* How long (in milliseconds) before the expiration time of an active user's
|
|
* session is refreshed (to now + sessionLifetime). This setting affects the
|
|
* following:
|
|
* - How often a new session expiration time will be written to the
|
|
* database.
|
|
* - How often each user's browser will ping the Etherpad server to
|
|
* refresh the expiration time of the session cookie.
|
|
*
|
|
* High values reduce the load on the database and the load from browsers,
|
|
* but can shorten the effective session lifetime if Etherpad is restarted
|
|
* or the user navigates away.
|
|
*
|
|
* Automatic session refreshes can be disabled (not recommended) by setting
|
|
* this to null.
|
|
*/
|
|
// 86400000 = 1d * 24h/d * 60m/h * 60s/m * 1000ms/s
|
|
"sessionRefreshInterval": "${COOKIE_SESSION_REFRESH_INTERVAL:86400000}"
|
|
},
|
|
|
|
/*
|
|
* Controls what Etherpad writes to its logs about client IP addresses.
|
|
* Allowed values: "anonymous" (default), "truncated", "full".
|
|
* See settings.json.template for details.
|
|
*/
|
|
"ipLogging": "${IP_LOGGING:anonymous}",
|
|
|
|
/*
|
|
* Deprecated — use `ipLogging` above. Still honoured for one release
|
|
* cycle: true → "anonymous", false → "full".
|
|
*/
|
|
"disableIPlogging": "${DISABLE_IP_LOGGING:false}",
|
|
|
|
/*
|
|
* Allow any user who can edit a pad to delete it without the one-time pad
|
|
* deletion token. If false, only the original creator's author cookie or the
|
|
* deletion token can delete the pad.
|
|
*/
|
|
"allowPadDeletionByAllUsers": "${ALLOW_PAD_DELETION_BY_ALL_USERS:false}",
|
|
|
|
/*
|
|
* Time (in seconds) to automatically reconnect pad when a "Force reconnect"
|
|
* message is shown to user.
|
|
*
|
|
* Set to 0 to disable automatic reconnection.
|
|
*/
|
|
"automaticReconnectionTimeout": "${AUTOMATIC_RECONNECTION_TIMEOUT:0}",
|
|
|
|
/*
|
|
* By default, when caret is moved out of viewport, it scrolls the minimum
|
|
* height needed to make this line visible.
|
|
*/
|
|
"scrollWhenFocusLineIsOutOfViewport": {
|
|
|
|
/*
|
|
* Percentage of viewport height to be additionally scrolled.
|
|
*
|
|
* E.g.: use "percentage.editionAboveViewport": 0.5, to place caret line in
|
|
* the middle of viewport, when user edits a line above of the
|
|
* viewport
|
|
*
|
|
* Set to 0 to disable extra scrolling
|
|
*/
|
|
"percentage": {
|
|
"editionAboveViewport": "${FOCUS_LINE_PERCENTAGE_ABOVE:0}",
|
|
"editionBelowViewport": "${FOCUS_LINE_PERCENTAGE_BELOW:0}"
|
|
},
|
|
|
|
/*
|
|
* Time (in milliseconds) used to animate the scroll transition.
|
|
* Set to 0 to disable animation
|
|
*/
|
|
"duration": "${FOCUS_LINE_DURATION:0}",
|
|
|
|
/*
|
|
* Flag to control if it should scroll when user places the caret in the
|
|
* last line of the viewport
|
|
*/
|
|
"scrollWhenCaretIsInTheLastLineOfViewport": "${FOCUS_LINE_CARET_SCROLL:false}",
|
|
|
|
/*
|
|
* Percentage of viewport height to be additionally scrolled when user
|
|
* presses arrow up in the line of the top of the viewport.
|
|
*
|
|
* Set to 0 to let the scroll to be handled as default by Etherpad
|
|
*/
|
|
"percentageToScrollWhenUserPressesArrowUp": "${FOCUS_LINE_PERCENTAGE_ARROW_UP:0}"
|
|
},
|
|
|
|
/*
|
|
* User accounts. These accounts are used by:
|
|
* - default HTTP basic authentication if no plugin handles authentication
|
|
* - some but not all authentication plugins
|
|
* - some but not all authorization plugins
|
|
*
|
|
* User properties:
|
|
* - password: The user's password. Some authentication plugins will ignore
|
|
* this.
|
|
* - is_admin: true gives access to /admin. Defaults to false. If you do not
|
|
* uncomment this, /admin will not be available!
|
|
* - readOnly: If true, this user will not be able to create new pads or
|
|
* modify existing pads. Defaults to false.
|
|
* - canCreate: If this is true and readOnly is false, this user can create
|
|
* new pads. Defaults to true.
|
|
*
|
|
* Authentication and authorization plugins may define additional properties.
|
|
*
|
|
* WARNING: passwords should not be stored in plaintext in this file.
|
|
* If you want to mitigate this, please install ep_hash_auth and
|
|
* follow the section "secure your installation" in README.md
|
|
*/
|
|
|
|
"users": {
|
|
"admin": {
|
|
// 1) "password" can be replaced with "hash" if you install ep_hash_auth
|
|
// 2) please note that if password is null, the user will not be created
|
|
"password": "${ADMIN_PASSWORD:null}",
|
|
"is_admin": true
|
|
},
|
|
"user": {
|
|
// 1) "password" can be replaced with "hash" if you install ep_hash_auth
|
|
// 2) please note that if password is null, the user will not be created
|
|
"password": "${USER_PASSWORD:null}",
|
|
"is_admin": false
|
|
}
|
|
},
|
|
|
|
/*
|
|
* Restrict socket.io transport methods
|
|
*/
|
|
"socketTransportProtocols" : ["websocket", "polling"],
|
|
|
|
"socketIo": {
|
|
/*
|
|
* Maximum permitted client message size (in bytes). This controls the
|
|
* maximum single-message size for socket.io and directly affects large
|
|
* paste operations. All messages from clients that are larger than this
|
|
* will be rejected. Large values make it possible to paste large amounts
|
|
* of text, and plugins may require a larger value to work properly, but
|
|
* increasing the value increases susceptibility to denial of service
|
|
* attacks (malicious clients can exhaust memory).
|
|
*
|
|
* 1MB accommodates large pastes while still preventing abuse.
|
|
*/
|
|
"maxHttpBufferSize": "${SOCKETIO_MAX_HTTP_BUFFER_SIZE:1000000}"
|
|
},
|
|
|
|
/*
|
|
* Allow Load Testing tools to hit the Etherpad Instance.
|
|
*
|
|
* WARNING: this will disable security on the instance.
|
|
*/
|
|
"loadTest": "${LOAD_TEST:false}",
|
|
|
|
/**
|
|
* Disable dump of objects preventing a clean exit
|
|
*/
|
|
"dumpOnUncleanExit": "${DUMP_ON_UNCLEAN_EXIT:false}",
|
|
|
|
/*
|
|
* Disable indentation on new line when previous line ends with some special
|
|
* chars (':', '[', '(', '{')
|
|
*/
|
|
|
|
/*
|
|
"indentationOnNewLine": false,
|
|
*/
|
|
|
|
/*
|
|
* From Etherpad 1.8.3 onwards, import and export of pads is always rate
|
|
* limited.
|
|
*
|
|
* The default is to allow at most 10 requests per IP in a 90 seconds window.
|
|
* After that the import/export request is rejected.
|
|
*
|
|
* See https://github.com/nfriedly/express-rate-limit for more options
|
|
*/
|
|
"importExportRateLimiting": {
|
|
// duration of the rate limit window (milliseconds)
|
|
"windowMs": "${IMPORT_EXPORT_RATE_LIMIT_WINDOW:90000}",
|
|
|
|
// maximum number of requests per IP to allow during the rate limit window
|
|
"max": "${IMPORT_EXPORT_MAX_REQ_PER_IP:10}"
|
|
},
|
|
|
|
/*
|
|
* From Etherpad 1.8.3 onwards, the maximum allowed size for a single imported
|
|
* file is always bounded.
|
|
*
|
|
* File size is specified in bytes. Default is 50 MB.
|
|
*/
|
|
"importMaxFileSize": "${IMPORT_MAX_FILE_SIZE:52428800}", // 50 * 1024 * 1024
|
|
|
|
/*
|
|
* From Etherpad 1.8.5 onwards, when Etherpad is in production mode commits from individual users are rate limited
|
|
*
|
|
* The default is to allow at most 10 changes per IP in a 1 second window.
|
|
* After that the change is rejected.
|
|
*
|
|
* See https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#websocket-single-connection-prevent-flooding for more options
|
|
*/
|
|
"commitRateLimiting": {
|
|
// duration of the rate limit window (seconds)
|
|
"duration": "${COMMIT_RATE_LIMIT_DURATION:1}",
|
|
|
|
// maximum number of changes per IP to allow during the rate limit window
|
|
"points": "${COMMIT_RATE_LIMIT_POINTS:10}"
|
|
},
|
|
|
|
/*
|
|
* Toolbar buttons configuration.
|
|
*
|
|
* Uncomment to customize.
|
|
*/
|
|
|
|
/*
|
|
"toolbar": {
|
|
"left": [
|
|
["bold", "italic", "underline", "strikethrough"],
|
|
["orderedlist", "unorderedlist", "indent", "outdent"],
|
|
["undo", "redo"],
|
|
["clearauthorship"]
|
|
],
|
|
"right": [
|
|
["importexport", "timeslider", "savedrevision"],
|
|
["settings", "embed", "home"],
|
|
["showusers"]
|
|
],
|
|
"timeslider": [
|
|
["timeslider_export", "timeslider_returnToPad"]
|
|
]
|
|
},
|
|
*/
|
|
|
|
/*
|
|
* Expose Etherpad version in the web interface and in the Server http header.
|
|
*
|
|
* Do not enable on production machines.
|
|
*/
|
|
"exposeVersion": "${EXPOSE_VERSION:false}",
|
|
|
|
/*
|
|
* The log level we are using.
|
|
*
|
|
* Valid values: DEBUG, INFO, WARN, ERROR
|
|
*/
|
|
"loglevel": "${LOGLEVEL:INFO}",
|
|
|
|
/* Override any strings found in locale directories */
|
|
"customLocaleStrings": {},
|
|
|
|
/* Disable Admin UI tests */
|
|
"enableAdminUITests": false,
|
|
|
|
/*
|
|
* Enable/Disable case-insensitive pad names.
|
|
*/
|
|
"lowerCasePadIds": "${LOWER_CASE_PAD_IDS:false}",
|
|
"sso": {
|
|
"issuer": "${SSO_ISSUER:http://localhost:9001}",
|
|
"clients": [
|
|
{
|
|
"client_id": "${ADMIN_CLIENT:admin_client}",
|
|
"client_secret": "${ADMIN_SECRET:admin}",
|
|
"grant_types": ["authorization_code"],
|
|
"response_types": ["code"],
|
|
"redirect_uris": ["${ADMIN_REDIRECT:http://localhost:9001/admin/}"]
|
|
},
|
|
{
|
|
"client_id": "${USER_CLIENT:user_client}",
|
|
"client_secret": "${USER_SECRET:user}",
|
|
"grant_types": ["authorization_code"],
|
|
"response_types": ["code"],
|
|
"redirect_uris": ["${USER_REDIRECT:http://localhost:9001/}"]
|
|
}
|
|
]
|
|
},
|
|
|
|
/* Set the time to live for the tokens
|
|
This is the time of seconds a user is logged into Etherpad
|
|
"ttl": {
|
|
"AccessToken": 3600,
|
|
"AuthorizationCode": 600,
|
|
"ClientCredentials": 3600,
|
|
"IdToken": 3600,
|
|
"RefreshToken": 86400
|
|
}
|
|
*/
|
|
}
|