diff --git a/Gemfile b/Gemfile
index cea22dfe3ade98ac1ee7cce0659193f1732bf838..d5c9bd27b605d0485e8b76b1430a439838ff5608 100644
--- a/Gemfile
+++ b/Gemfile
@@ -29,6 +29,7 @@ gem "devise-i18n"
 gem "enum_help"
 # gem "faceted_search"#, path: "../../noesya/faceted_search"
 gem "faceted_search"
+gem "faraday"
 gem "font-awesome-sass"
 gem "front_matter_parser"
 gem "geocoder", "~> 1.8"
diff --git a/Gemfile.lock b/Gemfile.lock
index 1d62c2ac3e6fd38768aa75d130c383ecfabe48f1..5aa6f78d0809e7c6afb8ce72788c57fe7cdd1ecc 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -612,6 +612,7 @@ DEPENDENCIES
   devise-i18n
   enum_help
   faceted_search
+  faraday
   figaro
   font-awesome-sass
   front_matter_parser
diff --git a/app/controllers/admin/communication/websites_controller.rb b/app/controllers/admin/communication/websites_controller.rb
index 796e197834980f45cde6a6f05b01b0c58cdb6e31..17f9c2cf221a99c05a2f485cf4f1d0f3fbea6ce3 100644
--- a/app/controllers/admin/communication/websites_controller.rb
+++ b/app/controllers/admin/communication/websites_controller.rb
@@ -89,6 +89,7 @@ class Admin::Communication::WebsitesController < Admin::Communication::Websites:
       :name, :url, :repository, :about_type, :about_id, :in_production,
       :git_provider, :git_endpoint, :git_branch, :plausible_url, 
       :feature_posts, :feature_agenda,
+      :deuxfleurs_hosting,
       :social_mastodon, :social_x, :social_linkedin, :social_youtube, :social_vimeo, :social_peertube, :social_instagram, :social_facebook, :social_tiktok,
       :deployment_status_badge, :autoupdate_theme, language_ids: []
     ]
diff --git a/app/models/communication/website.rb b/app/models/communication/website.rb
index 8ba01a97bcf0b70c4838a65a6c1ec80d0f35691e..2aaf024bdf9e8be8078399fdad642800e1f73d2e 100644
--- a/app/models/communication/website.rb
+++ b/app/models/communication/website.rb
@@ -7,6 +7,8 @@
 #  access_token            :string
 #  autoupdate_theme        :boolean          default(TRUE)
 #  deployment_status_badge :text
+#  deuxfleurs_hosting      :boolean          default(FALSE)
+#  deuxfleurs_identifier   :string
 #  feature_agenda          :boolean          default(FALSE)
 #  feature_posts           :boolean          default(TRUE)
 #  git_branch              :string
@@ -54,6 +56,7 @@ class Communication::Website < ApplicationRecord
   include WithConfigs
   include WithConnectedObjects
   include WithDependencies
+  include WithDeuxfleurs
   include WithGit
   include WithGitRepository
   include WithImport
diff --git a/app/models/communication/website/configs/base.rb b/app/models/communication/website/configs/base.rb
index 9b7fa604c17341528509a83ffc6ab87097f34fe4..c56540ab78b506e4e52a5a7f583384a00e2925d1 100644
--- a/app/models/communication/website/configs/base.rb
+++ b/app/models/communication/website/configs/base.rb
@@ -7,6 +7,8 @@
 #  access_token            :string
 #  autoupdate_theme        :boolean          default(TRUE)
 #  deployment_status_badge :text
+#  deuxfleurs_hosting      :boolean          default(FALSE)
+#  deuxfleurs_identifier   :string
 #  feature_agenda          :boolean          default(FALSE)
 #  feature_posts           :boolean          default(TRUE)
 #  git_branch              :string
