diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index fd4d8c514ff3eecf025f2378286d6b4116b2529c..d0d43a439b800d3b58b32b6d1408f7712c1411ce 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -3,5 +3,7 @@
 //= require bootstrap-sprockets
 //= require jquery3
 //= require jquery_ujs
+//= require cropperjs/dist/cropper
+//= require jquery-cropper/dist/jquery-cropper
 //= require simple_form_password_with_hints
 //= require simple_form_bs5_file_input
diff --git a/app/assets/stylesheets/admin/appstack.sass b/app/assets/stylesheets/admin/appstack.sass
new file mode 100644
index 0000000000000000000000000000000000000000..27dbe490da6d53ea1db49d87ec5b4aebf64b15d0
--- /dev/null
+++ b/app/assets/stylesheets/admin/appstack.sass
@@ -0,0 +1,8 @@
+main.content
+    padding-bottom: 65px
+
+.footer.fixed
+    bottom: 0
+    left: 260px
+    position: fixed
+    right: 0
diff --git a/app/assets/stylesheets/admin/styles.sass b/app/assets/stylesheets/admin/styles.sass
index 16b3d9b0a4f1b1d8da4c6c1ec326df5e98fe7a55..8178a52174984b4940d2e979626a7654a75006b2 100644
--- a/app/assets/stylesheets/admin/styles.sass
+++ b/app/assets/stylesheets/admin/styles.sass
@@ -9,9 +9,9 @@ h1
 .sidebar-content
     background-color: black
     background-image: asset-url('sun.svg')
-    background-repeat: no-repeat
     background-position-x: center
     background-position-y: -420px
+    background-repeat: no-repeat
     background-size: 400%
 .sidebar-brand
     padding: 90px 80px 120px
diff --git a/app/assets/stylesheets/adminserver.sass b/app/assets/stylesheets/adminserver.sass
deleted file mode 100644
index d484bedaa6470925a3a405c85b84f9d7999b70a5..0000000000000000000000000000000000000000
--- a/app/assets/stylesheets/adminserver.sass
+++ /dev/null
@@ -1,2 +0,0 @@
-@import 'appstack/light'
-@import 'admin/*'
diff --git a/app/assets/stylesheets/application.sass b/app/assets/stylesheets/application.sass
index dcef042038a01e996e939651a0ad07597cb883c7..b5505231df998e867116ddc0a89768d23426b58e 100644
--- a/app/assets/stylesheets/application.sass
+++ b/app/assets/stylesheets/application.sass
@@ -2,5 +2,6 @@
 @import 'appstack/light'
 @import 'simple_form_password_with_hints'
 @import 'simple_form_bs5_file_input'
+@import 'cropperjs/dist/cropper'
 @import 'commons/*'
 @import 'application/*'
diff --git a/app/controllers/server/universities_controller.rb b/app/controllers/server/universities_controller.rb
index ae7122d8df97d216d812608ef60182f98e63dd9d..233d9c288e0638d73d1703999de7df8f9d870398 100644
--- a/app/controllers/server/universities_controller.rb
+++ b/app/controllers/server/universities_controller.rb
@@ -57,6 +57,6 @@ class Server::UniversitiesController < Server::ApplicationController
   end
 
   def university_params
-    params.require(:university).permit(:name, :address, :zipcode, :city, :country, :private, :identifier)
+    params.require(:university).permit(:name, :address, :zipcode, :city, :country, :private, :identifier, :logo, :logo_delete)
   end
 end
diff --git a/app/models/university.rb b/app/models/university.rb
index a434400300ed7dc1f02d996af5b561ddeb1610c3..a067650891a686f0f014fb1dc06478938e2cb7df 100644
--- a/app/models/university.rb
+++ b/app/models/university.rb
@@ -19,11 +19,13 @@ class University < ApplicationRecord
   validates_presence_of :name
   scope :ordered, -> { order(:name) }
 
-  include WithIdentifier
-  include WithUsers
+  include WithCommunication
   include WithEducation
+  include WithIdentifier
   include WithResearch
-  include WithCommunication
+  include WithUsers
+
+  has_one_attached_deletable :logo
 
   def to_s
     "#{name}"
diff --git a/app/models/user/with_roles.rb b/app/models/user/with_roles.rb
index 635cac94847f5eef5a3f4e9e8ac0a428b8e6f049..59cfd936ceb12633b3cc9beec77d46a96e37e1c4 100644
--- a/app/models/user/with_roles.rb
+++ b/app/models/user/with_roles.rb
@@ -4,7 +4,7 @@ module User::WithRoles
   included do
     attr_accessor :modified_by
 
-    enum role: { visitor: 0, admin: 20, superadmin: 30 }
+    enum role: { visitor: 0, admin: 20, server_admin: 30 }
 
     scope :for_role, -> (role) { where(role: role) }
 
