ajoute le portail Laravel : connexion prof/élève, session unique, gestion de classe, salle d'attente
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
aa31b6112f
commit
30e14b1c54
191 changed files with 25324 additions and 0 deletions
8
ansible/roles/portail/defaults/main.yml
Normal file
8
ansible/roles/portail/defaults/main.yml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
portail_mysql_port: 3307
|
||||
portail_redis_port: 6380
|
||||
portail_mysql_database: portail
|
||||
portail_mysql_user: portail
|
||||
portail_dossier_docker: /etc/portail
|
||||
portail_dossier_app: /var/www/portail
|
||||
portail_php_version: "8.3"
|
||||
4
ansible/roles/portail/handlers/main.yml
Normal file
4
ansible/roles/portail/handlers/main.yml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
- name: recharger nginx
|
||||
ansible.builtin.shell: nginx -t && systemctl reload nginx
|
||||
changed_when: true
|
||||
91
ansible/roles/portail/tasks/01-systeme.yml
Normal file
91
ansible/roles/portail/tasks/01-systeme.yml
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
---
|
||||
- name: installer les prérequis pour le dépôt PHP Sury
|
||||
ansible.builtin.apt:
|
||||
name: [lsb-release, ca-certificates, curl, gnupg, rsync]
|
||||
state: present
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
|
||||
- name: télécharger le trousseau de clés du dépôt Sury
|
||||
ansible.builtin.get_url:
|
||||
url: https://packages.sury.org/debsuryorg-archive-keyring.deb
|
||||
dest: /tmp/debsuryorg-archive-keyring.deb
|
||||
mode: "0644"
|
||||
|
||||
- name: installer le trousseau de clés Sury
|
||||
ansible.builtin.apt:
|
||||
deb: /tmp/debsuryorg-archive-keyring.deb
|
||||
state: present
|
||||
|
||||
- name: ajouter le dépôt PHP Sury
|
||||
ansible.builtin.apt_repository:
|
||||
repo: "deb [signed-by=/usr/share/keyrings/debsuryorg-archive-keyring.gpg] https://packages.sury.org/php/ {{ ansible_distribution_release }} main"
|
||||
filename: php
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: installer PHP {{ portail_php_version }}, Nginx et les extensions nécessaires
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- "php{{ portail_php_version }}-fpm"
|
||||
- "php{{ portail_php_version }}-cli"
|
||||
- "php{{ portail_php_version }}-mysql"
|
||||
- "php{{ portail_php_version }}-redis"
|
||||
- "php{{ portail_php_version }}-mbstring"
|
||||
- "php{{ portail_php_version }}-xml"
|
||||
- "php{{ portail_php_version }}-curl"
|
||||
- "php{{ portail_php_version }}-zip"
|
||||
- "php{{ portail_php_version }}-bcmath"
|
||||
- "php{{ portail_php_version }}-gd"
|
||||
- "php{{ portail_php_version }}-intl"
|
||||
- "php{{ portail_php_version }}-opcache"
|
||||
- nginx
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: installer Composer (avec vérification de la somme d'installation officielle)
|
||||
block:
|
||||
- name: télécharger le programme d'installation de Composer
|
||||
ansible.builtin.get_url:
|
||||
url: https://getcomposer.org/installer
|
||||
dest: /tmp/composer-setup.php
|
||||
mode: "0644"
|
||||
|
||||
- name: récupérer la somme SHA384 officielle
|
||||
ansible.builtin.uri:
|
||||
url: https://composer.github.io/installer.sig
|
||||
return_content: true
|
||||
register: portail_composer_signature
|
||||
when: not (ansible_check_mode | default(false))
|
||||
|
||||
- name: calculer la somme SHA384 du fichier téléchargé
|
||||
ansible.builtin.stat:
|
||||
path: /tmp/composer-setup.php
|
||||
checksum_algorithm: sha384
|
||||
register: portail_composer_setup_stat
|
||||
|
||||
- name: vérifier que la somme correspond (sinon, installateur corrompu)
|
||||
ansible.builtin.fail:
|
||||
msg: "La somme de l'installateur Composer ne correspond pas à la signature officielle : installation interrompue."
|
||||
when:
|
||||
- portail_composer_signature is defined
|
||||
- portail_composer_setup_stat.stat.checksum != portail_composer_signature.content.strip()
|
||||
|
||||
- name: installer Composer (dernière version stable)
|
||||
ansible.builtin.command:
|
||||
cmd: php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer
|
||||
args:
|
||||
creates: /usr/local/bin/composer
|
||||
|
||||
- name: installer Node.js 22 LTS (dépôt NodeSource)
|
||||
block:
|
||||
- name: ajouter le dépôt NodeSource
|
||||
ansible.builtin.shell:
|
||||
cmd: curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
|
||||
creates: /etc/apt/sources.list.d/nodesource.list
|
||||
|
||||
- name: installer nodejs
|
||||
ansible.builtin.apt:
|
||||
name: nodejs
|
||||
state: present
|
||||
update_cache: true
|
||||
63
ansible/roles/portail/tasks/02-bases-donnees.yml
Normal file
63
ansible/roles/portail/tasks/02-bases-donnees.yml
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
---
|
||||
- name: créer le dossier de configuration Docker du portail
|
||||
ansible.builtin.file:
|
||||
path: "{{ portail_dossier_docker }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0750"
|
||||
|
||||
# Un seul fichier de secrets, nommé .env : docker compose le charge
|
||||
# automatiquement pour les substitutions ${...} de docker-compose.yml, et une
|
||||
# tâche plus loin le relit pour remplir le .env de Laravel avec les mêmes
|
||||
# valeurs (une seule source de vérité, jamais dans Git).
|
||||
- name: générer les secrets MariaDB/Redis de l'app (première fois seulement)
|
||||
ansible.builtin.copy:
|
||||
dest: "{{ portail_dossier_docker }}/.env"
|
||||
content: |
|
||||
MYSQL_ROOT_PASSWORD={{ lookup('community.general.random_string', length=32, special=false) }}
|
||||
MYSQL_PASSWORD={{ lookup('community.general.random_string', length=32, special=false) }}
|
||||
REDIS_PASSWORD={{ lookup('community.general.random_string', length=32, special=false) }}
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
force: false
|
||||
register: portail_secrets_generes
|
||||
|
||||
- name: lire les secrets générés
|
||||
ansible.builtin.slurp:
|
||||
src: "{{ portail_dossier_docker }}/.env"
|
||||
register: portail_secrets_brut
|
||||
|
||||
- name: "exposer les secrets comme variables (jamais affichées, no_log)"
|
||||
ansible.builtin.set_fact:
|
||||
portail_secrets: "{{ dict(portail_secrets_lignes | map('split', '=', 1)) }}"
|
||||
vars:
|
||||
portail_secrets_lignes: "{{ (portail_secrets_brut.content | b64decode).splitlines() | select('string') | list }}"
|
||||
no_log: true
|
||||
|
||||
- name: déployer docker-compose.yml (MariaDB + Redis de l'app)
|
||||
ansible.builtin.template:
|
||||
src: docker-compose.yml.j2
|
||||
dest: "{{ portail_dossier_docker }}/docker-compose.yml"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0640"
|
||||
vars:
|
||||
portail_mysql_root_password: "${MYSQL_ROOT_PASSWORD}"
|
||||
portail_mysql_password: "${MYSQL_PASSWORD}"
|
||||
portail_redis_password: "${REDIS_PASSWORD}"
|
||||
register: portail_compose_deploye
|
||||
|
||||
- name: démarrer MariaDB et Redis (app)
|
||||
community.docker.docker_compose_v2:
|
||||
project_src: "{{ portail_dossier_docker }}"
|
||||
state: present
|
||||
register: portail_compose_resultat
|
||||
|
||||
- name: attendre que MariaDB (app) accepte les connexions
|
||||
ansible.builtin.wait_for:
|
||||
host: 127.0.0.1
|
||||
port: "{{ portail_mysql_port }}"
|
||||
delay: 2
|
||||
timeout: 60
|
||||
113
ansible/roles/portail/tasks/03-code.yml
Normal file
113
ansible/roles/portail/tasks/03-code.yml
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
---
|
||||
- name: créer le dossier de l'application
|
||||
ansible.builtin.file:
|
||||
path: "{{ portail_dossier_app }}"
|
||||
state: directory
|
||||
owner: "{{ ansible_user }}"
|
||||
group: "{{ ansible_user }}"
|
||||
mode: "0755"
|
||||
|
||||
# storage/ et bootstrap/cache/ sont de l'état et du cache runtime, jamais du
|
||||
# code : on ne les synchronise jamais depuis le Mac (un rsync --delete les
|
||||
# effacerait sinon, y compris storage/app/ où atterriront plus tard les
|
||||
# travaux d'élèves). On crée leur structure une fois, puis on laisse
|
||||
# www-data (PHP-FPM) les posséder en continu.
|
||||
- name: créer la structure storage/ et bootstrap/cache/ (une seule fois)
|
||||
ansible.builtin.file:
|
||||
path: "{{ portail_dossier_app }}/{{ item }}"
|
||||
state: directory
|
||||
owner: www-data
|
||||
group: www-data
|
||||
mode: "0775"
|
||||
loop:
|
||||
- storage/app/public
|
||||
- storage/framework/cache/data
|
||||
- storage/framework/sessions
|
||||
- storage/framework/views
|
||||
- storage/logs
|
||||
- bootstrap/cache
|
||||
|
||||
- name: synchroniser le code du portail (sans vendor/node_modules/.env/storage)
|
||||
become: false
|
||||
ansible.posix.synchronize:
|
||||
src: "{{ playbook_dir }}/../portail/"
|
||||
dest: "{{ portail_dossier_app }}/"
|
||||
delete: true
|
||||
rsync_opts:
|
||||
- "--exclude=/vendor"
|
||||
- "--exclude=/node_modules"
|
||||
- "--exclude=/.env"
|
||||
- "--exclude=/database/database.sqlite"
|
||||
- "--exclude=/storage"
|
||||
- "--exclude=/bootstrap/cache"
|
||||
- "--exclude=/public/build"
|
||||
- "--exclude=/public/hot"
|
||||
- "--exclude=/.git"
|
||||
register: portail_code_synchronise
|
||||
|
||||
- name: installer les dépendances PHP (composer)
|
||||
ansible.builtin.command:
|
||||
cmd: composer install --no-dev --optimize-autoloader --no-interaction
|
||||
args:
|
||||
chdir: "{{ portail_dossier_app }}"
|
||||
environment:
|
||||
COMPOSER_ALLOW_SUPERUSER: "1"
|
||||
register: portail_composer_install_app
|
||||
changed_when: "'Nothing to install' not in portail_composer_install_app.stdout"
|
||||
|
||||
- name: vérifier si .env existe déjà
|
||||
ansible.builtin.stat:
|
||||
path: "{{ portail_dossier_app }}/.env"
|
||||
register: portail_env_stat
|
||||
|
||||
- name: générer une clé d'application (une seule fois)
|
||||
ansible.builtin.command:
|
||||
cmd: php artisan key:generate --show
|
||||
args:
|
||||
chdir: "{{ portail_dossier_app }}"
|
||||
register: portail_app_key_generee
|
||||
when: not portail_env_stat.stat.exists
|
||||
changed_when: true
|
||||
|
||||
- name: déployer .env de production (une seule fois, jamais réécrit ensuite)
|
||||
ansible.builtin.template:
|
||||
src: env.production.j2
|
||||
dest: "{{ portail_dossier_app }}/.env"
|
||||
owner: "{{ ansible_user }}"
|
||||
group: www-data
|
||||
mode: "0640"
|
||||
vars:
|
||||
portail_app_key: "{{ portail_app_key_generee.stdout }}"
|
||||
portail_app_url: "http://{{ ansible_host }}"
|
||||
when: not portail_env_stat.stat.exists
|
||||
|
||||
- name: installer les dépendances JS (npm)
|
||||
ansible.builtin.command:
|
||||
cmd: npm ci
|
||||
args:
|
||||
chdir: "{{ portail_dossier_app }}"
|
||||
register: portail_npm_ci
|
||||
changed_when: true
|
||||
|
||||
- name: compiler les assets (vite build)
|
||||
ansible.builtin.command:
|
||||
cmd: npm run build
|
||||
args:
|
||||
chdir: "{{ portail_dossier_app }}"
|
||||
register: portail_npm_build
|
||||
changed_when: true
|
||||
|
||||
- name: appliquer les migrations
|
||||
ansible.builtin.command:
|
||||
cmd: php artisan migrate --force
|
||||
args:
|
||||
chdir: "{{ portail_dossier_app }}"
|
||||
register: portail_migrate
|
||||
changed_when: "'Nothing to migrate' not in portail_migrate.stdout"
|
||||
|
||||
- name: mettre en cache la configuration et les routes
|
||||
ansible.builtin.shell:
|
||||
cmd: php artisan config:cache && php artisan route:cache && php artisan view:cache
|
||||
args:
|
||||
chdir: "{{ portail_dossier_app }}"
|
||||
changed_when: true
|
||||
29
ansible/roles/portail/tasks/04-nginx.yml
Normal file
29
ansible/roles/portail/tasks/04-nginx.yml
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
- name: déployer le vhost Nginx du portail
|
||||
ansible.builtin.template:
|
||||
src: nginx-portail.conf.j2
|
||||
dest: /etc/nginx/sites-available/portail.conf
|
||||
mode: "0644"
|
||||
notify: recharger nginx
|
||||
|
||||
- name: activer le vhost
|
||||
ansible.builtin.file:
|
||||
src: /etc/nginx/sites-available/portail.conf
|
||||
dest: /etc/nginx/sites-enabled/portail.conf
|
||||
state: link
|
||||
notify: recharger nginx
|
||||
|
||||
- name: désactiver le vhost par défaut de Nginx
|
||||
ansible.builtin.file:
|
||||
path: /etc/nginx/sites-enabled/default
|
||||
state: absent
|
||||
notify: recharger nginx
|
||||
|
||||
- name: activer et démarrer php-fpm et nginx
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ item }}"
|
||||
enabled: true
|
||||
state: started
|
||||
loop:
|
||||
- "php{{ portail_php_version }}-fpm"
|
||||
- nginx
|
||||
12
ansible/roles/portail/tasks/main.yml
Normal file
12
ansible/roles/portail/tasks/main.yml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
- name: système (PHP, Nginx, Composer, Node)
|
||||
ansible.builtin.import_tasks: 01-systeme.yml
|
||||
|
||||
- name: bases de données de l'app (MariaDB, Redis)
|
||||
ansible.builtin.import_tasks: 02-bases-donnees.yml
|
||||
|
||||
- name: code de l'application
|
||||
ansible.builtin.import_tasks: 03-code.yml
|
||||
|
||||
- name: Nginx
|
||||
ansible.builtin.import_tasks: 04-nginx.yml
|
||||
28
ansible/roles/portail/templates/docker-compose.yml.j2
Normal file
28
ansible/roles/portail/templates/docker-compose.yml.j2
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
services:
|
||||
mariadb:
|
||||
image: mariadb:11
|
||||
container_name: portail_mariadb
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "127.0.0.1:{{ portail_mysql_port }}:3306"
|
||||
environment:
|
||||
MARIADB_ROOT_PASSWORD: "{{ portail_mysql_root_password }}"
|
||||
MARIADB_DATABASE: "{{ portail_mysql_database }}"
|
||||
MARIADB_USER: "{{ portail_mysql_user }}"
|
||||
MARIADB_PASSWORD: "{{ portail_mysql_password }}"
|
||||
volumes:
|
||||
- portail_mariadb_data:/var/lib/mysql
|
||||
|
||||
redis:
|
||||
image: redis:7
|
||||
container_name: portail_redis
|
||||
restart: unless-stopped
|
||||
command: ["redis-server", "--requirepass", "{{ portail_redis_password }}"]
|
||||
ports:
|
||||
- "127.0.0.1:{{ portail_redis_port }}:6379"
|
||||
volumes:
|
||||
- portail_redis_data:/data
|
||||
|
||||
volumes:
|
||||
portail_mariadb_data:
|
||||
portail_redis_data:
|
||||
29
ansible/roles/portail/templates/env.production.j2
Normal file
29
ansible/roles/portail/templates/env.production.j2
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
APP_NAME=Syllabus
|
||||
APP_ENV=production
|
||||
APP_KEY={{ portail_app_key }}
|
||||
APP_DEBUG=false
|
||||
APP_URL={{ portail_app_url }}
|
||||
|
||||
APP_LOCALE=fr
|
||||
APP_FALLBACK_LOCALE=fr
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_LEVEL=warning
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT={{ portail_mysql_port }}
|
||||
DB_DATABASE={{ portail_mysql_database }}
|
||||
DB_USERNAME={{ portail_mysql_user }}
|
||||
DB_PASSWORD={{ portail_secrets.MYSQL_PASSWORD }}
|
||||
|
||||
SESSION_DRIVER=redis
|
||||
SESSION_LIFETIME=120
|
||||
CACHE_STORE=redis
|
||||
QUEUE_CONNECTION=redis
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PORT={{ portail_redis_port }}
|
||||
REDIS_PASSWORD={{ portail_secrets.REDIS_PASSWORD }}
|
||||
|
||||
MAIL_MAILER=log
|
||||
28
ansible/roles/portail/templates/nginx-portail.conf.j2
Normal file
28
ansible/roles/portail/templates/nginx-portail.conf.j2
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name _;
|
||||
|
||||
root {{ portail_dossier_app }}/public;
|
||||
index index.php;
|
||||
|
||||
client_max_body_size 20m;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
fastcgi_pass unix:/run/php/php{{ portail_php_version }}-fpm.sock;
|
||||
fastcgi_index index.php;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
}
|
||||
|
||||
location ~ /\.(?!well-known) {
|
||||
deny all;
|
||||
}
|
||||
|
||||
access_log /var/log/nginx/portail-access.log;
|
||||
error_log /var/log/nginx/portail-error.log;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue