Sam & Max » Administration System http://sametmax.com Du code, du cul Sat, 07 Nov 2015 10:56:13 +0000 en-US hourly 1 http://wordpress.org/?v=4.1 Désactiver un service dans Ubuntu 14.04 11 http://sametmax.com/desactiver-un-service-dans-ubuntu-14-04/ http://sametmax.com/desactiver-un-service-dans-ubuntu-14-04/#comments Tue, 25 Aug 2015 11:25:59 +0000 http://sametmax.com/?p=16801 Quand on installe un service, Ubuntu le lance automatiquement, et installe de quoi le faire démarer à chaque boot de la machine.

Si c’est votre machine de dev, vous ne voulez peut être pas qu’Apache, Nginx, Redis, MySQL, ElasticSearch, Solr, Supervisor, Postgres, Docker, et MongoDB soient up à chaque fois tous en même temps alors que vous voulez juste vous palucher sur youjizz.

La plupart des scripts de démarrage sont dans /etc/initd.d:

ls /etc/init.d
acpid           brltty             grub-common  lpd         pppd-dns      resolvconf   skeleton           unattended-upgrades
anacron         console-setup      halt...

Mais ces scripts sont lancés parce qu’ils sont symlinkés dans un des répertoires /etc/rcX:

ls /etc/rc*.d/*apache*
/etc/rc0.d/K80apache2  /etc/rc5.d/K80apache2  /etc/rc6.d/K80apache2

Ouai, j’ai encore des clients qui utilisent apache. Certains utilisent même Tomcat.

Pour désactiver le démarrage automatique, vous pouvez essayer bourinement la suppression des liens :

sudo rm $(ls /etc/rc*.d/*apache*)

Ça marche.

Solution plus pratique, utiliser la commande update-rc.d, qui n’est pas faite pour l’utilisation par les humains, mais fuck it :

sudo update-rc.d -f apache2 remove

Ça supprime aussi tous les liens. sudo update-rc.d -f apache2 disable devrait le faire moins bourinement mais ne marche pas sur ma machine.

Pour inverser la tendance :

sudo update-rc.d apache2 defaults

(ou enable si par miracle ça marche pour vous)

Enfin, si le cœur vous en dit:

sudo update-rc.d -f apache2 remove
sudo sysv-rc-conf

Vous donnera une joli interface curse pour le faire plus visuellement.

]]>
http://sametmax.com/desactiver-un-service-dans-ubuntu-14-04/feed/ 11
Minitip pew et OSX http://sametmax.com/minitip-pew-et-osx/ http://sametmax.com/minitip-pew-et-osx/#comments Wed, 15 Apr 2015 11:27:32 +0000 http://sametmax.com/?p=15826 Ceci est un post invité de coyote posté sous licence creative common 3.0 unported.

Comme tout bon lecteur de S&M, je me fais un devoir d’adopter tous les outils conseillés par nos maîtres (oui bon sauf crossbar.io – j’ai une vie…)

Donc, j’étais très heureux de découvrir pew mais soyons honnête, ce n’est pas exactement un drop-in replacement de virtualenv-wrapper. Bien sûr, c’est très proche et c’est beaucoup mieux mais… deux-trois petites bricoles n’emmerdaient toujours.

Le problème

bash sous OSX et Linux ont des configurations et conventions un poil différentes ce qui fait que par défaut, si vous n’êtes pas déjà au fait de ces différences, vous vous rendez compte que dès que vous activez un environnement avec pew, tout est cassé : votre prompt, vos raccourcis, etc.

Tout ça est dû au fait que (/!\ simplification inside) :

* Sous linux, au lancement de tout shell, le contenu du bashrc (~/.bashrc, /etc/bashrc) est exécuté.
* Sous OSX, au lancement d’un terminal, le contenu du ~/.bash_login est exécuté puis au lancement de subshell, c’est le ~/bashrc.

C’est con, mais ça veut dire qu’à chaque pew workon toto, seul .bashrc est exécuté. Et généralement, sous OSX, il est vide ou non existant.

La solution

C’est très simple, mais ça prends quand même 5mn…

On ne peut pas simplement tout déplacer du .bash_login vers le .bashrc, sinon hors virtualenv ça ne marchera pas. Voici donc comment je fais moi, mais c’est juste parce que je suis paresseux.

~/.bash_login:

source ~/.bashrc

Et c’est tout. En gros, on court-circuite le comportement OSX pour revenir vers du plus standard.

Extrait du ~/.bashrc:

# modification de diverses variables que je veux PARTOUT (hors env et dans env)
export PATH=/usr/local/mongodb-osx-x86_64-2.6.3/bin:$PATH
 
# modifications que je veux uniquement HORS env
# si vous avez d'autres versions de python ou pip dans votre path,
# comme le .bashrc est lancé après l'inclusion du path de l'environ par pew
# vous devez bricoler sinon vous aurez pas la bonne version. 
if [ "${VIRTUAL_ENV}a" = "a" ]
	then
	export PATH="/Library/Frameworks/Python.framework/Versions/3.4/bin:${PATH}"
else
        # modification voulues uniquement dans l'env ?
fi
 
# raccourcis pour les vieilles habitudes. c'est ce qui me derange
# le plus avec pew :)
function workon() {
	pew-workon $@;
}
 
# completion pew sur le raccourci. vous connaissez le nom de vos envs vous ?
_pew()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=( $(compgen -W "$(pew-ls)" -- ${cur}) )
}
complete -F _pew workon
 
# renvoie le path d'un projet depuis le nom de l'env pour faire d'une pierre deux coups (optionnel)
# utilise pyp
function pwdof() {
	path=`pwd`
	env_name=`echo $@| pyp "p.split('/')[-1]"`
	if [ "${env_name}" = "toto" ]
		then
		path=~/src/toto-project;
	fi
 
	echo $path;
}
 
# coloration du prompt a l’intérieur du subshell
# j'aime avoir les branches git et le nom de l'env dans mon prompt.
# donc pour que votre prompt marche dehors ET dedans (exemple)
function color_prompt {
    local __user_and_host="\[\033[01;32m\]\u@\h"
    local __cur_location="\[\033[01;34m\]\w"
    local __git_branch_color="\[\033[31m\]"
    local __git_branch='`git branch 2> /dev/null | grep -e ^* | sed -E  s/^\\\\\*\ \(.+\)$/\(\\\\\1\)\ /`'
    local __prompt_tail="\[\033[35m\]$"
    local __last_color="\[\033[00m\]"
    export PS1="$__user_and_host $__cur_location $__git_branch_color$__git_branch$__prompt_tail$__last_color "
    if [ "${VIRTUAL_ENV}a" != "a" ]
    	then
		export PS1="(\$(basename '$VIRTUAL_ENV'))$PS1";
 
		# facultatif: permet de faire un cd au lancement du subshell
		cd `pwdof ${VIRTUAL_ENV}`
   	fi
}
color_prompt
 
# completion de la commande pew qui n'est pas installé par pip
# mais qui reste pratique.
# adapté depuis: https://github.com/berdario/pew/blob/master/pew/complete_scripts/complete.bash
_pew()
{
	local cur=${COMP_WORDS[COMP_CWORD]}
	local prev=${COMP_WORDS[COMP_CWORD-1]}
    args="--help --python -i -a -r"
    commands="ls add mkproject rm lssitepackages cp workon new mktmpenv setproject show wipeenv sitepackages_dir inall toggleglobalsitepackages"
 
    case $prev in
        ls|show|rm|workon|cp|setproject)
            COMPREPLY=( $(compgen -W "$(pew-ls)" -- ${cur}) )
            return 0
            ;;
        inall)
            _command_offset 2
            return 0
            ;;
        mktmpenv|new)
            COMPREPLY=( $(compgen -W "${args}" -- ${cur}) )
            return 0
            ;;
        mkproject)
            COMPREPLY=( $(compgen -W "${args} -t --list" -- ${cur}) )
            return 0
            ;;
        add)
            COMPREPLY=( $(compgen -W "--help -d" -- ${cur}) )
            return 0
            ;;
    esac
 
    COMPREPLY=( $(compgen -W "${commands}" -- ${cur}) )
 
}
complete -F _pew pew

Et voilà !

Ça casse pas trois pattes à un canard mais si vous êtes sous OSX, que vous avez installé, vu que c’était pas parfait puis vous êtes dit «on verra plus tard» et bien le moment est arrivé.

]]>
http://sametmax.com/minitip-pew-et-osx/feed/ 0
Écouter sur le port 80 sans être root 16 http://sametmax.com/ecouter-sur-le-port-80-sans-etre-root/ http://sametmax.com/ecouter-sur-le-port-80-sans-etre-root/#comments Wed, 28 Jan 2015 13:47:08 +0000 http://sametmax.com/?p=15817 Sous beaucoup d’OS, tous les ports d’un nombre inférieur à 1024 ne peuvent pas être utilisés par des processus sans avoir les privilèges administrateurs. Néanmoins, on a pas vraiment envie que son app bricolée un lendemain de cuite soit lancée en root, pour que la moindre faille de sécurité donne l’accès total à son système.

Beaucoup de logiciels se lancent en root, et relâchent leurs privilèges a posteriori. C’est ce que faisait Apache a une époque (peut être le fait-il toujours, j’ai pas cheché). Nginx lui, lance un processus racine en root, et spawn des enfants avec un utilisateur normal.

Mais nous, on a pas la foi de se faire chier à faire ça, donc généralement, on met nginx en front et il gère ça pour nous.

Sauf que, parfois, on a pas envie de mettre 40 couches devant notre app. Par exemple, si on utilise crossbar.io (ouai, j’ai encore réussi à le placer \o/), le logiciel est clairement capable d’être en front tout seul.

Bonne nouvelle, sur les Linux modernes, les exécutables peuvent avoir des permissions avancées, comme “pourvoir changer l’horloge système” ou “empêcher la mise en veille”. Ces permissions sont changeables avec l’outil setcap.

Sous Ubuntu, ça s’installe avec :

sudo apt-get install libcap2-bin

Puis on choisit l’exécutable à qui on veut donner nos nouvelles permissions. Dans mon cas, le Python du virtualenv de mon projet :

$ pew workon super_projet
$ which python
/home/sam/.local/share/virtualenvs/super_projet/bin/python

Je check si il a pas déjà des permissions (normalement non) :

$ sudo getcap `which python`

Nada. Good.

Un petit coup de man setcap nous liste les permissions utilisables, et on peut voire que CAP_NET_BIND_SERVICE est la permission qui permet d’autoriser un exécutable à binder n’importe quel port.

On rajoute les permissions :

sudo setcap cap_net_bind_service=+ep `which python`

On check que les permissions ont bien été ajoutées :

$ sudo getcap `which python`
/home/sam/.local/share/virtualenvs/super_projet/bin/python = cap_net_bind_service+eip

On a rajouté avec le + la permission cap_net_bind_service pour les cas e et p qui correspondent aux premières lettres de ces définitions :

Permitted (formerly known as forced):
    These capabilities are automatically permitted to the thread, regardless of the thread's inheritable capabilities. 

Inheritable (formerly known as allowed):
    This set is ANDed with the thread's inheritable set to determine which inheritable capabilities are enabled in the permitted set of the thread after the execve(2). 

Effective:
    This is not a set, but rather just a single bit. If this bit is set, then during an execve(2) all of the new permitted capabilities for the thread are also raised in the effective set. If this bit is not set, then after an execve(2), none of the new permitted capabilities is in the new effective set.

Et je n’ai absolument rien compris à celles-ci, je sais juste que ça marche.

Voilà, maintenant tout ce que vous lancez avec le Python de ce virtualenv peut se binder au port 80.

Si vous n’aimez pas l’idée de donner cette permission à tout un Python, il existe une alternative : rediriger tout ce qui rentre sur le port 80 vers un autre port.

Pour ça on peut utiliser un autre soft :

sudo apt-get install socat

Par exemple, balancer tout le trafic du port 80 vers le port 8080 :

socat tcp-listen:80,fork,reuseaddr tcp:localhost:8080

Et pouf, votre appli qui écoute sur le port 8080 reçoit le trafic du port 80.

C’est plus simple, mais il faut le faire pour chaque port, et s’assurer que la commande est bien lancée au démarrage du serveur.

]]>
http://sametmax.com/ecouter-sur-le-port-80-sans-etre-root/feed/ 16
Conclusions de la migration 10 http://sametmax.com/conclusions-de-la-migration/ http://sametmax.com/conclusions-de-la-migration/#comments Thu, 08 Jan 2015 09:15:40 +0000 http://sametmax.com/?p=15682 multiboards, IndexError et 0bin on été rétablis. On en a profité pour remettre sur pied AllThatCounts qui avait été délaissé durant le dernier crash.]]> La migration de serveur est terminée. Le blog, le multiboards, IndexError et 0bin on été rétablis. On en a profité pour remettre sur pied AllThatCounts qui avait été délaissé durant le dernier crash.

On quitte donc LeaseWeb, qui nous a forcé à migré 3 fois avec ses machines qui ont planté. En plus deux fois la partition /tmp était corrompue, ce qui rend le backup particulièrement compliqué. On notera que leur SAV nous posait des questions du genre “si vous installez ça, et lancez cette commande, ça donne quoi ?”, alors qu’on leur a bien notifié qu’on avait un disque monté en lecture seul du fait du FS en vrac…

On est passé chez Cinfu, car on peut les payer en Bitcoin. Livraison du serveur rapide, installation sans histoire, et finalement une migration beaucoup moins chiante que la dernière fois car on a fait les gros bourrins : rsync + mysqldump bien large. Ce qui a pris le plus de temps c’était de résoudre les centaines de problèmes de permissions que ça a créé, les trucs que ça aurait pas du écraser, etc.

On avait + de 100000 spams dans la poubelle des commentaires, qui prenaient 300 Mo des 400 mo de la taille totale de la BDD du blog. Un petit :

DELETE FROM wp_comments WHERE comment_approved = 'trash';

A accéléré la migration vu qu’on a du transférer la base 3 fois et la réimporter autant à cause d’erreurs diverses. Note à nous-même : arrêter de mettre des .bak dans /tmp parce que c’est “juste pour 5 minutes”. Après on se fait avoir comme des débutants au reboot.

C’est là qu’on voit qu’on est dev, et pas admin.

Rajouter dans wp-config.php :

define('EMPTY_TRASH_DAYS', 30);

Nous évitera d’avoir à repenser à tout ça. C’est con mais faut le savoir.

J’en profite pour témoigner mon amour immodéré pour mosh. Parce que faire tout ça sur une connexion thai avec 300ms de ping minimum et une coupure toutes les 10 minutes, avec SSH, c’est juste un enfer.

Sous Centos, faut installer les repos EPEL et yum install mosh derrière.

Sous Ubuntu, fait installer le ppa ppa:keithw/mosh et apt-get install mosh derrière.

Certains serveurs ont un pare feu tatillon, et il faut rajouter dans la section :RH-Firewall-1-INPUT - [0:0] de iptable :

-A RH-Firewall-1-INPUT -p udp --dport 60000:61000 -j ACCEPT

D’autres ont des problèmes de locales:

apt-get install --reinstall language-pack-fr
dpkg-reconfigure locales

Parfois y a aucun problème. C’est juste qu’on a pas un parc homogène, avec des bécanes vieilles de 1000 ans, alors forcément…

Mais Max a fait des devis, et si on passe au cloud avec les 2G/s de BP et les To de disque dur qu’on consomme, on multiplie les prix par 10 d’hébergement. Faire les trucs à la main, c’est chiant, mais c’est économe.

Pour mosh, pas de serveur à lancer, juste remplacer ssh par mosh dans la commande quand on se connecte. Des fois je lance avec --predict=experimental car je suis impatient et le retour de frappe est plus rapide, mais le cursor fait des mouvements bizarres, faut s’habituer.

Bon, on retourne faire des trucs plus productifs.

]]>
http://sametmax.com/conclusions-de-la-migration/feed/ 10
Black awk down 8 http://sametmax.com/black-awk-down/ http://sametmax.com/black-awk-down/#comments Tue, 06 Jan 2015 10:26:20 +0000 http://sametmax.com/?p=10493

Ceci est un post invité de foX posté sous licence creative common 3.0 unported.

Introduction (sans douleur)

Qui n’a jamais rêvé d’avoir un shell Unix un peu plus pythonic ? Les oneliners en sed et Awk bien chiadés, c’est l’apanage des grands barbus en sandales et ça déchire, mais ça reste cryptique et la manipulation de liste et de chaînes de caractères est tout de même limitée. On peut dégainer perl en one line, comme ça c’est encore plus puissant mais moins lisible…

Et python dans tout ça ? En oneliner, ça craint, car le principe d’indentation ne facilite pas les choses et on finit avec une imbrication de bazar de parenthèses illisible.

La solution ? Pour se faire plaisir : une bonne pyp. Le bidule s’installe avec… pip (c’est une méta pipe).

pip install pyp

pyp (Python Power at the Prompt) va enchanter votre shell unix et vous envoyer au 7ème ciel. Petit tour d’horizon de la merveille.

Pyp et les strings

C’est la base quand on bricole des oneliners en shell, tripoter des strings.

ls *JPG | pyp "'mv', p, p.replace('JPG', 'jpg')"

Revoyons l’action au ralenti :

  • ls *JPG va nous lister tous les fichiers qui finissent par JPG dans le dossier courant.
  • Ensuite on envoie cela dans pyp avec un pipe Unix. Celui-ci va composer une ligne de commande qui est la concaténation d’une commande unix (mv pour renommer un fichier), ce qu’on aura reçu en entrée (qui s’appelle par convention “p”) et une version modifiée de p où l’on remplace JPG par jpg.

On voit ici que l’on utilise la méthode replace de la classe str python. On peut utiliser n’importe quelle méthode de str : lower, upper, title, strip(tease), count etc. Avec des petits bonus comme refindall(re) :-)

Ça donne quoi ma brave dame ? Et bien si on avait des fichiers appelés porn1.JPG et ass.JPG notre jolie commande renverrait :

mv porn1.JPG porn1.jpg
mv ass.JPG ass.jpg

Ok, bien gentil me direz-vous, mais qu’en fait-on ? Et bien ou l’on pipe ça dans le shell ( | sh) ou alors on passe l’argument -x (ou –execute) à pyp ou directement exécuter le résultat.

ls *JPG | pyp "'mv', p, p.replace('JPG', 'jpg')" | sh
# ou bien
ls *JPG | pyp -x "'mv', p, p.replace('JPG', 'jpg')"

Pourquoi on aime bien python ? Car il slice le bread comme un chef. Pyp aussi, oeuf corse, quelques exemples :

echo "sam-et-max" | pyp "p.split('-')[2]"
# max
 
# La même chose en plus court. Le m, comme minus, sous-entend qu'on split sur "-"
echo "sam-et-max" | pyp "m[2]"
# max
 
echo "sam-et-max" | pyp "m[0], m[2]"
# sam max

Comme vous avez vu, il y a un petit raccourci sympa avec m (comme minus) au lieu de p. C’est pas fini, vous en avez d’autres : d (dot) pour un point, w (whitespace) pour une espace, u pour underscore, s pour slash… Ils ont pensé à tout.

Des pyp à la chaîne

On tout de suite envie de remettre le couvert avec une autre pyp. C’est possible et même encouragé. Le symbole utilisé est le pipe unix | dans une commande pyp. Ce n’est donc pas un pipe du shell mais un pipe interne de pyp. Vous suivez ? Un petit exemple :

echo "sam et max" | pyp "w[0] | 'avant : ', o, 'après :', p"
# avant :  sam et max après : sam

Le p représente toujours le paramètre courant. Donc dans la seconde partie du pipe, c’est le premier élément de la liste issu du split de la chaîne “sam et max” sur l’espace (w comme whitespace). Vous suivez toujours ? Oui, bon. Et donc le o ? Et bien c’est le paramètre d’origine non modifié. Et il y a h (comme history ou comme hâlibi !) pour avoir le paramètre p à toutes les étapes de la chaîne de pipe… Beaucoup de puissance on vous dit !

On peut aussi rouler^w faire des join facilement avec les mêmes raccourcis. Par exemple on split sur les espaces puis join sur slash :

echo "sam et max aiment le lourd en fin de soirée" | pyp "w[:6]|s"
# sam/et/max/aiment/le/lourd

Une liste de pyp avec une belle pp

S’il y a un bien un truc qui envoie du bois avec python, c’est la gestion des listes. Pyp n’est pas en reste. C’est pp qui contient les listes. En avant :

ls | pyp "pp[3]"
# Affiche le troisième fichier

On peut utiliser toutes les méthodes standards de la classe list (sort, count etc.) plus quelques bonus :

# Équivalent de | sort | uniq

ls | pyp "pp.uniq()"
 
# Additionne tous les PID des process de machine.
# Ça ne sert à rien, mais c'est un exemple hein ?
ps -ef | pyp "w[1] | int(p) | sum(pp)"
 
# Voilà qui est plus utile. 
# Au passage, on note que la ligne d'en-tête est ignoré et ne fait pas planter pyp.
# Malin le lapin.
df -m | pyp "w[1] | int(p) | sum(pp)"

pyp au naturel

Pour compléter les fonctions python, pyp propose quelques fonctions maisons tout à fait sympathiques. Florilège :

echo "Sam Bill Max" | pyp "p.kill('Bill')"  # quand c'est pas bill, c'est kenny...
# Sam  Max
 
echo 124 | pyp "(int(p)/2+30)"
# 91
 
ls  | pyp "n, p"
# Liste des fichiers avec un numéro croissant devant
 
echo /home/fox/video/gangbang.avi  | pyp "'Dir='+p.dir, '\nFile='+p.file, '\nExt='+p.ext" # basename, dirname et ses amis
# Dir=/home/fox/video 
# File=gangbang.avi 
# Ext=avi
 
# On définit le séparateur de liste comme l'espace, 
# puis on regroupe la liste par deux élément
# et enfin on fait un join sur le caractère tiret (minus)
echo "1 2 3 4 5 6" | pyp "pp.delimit(' ') | pp.divide(2) | m"
# 1-2
# 3-4
# 5-6
 
ps -ef | pyp "w[1] | int(p) | max(pp)" 
# (le PID le plus grand)

pyp en intention ou intention de pyp ?

Il ne faut pas se gêner, on peut utiliser les excellentes listes en intention de Python. Voici tous les PID impaires :

ps -ef | pyp "w[1] | int(p) | [i for i in pp if i%2] | p "

L’industrie de la pyp c’est un truc de macro

Les bonnes choses, ça se garde, alors voilà :

ps -ef | pyp "w[1] | int(p) | [i for i in pp if i%2] | p " -s odd  # on enregistre la macro 'odd'
 
ps ef | pyp odd # c'est aussi simple que cela ;-)

pyp sur grand écran

Cette petite pépite est développée par Sony Pictures Imageworks pour ses besoins internes. Le développement n’est pas très collaboratif (un commit par release…) mais reste ouvert aux contributions externes. C’est sous une licence de type BSD.
Les loulous ont fait une jolie vidéo de tutorial très bling bling. C’est l’avantage de bosser dans le milieu :

Et bien plus encore…

Cet outil merveilleux possède encore des fonctionnalités qui vont vous le faire adorer comme son mode interactif avec une coloration syntaxique sympathique, la gestion de l’historique dans le pipe et beaucoup d’autres. Adieu sed, awk, uniq, sort et con sort, vous étiez mes premiers amours, mais pyp vous chasse dehors.

Ce n’est pas la seule ni la première tentative de faire la peau d’awk avec python. Sam avait déjà écrit un article sur une autre solution aussi appelée pyped.

C’est donc parfait ?

Oui, bien entendu. Aucun défaut, aucun bug. Ok… voici les limites :

      Perf de daube. Sur des petits volumes (quelques milliers de lignes) ça le fait. Au delà, ça rame. Quelques patch sont proposés pour diviser par trois le temps de traitement :-)
      Conso mémoire obcène. Idem, pour des petits volumes on s’en fout, mais sinon ça peut rapidement chiffrer. Pourquoi ? Le machin ne fonctionne pas en stream, tout est gardé en mémoire et à chaque étape de transformation (pour permettre d’accéder à l’historique).
      C’est installé sur votre pc, mais pas partout, contrairement à ce bon vieux awk.

Amusez vous bien, celui qui fait la plus jolie commande pyp dans les commentaires aura le droit à un bisous.

]]>
http://sametmax.com/black-awk-down/feed/ 8
S’assurer que SELinux ne bloque pas un programme 7 http://sametmax.com/sassurer-que-selinux-ne-bloque-pas-un-programme/ http://sametmax.com/sassurer-que-selinux-ne-bloque-pas-un-programme/#comments Sat, 03 Jan 2015 11:48:34 +0000 http://sametmax.com/?p=15659 Les distros Linux récentes viennent souvent avec des surcouches de protections type policykit, apparmor, SELinux, etc.

Tout ça est bien loin de la simplicité de la notion user/group et leurs permissions, et peut mener à un arrachage de cheveux en règle.

Cette après midi par exemple, on avait notre backend qui ne répondait pas sur le serveur tout neuf. On a changé toutes les permissions, passé de sock:// à http://, tweaké les fichiers de settings de iptables, varnish, nginx, gunicorn, supervisor, django… Puis en dernier recours, on a viré toutes les couches une par une, desinstaller les programmes, réinstaller à neuf, reset les fichiers de config en valeur par défaut, créé des fichiers de config minimaux pour toute la stack, nada. La journée frustrante et foutue en l’air.

On a quand même isolé le point de blocage sur varnish, et après avoir fait tous les tests possibles et des sacrifices humains, Max a eu l’intuition SELinux.

Voici maintenant ce qui se passe généralement dans cette situation.

Dans un élan de colère, l’utilisateur impatient fera un rapide test pour savoir si SELinux le protège comme les USA ont protégé les irakiens :

echo 0 >/selinux/enforce

Ça désactive tout le bouzin jusqu’au prochain reboot, mettre 1 inversant la tendance.

Lançant son programme et voyant que ça marche, notre dev échaudé se fend de l’équivalent du chmod 777 -R pour SELinux, à savoir éditer le fichier de config (/etc/sysconfig/selinux sur Centos) et changer rageusement SELINUX=enforcing pour SELINUX=disabled. Reboot and forget.

Une solution radicale et efficace, certes, mais qui laisse quand même un petit poids sur le conscience : diantre, il y a sûrement un moyen propre d’essuyer toute cette merde. Où sont les 3 coquillages ?

La solution est dans un petit programme appelé audit2allow, qui fait parti d’un package plus gros qu’il vous faudra trouver pour votre OS. Sous CentOs, puisque c’était notre config ce jour là, on a du faire un petit :

yum install policycoreutils-python

Ensuite, on lance notre audit :

audit2allow -a -w

Et après un peu de moulinage, il va vous sortir tout un listing de blocage, et quoi faire pour s’en sortir. Un petit grep votre_prog sur la sortie et vous obtenez ceci :

type=AVC msg=audit(1331500393.450:25): avc:  denied  { name_connect } for  pid=1276 comm="varnishd" dest=81 scontext=unconfined_u:system_r:varnishd_t:s0 tcontext=system_u:object_r:reserved_port_t:s0 tclass=tcp_socket
        Was caused by:
        One of the following booleans was set incorrectly.
        Description:
        Allow varnishd to connect to all ports, not just HTTP.

        Allow access by executing:
        # setsebool -P varnishd_connect_any 1
        Description:
        Allow system to run with NIS

        Allow access by executing:
        # setsebool -P allow_ypbind 1

Nous, c’était varnish qui était bloqué, comme le confirme le discret denied dans ce gros blog d’informations illisibles. A croire que les gars de SELinux ont tout fait pour créer la techno la moins user friendly possible. Je pense que la ligne ne commence pas par “AVC” pour rien, chaque fois que SELinux bloque un truc, un devops stagiaire meurt quelque part.

Il suffit ensuite de suivre docilement les instructions. Pour ce cas, on rentre avec les droits admin la commande :

setsebool -P varnishd_connect_any 1

Et on est bon.

Enfin, jusqu’à la prochaine après midi de debug incompréhensible qui vous fera revenir à SELinux. Max est beaucoup tenté par la solution 1 pour éviter une nouvelle galère.

]]>
http://sametmax.com/sassurer-que-selinux-ne-bloque-pas-un-programme/feed/ 7
Créer un réseau ad hoc sous Windows 8 2 http://sametmax.com/creer-un-reseau-ad-hoc-sous-windows-8/ http://sametmax.com/creer-un-reseau-ad-hoc-sous-windows-8/#comments Thu, 04 Dec 2014 15:07:34 +0000 http://sametmax.com/?p=12704 On a pas toujours un switch sous la main, et pourtant, mettre deux ordinateurs en réseau peut se faire sentir. Ok, c’est pour faire une LAN, qui j’essaye de tromper là ?

La solution, c’est le réseau ad hoc, c’est à dire demander à son ordi d’être point d’accès WIFI et réseau local.

Sous Windows 7, c’est facile, panneau de config, réseaux et partages, 3 clics et ça roule.

Mais mon Windows 8 ne voyait pas le réseau, et j’ai steam installé dessus.

Du coup, on a cherché un moyen de faire le réseau depuis W8, et l’option a été retirée des GUI.

Heureusement, il reste la ligne de commande.

D’abord, vérifier que son matos supporte le mode ad hoc :

netsh wlan show drivers

Dans la liste, il doit y avoir une ligne à propos d’un réseau hébergé avec marqué “oui”.

Si ce n’est pas le cas, fin du voyage. Sinon, on configure le réseau (les droits admins sont nécessaires) :

netsh wlan set un_nom_de_reseau mode=allow ssid=un_ssid key=un_mot_de_passe

Quand on veut lancer le réseau :

netsh wlan start un_nom_de_reseau

Quand on veut l’arrêter :

netsh wlan stop un_nom_de_reseau

Et les autres systèmes peuvent le voir dans la liste des réseaux WIFI sous le nom de “un_ssid” avec le mot de passe “un_mot_de_passe”.

]]>
http://sametmax.com/creer-un-reseau-ad-hoc-sous-windows-8/feed/ 2
Servir des fichiers statiques avec nginx 10 http://sametmax.com/servir-des-fichiers-statiques-avec-nginx/ http://sametmax.com/servir-des-fichiers-statiques-avec-nginx/#comments Thu, 23 Oct 2014 06:20:02 +0000 http://sametmax.com/?p=10490 C’est un truc dont j’ai tout le temps besoin, alors l’article servira de pense bête. Marre de chercher à chaque fois :

        # sur django, on met tout dans /static/, donc par habitude je le fais
        # pour tout
        location /static/ {

            # Le dossier doit contenir le dossier 'static'. Par exemple si votre
            # arbo est /home/sametmax/repo/static, le chemin sera
            # /home/sametmax/repo. Rassurez-vous, personne n'aura accès aux
            # autres sous dossiers de "repo".
            root  /chemin/absolu/vers/dossier/;

            # On active la compression
            gzip  on;
            gzip_http_version 1.0;
            gzip_vary on;
            gzip_comp_level 6;
            gzip_proxied any;
            gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
            gzip_buffers 16 8k;

            # Sauf pour les vieux nav
            gzip_disable ~@~\MSIE [1-6].(?!.*SV1)~@~];

            # On dit au navigateur de le mettre en cache pour 3 mois. Faites gaffe,
            # mettez un param dans les url de vos balises script/link qui change
            # à chaque version du fichier, sinon vous ne pourrez pas mettre à jour
            # vos fichiers.
            expires modified +90d;
        }
]]>
http://sametmax.com/servir-des-fichiers-statiques-avec-nginx/feed/ 10
Passer d’une clé Putty (ppk) à une clé OpenSSH 6 http://sametmax.com/passer-dun-cle-putty-ppk-a-une-cle-openssh/ http://sametmax.com/passer-dun-cle-putty-ppk-a-une-cle-openssh/#comments Sat, 27 Sep 2014 12:29:25 +0000 http://sametmax.com/?p=12248 Cas d’école, mon client me donne la clé pour accéder à son instance Amazon (bouh !) et il me file une clé Putty puisqu’il est sous Windows.

Heureusement, Putty existe aussi sous nunux. Par exemple sous Ubuntu :

sudo apt-get install putty-tools

Et il embarque tout ce qu’il faut pour convertir sa clé :

puttygen cle.ppk -O public-openssh -o nouvelle_cle.pub
puttygen cle.ppk -O private-openssh -o nouvelle_cle

Y a plus qu’à mettre dans son dossier .ssh. En prime, je rajoute généralement ça dans .ssh/config :

Host ip ou domaine
HostName ip ou domaine
User username pour le server
IdentityFile ~/.ssh/nouvelle_cle

Comme ça pas besoin de sélectionner la clé manuellement à chaque connexion, si SSH voit cette IP, il me prend la bonne clé.

Mon dossier .ssh est un simple lien vers le vrai dossier dans la partition Truecrypt. Malgré la disparition du projet, j’ai pas trouvé mieux.

]]>
http://sametmax.com/passer-dun-cle-putty-ppk-a-une-cle-openssh/feed/ 6
Le déploiement par conteneurs avec Docker 30 http://sametmax.com/le-deploiement-par-conteneurs-avec-docker/ http://sametmax.com/le-deploiement-par-conteneurs-avec-docker/#comments Thu, 15 May 2014 19:10:39 +0000 http://sametmax.com/?p=10270 Cortex, j'ai découvert un projet écrit en Go nommé Docker, qui propose encore une autre approche du problème. ]]> Mettre son projet en production, c’est la galère. Tellement que mille méthodes ont vu le jour pour automatiser tout ça. Chef, salt, fabric, des script bash, virtualenv, git hooks, etc.

Après, il y a ceux qui utilisent des VM, qui elles, ont leur propres outils d’automatisation type Vagrant.

Et comme ça ne suffit pas, des services ce sont mis en place pour faciliter la mise en prod dans le cloud comme Heroku, Gondor, dotCloud…

Malgré ça, Max fait encore beaucoup de trucs à la main parce que “ça marche jamais comme prévu”. Pas très scalable.

Dernièrement, grâce à notre cher Cortex, j’ai découvert un projet écrit en Go nommé Docker, qui propose encore une autre approche du problème.

J’ai été intrigué après avoir visionné une conf sur le sujet car le principe est très cool, mais aussi parce que j’ai bossé à une époque avec un des mecs de chez Docker. Et ce gars est un monstre. Mais vraiment. Une brute. Le genre qui n’a pas besoin de souris ni de gestionnaire de fenêtre, mais qui peut vous régler votre problème en tapant d’une main tout en vous expliquant ce qu’il fait dans votre domaine d’expertise alors que ce n’est pas le sien. Je l’ai vu faire. C’est énervant.

Pour le moment, je dois dire que Docker est vraiment sympa. Petit tour du propriétaire.

C’est comme si chaque process avait sa mini VM

Pour faire simple, docker, c’est de la virtualisation légère.

Ça marche comme cela : on prend une image d’un Linux de base qu’on fait tourner dans Docker, on lui installe de quoi faire tourner un process – par exemple Redis – et on obtient une nouvelle image qui contient juste la différence avec l’image précédente. On fait ça avec plein d’autres process, et quand on a besoin de l’un d’entre eux, on lance l’image qui contient l’install de celui-ci.

Ce sont des images très légères, on peut en lancer 100 sur une même machine si on le souhaite. Mais elles sont parfaitement isolées : elles ont leur propre système de fichier, leurs propres arbres de processus, utilisateurs, permissions, ports… Donc si par exemple je fais un nginx compilé avec des extensions exotiques et une config zarb, je peux en faire une image puis l’utiliser sur n’importe quel serveur qui contient Docker.

Le but, c’est de créer plein de petits conteneurs légers et isolés de votre machine. Et au lieu de configurer chaque serveur, on envoie juste les conteneurs dont on a besoin, et on est certain qu’ils marchent partout pareil, peu importe la config à l’arrivée. On virtualise des services, qu’on combine, et non une machine complète.

Quand je vous dis que c’est léger, c’est VRAIMENT léger. A peine plus gourmand que le process sans la VM. En fait, un conteneur Docker démarre presque instantanément, il n’y a pas de “boot” comme pour une vraie VM. Mais on en a les avantages car votre Redis dockerisé marchera pareil sur une Fedora et une Ubuntu.

Docker ne marche que sur Linux pour le moment, et encore, sur un Linux pas trop vieux car il utilise une technologie récente, dont vous avez probablement peu entendu parler : LXC.

Détail amusant : Docker est pas mal utilisé dans la communauté des devs sous Mac, qui du coup ont une VM Ubuntu dans laquelle ils font tourner Docker pour travailler. N’est-ce pas merveilleux ?

La démonstration obligatoire

Je ne vais pas vous laisser comme ça et vous demander de vous la mettre derrière l’oreille, donc exemple d’utilisation sous Bubuntoune.

Je suis en 14.04, mais je pense que ça marche pareil depuis la 12.04.

Installation :

$ sudo apt-get install docker.io

Cela va mettre la commande docker.io à votre disposition, mais sous d’autres systèmes, elle s’appelle juste docker. Perso je fais un

alias docker="sudo docker.io"

puisque de toute façon il faut toujours lancer cette commande avec les droits admin.

Ensuite, on va télécharger une image de base sur laquelle baser toutes nos images :

$ docker pull ubuntu

Docker.io, ce n’est pas juste un software, c’est aussi un service qui héberge les images. Vous pouvez bien entendu créer vos propres images de base, et héberger votre dépôt personnel d’images, mais on ne va pas se faire chier à faire ça ici. Prévoyez quelques gigas de place, Docker ne prend pas beaucoup de ressources CPU/RAM, mais par contre ça bouffe en espace disque.

Donc là, je demande la récupération des images “ubuntu”, qui vont nous servir d’images de base. Elles sont toutes faites et prêtes à l’emploi, que demande le peuple ?

Ça va downloader pendant pas mal de temps, puis vous aurez plusieurs images à votre disposition, que l’on peut lister ainsi :

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              12.04               8dbd9e392a96        4 months ago        131.5 MB (virtual 131.5 MB)
ubuntu              12.10               b750fe79269d        5 months ago        24.65 kB (virtual 180.1 MB)
ubuntu              latest              8dbd9e392a96        4 months ago        131.5 MB (virtual 131.5 MB)
ubuntu              precise             8dbd9e392a96        4 months ago        131.5 MB (virtual 131.5 MB)
ubuntu              quantal             b750fe79269d        5 months ago        24.65 kB (virtual 180.1 MB)

Vous faites votre marché : quelle image de base voulez-vous utiliser ?

La 12.04 est une LTS qui est déjà bien field testée, donc je vais prendre celle là.

Ensuite, pour lancer une commande avec, il faut faire docker run id_image commande. Ceci va lancer l’image, lancer la commande, et dès que la commande se termine, arrêter l’image :

$ docker run 74fe38d11401 echo 'YEAHHHHHHHHHHHHHH'
WARNING: Local (127.0.0.1) DNS resolver found in resolv.conf and containers can't use it. Using default external servers : [8.8.8.8 8.8.4.4]
YEAHHHHHHHHHHHHHH

Mesurons le temps pris en tout pour faire cela :

$ time -f "%e seconds" sudo docker.io run 74fe38d11401 echo 'YEAHHHHHHHHHHHHHH'
WARNING: Local (127.0.0.1) DNS resolver found in resolv.conf and containers can't use it. Using default external servers : [8.8.8.8 8.8.4.4]
YEAHHHHHHHHHHHHHH
0.45 seconds

Comme vous le voyez, démarrer un conteneur, c’est vraiment rapide. Mais faire un

echo

, ça ne sert pas à grand chose :)

Faisons quelque chose de plus utile : lançons un terminal bash et demandons un accès à stdin/stdout (-i) ainsi qu’un tty (-t) :

$ docker run -i -t 74fe38d11401 bash
WARNING: Local (127.0.0.1) DNS resolver found in resolv.conf and containers can't use it. Using default external servers : [8.8.8.8 8.8.4.4]
root@8195e92a5e62:/#

Et hop, comme le process ne se termine pas tant qu’on est connecté au tty, on a le conteneur qui continue de tourner, mais on a un terminal dessus, nous permettant d’entrer n’importe quelle commande.

Si on installait 0bin ?

D’abord, on a besoin de pip dans le conteneur:

# apt-get install python-pip

Notez qu’on est toujours root dans son conteneur. Après tout, c’est virtuel et isolé, donc pas de raison de se faire chier.

Ensuite, on tape dans pypi :

# pip install zerobin

Pas besoin de virtualenv, on est déjà dans un environnement isolé.

Faisons un petit fichier de config. On va avoir besoin de vim :

# apt-get install vim
# cd /home
# vi settings.py

On met des settings perso pour zerobin, histoire de montrer le principe de faire un conteneur avec un setup sur mesure (on peut, bien entendu, faire 1000 fois plus compliqué, c’est un exemple bande de bananes) :

# on le fait ecouter sur l'exterieur
HOST = "0.0.0.0"
# on change le menu de la page d'accueil
MENU = (
    ('Home', '/'),
    ('Contact', 'mailto:mysupermail@awesomesite.com')
)

Et on lance notre petit zerobin :

# zerobin --settings-file=settings.py

Et voilà, on a un zerobin qui tourne dans notre conteneur isolé.

On va sauvegarder tout ça. Sur notre machine hôte (donc pas dans le conteneur), on va sauvegarder notre nouvelle image. D’abord, on va trouver l’ID du conteneur qui tourne :

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                     NAMES
8195e92a5e62        ubuntu:12.04        bash                37 minutes ago      Up 37 minutes                                 boring_mccarthy

Ensuite on commite ce conteneur pour obtenir une nouvele image. Pour faire simple, on va l’appeller “zerobin” :

$ docker commit 8195e92a5e62 zerobin

On peut alors tranquillement arrêter notre conteneur :

$ docker stop 8195e92a5e62

Maintenant on peut pusher notre image tout neuve sur un repo distant avec docker push pour pouvoir la puller plus tard. Il faut ouvrir un compte sur leur service ou créer son propre depot, je vous laisse trouver comment faire. Plus simplement, on peut juste dumper l’image avec docker save id_image > nom_image.tar, la copier sur une clé USB, et la recharger avec docker load < nom_image.tar.

Dans tous les cas, une fois sur le serveur, vous pouvez lancer votre image "zerobin", ici encore une fois avec la commande bash:

# docker run -t -i -p 7777:8000 zerobin bash

Cette fois, on rajoute une option de plus : -p 7777:8000 dit à docker de relier le port 7777 de ma machine au port 8000 (port de 0bin par défaut) de mon conteneur. Ainsi, si une app va sur le port 7777 de ma machine, elle va en fait parler au port 8000 du conteneur sans s'en rendre compte.

Du coup, je peux lancer mon petit zerobin depuis mon contenur :

# cd /home
# zerobin --settings-file=settings.py

Et voilà ! J'ai un zerobin qui marche, qui est préconfiguré, isolé et portable. Si je change de serveur, ou même d'OS, je peux juste reprendre le même conteneur et le relancer tel quel. Et je peux faire ça avec plein de process et les faire communiquer entre eux.

Capture d'écran de zerobin

J'accède à 7777 sur la machine, mais ça tape sur 8000 dans mon conteneur

Docker est un outil très riche, et vous vous doutez bien que je ne vous ai montré que le début.

Par exemple, vous voulez sans doute ne pas avoir à lancer bash, puis un cd, puis zerobin. Ça peut s'automatiser avec un dockerfile. Vous voulez aussi peut être lancer le conteneur en arrière-plan, ça se fait avec l'option -d. Ou peut être voulez-vous un dossier partagé entre tous les conteneurs ? C'est possible avec l'option volume.

Parmi les usages vraiment intéressants de dockers : packager les services très custos comme les nginx ou ffmpeg compilés avec des options cryptiques, deployer son app django avec toutes les libs Python et les settings qui vont bien, remplacer une app à chaud en redirigeant juste le load balancer sur le nouveau conteneur, ou encore fournir un env de test à un client. Perso, rien que pour tester des nouveaux logiciels sans pourrir ma machine, je trouve ça pratique : on a bien moins peur de faire un make install.

Je vous laisse prendre en main le nouveau joujou, j'ai des serveurs à planter.

]]>
http://sametmax.com/le-deploiement-par-conteneurs-avec-docker/feed/ 30