Security & Limits
Environment variables are configurable for Directus Enterprise Cloud projects via our Customer Success team. You can also set environment variables in self-hosted projects.
| Variable | Description | Default Value | 
|---|---|---|
| SECRET1 | Secret string for the project. Used for secret signing. | Random value | 
| ACCESS_TOKEN_TTL | The duration that an access token is valid. | 15m | 
| EMAIL_VERIFICATION_TOKEN_TTL | The duration that an email verification token is valid. | 7d | 
| REFRESH_TOKEN_TTL | The duration that a refresh token is valid. This value should be higher than ACCESS_TOKEN_TTLandSESSION_COOKIE_TTL. | 7d | 
| REFRESH_TOKEN_COOKIE_DOMAIN | Which domain to use for the refresh token cookie. Useful for development mode. | |
| REFRESH_TOKEN_COOKIE_SECURE | Whether or not to set the secureattribute for the refresh token cookie. | false | 
| REFRESH_TOKEN_COOKIE_SAME_SITE | Value for sameSitein the refresh token cookie. | lax | 
| REFRESH_TOKEN_COOKIE_NAME | Name of the refresh token cookie. | directus_refresh_token | 
| SESSION_COOKIE_TTL | The duration that the session cookie/token is valid, and also how long users stay logged-in to the App. | 1d | 
| SESSION_COOKIE_DOMAIN | Which domain to use for the session cookie. Useful for development mode. | |
| SESSION_COOKIE_SECURE | Whether or not to set the secureattribute for the session cookie. | false | 
| SESSION_COOKIE_SAME_SITE | Value for sameSitein the session cookie. | lax | 
| SESSION_COOKIE_NAME | Name of the session cookie. | directus_session_token | 
| SESSION_REFRESH_GRACE_PERIOD | The duration during which a refresh request will permit recently refreshed sessions to be used, thereby preventing race conditions in refresh calls. | 10s | 
| LOGIN_STALL_TIME | The duration in milliseconds that a login request will be stalled for, and it should be greater than the time taken for a login request with an invalid password. | 500 | 
| REGISTER_STALL_TIME | The duration in milliseconds that a registration request will be stalled for, and it should be greater than the time taken for a registration request with an already registered email. | 750 | 
| PASSWORD_RESET_URL_ALLOW_LIST | List of URLs that can be used as reset_urlin the/password/requestendpoint. | |
| USER_INVITE_TOKEN_TTL | The duration that the invite token is valid. | 7d | 
| USER_INVITE_URL_ALLOW_LIST | List of URLs that can be used as invite_urlin the/users/inviteendpoint. | |
| USER_REGISTER_URL_ALLOW_LIST | List of URLs that can be used as verification_urlin the/users/registerendpoint. | |
| IP_TRUST_PROXY | Settings for the Express.js trust proxy setting. | true | 
| IP_CUSTOM_HEADER | What custom request header to use for the IP address. | false | 
| ASSETS_CONTENT_SECURITY_POLICY | Custom overrides for the Content-Security-Policy header for the /assets endpoint. See helmet's documentation on helmet.contentSecurityPolicy(). Example:ASSETS_CONTENT_SECURITY_POLICY_DIRECTIVES__IMG_SRC="'self' https://cdn.example.com data:" | |
| IMPORT_IP_DENY_LIST2 | Deny importing files from these IP addresses / IP ranges / CIDR blocks. Use 0.0.0.0to match any local IP address. | 0.0.0.0,169.254.169.254 | 
| CONTENT_SECURITY_POLICY_* | Custom overrides for the Content-Security-Policy header. See helmet's documentation on helmet.contentSecurityPolicy(). Example:CONTENT_SECURITY_POLICY_DIRECTIVES__IMG_SRC="'self' https://images.example.com data:" | |
| HSTS_ENABLED | Enable the Strict-Transport-Security policy header. When enabled, Directus will send the Strict-Transport-Security: max-age=15552000; includeSubDomainsheader on all responses. | false | 
| HSTS_* | Custom overrides for the Strict-Transport-Security header. See helmet's documentation. Example: HSTS_MAX_AGE=63072000 | 
1 When SECRET is not set, a random value will be used. This means sessions won't persist across system
restarts or horizontally scaled deployments. Must be explicitly set to a secure random value in production.
2 localhost can get resolved to ::1 as well as 127.0.0.1 depending on the system - ensure to include
both if you want to specifically block localhost.
Browser are pretty strict when it comes to third-party cookies. If you're running into unexpected problems when running your project and API on different domains, make sure to verify your configuration for REFRESH_TOKEN_COOKIE_NAME, REFRESH_TOKEN_COOKIE_SECURE, and REFRESH_TOKEN_COOKIE_SAME_SITE.
Hashing
| Variable | Description | Default Value | 
|---|---|---|
| HASH_MEMORY_COST | How much memory to use when generating hashes, in KiB. | 4096(4 MiB) | 
| HASH_LENGTH | The length of the hash function output in bytes. | 32 | 
| HASH_TIME_COST | The amount of passes (iterations) used by the hash function. It increases hash strength at the cost of time required to compute. | 3 | 
| HASH_PARALLELISM | The amount of threads to compute the hash on. Each thread has a memory pool with HASH_MEMORY_COSTsize. | 1(single thread) | 
| HASH_TYPE | The variant of the hash function ( 0: argon2d,1: argon2i, or2: argon2id). | 2(argon2id) | 
| HASH_ASSOCIATED_DATA | An extra and optional non-secret value. The value will be included Base64 encoded in the parameters portion of the digest. | 
Argon2's hashing function is used by Directus to hash user passwords, generate hashes for the Hash field type in collections, and for use in the /utils/hash/generate endpoint.
All HASH_* environment variable parameters are passed to the argon2.hash function. See the node-argon2 library options page for reference.
Modifying
HASH_MEMORY_COST and/or HASH_PARALLELISM will affect the amount of memory directus uses when computing hashes; each thread gets HASH_MEMORY_COST amount of memory, so the total additional memory will be these two values multiplied. This may cause out of memory errors, especially when running in containerized environments.CORS
| Variable | Description | Default Value | 
|---|---|---|
| CORS_ENABLED | Whether or not to enable the CORS headers. | false | 
| CORS_ORIGIN | Value for the Access-Control-Allow-Originheader. Usetrueto match the Origin header, or provide a domain or a CSV of domains for specific access. | false | 
| CORS_METHODS | Value for the Access-Control-Allow-Methodsheader. | GET,POST,PATCH,DELETE | 
| CORS_ALLOWED_HEADERS | Value for the Access-Control-Allow-Headersheader. | Content-Type,Authorization | 
| CORS_EXPOSED_HEADERS | Value for the Access-Control-Expose-Headersheader. | Content-Range | 
| CORS_CREDENTIALS | Whether or not to send the Access-Control-Allow-Credentialsheader. | true | 
| CORS_MAX_AGE | Value for the Access-Control-Max-Ageheader. | 18000 | 
For more details about each configuration variable, please see the CORS package documentation.
Rate Limiting
You can use the built-in rate-limiter to prevent users from hitting the API too much.
Enabling the rate-limiter with no other options will set a default maximum of 50 requests per second, tracked in memory.
| Variable | Description | Default Value | 
|---|---|---|
| RATE_LIMITER_ENABLED | Whether or not to enable rate limiting per IP on the API. | false | 
| RATE_LIMITER_POINTS | The amount of allowed hits per duration. | 50 | 
| RATE_LIMITER_DURATION | The time window in seconds in which the points are counted. | 1 | 
| RATE_LIMITER_STORE | Where to store the rate limiter counts. One of memory,redis. | memory | 
| RATE_LIMITER_HEALTHCHECK_THRESHOLD | Healthcheck timeout threshold in milliseconds. | 150 | 
| RATE_LIMITER_GLOBAL_ENABLED | Whether or not to enable global rate limiting on the API. | false | 
| RATE_LIMITER_GLOBAL_POINTS | The total amount of allowed hits per duration. | 1000 | 
| RATE_LIMITER_GLOBAL_DURATION | The time window in seconds in which the points are counted. | 1 | 
| RATE_LIMITER_GLOBAL_HEALTHCHECK_THRESHOLD | Healthcheck timeout threshold in milliseconds. | 150 | 
| RATE_LIMITER_REGISTRATION_ENABLED | Whether or not to enable rate limiting per IP on the user registration. | true | 
| RATE_LIMITER_REGISTRATION_POINTS | The amount of allowed hits per duration. | 5 | 
| RATE_LIMITER_REGISTRATION_DURATION | The time window in seconds in which the points are counted. | 60 | 
Pressure-Based Rate Limiter
This rate-limiter prevents the API from accepting new requests while the server is experiencing high load. This continuously monitors the current event loop and memory usage, and error with a 503 early when the system is overloaded.
| Variable | Description | Default Value | 
|---|---|---|
| PRESSURE_LIMITER_ENABLED | Whether or not to enable pressure-based rate limiting on the API. | true | 
| PRESSURE_LIMITER_SAMPLE_INTERVAL | The time window for measuring pressure in milliseconds. | 250 | 
| PRESSURE_LIMITER_MAX_EVENT_LOOP_UTILIZATION | The maximum allowed utilization where 1is 100% loop utilization. | 0.99 | 
| PRESSURE_LIMITER_MAX_EVENT_LOOP_DELAY | The maximum amount of time the current loop can be delayed in milliseconds. | 500 | 
| PRESSURE_LIMITER_MAX_MEMORY_RSS | The maximum allowed memory Resident Set Size (RSS) in bytes. | false | 
| PRESSURE_LIMITER_MAX_MEMORY_HEAP_USED | The maximum allowed heap usage in bytes. | false | 
| PRESSURE_LIMITER_RETRY_AFTER | Sets the Retry-Afterheader when the rate limiter is triggered. | false | 
Limits & Optimizations
Allows you to configure hard technical limits, to prevent abuse and optimize for your particular server environment.
| Variable | Description | Default Value | 
|---|---|---|
| RELATIONAL_BATCH_SIZE | How many rows are read into memory at a time when constructing nested relational datasets. | 25000 | 
| EXPORT_BATCH_SIZE | How many rows are read into memory at a time when constructing exports. | 5000 | 
| USERS_ADMIN_ACCESS_LIMIT | How many active users with admin privilege are allowed. | Infinity | 
| USERS_APP_ACCESS_LIMIT | How many active users with access to the Data Studio are allowed. | Infinity | 
| USERS_API_ACCESS_LIMIT | How many active API access users are allowed. | Infinity | 
| GRAPHQL_QUERY_TOKEN_LIMIT | How many GraphQL query tokens will be parsed. | 5000 | 
| MAX_PAYLOAD_SIZE | Controls the maximum request body size. Accepts number of bytes, or human readable string. | 1mb | 
| MAX_BATCH_MUTATION | The maximum number of items for batch mutations when creating, updating and deleting. | Infinity | 
| MAX_RELATIONAL_DEPTH | The maximum depth when filtering / querying relational fields, with a minimum value of 2. | 10 | 
| QUERY_LIMIT_DEFAULT | The default query limit used when not defined in the API request. | 100 | 
| QUERY_LIMIT_MAX | The maximum query limit accepted on API requests. | -1 | 
| QUERYSTRING_MAX_PARSE_DEPTH  | The maximum object depth when parsing URL query parameters using the querystring format | 10 | 
Get once-a-month release notes & real‑world code tips...no fluff. 🐰