diff --git a/app/controllers/admin/education/program/roles_controller.rb b/app/controllers/admin/education/program/roles_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b3488e4ad86c359ce2404b33cffcc1b10c3a5450
--- /dev/null
+++ b/app/controllers/admin/education/program/roles_controller.rb
@@ -0,0 +1,54 @@
+class Admin::Education::Program::RolesController < Admin::Education::Program::ApplicationController
+  load_and_authorize_resource class: Education::Program::Role, through: :program
+
+  def show
+    breadcrumb
+  end
+
+  def new
+    breadcrumb
+  end
+
+  def edit
+    breadcrumb
+    add_breadcrumb t('edit')
+  end
+
+  def create
+    if @role.save
+      redirect_to admin_education_program_role_path(@role), notice: t('admin.successfully_created_html', model: @role.to_s)
+    else
+      breadcrumb
+      render :new, status: :unprocessable_entity
+    end
+  end
+
+  def update
+    if @role.update(role_params)
+      redirect_to admin_education_program_role_path(@role), notice: t('admin.successfully_updated_html', model: @role.to_s)
+    else
+      breadcrumb
+      render :edit, status: :unprocessable_entity
+      add_breadcrumb t('edit')
+    end
+  end
+
+  def destroy
+    @role.destroy
+    redirect_to admin_education_program_path(@program), notice: t('admin.successfully_destroyed_html', model: @role.to_s)
+  end
+
+  protected
+
+  def breadcrumb
+    super
+    add_breadcrumb Education::Program::Role.model_name.human(count: 2)
+    breadcrumb_for @role
+  end
+
+  def role_params
+    params.require(:education_program_role)
+          .permit(:title)
+          .merge(program_id: @program.id, university_id: current_university.id)
+  end
+end
diff --git a/app/models/education/program/role.rb b/app/models/education/program/role.rb
index 2bb9dd6c76c02b20e6f2efcb39c8158d68e926a7..5a0365f34fd024730760fe4298958fd0c9d4c693 100644
--- a/app/models/education/program/role.rb
+++ b/app/models/education/program/role.rb
@@ -26,6 +26,10 @@ class Education::Program::Role < ApplicationRecord
   belongs_to :university
   belongs_to :program, class_name: 'Education::Program'
 
+  def to_s
+    "#{title}"
+  end
+
   protected
 
   def last_ordered_element