diff --git a/app/models/communication/website/configs/default_languages.rb b/app/models/communication/website/configs/default_languages.rb
index 47d7ec2edff86fc8bd2237d2e01fa24d342d1ea5..fa3f09d80d1957526445e04d40e7f87ac830962f 100644
--- a/app/models/communication/website/configs/default_languages.rb
+++ b/app/models/communication/website/configs/default_languages.rb
@@ -7,6 +7,8 @@
 #  access_token            :string
 #  autoupdate_theme        :boolean          default(TRUE)
 #  deployment_status_badge :text
+#  deuxfleurs_hosting      :boolean          default(FALSE)
+#  deuxfleurs_identifier   :string
 #  feature_agenda          :boolean          default(FALSE)
 #  feature_posts           :boolean          default(TRUE)
 #  git_branch              :string
diff --git a/app/models/communication/website/configs/default_permalinks.rb b/app/models/communication/website/configs/default_permalinks.rb
index 20b02d54915db8cc4869ae6dc9c6ccb906685b33..ff8cbc66309adce7cc4360f974fe73c030ab7436 100644
--- a/app/models/communication/website/configs/default_permalinks.rb
+++ b/app/models/communication/website/configs/default_permalinks.rb
@@ -7,6 +7,8 @@
 #  access_token            :string
 #  autoupdate_theme        :boolean          default(TRUE)
 #  deployment_status_badge :text
+#  deuxfleurs_hosting      :boolean          default(FALSE)
+#  deuxfleurs_identifier   :string
 #  feature_agenda          :boolean          default(FALSE)
 #  feature_posts           :boolean          default(TRUE)
 #  git_branch              :string
diff --git a/app/models/communication/website/configs/development_config.rb b/app/models/communication/website/configs/development_config.rb
index 25cdeed1bf74674465bc71db1929252e61c22415..3a412dd008aa090d4e6ef04bf6022e1be6925138 100644
--- a/app/models/communication/website/configs/development_config.rb
+++ b/app/models/communication/website/configs/development_config.rb
@@ -7,6 +7,8 @@
 #  access_token            :string
 #  autoupdate_theme        :boolean          default(TRUE)
 #  deployment_status_badge :text
+#  deuxfleurs_hosting      :boolean          default(FALSE)
+#  deuxfleurs_identifier   :string
 #  feature_agenda          :boolean          default(FALSE)
 #  feature_posts           :boolean          default(TRUE)
 #  git_branch              :string
diff --git a/app/models/communication/website/configs/production_config.rb b/app/models/communication/website/configs/production_config.rb
index 8f3a51424c4dad862237f24fdbc11a907a873be8..06e6e48a74312afefa1863013ca4785e9c333ca5 100644
--- a/app/models/communication/website/configs/production_config.rb
+++ b/app/models/communication/website/configs/production_config.rb
@@ -7,6 +7,8 @@
 #  access_token            :string
 #  autoupdate_theme        :boolean          default(TRUE)
 #  deployment_status_badge :text
+#  deuxfleurs_hosting      :boolean          default(FALSE)
+#  deuxfleurs_identifier   :string
 #  feature_agenda          :boolean          default(FALSE)
 #  feature_posts           :boolean          default(TRUE)
 #  git_branch              :string
