Configurations

    When you have a file ./config/server.js with the following config:

    You can access it as

    1. strapi.config.get('server.host', 'defaultValueIfUndefined');

    Nested keys are accessible with dot-notation.

    NOTE

    Notice that the filename is used as a prefix to access the configurations.

    This file lets you define database connections that will be used to store your application content.

    NOTE

    You can find supported database and versions in the local installation process.

    Path — ./config/database.js.

    • defaultConnection (string): Connection by default for models which are not related to a specific connection. Default value: default.
    • connections List of all available connections.

      • default
        • connector (string): Connector used by the current connection. Will be bookshelf.
        • settings Useful for external session stores such as Redis.
          • client (string): Database client to create the connection. sqlite or postgres or mysql.
          • host (string): Database host name. Default value: localhost.
          • port (integer): Database port.
          • database (string): Database name.
          • username (string): Username used to establish the connection.
          • password (string): Password used to establish the connection.
          • timezone (string): Set the default behavior for local time. Default value: utc .
          • schema (string): Set the default database schema. Used only for Postgres DB.
          • ssl (boolean/object): For ssl database connection. Object is used to pass certificate files as strings.
        • options Options used for database connection.
          • debug (boolean): Show database exchanges and errors.
          • autoMigration (boolean): To disable auto tables/columns creation for SQL database.
          • pool Options used for database connection pooling. For default value and more information, look at Knex’s pool config documentation Configurations - 图2 (opens new window).
            • min (integer): Minimum number of connections to keep in the pool.
            • max (integer): Maximum number of connections to keep in the pool.
            • acquireTimeoutMillis (integer): Maximum time in milliseconds to wait for acquiring a connection from the pool.
            • createTimeoutMillis (integer): Maximum time in milliseconds to wait for creating a connection to be added to the pool.
            • idleTimeoutMillis (integer): Number of milliseconds to wait before destroying idle connections.
            • reapIntervalMillis (integer): How often to check for idle connections in milliseconds.
            • createRetryIntervalMillis (integer): How long to idle after a failed create before trying again in milliseconds.
    • defaultConnection (string): Connection by default for models which are not related to a specific connection. Default value: default.

    • connections List of all available connections.
      • default
        • connector (string): Connector used by the current connection. Will be mongoose.
        • settings Useful for external session stores such as Redis.
          • client (string): Database client to create the connection. Will be mongo.
          • host (string): Database host name. Default value: localhost.
          • port (integer): Database port. Default value: 27017.
          • database (string): Database name.
          • username (string): Username used to establish the connection.
          • password (string): Password used to establish the connection.
          • uri (string): This can overide all previous configurations - optional
        • options Options used for database connection.
          • ssl (boolean): For ssl database connection.
          • sslCA (string): Pass content (not filepath!) of server’s root CA for ssl connection.
          • debug (boolean): Show database exchanges and errors.
          • authenticationDatabase (string): Connect with authentication.
    1. module.exports = ({ env }) => ({
    2. defaultConnection: 'default',
    3. connections: {
    4. default: {
    5. connector: 'bookshelf',
    6. settings: {
    7. client: 'postgres',
    8. host: env('DATABASE_HOST', 'localhost'),
    9. port: env.int('DATABASE_PORT', 5432),
    10. database: env('DATABASE_NAME', 'strapi'),
    11. username: env('DATABASE_USERNAME', 'strapi'),
    12. password: env('DATABASE_PASSWORD', 'strapi'),
    13. schema: env('DATABASE_SCHEMA', 'public'), // Not Required
    14. ssl: {
    15. rejectUnauthorized: env.bool('DATABASE_SSL_SELF', false), // For self-signed certificates
    16. },
    17. },
    18. options: {
    19. ssl: env.bool('DATABASE_SSL', false),
    20. },
    21. },
    22. },
    23. });

    Please note that if you need client side SSL CA verification you will need to use the ssl:{} object with the fs module to convert your CA certificate to a string. You can see an example below:

    1. module.exports = ({ env }) => ({
    2. defaultConnection: 'default',
    3. connections: {
    4. default: {
    5. connector: 'bookshelf',
    6. settings: {
    7. client: 'postgres',
    8. ...
    9. ssl: {
    10. ca: fs.readFileSync(`${__dirname}/path/to/your/ca-certificate.crt`).toString(),
    11. },
    12. },
    13. options: {
    14. ssl: true
    15. },
    16. },
    17. },
    18. });
    1. module.exports = ({ env }) => ({
    2. defaultConnection: 'default',
    3. connections: {
    4. default: {
    5. connector: 'bookshelf',
    6. settings: {
    7. client: 'mysql',
    8. host: env('DATABASE_HOST', 'localhost'),
    9. port: env.int('DATABASE_PORT', 3306),
    10. database: env('DATABASE_NAME', 'strapi'),
    11. username: env('DATABASE_USERNAME', 'strapi'),
    12. password: env('DATABASE_PASSWORD', 'strapi'),
    13. },
    14. options: {},
    15. },
    16. },
    17. });
    1. module.exports = ({ env }) => ({
    2. defaultConnection: 'default',
    3. connections: {
    4. default: {
    5. connector: 'bookshelf',
    6. settings: {
    7. client: 'sqlite',
    8. filename: env('DATABASE_FILENAME', '.tmp/data.db'),
    9. },
    10. options: {
    11. useNullAsDefault: true,
    12. },
    13. },
    14. },
    15. });
    1. module.exports = ({ env }) => ({
    2. defaultConnection: 'default',
    3. connections: {
    4. default: {
    5. connector: 'mongoose',
    6. settings: {
    7. client: 'mongo',
    8. host: env('DATABASE_HOST', 'localhost'),
    9. port: env.int('DATABASE_PORT', 27017),
    10. database: env('DATABASE_NAME', 'strapi'),
    11. username: env('DATABASE_USERNAME', 'strapi'),
    12. password: env('DATABASE_PASSWORD', 'strapi'),
    13. },
    14. options: {
    15. authenticationDatabase: env('AUTHENTICATION_DATABASE'),
    16. ssl: env('DATABASE_SSL'),
    17. },
    18. },
    19. },
    20. });

    TIP

    Take a look at the for more details.

    Configuration in database

    Configuration files are not multi server friendly. So we created a data store for config you will want to update in production.

    Get settings
    • environment (string): Sets the environment you want to store the data in. By default it’s current environment (can be an empty string if your config is environment agnostic).
    • type (string): Sets if your config is for an api, plugin or core. By default it’s core.
    • name (string): You have to set the plugin or api name if type is api or plugin.
    • key (string, required): The name of the key you want to store.
    1. // strapi.store(object).get(object);
    2. // create reusable plugin store variable
    3. const pluginStore = strapi.store({
    4. environment: strapi.config.environment,
    5. type: 'plugin',
    6. name: 'users-permissions',
    7. });
    8. await pluginStore.get({ key: 'grant' });
    Set settings
    • value (any, required): The value you want to store.
    1. // strapi.store(object).set(object);
    2. // create reusable plugin store variable
    3. const pluginStore = strapi.store({
    4. environment: strapi.config.environment,
    5. type: 'plugin',
    6. name: 'users-permissions'
    7. });
    8. await pluginStore.set({
    9. key: 'grant',
    10. value: {
    11. ...
    12. }
    13. });

    Databases installation guides

    Strapi gives you the option to choose the most appropriate database for your project. It currently supports PostgreSQL, MongoDB, SQLite, MySQL and MariaDB. The following documentation covers how to install these databases locally (for development purposes) and on various hosted or cloud server solutions (for staging or production purposes).

    TIP

    Deploying Strapi itself is covered in the Deployment Guide.

    [

    SQLite

    Installation guide for SQLite database

    ]()

    [Configurations - 图4

    MongoDB

    Installation guide for MongoDB database

    ](https://strapi.io/documentation/developer-docs/latest/setup-deployment-guides/configurations/databases/mongodb.html)

    Server

    Minimal Server Config

    This is the default config created with any new project, all these keys are required at the very least, environmental configs do not need to contain all these values so long as they exist in the default ./config/server.js.

    Path — ./config/server.js.

    1. module.exports = ({ env }) => ({
    2. host: env('HOST', '0.0.0.0'),
    3. port: env.int('PORT', 1337),
    4. admin: {
    5. auth: {
    6. secret: env('ADMIN_JWT_SECRET', 'someSecretKey'),
    7. },
    8. },
    9. });

    Full Server Config

    This is an example of a full configuration, typically certain keys do not need to present in environmental configs, and not all of these keys are required. Please see the table below to see what each key does.

    Path — ./config/server.js.

    1. module.exports = ({ env }) => ({
    2. host: env('HOST', '0.0.0.0'),
    3. port: env.int('PORT', 1337),
    4. socket: '/tmp/nginx.socket', // only use if absolutely required
    5. emitErrors: false,
    6. url: env('PUBLIC_URL', 'https://api.example.com'),
    7. proxy: env.bool('IS_PROXIED', true),
    8. cron: {
    9. enabled: env.bool('CRON_ENABLED', false),
    10. },
    11. admin: {
    12. auth: {
    13. events: {
    14. onConnectionSuccess(e) {
    15. console.log(e.user, e.provider);
    16. },
    17. onConnectionError(e) {
    18. console.error(e.error, e.provider);
    19. },
    20. },
    21. secret: env('ADMIN_JWT_SECRET', 'someSecretKey'),
    22. },
    23. url: env('PUBLIC_ADMIN_URL', '/dashboard'),
    24. autoOpen: false,
    25. watchIgnoreFiles: [
    26. './my-custom-folder', // Folder
    27. './scripts/someScript.sh', // File
    28. ],
    29. host: 'localhost', // Only used for --watch-admin
    30. port: 8003, // Only used for --watch-admin
    31. serveAdminPanel: env.bool('SERVE_ADMIN', true),
    32. forgotPassword: {
    33. from: 'no-reply@example.com',
    34. replyTo: 'no-reply@example.com',
    35. },
    36. },
    37. });
    Available options

    Formats

    You can either use .js or .json files to configure your application.

    When using a .js you can either export an object:

    1. module.exports = {
    2. mySecret: 'someValue',
    3. };

    or a function returning a configuration object (recommended usage). The function will get access to the env utility.

    1. module.exports = ({ env }) => {
    2. mySecret: 'someValue',
    3. };
    4. };

    Optional configurations

    Environment

    In case you need specific static configurations for specific environments, and using environment variables becomes tedious, Strapi configurations can be created per environment in ./config/env/{env}/{filename}.

    These configurations will be merged into the base configurations defined in the ./config folder. The environment is based on the NODE_ENV environment variable (defaults to development).

    When starting Strapi with NODE_ENV=production it will load the configuration from ./config/* and ./config/env/production/*. Everything defined in the production config will override the default config.

    In combination with environment variables this pattern becomes really powerful.

    Examples:

    ./config/server.js

    1. module.exports = {
    2. host: '127.0.0.1',
    3. };

    ./config/env/production/server.js

    1. module.exports = ({ env }) => ({
    2. host: env('HOST', '0.0.0.0'),
    3. });

    When starting your application:

    1. yarn start
    2. # uses host 127.0.0.1
    1. NODE_ENV=production yarn start
    2. # uses host 0.0.0.0
    1. HOST=10.0.0.1 NODE_ENV=production yarn start
    2. # uses host 10.0.0.1

    List of Strapi’s environment variables

    Some settings can only be modified through environment variables. Here is a list of those settings are associated environment variable names:

    Configuration using environment variables

    In most use cases you will have different configurations between your environments. For example: your database credentials.

    Instead of writing those credentials into your configuration files, you can define those variables in a .env file at the root of your application.

    Example:

    Path — .env

    1. DATABASE_PASSWORD=acme

    If you want to customize the path of the .env file to load you can set an environment variable called ENV_PATH before starting your application:

    1. $ ENV_PATH=/absolute/path/to/.env npm run start

    Now you can access those variables in your configuration files and application. You can use process.env.{varName} to access those variables anywhere.

    In your configuration files you will have access to a env utility that allows defining defaults and casting values.

    Path — ./config/database.js

    1. module.exports = ({ env }) => ({
    2. connections: {
    3. default: {
    4. settings: {
    5. password: env('DATABASE_PASSWORD'),
    6. },
    7. },
    8. },
    9. });

    Casting environment variables

    API

    Path — ./config/api.js.

    1. module.exports = ({ env }) => ({
    2. responses: {
    3. privateAttributes: ['_v', 'id', 'created_at'],
    4. },
    5. rest: {
    6. defaultLimit: 100,
    7. maxLimit: 250,
    8. },
    9. });

    Available options

    Plugins

    A plugin is like a small independent sub-application. It has its own business logic with dedicated models, controllers, services, middlewares or hooks. It can also have its own UI integrated in the admin panel.

    TIP

    Please refer to the for more information.

    Hooks

    The hooks are modules that add functionality to the core. They are loaded during the server boot.

    Structure

    File structure
    1. module.exports = strapi => {
    2. const hook = {
    3. /**
    4. * Default options
    5. */
    6. defaults: {
    7. // config object
    8. },
    9. /**
    10. * Initialize the hook
    11. */
    12. async initialize() {
    13. // await someAsyncCode()
    14. // const settings = {...this.defaults, ...strapi.config.hook.settings.**};
    15. },
    16. };
    17. return hook;
    18. };
    • defaults (object): Contains the default configurations.
    • initialize (function): Called during the server boot.

    The of the hook are accessible through strapi.config.hook.settings.**.

    The hooks are accessible through the strapi.hook variable.

    Node modules

    Every folder that follows this name pattern strapi-hook-* in your ./node_modules folder will be loaded as a hook.

    1. /strapi-hook-[...]
    2. └─── lib
    3. - index.js
    4. - LICENSE.md
    5. - package.json
    6. - README.md

    The index.js is the entry point to your hook. It should look like the example above.

    Custom local hooks

    The framework allows loading hooks from the project directly without having to install them from npm. It’s a great way to take advantage of the features of the hooks system for code that doesn’t need to be shared between apps. To achieve this, you have to create a ./hooks folder at the root of your project and put the hooks into it.

    1. /project
    2. └─── admin
    3. └─── api
    4. └─── config
    5. - hook.js
    6. └─── hooks
    7. └─── strapi-documentation
    8. - index.js
    9. └─── strapi-server-side-rendering
    10. - index.js
    11. └─── public
    12. - favicon.ico
    13. - package.json
    14. - server.js

    Configuration and activation

    To activate and configure hooks with custom options, you need to add/edit your ./config/hook.js file in your Strapi app. A hook specific timeout value will overwrite the global timeout value, the default timeout value is 1000 milliseconds.

    1. module.exports = {
    2. timeout: 2000,
    3. settings: {
    4. 'hook-name': {
    5. enabled: true,
    6. timeout: 3000,
    7. },
    8. },
    9. };

    The middlewares are functions which are composed and executed in a stack-like manner upon request. If you are not familiar with the middleware stack in Koa, we highly recommend you to read the .

    Structure

    File structure
    1. module.exports = strapi => {
    2. return {
    3. // can also be async
    4. initialize() {
    5. strapi.app.use(async (ctx, next) => {
    6. // await someAsyncCode()
    7. await next();
    8. // await someAsyncCode()
    9. });
    10. },
    11. };
    12. };
    • initialize (function): Called during the server boot.

    The middlewares are accessible through the strapi.middleware variable.

    Node modules

    Every folder that follows this name pattern strapi-middleware-* in your ./node_modules folder will be loaded as a middleware.

    A middleware needs to follow the structure below:

    1. /middleware
    2. └─── lib
    3. - index.js
    4. - LICENSE.md
    5. - package.json
    6. - README.md

    The index.js is the entry point to your middleware. It should look like the example above.

    Custom middlewares

    The framework allows the application to override the default middlewares and add new ones. You have to create a ./middlewares folder at the root of your project and put the middlewares into it.

    1. /project
    2. └─── api
    3. └─── config
    4. └─── middlewares
    5. └─── responseTime // It will override the core default responseTime middleware.
    6. - index.js
    7. └─── views // It will be added into the stack of middleware.
    8. - index.js
    9. └─── public
    10. - favicon.ico
    11. - package.json
    12. - server.js

    Every middleware will be injected into the Koa stack. To manage the load order, please refer to the Middleware order section.

    Configuration and activation

    To configure the middlewares of your application, you need to create or edit the ./config/middleware.js file in your Strapi app.

    By default this file doesn’t exist, you will have to create it.

    Available options

    • timeout (integer): Defines the maximum allowed milliseconds to load a middleware.
    • load (Object): Configuration middleware loading. See details here
    • settings (Object): Configuration of each middleware
      • {middlewareName} (Object): Configuration of one middleware
        • enabled (boolean): Tells Strapi to run the middleware or not
    Settings

    Example:

    Path — ./config/middleware.js.

    1. module.exports = {
    2. //...
    3. settings: {
    4. cors: {
    5. origin: ['http://localhost', 'https://mysite.com', 'https://www.mysite.com'],
    6. },
    7. },
    8. };
    Load order

    The middlewares are injected into the Koa stack asynchronously. Sometimes it happens that some of these middlewares need to be loaded in a specific order. To define a load order, create or edit the file ./config/middleware.js.

    Path — ./config/middleware.js.

    1. module.exports = {
    2. load: {
    3. before: ['responseTime', 'logger', 'cors', 'responses'],
    4. order: [
    5. "Define the middlewares' load order by putting their name in this array in the right order",
    6. ],
    7. after: ['parser', 'router'],
    8. },
    9. };
    • load:
      • before: Array of middlewares that need to be loaded in the first place. The order of this array matters.
      • order: Array of middlewares that need to be loaded in a specific order.
      • after: Array of middlewares that need to be loaded at the end of the stack. The order of this array matters.

    Core middleware configurations

    The core of Strapi embraces a small list of middlewares for performances, security and great error handling.

    • boom
    • cors
    • cron
    • csp
    • favicon
    • gzip
    • hsts
    • ip
    • language
    • logger
    • p3p
    • parser
    • public
    • responses
    • responseTime
    • router
    • session
    • xframe
    • xss

    TIP

    The following middlewares cannot be disabled: responses, router, logger and boom.

    Global middlewares
    • favicon
      • path (string): Path to the favicon file. Default value: favicon.ico.
      • maxAge (integer): Cache-control max-age directive in ms. Default value: 86400000.
    • public
      • path (string): Path to the public folder. Default value: ./public.
      • maxAge (integer): Cache-control max-age directive in ms. Default value: 60000.
      • defaultIndex (boolean): Display default index page at / and /index.html. Default value: true.
    Request middlewares
    • session
      • enabled (boolean): Enable or disable sessions. Default value: false.
    • logger
      • level (string): Default log level. Default value: debug.
      • exposeInContext (boolean): Expose logger in context so it can be used through strapi.log.info(‘my log’). Default value: true.
      • requests (boolean): Enable or disable requests logs. Default value: false.
    • parser (See koa-body Configurations - 图10 (opens new window) for more information)
      • enabled(boolean): Enable or disable parser. Default value: true.
      • multipart (boolean): Enable or disable multipart bodies parsing. Default value: true.
      • jsonLimit (string|integer): The byte (if integer) limit of the JSON body. Default value: 1mb.
      • formLimit (string|integer): The byte (if integer) limit of the form body. Default value: 56k.
      • queryStringParser (see for a full list of options).
        • arrayLimit (integer): the maximum length of an array in the query string. Any array members with an index of greater than the limit will instead be converted to an object with the index as the key. Default value: 100.
        • depth (integer): maximum parsing depth of nested query string objects. Default value: 20.

    TIP

    The session doesn’t work with mongo as a client. The package that we should use is broken for now.

    Response middlewares
    • responseTime
      • enabled (boolean): Enable or not X-Response-Time header to response. Default value: false.
    • poweredBy
      • enabled (boolean): Enable or not X-Powered-By header to response. Default value: true.
      • value (string): The value of the header. Default value: Strapi <strapi.io>

    TIP

    gzip compression via koa-compress uses by default, but is not configured with sensible defaults for most cases. If you experience slow response times with gzip enabled, consider disabling Brotli by passing {br: false} as an option. You may also pass more sensible params with {br: { params: { // YOUR PARAMS HERE } }}

    Security middlewares
      • enabled (boolean): Enable or disable CSP to avoid Cross Site Scripting (XSS) and data injection attacks.
      • policy (string): Configures the Content-Security-Policy header. If not specified uses default value. Default value: undefined.
    • p3p Configurations - 图16 (opens new window)
      • enabled (boolean): Enable or disable p3p.
      • enabled (boolean): Enable or disable HSTS.
      • maxAge (integer): Number of seconds HSTS is in effect. Default value: 31536000.
      • includeSubDomains (boolean): Applies HSTS to all subdomains of the host. Default value: true.
    • xframe Configurations - 图18 (opens new window)
      • enabled (boolean): Enable or disable X-FRAME-OPTIONS headers in response.
      • value (string): The value for the header, e.g. DENY, SAMEORIGIN or ALLOW-FROM uri. Default value: SAMEORIGIN.
      • enabled (boolean): Enable or disable XSS to prevent Cross Site Scripting (XSS) attacks in older IE browsers (IE8).
    • cors Configurations - 图20 (opens new window)
      • enabled (boolean): Enable or disable CORS to prevent your server to be requested from another domain.
      • origin (string or array): Allowed URLs (http://example1.com, http://example2.com, ['http://www.example1.com', 'http://example1.com'] or allows everyone *). Default value: *.
      • expose (array): Configures the Access-Control-Expose-Headers CORS header. If not specified, no custom headers are exposed. Default value: ["WWW-Authenticate", "Server-Authorization"].
      • maxAge (integer): Configures the Access-Control-Max-Age CORS header. Default value: 31536000.
      • credentials (boolean): Configures the Access-Control-Allow-Credentials CORS header. Default value: true.
      • methods (array)|String - Configures the Access-Control-Allow-Methods CORS header. Default value: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"].
      • headers (array): Configures the Access-Control-Allow-Headers CORS header. If not specified, defaults to reflecting the headers specified in the request’s Access-Control-Request-Headers header. Default value: ["Content-Type", "Authorization", "X-Frame-Options"].
    • ip
      • enabled (boolean): Enable or disable IP blocker. Default value: false.
      • whiteList (array): Whitelisted IPs. Default value: [].
      • blackList (array): Blacklisted IPs. Default value: [].

    Example

    Create your custom middleware.

    Path — ./middlewares/timer/index.js

    1. module.exports = strapi => {
    2. return {
    3. initialize() {
    4. strapi.app.use(async (ctx, next) => {
    5. const start = Date.now();
    6. await next();
    7. const delta = Math.ceil(Date.now() - start);
    8. ctx.set('X-Response-Time', delta + 'ms');
    9. });
    10. },
    11. };
    12. };

    Enable the middleware in environments settings.

    Load a middleware at the very first place

    Path — ./config/middleware.js

    1. module.exports = {
    2. load: {
    3. before: ['timer', 'responseTime', 'logger', 'cors', 'responses', 'gzip'],
    4. order: [
    5. "Define the middlewares' load order by putting their name in this array is the right order",
    6. ],
    7. after: ['parser', 'router'],
    8. },
    9. settings: {
    10. timer: {
    11. enabled: true,
    12. },
    13. },
    14. };

    Functions

    The ./config/functions/ folder contains a set of JavaScript files in order to add dynamic and logic based configurations.

    All functions that are exposed in this folder are accessible via strapi.config.functions['fileName']();

    Bootstrap

    Path — ./config/functions/bootstrap.js.

    The bootstrap function is called at every server start. You can use it to add a specific logic at this moment of your server’s lifecycle.

    Here are some use cases:

    • Create an admin user if there isn’t one.
    • Fill the database with some necessary data.
    • Load some environment variables.

    The bootstrap function can be synchronous or asynchronous.

    Synchronous

    1. module.exports = () => {
    2. // some sync code
    3. };

    Return a promise

    1. module.exports = () => {
    2. return new Promise(/* some code */);
    3. };

    Asynchronous

    1. module.exports = async () => {
    2. await someSetup();
    3. };

    CRON tasks

    CRON tasks allow you to schedule jobs (arbitrary functions) for execution at specific dates, with optional recurrence rules. It only uses a single timer at any given time (rather than reevaluating upcoming jobs every second/minute).

    This feature is powered by node modules. Check it for more information.

    WARNING

    Make sure the enabled cron config is set to true in ./config/server.js file.

    The cron format consists of:

    1. * * * * * *
    2. |
    3. day of week (0 - 7) (0 or 7 is Sun)
    4. └───── month (1 - 12)
    5. └────────── day of month (1 - 31)
    6. └─────────────── hour (0 - 23)
    7. └───────────────────────── second (0 - 59, OPTIONAL)

    To define a CRON job, add your logic like below:

    Path — ./config/functions/cron.js.

    1. module.exports = {
    2. /**
    3. * Simple example.
    4. * Every monday at 1am.
    5. */
    6. '0 0 1 * * 1': () => {
    7. },
    8. };

    If your CRON task is required to run based on a specific timezone then you can configure the task like below:

    1. module.exports = {
    2. /**
    3. * CRON task with timezone example.
    4. * Every monday at 1am for Asia/Dhaka timezone.
    5. * List of valid timezones: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List
    6. */
    7. '0 0 1 * * 1': {
    8. task: () => {
    9. // Add your own logic here (e.g. send a queue of email, create a database backup, etc.).
    10. },
    11. options: {
    12. tz: 'Asia/Dhaka',
    13. },
    14. },
    15. };

    Database ORM customization

    When present, they are loaded to let you customize your database connection instance, for example for adding some plugin, customizing parameters, etc.

    You will need to install the plugin using the normal npm install the-plugin-name or any of the other supported package tools such as yarn then follow the below examples to load them.

    As an example, for using the mongoose-simple-random plugin for MongoDB, you can register it like this:

    Path — ./config/functions/mongoose.js.

    1. 'use strict';
    2. const random = require('mongoose-simple-random');
    3. module.exports = (mongoose, connection) => {
    4. mongoose.plugin(random);
    5. };

    Another example would be using the bookshelf-uuid plugin for MySQL, you can register it like this:

    Path — ./config/functions/bookshelf.js.

    1. 'use strict';
    2. module.exports = (bookshelf, connection) => {
    3. bookshelf.plugin('bookshelf-uuid');
    4. };

    Public assets

    Public assets are static files such as images, video, css, etc. that you want to make accessible to the outside world.

    Because an API may need to serve static assets, every new Strapi project includes by default, a folder named /public. Any file located in this directory is accessible if the request’s path doesn’t match any other defined route and if it matches a public file name.

    Example:

    An image named company-logo.png in ./public/ is accessible through /company-logo.png URL.

    TIP

    index.html files are served if the request corresponds to a folder name (/pictures url will try to serve public/pictures/index.html file).

    The dotfiles are not exposed. It means that every file name that starts with ., such as .htaccess or .gitignore, are not served.

    Single Sign On


    Single-Sign-On on Strapi allows you to configure additional sign-in and sign-up methods for your administration panel.

    CAUTION

    It is currently not possible to associate a unique SSO provider to an email address used for a Strapi account, meaning that the access to a Strapi account cannot be restricted to only one SSO provider. For more information and workarounds to solve this issue, please refer to the dedicated GitHub issue (opens new window).

    Prerequisites

    • A Strapi application running on version 3.5.0 or higher is required.
    • To configure SSO on your application, you will need an EE license with a Gold plan.
    • Make sure Strapi is part of the applications you can access with your provider. For example, with Microsoft (Azure) Active Directory, you must first ask someone with the right permissions to add Strapi to the list of allowed applications. Please refer to your provider(s) documentation to learn more about that.

    Usage

    SSO configuration lives in the server configuration of your application found within /config/server.js.

    Accessing the configuration

    The providers’ configuration should be written within the admin.auth.providers path of the server configuration.

    admin.auth.providers is an array of provider configuration.

    Provider Configuration

    A provider’s configuration is a Javascript object built with the following properties:

    TIP

    The uid property is the unique identifier of each strategy and is generally found in the strategy’s package. If you are not sure of what it refers to, please contact the maintainer of the strategy.

    The createStrategy Factory

    A passport strategy is usually built by instantiating it using 2 parameters: the configuration object, and the verify function.

    Configuration Object

    The configuration object depends on the strategy needs, but often asks for a callback URL to be redirected to once the connection has been made on the provider side.

    You can generate a specific callback URL for your provider using the getStrategyCallbackURL method. This URL also needs to be written on the provider side in order to allow redirection from it.

    The format of the callback URL is the following: /admin/connect/<provider_uid>.

    TIP

    strapi.admin.services.passport.getStrategyCallbackURL is a Strapi helper you can use to get a callback URL for a specific provider. It takes a provider name as a parameter and returns a URL.

    If needed, this is also where you will put your client ID and secret key for your OAuth2 application.

    Verify Function

    The verify function is used here as a middleware allowing the user to transform and make extra processing on the data returned from the provider API.

    This function always takes a done method as last parameter which is used to transfer needed data to the Strapi layer of SSO.

    Its signature is the following: void done(error: any, data: object); and it follows the following rules:

    • If error is not set to null, then the data sent is ignored, and the controller will throw an error.
    • If the SSO’s auto-registration feature is disabled, then the data object only need to be composed of an email property.
    • If the SSO’s auto-registration feature is enabled, then you will need to define (in addition to the email) either a username property or both firstname and lastname within the data oject.
    Adding a provider

    Adding a new provider means adding a new way for your administrators to log-in.

    To achieve a great flexibility and a large choice of provider, Strapi uses Passport.js Configurations - 图24 (opens new window). Any valid passport strategy that doesn’t need additional custom data should therefore work with Strapi.

    WARNING

    Strategies such as don’t work out of the box since they require extra data to be sent from the admin panel. If you want to add an LDAP provider to your application, you will need to write a custom strategy Configurations - 图26 (opens new window). You can also use services such as Okta and Auth0 as bridge services.

    Configuring the provider

    To configure a provider, follow the procedure below:

    1. Make sure to import your strategy in your server configuration file, either from an installed package or a local file.
    2. You’ll need to add a new item to the admin.auth.providers array in your server configuration that will match the format given above
    3. Restart your application, the provider should appear on your admin login page.
    Examples

    Using: passport-google-oauth2 (opens new window)

    1. yarn add passport-google-oauth2
    1. npm install --save passport-google-oauth2

    /config/server.js

    1. 'use strict';
    2. const GoogleStrategy = require('passport-google-oauth2');
    3. module.exports = ({ env }) => ({
    4. // ...
    5. admin: {
    6. // ...
    7. auth: {
    8. /// ...
    9. providers: [
    10. {
    11. uid: 'google',
    12. displayName: 'Google',
    13. icon: 'https://cdn2.iconfinder.com/data/icons/social-icons-33/128/Google-512.png',
    14. createStrategy: strapi =>
    15. new GoogleStrategy(
    16. {
    17. clientID: env('GOOGLE_CLIENT_ID'),
    18. clientSecret: env('GOOGLE_CLIENT_SECRET'),
    19. scope: [
    20. 'https://www.googleapis.com/auth/userinfo.email',
    21. 'https://www.googleapis.com/auth/userinfo.profile',
    22. ],
    23. callbackURL: strapi.admin.services.passport.getStrategyCallbackURL('google'),
    24. },
    25. (request, accessToken, refreshToken, profile, done) => {
    26. done(null, {
    27. email: profile.email,
    28. firstname: profile.given_name,
    29. lastname: profile.family_name,
    30. });
    31. }
    32. ),
    33. },
    34. ],
    35. },
    36. },
    37. });

    Using:

    1. yarn add passport-github2
    1. npm install --save passport-github2

    /config/server.js

    1. 'use strict';
    2. const GithubStrategy = require('passport-github2');
    3. module.exports = ({ env }) => ({
    4. // ...
    5. admin: {
    6. // ...
    7. auth: {
    8. // ...
    9. providers: [
    10. {
    11. uid: 'github',
    12. displayName: 'Github',
    13. icon: 'https://cdn1.iconfinder.com/data/icons/logotypes/32/github-512.png',
    14. createStrategy: strapi =>
    15. new GithubStrategy(
    16. {
    17. clientID: env('GITHUB_CLIENT_ID'),
    18. clientSecret: env('GITHUB_CLIENT_SECRET'),
    19. scope: ['user:email'],
    20. callbackURL: strapi.admin.services.passport.getStrategyCallbackURL('github'),
    21. },
    22. (accessToken, refreshToken, profile, done) => {
    23. done(null, {
    24. email: profile.emails[0].value,
    25. username: profile.username,
    26. });
    27. }
    28. ),
    29. },
    30. ],
    31. },
    32. },
    33. });

    Using: passport-discord (opens new window)

    1. yarn add passport-discord
    1. npm install --save passport-discord

    /config/server.js

    1. 'use strict';
    2. const DiscordStrategy = require('passport-discord');
    3. module.exports = ({ env }) => ({
    4. // ...
    5. admin: {
    6. // ...
    7. auth: {
    8. // ...
    9. providers: [
    10. {
    11. uid: 'discord',
    12. displayName: 'Discord',
    13. icon: 'https://cdn0.iconfinder.com/data/icons/free-social-media-set/24/discord-512.png',
    14. createStrategy: strapi =>
    15. new DiscordStrategy(
    16. {
    17. clientID: env('DISCORD_CLIENT_ID'),
    18. clientSecret: env('DISCORD_SECRET'),
    19. callbackURL: strapi.admin.services.passport.getStrategyCallbackURL('discord'),
    20. scope: ['identify', 'email'],
    21. },
    22. (accessToken, refreshToken, profile, done) => {
    23. done(null, {
    24. email: profile.email,
    25. username: `${profile.username}#${profile.discriminator}`,
    26. });
    27. }
    28. ),
    29. },
    30. ],
    31. },
    32. },
    33. });

    Using:

    1. yarn add passport-azure-ad-oauth2 jsonwebtoken
    1. npm install --save passport-azure-ad-oauth2 jsonwebtoken

    /config/server.js

    1. 'use strict';
    2. const AzureAdOAuth2Strategy = require('passport-azure-ad-oauth2');
    3. const jwt = require('jsonwebtoken');
    4. module.exports = ({ env }) => ({
    5. // ...
    6. admin: {
    7. // ...
    8. auth: {
    9. // ...
    10. providers: [
    11. {
    12. uid: 'azure_ad_oauth2',
    13. displayName: 'Microsoft',
    14. icon:
    15. 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/96/Microsoft_logo_%282012%29.svg/320px-Microsoft_logo_%282012%29.svg.png',
    16. createStrategy: strapi =>
    17. new AzureAdOAuth2Strategy(
    18. {
    19. clientID: env('MICROSOFT_CLIENT_ID', ''),
    20. clientSecret: env('MICROSOFT_CLIENT_SECRET', ''),
    21. scope: ['user:email'],
    22. tenant: env('MICROSOFT_TENANT_ID', ''),
    23. callbackURL: strapi.admin.services.passport.getStrategyCallbackURL(
    24. 'azure_ad_oauth2'
    25. ),
    26. },
    27. (accessToken, refreshToken, params, profile, done) => {
    28. var waadProfile = jwt.decode(params.id_token, '', true);
    29. done(null, {
    30. email: waadProfile.upn,
    31. username: waadProfile.upn,
    32. });
    33. }
    34. ),
    35. },
    36. ],
    37. },
    38. },
    39. });
    Advanced Customization
    Admin Panel URL

    If your administration panel lives on a different host/port than your Strapi server, you will need to modify the admin URL. To do so, head to your /config/server.js configuration file and tweak the admin.url field.

    For example, if your admin application has been started on https://api.example.com, your configuration will look like the following:

    /config/server.js

    1. module.exports = () => ({
    2. // ...
    3. admin: {
    4. // ...
    5. url: 'https://api.example.com/admin',
    6. },
    7. });
    Custom Logic

    In some scenarios, you will want to write additional logic for your connection workflow such as:

    • Restricting connection and registration for a specific domain
    • Triggering actions on connection attempt
    • Analytics

    The easiest way to do so is to plug into the verify function of your strategy and write some code.

    For example, if you want to allow only people with an official strapi.io email address, you can instantiate your strategy like this:

    1. const strategyInstance = new Strategy(configuration, ({ email, username }, done) => {
    2. // If the email ends with @strapi.io
    3. if (email.endsWith('@strapi.io')) {
    4. // Then we continue with the data given by the provider
    5. return done(null, { email, username });
    6. }
    7. // Otherwise, we continue by sending an error to the done function
    8. done(new Error('Forbidden email address'));
    9. });
    Authentication Events

    The SSO feature adds a new authentication event: onSSOAutoRegistration.

    This event is triggered whenever a user is created using the auto-register feature added by SSO. It contains the created user (event.user), and the provider used to make the registration (event.provider).

    Example:

    /config/server.js

    1. module.exports = () => ({
    2. // ...
    3. admin: {
    4. // ...
    5. auth: {
    6. // ...
    7. events: {
    8. onConnectionSuccess(e) {},
    9. onConnectionError(e) {},
    10. // ...
    11. onSSOAutoRegistration(e) {
    12. const { user, provider } = e;
    13. console.log(
    14. `A new user (${user.id}) has been automatically registered using ${provider}`
    15. );
    16. },
    17. },
    18. },
    19. },
    20. });

    🚧 This API is considered unstable for now.

    Role-Based Access Control (RBAC) is an approach to restricting access to some users. In a Strapi application, users of the admin panel are administrators. Their roles and permissions are . The Community Edition of Strapi offers 3 default roles (Author, Editor, and Super Admin). To go further, creating custom conditions for any type of permission is also possible. This requires an Enterprise Edition with at minimum a Bronze licence plan.

    Declaring new conditions

    Declare a single condition as an object, and multiple conditions as an array of objects. Each condition object can have 5 possible properties:

    • displayName (string): the condition name as shown in the admin panel,
    • name (string): the condition name, kebab-cased,
    • category (string, optional): conditions can be grouped into categories available ; if undefined, the condition will appear under the “Default” category,
    • plugin (string, optional): if the condition is created by a plugin, should be the plugin’s name, kebab-cased (e.g content-manager),
    • handler: a query object or a function used to verify the condition (see using the condition handler)

    Declare and register conditions in your file (see Registering conditions).

    NOTE

    The condition name property acts as a within its namespace, that is either the plugin if the plugin property is defined, or the root namespace.

    Using the condition handler

    A condition can be applied to any permission, and the condition handler is used to verify the condition. The handler can be a query object or a function.

    Query objects are useful to verify conditions on the entities you read, create, update, delete or publish. They use the library, but only with the following supported operators:

    • $or
    • $eq
    • $ne
    • $in
    • $nin
    • $lt
    • $lte
    • $gt
    • $gte
    • $exists
    • $elemMatch

    For instance, this handler uses a query object to match entities with an amount lower than 10,000:

    1. handler: { amount: { $lt: 10000 } }

    The condition handler can also be a synchronous or asynchronous function that:

    • receives the authenticated user making the request,
    • and returns true, false, or a query object.

    Returning true or false is useful to verify an external condition or a condition on the authenticated user. For instance, a condition that allows access to a page in the admin panel only if server time is 5pm could use this handler:

    1. handler: () => new Date().getHours() === 17

    The handler function receives the authenticated user, so it can verify conditions on the user:

    1. const condition = {
    2. displayName: "Email address from strapi.io",
    3. name: "email-strapi-dot-io",
    4. async handler(user) {
    5. return user.email.includes('@strapi.io');
    6. },
    7. };

    For more granular control, the handler function can also return a query object:

    1. const condition = {
    2. displayName: "price greater than 50",
    3. name: "price-gt-50",
    4. async handler(user) {
    5. return { price: { $gt: 50 } };
    6. },
    7. };

    Registering conditions

    1. module.exports = () => {
    2. strapi.admin.services.permission.conditionProvider.register({
    3. displayName: 'Billing amount under 10K',
    4. name: 'billing-amount-under-10k',
    5. plugin: 'admin',
    6. handler: { amount: { $lt: 10000 }},
    7. };

    To register multiple conditions, defined as an array of , use :