diff --git a/Gemfile b/Gemfile
index 66ca052dada0d3eb703db5e80c65d10b31773669..58eea95642746aeba0080833fc70c6ae6c5b06e2 100644
--- a/Gemfile
+++ b/Gemfile
@@ -156,7 +156,7 @@ gem 'wikicloth', '0.8.1'
 gem 'asciidoctor', '~> 2.0.10'
 gem 'asciidoctor-include-ext', '~> 0.3.1', require: false
 gem 'asciidoctor-plantuml', '~> 0.0.12'
-gem 'asciidoctor-kroki', '~> 0.2.2', require: false
+gem 'asciidoctor-kroki', '~> 0.3.0', require: false
 gem 'rouge', '~> 3.26.0'
 gem 'truncato', '~> 0.7.11'
 gem 'bootstrap_form', '~> 4.2.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index 3962fe270733082e28299fd56fe219ffe884e355..bea01cf000d55220d9afbd4d3e379b4dde128e76 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -84,7 +84,7 @@ GEM
     asciidoctor (2.0.12)
     asciidoctor-include-ext (0.3.1)
       asciidoctor (>= 1.5.6, < 3.0.0)
-    asciidoctor-kroki (0.2.2)
+    asciidoctor-kroki (0.3.0)
       asciidoctor (~> 2.0)
     asciidoctor-plantuml (0.0.12)
       asciidoctor (>= 1.5.6, < 3.0.0)
@@ -1291,7 +1291,7 @@ DEPENDENCIES
   asana (~> 0.10.3)
   asciidoctor (~> 2.0.10)
   asciidoctor-include-ext (~> 0.3.1)
-  asciidoctor-kroki (~> 0.2.2)
+  asciidoctor-kroki (~> 0.3.0)
   asciidoctor-plantuml (~> 0.0.12)
   atlassian-jwt (~> 0.2.0)
   attr_encrypted (~> 3.1.0)
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index eb3de936fadf9fa051ba9f5ec0af5765c8dbe8d2..7f7d38a09c580489c6105b591a88d43f60d56683 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -238,6 +238,7 @@ def visible_application_setting_attributes
       *::ApplicationSettingsHelper.visible_attributes,
       *::ApplicationSettingsHelper.external_authorization_service_attributes,
       *ApplicationSetting.repository_storages_weighted_attributes,
+      *ApplicationSetting.kroki_formats_attributes.keys.map { |key| "kroki_formats_#{key}".to_sym },
       :lets_encrypt_notification_email,
       :lets_encrypt_terms_of_service_accepted,
       :domain_denylist_file,
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index b3b90c79076a6a97b88e55ea13e609d34008241b..30ae535b06fd985447944eee7b1502d3068bd962 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -26,6 +26,16 @@ def enabled_protocol
     end
   end
 
+  def kroki_available_formats
+    ApplicationSetting.kroki_formats_attributes.map do |key, value|
+      {
+        name: "kroki_formats_#{key}",
+        label: value[:label],
+        value: @application_setting.kroki_formats[key] || false
+      }
+    end
+  end
+
   def storage_weights
     ApplicationSetting.repository_storages_weighted_attributes.map do |attribute|
       storage = attribute.to_s.delete_prefix('repository_storages_weighted_')
@@ -259,6 +269,7 @@ def visible_attributes
       :personal_access_token_prefix,
       :kroki_enabled,
       :kroki_url,
+      :kroki_formats,
       :plantuml_enabled,
       :plantuml_url,
       :polling_interval_multiplier,
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 6d375a19ffb12827bed6f6a2ac45538e063058ff..33c058dab96b47da57dacde2665620daa13f6b23 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -29,6 +29,21 @@ def self.repository_storages_weighted_attributes
     @repository_storages_weighted_atributes ||= Gitlab.config.repositories.storages.keys.map { |k| "repository_storages_weighted_#{k}".to_sym }.freeze
   end
 
+  def self.kroki_formats_attributes
+    {
+      blockdiag: {
+        label: 'BlockDiag (includes BlockDiag, SeqDiag, ActDiag, NwDiag, PacketDiag and RackDiag)'
+      },
+      bpmn: {
+        label: 'BPMN'
+      },
+      excalidraw: {
+        label: 'Excalidraw'
+      }
+    }
+  end
+
+  store_accessor :kroki_formats, *ApplicationSetting.kroki_formats_attributes.keys, prefix: true
   store_accessor :repository_storages_weighted, *Gitlab.config.repositories.storages.keys, prefix: true
 
   # Include here so it can override methods from
@@ -54,6 +69,7 @@ def self.repository_storages_weighted_attributes
 
   default_value_for :id, 1
   default_value_for :repository_storages_weighted, {}
+  default_value_for :kroki_formats, {}
 
   chronic_duration_attr_writer :archive_builds_in_human_readable, :archive_builds_in_seconds
 
@@ -135,6 +151,8 @@ def self.repository_storages_weighted_attributes
 
   validate :validate_kroki_url, if: :kroki_enabled
 
+  validates :kroki_formats, json_schema: { filename: 'application_setting_kroki_formats' }
+
   validates :plantuml_url,
             presence: true,
             if: :plantuml_enabled
@@ -570,6 +588,25 @@ def recaptcha_or_login_protection_enabled
     end
   end
 
+  kroki_formats_attributes.keys.each do |key|
+    define_method :"kroki_formats_#{key}=" do |value|
+      super(::Gitlab::Utils.to_boolean(value))
+    end
+  end
+
+  def kroki_format_supported?(diagram_type)
+    case diagram_type
+    when 'excalidraw'
+      return kroki_formats_excalidraw
+    when 'bpmn'
+      return kroki_formats_bpmn
+    end
+
+    return kroki_formats_blockdiag if ::Gitlab::Kroki::BLOCKDIAG_FORMATS.include?(diagram_type)
+
+    ::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES.include?(diagram_type)
+  end
+
   private
 
   def parsed_grafana_url
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index e5284d15a49404e1e3f4cedbb420f91dd581753d..2911ae6b1c8f362247547d84c92905eee7c17edb 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -176,6 +176,7 @@ def defaults
         container_registry_expiration_policies_worker_capacity: 0,
         kroki_enabled: false,
         kroki_url: nil,
+        kroki_formats: { blockdiag: false, bpmn: false, excalidraw: false },
         rate_limiting_response_text: nil
       }
     end
diff --git a/app/validators/json_schemas/application_setting_kroki_formats.json b/app/validators/json_schemas/application_setting_kroki_formats.json
new file mode 100644
index 0000000000000000000000000000000000000000..460dc74069fa3cdae1409b5cc58e780d8af6b5f0
--- /dev/null
+++ b/app/validators/json_schemas/application_setting_kroki_formats.json
@@ -0,0 +1,10 @@
+{
+  "description": "Kroki formats",
+  "type": "object",
+  "properties": {
+    "bpmn": { "type": "boolean" },
+    "excalidraw": { "type": "boolean" },
+    "blockdiag": { "type": "boolean" }
+  },
+  "additionalProperties": false
+}
diff --git a/app/views/admin/application_settings/_kroki.html.haml b/app/views/admin/application_settings/_kroki.html.haml
index 23848fb8b9b02ab62b0dc16a2e6c94161aa119fd..cd57d4cca6570d88e369749cd38204e22560f0df 100644
--- a/app/views/admin/application_settings/_kroki.html.haml
+++ b/app/views/admin/application_settings/_kroki.html.haml
@@ -21,5 +21,13 @@
           = f.text_field :kroki_url, class: 'form-control gl-form-input', placeholder: 'http://your-kroki-instance:8000'
           .form-text.text-muted
             = (_('When Kroki is enabled, GitLab sends diagrams to an instance of Kroki to display them as images. You can use the free public cloud instance %{kroki_public_url} or you can %{install_link} on your own infrastructure. Once you\'ve installed Kroki, make sure to update the server URL to point to your instance.') % { kroki_public_url: '<code>https://kroki.io</code>', install_link: link_to('install Kroki', 'https://docs.kroki.io/kroki/setup/install/', target: '_blank') }).html_safe
+        .form-group
+          = f.label :kroki_formats, 'Additional diagram formats', class: 'label-bold'
+          .form-text.text-muted
+            = (_('Using additional formats requires starting the companion containers. Make sure that all %{kroki_images} are running.') % { kroki_images: link_to('required containers', 'https://docs.kroki.io/kroki/setup/install/#_images', target: '_blank') }).html_safe
+          - kroki_available_formats.each do |format|
+            .form-check
+              = f.check_box format[:name], class: 'form-check-input'
+              = f.label format[:name], format[:label], class: 'form-check-label'
 
       = f.submit _('Save changes'), class: "btn gl-button btn-success"