diff --git a/app/models/communication/website/with_deuxfleurs.rb b/app/models/communication/website/with_deuxfleurs.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b7b31e60f99c40520ba23bc4dd9581d1cdcd3884
--- /dev/null
+++ b/app/models/communication/website/with_deuxfleurs.rb
@@ -0,0 +1,48 @@
+module Communication::Website::WithDeuxfleurs
+  extend ActiveSupport::Concern
+
+  attr_reader :deuxfleurs_first_load
+
+  included do
+    before_save :deuxfleurs_setup, if: :deuxfleurs_hosting
+    after_save_commit :deuxfleurs_preload, if: :deuxfleurs_hosting
+  end
+
+  protected
+
+  def deuxfleurs_setup_done?
+    deuxfleurs_identifier.present?
+  end
+
+  def deuxfleurs_setup
+    return if deuxfleurs_setup_done?
+    self.deuxfleurs_identifier = deuxfleurs.create_bucket(deuxfleurs_host)
+    self.url = deuxfleurs_default_url
+    @deuxfleurs_first_load = true
+  end
+
+  def deuxfleurs_preload
+    return unless deuxfleurs_first_load
+    deuxfleurs_first_load_to_generate_certificate
+  end
+ 
+  def deuxfleurs_host
+    "#{university.identifier}-#{to_s.parameterize}"
+  end
+
+  def deuxfleurs_first_load_to_generate_certificate
+    Faraday.get url
+  rescue
+    # The certificate is not there yet, it is supposed to fail
+    # This first call will generate it
+  end
+  handle_asynchronously :deuxfleurs_first_load_to_generate_certificate
+
+  def deuxfleurs_default_url
+    deuxfleurs.default_url_for(deuxfleurs_host)
+  end
+
+  def deuxfleurs
+    @deuxfleurs ||= Deuxfleurs.new
+  end
+end
\ No newline at end of file
diff --git a/app/services/deuxfleurs.rb b/app/services/deuxfleurs.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d0594d413f439167f216f0fe9ea909a719678bc6
--- /dev/null
+++ b/app/services/deuxfleurs.rb
@@ -0,0 +1,26 @@
+class Deuxfleurs
+
+  def create_bucket(host)
+    response = client.post("website/#{host}")
+    data = JSON.parse response.body
+    data.dig('vhost', 'name')
+  end
+
+  def default_url_for(host)
+    "https://#{host}.web.deuxfleurs.fr"
+  end
+
+  protected
+
+  def client
+    unless @client
+      @client = Faraday.new url: 'https://guichet.deuxfleurs.fr/api/unstable/'
+      @client.request :authorization, 
+                      :basic, 
+                      ENV['DEUXFLEURS_USER'], 
+                      ENV['DEUXFLEURS_PASSWORD']
+    end
+    @client
+  end
+
+end
\ No newline at end of file
diff --git a/app/views/admin/communication/websites/_form.html.erb b/app/views/admin/communication/websites/_form.html.erb
index b984f5fa72cb650d99f28662624baf2993c91cf7..82c57b5677d1f341a3f7d6a24fc834f8a3533b5c 100644
--- a/app/views/admin/communication/websites/_form.html.erb
+++ b/app/views/admin/communication/websites/_form.html.erb
@@ -10,27 +10,32 @@
         <%= f.input :in_production %>
         <%= render 'admin/communication/abouts', f: f, i18n_key: 'activerecord.attributes.communication/website.about_' %>
       <% end %>
+    </div>
+    <div class="col-xl-4">
       <%= osuny_panel Communication::Website.human_attribute_name('features') do %>
         <%= f.input :feature_posts %>
         <%= f.input :feature_agenda %>
       <% end %>
+      <%= osuny_panel t('communication.website.hosting') do %>
+        <%= f.input :deuxfleurs_hosting, hint: website.deuxfleurs_identifier %>
+      <% end %>
+      <%= osuny_panel t('communication.website.analytics') do %>
+        <%= f.input :plausible_url %>
+      <% end %>
+    </div>
+    <div class="col-xl-4">
       <%= osuny_panel Language.model_name.human(count: 2) do %>
         <%= f.association :languages, as: :check_boxes, required: true, wrapper_html: { class: "js-languages" }, label_method: lambda { |l| language_name(l.iso_code) } %>
         <%= f.association :default_language, include_blank: t('simple_form.include_blanks.defaults.language'), input_html: (@website.persisted? ? { disabled: true } : { class: "js-default-language" }) %>
       <% end %>
     </div>