diff --git a/app/views/admin/application/_footer.html.erb b/app/views/admin/application/_footer.html.erb
index 34e022a16c6bffc6f677ac6f179a729cffc84f08..85dcc754f505f6d713c1f64cbc74ccf27736d1a2 100644
--- a/app/views/admin/application/_footer.html.erb
+++ b/app/views/admin/application/_footer.html.erb
@@ -1,29 +1,10 @@
-<footer class="footer">
-  <div class="container-fluid">
-    <div class="row text-muted">
-      <div class="col-6 text-start">
-        <ul class="list-inline">
-          <li class="list-inline-item">
-            <a class="text-muted" href="#">Support</a>
-          </li>
-          <li class="list-inline-item">
-            <a class="text-muted" href="#">Help Center</a>
-          </li>
-          <li class="list-inline-item">
-            <a class="text-muted" href="#">Privacy</a>
-          </li>
-          <li class="list-inline-item">
-            <a class="text-muted" href="#">Terms of Service</a>
-          </li>
-        </ul>
-      </div>
-      <div class="col-6 text-end">
-        <p class="mb-0">
-          <a href="https://www.osuny.org" target="_blank" rel="noreferrer">
-            <%= image_tag 'osuny-white.svg', width: 65 %>
-          </a>
-        </p>
-      </div>
+<% if content_for?(:action_bar_left) or content_for?(:action_bar_right) %>
+  <footer class="footer fixed">
+    <div class="float-start">
+      <%= yield :action_bar_left %>
     </div>
-  </div>
-</footer>
+    <div class="float-end">
+      <%= yield :action_bar_right %>
+    </div>
+  </footer>
+<% end %>
diff --git a/app/views/devise/confirmations/new.html.erb b/app/views/devise/confirmations/new.html.erb
index b1517851106720608dddb8c6d6834e4d8168df8a..e0413b71336486fe6995d1d72964d5d76ac90902 100644
--- a/app/views/devise/confirmations/new.html.erb
+++ b/app/views/devise/confirmations/new.html.erb
@@ -14,7 +14,6 @@
     <div class="col-md-6">
       <label class="form-label">&nbsp;</label><br>
       <%= f.button :submit, t(".resend_confirmation_instructions"), class: 'btn btn-primary' %>
-      <%= render "devise/shared/links" %>
     </div>
   </div>
 <% end %>
diff --git a/app/views/devise/passwords/edit.html.erb b/app/views/devise/passwords/edit.html.erb
index f9f48cfc05fb79764acdb5762afbff0ba3d37a09..6dfd0d076bbec8d6357628283feb8d13f7ab75d6 100644
--- a/app/views/devise/passwords/edit.html.erb
+++ b/app/views/devise/passwords/edit.html.erb
@@ -6,32 +6,32 @@
   <%= f.input :reset_password_token, as: :hidden %>
   <%= f.full_error :reset_password_token %>
 
-  <div class="form-inputs">
-    <%= f.input :password,
-                as: :password_with_hints,
-                label: t(".new_password"),
-                required: true,
-                autofocus: true,
-                allow_password_uncloaking: true,
-                validators: {
-                  length: Devise.password_length.first,
-                  uppercase_char: true,
-                  lowercase_char: true,
-                  numeric_char: true,
-                  special_char: Rails.application.config.allowed_special_chars
-                },
-                input_html: { autocomplete: "new-password" } %>
-    <%= f.input :password_confirmation,
-                as: :password_with_sync,
-                label: t(".confirm_new_password"),
-                required: true,
-                allow_password_uncloaking: true,
-                compare_with_field: :password,
-                input_html: { autocomplete: "new-password" } %>
-  </div>
-
-  <div class="form-actions">
-    <%= f.button :submit, t(".change_my_password"), class: 'btn btn-primary' %>
-    <%= render "devise/shared/links" %>
+  <div class="row">
+    <div class="col-md-6">
+      <%= f.input :password,
+                  as: :password_with_hints,
+                  label: t(".new_password"),
+                  required: true,
+                  autofocus: true,
+                  allow_password_uncloaking: true,
+                  validators: {
+                    length: Devise.password_length.first,
+                    uppercase_char: true,
+                    lowercase_char: true,
+                    numeric_char: true,
+                    special_char: Rails.application.config.allowed_special_chars
+                  },
+                  input_html: { autocomplete: "new-password" } %>
+      <%= f.button :submit, t(".change_my_password"), class: 'btn btn-primary' %>
+    </div>
+    <div class="col-md-6">
+      <%= f.input :password_confirmation,
+                  as: :password_with_sync,
+                  label: t(".confirm_new_password"),
+                  required: true,
+                  allow_password_uncloaking: true,
+                  compare_with_field: :password,
+                  input_html: { autocomplete: "new-password" } %>
+    </div>
   </div>
 <% end %>
diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb
index a708f5e6a11ee3e82a439aafe8bc67538db4f6ec..6a26084622965182e80d70984d75e9f2f531888b 100644
--- a/app/views/devise/passwords/new.html.erb
+++ b/app/views/devise/passwords/new.html.erb
@@ -13,7 +13,6 @@
     <div class="col-md-6">
       <label class="form-label">&nbsp;</label><br>
       <%= f.button :submit, t(".send_me_reset_password_instructions"), class: 'btn btn-primary' %>
-      <%= render "devise/shared/links" %>
     </div>
   </div>
 <% end %>
diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb
index 56b1081e0a1054dc6521326ab2e14c12c895eab7..4e94477c8a43c88939f1a024ade31c34d960b6c2 100644
--- a/app/views/devise/registrations/edit.html.erb
+++ b/app/views/devise/registrations/edit.html.erb
@@ -36,11 +36,11 @@
       <% end %>
     </div>
   </div>
-  <%= f.button :submit, t(".update"), class: 'btn btn-primary' %>
+  <% content_for :action_bar_right do %>
+    <%= f.button :submit, t(".update"), class: 'btn btn-primary' %>
+  <% end %>
 <% end %>
 
 <h3 class="mt-5 mb-4"><%= t(".cancel_my_account") %></h3>
 
 <p><%= t(".unhappy") %> <%= link_to t(".cancel_my_account"), registration_path(resource_name), data: { confirm: t(".are_you_sure") }, method: :delete %></p>
-
-<%= link_to t("devise.shared.links.back"), :back %>
diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb
index 1e79c849000b4a56943a12830b27b743bb484f73..5aa32d8310649bf868e4a149b5eefc191a1979c8 100644
--- a/app/views/devise/registrations/new.html.erb
+++ b/app/views/devise/registrations/new.html.erb
@@ -41,10 +41,11 @@
                   input_html: { autocomplete: "new-password" } %>
       <%= f.input :picture,
                         as: :single_deletable_file,
-                        input_html: { accept: '.png' } %>
+                        input_html: { accept: '.jpg,.jpeg,.png' },
+                        preview: 200,
+                        resize: 1,
+                        direct_upload: true %>
     </div>
   </div>
   <%= f.button :submit, t(".sign_up"), class: 'btn btn-primary' %>
 <% end %>
-
-<%= render "devise/shared/links" %>
diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb
index 9e9222d0766e18e7c47337c748fb98a73387e9a6..691715882917faff3e85378614de7146a79cae07 100644
--- a/app/views/devise/sessions/new.html.erb
+++ b/app/views/devise/sessions/new.html.erb
@@ -16,7 +16,7 @@
                     required: false,
                     autofocus: true,
                     input_html: { autocomplete: "email" } %>
-        <div class="mb-3 password optional user_password">
+        <div class="mb-3 password optional user_password password_with_hints">
           <%= f.input :password,
                       as: :password_with_hints,
                       allow_password_uncloaking: true,
@@ -32,7 +32,17 @@
 
       <div class="form-actions">
         <%= f.button :submit, t(".sign_in"), class: 'btn btn-primary' %>
-        <%= render "devise/shared/links" %>
+
+        <div class="mt-3">
+
+          <% if devise_mapping.confirmable? %>
+            <%= link_to t('devise.shared.links.didn_t_receive_confirmation_instructions'), new_confirmation_path(resource_name) %><br />
+          <% end %>
+
+          <% if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) %>
+            <%= link_to t('devise.shared.links.didn_t_receive_unlock_instructions'), new_unlock_path(resource_name) %><br />
+          <% end %>
+        </div>
       </div>
     <% end %>
   </div>
diff --git a/app/views/devise/shared/_links.html.erb b/app/views/devise/shared/_links.html.erb
deleted file mode 100644
index c92bd18bcb3049b9ee91522430cf27afb2727e65..0000000000000000000000000000000000000000
--- a/app/views/devise/shared/_links.html.erb
+++ /dev/null
@@ -1,19 +0,0 @@
-<div class="mt-3">
-  <%- if controller_name != 'sessions' %>
-    <%= link_to t(".sign_in"), new_session_path(resource_name) %><br />
-  <% end %>
-
-  <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
-    <%= link_to t('.didn_t_receive_confirmation_instructions'), new_confirmation_path(resource_name) %><br />
-  <% end %>
-
-  <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
-    <%= link_to t('.didn_t_receive_unlock_instructions'), new_unlock_path(resource_name) %><br />
-  <% end %>
-
-  <%- if devise_mapping.omniauthable? %>
-    <%- resource_class.omniauth_providers.each do |provider| %>
-      <%= link_to t('.sign_in_with_provider', provider: OmniAuth::Utils.camelize(provider)), omniauth_authorize_path(resource_name, provider), method: :post %><br />
-    <% end %>
-  <% end %>
-</div>
diff --git a/app/views/devise/unlocks/new.html.erb b/app/views/devise/unlocks/new.html.erb
index e5086ff9421df6b32dba624a286429f0cc878c70..75388e5567465268245d7e92411b5564b943bca2 100644
--- a/app/views/devise/unlocks/new.html.erb
+++ b/app/views/devise/unlocks/new.html.erb
@@ -13,7 +13,6 @@
     <div class="col-md-6">
       <label class="form-label">&nbsp;</label><br>
       <%= f.button :submit, t(".resend_unlock_instructions"), class: 'btn btn-primary' %>