diff --git a/changelogs/unreleased/241744-additional-formats-kroki.yml b/changelogs/unreleased/241744-additional-formats-kroki.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f305ee13553bd985322f3435eaf84cc598e472ce
--- /dev/null
+++ b/changelogs/unreleased/241744-additional-formats-kroki.yml
@@ -0,0 +1,5 @@
+---
+title: "Enable/disable additional diagram formats on Kroki"
+merge_request: 49304
+author: Guillaume Grossetie
+type: added
diff --git a/db/migrate/20201120092000_add_kroki_formats_to_application_settings_table.rb b/db/migrate/20201120092000_add_kroki_formats_to_application_settings_table.rb
new file mode 100644
index 0000000000000000000000000000000000000000..a059099dbc4f1fe1e9233c28093550a61f0344e9
--- /dev/null
+++ b/db/migrate/20201120092000_add_kroki_formats_to_application_settings_table.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddKrokiFormatsToApplicationSettingsTable < ActiveRecord::Migration[6.0]
+  DOWNTIME = false
+
+  def change
+    change_table :application_settings do |t|
+      t.jsonb :kroki_formats, null: false, default: {}
+    end
+  end
+end
diff --git a/db/schema_migrations/20201120092000 b/db/schema_migrations/20201120092000
new file mode 100644
index 0000000000000000000000000000000000000000..eaa6c37cff27e6a10f6b71e4e68b31337c67abaf
--- /dev/null
+++ b/db/schema_migrations/20201120092000
@@ -0,0 +1 @@
+c8f837a5fe7a1959af41f19f93b6dd96d8907a476626f124876ee8b10b120b71
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 429f233c8d56823567ddc01f5ad3ee43af6b5d48..f3feb2573de071de6a28374ceb71d9672943f425 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -9398,6 +9398,7 @@ CREATE TABLE application_settings (
     keep_latest_artifact boolean DEFAULT true NOT NULL,
     notes_create_limit integer DEFAULT 300 NOT NULL,
     notes_create_limit_allowlist text[] DEFAULT '{}'::text[] NOT NULL,
+    kroki_formats jsonb DEFAULT '{}'::jsonb NOT NULL,
     CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
     CONSTRAINT app_settings_registry_exp_policies_worker_capacity_positive CHECK ((container_registry_expiration_policies_worker_capacity >= 0)),
     CONSTRAINT check_17d9558205 CHECK ((char_length((kroki_url)::text) <= 1024)),
diff --git a/lib/gitlab/kroki.rb b/lib/gitlab/kroki.rb
index 8c5652fb766e3bbd5219eb029d7c3af1141af0a4..38090786836b412b16605edb90adea88b445c76e 100644
--- a/lib/gitlab/kroki.rb
+++ b/lib/gitlab/kroki.rb
@@ -13,9 +13,7 @@ module Kroki
         packetdiag
         rackdiag
       ].freeze
-    # Diagrams that require a companion container are disabled for now
     DIAGRAMS_FORMATS = ::AsciidoctorExtensions::Kroki::SUPPORTED_DIAGRAM_NAMES
-                           .reject { |diagram_type| diagram_type == 'mermaid' || diagram_type == 'bpmn' || BLOCKDIAG_FORMATS.include?(diagram_type) }
     DIAGRAMS_FORMATS_WO_PLANTUML = DIAGRAMS_FORMATS
                                         .reject { |diagram_type| diagram_type == 'plantuml' }
 
@@ -28,10 +26,18 @@ def self.formats(current_settings)
 
       # If PlantUML is enabled, PlantUML diagrams will be processed by the PlantUML server.
       # In other words, the PlantUML server has precedence over Kroki since both can process PlantUML diagrams.
-      if current_settings.plantuml_enabled
-        DIAGRAMS_FORMATS_WO_PLANTUML
-      else
-        DIAGRAMS_FORMATS
+      diagram_formats = if current_settings.plantuml_enabled
+                          DIAGRAMS_FORMATS_WO_PLANTUML
+                        else
+                          DIAGRAMS_FORMATS
+                        end
+
+      # No additional diagram formats
+      return diagram_formats unless current_settings.kroki_formats.present?
+
+      # Diagrams that require a companion container must be explicitly enabled from the settings
+      diagram_formats.select do |diagram_type|
+        current_settings.kroki_format_supported?(diagram_type)
       end
     end
   end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 3847742c1b5884df1c10a2cb6e6f736ea647eaa2..5076242892788f9dc67097e8b99ad10230975ac8 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -32256,6 +32256,9 @@ msgstr ""
 msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
 msgstr ""
 
