Catégorie : linux

python, flask, https et wsgi howto

Je ne vais pas dire le temps que j’ai passé à réussir à mettre ça en oeuvre si quelqu’un fait ça en quelques minutes j’aurais honte… mais disons que j’ai passé beaucoup de temps à le faire tourner, mais je suis vraiment impressionné par sa rapidité. Voici – via ma petite expérience – comment faire tourner un serveur Web très optimisé, en mode production  :
  • flask
  • wsgi
  • https

https / certbot

Je vous donne des pistes, à vous de finir.
L’idée, c’est que je veux paramétrer pour la n-ième fois un nouveau nom de domaine via certbot, et je ne veux pas qu’il touche à la conf de nginx. L’idée c’est que :
(1) Je le fais simplement via certbot-auto puis après,
(2) toutes les autres fois j’utilise « -d » pour qu’il ne touche pas à la conf, et je le fais à la main, en m’inspirant de la conf que cert-bot a fait dans le (1)
Donc, pour faire le (1), je demande à certbot de me créer uniquement le certificat : ./certbot-auto certonly -d monsite.fr
Pour le https, regardez ici.

Python

Code exemple, qui lit un fichier JSON, lance le serveur et sert le fichier lu en tant que JSON :

import json

from flask import Flask, jsonify

app = Flask(__name__)

with open("mon fichier JSON", 'r') as f:
    json_levels_full_description = json.load(f)


@app.route('/')
def index():
    return jsonify(json_levels_full_description)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8004)
else:
    application = app

Attention : surtout ne faites pas le classique if __name__ == '__main__' car uwsgi inclut ce fichier, donc ce fichier n’est jamais un __main__, par contre la configuration au lancement a besoin d’une variable globale nommée application.

Nginx

Je copie colle la configuration d’un site qui tourne déjà en https, en voici un extrait diminué à mort pour ne pas polluer avec des règles personnelles, regardez bien le texte en gras, c’est le plus important pour faire tourner Nginx en collaboration avec wsgi :

server {
  server_name "~(www\.)?monsite\.(com|fr|org|biz|be)$";

  index index.html index.htm;

  access_log /blah/proxy-access.monsite.log proxylog;
  error_log /blah/proxy-error.monsite.log error;

  listen 443 ssl;
  ssl_certificate /blah/fullchain.pem;
  ssl_certificate_key /blah/privkey.pem;
  include /blah/options-ssl-nginx.conf;
  ssl_dhparam /blah/ssl-dhparams.pem;

  location / {
    include denied_clients;

    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-Server $host;

    # (!) here it's uwsgi:
    include uwsgi_params;
    uwsgi_pass 127.0.0.1:8002;

  }
}

# redirect http -> https:
server {
  listen *:80;
  server_name "~^monsite\..*$";
  return 302 https://$host$request_uri;
}

Flask

Pour installer flask, et uwsgi, faites un environnement virtuel puis installez les deux :

$ python3 -m venv venvpython.3.6.6
$ source venvpython.3.6.6/bin/activate
$ pip install --upgrade pip
$ pip install flask

uwsgi

Il faut être dans le venv activé (voir paragraphe précédent), puis l’installer via pip :

$ pip install uwsgi

Enfin, le script de lancement !

uwsgi --chdir=/web/htdocs/blah \
    --module=flask_server:application \
    --master --pidfile=/tmp/uwsgi.blah.pid \
    --socket=127.0.0.1:8004 \
    --processes=5 \
    --uid=1000 --gid=2000 \
    --harakiri=20 \
    --max-requests=5000 \
    --vacuum \
    --home=/web/htdocs/blah/venvpython.3.6.6

flask_server correspond au fichier python flask_server.pydécrit dans la section python au début et application est le nom de la variable globale (lisez le code de la section python)

Lorsque vous le lancerez, tout se passera bien, mais l’exécutable ne sera pas en tâche de fond. Cela a un avantage : un CTRL-C et vous l’arrêtez ! L’inconvénient, c’est que vous n’avez pas la main.

Si vous voulez le lancer en tâche de fond et qu’il écrive les logs dans un fichier, ajoutez l’option     --daemonize=/var/log/uwsgi/blah.uwsgi.log


Notes d’amélioration :
– Le port 8004 peut être passé en tant que variable d’environnement à l’application flask via le paramètre `env` de la commande uwsgi, ce qui rend le code plus portable ;
– Les paramètres uwsgi peuvent être consignés dans un fichier my_app.ini et uwsgi serait alors lancé en faisant uwsgi my_app.ini

Linux prompt how-to customisé + explications