diff --git a/app/views/admin/education/program/roles/_form.html.erb b/app/views/admin/education/program/roles/_form.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..26ccb783e9660e9a9c21fdeab7c8088934d0a0c9
--- /dev/null
+++ b/app/views/admin/education/program/roles/_form.html.erb
@@ -0,0 +1,17 @@
+<%= simple_form_for [:admin, role] do |f| %>
+  <div class="row">
+    <div class="col-md-8">
+      <div class="card flex-fill w-100">
+        <div class="card-header">
+          <h5 class="card-title mb-0"><%= t('admin.infos') %></h5>
+        </div>
+        <div class="card-body">
+          <%= f.input :title %>
+        </div>
+      </div>
+    </div>
+  </div>
+  <% content_for :action_bar_right do %>
+    <%= submit f %>
+  <% end %>
+<% end %>
diff --git a/app/views/admin/education/program/roles/_list.html.erb b/app/views/admin/education/program/roles/_list.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..b3a3b5fee618931e112cf5e7958f796ff8e657cb
--- /dev/null
+++ b/app/views/admin/education/program/roles/_list.html.erb
@@ -0,0 +1,31 @@
+<table class="table">
+  <thead>
+    <tr>
+      <th><%= Education::Program::Role.model_name.human %></th>
+      <th></th>
+    </tr>
+  </thead>
+  <tbody>
+    <% roles.each do |role| %>
+      <tr>
+        <td>
+          <%= link_to_if  can?(:read, role),
+                          role,
+                          admin_education_program_role_path(role, { program_id: @program.id }) %>
+        </td>
+        <td class="text-end pe-0">
+          <div class="btn-group" role="group">
+            <%= link_to t('edit'),
+                        edit_admin_education_program_role_path(role, { program_id: @program.id }),
+                        class: button_classes %>
+            <%= link_to t('delete'),
+                        admin_education_program_role_path(role, { program_id: @program.id }),
+                        method: :delete,
+                        data: { confirm: t('please_confirm') },
+                        class: button_classes_danger %>
+          </div>
+        </td>
+      </tr>
+    <% end %>
+  </tbody>
+</table>
diff --git a/app/views/admin/education/program/roles/edit.html.erb b/app/views/admin/education/program/roles/edit.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..ff1ec73bd6f1465a96497606080d481b6fd6ca51
--- /dev/null
+++ b/app/views/admin/education/program/roles/edit.html.erb
@@ -0,0 +1,3 @@
+<% content_for :title, @role %>
+
+<%= render 'form', role: @role %>
diff --git a/app/views/admin/education/program/roles/new.html.erb b/app/views/admin/education/program/roles/new.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..1bad6fa6b7171dc693ea7eeb1652b264eca17d07
--- /dev/null
+++ b/app/views/admin/education/program/roles/new.html.erb
@@ -0,0 +1,3 @@
+<% content_for :title, Education::Program::Role.model_name.human %>
+
+<%= render 'form', role: @role %>
diff --git a/app/views/admin/education/program/roles/show.html.erb b/app/views/admin/education/program/roles/show.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..e6d4117f32fda150675fcedacdeab4a3c54ae5d0
--- /dev/null
+++ b/app/views/admin/education/program/roles/show.html.erb
@@ -0,0 +1,19 @@
+<% content_for :title, @role %>
+
+<div class="row">
+  <div class="col-md-4">
+    <div class="card flex-fill w-100">
+      <div class="card-header">
+        <h2 class="card-title mb-0 h5"><%= t('admin.infos') %></h2>
+      </div>
+      <div class="card-body">
+        <h3 class="h5"><%= Education::Program::Role.human_attribute_name('title') %></h3>
+        <%= @role.title %>
+      </div>
+    </div>
+  </div>
+</div>
+
+<% content_for :action_bar_right do %>
+  <%= edit_link @role %>
+<% end %>
diff --git a/app/views/admin/education/program/teachers/_list.html.erb b/app/views/admin/education/program/teachers/_list.html.erb
new file mode 100644
index 0000000000000000000000000000000000000000..9bd8965dfed39198d4fcd9a72a8dc946f4be1101
--- /dev/null
+++ b/app/views/admin/education/program/teachers/_list.html.erb
@@ -0,0 +1,33 @@
+<table class="table">
+  <thead>
+    <tr>
+      <th><%= Education::Program::Teacher.model_name.human %></th>
+      <th><%= Education::Program::Teacher.human_attribute_name('description') %></th>
+      <th></th>
+    </tr>
+  </thead>
+  <tbody>
+    <% teachers.each do |teacher| %>
+      <tr>
+        <td>
+          <%= link_to_if  can?(:read, teacher.person),
+                          teacher.person,
+                          admin_education_teacher_path(teacher.person) %>
+        </td>
+        <td><%= teacher.description %></td>
+        <td class="text-end pe-0">
+          <div class="btn-group" role="group">
+            <%= link_to t('edit'),
+                        edit_admin_education_program_teacher_path(teacher, { program_id: @program.id }),
+                        class: button_classes %>
+            <%= link_to t('delete'),
+                        admin_education_program_teacher_path(teacher, { program_id: @program.id }),
+                        method: :delete,
+                        data: { confirm: t('please_confirm') },
+                        class: button_classes_danger %>
+          </div>
+        </td>
+      </tr>
+    <% end %>
+  </tbody>
+</table>
diff --git a/app/views/admin/education/programs/show.html.erb b/app/views/admin/education/programs/show.html.erb
index a97ddb9cf76eb9d0409c9af2edfe1887cb044a57..355231df10da4dce55ae6f2b90dbbc86f68b8edf 100644
--- a/app/views/admin/education/programs/show.html.erb
+++ b/app/views/admin/education/programs/show.html.erb
@@ -93,46 +93,25 @@
           <%= @program.public_send prop %>
           <% i += 1 %>
         <% end %>
+
         <h3 class="h5 <%= 'mt-4' if i > 0 %>"><%= Education::Program.human_attribute_name('teachers') %></h3>
         <p><%= link_to t('create'), new_admin_education_program_teacher_path(program_id: @program.id), class: 'btn btn-primary' %></p>
-        <table class="table">
-          <thead>
-            <tr>
-              <th><%= Education::Program::Teacher.model_name.human %></th>
-              <th><%= Education::Program::Teacher.human_attribute_name('description') %></th>
-              <th></th>
-            </tr>
-          </thead>
-          <tbody>
-            <% @program.teachers.includes(:person).ordered.each do |teacher| %>
-              <tr>
-                <td>
-                  <%= link_to_if  can?(:read, teacher.person),
-                                  teacher.person,
-                                  admin_education_teacher_path(teacher.person) %>
-                </td>
-                <td><%= teacher.description %></td>
-                <td class="text-end pe-0">
-                  <div class="btn-group" role="group">
-                    <%= link_to t('edit'),
-                                edit_admin_education_program_teacher_path(teacher, { program_id: @program.id }),
-                                class: button_classes %>
-                    <%= link_to t('delete'),
-                                admin_education_program_teacher_path(teacher, { program_id: @program.id }),
-                                method: :delete,
-                                data: { confirm: t('please_confirm') },
-                                class: button_classes_danger %>
-                  </div>
-                </td>
-              </tr>
-            <% end %>
-          </tbody>
-        </table>
+        <%= render 'admin/education/program/teachers/list', teachers: @program.teachers.includes(:person).ordered %>
       </div>
     </div>
   </div>
 </div>
 
+<div class="card flex-fill w-100">
+  <div class="card-header">
+    <h5 class="card-title mb-0"><%= Education::Program.human_attribute_name('roles') %></h5>
+  </div>
+  <div class="card-body">
+    <p><%= link_to t('create'), new_admin_education_program_role_path(program_id: @program.id), class: 'btn btn-primary' %></p>
+    <%= render 'admin/education/program/roles/list', roles: @program.roles.ordered %>
+  </div>
+</div>
+
 <% if @program.children.any? %>
   <div class="card flex-fill w-100">
     <div class="card-header">
diff --git a/config/locales/education/en.yml b/config/locales/education/en.yml
index fd30ffcd168332785b304ac0bb935ecc5f2c2fc2..a5e6d3c66d384495ce2d0d80a1bd3e996a457c0a 100644
--- a/config/locales/education/en.yml
+++ b/config/locales/education/en.yml
@@ -7,6 +7,9 @@ en:
       education/program:
         one: Program
         other: Programs
+      education/program/role:
+        one: Role
+        other: Roles
       education/program/teacher:
         one: Teacher
         other: Teachers
@@ -35,9 +38,13 @@ en:
         pricing: Tarifs
         published: Published?
         registration: Modalités et délais d’accès
+        roles: Roles
         schools: Schools with this formation
         teachers: Teachers
         team: Team
+      education/program/role:
+        people: People
+        title: Title
       education/program/teacher:
         description: Description
         person: Person
diff --git a/config/locales/education/fr.yml b/config/locales/education/fr.yml
index dd27c981a4268c0e46e646bea0c38c16c2eaf05f..3240cf6daa7a2a2069f8f1fa1cd60ba6982dee38 100644
--- a/config/locales/education/fr.yml
+++ b/config/locales/education/fr.yml
@@ -7,9 +7,12 @@ fr:
       education/program:
         one: Formation
         other: Formations
+      education/program/role:
+        one: Rôle
+        other: Rôles
       education/program/teacher:
-        one: Enseignant
-        other: Enseignants
+        one: Enseignant·e
+        other: Enseignants·es
       education/school:
         one: École
         other: Écoles
@@ -35,9 +38,13 @@ fr:
         pricing: Tarifs
         published: Publiée ?
         registration: Modalités et délais d’accès
+        roles: Rôles
         schools: Écoles proposant cette formation
         teachers: Enseignants·es
         team: Équipe
+      education/program/role:
+        people: Personnes
+        title: Titre
       education/program/teacher:
         description: Description
         person: Personne
@@ -57,6 +64,9 @@ fr:
       educational_informations: Informations pédagogiques
       main_informations: Informations essentielles
       useful_informations: Informations pratiques
+    roles:
+      one: Rôle
+      other: Rôles
     teachers:
       one: Enseignant·e
       other: Enseignants·es
diff --git a/config/routes/admin/education.rb b/config/routes/admin/education.rb
index 115919b3d952703d5df46725d560133c7cb0526d..75ca3697efed49b6227f94127c53190c52936003 100644
--- a/config/routes/admin/education.rb
+++ b/config/routes/admin/education.rb
@@ -2,6 +2,7 @@ namespace :education do
   resources :teachers, only: [:index, :show]
   resources :schools
   resources :programs do
+    resources :roles, controller: 'program/roles', except: :index
     resources :teachers, controller: 'program/teachers', except: [:index, :show]
     collection do
       post :reorder