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:
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:
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 asname-1.ext,name-2.ext...replace: overwriteerror: fail with409 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,srcand similar links tojavascript:,vbscript:ordata: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/"
}
}
}