Je vais faire un résumé de ce que j’ai trouvé un peu partout, et pourquoi j’ai choisi mon prompt tel que je l’ai fait.

  1. Visuellement, avoir quelque chose de coloré est extrêmement parlant. Il me fallait absolument utiliser les couleurs possibles du prompt pour rapidement mettre en évidence ce qui m’intéresse ;
  2. Le bash a sa syntaxe qui est très efficace mais pas forcément facile à appréhender ;
  3. Comme pour tout ce qu’on cherche sur Internet en termes de développement, il y a à boire et à manger… et cela semble devenir vrai aussi pour Linux. J’espère vraiment (x 450e+6654) me tromper.

Ce que j’ai trouvé et qui fonctionne selon mes tests. Ici, bien sûr, peut être qu’il y a d’autres solutions, mais celle que je donne ici a fonctionné sur tous les shells que j’ai testé (Ubuntu, Mint mais aussi CentOS).

Séquence invisible

Toute séquence qu’on ne veut pas visible doit être entourée par \[ et \].
Fin de l’histoire. Je vais pas pleurer en disant que j’ai passé un sacré paquet de temps à trouver ça alors que c’est très simple. Ah si je pleure ? Bon ok.

Changer de couleur

Pour changer de couleur, il faut imaginer qu’on change simplement de stylo. Simple, me direz-vous ? Mais après avoir lu et travaillé dans le Web où on ouvre puis on ferme une balise, ici, non. Il faut envoyer une séquence spéciale : \033 puis ouvrir un crochet qu’on ne va pas fermer, c’est codé en dur, il faut l’accepter tel quel : [. Et ensuite, un chiffre : 0 pour dire qu’on veut une couleur foncée, ou 1 pour dire qu’on la veut un peu plus claire (ex : le noir devient gris) puis un point virgule ;. Ensuite, il faut donner un chiffre compris entre 30 et 36 pour préciser la couleur. Et vous croyez que c’est terminé ? Non ! Il faut terminer par la lettre m. Si vous avez bien lu, vous devriez instantanément comprendre l’exemple suivant : \[\033[1;31m\]. Oui oui, le crochet au milieu ne se ferme jamais. Respirez, calmez-vous. C’est la vie. Il faut faire avec.

Pour toutes les couleurs, j’ai tout mis dans mon mémo qui remplace ma mémoire trop remplie (je préfère dire « trop remplie » que « défaillante », mais parfois j’hésite entre les deux…).

Restorer la couleur d’origine

Oui c’est en h1 parce que c’est aussi important que les deux paragraphes précédents : pour restaurer la couleur d’origine, cela ressemble un peu à l’ordre précédent : entourer par des crochets échappés, une séquence de couleur qui n’a pas deux valeurs mais une seule : 0. Cela donne : \[\033[0m\].
Donc votre code qui change votre prompt devrait toujours se terminer par « remettre la couleur d’origine », soit \[\033[0m\]. Ce n’est que mon point de vue…

Mon prompt

Vous allez me dire « mais pourquoi il fait tout un article sur un prompt ? ». Réponse : c’est comme mon clavier : j’ai passé beaucoup de temps à l’apprendre et le configurer, parce que je sais que sur du long terme ça va m’être très rentable. Passer plusieurs semaines pour gagner plusieurs mois, ça vaut le coup, fin de l’histoire. Donc, voici ma réflexion qui explique mon choix de prompt. J’aurais tout autant pu vous répondre un grand classique indétrônable : le diable est dans les détails.

  1. J’ai très souvent besoin de savoir globalement l’heure qu’il est. J’aimerais bien, dans mon prompt, je sache l’heure qu’il est. Si je tape quelque chose, je valide, hop j’ai la nouvelle heure. Pratique, pas « mortellement pratique », mais sympa. De plus, 6 caractères utilisés pour HH:MM[espace] c’est négligeable. Par contre, j’aimerais que visuellement, ça ne soit pas polluant. C’est pratique, mais pas important. La couleur la plus sombre possible dans le prompt c’est « noir éclairci », soit premier chiffre = éclairci = 1 et second chiffre = noir = 30. Donc mon premier ordre c’est « noir éclairci + heure », donc : \[\033[1;30m\]\t 
  2. La seconde chose, qu’on retrouve partout, c’est bien sûr, qui est connecté, donc l’utilisateur. Là, ça devient plus important. Mais pas le plus important pour moi (surtout sur la fin du prompt où on voit en méga surbrillance, si on est superuser ou utilisateur normal) : c’est une couleur foncée 0 et qui peut avoir un pendant « éclairci » plus agréable pour préciser l’hôte (j’en parle juste après) : j’ai choisi purple = 35. La séquence échappée du user en cours est \u. Ici aussi, si vous avez suivi, ça donne, couleur + user en cours : \[\033[0;35m\]\u
  3. Ensuite, séparateur entre l’utilisateur et l’hôte. Le classique « @ » qui ne doit pas être gênant, même couleur que l’heure : « noir éclairci », soit \[\033[1;30m\]@
  4. L’hôte. Oui, le grand classique c’est «[userconnecté]@[hôte]», et si des millions de geeks linux ont choisi cela c’est que c’est parlant. Mais ici, comme je gère pas mal de machines, selon moi, il faudrait que l’hôte soit un peu plus visible que le user en cours. Donc même couleur que le user, mais avec «1» au lieu de «0». Sachant que la séquence échappée de l’hôte est \h on obtient : \[\033[1;35m\]\h
  5. Avant dernière chose (pour moi) : le path. Là, bon sang, il faut que ça pète. Il faut que le yeux le voient même si on commence à s’endormir (petit clin d’œil à ceux qui mangent kebab-frites avant de commencer les cours avec moi). Un bon rouge, bien éclairci. Allez on le fait rapide : pour exécuter un ordre à chaque appel de prompt, l’astuce est d’échapper le $ et de mettre entre parenthèses l’ordre shell qu’on veut lancer : ici, on est sur du Linux, c’est instantané. La solution, donc : rouge vif + $(pwd) version « échappée » :
    \[\033[1;31m\]\$(pwd)
  6. Dernière information : la plus cruciale, toujours présente sur tous les paths : quel type d’utilisateur est connecté : \$. Il est substitué par # si vous êtes root, sinon $. Là, il faut qu’on ait les yeux qui brûlent. Lunettes de soleil. Du jaune, le plus visible possible (= « 1« ). Un bon jaune qui fait pleurer les yeux, mais ça ne prend qu’un caractère, qui est IMHO, d’une importance cruciale :
    \[\033[1;33m\]\$

Voici donc mon bash résumé en une ligne, que je mets dans tous mes .bashrc. Si vous ne savez pas ce qu’est un .bashrc, je vous laisse chercher, ce n’est pas le but de l’article.

Voici ce que donne mon prompt, et même si ici il n’est pas super vendeur, en pratique, je n’ai pas trouvé quelque chose de plus efficace visuellement parlant, si vous avez des idées / suggestions, améliorations, commme d’habitude, je suis preneur :

Mon prompt Linux shell

Le code de mon prompt, volontairement en minuscules juste pour vous faire râler :

export PS1="\[\033[1;30m\]\t \[\033[0;35m\]\u\[\033[1;30m\]@\[\033[1;35m\]\h \[\033[1;31m\]\$(pwd) \[\033[1;33m\]\$\[\033[0m\] "

PS : pour ceux qui ne savent pas ce que « IMHO » signifie, ne le dites à personne, et allez vite chercher sur Internet. Promis on ne le dira à personne. C’est comme « RTFM ». Promis. Chut. [silence gêné].

cheatsheet » weechat

weechat hints / aide

Côté utilisateur

La souris Quand on aimerait cliquer :
/mouse disable
Pour la remettre :
/mouse enable
Documentation Raccourci : cliquer sur le lien :
– Message privé
– Raccourcis clavier

Configuration

Toujours installer v2+ et pas moins https://weechat.org/download/
Fichier de conf :
~/.weechat/
Weechat = une seule instance.
Conf. chargée en entier ici :
~/.weechat/
Pour plusieurs instances, copier tout le dossier, ex :
cp -R ~/.weechat ~/.weechat2
Puis lancez en précisant weechat -d ~/.weechat2
Lancement + connexion auto Exemple de code :
weechat -r '/server add freenode irc.freenode.net; /connect freenode -nicks=Olivier; /set irc.server.freenode.username "Olivier2"; /set irc.server.freenode.realname "Olivier Pons"; /set irc.server.freenode.autojoin "#prognosis-dev"'

Plugins

Situés dans :
~/.weechat/
Plugins Python ici :
~/.weechat/python
Chargement manuel Exemple Python / plugin arespond.py :
/script load arespond.py
Chargement automatique Exemple Python / plugin arespond.py :
Faire un lien symbolique :
cd ~/.weechat/python/autoload
ln -s ../arespond.py arespond.py
Options / switches Définir une option manuellement :
/set plugins.var.python.[SCRIPT_NAME].[option]="[valeur]
Appuyer sur TAB pour autocompléter
Au pire lire les options dans le code même.
Exemple Python / plugin arespond.py :
Les options sont en « camelCase », mais elles sont toutes transformées en minuscules dans weechat.
Il y a trois options marquée dans le code:
"muted"
"respondAfterMinutes"
"responderText"
Donc pour y accéder, il suffit de taper :
/set plugins.var.python.arespond.[tab]
Et les trois options seront affichées sur la ligne du dessus, il suffit d’autocompléter.

2 – Preonic : le clavier parfait. Pour les nerds.

C’est l’Ergodox Infinity, mais en plus petit.

  1. mkdir keyboards && cd keyboards && mkdir preonic && cd preonic
  2. git clone https://github.com/qmk/qmk_firmware
  3. cp -R ./keyboards/preonic/keymaps/default ./keyboards/preonic/keymaps/azerty
  4. make preonic:azerty:dfu

Vous pourrez ainsi éditer le dossier qui est maintenant votre dossier custom azerty

vim ./keyboards/preonic/keymaps/azerty

Windows : le shell Linux / Ubuntu enfin acceptable !

Merci à l’un de mes étudiants pour l’astuce :

Sous Windows 10 :

  • Activez le mode développeur ;
  • Cochez l’option « Linux » (il faut la chercher) ;
  • Tentez de lancer un shell via le menu « Démarrer » et tapez « Ubuntu ».

Vous aurez un Shell Linux, mais totalement pourri.

Faites néanmoins le classique « sudo apt-get update && sudo apt-get upgrade« .

Une fois cela terminé, allez récupérer ce qui va vous changer la vie : wsltty.
C’est un outil qui remplace le shell Ubuntu de Windows, mais qui est mieux sur tous les plans.
Et là vous aurez un shell qui ressemble au mintty de Cygwin (mon shell préféré).

Linux tar : faire une archive au format « AAAA-MM-JJ_HHMMSS.archive.tar.bz2 »

C’est tout simple sous Linux.
Il faut juste savoir, pour ceux qui commencent à faire quelques lignes de commande sous Linux, que le « backquotes », donc le ` demande à exécuter quelque chose et le remplacer par le résultat de l’exécution.

Exemple : si vous tapez `(date '+%Y.%m.%d-%Hh%Mm%Ss')` alors il exécutera l’ordre date, et le remplacera par la date en cours.

Exemple concret :

tar cjf "`(date '+%Y.%m.%d-%Hh%Mm%Ss')`.monarchive.tar.bz2" htdocs/*

Vous archivera tout le dossier htdocs dans l’archive :
2018.02.06-09h45m05s.monarchive.tar.bz2

En espérant que cela serve à quelqu’un !

Comment transférer des fichiers très rapidement entre deux PCs distants ?

Petite astuce très pratique : vous voulez transférer des fichiers d’un PC à un autre, sans forcément partager le répertoire, vous faire suer avec les problèmes de droits, etc. ?

Rien de plus simple, lancez un serveur local Python qui servira les fichiers de manière statique :

  • Python 2 : python -m SimpleHTTPServer
  • Python 3 : python3 -m http.server

Et à distance, tapez l’URL du PC sur lequel tourne le serveur, et hop, vous pouvez récupérer ce que vous voulez !

Exemple de python webserver
Exemple de python webserver

Windows : les loopbacks. Impossible à surveiller

Si jamais vous faites un site Internet, que vous le mettez sur localhost et que vous lancez un navigateur, il se peut que, comme moi, vous ayez envie de voir exactement ce qui se passe.

Dans ce cadre, un « espion » parfait pour cela est wireshark (analyseur de trames réseau).

Après plusieurs minutes, voire heures, vous verrez que quelles que soient vos actions, rien ne se passe.
L’explication est simple : Windows, peu importe sa version, « coupe » les arrivées réseau si elles sont en loopback = sur localhost.

Un grand merci, encore une fois, pour Windows !

Toute l’explication est là.

Il faut utiliser un outil, RawCap, qui hacke un peu Windows et génère un fichier « .pcap » compatible avec Wireshark.

Sur Linux, vous n’aurez pas ce problème typique Windows

En ligne de commande, on peut faire le dump de tout le traffic, y compris le localhost.
Il vous suffit d’utiliser l’utilitaire tcpdump, exemple :

$
$ sudo tcpdump -vv -i lo port 8000
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes

Et à partir de là il écoutera sur le port 8000. Lancez Chrome, allez sur localhost:8000 et là vous verrez :

(pour la note, même s’il n’y a pas de serveur, ce qui est le cas ici, il écoute et trace vraiment tout)

17:23:14.100160 IP6 (flowlabel 0x52956, hlim 64, next-header TCP (6) payload length: 40) ip6-localhost.44238 > ip6-localhost.8000: Flags [S], cksum 0x0030 (incorrect -> 0xfe61), seq 1512481496, win 43690, options [mss 65476,sackOK,TS val 3860198845 ecr 0,nop,wscale 7], length 0
17:23:14.100165 IP6 (flowlabel 0xe143c, hlim 64, next-header TCP (6) payload length: 20) ip6-localhost.8000 > ip6-localhost.44238: Flags [R.], cksum 0x001c (incorrect -> 0xe6c0), seq 0, ack 1512481497, win 0, length 0
17:23:14.100189 IP (tos 0x0, ttl 64, id 63584, offset 0, flags [DF], proto TCP (6), length 60)
localhost.43918 > localhost.8000: Flags [S], cksum 0xfe30 (incorrect -> 0x631e), seq 4099830766, win 43690, options [mss 65495,sackOK,TS val 1743693574 ecr 0,nop,wscale 7], length 0
17:23:14.100194 IP (tos 0x0, ttl 64, id 12132, offset 0, flags [DF], proto TCP (6), length 40)
localhost.8000 > localhost.43918: Flags [R.], cksum 0x7eb1 (correct), seq 0, ack 4099830767, win 0, length 0
17:23:14.153839 IP6 (flowlabel 0xc30e0, hlim 64, next-header TCP (6) payload length: 40) ip6-localhost.44242 > ip6-localhost.8000: Flags [S], cksum 0x0030 (incorrect -> 0xaa17), seq 1123880506, win 43690, options [mss 65476,sackOK,TS val 3860198859 ecr 0,nop,wscale 7], length 0
17:23:14.153847 IP6 (flowlabel 0xee9c9, hlim 64, next-header TCP (6) payload length: 20) ip6-localhost.8000 > ip6-localhost.44242: Flags [R.], cksum 0x001c (incorrect -> 0x9284), seq 0, ack 1123880507, win 0, length 0
17:23:14.153884 IP (tos 0x0, ttl 64, id 20755, offset 0, flags [DF], proto TCP (6), length 60)
localhost.43922 > localhost.8000: Flags [S], cksum 0xfe30 (incorrect -> 0x1c4e), seq 3564886671, win 43690, options [mss 65495,sackOK,TS val 1743693588 ecr 0,nop,wscale 7], length 0
17:23:14.153891 IP (tos 0x0, ttl 64, id 12140, offset 0, flags [DF], proto TCP (6), length 40)
localhost.8000 > localhost.43922: Flags [R.], cksum 0x37ef (correct), seq 0, ack 3564886672, win 0, length 0
17:23:19.161265 IP6 (flowlabel 0x606b8, hlim 64, next-header TCP (6) payload length: 40) ip6-localhost.44246 > ip6-localhost.8000: Flags [S], cksum 0x0030 (incorrect -> 0x1e75), seq 983670096, win 43690, options [mss 65476,sackOK,TS val 3860200111 ecr 0,nop,wscale 7], length 0
17:23:19.161281 IP6 (flowlabel 0xe0662, hlim 64, next-header TCP (6) payload length: 20) ip6-localhost.8000 > ip6-localhost.44246: Flags [R.], cksum 0x001c (incorrect -> 0x0bc6), seq 0, ack 983670097, win 0, length 0
17:23:19.161360 IP (tos 0x0, ttl 64, id 18581, offset 0, flags [DF], proto TCP (6), length 60)
localhost.43926 > localhost.8000: Flags [S], cksum 0xfe30 (incorrect -> 0xe872), seq 99211285, win 43690, options [mss 65495,sackOK,TS val 1743694840 ecr 0,nop,wscale 7], length 0
17:23:19.161372 IP (tos 0x0, ttl 64, id 13102, offset 0, flags [DF], proto TCP (6), length 40)
localhost.8000 > localhost.43926: Flags [R.], cksum 0x08f8 (correct), seq 0, ack 99211286, win 0, length 0

Linux bc : float / flottants

Plein de personnes utilisent « calc » sous Windows. C’est bien.
Mais, comme la plupart des outils Windows : Linux c’est 20x moins ergonomique, mais 20x puissant.

Bah comme Linux en général, en fait…

Let me introduce bc.

C’est le « calc » de Windows, mais en plus laid et en 20 x plus puissant que la calculatrice Windows (déjà dit).

Le seul truc bizarre de bc c’est qu’il ne fait que des calculs en entier.
En bref : bc -l et hop tout est en flottant et fonctionne.
To make a long story short: bc -l and everything is ok.