+  </div>
+  <div class="row">
     <div class="col-xl-4">
       <%= osuny_panel t('communication.website.git') do %>
         <%= f.input :autoupdate_theme %>
         <%= f.input :git_provider, include_blank: false %>
         <%= f.input :git_endpoint %>
-        <%= f.input :deployment_status_badge, 
-                    as: :string, 
-                    input_html: {
-                      autocomplete: 'deployment_status_badge',
-                      role: 'presentation'
-                    }
-                    %>
         <%= f.input :access_token, 
                     as: :string, 
                     placeholder: masked_string(f.object.access_token), 
@@ -43,12 +48,21 @@
                     %>
         <%= f.input :repository %>
         <%= f.input :git_branch %>
+        <%= f.input :deployment_status_badge, 
+                    as: :string, 
+                    input_html: {
+                      autocomplete: 'deployment_status_badge',
+                      role: 'presentation'
+                    }
+                    %>
       <% end %>
+    </div>
+    <div class="col-xl-6">
       <%= osuny_panel t('communication.website.analytics') do %>
         <%= f.input :plausible_url %>
       <% end %>
     </div>
-    <div class="col-xl-4">
+    <div class="col-xl-6">
       <%= osuny_panel Communication::Website.human_attribute_name('social') do %>
         <%= f.input :social_mastodon %>
         <%= f.input :social_peertube %>
diff --git a/app/views/admin/communication/websites/configs/production_config/static.html.erb b/app/views/admin/communication/websites/configs/production_config/static.html.erb
index 4e86dabd96882e994b0e09592409f225d2fcf978..c07982d31f5f517ae15482aae5d6709a7b35085c 100644
--- a/app/views/admin/communication/websites/configs/production_config/static.html.erb
+++ b/app/views/admin/communication/websites/configs/production_config/static.html.erb
@@ -5,3 +5,11 @@ baseURL: <%= @website.url %>
 ## LANGUAGE
 defaultContentLanguage: <%= @website.default_language.iso_code %>
 defaultContentLanguageInSubdir: <%= @website.languages.many? %>
+
+<% if @website.deuxfleurs_hosting %>
+## DEUXFLEURS
+deployment:
+  targets:
+    - name: "production"
+      URL: "s3://#{@website.deuxfleurs_identifier}?endpoint=garage.deuxfleurs.fr&s3ForcePathStyle=true&region=garage"
+<% end %>
\ No newline at end of file
diff --git a/config/application.sample.yml b/config/application.sample.yml
index 2cd58ec221e6b9b33726f8293592326b466df439..3934469262b923aab3261c10583e93d661c2d35c 100644
--- a/config/application.sample.yml
+++ b/config/application.sample.yml
@@ -36,6 +36,9 @@ UNSPLASH_ACCESS_KEY:
 UNSPLASH_SECRET:
 PEXELS_API_KEY:
 
+DEUXFLEURS_USER: 
+DEUXFLEURS_PASSWORD: 
+
 MAINTENANCE: "false"
 
 # Pour les tests automatisés
diff --git a/config/locales/communication/en.yml b/config/locales/communication/en.yml
index 9d09b977b1ed25cfd9e395a65978c36edd12f9f1..dedce9b308a9229e75e7b3912a07a93a502da7a6 100644
--- a/config/locales/communication/en.yml
+++ b/config/locales/communication/en.yml
@@ -138,6 +138,8 @@ en:
         created_at: Creation
         default_language: Default language
         deployment_status_badge: Deployment status badge
+        deuxfleurs_hosting: Hébergement avec Deuxfleurs
+        deuxfleurs_identifier: Identifiant Deuxfleurs
         features: Features
         feature_posts: Posts
         feature_agenda: Agenda
@@ -296,6 +298,7 @@ en:
     website:
       analytics: Analytics
       git: Git
+      hosting: Hosting
       imported:
         from: Imported from
         launch: Launch import
