# Le DevOps, c'est pas que du Dev ... -v- ## Présentation Julien Lenormand
--- # D'où je pars * le côté Dev du DevOps : * confier le déploiement à des ops * intégrer le soft dans un OS qui sera flashé * produire une image Docker + manifest Helm pour déploiement sur k8s * quelques expériences en Ops : * j'ai un PC Linux depuis + de 15 ans * j'ai fait du Docker cap et network avancé * j'ai fait un peu d'Ansible et de SSH, mais peu --- # Là où je dois aller * un ensemble de repos Python qui constituent une appli micro-services * la moitié que j'ai déjà faite tourner sur ma machine * la config que j'ai déjà un peu bidouillée * le fonctionnement que je connais * à déployer sur un serveur vierge, tout juste loué dans le Cloud * et tout doit fonctionner --- # Jour 1 : achat du serveur * je suis occupé à autre chose, je m'en occuperai demain 🤦 * lendemain matin un collègue me met en garde : le serveur se fait pilonner --- # Jour 2 : sécurisation du serveur * je me connecte en root avec la clé SSH * je crée un utilisateur, je lui donne sudo * je lui ajoute la clé publique SSH * je teste la connexion -v- ## Changement de la config SSH `sudo nano /etc/ssh/sshd_config` * on garde le port 22 * on interdit de se SSH en tant que root * on interdit les connexions par mot de passe (uniquement par clé) -v- ## Firewall : nftables `sudo nano /etc/nftables.conf` `sudo nft -c -f /etc/nftables.conf` `sudo nft -f /etc/nftables.conf` ```python flush ruleset table inet filter { set cloudflare_ipv4 { type ipv4_addr; flags interval; elements = { 173.245.48.0/20, ... } } chain input { type filter hook input priority 0; policy drop; iif "lo" accept comment "Accept localhost" ct state established,related accept comment "Allow replies" tcp dport 22 ct state new accept comment "Allow SSH" ip saddr @cloudflare_ipv4 tcp dport 443 accept comment "Allow HTTPS from Cloudflare" } ... ``` -v- ## En vrac : * "unattended upgrades" pour les MAJ de sécu * password security (libpam-pwquality) * "umask 027" pour limiter les droits des fichiers * lynis pour faire des diagnostics sécu * auditd pour surveiller les changements de certains fichiers * kernel params tuning (sysctl) * locale (UTC) et timezone (UTC) * VPN * ... --- # Jour 3 : début du déploiement de l'appli * création d'un nouvel utilisateur (no shell) pour exécuter les applicatifs * les repos ne sont pas packagés, donc déploiement via git-clone + scp 🤦 * problèmes de droit : il faut chown + mv tous les fichiers * c'est très fastidieux car manuel (spoiler : le premier déploiement ne sera pas le bon) -v- * l'un des repos a des dépendances complexes, il est packagé en conteneur 🤦 * l'image fait presque 4 Go, et j'ai pas de bande passante dans mon chalet du Jura -v- # Jour 4 : lancer les applicatifs * avant, un fatras de shells, tmux, screen, nohop, ... * mettre les choses à plat : systemd * utilisation des units de nos dépendances (BD, Queue, ...) * création des 10 units + 2 timers pour les applicatifs `sudo systemctl daemon-reload` `sudo systemctl status flup-api` -v- ```python [Unit] Description=Flup API Service After=network.target flup-component.service queue.service db.service [Service] Type=simple User=flup Group=flup WorkingDirectory=/home/flup/api_flup/ Environment=PATH=/home/bda/api_flup/.venv/bin ExecStart=/home/flup/api_flup/.venv/bin/python src/run_api.py EnvironmentFile=/etc/flup/api_flup.env Restart=on-failure RestartSec=3s StandardOutput=journal StandardError=journal [Install] WantedBy=flup.target ``` --- # Jour 4 : Configuration des dépendances * 3 BDD différentes 🤦 * 1 système de queues * pour chaque : lire les docs, configurer d'une façon différente --- # Jour 5 : le reverse-proxy (Nginx) `/etc/nginx/nginx.conf` `/etc/nginx/conf.d/*.conf` ```nginx log_format without_referrer_with_correlation_id '$remote_addr - $remote_user [$time_iso8601] ' '"$request" $status $body_bytes_sent ' '"$http_user_agent" id="$request_id"'; access_log syslog:server=unix:/dev/log without_referrer_with_correlation_id; # not just /dev/stdout because would fail on systemd ExecPre upstream flup_server { server 127.0.0.1:1234; } server { # first server as fallback if nothing matches listen 1.2.3.4:443 default_server ssl; server_name _; # an invalid name that can't be matched } ``` -v- ``` server { # Flup served to Cloudflare listen 1.2.3.4:443 ssl; http2 on; server_name flup.pluf.com; ssl_certificate /etc/ssl/certs/cloudflare-origin.pem; ssl_certificate_key /etc/ssl/private/cloudflare-origin.key; # only trust Cloudflare for providing a real IP set_real_ip_from 173.245.48.0/20; ... real_ip_header CF-Connecting-IP; add_header X-Frame-Options DENY; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block"; add_header Referrer-Policy "no-referrer"; 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 CF-Connecting-IP $http_cf_connecting_ip; proxy_set_header X-Request-ID $request_id; location / { proxy_pass http://flup_server; } } ``` --- # Paramètres (environnement) * plein de paramètres et de fichiers de config à gérer * droits à gérer : root (si lus par systemd) ou utilisateur si lus au runtime --- # Cloudflare * tout un monde ! * features de sécurité : * reverse proxy * filtrage IP * Mirage * WAF * pages d'erreur custom * migration du nom de domaine * captcha Turnstile * Rocket Loader * ... --- # Monitoring : CheckMk  * systemd * OTel --- # Conclusion * Merci ChatGPT (et consorts) pour leurs réponses * (et StackOverflow parfois aussi) * je comprends pourquoi les gens aiment le Cloud et k8s * je comprends pourquoi les gens détestent le Cloud et k8s * la partie immergée de l'iceberg est quand même cachement grande !! --- # Questions (et pensez au ROTI) Repo : https://github.com/Lenormju/talk-devops-ops Notes: Sujets à venir : * Bastion SSH * Fail2Ban * AppArmor * Sudo * CSP --- ## Abstract Je suis convaincu par le DevOps, mais c'est facile de dire ça et de ne faire que du dev. Jusqu'à maintenant, je m'étais contenté de produire des images Docker, parfois quelques petits problèmes de droits de fichier ou d'interconnexion dans un Compose. Mais aujourd'hui, j'ai du passer le cap, et plonger dans le côté Ops : pas de Cloud, juste un serveur nu, avec un OS tout juste installé dessus. Comment faire pour le sécuriser, configurer, déployer les applications dessus, et les monitorer ? Je vais vous présenter ce que j'ai fait, les sujets que j'ai rencontrés, ce qu'il m'a fallu apprendre, mes erreurs, et ce que j'en retire. J'espère que vous en apprendrez un peu sur le monde de l'Ops, et que vous apprécierez les personnes qui font ce travail.