{"id":31026,"date":"2025-05-09T05:00:00","date_gmt":"2025-05-09T03:00:00","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=31026"},"modified":"2025-05-05T14:56:38","modified_gmt":"2025-05-05T12:56:38","slug":"give-drupal-what-it-didnt-get-at-birth","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/en\/give-drupal-what-it-didnt-get-at-birth\/","title":{"rendered":"Give Drupal what it didn&#8217;t get at birth"},"content":{"rendered":"\n<p>Implementing Drupal from scratch always raises the question of initial environment configuration. At that point, we start digging in our memory for the modules we will need that will be useful or make life easier \u2013 modules that are not installed in the CMS by default.<\/p>\n\n\n\n<p>Experience shows that it is helpful to collect in a single document the modules that are worth installing at the outset or at least worth considering. When administering an existing instance, knowing which additional modules can enrich it is also good. The descriptions below refer to modules compatible with Drupal&nbsp;10 and&nbsp;11.<\/p>\n\n\n\n<p>I will also rely on experience, highlighting the functionality frequently required or appearing as best practice.<\/p>\n\n\n\n<p>All modules can be installed through Composer (composer require drupal\/[module_name]), and the project pages list installation commands for the latest available versions.<\/p>\n\n\n\n<p><strong>This set can also serve as a development path<\/strong>: mastering the listed modules will allow you to deliver solutions to clients quickly and cleanly.<\/p>\n\n\n\n<p>I have divided the modules into several categories according to their purpose:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration\u00a0<\/li>\n\n\n\n<li>Content\u00a0<\/li>\n\n\n\n<li>Security<\/li>\n<\/ul>\n\n\n\n<p>I also provide an assessment of each module&#8217;s usefulness in the context of larger projects. Every large Drupal project cannot do without some of these features, so they should be treated as \u201cmust\u2011haves\u201d and studied carefully.<\/p>\n\n\n\n<p>I include useful links that explain the functionality and show concrete use cases wherever possible.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong><strong>Configuration<\/strong><\/strong><\/h2>\n\n\n\n<p>Here, I present modules that help manage and maintain Drupal\u2019s configuration. They are convenient, and even indispensable, for large, multi-environment deployments (where you have separate test, production, and other environments).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Config Split<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/config_split\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/config_split<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>always<\/strong><\/li>\n<\/ul>\n\n\n\n<p>This module lets you keep the configuration tailored to a given environment\u2013development, testing, production, etc. You can create multiple configuration splits that are enabled according to rules you define in the configuration files for each environment.<\/p>\n\n\n\n<p>The most basic usage is to add to&nbsp;settings.php&nbsp;a list of configuration sets that should be active or inactive depending on the value of an environment variable, where the key<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nconfig_split.config_split.{split_key},\n{split_key} jest identyfikatorem \u015brodowiska skonfigurowanym w \/admin\/config\/development\/configuration\/config-split.\n<\/pre><\/div>\n\n\n<p>Example:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nif (&#039;production&#039; === $_ENV&#x5B;&#039;ENVIRONMENT&#039;]) { \n  $config&#x5B;&#039;config_split.config_split.prod&#039;]&#x5B;&#039;status&#039;] = TRUE; \n  $config&#x5B;&#039;config_split.config_split.dev&#039;]&#x5B;&#039;status&#039;] = FALSE; \n} else { \n  $config&#x5B;&#039;config_split.config_split.prod&#039;]&#x5B;&#039;status&#039;] = FALSE; \n  $config&#x5B;&#039;config_split.config_split.dev&#039;]&#x5B;&#039;status&#039;] = TRUE; \n} \n<\/pre><\/div>\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration path: \/admin\/config\/development\/configuration\/config-split<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Config Ignore<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/config_ignore\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/config_ignore<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>very often<\/strong><\/li>\n<\/ul>\n\n\n\n<p>In its basic functionality, the module lets you ignore entire configuration files or only specific fields during import, thus ensuring that the configuration stored in the database will not be changed. This is useful when, for example, you do not want to keep the password to some system that is already set on the production server in a configuration file.<\/p>\n\n\n\n<p>The latest version introduced two additional modes \u2013 Intermediate and Advanced \u2013 that now allow granular filtering during Imports and Exports and per Create, Update, or Delete operation.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration path: \/admin\/config\/development\/configuration\/ignore<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Config Readonly<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/config_readonly\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/config_readonly<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>depends on needs<\/strong><\/li>\n<\/ul>\n\n\n\n<p>The module allows you to lock any changes to the site configuration by simply setting $settings[&#8216;config_readonly&#8217;] = TRUE. You can condition on whatever logic you need, such as disabling any configuration changes on production.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Content<\/h2>\n\n\n\n<p>Here I present a list of modules that make working with Drupal easier, expand its capabilities, and improve the overall look and feel of the experience.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Paragraphs<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/paragraphs\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/paragraphs<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>always<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Paragraphs let you structure content by splitting it into independent, predefined paragraph types that can comprise any mix of text and media. Editors can add and reorder them freely instead of relying on one huge body field. This keeps the code base clean and gives greater flexibility when styling each section. Paragraphs are practically a must\u2011have in every project.<\/p>\n\n\n\n<p>The Paragraphs&nbsp;Library sub\u2011module makes previously created paragraph items reusable across multiple documents.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration paths paragraphs types: \/admin\/structure\/paragraphs_type<\/li>\n\n\n\n<li>Configuration paths paragraphs library: \/admin\/config\/content\/paragraphs_library_item<\/li>\n\n\n\n<li>Resources: <a href=\"https:\/\/www.youtube.com\/watch?v=0gboYyLtTQk\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.youtube.com\/watch?v=0gboYyLtTQk<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Entity Usage<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/entity_usage\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/entity_usage<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>depends on needs<\/strong><\/li>\n<\/ul>\n\n\n\n<p>This module tracks relationships between entities, letting you verify what is used where. Because of the performance cost, use with caution on large sites.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Resources:\n<ul class=\"wp-block-list\">\n<li><a style=\"font-size: 1.4rem;\" href=\"https:\/\/www.thedroptimes.com\/30817\/video-know-more-about-entity-usage-module\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.thedroptimes.com\/30817\/video-know-more-about-entity-usage-module<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.drupal.org\/docs\/contributed-modules\/entity-usage\/installation-and-basic-usage\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/docs\/contributed-modules\/entity-usage\/installation-and-basic-usage<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Entity Browser<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/entity_browser\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/entity_browser<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>very often<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Entity Browser allows you to build flexible, feature\u2011rich interfaces for searching and selecting entities (content, files, images, media, etc.). Instead of a simple select list, you can define sophisticated browsing, filtering, and previewing interfaces \u2013 for instance, with Views or modal windows. Editors can more easily search, sort, and pick objects, and the interface can be tailored to project needs.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration path: \/admin\/config\/content\/entity_browser<\/li>\n\n\n\n<li>Resources:\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=wn_bkTdBkc8\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.youtube.com\/watch?v=wn_bkTdBkc8<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.drupal.org\/docs\/contributed-modules\/entity-browser\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/docs\/contributed-modules\/entity-browser<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Redirect<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/redirect\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/redirect<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>always<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Provides a mechanism for redirecting any path to a specific Drupal document and lets you choose the appropriate HTTP status code (300\u00a0\u2013\u00a0307, see <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Reference\/Status\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Reference\/Status<\/a>)<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration path: \/admin\/config\/search\/redirect<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Media<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/docs\/8\/core\/modules\/media\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/docs\/8\/core\/modules\/media<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>very often<\/strong><\/li>\n<\/ul>\n\n\n\n<p>The module is part of Drupal&nbsp;11 core but is not installed by default.<\/p>\n\n\n\n<p>It introduces a mechanism for creating and managing several media types: Audio, Document, Image, Remote&nbsp;video, and Video. Each media type can have its fields and display settings, letting you tailor it to the site\u2019s requirements. For example, you can create fields in a document that accept only a specific, predefined media type.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration paths: \/admin\/structure\/media oraz \/admin\/config\/media\/media-settings<\/li>\n\n\n\n<li>Resources: <a href=\"https:\/\/www.youtube.com\/watch?v=2x21f2MnQ8E\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.youtube.com\/watch?v=2x21f2MnQ8E<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Media library<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/media_library\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/media_library<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>very often<\/strong><\/li>\n<\/ul>\n\n\n\n<p>This is a convenient, advanced widget that extends the Media module, offering an intuitive interface for managing media assets. Integrated with CKEditor\u00a05, it lets editors embed media directly in content. <\/p>\n\n\n\n<p>To make the widget available in CKEditor\u00a05, add the Drupal\u00a0Media button to the chosen text format at\u00a0\/admin\/config\/content\/formats.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"54\" height=\"54\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/05\/img_1.png\" alt=\"ikona\" class=\"wp-image-31011\"\/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Resources:\n<ul class=\"wp-block-list\">\n<li><a style=\"font-size: 1.4rem;\" href=\"https:\/\/www.drupal.org\/docs\/core-modules-and-themes\/core-modules\/media-library-module\/overview\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/docs\/core-modules-and-themes\/core-modules\/media-library-module\/overview<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=Ge-C0Oe4wuE\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.youtube.com\/watch?v=Ge-C0Oe4wuE<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Media entity browser<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/media_entity_browser\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/media_entity_browser<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>depends on needs<\/strong><\/li>\n<\/ul>\n\n\n\n<p>This module is essential if you want users to have a convenient file\u2011management tool. It combines the strengths of <em>Entity Browser<\/em> with Drupal\u2019s <em>Media<\/em> module. <\/p>\n\n\n\n<p>You can customize this widget\u2019s appearance and use Views to decide which available media items to display.<\/p>\n\n\n\n<p>Note that it depends on <em>inline_entity_form<\/em>, currently in RC; test thoroughly before deploying to production.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" width=\"1024\" height=\"486\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/05\/img_2-1024x486.png\" alt=\"select media\" class=\"wp-image-31013\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/05\/img_2-1024x486.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/05\/img_2-300x142.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/05\/img_2-768x364.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/05\/img_2.png 1081w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration path: \/admin\/config\/content\/entity_browser<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Trash<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/trash\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/trash<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>depends on needs<\/strong><\/li>\n<\/ul>\n\n\n\n<p>This is a great safeguard against accidental deletion that introduces a Trash\u00a0bin mechanism. You can choose which entity types are handled and set automatic cleanup after a defined time.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration path:\u00a0\/admin\/config\/content\/trash<\/li>\n\n\n\n<li>Resources:\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/git.drupalcode.org\/project\/trash\/-\/blob\/3.x\/README.md\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/git.drupalcode.org\/project\/trash\/-\/blob\/3.x\/README.md<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.youtube.com\/shorts\/UgcUWIzQaoo\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.youtube.com\/shorts\/UgcUWIzQaoo<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.youtube.com\/watch?v=7jNmM2VnjUQ\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.youtube.com\/watch?v=7jNmM2VnjUQ<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Dropzonejs<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/dropzonejs\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/dropzonejs<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>depends on needs<\/strong><\/li>\n<\/ul>\n\n\n\n<p>It exposes the DropzoneJS library and lets users upload files with drag\u2011and\u2011drop. It works great with <em>Media Entity Browser<\/em>. Installation requires adding to&nbsp;composer.json&nbsp;a&nbsp;repositories&nbsp;entry, followed by running composer commands.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n &quot;repositories&quot;: &#x5B;\n        {\n            &quot;type&quot;: &quot;package&quot;,\n            &quot;package&quot;: {\n                &quot;name&quot;: &quot;enyo\/dropzone&quot;,\n                &quot;version&quot;: &quot;5.9.3&quot;,\n                &quot;type&quot;: &quot;drupal-library&quot;,\n                &quot;dist&quot;: {\n                    &quot;url&quot;: &quot;https:\/\/github.com\/dropzone\/dropzone\/releases\/download\/v5.9.3\/dist.zip&quot;,\n                    &quot;type&quot;: &quot;zip&quot;\n                }\n            }\n        }\n    ]\n<\/pre><\/div>\n\n\n<p>And then run the command: <em>composer require drupal\/dropzonejs enyo\/dropzone<\/em><\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img decoding=\"async\" width=\"1024\" height=\"456\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/05\/img-1024x456.png\" alt=\"add or select media\" class=\"wp-image-31015\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/05\/img-1024x456.png 1024w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/05\/img-300x134.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/05\/img-768x342.png 768w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/05\/img.png 1468w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration path: No configuration is required.<\/li>\n\n\n\n<li>Resources:\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/dropzone\/dropzone\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/github.com\/dropzone\/dropzone<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.dropzone.dev\/\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.dropzone.dev\/<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Pathauto<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/pathauto\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/pathauto<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>always<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Automatically generates URL aliases for any entity type. For each entity and language, you can configure a custom path pattern.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration path: \/admin\/config\/search\/path\/patterns<\/li>\n\n\n\n<li>Resources: <a href=\"https:\/\/www.youtube.com\/watch?v=Pi5CweTmF5Q\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.youtube.com\/watch?v=Pi5CweTmF5Q<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong><strong>Security<\/strong><\/strong><\/h2>\n\n\n\n<p>Here, I present the most useful and widely used modules that enhance a site&#8217;s security, which every Drupal developer should be familiar with.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Rename Admin Paths<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/rename_admin_paths\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/rename_admin_paths<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>always<\/strong><\/li>\n<\/ul>\n\n\n\n<p>This is a simple yet effective module that hardens the site by changing default admin paths such as <em>\/admin<\/em> and <em>\/user<\/em> to custom ones, making it harder for attackers to find the login panel.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img decoding=\"async\" width=\"707\" height=\"574\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/05\/img_4.png\" alt=\"rename admin path\" class=\"wp-image-31017\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/05\/img_4.png 707w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/05\/img_4-300x244.png 300w\" sizes=\"(max-width: 707px) 100vw, 707px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration path: \/backend\/config\/system\/rename-admin-paths<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Password Policy<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/password_policy\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/password_policy<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>depends on needs<\/strong><\/li>\n<\/ul>\n\n\n\n<p>The module lets you create password policies for selected roles. By installing the accompanying <strong>Policy Constraints<\/strong> sub-modules, you can specify, among other things, the following settings.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>password_policy_blacklist<\/strong>: a list of strings that cannot be used as passwords and that passwords are not allowed to contain.<\/li>\n\n\n\n<li><strong>password_policy_character_types<\/strong>: the minimum number of character types (2, 3, or 4) required from the following set: lowercase letters, uppercase letters, digits, special characters.<\/li>\n\n\n\n<li><strong>password_policy_characters<\/strong>: specifies the minimum number of characters of each type (lowercase letters, uppercase letters, digits, special characters).<\/li>\n\n\n\n<li><strong>password_policy_consecutive<\/strong>: limits how many times the same character may be repeated consecutively in a password.<\/li>\n\n\n\n<li><strong>password_policy_delay<\/strong>: sets the hours that must pass before a password can be changed again (this limit also applies when changing a password via the admin UI).<\/li>\n\n\n\n<li><strong>password_policy_history<\/strong>: prevents a user from re-using a previous password.<\/li>\n\n\n\n<li><strong>password_policy_length<\/strong>: lets you define both the maximum and minimum length of a password.<\/li>\n<\/ul>\n\n\n\n<p>It also lets you enforce a password change after a defined period.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration path: \/admin\/config\/security\/password-policy<\/li>\n\n\n\n<li>Resources: <a href=\"https:\/\/www.youtube.com\/watch?v=aYLnFQh7Mj0\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.youtube.com\/watch?v=aYLnFQh7Mj0<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Security Kit<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/seckit\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/seckit<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>depends on needs<\/strong><\/li>\n<\/ul>\n\n\n\n<p>This module enhances Drupal\u2019s security by guarding against common web threats such as XSS attacks, clickjacking, and SSL stripping. It lets you configure HTTP headers, set a Content Security Policy (CSP), manage HTTPS, and block unauthorized embedded content. You can also disable the browser\u2019s autofill of the username field on the login page.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration page: \/admin\/config\/system\/seckit<\/li>\n\n\n\n<li>Resources:\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.droptica.com\/blog\/security-kit-drupal-module-overview\/\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.droptica.com\/blog\/security-kit-drupal-module-overview\/<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/sekurak.pl\/czym-jest-xss\/\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/sekurak.pl\/czym-jest-xss\/<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/sekurak.pl\/czym-jest-podatnosc-csrf-cross-site-request-forgery\/\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/sekurak.pl\/czym-jest-podatnosc-csrf-cross-site-request-forgery\/<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.keepersecurity.com\/blog\/pl\/2023\/07\/24\/what-is-clickjacking\/\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.keepersecurity.com\/blog\/pl\/2023\/07\/24\/what-is-clickjacking\/<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Autologout<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/autologout\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/autologout<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>depends on needs<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Let&#8217;s you configure automatic logouts based on inactivity or a hard session limit.<\/p>\n\n\n\n<p>You can set an inactivity timeout that logs a user out after a period of idle time, and an absolute session limit after which the user is forcibly logged out regardless of activity. Both limits can be configured per role, and you can define a URL to which the user is redirected immediately after the automatic logout. It\u2019s also worth looking at the companion module <a href=\"https:\/\/www.drupal.org\/project\/autologout_alterable\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/autologout_alterable<\/a>.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration path: \/admin\/config\/people\/autologout<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Shield<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/shield\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/shield<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>depends on needs<\/strong><\/li>\n<\/ul>\n\n\n\n<p>The module restricts access to a Drupal instance by requiring a predefined username and password before anyone can reach the site. It\u2019s very useful for shielding test environments from external visitors and can replace mechanisms that DevOps teams often configure at the server level.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration path: \/admin\/config\/system\/shield<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Username Enumeration Prevention<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/username_enumeration_prevention\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/username_enumeration_prevention<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>depends on needs<\/strong><\/li>\n<\/ul>\n\n\n\n<p>Prevents anonymous users from enumerating valid usernames.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration path: No configuration is required.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Masquerade<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/masquerade\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/masquerade<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>depends on needs<\/strong><\/li>\n<\/ul>\n\n\n\n<p>This module allows administrators to switch to another user without entering a password and to operate fully in that user\u2019s context. It is an extremely useful tool for developers and site admins when testing user permissions or troubleshooting access and configuration issues.<\/p>\n\n\n\n<p>To impersonate a user, go to <strong>\/admin\/people<\/strong> and choose <strong>Masquerade as<\/strong> from the operations column.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration path: No configuration is required.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Security Review<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/security_review\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/security_review<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>always<\/strong><\/li>\n<\/ul>\n\n\n\n<p>This tool offers a set of tests that detect vulnerabilities related to your application\u2019s configuration and environment.<\/p>\n\n\n\n<p>You can run the tests manually from the admin interface or integrate them into your release scripts by executing <em>drush security:review<\/em>.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration path: \/admin\/config\/security-review<\/li>\n\n\n\n<li>Resources: <a href=\"https:\/\/www.droptica.pl\/blog\/security-review-opis-modulu\/\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.droptica.pl\/blog\/security-review-opis-modulu\/<\/a><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>CORS UI<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/cors_ui\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/cors_ui<\/a><\/li>\n\n\n\n<li>Usefulness rating: <strong>always<\/strong><\/li>\n<\/ul>\n\n\n\n<p>It lets you manage Cross-Origin Resource Sharing (CORS) settings, allowing site administrators to configure CORS policies without manually editing config files. This makes integration with external applications and services more intuitive and less error-prone.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration path: \/admin\/config\/services\/cors<\/li>\n\n\n\n<li>Resources:\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Guides\/CORS\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Guides\/CORS<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/sekurak.pl\/czym-jest-cors-cross-origin-resource-sharing-i-jak-wplywa-na-bezpieczenstwo\/\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/sekurak.pl\/czym-jest-cors-cross-origin-resource-sharing-i-jak-wplywa-na-bezpieczenstwo\/<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Flood control<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Project: <a href=\"https:\/\/www.drupal.org\/project\/flood_control\" target=\"_blank\" rel=\"noopener\" title=\"\" rel=\"nofollow\" >https:\/\/www.drupal.org\/project\/flood_control<\/a><\/li>\n\n\n\n<li>Usefulness rating: always<\/li>\n<\/ul>\n\n\n\n<p>The module lets you limit the number of failed logins per IP address or user, define a whitelist, and restrict form submissions for a specific email address.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Configuration path: \/admin\/config\/people\/flood-control<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/en\/job-ads\/\" target=\"_blank\" rel=\"noreferrer noopener\"><img decoding=\"async\" width=\"737\" height=\"170\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/05\/praca-EN-k.jpg\" alt=\"job offert\" class=\"wp-image-31028\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/05\/praca-EN-k.jpg 737w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/05\/praca-EN-k-300x69.jpg 300w\" sizes=\"(max-width: 737px) 100vw, 737px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong><strong>Summary<\/strong><\/strong><\/h2>\n\n\n\n<p>In short, with the modules outlined above, you launch Drupal in its \u201cpro\u201d edition\u2013easier to extend, maintain, and use securely. Knowing their capabilities lets you tailor solutions to client needs in no time, and it can also serve as your first-run checklist for every new deployment.<\/p>\n\n\n\n<p>***<\/p>\n\n\n\n<p>If you are interested in Drupal, be sure to also take a look at another article by our specialist: <a href=\"https:\/\/sii.pl\/blog\/en\/drupal-vs-wordpress-which-system-should-you-choose\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Drupal vs WordPress \u2013 which system should you choose?<\/a><\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;31026&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;1&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;5&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;5\\\/5 ( vote: 1)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;Give Drupal what it didn\\u0026#039;t get at birth&quot;,&quot;width&quot;:&quot;139.5&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 139.5px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            5\/5 ( vote: 1)    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>Implementing Drupal from scratch always raises the question of initial environment configuration. At that point, we start digging in our &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/en\/give-drupal-what-it-didnt-get-at-birth\/\">Continued<\/a><\/p>\n","protected":false},"author":712,"featured_media":31022,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1320],"tags":[2742,1590,1526,1353],"class_list":["post-31026","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hard-development","tag-drupal-en","tag-tools","tag-guidebook","tag-e-commerce-en"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2025\/05\/Raport-analiza-wykres_v3.jpg","category_names":["Hard development"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/31026"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/users\/712"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/comments?post=31026"}],"version-history":[{"count":1,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/31026\/revisions"}],"predecessor-version":[{"id":31030,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/posts\/31026\/revisions\/31030"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media\/31022"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/media?parent=31026"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/categories?post=31026"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/en\/wp-json\/wp\/v2\/tags?post=31026"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}