{ "$id": "configuration", "title": "Configuration", "description": "Configuration for Kemono.", "type": "object", "additionalProperties": false, "required": ["site", "development_mode", "automatic_migrations", "webserver"], "properties": { "site": { "description": "Deprecated in favour of `#/webserver/site`.", "$comment": "`$deprecated` keyword was in introduced in draft `2019-09`, so just using `description` field instead.", "type": "string" }, "favicon": { "description": "favicon.ico file path.", "type": "string" }, "development_mode": { "type": "boolean" }, "automatic_migrations": { "type": "boolean" }, "sentry_dsn": { "type": "string" }, "sentry_dsn_js": { "type": "string" }, "open_telemetry_endpoint": { "type": "null" }, "ban_url": { "description": "Kemono3 `BAN` URL prefix for cache purging.", "anyOf": [ { "type": "string" }, { "type": "array", "items": { "type": "string" } } ] }, "enable_notifications": { "type": "boolean" }, "cache_ttl_for_recent_posts": { "type": "integer" }, "webserver": { "$ref": "#/definitions/webserver" }, "database": { "$ref": "#/definitions/database" }, "redis": { "$ref": "#/definitions/redis" }, "archive_server": { "$ref": "#/definitions/archive-server" }, "filehaus": { "$ref": "#/definitions/filehaus" } }, "definitions": { "webserver": { "description": "Configuration for the frontend server.", "type": "object", "additionalProperties": false, "required": ["secret", "ui"], "properties": { "secret": { "description": "Secret key used to encrypt sessions.", "type": "string" }, "workers": { "description": "Amount of workers to run at once.", "type": "integer" }, "harakiri": { "$comment": "This one isn't used by server code.", "type": "integer" }, "threads": { "description": "Amount of thread to run at once.", "type": "integer" }, "ip_security": { "description": "If you've dealt with how the trust of forwarding IPs works upstream, flip this off.", "type": "boolean" }, "country_header_key": { "description": "Header for user country iso, generater by DDOS-GUARD.", "anyOf": [{ "type": "string" }, { "const": "DDG-Connecting-Country" }] }, "uwsgi_options": { "$ref": "#/definitions/uwsgi-options" }, "logging": { "description": "Logging mode.", "enum": ["DEBUG", "ERROR"] }, "site": { "description": "The URL at which the site is publicly accessible.", "type": "string" }, "static_folder": { "description": "The location of the resources that will be served.", "type": "string" }, "template_folder": { "type": "string" }, "jinja_bytecode_cache_path": { "type": "null" }, "max_full_text_search_input_len": { "type": "integer" }, "table_sample_bernoulli_sample_size": { "type": "number" }, "extra_pages_to_load_on_posts": { "type": "integer" }, "pages_in_popular": { "type": "integer" }, "earliest_date_for_popular": { "type": "string" }, "use_redis_by_lock_default_on_queries": { "type": "boolean" }, "api": { "type": "object", "additionalProperties": false, "properties": { "creators_location": { "type": "string" } } }, "base_url": { "type": "string" }, "port": { "description": "The port the site will be served on.", "type": "integer" }, "ui": { "$ref": "#/definitions/ui" } } }, "ui": { "description": "Interface preferences and customization options.", "type": "object", "additionalProperties": false, "required": ["home", "config"], "properties": { "home": { "$ref": "#/definitions/ui-home" }, "config": { "$ref": "#/definitions/ui-config" }, "fileservers": { "type": "array", "items": { "type": "array", "minItems": 2, "maxItems": 2, "items": [ { "type": "string" }, { "anyOf": [{ "type": "integer" }, { "type": "string" }] } ] } }, "sidebar": { "type": "object", "additionalProperties": false, "properties": { "disable_filehaus": { "type": "boolean" }, "disable_faq": { "type": "boolean" }, "disable_dms": { "type": "boolean" } } }, "sidebar_items": { "description": "Add custom links to the bottom of the sidebar.", "type": "array", "items": { "type": "object", "additionalProperties": false, "required": ["text"], "properties": { "header": { "type": "boolean" }, "text": { "type": "string" }, "class_name": { "type": "string" }, "link": { "type": "string" }, "is_external": { "type": "boolean" }, "color": { "type": "string" } } } }, "footer_items": { "description": "Add custom HTML elements to the footer.", "type": "array", "items": { "type": "string" } }, "banner": { "description": "Banner HTML. Each entry should be Base64-encoded.", "type": "object", "additionalProperties": false, "properties": { "global": { "description": "B64-encoded html fragment.", "type": "string" }, "announcement_global": { "description": "B64-encoded html fragment.", "type": "string" }, "welcome": { "description": "B64-encoded html fragment.", "type": "string" } } }, "ads": { "$ref": "#/definitions/ui-ads" }, "matomo": { "$ref": "#/definitions/matomo" }, "video_extensions": { "description": "File extensions recognized as (browser-friendly) video. Will automatically be embedded in post pages.", "type": "array", "uniqueItems": true, "items": { "enum": [".mp4", ".webm", ".m4v", ".3gp", ".mov"] } }, "files_url_prepend": { "type": "object", "additionalProperties": false, "properties": { "icons_base_url": { "type": "string" }, "banners_base_url": { "type": "string" }, "thumbnails_base_url": { "type": "string" } } } } }, "ui-home": { "type": "object", "additionalProperties": false, "properties": { "site_name": { "type": "string" }, "welcome_credits": { "description": "B64-encoded html fragment.", "type": "string" }, "home_background_image": { "description": "A path to background image on server.", "type": "string" }, "logo_path": { "type": "string" }, "mascot_path": { "type": "string" }, "announcements": { "type": "array", "items": { "type": "object", "additionalProperties": false, "properties": { "title": { "type": "string" }, "date": { "type": "string" }, "content": { "type": "string" } } } } } }, "ui-config": { "type": "object", "additionalProperties": false, "required": ["paysite_list"], "properties": { "paysite_list": { "type": "array", "uniqueItems": true, "items": { "enum": [ "patreon", "fanbox", "afdian", "discord", "fantia", "boosty", "gumroad", "subscribestar", "dlsite", "candfans", "fansly", "onlyfans" ] } }, "artists_or_creators": { "type": "string" } } }, "ui-ads": { "description": "Ads preferences. Each spot should be Base64-encoded.", "type": "object", "additionalProperties": false, "properties": { "header": { "description": "Base64-encoded html fragment.", "type": "string" }, "middle": { "description": "Base64-encoded html fragment.", "type": "string" }, "footer": { "description": "Base64-encoded html fragment.", "type": "string" }, "slider": { "description": "Base64-encoded html fragment.", "type": "string" }, "video": { "description": "Base64-encoded JSON list of objects.\nSee https://docs.fluidplayer.com/docs/configuration/ads/#adlist .", "type": "string" } } }, "matomo": { "description": "Matomo preferences.", "type": "object", "additionalProperties": false, "properties": { "enabled": { "type": "boolean" }, "tracking_domain": { "type": "string" }, "tracking_code": { "type": "string" }, "site_id": { "type": "integer" }, "plain_code": { "description": "Base64-encoded html fragment.", "type": "string" } } }, "database": { "description": "Database configuration.", "type": "object", "additionalProperties": false, "required": ["host", "user", "password", "database"], "properties": { "host": { "type": "string" }, "port": { "type": "integer" }, "user": { "type": "string" }, "password": { "type": "string" }, "database": { "type": "string" }, "application_name": { "type": "string" } } }, "redis": { "type": "object", "additionalProperties": false, "required": ["defaults"], "properties": { "defaults": { "$ref": "#/definitions/redis-defaults" }, "compression": { "type": "string" }, "default_ttl": { "type": "string" }, "node_options": { "type": "object", "additionalProperties": false, "properties": { "host": { "type": "string" }, "port": { "type": "integer" }, "db": { "type": "integer" }, "password": { "type": "string" } } }, "nodes": { "anyOf": [ { "type": "object", "additionalProperties": { "type": "string" } }, { "type": "array", "items": { "type": "object", "additionalProperties": false, "properties": { "port": { "type": "integer" }, "db": { "type": "integer" } } } } ] }, "keyspaces": { "type": "object", "propertyNames": { "$ref": "#/definitions/redis-keyspaces" }, "additionalProperties": { "type": "integer" } } } }, "redis-defaults": { "type": "object", "additionalProperties": false, "required": ["host"], "properties": { "host": { "type": "string" }, "password": { "type": "string" }, "port": { "type": "integer" }, "db": { "type": "integer" } } }, "redis-keyspaces": { "enum": [ "account", "saved_key_import_ids", "saved_keys", "random_artist_keys", "top_artists", "artists_by_update_time", "artists_faved", "artists_faved_count", "artists_recently_faved_count", "top_artists_recently", "non_discord_artist_keys", "non_discord_artists", "artists_by_service", "artist", "artist_post_count", "artist_post_offset", "artist_last_updated", "artist_favorited", "dms", "all_dms", "all_dms_count", "all_dms_by_query", "all_dms_by_query_count", "dms_count", "unapproved_dms", "favorite_artists", "favorite_posts", "notifications_for_account", "random_post_keys", "post", "next_post", "previous_post", "posts_incomplete_rewards", "post_favorited", "posts_by_artist", "posts_by_artists", "posts_by_favorited_artists", "comments", "artist_posts_offset", "is_post_flagged", "importer_logs", "ratelimit", "all_posts", "all_post_keys", "all_shares", "all_shares_count", "all_posts_for_query", "global_post_count", "global_post_count_for_query", "lock", "lock-signal", "imports", "share_files", "account_notifications", "new_notifications", "share", "artist_shares", "post_revisions", "post_revision", "files", "post_by_id", "fancards", "announcements", "announcement_count", "artist_share_count", "discord_channels_for_server", "discord_posts", "popular_posts", "tagged_posts", "tags", "file", "archive_files", "linked_accounts", "running_imports", "importer_configuration" ] }, "archive-server": { "type": "object", "additionalProperties": false, "properties": { "enabled": { "type": "boolean" }, "api_url": { "type": "string" }, "serve_files": { "type": "boolean" }, "file_serving_enabled": { "type": "boolean" } } }, "filehaus": { "description": "Filehaus configuration.", "type": "object", "additionalProperties": false, "properties": { "requires_account": { "description": "If true, an account will be required for uploading.", "type": "boolean" }, "required_roles": { "description": "Required account roles for uploading. If set to an empty list, no permissions will be required.", "type": "array", "uniqueItems": true, "items": { "enum": ["administrator", "moderator", "uploader"] } }, "tus": { "description": "`tusd` configuration.", "type": "object", "additionalProperties": false, "properties": { "manage": { "description": "Automatically manage `tusd` on port 1080. If you intend to store uploads on a different server from Kemono3, set a custom URL instead...", "type": "boolean" }, "url": { "description": "...right here. Note that if you do not allow automatic management and did not set a custom URL, uploads will be blackholed to a demo instance and Filehaus sharing will not function correctly.\nDo note that using `tusd` instances to enable Filehaus functionality requires the `post-create` hook to be pointed at Kemono's `/shares/tus` endpoint.\n`tusd --hooks-enabled-events post-create -hooks-http \"http://127.0.0.1:6942/shares/tus\" -upload-dir=./data`", "type": "string" } } } } }, "uwsgi-options": { "description": "Set additional uWSGI options if you want. Overrides any of the other options.", "type": "object", "additionalProperties": false, "properties": { "cheaper-algo": { "enum": ["busyness"] }, "cheaper": { "type": "integer" }, "cheaper-initial": { "type": "integer" }, "cheaper-overload": { "type": "integer" }, "cheaper-step": { "type": "integer" }, "cheaper-busyness-multiplier": { "type": "integer" }, "cheaper-busyness-min": { "type": "integer" }, "cheaper-busyness-max": { "type": "integer" }, "cheaper-busyness-backlog-alert": { "type": "integer" }, "cheaper-busyness-backlog-step": { "type": "integer" }, "disable-logging": { "type": "boolean" } } } } }