-      <%= render "devise/shared/links" %>
     </div>
   </div>
 <% end %>
diff --git a/app/views/layouts/devise.html.erb b/app/views/layouts/devise.html.erb
index 4680876320b28a49e7e7132b51e66a00393d6901..f41e67ebfb02d55b5bf01960ff390291688efd61 100644
--- a/app/views/layouts/devise.html.erb
+++ b/app/views/layouts/devise.html.erb
@@ -14,7 +14,9 @@
     <div class="container">
       <div class="row">
         <div class="col-sm-10 mx-auto">
-          <h1 class="my-5 py-5 text-center"><%= current_university %></h1>
+          <h1 class="my-5 py-5 text-center">
+            <%= link_to current_university, root_path %>
+          </h1>
           <div class="card">
             <div class="card-body text-start">
               <% unless notice.blank? %>
diff --git a/app/views/server/layouts/application.html.erb b/app/views/server/layouts/application.html.erb
index 717e1cb71b6e5b77c12c37b6be7a12abdef5c684..840db98db1396fb0978c5c672802faa31d620550 100644
--- a/app/views/server/layouts/application.html.erb
+++ b/app/views/server/layouts/application.html.erb
@@ -8,7 +8,7 @@
     <%= csrf_meta_tags %>
     <%= csp_meta_tag %>
   	<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500&display=swap" rel="stylesheet">
-    <%= stylesheet_link_tag 'adminserver', media: 'all' %>
+    <%= stylesheet_link_tag 'admin', media: 'all' %>
     <%= favicon_link_tag 'favicon.png' %>
   </head>
 
diff --git a/app/views/server/universities/_form.html.erb b/app/views/server/universities/_form.html.erb
index 37699903e2fe1d1f9d3e1f71d56cd79b925e115f..136c8d11afec21f0ce62c755b8716fb60d0f6e38 100644
--- a/app/views/server/universities/_form.html.erb
+++ b/app/views/server/universities/_form.html.erb
@@ -5,7 +5,7 @@
       <%= f.input :identifier %>
       <%= f.input :private %>
     </div>
-    <div class="col-md-8">
+    <div class="col-md-4">
       <%= f.input :address %>
       <div class="row">
         <div class="col-md-4">
@@ -17,6 +17,13 @@
       </div>
       <%= f.input :country %>
     </div>
+    <div class="col-md-4">
+      <%= f.input :logo,
+                  as: :single_deletable_file,
+                  input_html: { accept: '.jpg,.jpeg,.png,.svg' },
+                  preview: 200,
+                  direct_upload: true %>
+    </div>
   </div>
   <% content_for :buttons do %>
     <%= submit f %>
diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb
index 4b828e80cb778244843194acf5f8a74238ec2c13..be3e6588af329336c2a22e8678885101fe10cfd2 100644
--- a/config/initializers/assets.rb
+++ b/config/initializers/assets.rb
@@ -12,3 +12,5 @@ Rails.application.config.assets.paths << Rails.root.join('node_modules')
 # application.js, application.css, and all non-JS/CSS in the app/assets
 # folder are already added.
 # Rails.application.config.assets.precompile += %w( admin.js admin.css )
+
+Rails.application.config.assets.export_concurrent = false
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 8a22bcef3fa6762d7177ced7b9ecab32f3cb936a..6687df3c22e62930901a0ca66a4e0df2f1e16b18 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -37,6 +37,7 @@ en:
     failure:
       invalid: "Invalid email or password."
       not_found_in_database: "Invalid email or password."
+      unauthenticated: ''
     mailer:
       two_factor_authentication_code:
         subject: "Two-factor authentication code"
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 8dbc00d51a45ba2f5da2ed0c3da2bfa51040e32e..6d9606c5dc7fa76fe5d8e71d0854e346a310cd26 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -37,6 +37,7 @@ fr:
     failure:
       invalid: "Email ou mot de passe incorrect."
       not_found_in_database: "Email ou mot de passe incorrect."
+      unauthenticated: ''
     mailer:
       two_factor_authentication_code:
         subject: "Code d'authentification à deux facteurs"