chore: update
This commit is contained in:
@@ -1,47 +1,37 @@
|
||||
postgres_version: "16"
|
||||
postgres_databases:
|
||||
- name: gestion_db
|
||||
owner: postgres
|
||||
postgres_password: "VotreMotDePasseSecure123!"
|
||||
|
||||
pg_version: "16"
|
||||
db_user: admin_gestion_commande_db
|
||||
db_name: gestion_commande_db
|
||||
db_password: "hb-FS462(#I~6(4',Nt=3Rd4567890jsezZ"
|
||||
db_host: "localhost"
|
||||
db_port: 5432
|
||||
# Redis Configuration
|
||||
redis_bind: "127.0.0.1"
|
||||
redis_port: 6379
|
||||
redis_maxmemory: "512mb"
|
||||
redis_maxmemory: "1024mb"
|
||||
redis_maxmemory_policy: "allkeys-lru"
|
||||
redis_password: "UltrasecretMdp123!"
|
||||
redis_password: "uQ64h5UhFdrm!H|_cCQer"
|
||||
|
||||
# ============================================
|
||||
# Configuration Nginx et Applications
|
||||
# ============================================
|
||||
nginx_app_name: "nantais-livraison"
|
||||
nginx_domain: "{{ ansible_default_ipv4.address }}"
|
||||
|
||||
directory: "/home/ubuntu"
|
||||
tunnel_log: "/var/log/tunnel.log"
|
||||
tunnel_log_error: "/var/log/tunnel-error.log"
|
||||
# Chemins des applications (bonnes pratiques)
|
||||
nginx_frontend_path: "/home/ubuntu/frontend"
|
||||
backend_dir: "/home/ubuntu/backend"
|
||||
backend_binary: "/home/ubuntu/backend/main"
|
||||
docker_dir: "/home/ubuntu/docker"
|
||||
uploads_dir: "/home/ubuntu/backend/uploads"
|
||||
frontend_port: 5173
|
||||
backend_dir_docker: "/home/ubuntu/backend/docker"
|
||||
domain_name: "uber-stup.club"
|
||||
# Utilisateurs et permissions
|
||||
user_web: "www-data" # Utilisateur pour les applications web
|
||||
user_deploy: "ubuntu" # Utilisateur pour le déploiement
|
||||
user_owner: "root" # Propriétaire des fichiers systemd
|
||||
docker_user: docker
|
||||
docker_group: docker
|
||||
# Backend
|
||||
backend_port: 8080
|
||||
|
||||
# Backend
|
||||
backend_local_port: 8080
|
||||
backend_port: 443
|
||||
# Timeouts
|
||||
nginx_proxy_timeout: 60
|
||||
|
||||
# Cache Duration
|
||||
nginx_cache_static_duration: "1y"
|
||||
nginx_cache_media_duration: "1y"
|
||||
|
||||
# Upload Size
|
||||
nginx_max_body_size: "10M"
|
||||
|
||||
|
||||
@@ -1,21 +1,5 @@
|
||||
[all]
|
||||
vm-postgres ansible_host=192.168.1.65 ansible_user=ubuntu ansible_ssh_pass=root
|
||||
vm-redis ansible_host=192.168.1.62 ansible_user=ubuntu ansible_ssh_pass=root
|
||||
vm-nginx ansible_host=192.168.1.67 ansible_user=ubuntu ansible_ssh_pass=root
|
||||
vm-backend ansible_host=192.168.1.72 ansible_user=ubuntu ansible_ssh_pass=root
|
||||
uber-stup ansible_host=5.252.20.129 ansible_user=root ansible_ssh_pass=rL9lY6YkcDQmfRuZ3Z
|
||||
|
||||
[postgres]
|
||||
vm-postgres ansible_host=192.168.1.65 ansible_user=ubuntu ansible_ssh_pass=root
|
||||
|
||||
[redis]
|
||||
vm-redis ansible_host=192.168.1.62 ansible_user=ubuntu ansible_ssh_pass=root
|
||||
|
||||
[nginx]
|
||||
vm-nginx ansible_host=192.168.1.67 ansible_user=ubuntu ansible_ssh_pass=root
|
||||
|
||||
[backend]
|
||||
vm-backend ansible_host=192.168.1.72 ansible_user=ubuntu ansible_ssh_pass=root
|
||||
|
||||
[services]
|
||||
vm-redis ansible_host=192.168.1.62 ansible_user=ubuntu ansible_ssh_pass=root
|
||||
vm-postgres ansible_host=192.168.1.65 ansible_user=ubuntu ansible_ssh_pass=root
|
||||
[uber-stup]
|
||||
uber-stup ansible_host=5.252.20.129 ansible_user=root ansible_ssh_pass=rL9lY6YkcDQmfRuZ3Z
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
- name: Installation et configuration du frontend et backend
|
||||
hosts: nginx
|
||||
hosts: all
|
||||
become: true
|
||||
gather_facts: true
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
- tar
|
||||
- rsync
|
||||
- acl
|
||||
- nginx
|
||||
- certbot
|
||||
- python3-certbot-nginx
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
||||
@@ -42,23 +45,8 @@
|
||||
state: present
|
||||
mode: "0644"
|
||||
|
||||
- name: Setup Node.js 20 repository
|
||||
- name: Check Go versions
|
||||
ansible.builtin.shell: |
|
||||
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
|
||||
args:
|
||||
executable: /bin/bash
|
||||
|
||||
- name: Install Node.js 20
|
||||
ansible.builtin.apt:
|
||||
name: nodejs
|
||||
state: present
|
||||
update_cache: yes
|
||||
dpkg_options: "force-overwrite"
|
||||
|
||||
- name: Check Node.js, npm and Go versions
|
||||
ansible.builtin.shell: |
|
||||
echo "Node: $(node -v)"
|
||||
echo "npm: $(npm -v)"
|
||||
echo "Go: $(go version)"
|
||||
register: versions_check
|
||||
changed_when: false
|
||||
@@ -80,68 +68,25 @@
|
||||
group: root
|
||||
mode: "0755"
|
||||
|
||||
- name: Ensure /home/ubuntu exists with correct permissions
|
||||
- name: Créer l'utilisateur de déploiement s'il n'existe pas
|
||||
ansible.builtin.user:
|
||||
name: "{{ user_deploy }}"
|
||||
shell: /bin/bash
|
||||
create_home: yes
|
||||
state: present
|
||||
|
||||
- name: Ensure /home/{{ user_deploy }} exists with correct permissions
|
||||
ansible.builtin.file:
|
||||
path: /home/ubuntu
|
||||
path: "/home/{{ user_deploy }}"
|
||||
state: directory
|
||||
owner: "{{ user_deploy }}"
|
||||
group: "{{ user_deploy }}"
|
||||
mode: "0755"
|
||||
|
||||
- name: Remove old frontend directory if exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ nginx_frontend_path }}"
|
||||
state: absent
|
||||
|
||||
- name: Create frontend directory with deploy user ownership
|
||||
ansible.builtin.file:
|
||||
path: "{{ nginx_frontend_path }}"
|
||||
state: directory
|
||||
owner: "{{ user_deploy }}"
|
||||
group: "{{ user_deploy }}"
|
||||
mode: "0755"
|
||||
|
||||
- name: Synchronize frontend content (excluding node_modules and .git)
|
||||
ansible.builtin.synchronize:
|
||||
src: ../frontend/
|
||||
dest: "{{ nginx_frontend_path }}/"
|
||||
rsync_opts:
|
||||
- "--exclude=node_modules"
|
||||
- "--exclude=.git"
|
||||
- "--exclude=dist"
|
||||
- "--exclude=build"
|
||||
delete: no
|
||||
recursive: yes
|
||||
tags:
|
||||
- syncro
|
||||
|
||||
- name: Install npm dependencies as deploy user
|
||||
become_user: "{{ user_deploy }}"
|
||||
ansible.builtin.shell: |
|
||||
export PATH=/usr/local/go/bin:$PATH
|
||||
npm install
|
||||
npm run build
|
||||
args:
|
||||
chdir: "{{ nginx_frontend_path }}"
|
||||
executable: /bin/bash
|
||||
|
||||
- name: Set ownership to www-data for runtime
|
||||
ansible.builtin.file:
|
||||
path: "{{ nginx_frontend_path }}"
|
||||
owner: "{{ user_web }}"
|
||||
group: "{{ user_web }}"
|
||||
mode: "0755"
|
||||
recurse: yes
|
||||
|
||||
# ============================================
|
||||
# BACKEND
|
||||
# ============================================
|
||||
|
||||
- name: Remove old backend directory if exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ backend_dir }}"
|
||||
state: absent
|
||||
|
||||
- name: Create backend directory with deploy user ownership
|
||||
ansible.builtin.file:
|
||||
path: "{{ backend_dir }}"
|
||||
@@ -149,15 +94,22 @@
|
||||
owner: "{{ user_deploy }}"
|
||||
group: "{{ user_deploy }}"
|
||||
mode: "0755"
|
||||
tags: backend
|
||||
|
||||
- name: Copy backend files
|
||||
ansible.builtin.copy:
|
||||
src: "../backendprod/gestion/"
|
||||
- name: Synchroniser le backend Go
|
||||
ansible.builtin.synchronize:
|
||||
src: ../backend/gestion/
|
||||
dest: "{{ backend_dir }}/"
|
||||
owner: "{{ user_deploy }}"
|
||||
group: "{{ user_deploy }}"
|
||||
mode: preserve
|
||||
directory_mode: "0755"
|
||||
rsync_opts:
|
||||
- "--exclude=.git"
|
||||
- "--exclude=.gitignore"
|
||||
- "--exclude=docker-compose.yml"
|
||||
- "--exclude=.env"
|
||||
- "--no-owner"
|
||||
- "--no-group"
|
||||
delete: yes
|
||||
recursive: yes
|
||||
tags: backend
|
||||
|
||||
- name: Compile backend as deploy user
|
||||
become_user: "{{ user_deploy }}"
|
||||
@@ -168,8 +120,8 @@
|
||||
args:
|
||||
chdir: "{{ backend_dir }}"
|
||||
executable: /bin/bash
|
||||
tags:
|
||||
- compile
|
||||
tags: backend
|
||||
|
||||
- name: Set ownership to www-data for runtime
|
||||
ansible.builtin.file:
|
||||
path: "{{ backend_dir }}"
|
||||
@@ -177,6 +129,7 @@
|
||||
group: "{{ user_web }}"
|
||||
mode: "0755"
|
||||
recurse: yes
|
||||
tags: backend
|
||||
|
||||
- name: Set executable permission on backend binary
|
||||
ansible.builtin.file:
|
||||
@@ -184,6 +137,7 @@
|
||||
owner: "{{ user_web }}"
|
||||
group: "{{ user_web }}"
|
||||
mode: "0755"
|
||||
tags: backend
|
||||
|
||||
# ============================================
|
||||
# SYSTEMD SERVICES
|
||||
@@ -196,39 +150,156 @@
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
tags: backend
|
||||
|
||||
- name: Reload systemd daemon
|
||||
ansible.builtin.systemd:
|
||||
daemon_reload: yes
|
||||
|
||||
- name: Enable and restart frontend service
|
||||
ansible.builtin.systemd:
|
||||
name: frontend
|
||||
enabled: yes
|
||||
state: restarted
|
||||
tags: backend
|
||||
|
||||
- name: Enable and restart backend service
|
||||
ansible.builtin.systemd:
|
||||
name: backend
|
||||
enabled: yes
|
||||
state: restarted
|
||||
tags: backend
|
||||
|
||||
- name: Wait for backend to be ready
|
||||
ansible.builtin.wait_for:
|
||||
port: "{{ backend_port }}"
|
||||
port: "{{ backend_local_port }}"
|
||||
delay: 2
|
||||
timeout: 30
|
||||
tags: backend
|
||||
|
||||
- name: Display service status
|
||||
ansible.builtin.shell: |
|
||||
echo "=== Frontend Service ==="
|
||||
systemctl status frontend --no-pager || true
|
||||
echo ""
|
||||
echo "=== Backend Service ==="
|
||||
systemctl status backend --no-pager || true
|
||||
register: service_status
|
||||
changed_when: false
|
||||
tags: backend
|
||||
|
||||
- name: Show service status
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ service_status.stdout_lines }}"
|
||||
|
||||
- name: Configuration UFW
|
||||
ansible.builtin.ufw:
|
||||
rule: allow
|
||||
port: "{{ item }}"
|
||||
proto: tcp
|
||||
loop:
|
||||
- "{{ backend_port }}"
|
||||
- 80
|
||||
- 22
|
||||
|
||||
- name: Activation du firewall
|
||||
ansible.builtin.ufw:
|
||||
state: enabled
|
||||
|
||||
- name: Vérifier si un certificat existe déjà
|
||||
ansible.builtin.stat:
|
||||
path: "/etc/letsencrypt/live/{{ domain_name }}/fullchain.pem"
|
||||
register: cert_file
|
||||
tags: [certbot]
|
||||
|
||||
- name: Déployer la configuration Nginx HTTP
|
||||
ansible.builtin.template:
|
||||
src: templates/nginx.conf.j2
|
||||
dest: /etc/nginx/sites-available/api
|
||||
vars:
|
||||
ssl_enabled: false
|
||||
tags: [certbot]
|
||||
|
||||
- name: Activation du site Nginx
|
||||
ansible.builtin.file:
|
||||
src: /etc/nginx/sites-available/api
|
||||
dest: /etc/nginx/sites-enabled/api
|
||||
state: link
|
||||
force: yes
|
||||
tags: [certbot]
|
||||
|
||||
- name: Suppression du site par défaut
|
||||
ansible.builtin.file:
|
||||
path: /etc/nginx/sites-enabled/default
|
||||
state: absent
|
||||
tags: [certbot]
|
||||
|
||||
- name: Test de la configuration Nginx
|
||||
ansible.builtin.command: nginx -t
|
||||
changed_when: false
|
||||
tags: [certbot]
|
||||
|
||||
- name: Redémarrage de Nginx
|
||||
ansible.builtin.systemd:
|
||||
name: nginx
|
||||
state: restarted
|
||||
enabled: yes
|
||||
tags: [certbot]
|
||||
|
||||
# ============================================================
|
||||
# Certificat SSL Let's Encrypt
|
||||
# ============================================================
|
||||
|
||||
- name: Générer le certificat SSL avec Certbot
|
||||
ansible.builtin.command: >
|
||||
certbot certonly --nginx
|
||||
-d {{ domain_name }}
|
||||
--non-interactive
|
||||
--agree-tos
|
||||
--email admin@{{ domain_name }}
|
||||
when: not cert_file.stat.exists
|
||||
tags: [certbot]
|
||||
|
||||
# ============================================================
|
||||
# Nginx - reconfiguration HTTPS après certificat
|
||||
# ============================================================
|
||||
- name: Vérifier la présence du certificat
|
||||
ansible.builtin.stat:
|
||||
path: "/etc/letsencrypt/live/{{ domain_name }}/fullchain.pem"
|
||||
register: cert_file_after
|
||||
tags: [nginx]
|
||||
|
||||
- name: Déployer la configuration Nginx HTTPS
|
||||
ansible.builtin.template:
|
||||
src: templates/nginx.conf.j2
|
||||
dest: /etc/nginx/sites-available/api
|
||||
vars:
|
||||
ssl_enabled: true
|
||||
when: cert_file_after.stat.exists
|
||||
notify: Restart nginx
|
||||
tags: [nginx]
|
||||
|
||||
- name: Test de la configuration Nginx finale
|
||||
ansible.builtin.command: nginx -t
|
||||
changed_when: false
|
||||
tags: [nginx]
|
||||
|
||||
- name: Redémarrage de Nginx avec SSL
|
||||
ansible.builtin.systemd:
|
||||
name: nginx
|
||||
state: restarted
|
||||
when: cert_file_after.stat.exists
|
||||
tags: [nginx]
|
||||
|
||||
- name: Vérifier le renouvellement automatique
|
||||
ansible.builtin.command: certbot renew --dry-run
|
||||
register: certbot_renew
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
tags: [certbot]
|
||||
|
||||
- name: Afficher le statut du renouvellement
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ certbot_renew.stdout_lines }}"
|
||||
tags: [certbot]
|
||||
|
||||
handlers:
|
||||
- name: Reload systemd
|
||||
ansible.builtin.systemd:
|
||||
daemon_reload: yes
|
||||
|
||||
- name: Restart nginx
|
||||
ansible.builtin.systemd:
|
||||
name: nginx
|
||||
state: restarted
|
||||
@@ -1,108 +0,0 @@
|
||||
---
|
||||
- name: Installation et configuration de Nginx
|
||||
hosts: nginx
|
||||
become: true
|
||||
gather_facts: true
|
||||
|
||||
tasks:
|
||||
- name: Installer Nginx
|
||||
ansible.builtin.apt:
|
||||
name: nginx
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
||||
- name: Créer le répertoire frontend
|
||||
ansible.builtin.file:
|
||||
path: "{{ nginx_frontend_path }}"
|
||||
state: directory
|
||||
owner: www-data
|
||||
group: www-data
|
||||
mode: "0755"
|
||||
|
||||
- name: Créer le répertoire de logs
|
||||
ansible.builtin.file:
|
||||
path: /var/log/nginx
|
||||
state: directory
|
||||
owner: www-data
|
||||
group: adm
|
||||
mode: "0755"
|
||||
|
||||
- name: Supprimer la config par défaut
|
||||
ansible.builtin.file:
|
||||
path: /etc/nginx/sites-enabled/default
|
||||
state: absent
|
||||
|
||||
- name: Créer la configuration Nginx
|
||||
ansible.builtin.template:
|
||||
src: ./templates/nginx.conf.j2
|
||||
dest: /etc/nginx/sites-available/{{ nginx_app_name }}
|
||||
notify: Recharger Nginx
|
||||
|
||||
- name: Activer la configuration
|
||||
ansible.builtin.file:
|
||||
src: /etc/nginx/sites-available/{{ nginx_app_name }}
|
||||
dest: /etc/nginx/sites-enabled/{{ nginx_app_name }}
|
||||
state: link
|
||||
notify: Recharger Nginx
|
||||
|
||||
- name: Configurer Nginx global settings
|
||||
lineinfile:
|
||||
path: /etc/nginx/nginx.conf
|
||||
regexp: "{{ item.regexp }}"
|
||||
line: "{{ item.line }}"
|
||||
insertafter: "http {"
|
||||
loop:
|
||||
- {
|
||||
regexp: '^\s*server_tokens',
|
||||
line: " server_tokens off;",
|
||||
}
|
||||
- {
|
||||
regexp: '^\s*client_max_body_size',
|
||||
line: " client_max_body_size {{ nginx_max_body_size }};",
|
||||
}
|
||||
notify: Recharger Nginx
|
||||
|
||||
- name: Tester la configuration Nginx
|
||||
command: nginx -t
|
||||
register: nginx_test
|
||||
changed_when: false
|
||||
|
||||
- name: Afficher le résultat du test
|
||||
debug:
|
||||
var: nginx_test.stderr_lines
|
||||
|
||||
- name: Démarrer Nginx
|
||||
ansible.builtin.systemd:
|
||||
name: nginx
|
||||
state: started
|
||||
enabled: yes
|
||||
|
||||
- name: Configurer UFW - Autoriser HTTP
|
||||
ansible.builtin.ufw:
|
||||
rule: allow
|
||||
port: "80"
|
||||
proto: tcp
|
||||
when: nginx_enable_firewall | default(true)
|
||||
|
||||
- name: Configurer UFW - Bloquer accès direct au backend
|
||||
ansible.builtin.ufw:
|
||||
rule: deny
|
||||
port: "{{ backend_port }}"
|
||||
proto: tcp
|
||||
from_ip: any
|
||||
when: nginx_enable_firewall | default(true)
|
||||
|
||||
- name: Configurer le tunnel
|
||||
ansible.builtin.template:
|
||||
src: tunnel.conf.j2
|
||||
dest: /etc/tunnel.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0644
|
||||
notify: Recharger Nginx
|
||||
|
||||
handlers:
|
||||
- name: Recharger Nginx
|
||||
systemd:
|
||||
name: nginx
|
||||
state: reloaded
|
||||
+137
-58
@@ -3,101 +3,180 @@
|
||||
# PostgreSQL Installation (vm-postgres uniquement)
|
||||
# ============================================
|
||||
- name: Installation et configuration de PostgreSQL
|
||||
hosts: postgres
|
||||
hosts: uber-stup
|
||||
become: true
|
||||
gather_facts: true
|
||||
|
||||
tasks:
|
||||
- name: Installer les dépendances système
|
||||
apt:
|
||||
# ============================================================
|
||||
# Dépendances requises
|
||||
# ============================================================
|
||||
- name: Installer les dépendances pour le dépôt APT
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- wget
|
||||
- gnupg2
|
||||
- lsb-release
|
||||
- curl
|
||||
- ca-certificates
|
||||
- apt-transport-https
|
||||
- acl # Nécessaire pour become_user
|
||||
- lsb-release
|
||||
- python3-psycopg2
|
||||
- acl
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
||||
# ============================================================
|
||||
# Ajout du dépôt officiel PostgreSQL
|
||||
# ============================================================
|
||||
- name: Ajouter la clé GPG du dépôt PostgreSQL
|
||||
apt_key:
|
||||
ansible.builtin.apt_key:
|
||||
url: https://www.postgresql.org/media/keys/ACCC4CF8.asc
|
||||
state: present
|
||||
|
||||
- name: Ajouter le dépôt PostgreSQL
|
||||
apt_repository:
|
||||
- name: Ajouter le dépôt PostgreSQL 16
|
||||
ansible.builtin.apt_repository:
|
||||
repo: "deb http://apt.postgresql.org/pub/repos/apt {{ ansible_distribution_release }}-pgdg main"
|
||||
state: present
|
||||
filename: pgdg
|
||||
|
||||
- name: Installer PostgreSQL {{ postgres_version }}
|
||||
apt:
|
||||
# ============================================================
|
||||
# Installation PostgreSQL 16
|
||||
# ============================================================
|
||||
- name: Installer PostgreSQL 16
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- postgresql-{{ postgres_version }}
|
||||
- postgresql-contrib-{{ postgres_version }}
|
||||
- python3-psycopg2
|
||||
- "postgresql-{{ pg_version }}"
|
||||
- "postgresql-client-{{ pg_version }}"
|
||||
- "postgresql-contrib-{{ pg_version }}"
|
||||
state: present
|
||||
update_cache: yes
|
||||
|
||||
- name: S'assurer que PostgreSQL est démarré
|
||||
systemd:
|
||||
- name: Démarrer et activer PostgreSQL
|
||||
ansible.builtin.systemd:
|
||||
name: postgresql
|
||||
state: started
|
||||
enabled: yes
|
||||
|
||||
- name: Définir le mot de passe du user postgres
|
||||
postgresql_user:
|
||||
name: postgres
|
||||
password: "{{ postgres_password }}"
|
||||
state: present
|
||||
become_user: postgres
|
||||
|
||||
- name: Créer les bases de données PostgreSQL
|
||||
postgresql_db:
|
||||
name: "{{ item.name }}"
|
||||
owner: postgres
|
||||
state: present
|
||||
loop: "{{ postgres_databases }}"
|
||||
become_user: postgres
|
||||
|
||||
- name: Configurer pg_hba.conf pour autoriser le backend
|
||||
blockinfile:
|
||||
path: "/etc/postgresql/{{ postgres_version }}/main/pg_hba.conf"
|
||||
block: |
|
||||
# Connexions locales
|
||||
local all postgres peer
|
||||
host all postgres 127.0.0.1/32 scram-sha-256
|
||||
# Connexions backend LAN
|
||||
host all postgres 192.168.1.0/24 scram-sha-256
|
||||
marker: "# {mark} ANSIBLE MANAGED BLOCK"
|
||||
notify: Redémarrer PostgreSQL
|
||||
tags:
|
||||
- reload
|
||||
|
||||
- name: Configurer PostgreSQL pour écouter sur toutes les interfaces
|
||||
lineinfile:
|
||||
path: "/etc/postgresql/{{ postgres_version }}/main/postgresql.conf"
|
||||
# ============================================================
|
||||
# Configuration PostgreSQL
|
||||
# ============================================================
|
||||
- name: Configurer l'écoute sur localhost
|
||||
ansible.builtin.lineinfile:
|
||||
path: "/etc/postgresql/{{ pg_version }}/main/postgresql.conf"
|
||||
regexp: "^#?listen_addresses"
|
||||
line: "listen_addresses = '*'"
|
||||
line: "listen_addresses = 'localhost'"
|
||||
notify: Restart postgresql
|
||||
|
||||
- name: Configurer le port
|
||||
ansible.builtin.lineinfile:
|
||||
path: "/etc/postgresql/{{ pg_version }}/main/postgresql.conf"
|
||||
regexp: "^#?port"
|
||||
line: "port = {{ db_port }}"
|
||||
notify: Restart postgresql
|
||||
|
||||
# ============================================================
|
||||
# Locale requise
|
||||
# ============================================================
|
||||
- name: Générer la locale fr_FR.UTF-8
|
||||
ansible.builtin.command: locale-gen fr_FR.UTF-8
|
||||
register: locale_gen
|
||||
changed_when: "'Generation complete' in locale_gen.stdout"
|
||||
|
||||
- name: Mettre à jour les locales
|
||||
ansible.builtin.command: update-locale
|
||||
when: locale_gen.changed
|
||||
|
||||
# ============================================================
|
||||
# Création de la base de données et configuration utilisateur
|
||||
# ============================================================
|
||||
- name: Définir le mot de passe de l'utilisateur postgres
|
||||
become_user: postgres
|
||||
ansible.builtin.postgresql_user:
|
||||
name: "{{ db_user }}"
|
||||
password: "{{ db_password }}"
|
||||
state: present
|
||||
notify: Redémarrer PostgreSQL
|
||||
tags:
|
||||
- reload
|
||||
|
||||
- name: Vérifier si la base de données existe
|
||||
become_user: postgres
|
||||
ansible.builtin.command: psql -tAc "SELECT 1 FROM pg_database WHERE datname='{{ db_name }}'"
|
||||
register: db_exists
|
||||
changed_when: false
|
||||
|
||||
- name: Créer la base de données avec ICU
|
||||
become_user: postgres
|
||||
ansible.builtin.command: >
|
||||
psql -c "CREATE DATABASE {{ db_name }}
|
||||
OWNER {{ db_user }}
|
||||
ENCODING 'UTF8'
|
||||
LOCALE_PROVIDER icu
|
||||
ICU_LOCALE 'fr-FR'
|
||||
TEMPLATE template0"
|
||||
when: db_exists.stdout != "1"
|
||||
|
||||
- name: Accorder tous les privilèges sur la base
|
||||
become_user: postgres
|
||||
ansible.builtin.postgresql_privs:
|
||||
db: "{{ db_name }}"
|
||||
role: "{{ db_user }}"
|
||||
type: database
|
||||
privs: ALL
|
||||
state: present
|
||||
|
||||
# ============================================================
|
||||
# Authentification pg_hba.conf
|
||||
# ============================================================
|
||||
- name: Configurer l'authentification md5 pour les connexions locales
|
||||
ansible.builtin.postgresql_pg_hba:
|
||||
dest: "/etc/postgresql/{{ pg_version }}/main/pg_hba.conf"
|
||||
contype: host
|
||||
databases: "{{ db_name }}"
|
||||
users: "{{ db_user }}"
|
||||
source: "127.0.0.1/32"
|
||||
method: md5
|
||||
notify: Restart postgresql
|
||||
|
||||
- name: Configurer l'authentification md5 pour IPv6 local
|
||||
ansible.builtin.postgresql_pg_hba:
|
||||
dest: "/etc/postgresql/{{ pg_version }}/main/pg_hba.conf"
|
||||
contype: host
|
||||
databases: "{{ db_name }}"
|
||||
users: "{{ db_user }}"
|
||||
source: "::1/128"
|
||||
method: md5
|
||||
notify: Restart postgresql
|
||||
|
||||
# ============================================================
|
||||
# Vérification
|
||||
# ============================================================
|
||||
- name: Vérifier la version de PostgreSQL
|
||||
become_user: postgres
|
||||
ansible.builtin.command: psql --version
|
||||
register: pg_version_check
|
||||
changed_when: false
|
||||
|
||||
- name: Afficher la version
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ pg_version_check.stdout }}"
|
||||
|
||||
- name: Vérifier que la base existe
|
||||
become_user: postgres
|
||||
ansible.builtin.command: psql -lqt
|
||||
register: pg_databases
|
||||
changed_when: false
|
||||
|
||||
- name: Afficher les bases de données
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ pg_databases.stdout_lines }}"
|
||||
|
||||
handlers:
|
||||
- name: Redémarrer PostgreSQL
|
||||
systemd:
|
||||
- name: Restart postgresql
|
||||
ansible.builtin.systemd:
|
||||
name: postgresql
|
||||
state: restarted
|
||||
tags:
|
||||
- reload
|
||||
|
||||
# ============================================
|
||||
# Redis Installation (vm-redis uniquement)
|
||||
# ============================================
|
||||
- name: Installation et configuration de Redis
|
||||
hosts: redis
|
||||
hosts: uber-stup
|
||||
become: true
|
||||
gather_facts: true
|
||||
|
||||
|
||||
@@ -5,6 +5,22 @@ After=network.target
|
||||
[Service]
|
||||
User={{ user_owner }}
|
||||
WorkingDirectory={{ backend_dir }}
|
||||
Environment="PATH=/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
Environment="USER_JWT_SECRET=TheAmaziNgSecretJwtMotherFuckerInThEbitCh3232131231313443jqfdksdjfjsldfjlds"
|
||||
Environment="DB_HOST=localhost"
|
||||
Environment="DB_PORT=5432"
|
||||
Environment="DB_USER=admin_gestion_commande_db"
|
||||
Environment="DB_PASSWORD=hb-FS462(#I~6(4',Nt=3Rd4567890jsezZ"
|
||||
Environment="DB_NAME=gestion_commande_db"
|
||||
Environment="DB_SSLMODE=disable"
|
||||
Environment="REDIS_HOST=127.0.0.1"
|
||||
Environment="REDIS_PORT=6379"
|
||||
Environment="REDIS_PASSWORD=uQ64h5UhFdrm!H|_cCQer"
|
||||
Environment="SESSION_SECRET=jfWR21Ywbuy{Yq<1A26TV)jCe"
|
||||
Environment="GIN_MODE=release"
|
||||
Environment="TOMTOM_API_KEY=MERY8I7LMeYVSLKO5WuV73W9rKJpBLoB"
|
||||
Environment="API_PORT={{ backend_local_port }}"
|
||||
Environment="ADMIN_JWT_SECRET=TheAmaziNgSecretJwtMotherFuckerInThEbitCh3232131231313443jqfdksdjfjsldfjlzZ"
|
||||
ExecStart={{ backend_binary }}
|
||||
Restart=always
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
SecRuleRemoveById 932235
|
||||
SecRuleRemoveById 911100
|
||||
|
||||
SecRule REQUEST_URI "@streq /api/v2/admin/protected/products" \
|
||||
"id:399002,phase:2,nolog,pass,\
|
||||
ctl:ruleRemoveById=920120,\
|
||||
ctl:ruleRemoveById=920121"
|
||||
|
||||
SecRule REQUEST_URI "@beginsWith /uploads/" \
|
||||
"id:1000,\
|
||||
phase:1,\
|
||||
pass,\
|
||||
nolog,\
|
||||
ctl:ruleEngine=Off"
|
||||
|
||||
SecRule IP:BANNED "@eq 1" \
|
||||
"id:100000,phase:1,deny,status:403,log,\
|
||||
msg:'IP is banned'"
|
||||
|
||||
SecRule IP:REPUTATION_SCORE "@ge 100" \
|
||||
"id:100099,phase:1,deny,status:403,log,\
|
||||
msg:'Critical reputation score',\
|
||||
setvar:'ip.blocked=1',expirevar:'ip.blocked=86400'"
|
||||
|
||||
SecRule TX:SQL_INJECTION_SCORE "@ge 5" \
|
||||
"id:100001,phase:2,deny,status:403,log,\
|
||||
msg:'SQL Injection detected',\
|
||||
setvar:'ip.banned=1',expirevar:'ip.banned=172800'"
|
||||
|
||||
SecRule TX:XSS_SCORE "@ge 5" \
|
||||
"id:100010,phase:2,deny,status:403,log,\
|
||||
msg:'XSS detected',\
|
||||
setvar:'ip.banned=1',expirevar:'ip.banned=172800'"
|
||||
|
||||
SecRule TX:RCE_SCORE "@ge 5" \
|
||||
"id:100020,phase:2,deny,status:403,log,\
|
||||
msg:'RCE detected',\
|
||||
setvar:'ip.banned=1',expirevar:'ip.banned=259200'"
|
||||
|
||||
SecRule TX:LFI_SCORE "@ge 5" \
|
||||
"id:100030,phase:2,deny,status:403,log,\
|
||||
msg:'LFI detected',\
|
||||
setvar:'ip.banned=1',expirevar:'ip.banned=172800'"
|
||||
|
||||
SecRule TX:INBOUND_ANOMALY_SCORE "@ge 20" \
|
||||
"id:100060,phase:2,deny,status:403,log,\
|
||||
msg:'Critical anomaly score',\
|
||||
setvar:'ip.banned=1',expirevar:'ip.banned=172800'"
|
||||
|
||||
SecRule REQUEST_URI "@streq /api/v1/panier/remove" \
|
||||
"id:399010,phase:1,nolog,pass,\
|
||||
ctl:ruleRemoveById=911100,ctl:ruleRemoveById=920350"
|
||||
|
||||
SecRule REQUEST_URI "@streq /api/v1/panier/clear" \
|
||||
"id:399011,phase:1,nolog,pass,\
|
||||
ctl:ruleRemoveById=911100,ctl:ruleRemoveById=920350"
|
||||
|
||||
SecRule REQUEST_URI "@streq /api/v2/admin/protected/products" \
|
||||
"id:399001,phase:2,nolog,pass,\
|
||||
ctl:ruleRemoveById=932235"
|
||||
|
||||
SecAction \
|
||||
"id:400161,phase:1,nolog,pass,\
|
||||
setvar:'ip.request_window_1sec=+1',\
|
||||
expirevar:'ip.request_window_1sec=1'"
|
||||
|
||||
SecRule IP:REQUEST_WINDOW_1SEC "@gt 20" \
|
||||
"id:400160,phase:1,deny,status:429,log,\
|
||||
msg:'Too many requests'"
|
||||
|
||||
SecRule IP:REPUTATION_SCORE "@ge 100" \
|
||||
"id:409999,phase:1,deny,status:403,log,\
|
||||
msg:'Critical reputation score',\
|
||||
setvar:'ip.blocked=1',expirevar:'ip.blocked=86400'"
|
||||
+135
-44
@@ -1,79 +1,170 @@
|
||||
upstream backend {
|
||||
server 127.0.0.1:{{ backend_port }} max_fails=3 fail_timeout=30s;
|
||||
keepalive 32;
|
||||
# =========================================================
|
||||
# Request ID for correlation
|
||||
# =========================================================
|
||||
map $http_x_request_id $req_id {
|
||||
default $http_x_request_id;
|
||||
"" $request_id;
|
||||
}
|
||||
|
||||
# =========================================================
|
||||
# Rate limiting
|
||||
# =========================================================
|
||||
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/m;
|
||||
limit_req_zone $binary_remote_addr zone=uploads:10m rate=10r/m;
|
||||
|
||||
# =========================================================
|
||||
# Upstream backend
|
||||
# =========================================================
|
||||
upstream backend {
|
||||
server 127.0.0.1:{{ backend_local_port }} max_fails=3 fail_timeout=30s;
|
||||
keepalive 32;
|
||||
keepalive_requests 100;
|
||||
keepalive_timeout 60s;
|
||||
}
|
||||
|
||||
{% if ssl_enabled %}
|
||||
# =========================================================
|
||||
# HTTP → HTTPS redirect
|
||||
# =========================================================
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name {{ nginx_domain }};
|
||||
root {{ nginx_frontend_path }}/dist;
|
||||
index index.html;
|
||||
server_name {{ domain_name }};
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
access_log /var/log/nginx/{{ nginx_app_name }}.access.log;
|
||||
error_log /var/log/nginx/{{ nginx_app_name }}.error.log;
|
||||
# =========================================================
|
||||
# API Server
|
||||
# =========================================================
|
||||
server {
|
||||
{% if ssl_enabled %}
|
||||
listen {{ backend_port }} ssl;
|
||||
listen [::]:{{ backend_port }} ssl;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/{{ domain_name }}/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/{{ domain_name }}/privkey.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
|
||||
ssl_prefer_server_ciphers off;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_tickets off;
|
||||
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
|
||||
{% else %}
|
||||
listen {{ backend_port }};
|
||||
listen [::]:{{ backend_port }};
|
||||
{% endif %}
|
||||
|
||||
server_name {{ domain_name }};
|
||||
client_max_body_size {{ nginx_max_body_size }};
|
||||
|
||||
location /api/ {
|
||||
limit_except GET POST PUT DELETE PATCH OPTIONS {
|
||||
deny all;
|
||||
}
|
||||
server_tokens off;
|
||||
|
||||
proxy_pass http://backend/;
|
||||
# =========================================================
|
||||
# Security headers
|
||||
# =========================================================
|
||||
add_header X-Frame-Options "DENY" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
proxy_hide_header X-Powered-By;
|
||||
proxy_hide_header Server;
|
||||
|
||||
# =========================================================
|
||||
# API proxy
|
||||
# =========================================================
|
||||
location / {
|
||||
limit_req zone=api burst=20 nodelay;
|
||||
|
||||
limit_except GET POST PUT PATCH DELETE OPTIONS { deny all; }
|
||||
|
||||
proxy_pass http://backend;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Connection "";
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Request-ID $req_id;
|
||||
proxy_set_header Connection "";
|
||||
|
||||
proxy_connect_timeout {{ nginx_proxy_timeout }}s;
|
||||
proxy_send_timeout {{ nginx_proxy_timeout }}s;
|
||||
proxy_read_timeout {{ nginx_proxy_timeout }}s;
|
||||
|
||||
proxy_buffering on;
|
||||
proxy_buffer_size 4k;
|
||||
proxy_buffers 8 4k;
|
||||
proxy_no_cache 1;
|
||||
proxy_cache_bypass 1;
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
}
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||
}
|
||||
# =========================================================
|
||||
# Uploads
|
||||
# =========================================================
|
||||
location /uploads/ {
|
||||
alias {{ uploads_dir }}/;
|
||||
limit_req zone=uploads burst=20 nodelay;
|
||||
limit_except GET HEAD { deny all; }
|
||||
|
||||
location ~* \.(css|js)$ {
|
||||
expires {{ nginx_cache_static_duration }};
|
||||
# Bloquer les fichiers exécutables
|
||||
location ~* \.(php|php5|phtml|sh|py|pl|cgi|exe|asp|aspx|jsp)$ {
|
||||
deny all;
|
||||
}
|
||||
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
access_log off;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
}
|
||||
|
||||
location ~* \.(jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires {{ nginx_cache_media_duration }};
|
||||
add_header Cache-Control "public, immutable";
|
||||
access_log off;
|
||||
location ^~ /uploads/images/ {
|
||||
alias {{ uploads_dir }}/images/;
|
||||
limit_req zone=uploads burst=20 nodelay;
|
||||
limit_except GET HEAD OPTIONS { deny all; }
|
||||
|
||||
add_header Access-Control-Allow-Origin "*" always;
|
||||
add_header Access-Control-Allow-Methods "GET, HEAD, OPTIONS" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, immutable" always;
|
||||
|
||||
types {
|
||||
image/jpeg jpg jpeg;
|
||||
image/png png;
|
||||
image/gif gif;
|
||||
image/webp webp;
|
||||
image/svg+xml svg;
|
||||
}
|
||||
default_type image/jpeg;
|
||||
}
|
||||
|
||||
location = /health {
|
||||
access_log off;
|
||||
return 200 "healthy\n";
|
||||
add_header Content-Type text/plain;
|
||||
location ^~ /uploads/videos/ {
|
||||
alias {{ uploads_dir }}/videos/;
|
||||
limit_req zone=uploads burst=20 nodelay;
|
||||
limit_except GET HEAD OPTIONS { deny all; }
|
||||
|
||||
add_header Access-Control-Allow-Origin "*" always;
|
||||
add_header Access-Control-Allow-Methods "GET, HEAD, OPTIONS" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, immutable" always;
|
||||
|
||||
types {
|
||||
video/mp4 mp4;
|
||||
video/webm webm;
|
||||
video/ogg ogv;
|
||||
}
|
||||
default_type video/mp4;
|
||||
}
|
||||
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
|
||||
|
||||
# =========================================================
|
||||
# Deny hidden files and sensitive files
|
||||
# =========================================================
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
location ~* (\.env|\.git|package\.json|package-lock\.json|yarn\.lock)$ {
|
||||
location ~* (\.env|\.git|package\.json|package-lock\.json|yarn\.lock|Dockerfile|docker-compose\.yml)$ {
|
||||
deny all;
|
||||
access_log off;
|
||||
log_not_found off;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user