+msgid "Using additional formats requires starting the companion containers. Make sure that all %{kroki_images} are running."
+msgstr ""
+
 msgid "Using required encryption strategy when encrypted field is missing!"
 msgstr ""
 
diff --git a/spec/controllers/admin/application_settings_controller_spec.rb b/spec/controllers/admin/application_settings_controller_spec.rb
index f0b224484c6c25000fcfc9d1557bbf196c5dc7ba..71abf3191b89f3992508bbfc1868c42da44a3e67 100644
--- a/spec/controllers/admin/application_settings_controller_spec.rb
+++ b/spec/controllers/admin/application_settings_controller_spec.rb
@@ -150,6 +150,13 @@
       expect(ApplicationSetting.current.repository_storages_weighted_default).to eq(75)
     end
 
+    it 'updates kroki_formats setting' do
+      put :update, params: { application_setting: { kroki_formats_excalidraw: '1' } }
+
+      expect(response).to redirect_to(general_admin_application_settings_path)
+      expect(ApplicationSetting.current.kroki_formats_excalidraw).to eq(true)
+    end
+
     it "updates default_branch_name setting" do
       put :update, params: { application_setting: { default_branch_name: "example_branch_name" } }
 
diff --git a/spec/helpers/application_settings_helper_spec.rb b/spec/helpers/application_settings_helper_spec.rb
index 479e2d7ef9d6f8af25b01d078a01878523e75ed8..2cd01451e0d12c3f310b4e3589cee13929e19ac7 100644
--- a/spec/helpers/application_settings_helper_spec.rb
+++ b/spec/helpers/application_settings_helper_spec.rb
@@ -194,4 +194,33 @@
       it { is_expected.to be false }
     end
   end
+
+  describe '.kroki_available_formats' do
+    let(:application_setting) { build(:application_setting) }
+
+    before do
+      helper.instance_variable_set(:@application_setting, application_setting)
+      stub_application_setting(kroki_formats: { 'blockdiag' => true, 'bpmn' => false, 'excalidraw' => false })
+    end
+
+    it 'returns available formats correctly' do
+      expect(helper.kroki_available_formats).to eq([
+                                             {
+                                               name: 'kroki_formats_blockdiag',
+                                               label: 'BlockDiag (includes BlockDiag, SeqDiag, ActDiag, NwDiag, PacketDiag and RackDiag)',
+                                               value: true
+                                             },
+                                             {
+                                               name: 'kroki_formats_bpmn',
+                                               label: 'BPMN',
+                                               value: false
+                                             },
+                                             {
+                                               name: 'kroki_formats_excalidraw',
+                                               label: 'Excalidraw',
+                                               value: false
+                                             }
+                                           ])
+    end
+  end
 end
diff --git a/spec/lib/gitlab/asciidoc_spec.rb b/spec/lib/gitlab/asciidoc_spec.rb
index 36e4decdeadbee39369e61bd9e7ddee1c979e551..08510d4652b108c0ed15f7988be273aa9a557411 100644
--- a/spec/lib/gitlab/asciidoc_spec.rb
+++ b/spec/lib/gitlab/asciidoc_spec.rb
@@ -510,6 +510,73 @@ module Gitlab
 
           expect(render(input, context)).to include(output.strip)
         end
+
+        it 'does not convert a blockdiag diagram to image' do
+          input = <<~ADOC
+            [blockdiag]
+            ....
+            blockdiag {
+              Kroki -> generates -> "Block diagrams";
+              Kroki -> is -> "very easy!";
+
+              Kroki [color = "greenyellow"];
+              "Block diagrams" [color = "pink"];
+              "very easy!" [color = "orange"];
+            }
+            ....
+          ADOC
+
+          output = <<~HTML
+            <div>
+            <div>
+            <pre>blockdiag {
+              Kroki -&gt; generates -&gt; "Block diagrams";
+              Kroki -&gt; is -&gt; "very easy!";
+
+              Kroki [color = "greenyellow"];
+              "Block diagrams" [color = "pink"];
+              "very easy!" [color = "orange"];
+            }</pre>
+            </div>
+            </div>
+          HTML
+
+          expect(render(input, context)).to include(output.strip)
+        end
+      end
+
+      context 'with Kroki and BlockDiag (additional format) enabled' do
+        before do
+          allow_any_instance_of(ApplicationSetting).to receive(:kroki_enabled).and_return(true)
+          allow_any_instance_of(ApplicationSetting).to receive(:kroki_url).and_return('https://kroki.io')
+          allow_any_instance_of(ApplicationSetting).to receive(:kroki_formats_blockdiag).and_return(true)
+        end
+
+        it 'converts a blockdiag diagram to image' do
+          input = <<~ADOC
+            [blockdiag]
+            ....
+            blockdiag {
+              Kroki -> generates -> "Block diagrams";
+              Kroki -> is -> "very easy!";
+
+              Kroki [color = "greenyellow"];
+              "Block diagrams" [color = "pink"];
+              "very easy!" [color = "orange"];
+            }
+            ....
+          ADOC
+
+          output = <<~HTML
+            <div>
+            <div>
+            <a class="no-attachment-icon" href="https://kroki.io/blockdiag/svg/eNpdzDEKQjEQhOHeU4zpPYFoYesRxGJ9bwghMSsbUYJ4d10UCZbDfPynolOek0Q8FsDeNCestoisNLmy-Qg7R3Blcm5hPcr0ITdaB6X15fv-_YdJixo2CNHI2lmK3sPRA__RwV5SzV80ZAegJjXSyfMFptc71w==" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Diagram" class="lazy" data-src="https://kroki.io/blockdiag/svg/eNpdzDEKQjEQhOHeU4zpPYFoYesRxGJ9bwghMSsbUYJ4d10UCZbDfPynolOek0Q8FsDeNCestoisNLmy-Qg7R3Blcm5hPcr0ITdaB6X15fv-_YdJixo2CNHI2lmK3sPRA__RwV5SzV80ZAegJjXSyfMFptc71w=="></a>
+            </div>
+            </div>
+          HTML
+
+          expect(render(input, context)).to include(output.strip)
+        end
       end
     end
 
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index efa9125bff9940b95645b5391c5b47a275741f15..9a4dd2c799b7fa66e424459f8ec2778c676b1016 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -964,6 +964,50 @@ def expect_invalid
     end
   end
 
+  describe 'kroki_format_supported?' do
+    it 'returns true when Excalidraw is enabled' do
+      subject.kroki_formats_excalidraw = true
+      expect(subject.kroki_format_supported?('excalidraw')).to eq(true)
+    end
+
+    it 'returns true when BlockDiag is enabled' do
+      subject.kroki_formats_blockdiag = true
+      # format "blockdiag" aggregates multiple diagram types: actdiag, blockdiag, nwdiag...
+      expect(subject.kroki_format_supported?('actdiag')).to eq(true)
+      expect(subject.kroki_format_supported?('blockdiag')).to eq(true)
+    end
+
+    it 'returns false when BlockDiag is disabled' do
+      subject.kroki_formats_blockdiag = false
+      # format "blockdiag" aggregates multiple diagram types: actdiag, blockdiag, nwdiag...
+      expect(subject.kroki_format_supported?('actdiag')).to eq(false)
+      expect(subject.kroki_format_supported?('blockdiag')).to eq(false)
+    end
+
+    it 'returns false when the diagram type is optional and not enabled' do
+      expect(subject.kroki_format_supported?('bpmn')).to eq(false)
+    end
+
+    it 'returns true when the diagram type is enabled by default' do
+      expect(subject.kroki_format_supported?('vegalite')).to eq(true)
+      expect(subject.kroki_format_supported?('nomnoml')).to eq(true)
+      expect(subject.kroki_format_supported?('unknown-diagram-type')).to eq(false)
+    end
+
+    it 'returns false when the diagram type is unknown' do
+      expect(subject.kroki_format_supported?('unknown-diagram-type')).to eq(false)
+    end
+  end
+
+  describe 'kroki_formats' do
+    it 'returns the value for kroki_formats' do
+      subject.kroki_formats = { blockdiag: true, bpmn: false, excalidraw: true }
+      expect(subject.kroki_formats_blockdiag).to eq(true)
+      expect(subject.kroki_formats_bpmn).to eq(false)
+      expect(subject.kroki_formats_excalidraw).to eq(true)
+    end
+  end
+
   it 'does not allow to set weight for non existing storage' do
     setting.repository_storages_weighted = { invalid_storage: 100 }