diff --git a/config/locales/communication/fr.yml b/config/locales/communication/fr.yml
index fae233bd00eda971da6c2a24c163d8727fab5584..5f4f1f0d35f833ef4a611e6b002be31d54c584cf 100644
--- a/config/locales/communication/fr.yml
+++ b/config/locales/communication/fr.yml
@@ -138,6 +138,8 @@ fr:
         created_at: Création
         default_language: Langue par défaut
         deployment_status_badge: Badge de statut du déploiement
+        deuxfleurs_hosting: Hébergement avec Deuxfleurs
+        deuxfleurs_identifier: Identifiant Deuxfleurs
         features: Fonctionnalités
         feature_posts: Actualités
         feature_agenda: Agenda
@@ -296,6 +298,7 @@ fr:
     website:
       analytics: Analytics
       git: Git
+      hosting: Hébergement
       imported:
         from: Importé depuis
         launch: Importer le site
diff --git a/db/migrate/20230925144224_add_deuxfleurs_to_websites.rb b/db/migrate/20230925144224_add_deuxfleurs_to_websites.rb
new file mode 100644
index 0000000000000000000000000000000000000000..55cecf2e3c53b8d0e8ae91baf72b10e6dfe3ed37
--- /dev/null
+++ b/db/migrate/20230925144224_add_deuxfleurs_to_websites.rb
@@ -0,0 +1,6 @@
+class AddDeuxfleursToWebsites < ActiveRecord::Migration[7.0]
+  def change
+    add_column :communication_websites, :deuxfleurs_hosting, :boolean, default: false
+    add_column :communication_websites, :deuxfleurs_id, :string
+  end
+end
diff --git a/db/migrate/20230926101310_change_id_to_identifier.rb b/db/migrate/20230926101310_change_id_to_identifier.rb
new file mode 100644
index 0000000000000000000000000000000000000000..32ab2e09a96f852223dd3b915f0b4c5997493baf
--- /dev/null
+++ b/db/migrate/20230926101310_change_id_to_identifier.rb
@@ -0,0 +1,5 @@
+class ChangeIdToIdentifier < ActiveRecord::Migration[7.0]
+  def change
+    rename_column :communication_websites, :deuxfleurs_id, :deuxfleurs_identifier
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 10b2f9dba3fa6b50d6b72e51de8761fefdd7641c..9a009c6a89a7873a756618e29bcec393c9ee9df7 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema[7.0].define(version: 2023_09_25_125538) do
+ActiveRecord::Schema[7.0].define(version: 2023_09_26_101310) do
   # These are extensions that must be enabled in order to support this database
   enable_extension "pgcrypto"
   enable_extension "plpgsql"
@@ -561,6 +561,8 @@ ActiveRecord::Schema[7.0].define(version: 2023_09_25_125538) do
     t.string "social_instagram"
     t.string "social_facebook"
     t.string "social_tiktok"
+    t.boolean "deuxfleurs_hosting", default: false
+    t.string "deuxfleurs_identifier"
     t.index ["about_type", "about_id"], name: "index_communication_websites_on_about"
     t.index ["default_language_id"], name: "index_communication_websites_on_default_language_id"
     t.index ["university_id"], name: "index_communication_websites_on_university_id"
diff --git a/test/fixtures/communication/websites.yml b/test/fixtures/communication/websites.yml
index e4a7fe2de9e4f78663e7a3fb0453d4defbef5be2..2a1950c6351c60273cde1153e1a172b3a01ab7ce 100644
--- a/test/fixtures/communication/websites.yml
+++ b/test/fixtures/communication/websites.yml
@@ -7,6 +7,8 @@
 #  access_token            :string
 #  autoupdate_theme        :boolean          default(TRUE)
 #  deployment_status_badge :text
+#  deuxfleurs_hosting      :boolean          default(FALSE)
+#  deuxfleurs_identifier   :string
 #  feature_agenda          :boolean          default(FALSE)
 #  feature_posts           :boolean          default(TRUE)
 #  git_branch              :string