Skip to content

Configuration Reference

Format

The configuration is a JSON object with camelCase keys. Defaults live in code; a configuration file only lists what differs from them. See Installation for where it is read from.

{
  "debug": false,
  "allowCrossOrigin": true,
  "allowedOrigins": ["https://app.example.com"],
  "maxUploadFileSize": "20mb",
  "sources": {
    "uploads": {
      "title": "Uploads",
      "root": "/var/www/uploads",
      "baseurl": "https://cdn.example.com/uploads/"
    }
  }
}

Merging rules: nested objects (pdf, dynamicSourcesCache) are merged key by key, lists replace the default list, null keeps the default, and sources replaces the default source as a whole. Unknown keys and invalid values stop the start with a ConfigError.

In Python the validated settings are AppConfig attributes in snake_case (config.max_upload_file_size).

General

debug

boolean · default true

Log failed requests with tracebacks to the jcpy logger. Set false in production to log less; answers are the same either way.

errorHttpStatus

boolean · default true

Send an action's error with its HTTP status (400, 403, 404...). With false every error envelope of an action is sent with 200, as the PHP connector does; success: false and data.code still tell the error apart:

{"success": false, "data": {"code": 403, "messages": ["File type is not in white list"]}}

Jodit accepts only 200, 201 and 202 (successStatuses): on any other status its Ajax rejects with the HTTP reason phrase (HTTP/1.1), so the Uploader and the FileBrowser show "Forbidden" or "Not Found" instead of the connector's message. Set false when Jodit talks to the connector. /ping, CORS preflights and file contents are not affected.

title

string · default ""

Not used (kept for configuration compatibility).

defaultFilesKey

string · default "default"

Form field that holds an uploaded file besides files[0], files[1]... Used by fileUpload and imageSave.

Sources

sources

object · default: one source named default

File locations shown by the browser, keyed by name. Without sources the default source is built from SOURCE_NAME, SOURCE_ROOT and SOURCE_BASEURL (details).

{
  "sources": {
    "uploads": {
      "title": "User Uploads",
      "root": "/var/www/uploads",
      "baseurl": "https://cdn.example.com/uploads/"
    },
    "media": {
      "title": "Media",
      "baseurl": "https://my-bucket.s3.amazonaws.com/media/",
      "storageAdapter": "s3",
      "s3": {"bucket": "my-bucket", "region": "eu-central-1", "prefix": "media"}
    }
  }
}

Source settings:

Key Type Meaning
name string Name used in requests (source=...); defaults to the key
title string Required. Name shown in the browser
baseurl string Required. Public URL of the source root, absolute (https://cdn.example.com/uploads/) or from the site root (/uploads/); file links and thumbnails are built from it
root string Directory of the source; required for local storage, a virtual prefix for other adapters
defaultFilesKey string Overrides the global defaultFilesKey
storageAdapter string local (default), s3, azure, gcs, ftp, sftp, webdav or a registered name
s3 object Options of the s3 adapter, required with it (AWS S3)
azure object Options of the azure adapter, required with it (Azure Blob)
gcs object Options of the gcs adapter, required with it (Google Cloud Storage)
ftp object Options of the ftp adapter, required with it (FTP & SFTP)
sftp object Options of the sftp adapter, required with it (FTP & SFTP)
webdav object Options of the webdav adapter, required with it (WebDAV)
any global setting Per-source override

The connector does not serve the files: baseurl must point to a web server or a CDN that does.

A baseurl from the site root (/uploads/) is resolved by the browser against the page with the editor, so the same configuration works on every host the site is opened on (localhost, 127.0.0.1, a staging domain). The editor then inserts root-relative links (/uploads/a.png) into the content, and getLocalFileByUrl accepts them. Protocol-relative values (//cdn.example.com/uploads/) are refused: use the absolute URL.

dynamicSourcesCache

object · default {"max": 200, "ttlMs": 60000}

How many tenants resolved by resolve_sources are kept (least recently used first out) and for how long.

root, baseurl

string

Not used: sources carry their own root and baseurl.

sourceClassName

string · default "FileSystem"

Not used; the storage is chosen with storageAdapter.

File handling

extensions

string[] · default: common image, document, archive and media extensions

Allowed file extensions (lower case, without the dot). Uploads of other types get 403, and listings leave such files out.

Default list `jpg png gif jpeg bmp ico jpeg psd svg ttf tif ai txt css ini xml zip rar 7z gz tar pps ppt pptx odp xls xlsx csv doc docx pdf rtf avi flv 3gp mov mkv mp4 wmv webp`

Pages, scripts and SVG

Pages and scripts (html, htm, js) are not in the default list: if baseurl is served from your site's domain, uploaded pages and scripts run there (stored XSS). Add them to extensions only for sources where editors are trusted.

Uploaded SVG images are cleaned of scripts (see sanitizeSvg); xml files are stored as they are. The safest setup still serves baseurl from a separate domain (files.example.com, not example.com/uploads), so nothing uploaded runs with your site's cookies. Otherwise list only the types you need, e.g. images and documents:

{"extensions": ["jpg", "jpeg", "png", "gif", "webp", "pdf", "docx", "xlsx"]}

The same list governs names saved by imageSave. Make sure the file host never executes uploaded files (no PHP or CGI under baseurl).

maxUploadFileSize

string · default "8mb"

Largest accepted upload, as a number with a unit (b, kb, mb, gb...; case-insensitive) or plain bytes. Also caps fileUploadRemote downloads, which stop as soon as they exceed it.

maxFileSize

string · default "8mb"

Largest remote resource (image, stylesheet, font) loaded while generating PDF and DOCX.

saveSameFileNameStrategy

string · default "addNumber"

What an upload does when the name is taken:

  • addNumber: store as name-1.ext, name-2.ext...
  • replace: overwrite
  • error: fail with 409 File ... already exists

A client overrides it for one upload with the onExists parameter of fileUpload, so this setting is a default rather than a limit: to keep clients from overwriting files, deny FILE_REMOVE in the access rules. FILE_REMOVE is checked only for replace asked by the client; replace set here needs only FILE_UPLOAD.

datetimeFormat

string · default "M/D/YYYY h:mm:ss A"

Format of changed in listings, with Day.js tokens (YYYY, MM, DD, HH, mm, ss, A...), in the server's local time.

defaultSortBy

string · default "changed-desc"

Listing order when the request has no mods[sortBy]: name-asc, name-desc, changed-asc, changed-desc, size-asc, size-desc.

countInChunk

integer · default 1000000

Listing page size when the request has no mods[limit].

excludeDirectoryNames

string[] · default [".tmb", ".quarantine"]

Names hidden from listings, folders and files alike (the thumbnail folder is also hidden while thumbnails are on).

defaultPermission

integer · default 0o775 (509)

Not used: folders are created with the process umask.

allowReplaceSourceFile

boolean · default true

Not used.

Images

imageExtensions

string[] · default ["jpg", "png", "gif", "jpeg", "bmp", "svg", "ico", "webp"]

Extensions treated as images: listed with isImage: true and given real thumbnails.

quality

integer · default 90

JPEG and WebP quality of thumbnails.

maxImageWidth, maxImageHeight

integer · default 1900

Not enforced (kept for configuration compatibility).

Thumbnails

createThumb

boolean · default true

Create thumbnails while listing. Image thumbnails fit into a thumbSize square (never enlarged) and keep PNG, GIF and WebP formats; other formats become JPEG. SVG images are their own thumbnails.

thumbSize

integer · default 250

Side of the thumbnail square, in pixels.

thumbFolderName

string · default "_thumbs"

Folder, inside each listed folder, where thumbnails are stored.

safeThumbsCountInOneTime

integer · default 20

How many new thumbnails one listing may create. Items after that come without thumb and get one on a later listing, so a large folder does not make one request slow.

SVG icons

Folders and non-image files get SVG icons, drawn by the svg_generator argument of create_app() (a colored page with the extension by default).

Key Type · default Meaning
generateSvgThumbs boolean · true Draw icons; when false such items point to the file itself
svgThumbWidth integer · 100 Width passed to the generator
svgThumbHeight integer · 100 Height passed to the generator

A generator takes the entry (StatEntry with path, is_file, is_directory, size), the width and the height, and returns SVG markup. Escape names you put into the markup:

def colored_icon(entry: StatEntry, width: int, height: int) -> str:
    """Render a tile colored by file type with the extension and name.

    Args:
        entry: Folder or file the icon stands for.
        width: Icon width in pixels.
        height: Icon height in pixels.

    Returns:
        SVG document.
    """
    path = PurePosixPath(entry.path)
    ext = path.suffix.lower()
    color = "#2ecc71" if entry.is_directory else COLORS.get(ext, "#7f8c8d")
    label = "DIR" if entry.is_directory else ext.removeprefix(".").upper()
    name = path.name
    if len(name) > MAX_NAME:
        name = f"{name[:MAX_NAME]}..."
    # File names are user input: escape them inside the markup.
    return (
        f'<svg width="{width}" height="{height}" viewBox="0 0 100 100" '
        'xmlns="http://www.w3.org/2000/svg">'
        f'<rect width="100" height="100" fill="{color}" rx="8"/>'
        '<text x="50" y="40" text-anchor="middle" fill="white" '
        'font-family="Arial" font-size="20" font-weight="bold">'
        f"{escape(label)}</text>"
        '<text x="50" y="70" text-anchor="middle" fill="white" '
        'font-family="Arial" font-size="10" opacity="0.8">'
        f"{escape(name)}</text></svg>"
    )


def build_app() -> FastAPI:
    """Build the application.

    Returns:
        Connector application with the custom icon generator.
    """
    return create_app(CONFIG, svg_generator=colored_icon)

The generator is an argument, not a setting, so it is the same for every source of an instance.

Access and security

accessControl

rule[] · default []

Access rules; see Access Control. Rules computed in code or loaded at runtime are passed as access_control= instead.

defaultRole

string · default "guest"

Role of every request when there is no check_authentication callback. See Authentication.

roleSessionVar

string · default "JoditUserRole"

Not used: roles come from check_authentication.

allowCrossOrigin

boolean · default false

Answer cross-origin requests with CORS headers (Access-Control-Allow-Origin echoing the origin, Access-Control-Allow-Credentials: true) and handle OPTIONS preflights.

allowedOrigins

string[] | null · default null

Origins accepted when allowCrossOrigin is on; null accepts every origin. Requests from other origins get no CORS headers and their preflights get 403. A function deciding per request is passed as allowed_origins= to create_app().

onlyPOST

boolean · default false

Reject every GET with 405, /ping included. Links, images and scripts on other sites can only send GET, so this blocks cross-site triggering of actions when cookies authenticate requests. Configure Jodit to use POST then:

Jodit.make('#editor', {
  uploader: { url: '/connector/?action=fileUpload' },
  filebrowser: { ajax: { url: '/connector/', method: 'POST' } }
});

sanitizeSvg

boolean · default true

Remove active content from .svg files saved by fileUpload, fileUploadRemote and imageSave, before they are stored. An SVG opened directly runs its scripts on the domain that serves it, so these are dropped:

  • <script>, <foreignObject>, <iframe>, <embed>, <object>, <handler> and every element in the XHTML namespace;
  • event attributes (onload, onclick...);
  • href, src and similar links to javascript:, vbscript: or data: URLs other than PNG, JPEG, GIF and WebP images;
  • animations (<set>, <animate>...) that change a link or an event attribute, or set such a URL;
  • processing instructions (such as <?xml-stylesheet?>), comments and the DOCTYPE.

Shapes, gradients, text, <style>, <use> and editor metadata (Inkscape, Illustrator) are kept. The file is parsed without entities and external references: a file that declares entities, is not well-formed XML or whose root is not <svg> is refused with 400 File is not a valid SVG image before anything of the upload is written.

Turn it off only when every uploader is trusted and SVG files must stay byte for byte. Like other settings it can be set per source.

allowPrivateNetworkUploads

boolean · default false

Let fileUploadRemote fetch from private and local addresses. Keep it off unless the connector runs in a trusted network and must download from internal hosts.

Limits

timeoutLimit

integer · default 60

Network timeout, in seconds, of fileUploadRemote downloads and of remote resources in PDF/DOCX generation.

memoryLimit

string · default "256M"

Not used.

Documents

pdf

object

Key Default Meaning
isRemoteEnabled true Load remote images, styles and fonts (public http/https only) in PDF and DOCX; false blocks all of them
defaultFont "serif" Not used
fontDir, fontCache, tempDir, chroot temp dir Not used
paper {"format": "A4", "page_orientation": "portrait"} Not used: the page comes from options[...] of generatePdf

See Documents.

Per-source overrides

A source may set any global setting except sources; the value applies to that source only.

{
  "extensions": ["txt", "pdf", "doc", "docx"],
  "maxUploadFileSize": "10mb",
  "thumbSize": 250,
  "sources": {
    "images": {
      "title": "Images",
      "root": "/var/www/images",
      "baseurl": "https://cdn.example.com/images/",
      "extensions": ["jpg", "jpeg", "png", "gif", "webp"],
      "maxUploadFileSize": "5mb",
      "thumbSize": 150
    },
    "videos": {
      "title": "Videos",
      "root": "/var/www/videos",
      "baseurl": "https://cdn.example.com/videos/",
      "extensions": ["mp4", "webm", "mov"],
      "maxUploadFileSize": "500mb",
      "createThumb": false
    },
    "temp": {
      "title": "Temporary",
      "root": "/var/www/temp",
      "baseurl": "https://cdn.example.com/temp/",
      "saveSameFileNameStrategy": "replace",
      "datetimeFormat": "DD.MM.YYYY HH:mm"
    }
  }
}

Overrides are validated like global settings; an invalid one stops the start with the source name in the message. Settings that act before a source is known (onlyPOST, errorHttpStatus, CORS, accessControl, defaultRole) are read from the global level only.

Examples

Minimal

{
  "sources": {
    "default": {
      "title": "Files",
      "root": "/var/www/files",
      "baseurl": "https://example.com/files/"
    }
  }
}

Production

{
  "debug": false,
  "allowCrossOrigin": true,
  "allowedOrigins": ["https://app.example.com"],
  "onlyPOST": true,
  "maxUploadFileSize": "10mb",
  "safeThumbsCountInOneTime": 10,
  "defaultRole": "guest",
  "accessControl": [
    { "role": "guest", "FILE_UPLOAD": false, "FILE_UPLOAD_REMOTE": false,
      "FILE_REMOVE": false, "FILE_MOVE": false, "FILE_RENAME": false,
      "FOLDER_CREATE": false, "FOLDER_REMOVE": false, "FOLDER_MOVE": false,
      "FOLDER_RENAME": false, "IMAGE_RESIZE": false, "IMAGE_CROP": false,
      "IMAGE_SAVE": false },
    { "role": "user", "FILE_UPLOAD": true, "IMAGE_SAVE": true }
  ],
  "sources": {
    "uploads": {
      "title": "Uploads",
      "root": "/var/www/uploads",
      "baseurl": "https://cdn.example.com/uploads/"
    }
  }
}

Fast listings

{
  "debug": false,
  "createThumb": false,
  "countInChunk": 100,
  "excludeDirectoryNames": [".git", "node_modules", ".tmb", ".quarantine"],
  "sources": {
    "archive": {
      "title": "Archive",
      "root": "/srv/archive",
      "baseurl": "https://archive.example.com/"
    }
  }
}