[logger] # Whether the logger is overall enabled or not. # Passing "-q" completely silences all logging. enable = true # The log level to emit at. # # Possible values: # - "error" # - "warning" # - "info" # - "debug" # - "trace" level = "info" [server] # The IP and port to bind to when the server starts. address = "[::]:2747" # The path to write the pid file. # If excluded or empty, then no pid file is written. pid-file = "" [database] # Whether to run migrations on startup (if needed). # # If false, then an out-of-date database will yield errors, # you must migrate manually. run-migrations = true # Whether to run the seeder on startup (if needed). # # If false, then an empty database may yield errors, # you must seed manually. run-seeder = true # The path containing data files for the seeder. # Corresponds to /deepwell/seeder in the repository. seeder-path = "seeder" [security] # The time to sleep in between failed authentication requests. # # If a request successfully authenticates then it is responded to # without added delay. But if the request fails to authenticate, # then this amount of delay (in milliseconds) is slept before # returning the "authentication failed" response. # # This helps prevent brute-forcing by making repeatedly guessing invalid # passwords slow, as opposed to legitimate users who only occasionally # mistype their password and for whom this delay is not a significant issue. # # See https://unix.stackexchange.com/a/2127 authentication-fail-delay-ms = 100 [security.session] # All session tokens are prefixed with this string. # It makes a session token immediately recognizable # as it is otherwise a long random string. token-prefix = "wj:" # How long session tokens should be. # # Tokens are generated using rand::distributions::Alphanumeric, # meaning they are cryptographically secure strings composed of # ASCII characters A-Z, a-z, and 0-9. # # This starts counting at random bytes. # No matter how long your prefix is (see above), # the random portion of the session token will be this long. # This means the *actual* length of a token is length(token_prefix) + token_length. token-length = 64 # How long, in minutes, a user session token lasts. # # This is for the internal session token, which is automatically refreshed # by framerail when it sees the token is close to expiry. duration-session-minutes = 30 # How long, in minutes, a user has to enter their MFA code after initial login. # # When logging in with MFA, the user is given a "restricted session token". # This session token is only useful for logging in with MFA (at which point they # are given a regular session token), and is useless for anything else. # # This field determines how long such session tokens should last before expiry. duration-login-minutes = 5 [security.mfa] # The number of recovery codes to have available at any given time. # # After MFA setup, this number of recovery codes are generated for the user. # If they ever use a code, it is exhausted (single-use), and on refresh any # remaining recovery codes are invalidated and this number of new recovery # codes are generated. recovery-code-count = 12 # The length in bytes for each recovery code. # # It is suggested to make this value even, as a dash is inserted in the # middle of each recovery code to make it easier to read. recovery-code-length = 8 # The amount of time that each TOTP should last. # # We use 30 seconds because this is standard with helpers # such as Google Authenticator and Authy. # # It balances between giving the user enough time to enter a code, # but short enough to make bruteforcing values impractical. time-step = 30 # The allowed leniency value to account for clock skew. # # This represents the number of seconds (positive or negative) # that a TOTP is offset by in determining whether the authentication # was accepted. # # See https://github.com/TimDumol/rust-otp/blob/master/src/lib.rs#L56 time-skew = 1 [job] # How many job workers are running in one instance of the DEEPWELL server. # Each worker runs in parallel, taking items from the job queue and # processing them. # # This value must be at least 1. workers = 2 # How many retries to do on a failed job before deleting it regardless of outcome. # # This way perpetually-failing jobs eventually make their way out of the system. # Setting to 0 means jobs are not retried at all, being deleted after the first # job execution. max-attempts = 3 # How long, in milliseconds, to sleep in between jobs. # # The intent is to avoid overloading the database by allowing a # short sleep period in between background tasks. # # See the JobService (src/service/job/service.rs) for information # on the job queue and main loop. delay-ms = 5 # How long, in seconds, the sleep time for when there are no jobs. # # When there is a job, then the 'delay-ms' time is slept after the job # is complete. However, if there are no jobs on the queue, then checking # again that second is not useful. # # So instead, we use exponential backoff. We start with the minimum delay, # then for each next attempt which yields no pending jobs, we double the # wait time, up to the maximum delay. # # Then, if at any point the queue is not empty and a job is pulled, this # delay resets to the minimum again. min-delay-poll-secs = 10 # 10 seconds max-delay-poll-secs = 360 # 6 minutes # The period, in seconds, to prune all expired sessions. # # This is *not* needed to actually invalidate sessions, so # setting this to a long period is not a security risk. # It is merely for clearing the database of already-expired tokens. prune-session-secs = 3600 # 1 hour # The period, in seconds, to prune all unused text rows. # # The text table deduplicates identical text objects, and # their hashes are instead what is referenced from page revisions # etc. # # While revisions are only appended to and not deleted, it is # however possible for text rows to become orphaned and unused. # For instance, this can occur when previewing or rerendering pages. # # This job runs periodically to delete unused text rows from the database # to avoid clutter. However because this does not occur regularly, and # the cleanup query is slow, the job should be run infrequently. prune-text-secs = 86400 # 1 day # Users can change their name, but because it creates a permanent redirect there, # they are limited in how often they can rename. # # This describes how often users are checked to see if they can get a new name # change token added to their account. It does not affect how often they get # new tokens or how many they can have. # # See the "user" section of those configuration below for more information. name-change-refill-secs = 86400 # 1 day # Some punishments are temporary, and meant to expire after some time. # Currently this is only bans. # # This job runs periodically to check for any such expired punishments, # and if they exist, they are automatically lifted. # # This field does not affect the duration of such punishments, only the # frequency of which they are checked for expiration. lift-expired-punishments-secs = 86400 # 1 day [domain] # The main domain for this instance, where it's considered to be # hosted from. The canonical domain for sites will be "site.[this-domain]". # # Example values: # - wikijump.com (production) # - wikijump.dev (development / staging) # - wikijump.localhost (local) main = "wikijump.com" # The domain used by this instance to serve user-uploaded files # and other potentially-insecure data. files = "wjfiles.com" [locale] # The path containing Fluent translation files. # Corresponds to /locales in the repository. path = "../locales" [ftml] # How long (in milliseconds) to allow a render job to run before terminating it. # # This is to ensure that a parser bug or malicious input cannot # crash or freeze the backend. This value should not be too # aggressive, but still not extremely long. render-timeout-ms = 2000 # Under what conditions a rerender job should be skipped rather than processed. # # This exists to cut off some rare cases where a page update job results in further # updates, which leads to other updates, etc, in such a way that it is either an # infinite loop, or updating excessively many pages. # # This works like a filter-matching system, where the first matching condition causes # the rerendering to be skipped. [[ftml.rerender-skip]] # If a page was rerendered in the last 100 milliseconds, and this isn't a top-level job. job-depth = 1 last-update-ms = 100 [[ftml.rerender-skip]] # If a page was rerendered in the last 1.5 seconds, and it's a fairly deep rerender, may # be a possible loop. job-depth = 10 last-update-ms = 1500 [[ftml.rerender-skip]] # Disallow rerendering depths of more than 50, no matter what. # (0 disables the timestamp check) job-depth = 50 last-update-ms = 0 # Alternate, more compact representation of the above: # rerender-skip = [ # { job-depth = 1, last-update-ms = 100 }, # { job-depth = 10, last-update-ms = 1500 }, # { job-depth = 50, last-update-ms = 0 }, # ] [special-pages] # List of special pages, by slug. # These are used as templates in certain cases. # Any pages whose slug begin with this prefix are # treated as "special". # # This means that regular users cannot create these pages, # and that normal template processing does not apply # (to avoid infinite regress and other issues). special-prefix = "_" # This is included in all pages within this category, # or for _default, all pages in all categories without # a more specific _template page. # # Fallback is the fixed string "%%content%%" template = "_template" # When a page has not yet been created. # Fallback string is localized as "wiki-page-missing" missing = "_404" # When a user lacks permissions to see a page. # Fallback string is localized as "wiki-page-private" private = "_public" # When a user is banned from the site. # This is only shown if the site disallows banned users from # being able to see pages. # # Fallback string is localized as "wiki-page-banned" banned = "_ban" [user] # The number of name changes a user has by default. default-name-changes = 2 # The maximum number of name changes a user has. # # Attempting to add additional name change tokens to # a user will top out at this amount. maximum-name-changes = 3 # The minimum length for a user's name in bytes. # A user who attempts to register must have a slug which is at least this long. # # The intent is to prevent the proliferation of very short, unidentifiable usernames # such as single Latin letters (e.g. "N"). However, we check *bytes* specifically to # avoid Anglo-centricism, as many full names in other languages fit within two letters # (consider CJK for instance). Single characters outside of the main ASCII block # usually take up two or three bytes themselves, making it a non-issue for those languages. # # See WJ-1122. minimum-name-bytes = 3 # Every this many days, all users get another name change token (up to the cap). # See the "job" section above to configure how often this is checked. # # Set to 0 to disable. refill-name-change-days = 90 [message] # The maximum size of a message's subject line, in bytes. maximum-subject-bytes = 128 # The maximum size of a message wikitext, in bytes. maximum-body-bytes = 200000 # The maximum number of recipients allowed in one message. # This refers to the sum of direct recipients, CC, and BCC targets. maximum-recipients = 6