@ -0,0 +1,6 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Liens utiles | |||
* [Drivers](http://shop.transtec.fr/F/F/support/support_driverdownload.html) ; | |||
* [Manuel de la baie](http://download.transtec.de/doit/loadva/software/w3/CD_STOR_HTML/raid/pv6xx/docs/GMN_PV610S_SCSI-toSATA_v1.3.pdf). |
@ -0,0 +1,90 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Howto APU | |||
## minicom | |||
~~~ | |||
pu port /dev/ttyUSB0 | |||
pu baudrate 38400 | |||
pu rtscts No | |||
pu xonxoff Yes | |||
~~~ | |||
~~~ | |||
pu port /dev/ttyUSB0 | |||
pu baudrate 115200 | |||
pu rtscts No | |||
pu xonxoff Yes | |||
~~~ | |||
## Installation flashrd | |||
Suivre <http://arnaud.tomei.fr/alix-openbsd#installation-du-systeme> | |||
## Adaptations de base | |||
~~~ | |||
rw | |||
passwd | |||
echo 'PKG_PATH="ftp://ftp.openbsd.org/pub/OpenBSD/5.7/packages/amd64/"\nexport PKG_PATH' >> /root/.profile | |||
echo routeur > /etc/myname | |||
echo 'net.inet.ip.forwarding=1\nnet.inet.ip.redirect=0\nnet.inet6.ip6.forwarding=1\nnet.inet6.ip6.accept_rtadv=0' >> /etc/sysctl.conf | |||
echo 'description "LAN"\ninet 192.168.12.1 255.255.255.0 NONE' > /etc/hostname.re2 | |||
sync | |||
~~~ | |||
## Persistance de /var et /home | |||
Dans /etc/rc.flashrd.sub vérifier que les lignes suivantes sont présentes et décommentées : | |||
~~~ | |||
tardirs="var" | |||
set -A tarsize 64M # tmpfs sizes for tar dirs | |||
# | |||
# If you want to save all "tardirs" contents on shutdown: | |||
savetardirs="$tardirs" | |||
~~~ | |||
Le ramdisk de /var sera ainsi sauvegardé dans /flash/var.tar à l'extinction du routeur, et décompacté au démarrage. | |||
Si des modifications importantes sont faites, il est possible de régénérer l'archive manuellement ainsi : | |||
~~~ | |||
tar cf /flash/var.tar -C /var . | |||
~~~ | |||
Pour /home : | |||
~~~ | |||
mkdir /flash/home/ | |||
rmdir /home | |||
cat /etc/rc.local | |||
# $OpenBSD: rc.local,v 1.44 2011/04/22 06:08:14 ajacoutot Exp $ | |||
# Site-specific startup actions, daemons, and other things which | |||
# can be done AFTER your system goes into securemode. For actions | |||
# which should be done BEFORE your system has gone into securemode | |||
# please see /etc/rc.securelevel. | |||
rmdir /home | |||
ln -sf /flash/home /home | |||
# Run flashrd final boot routine | |||
/etc/rc.flashrd.local | |||
~~~ | |||
Ainsi, /home devient un lien symbolique vers le répertoire /flash/home qui est sur une partition persistante. C'est la méthode à préférer quand /home ne contient que des données "froides". | |||
Il est également possible dans le cas ou /home accueillerait des données écrites fréquemment de créer un ramdisk à la manière de /var. Dans ce cas, au lieu de réaliser la procédure précédente, il faut modifier le fichier /etc/rc.flashrd.sub comme ceci : | |||
~~~ | |||
tardirs="var home" | |||
set -A tarsize 64M 32M # tmpfs sizes for tar dirs | |||
# | |||
# If you want to save all "tardirs" contents on shutdown: | |||
savetardirs="$tardirs" | |||
~~~ | |||
Et de la même manière, pour sauvegarder l'arborescence sans attendre le prochain reboot (propre ! Sinon les données depuis la dernière archive sont perdues) : | |||
~~~ | |||
tar cf /flash/home.tar -C /home . | |||
~~~ |
@ -0,0 +1,31 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
Pour installer sous Squeeze : | |||
<http://infogerance-linux.net/2012/installation-de-debian-squeeze-sur-un-ibm-x3550m4-avec-carte-raid-m5110-base-sur-lsi-sas2208-roc-firmware-mars-2012/> | |||
Mettre en place le RAID 1 : <http://www.youtube.com/watch?v=2nyKz9Apg6Q> | |||
## Activer les cache lectures et écritures (avec BBU) : | |||
~~~ | |||
megacli -LDSetProp -Cached -LAll -aAll | |||
megacli -LDSetProp EnDskCache -LAll -aAll | |||
megacli -LDSetProp ADRA -LALL -aALL | |||
megacli -LDSetProp WB -LALL -aALL | |||
~~~ | |||
## Infos | |||
Voir les infos globales : | |||
~~~ | |||
# megacli -AdpAllInfo -aAll | |||
~~~ | |||
Voir les infos des volumes : | |||
~~~ | |||
# megacli -LDInfo -L0 -a0 | |||
# megacli -LDInfo -L1 -a0 | |||
~~~ |
@ -0,0 +1,17 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Cloud OVH | |||
## Adressage IP | |||
Attention, pour chaque sous-réseau (public ou privé) il ne faut *pas* utiliser (outre NetID et Broadcast évidemment) les 3 adresses les plus hautes. | |||
Par exemple, pour 172.21.22.0/24 : | |||
~~~ | |||
172.21.22.0 : NetID | |||
172.21.22.252 : réservé pour OVH | |||
172.21.22.253 : réservé pour OVH | |||
172.21.22.254 : gateway OVH | |||
172.21.22.255 : Broadcast OVH | |||
~~~ |
@ -0,0 +1,74 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Howto FreeBSD | |||
## Installer un package | |||
~~~ | |||
# setenv PACKAGESITE ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-8.3-release/Latest/ | |||
# setenv FTP_PASSIVE_MODE 1 | |||
# pkg_add -r php5-simplexml | |||
Fetching ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-8.3-release/Latest/php5-simplexml.tbz... Done. | |||
~~~ | |||
## Compiler depuis l'arbre des ports | |||
~~~ | |||
# cd /usr/ports/categorie_du_paquet/nom_du_paquet | |||
# make | |||
# make install | |||
~~~ | |||
## Voir les paquets installés | |||
~~~ | |||
# pkg_info -Ix nom_du_paquet | |||
~~~ | |||
## Mises à jour avec freebsd-update(8) | |||
<http://www.freebsd.org/doc/handbook/updating-freebsdupdate.html> | |||
Exemple : | |||
~~~ | |||
# pkg_delete -a (supprime tous les packages !!) | |||
# freebsd-install | |||
# reboot | |||
# freebsd-install | |||
~~~ | |||
## Optimisations | |||
<http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/configtuning-kernel-limits.html> | |||
Optimisations réseau pour permettre un grand nombre de connexions : | |||
~~~ | |||
# sysctl kern.ipc.nmbclusters=262144 | |||
# sysctl kern.ipc.maxsockets=204800 | |||
# sysctl net.inet.tcp.msl=20000 | |||
~~~ | |||
<http://rerepi.wordpress.com/2008/04/19/tuning-freebsd-sysoev-rit/> | |||
## Admin | |||
<http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/users-groups.html> | |||
Ajout d'un groupe : | |||
~~~ | |||
# pw groupadd <groupe> | |||
# pw groupmod <groupe> -M <user> | |||
~~~ | |||
## Installer des paquets à l'identique d'un serveur à l'autre | |||
~~~ | |||
server1# for i in /var/db/pkg/*; do pkg_create -b $i; done | |||
server1# rsync *.tbz server2: | |||
server2# pkg_add -i *.tbz | |||
~~~ |
@ -0,0 +1,202 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Installation Redmine | |||
Ce document explique l'installation du logiciel Redmine depuis les sources. | |||
Cette installation à été testé sur une Debian Jessie avec Redmine en version 3.0, 3.1 et 3.2. | |||
Informations supplémentaires : | |||
* [wiki:HowToRedmine-Source/Migrate Migrer une installation existante] | |||
* [wiki:HowToRedmine-Source/Save Backup de votre installation] | |||
* [wiki:HowToRedmine-Source/Update Mettre à jour votre installation] | |||
* [wiki:HowToRedmine-Source/Delete Supprimer votre installation] | |||
* [wiki:HowToRedmine-Source/Plugins Installer des plugins] | |||
À noter : | |||
* Les catégories nomnées prérequis ne sont à faire qu'une seule fois par serveur. | |||
* Les commandes sont à lancer avec l'utilisateur entre parenthèse. | |||
### 0. Prérequis (User = root) | |||
Installations des dépendances : | |||
~~~ | |||
aptitude install ruby ruby-dev imagemagick git-core git-svn gcc build-essential libxml2-dev libxslt1-dev libssl-dev | |||
~~~ | |||
Installation des dépendances 2 (L'installation en une fois crée des conflits !) : | |||
~~~ | |||
aptitude install libmagickwand-dev libmagickcore-dev | |||
~~~ | |||
Si Squid est présent vous devez rajouter les sites github et rubygems dans sa liste blanche ! | |||
~~~ | |||
echo "<https://github.com/.*"> >> /etc/squid3/whitelist.conf | |||
echo "<http://rubygems.org/.*"> >> /etc/squid3/whitelist.conf | |||
echo "<http://.*.rubygems.org/.*"> >> /etc/squid3/whitelist.conf | |||
~~~ | |||
#### /home ne doit pas avoir l'attribut noexec !!! | |||
### I. Création du compte Unix (User = root) | |||
Choix de l'utilisateur $REDMINE propriétaire de l'application | |||
~~~ | |||
REDMINE='redmine' | |||
~~~ | |||
Création de l'utilisateur $REDMINE : | |||
~~~ | |||
useradd $REDMINE -d "/home/$REDMINE" -c "Redmine $REDMINE" -s "/bin/bash" -m | |||
~~~ | |||
Ajout de l'utilisateur www-data au groupe $REDMINE : | |||
~~~ | |||
adduser www-data $REDMINE | |||
~~~ | |||
### II. Création de la base de donnée (User = root) | |||
Au choix : | |||
* [wiki:HowToRedmine-Source/BDD/MySQL MySQL] | |||
### III. Serveur Web (User = root) | |||
Au choix : | |||
* [wiki:HowToRedmine-Source/Web/Nginx Nginx] | |||
### IV. Serveur d'application (User = root) | |||
Au choix : | |||
* [wiki:HowToRedmine-Source/Rails/Puma Puma] | |||
### V. Finalisation (User = $REDMINE) | |||
Se connecter avec l'utilisateur $REDMINE : | |||
~~~ | |||
su - $REDMINE | |||
~~~ | |||
Choisir la $BRANCHE de la version de Redmine : | |||
* voir le dépôt [Github](https://github.com/redmine/redmine) pour choisir une version | |||
* vérifier les prérequis sur [redmine.org](http://www.redmine.org/projects/redmine/wiki/FrRedmineInstall#Exigences) | |||
~~~ | |||
BRANCHE=3.3-stable | |||
~~~ | |||
Ajout des gems locales dans le $PATH : | |||
~~~ | |||
cat >> ~/.profile <<EOF | |||
if [ -d "\$HOME/.gem/ruby/2.1.0/bin" ] ; then | |||
PATH="\$HOME/.gem/ruby/2.1.0/bin:\$PATH" | |||
fi | |||
EOF | |||
~~~ | |||
Clonage du dépôt Git du projet Redmine : | |||
~~~ | |||
git clone <https://github.com/redmine/redmine.git> -b $BRANCHE ~/www | |||
~~~ | |||
Création des dossiers nécessaires : | |||
~~~ | |||
mkdir ~/files | |||
~~~ | |||
Copie de la configration de Redmine : | |||
~~~ | |||
cat > ~/www/config/configuration.yml <<EOF | |||
production: | |||
email_delivery: | |||
delivery_method: :smtp | |||
smtp_settings: | |||
address: localhost | |||
port: 25 | |||
domain: "$(hostname -d)" | |||
ssl: false | |||
enable_starttls_auto: false | |||
attachments_storage_path: /home/$USER/files | |||
autologin_cookie_secure: true | |||
EOF | |||
~~~ | |||
Récupération du mot de passe Mysql : | |||
~~~ | |||
MYSQLPASS=`grep password ~/.my.cnf|cut -d'=' -f2|tr -d ' '` | |||
~~~ | |||
Configuraion de la base de donnée : | |||
~~~ | |||
cat > ~/www/config/database.yml <<EOF | |||
production: | |||
adapter: mysql2 | |||
database: $USER | |||
host: localhost | |||
username: $USER | |||
password: "$MYSQLPASS" | |||
encoding: utf8 | |||
EOF | |||
~~~ | |||
Correction des droits : | |||
~~~ | |||
chmod u=rwX,g=rX,o= ~/www ~/www/public ~/files ~/ -R | |||
~~~ | |||
Installation des dépendances Gem avec bundle (cela peut durer plusieurs minutes) : | |||
~~~ | |||
bundle install --gemfile=~/www/Gemfile --path=~/.gem | |||
~~~ | |||
Puis prise en compte du .profile : | |||
~~~ | |||
source .profile | |||
~~~ | |||
Génération d'un clé aléatoire utilisé pour encoder les cookies de session : | |||
~~~ | |||
rake -qf ~/www/Rakefile generate_secret_token | |||
~~~ | |||
Création des schémas de la base de données redmine : | |||
~~~ | |||
rake -qf ~/www/Rakefile db:migrate RAILS_ENV=production | |||
~~~ | |||
Chargement des données par défaut : | |||
~~~ | |||
rake -qf ~/www/Rakefile redmine:load_default_data RAILS_ENV=production REDMINE_LANG=fr | |||
~~~ | |||
Migration de la base pour les plugins : | |||
~~~ | |||
rake -qf ~/www/Rakefile redmine:plugins:migrate RAILS_ENV=production | |||
~~~ | |||
### Lancement de l'application (User = root) | |||
Démarrer/éteindre l'application : | |||
~~~ | |||
systemctl start/stop puma@$REDMINE | |||
~~~ | |||
Recharger la configuration après avoir modifier /etc/puma/$REDMINE/ (pas de coupure) : | |||
~~~ | |||
systemctl reload puma@$REDMINE | |||
~~~ | |||
Redémarrer l'application : | |||
~~~ | |||
systemctl restart puma@$REDMINE | |||
~~~ | |||
Activer/désactiver l'application au démarrage : | |||
~~~ | |||
systemctl enable/disable puma@$REDMINE | |||
~~~ | |||
### Taches d'administration | |||
Lancer un shell ruby dans l'environnement de production : | |||
~~~ | |||
su - $REDMINE | |||
cd ~/www | |||
RAILS_ENV=production bundle exec rails console | |||
~~~ | |||
#### Creer un compte admin / mot de passe admin | |||
~~~ | |||
user # User.new :firstname> "Admin", :lastname => "Admin", :mail => "admin@example.com", :mail_notification => "none", :status => 1 | |||
user.login = 'admin' | |||
user.hashed_password = "4af53bd5aff3b4b8ac275cfc918244f7e61aa4cb" | |||
user.salt = "270d36d363b07abc40245d02348a53a8" | |||
user.admin = true | |||
user.save | |||
~~~ |
@ -0,0 +1,36 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Mysql | |||
### Prérequis | |||
Installation de [wiki:HowtoMySQL MySQL]. | |||
Installation des librairies de développements MySQL | |||
~~~ | |||
aptitude install libmysqlclient-dev | |||
~~~ | |||
### Configuration | |||
Création de l'utilisateur et de la base de donnée : | |||
~~~ | |||
MYSQLPASS=$(perl -e 'print map{("a".."z","A".."Z",0..9)[int(rand(62))]}(1..16)') | |||
mysql <<EOF | |||
CREATE DATABASE $REDMINE CHARACTER SET utf8; | |||
GRANT ALL PRIVILEGES ON $REDMINE.* TO "$REDMINE"@'localhost' identified by '$MYSQLPASS'; | |||
EOF | |||
~~~ | |||
Configuration autologin MySQL de l'utilisateur $REDMINE : | |||
~~~ | |||
cat > /home/$REDMINE/.my.cnf <<EOF | |||
[client] | |||
user = $REDMINE | |||
password = $MYSQLPASS | |||
EOF | |||
~~~ | |||
Correction des droits sur .my.cnf : | |||
~~~ | |||
chown $REDMINE: /home/$REDMINE/.my.cnf | |||
~~~ |
@ -0,0 +1,42 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Suppression de Redmine | |||
Pour supprimer votre installation de redmine, rien de plus simple. | |||
## I. Suppression | |||
Arrêt du service Redmine : | |||
~~~ | |||
systemctl stop puma@$REDMINE | |||
~~~ | |||
Suppression de l'utilisateur système $REDMINE ainsi que son groupe : | |||
~~~ | |||
userdel $REDMINE | |||
groupdel $REDMINE | |||
~~~ | |||
Suppression de l'application : | |||
~~~ | |||
rm -rf /home/$REDMINE /etc/init.d/redmine_$REDMINE | |||
~~~ | |||
## II. Suppression de la base de donnée | |||
* Mysql : | |||
~~~ | |||
mysql <<SQL | |||
DROP DATABASE $REDMINE; | |||
DROP USER $REDMINE@localhost; | |||
SQL | |||
~~~ | |||
## III. Suppression configuration Web | |||
* Nginx : | |||
~~~ | |||
rm /etc/nginx/ssl/redmine_$REDMINE* /etc/nginx/sites-enabled/redmine_$REDMINE /etc/nginx/sites-available/redmine_$REDMINE | |||
nginx -t | |||
if [ $? == 0 ]; then | |||
service nginx reload | |||
fi | |||
~~~ |
@ -0,0 +1,47 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Migration de votre ancienne installation Redmine | |||
Après avoir finit votre [wiki:HowToRedmine-Source installation]. | |||
Se connecter avec l'utilisateur de votre nouveau Redmine : | |||
~~~ | |||
su - $REDMINE | |||
~~~ | |||
Réaliser un dump SQL de votre ancienne installation : | |||
~~~ | |||
ssh votre-serveur-actuel.tld mysqldump database_name > redmine_dump.sql | |||
~~~ | |||
Puis stopper votre nouvelle installation : | |||
~~~ | |||
systemctl stop puma@$REDMINE | |||
~~~ | |||
Vider la base de donnée actuelle : | |||
~~~ | |||
TABLES=$(mysql $USER -e 'show tables' | awk '{ print $1}' | grep -v '^Tables' ) | |||
for t in $TABLES | |||
do | |||
echo "Deleting $t table from $USER database..." | |||
mysql $USER -e "drop table $t" | |||
done | |||
~~~ | |||
Importer votre dump SQL: | |||
~~~ | |||
mysql -D $USER --default-character-set=utf8 < redmine_dump.sql | |||
~~~ | |||
Migrer la base de données : | |||
~~~ | |||
rake -qf ~/redmine/Rakefile db:migrate RAILS_ENV=production | |||
~~~ | |||
Migrer les plugins : | |||
~~~ | |||
rake -qf ~/redmine/Rakefile redmine:plugins:migrate RAILS_ENV=production | |||
~~~ | |||
Relancer votre Redmine : | |||
~~~ | |||
systemctl start puma@$REDMINE | |||
~~~ | |||
Synchroniser les fichiers attachés : | |||
~~~ | |||
scp -Cr votre-serveur-actuel.tld:dossier-files ~/ | |||
~~~ |
@ -0,0 +1,43 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Plugins | |||
### Listes des plugins | |||
* [wiki:HowToRedmine-Source/Plugins/Redmine_multiprojects_issue Plugin Redmine Multiprojects Issue] | |||
* Permet d'assigner des projets secondaires à une demande. | |||
* [wiki:HowToRedmine-Source/Plugins/Redmine_git_hosting Plugin Redmine Git Hosting] | |||
* Permet l'intégration de Redmine avec Gitolite. | |||
* [wiki:HowToRedmine-Source/Plugins/Redmine_wiki_notes Plugin Redmine Wiki Notes] | |||
* Ajoute des macros au wiki pour afficher un bloc de type note/info/warning/tip. | |||
### Mise à jour (User = $REDMINE) | |||
*Éteindre Puma avant les mises à jours.* | |||
Rendez vous dans le dossier du plugins /home/$REDMINE/redmine/plugins/nom_plugin puis : | |||
Pour une mise à jour mineure : | |||
~~~ | |||
git pull | |||
~~~ | |||
Pour une mise à jour majeure, récuperer la dernière branche stable, vérifier les prérequis puis : | |||
~~~ | |||
git checkout $BRANCHE | |||
~~~ | |||
Effectuer ensuite les tâches post-update ci-dessous. | |||
### Taches post-installation / post-update | |||
Mise à jour des gem : | |||
~~~ | |||
bundle install --gemfile=~/www/Gemfile --path=~/.gem | |||
~~~ | |||
Migration des plugins : | |||
~~~ | |||
rake -qf ~/www/Rakefile redmine:plugins:migrate RAILS_ENV=production | |||
~~~ | |||
Correction des droits | |||
~~~ | |||
chmod u=rwX,g=rX,o= ~/www/plugins -R" | |||
~~~ |
@ -0,0 +1,116 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Plugin Redmine Git Hosting + Gitolite | |||
#### Redmine et Gitolite doivent se situer sur le même serveur ! | |||
## Prérequis | |||
Installation de gitolite 3 (sous Wheezy nécessite les backports) : | |||
~~~ | |||
aptitude install gitolite3 | |||
~~~ | |||
Installation des dépendances Redmine Git Hosting : | |||
~~~ | |||
aptitude install build-essential libssh2-1 libssh2-1-dev cmake libgpg-error-dev | |||
~~~ | |||
Mise en place de [wiki:HowtoGitDaemon git-daemon] et [wiki:HowtoGitWeb gitweb] (optionnel). | |||
## I. Installation Gitolite | |||
Choix de l'utilisateur $GITOLITE : | |||
* $GITOLITE : utilisateur propriétaire de l'application | |||
* accès SSH depuis $GITOLITE@votre-domaine.tld | |||
~~~ | |||
GITOLITE='git' | |||
~~~ | |||
Création de l'utilisateur système $GITOLITE ainsi que son groupe. | |||
~~~ | |||
useradd $GITOLITE -d "/home/$GITOLITE" -c "Gitolite $GITOLITE" -s "/bin/bash" -m | |||
~~~ | |||
Initialisation de Gitolite : | |||
~~~ | |||
cp /home/$REDMINE/.ssh/redmine_gitolite_admin_id_rsa.pub /home/$GITOLITE/ | |||
chown $GITOLITE: /home/$GITOLITE/redmine_gitolite_admin_id_rsa.pub | |||
su - $GITOLITE -c "gitolite setup -pk redmine_gitolite_admin_id_rsa.pub" | |||
rm /home/$GITOLITE/redmine_gitolite_admin_id_rsa.pub | |||
~~~ | |||
Configuration gitolite3 : | |||
~~~ | |||
chmod 750 -R /home/$GITOLITE/repositories /home/$GITOLITE/projects.list | |||
vi /home/$GITOLITE/.gitolite.rc | |||
#changer UMASK de 0077 à 0027 | |||
#changer GIT_CONFIG_KEYS de '' à '.*' | |||
#décommenter la ligne : LOCAL_CODE => "$ENV{HOME}/local" | |||
~~~ | |||
Interdit l'utilisateur $GITOLITE de se connecter avec un mot de passe et l'autorise à se connecter si l'accès SSH est limité : | |||
~~~ | |||
cat >> /etc/ssh/sshd_config <<SSH | |||
Match User $GITOLITE | |||
PasswordAuthentication no | |||
SSH | |||
sed -ie "/^AllowUsers/s/.*/& $GITOLITE/" /etc/ssh/sshd_config | |||
sed -ie "/^AllowGroups/s/.*/& $GITOLITE/" /etc/ssh/sshd_config | |||
service ssh reload | |||
~~~ | |||
### II. Installation du plugin redmine Git Hosting -User = $REDMINE) | |||
Connection en tant que l'utilisateur $REDMINE : | |||
~~~ | |||
su - $REDMINE | |||
~~~ | |||
Génération de la clé SSH : | |||
~~~ | |||
ssh-keygen -N '' -f /home/$REDMINE/.ssh/redmine_gitolite_admin_id_rsa | |||
~~~ | |||
#### Cette clé aura accès à tous les dépots de Gitolite ! | |||
Ajout de localhost dans les know_hosts de l'utilisateur $REDMINE (vous devez accepter le fingerprint !) : | |||
~~~ | |||
ssh localhost | |||
~~~ | |||
Clonage des plugins dans redmine/plugins : | |||
~~~ | |||
git clone <https://github.com/jbox-web/redmine_bootstrap_kit.git> -b v0.2.x ~/redmine/plugins/redmine_bootstrap_kit | |||
git clone <https://github.com/jbox-web/redmine_git_hosting.git> -b v1.2.x ~/redmine/plugins/redmine_git_hosting | |||
~~~ | |||
Ajout du scm Xitolite dans Redmine : | |||
~~~ | |||
echo " scm_xitolite_command: /usr/bin/git" >> ~/redmine/config/configuration.yml | |||
~~~ | |||
### III. Configuration de l'accès sudo (User = root) | |||
*A faire même si l'utilisateur $GITOLITE est le même que $REDMINE* | |||
Autorise $REDMINE à sudo vers $Gitolite : | |||
~~~ | |||
cat > /etc/sudoers.d/$REDMINE\_$GITOLITE <<SUDO | |||
Defaults:$REDMINE !requiretty | |||
$REDMINE ALL=($GITOLITE) NOPASSWD:ALL | |||
SUDO | |||
chmod 440 /etc/sudoers.d/$REDMINE\_$GITOLITE | |||
~~~ | |||
#### Si le plugin est installé après Redmine et non en même temps | |||
Exécuter les taches [wiki:HowToRedmine-Source/Plugins post-installation]. | |||
### Configuration du plugin | |||
* Rendez vous dans Administration -> Redmine Git Hosting Plugin -> SSH et remplacer : | |||
* Nom d'utilisateur Gitolite par la valeur de $GITOLITE | |||
* L'emplacement des clés privées et publiques SSH de Gitolite par le dossier .ssh de l'utilisateur $REDMINE | |||
* Rendez vous dans Administration -> Redmine Git Hosting Plugin -> Accès et remplacer : | |||
* Nom de domaine du serveur HTTP et HTTPS par le nom de domaine de votre serveur | |||
* Nom de domaine du serveur SSH par $GITOLITE.votredomain.tld | |||
* Rendez vous dans Administration -> Redmine Git Hosting Plugin -> Stockage et remplacer : | |||
* Répertoire de stockage des hooks non-core par hooks | |||
* Rendez vous dans Administration -> Redmine Git Hosting Plugin -> Hooks et remplacer : | |||
* Url des hooks par <https://votre-domaine.tld> | |||
* Cliquer en haut à droit sur installer les hooks ! | |||
* Rendez vous dans Administration -> Redmine Git Hosting Plugin -> Test de la configuration et vérifier que tous les indicateurs sont au vert |
@ -0,0 +1,18 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Plugin Redmine Multiprojects Issue | |||
Connection en tant que l'utilisateur $REDMINE : | |||
~~~ | |||
su - $REDMINE | |||
~~~ | |||
Clonage des plugins dans redmine/plugins : | |||
~~~ | |||
git clone <https://github.com/jbbarth/redmine_base_select2.git> /home/$REDMINE/redmine/plugins/redmine_base_select2 | |||
git clone <https://github.com/jbbarth/redmine_base_deface.git> /home/$REDMINE/redmine/plugins/redmine_base_deface | |||
git clone <https://github.com/nanego/redmine_multiprojects_issue.git> /home/$REDMINE/redmine/plugins/redmine_multiprojects_issue | |||
~~~ | |||
#### Si le plugin est installé après Redmine et non en même temps : | |||
Exécuter les taches [wiki:HowToRedmine-Source/Plugins post-installation]. |
@ -0,0 +1,16 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Plugin Redmine Wiki Notes | |||
Connection en tant que l'utilisateur $REDMINE : | |||
~~~ | |||
su - $REDMINE | |||
~~~ | |||
Clonage du plugin dans redmine/plugins : | |||
~~~ | |||
git clone <https://github.com/dseifert/redmine_wiki_notes.git> | |||
~~~ | |||
#### Si le plugin est installé après Redmine et non en même temps : | |||
Exécuter les taches [wiki:HowToRedmine-Source/Plugins post-installation]. |
@ -0,0 +1,66 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Puma | |||
### 0. Prérequis | |||
Installation de Puma : | |||
~~~ | |||
gem install puma | |||
~~~ | |||
Création du dossier de configuration : | |||
~~~ | |||
mkdir /etc/puma | |||
~~~ | |||
Création d'un service SystemD : | |||
~~~ | |||
cat > /etc/systemd/system/puma@.service <<EOF | |||
[Unit] | |||
Description=Puma HTTP server for Ruby Apps : %i | |||
After=network.target | |||
[Service] | |||
PermissionsStartOnly=true | |||
ExecStartPre=/bin/mkdir -p %t/%i | |||
ExecStartPre=/bin/chown %i: %t/%i | |||
User=%i | |||
Group=%i | |||
UMask=0027 | |||
#WorkingDirectory=/home/%i/www | |||
PrivateTmp=true | |||
PIDFile=/run/%i/ruby.pid | |||
ExecStart=/usr/local/bin/puma --bind unix:///run/%i/ruby.sock?umask=0007 --pidfile /run/%i/ruby.pid --dir /home/%i/www --config /etc/puma/%i.rb | |||
ExecReload=/bin/kill -USR2 $MAINPID | |||
KillMode=process | |||
Restart=on-failure | |||
[Install] | |||
WantedBy=multi-user.target | |||
Alias=puma_%i.service | |||
EOF | |||
~~~ | |||
Correction des droits du service SystemD | |||
~~~ | |||
chmod 644 /etc/systemd/system/puma@.service | |||
systemctl daemon-reload | |||
~~~ | |||
### 1. Configuration | |||
Création du fichier de configuration de Puma pour l'utilisateur $REDMINE : | |||
~~~ | |||
cat > /etc/puma/$REDMINE.rb <<EOF | |||
environment 'production' | |||
workers 2 | |||
threads 0, 8 | |||
tag 'Redmine $REDMINE' | |||
EOF | |||
~~~ | |||
Correction des droits du fichier de configuration | |||
~~~ | |||
chmod 740 /etc/puma/$REDMINE.rb | |||
chown $REDMINE:www-data /etc/puma/$REDMINE.rb | |||
~~~ |
@ -0,0 +1,23 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Sauvegarde de votre installation Redmine | |||
Connexion en tant que l'utilisateur $REDMINE : | |||
~~~ | |||
su - $REDMINE | |||
~~~ | |||
Export de la base Mysql : | |||
~~~ | |||
mysqldump $USER > redmine_dump.sql | |||
~~~ | |||
Sauvegarde de la configuration de Redmine : | |||
~~~ | |||
tar -zcvf ~/$USER_config.tgz ~/redmine/config | |||
~~~ | |||
Sauvegarde des fichiers attachées : | |||
~~~ | |||
tar -zcvf ~/$USER_files.tgz ~/files | |||
~~~ |
@ -0,0 +1,77 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Mise à jour de votre installation Redmine | |||
Connection en tant que l'utilisateur $REDMINE : | |||
~~~ | |||
# su - $REDMINE | |||
$ umask 022 | |||
~~~ | |||
Rendez vous dans le dossier d'installation de Redmine : | |||
~~~ | |||
$ cd ~/redmine | |||
~~~ | |||
## Pour faire une mise à jour mineure (ex: 3.0.2 vers 3.0.3) | |||
~~~ | |||
# su - $REDMINE | |||
$ umask 022 | |||
$ cd ~/redmine | |||
$ git pull | |||
$ bundle update | |||
# systemctl restart puma@$REDMINE | |||
# systemctl status puma@$REDMINE | |||
~~~ | |||
## Pour faire une mise à jour majeure (ex: 2.6 vers 3.0) | |||
Déterminer votre branche courante (elle est précédé d'un étoile) : | |||
~~~ | |||
$ git branch | |||
~~~ | |||
Lister les branches distantes (ne prendre en compte que les versions stables) : | |||
~~~ | |||
$ git pull | |||
$ git branch -r | |||
~~~ | |||
Si une version plus récente de Redmine est présente, vérifier les prérequis en vous rendant sur [redmine.org](http://www.redmine.org/projects/redmine/wiki/RedmineInstall#Requirements) | |||
Version de Ruby et de Ruby on Rails : | |||
~~~ | |||
$ ruby -v | |||
$ rails -v | |||
~~~ | |||
Si les prérequis sont satisfaits : | |||
~~~ | |||
# systemctl stop puma@$REDMINE | |||
# su - $REDMINE | |||
$ umask 022 | |||
$ gem update puma --user | |||
$ cd ~/redmine | |||
# systemctl stop puma@$REDMINE | |||
$ git pull | |||
$ git checkout $BRANCHE | |||
$ rm Gemfile.lock | |||
$ bundle update | |||
$ rake -q db:migrate RAILS_ENV=production | |||
# systemctl start puma@REDMINE | |||
$ systemctl status puma@REDMINE | |||
~~~ | |||
Mise à jour des plugins (exemple avec le plugin foo) : | |||
~~~ | |||
# su - $REDMINE | |||
$ umask 022 | |||
$ cd ~/redmine | |||
# systemctl stop puma@$REDMINE | |||
$ cd plugins ; ls | |||
$ cd foo | |||
$ git pull && git branch -r | |||
$ rake -q redmine:plugins:migrate RAILS_ENV=production | |||
# systemctl start puma@REDMINE | |||
$ systemctl status puma@REDMINE | |||
~~~ |
@ -0,0 +1,82 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Nginx | |||
### Prérequis | |||
Installation de [wiki:HowtoNginx Nginx]. | |||
### Configuration | |||
Création du dossier de log : | |||
~~~ | |||
mkdir /var/log/nginx/$REDMINE | |||
chown www-data:adm /var/log/nginx/$REDMINE | |||
chmod u=rwx,g=rxs,o= /var/log/nginx/$REDMINE | |||
~~~ | |||
Création du vhost $REDMINE : | |||
~~~ | |||
cat > /etc/nginx/sites-available/$REDMINE <<EOF | |||
upstream ruby_$REDMINE { | |||
server unix:/run/$REDMINE/ruby.sock fail_timeout=0; | |||
} | |||
server { | |||
server_name $REDMINE.$(hostname -d); | |||
listen 0.0.0.0:80; | |||
listen [::]:80; | |||
# listen 0.0.0.0:443 ssl; | |||
# listen [::]:443 ssl; | |||
# if ( $scheme = http ) { | |||
# return 301 <https://$server_name$request_uri;> | |||
# } | |||
# ssl_certificate /etc/ssl/certs/redmine_$REDMINE.crt; | |||
# ssl_certificate_key /etc/ssl/private/redmine_$REDMINE.key; | |||
root /home/$REDMINE/www/public; | |||
access_log /var/log/nginx/$REDMINE/access.log; | |||
error_log /var/log/nginx/$REDMINE/error.log; | |||
error_page 503 @maintenance; | |||
location / { | |||
if (!-f /run/$REDMINE/ruby.pid) { | |||
return 503; | |||
} | |||
try_files \$uri @ruby; | |||
} | |||
location @maintenance { | |||
#proxy_pass <http://maintenance-url.com;> | |||
rewrite ^(.*)$ /500.html break; | |||
} | |||
location @ruby { | |||
proxy_set_header X-Forwarded-Proto \$scheme; | |||
proxy_set_header X-Forwarded-For \$remote_addr; | |||
proxy_set_header Host \$<http_host;> | |||
proxy_redirect off; | |||
proxy_read_timeout 300; | |||
proxy_pass <http://ruby_$REDMINE;> | |||
} | |||
} | |||
EOF | |||
~~~ | |||
Activation du vhost $REDMINE : | |||
~~~ | |||
ln -s /etc/nginx/sites-available/$REDMINE /etc/nginx/sites-enabled/$REDMINE | |||
~~~ | |||
Pour mettre en place le ssl, voir [wiki:HowtoSSL] et nommée votre certificat et votre clé comme ceci : | |||
* /etc/ssl/certs/redmine_$REDMINE.crt | |||
* /etc/ssl/private/redmine_$REDMINE.key. | |||
Test de la configuration nginx et rechargement le cas échéant : | |||
~~~ | |||
nginx -t | |||
if [ $? == 0 ]; then | |||
service nginx reload | |||
fi | |||
~~~ | |||
#### Si iptables est configuré, pensez à ouvrir les ports 80 et 443 entrants ! |
@ -0,0 +1,7 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Connexion sur port différent de 22 | |||
~~~ | |||
sftp -o "Port 3432" user@host | |||
~~~ |
@ -0,0 +1,32 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Howto ACL | |||
Savoir que le fichier a un ACL configuré (+) : | |||
~~~ | |||
$ ls -dl foo/ | |||
drwxr-x---+ ... | |||
~~~ | |||
### Obtenir ACL | |||
~~~ | |||
# getfacl foo/ | |||
~~~ | |||
récupérer le statut ACL sur le fichier. | |||
### Modifier ACL | |||
~~~ | |||
# setfacl -R -m group:example:rwx foo/ | |||
~~~ | |||
-R : récursif, -m : pour modifier. | |||
~~~ | |||
# setfacl -d -R -m group:example:rwx foo/ | |||
~~~ | |||
-d : défaut | |||
@ -0,0 +1,105 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
## Howto Alfresco Community | |||
### Installation | |||
Installer Tomcat 6 (voir [wiki:HowtoTomcat]) | |||
Installer MySQL (voir [wiki:HowtoMySQL]) | |||
Installer JDBC : | |||
~~~ | |||
# aptitude install libmysql-java | |||
# cd /usr/share/tomcat6/lib/ | |||
# ln -s ../../java/mysql-connector-java.jar mysql.jar | |||
~~~ | |||
Si cela n'est pas fait, vous aurez les erreurs très explicites : | |||
~~~ | |||
Caused by: org.hibernate.HibernateException: Hibernate Dialect must be explicitly set) | |||
~~~ | |||
Alfresco a aussi besoin d'OpenOffice et ImageMagick : | |||
~~~ | |||
# aptitude install openoffice.org-headless imagemagick | |||
~~~ | |||
Egalement l'outil _swftools_ non disponible sous Debian Lenny, on va donc se servir chez les voisins : | |||
~~~ | |||
wget <https://launchpad.net/ubuntu/+source/swftools/0.8.1-2.1ubuntu1/+build/924585/+files/swftools_0.8.1-2.1ubuntu1_amd64.deb> | |||
dpkg -i swftools_0.8.1-2.1ubuntu1_amd64.deb | |||
~~~ | |||
Il faut aussi préparer un répertoire pour le "contentstore" (stockage brut des documents), un autre pour les documents supprimés (à purger de temps en temps), un pour les index _Lucene_ et un autre pour les sauvegardes de ces index. Par exemple : | |||
~~~ | |||
# mkdir /srv/contentstore /srv/contentstore.deleted /srv/indexes /srv/indexes.backup | |||
# chown tomcat6:tomcat6 /srv/contentstore /srv/contentstore.deleted /srv/indexes /srv/indexes.backup | |||
~~~ | |||
Pour configurer Alfresco, le plus simple est de créer un fichier _alfresco-global.properties_ (à mettre par exemple dans _/var/lib/tomcat6/shared/classes/_) : | |||
~~~ | |||
db.name=NOM BDD | |||
db.username=USER BDD | |||
db.password=PASS BDD | |||
db.host=127.0.0.1 | |||
db.port=3306 | |||
db.driver=org.gjt.mm.mysql.Driver | |||
db.url=jdbc:mysql://${db.host}:${db.port}/${db.name} | |||
hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect | |||
ooo.exe=/usr/bin/soffice | |||
img.root=/usr | |||
swf.exe=/usr/bin/pdf2swf | |||
dir.root=/srv | |||
dir.contentstore=${dir.root}/contentstore | |||
dir.contentstore.deleted=${dir.root}/contentstore.deleted | |||
dir.auditcontentstore=${dir.root}/audit.contentstore | |||
dir.indexes=${dir.root}/indexes | |||
dir.indexes.backup=${dir.root}/indexes.backup | |||
~~~ | |||
Pour une configuration avancée, on utilisera le répertoire _/var/lib/tomcat6/shared/classes/alfresco/extension/_. | |||
Par exemple pour customiser les logs d'Alfresco, on créera un fichier _myalfresco-log4j.properties_ : | |||
~~~ | |||
log4j.appender.File2=org.apache.log4j.DailyRollingFileAppender | |||
log4j.appender.File2.File=/var/log/tomcat6/alfresco.log | |||
log4j.appender.File2.Append=true | |||
log4j.appender.File2.DatePattern='.'yyyy-MM-dd | |||
log4j.appender.File2.layout=org.apache.log4j.PatternLayout | |||
log4j.appender.File2.layout.ConversionPattern=%d{ABSOLUTE} %-5p [%c] %m%n | |||
log4j.rootLogger=error, Console, File2 | |||
~~~ | |||
Note : penser à créer le /var/log/tomcat6/alfresco.log avec les bons droits | |||
Télécharger alfresco-community-war-3.3.zip sur <http://sourceforge.net/projects/alfresco/files/Alfresco/3.3%20Community%20Edition/alfresco-community-war-3.3.zip/download> | |||
et déployer les fichiers WAR (alfresco.war, share.war si besoin) dans le répertoire _/var/lib/tomcat6/webapps/_, puis : | |||
~~~ | |||
# /etc/init.d/tomcat6 restart | |||
~~~ | |||
### Administration JMX | |||
<http://wiki.alfresco.com/wiki/JMX> | |||
On peut utiliser l'outil _jconsole_ avec les paramètres suivants : | |||
~~~ | |||
Remote process = service:jmx:rmi:///jndi/rmi://localhost:50500/alfresco/jmxrmi | |||
Username = controlRole | |||
Password = change_asap | |||
~~~ | |||
Note : mots de passe à changer via les fichiers _alfresco-jmxrmi.*_ | |||
@ -0,0 +1,800 @@ | |||
**Cette page a été importée automatiquement de notre ancien wiki mais n'a pas encore été révisée.** | |||
# Howto Ansible | |||
<http://docs.ansible.com/> | |||
Ansible est une plateforme de configuration et gestion de serveurs : il permet le déploiement de logiciels et l'execution de tâches via une connexion SSH. | |||
Ansible est *agent-less* et utilise le concept d’*[idempotence](https://fr.wikipedia.org/wiki/Idempotence)* : on décrit l'état d'un serveur dans un fichier YAML appelé *playbook* et des actions seront executées dans le but de rendre le serveur conforme à cette description. | |||
On pourra relancer Ansible plusieurs fois, l'état final reste le même : seules les actions nécessaires seront exécutées. | |||
Ansible peut exécuter des actions sur des serveurs distants sous : | |||
* *Debian* 6 et supérieur (nécessite uniquement _Python_ ce qui est le cas par défaut) | |||
* Debian 4 / 5 : voir [#AnsiblesurdesvieillesversionsDebian] | |||
* *FreeBSD* et *OpenBSD* : TODO => décrire pré-requis | |||
## Installation | |||
Nous utilisons Ansible 2.0.2 (disponible via <http://pub.evolix.net/jessie/)> sous Debian 8 : | |||
~~~ | |||
# apt install --allow-unauthenticated ansible=2.0.2.0-1~bpo8+1 | |||
~~~ | |||
## Utilisation | |||
~~~ | |||
$ ansible --version | |||
ansible 2.0.2.0 | |||
config file = /etc/ansible/ansible.cfg | |||
configured module search path = Default w/o overrides | |||
$ cat ~/.ansible.cfg | |||
[defaults] | |||
inventory = $HOME/.ansible/hosts | |||
[ssh_connection] | |||
#ssh_args = -o ControlMaster=no -o ControlPersist=no | |||
ssh_args = -o ControlMaster=auto -o ControlPersist=300s | |||
pipelining = True | |||
$ echo HOSTNAME >> ~/.ansible/hosts | |||
$ ssh-copy-id HOSTNAME | |||
$ ansible HOSTNAME -i $HOME/.ansible/hosts -m ping | |||
HOSTNAME | SUCCESS => { | |||
"changed": false, | |||
"ping": "pong" | |||
} | |||
$ ansible HOSTNAME -a "date" | |||
HOSTNAME | SUCCESS | rc=0 >> | |||
jeudi 26 mai 2016, 23:16:01 (UTC+0200) | |||
$ ansible-playbook PLAYBOOK.yml --limit HOSTNAME --forks 1 | |||
$ ansible-playbook PLAYBOOK_WITH-SUDO.yml --limit HOSTNAME --ask-become-pass | |||
~~~ | |||
Options utiles pour [ansible-playbook](https://manpages.debian.org/cgi-bin/man.cgi?query=ansible-playbook&apropos=0&sektion=0&manpath=Debian+unstable+sid&format=html&locale=en) : | |||
* *-vvvv* : très verbeux (utile notamment pour debug SSH quand on a une erreur _unreachable_) | |||
* *-k / --ask-pass* : demande le mot de passe utilisateur (si connexion SSH sans clé) | |||
* *-K / --ask-become-pass* : demande le mot de passe utilisateur pour sudo | |||
* *-l / --limit HOSTNAME* : limite la connexion au serveur HOSTNAME (attention, par défaut c'est *all*, cf `/etc/ansible/hosts`) | |||
* *-f / --forks N* : nombre de process lancé en parallèle (par défaut 5)... peut être utile de mettre à 1 pour ne pas paralléliser | |||
## Howto Playbook | |||
~~~ | |||
$ vim hello_World.yml | |||
- hosts: all | |||
tasks: | |||
- shell: echo hello World | |||
# vim:ft=ansible: | |||
~~~ | |||
Un playbook est un ensemble de "plays" ; un "play" contient au minimum *hosts* (serveurs cible) et *tasks* (ensemble de tâches), et peut également contenir : | |||
* *vars* : des variables | |||
* *handlers* : des actions déclenchées si une tâche a été exécutée (via l'option `notify`) | |||
* *roles* : des rôles pour avoir des playbooks organisés et modulaires | |||
### Modules pour tasks | |||
<http://docs.ansible.com/ansible/list_of_all_modules.html> | |||
Pour avoir la liste des modules utilisables dans *tasks* : `ansible-doc -l` | |||
Voici quelques exemples : | |||
~~~ | |||
- name : exemple avec le module COMMAND | |||
command: date | |||
- name : exemple avec le module SHELL | |||
shell: time date | |||
- name: exemple avec le module SERVICE | |||
service: name=<httpd> state=restarted | |||
- name: exemple avec le module FILE | |||
file: path=/etc/cron.daily/apticron state=absent | |||
- name : exemple avec le module COPY | |||
copy: src=files/foo dest=/etc/bar owner=root group=root mode=0644 | |||
- name : exemple avec le module LINEINFILE | |||
lineinfile: dest=/etc/evocheck.cf insertafter=EOF line="IS_APTICRON=0" regexp="^IS_APTICRON=" | |||
- name : exemple avec le module USER | |||
user: | |||
state: present | |||
name: {{ name }} | |||
comment: 'John Doe' | |||
shell: /bin/bash | |||
groups: adm | |||
append: yes | |||
password: '$6$k/Fg76xH' | |||
- name : exemple avec le module REPLACE | |||
replace: | |||
dest: /etc/ssh/sshd_config | |||
regexp: '^(Match User ((?!{{ name }}).)*)$' | |||
replace: '\1,{{ name }}' | |||
- name : exemple avec le module STAT | |||
stat: path=/etc/sudoers.d/foo | |||
register: foo_sudoers_file | |||
- name : exemple avec le module APT | |||
apt: | |||
name: '{{ item }}' | |||
state: latest | |||
allow_unauthenticated: yes | |||
update_cache: yes | |||
cache_valid_time: 3600 | |||
with_items: | |||
- vim | |||
- htop | |||
- name : exemple | |||
apt_repository: | |||
- name: exemple avec le module INI_FILE | |||
ini_file: | |||
dest: /root/.my.cnf | |||
section: client | |||
option: user | |||
value: root | |||
mode: 0640 | |||
- name: exemple avec le module MYSQL_USER (nécessite le paquet python_mysqldb) | |||
mysql_user: | |||
name: mysqladmin | |||
password: my_password | |||
priv: "*.*:ALL,GRANT" | |||
state: present | |||
config_file: /root/.my.cnf | |||
update_password: on_create | |||
- name: exemple avec l'ajout de plusieurs lignes dans un fichier | |||
blockinfile: | |||
dest: /etc/apache2/envvars | |||
block: | | |||
## Set umask for writing by Apache user. | |||
## Set rights on files and directories written by Apache | |||
- name: exemple | |||
systcl: | |||
- name: exemple | |||
alternatives: | |||
- name: exemple | |||
service: | |||
- name: exemple | |||
mount: | |||
~~~ | |||
#### replace: vs lineinfile: | |||
* lineinfile: si regexp= n'est pas matché... il insère quand même la ligne ! avec lineinfile: regexp= n'est pas une condition pour l'insertion mais une condition pour remplacer au lieu d'insérer ! | |||
* avec lineinfile: sauf cas tordus, regexp= doit matcher line= (sinon il va insérer line= à l'infini !) | |||
* lineinfile: va 1. regarder si regexp= existe et il remplace la dernière ligne, 2. si regexp n'existe pas, il ajoute line= (sans d'autre condition... même si elle existe déjà) | |||
* replace: il va remplacer uniquement si regex est matché, logique (comme sed) | |||
* si l'on veut utiliser une référence (\1) dans line# avec lineinfile:> erreur, il faut utiliser replace: | |||
* avec lineinfile: backrefs=yes c'est pour utiliser une référence au sein de regexp= (et non pas au sein de line=) | |||
### vars | |||
Gestion des variables : | |||
~~~ | |||
vars: | |||
ip: 31.170.9.129 | |||
conf_file: /etc/foo.conf | |||
tasks: | |||
- shell: echo {{ ip }} {{ conf_file }} | |||
~~~ | |||
Pour gérer de nombreuses variables dans un projet, voici l'arborescence conseillée : | |||
~~~ | |||
group_vars/ | |||
group1 # here we assign variables to particular groups | |||
group2 # "" | |||
host_vars/ | |||
hostname1 # if systems need specific variables, put them here | |||
hostname2 # "" | |||
~~~ | |||
### Handlers | |||
La directive `notify` permet de déclencher un `handler` après la fin d'éxecution d'une tâche : | |||
~~~ | |||
tasks: | |||
- apt: ... | |||
notify: Done | |||
handlers: | |||
- name: Done | |||
shell: echo "It's done" | |||
~~~ | |||
Le redémarrage d'un service devrait toujours être effectué via handler. | |||
### Tags | |||
<https://docs.ansible.com/ansible/playbooks_tags.html> | |||
Hormis le fait de ranger/trier chaque tâche dans une catégorie, permet de limiter/exclure des tâches. | |||
~~~ | |||
- name: Coucou | |||
debug: msg="Saloute!" | |||
tags: message | |||
... | |||
~~~ | |||
Pour ne pas afficher les messages : | |||
~~~ | |||
$ ansible-playbook ... --skip-tags "message" | |||
~~~ | |||
On peut appliquer des tags à des rôles, ou voir directement n'éxecuter que certains tags : | |||
~~~ | |||
$ ansible-playbook ... --tags "configuration,packages" | |||
~~~ | |||
Note : on peut également _taguer_ des `include`. | |||
### Register | |||
`register`. est un élément/champ que l'on peut rajouter pour tout type de tâche et qui initialisera la variable (par le nom donné) avec les valeurs retour du module. | |||
Pour shell, on a le droit à `.stdout`, `.stderr`, `.rc`, ... Mais cela dépend bien des valeurs de retour du module. | |||
Mais pour être sûr des valeurs initialisées, on peut utiliser `debug` afin d'analyser le résultat. | |||
~~~ | |||
- stat: path=/etc/passwd | |||
register: st | |||
- debug: var=st | |||
- fail: msg="Whoops! file ownership has changed" | |||
when: st.stat.pw_name != 'root' | |||
~~~ | |||
Pour certains modules, `register` est un passage obligatoire pour une utilisation cohérente des éléments (stat...). | |||
## Configuration | |||
<https://docs.ansible.com/ansible/intro_configuration.html> | |||
La configuration est lue dans l'ordre suivant : | |||
~~~ | |||
* ANSIBLE_CONFIG (an environment variable) | |||
* ansible.cfg (in the current directory) | |||
* .ansible.cfg (in the home directory) | |||
* /etc/ansible/ansible.cfg | |||
~~~ | |||
### Fichier "inventory" | |||
<http://docs.ansible.com/ansible/intro_inventory.html> | |||
Permet d'indiquer la liste des machines concernées par Ansible (peut être limité lors de l'exécution de la commande par l'option `-l`) et de pouvoir les regrouper dans des groupes. | |||
Exemple: | |||
~~~ | |||
hostname.internal | |||
[<httpservers>] | |||
machine[01:57].example.com | |||
<http.example.com:2222> | |||
[dbservers] | |||
machine12.example.com | |||
machine50.example.com | |||
m[a:o]chine52.example.com | |||
alias ansible_port=2222 ansible_host=192.168.1.50 | |||
[client] | |||
host1 <http_port=80> maxRequestsPerChild=808 #des variables qui seront automatiquement auto-completé lié à cet host | |||
[commercant] | |||
mercerie | |||
chapeautier | |||
[commercant:vars] | |||
ntp_server=ntp.mercerie.example.com | |||
proxy=proxy.mercerie.example.com | |||
~~~ | |||
* *hostname.internal* : host hors groupe | |||
* *[<httpservers>]* : le nom du groupe (pour les serveurs <http).> Les noms de hosts qui suivent appartiendront à ce groupe | |||
* *machine[01:57].evolix.net* : on peut indiquer une [pseudo-]expression régulière - ici ajoutera les machines _machine01.evolix.net_, _machine02.evolix.net_, _machine03.evolix.net_, ..., _machine57.evolix.net_ | |||
* *<http.evolix.net:2222*> : ansible se connecte par ssh, et _<http.evolix.net_> a un port ssh d'écoute différent qui est 2222 | |||
* *[dbservers]* : groupe pour les serveurs de base de donnée | |||
* *machine50.example.com* : cette machine est déjà présente dans le groupe _<httpservers_,> mais sera aussi accessible à partir du groupe _dbservers_ | |||
* *alias ansible_port=2222 ansible_host=192.168.1.50* : la machine alias n'est pas un vrai FQDN mais pointera vers _192.168.1.50_ car on a indiqué des variables propre à _ansible_. Il est aussi disponible `ansible_connection` (local ou ssh) ou `ansible_user` (le nom de l'utilisateur de la machine distante avec lequel _ansible_ se connectera en ssh) | |||
* *host1 <http_port=80> maxRequestsPerChild=808* : des variables qui seront automatiquement auto-completé lié à host1 | |||
* *[commercant:vars]* : des variables qui seront liés au groupe _commercant_. On peut aussi créer des groupes de groupes en utilisant `:children` | |||
On peut aussi découper le fichier "inventory" selon les groupes et les variables : [<http://docs.ansible.com/ansible/intro_inventory.html#splitting-out-host-and-group-specific-data>]. | |||
Les variables propres à Ansible : [<http://docs.ansible.com/ansible/intro_inventory.html#list-of-behavioral-inventory-parameters>] | |||
### ansible.cfg | |||
Options utiles (TODO : à revoir) : | |||
* *display_args_to_stdout* : mettre à `True` si on veut voir tout le contenu du _tasks_ executé pour chaque étape écrit sur _stdout_ | |||
* *display_skipped_hosts* : mettre à `False` si on ne veut pas voir affiché sur _stdout_ l'information d'un _task_ qui n'est pas exécuté _(le nom de variable est confu - mais il s'agit bien de l'affichage du task)_ | |||
* *error_on_undefined_vars* : mettre à `True` pour être sûr que le script ansible s'arrête si une variable n'est pas défini (alors qu'il y a utilisation de cette dernière dans une _task_) | |||
* *force_color* : mettre à `1` pour forcer la couleur | |||
* *forks* : le nombre de processus en parallèle possible lors déploiement du script ansible sur nombreux _hosts_. | |||
* *module_lang* : changer la langue | |||
* *module_name* : le module par défaut (`command`) lors de l'utilisation de la commande `ansible` | |||
* *hosts* : accès vers les _hosts_ par défaut (`all`) | |||
* *private_key_file* : le chemin pour la clé pem | |||
* *remote_port* : le port ssh par défaut (`22`) | |||
* *remote_user* : l'utilisateur pour la connexion ssh par défaut (`root`) | |||
* *retry_files_enabled* : mettre à `True` pour la création de fichier `.retry` après une failure de ansible pour reprendre le travail précédent - ajouté en argument dans l'appel de la commande | |||
## Erreurs | |||
### unbalanced jinja2 block or quotes | |||
~~~ | |||
fatal: [test.evolix.net]: FAILED! => {"failed": true, "reason": "error while splitting arguments, either an unbalanced jinja2 block or quotes"} | |||
~~~ | |||
Vérifier bien la syntaxe du document qui est référé pour cette erreur. Cela peut être une quote mal fermé (ou mélange simple quote, double quote), ou encore histoire de crochet devenant une parenthèse... | |||
### UNREACHABLE! | |||
~~~ | |||
fatal: [test.evolix.net]: UNREACHABLE! => {"changed": false, "msg": "SSH encountered an unknown error during the connection. We recommend you re-run the command using -vvvv, which will enable SSH debugging output to help diagnose the issue", "unreachable": true} | |||
~~~ | |||
Malheureusement, cela arrive souvent sur certaines machines (une?), mais pas de solutions pour le moment -> boire du café - beaucoup de café. | |||
Du côté de la machine distante, dans le fichier `/var/log/auth.log`: | |||
~~~ | |||
14:56:29 localhost sshd[19915]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=dual.evolix.net user=service | |||
14:56:31 localhost sshd[19915]: Accepted password for service from 192.168.4.137 port 42502 ssh2 | |||
14:56:31 localhost sshd[19915]: pam_unix(sshd:session): session opened for user service by (uid=0) | |||
14:56:31 localhost systemd-logind[641]: New session 181 of user service. | |||
14:56:32 localhost sshd[19915]: pam_unix(sshd:session): session closed for user service | |||
14:56:32 localhost systemd-logind[641]: Removed session 181. | |||
~~~ | |||
Et quand ça marche - la session ne se referme pas, et est réutilisé par les exécutions playbook suivantes: | |||
~~~ | |||
14:58:57 localhost sshd[20339]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=dual.evolix.net user=service | |||
14:59:00 localhost sshd[20339]: Accepted password for service from 192.168.4.137 port 42511 ssh2 | |||
14:59:00 localhost sshd[20339]: pam_unix(sshd:session): session opened for user service by (uid=0) | |||
14:59:00 localhost systemd-logind[641]: New session 182 of user service. | |||
... | |||
15:01:08 localhost sshd[23034]: Received disconnect from 192.168.4.137: 11: disconnected by user | |||
15:01:08 localhost sshd[23024]: pam_unix(sshd:session): session closed for user service | |||
15:01:08 localhost systemd-logind[641]: Removed session 182. | |||
~~~ | |||
Mais si tentative de déploiement ansible juste après la session supprimé (par ex la 182), c'est à ce moment là qu'on se retrouve avec des *UNREACHABLE* -> savoir pourquoi sshd supprime la session ssh... | |||
### Missing required arguments | |||
~~~ | |||
fatal: [test.evolix.net]: FAILED! => {"changed": false, "failed": true, "msg": "missing required arguments: section"} | |||
~~~ | |||
Le message est assez clair, donc bien relire la doc du module sur ansible, et toujours ajouter les arguments obligatoires pour ce module. | |||
### Requires stdlib json or simplejson module | |||
~~~ | |||
fatal: [lenny.evolix.net]: FAILED! => {"changed": false, "failed": true, "msg": "Error: ansible requires the stdlib json or simplejson module, neither was found!"} | |||
~~~ | |||
~~~ | |||
# apt install python-simplejson | |||
~~~ | |||
## Astuces | |||
### Vérifier un playbook | |||
* Vérifier la syntaxe : | |||
~~~ | |||
$ ansible-playbook --syntax-check my-experimental-playbook.yml | |||
~~~ | |||
<http://www.yamllint.com/> | |||
* vérifier les action qui vont être faite (mode _dry-run_) sans rien exécuter : | |||
~~~ | |||
$ ansible-playbook --check my-experimental-playbook.yml | |||
~~~ | |||
* avoir le diff des fichiers modifiés (ne marche pas avec les modules replace/lineinfile à priori) : | |||
~~~ | |||
$ ansible-playbook --check --diff my-experimental-playbook.yml | |||
~~~ | |||
### Plus d'infos sur module | |||
Lister les modules: | |||
~~~ | |||
# ansible-doc -l | |||
~~~ | |||
Avoir des infos sur un module: | |||
~~~ | |||
# ansible-doc shell | |||
> SHELL | |||
The [shell] module takes the command name followed by a li | |||
space-delimited arguments. It is almost exactly like the [ | |||
... | |||
~~~ | |||
### Stopper l'éxecution du code | |||
Pour par exemple, stopper le code à un moment pour lire les valeurs d'une variables | |||
~~~ | |||
- debug: var=cequejeveuxvoir | |||
- command: /bin/false | |||
~~~ | |||
ou | |||
~~~ | |||
- debug: var=cequejeveuxvoir | |||
- fail: msg="FAIL" | |||
~~~ | |||
ou | |||
~~~ | |||
- debug: var=cequejeveuxvoir | |||
- pause: | |||
~~~ | |||
### Ansible sur des vieilles versions Debian | |||
* Installer package python | |||
[<https://docs.ansible.com/ansible/raw_module.html>] | |||
(bzip2, php, ... selon services à installer) | |||
~~~ | |||
- raw: apt-get -y install python-simplejson [bzip2 php5-cli] | |||
~~~ | |||
* Si pas encore fait, donner droit mysql à l'utilisateur | |||
~~~ | |||
> GRANT ALL ON db.* TO 'user'@'localhost'; | |||
~~~ | |||
### Limiter l'exécution à certaines machines | |||
* Limiter aux groupes www et sql (www et sql peuvent en fait être indifféremment des groupes ou des serveurs) : | |||
~~~ | |||
$ ansible-playbook -l "www:sql" playbook.yml | |||
~~~ | |||
* limiter aux serveurs foo-www01, foo-lb01, foo-filer, etc… : | |||
~~~ | |||
$ ansible-playbook -l "foo-*" playbook.yml | |||
~~~ | |||
* limiter aux 10 premiers serveurs de l'inventaire (utile pour faire par paquets) : | |||
~~~ | |||
$ ansible-playbook -l "*[0:9]" playbook.yml | |||
~~~ | |||
* puis à ceux restant : | |||
~~~ | |||
$ ansible-playbook -l "*[10:]" playbook.yml | |||
~~~ | |||
Il est de toute façon préférable de ne pas mettre *all* dans le champs *hosts* dans le playbook pour éviter un -_possible_- oublie de "limite" de machines. | |||
### Lancement tâches hosts asynchrone | |||
Pour éviter que les différentes tâches s'appliquent une par une sur tout les hosts impliqués par le déploiement du play ansible, on peut utiliser l'option `strategy` à la valeur `free` pour que chaques tâches sur un host puisse continuer dès la fin de son exécution sans attendre l'état des autres hosts concernés en cours. | |||
~~~ | |||
- hosts: all | |||
... | |||
strategy: free | |||
~~~ | |||
_Ne plus se fier au texte `host changed` après texte de la tâche, car il pourrait s'agir d'une autre tâche affiché plus en haut dans le texte de l'historique_ | |||
### Fréquence des hosts | |||
Lors d'une appel d'un play, on peut indiquer une fréquence sur le nombre d'host touché par l'éxecution du playbook. | |||
* `Fork` pour le nombre de hosts simultanés (changeable dans le fichier _ansible.cfg_ - mettre une valeur importante > centaine). | |||
* `serial` en en-tête contenant une valeur numérique qui représente le nombre de machines pour chaque tour d'éxecution de playbook, ou un pourcentage par rapport à la liste inventory concerné. | |||
### Cowsay | |||
~~~ | |||
____________________ | |||
< NO MORE HOSTS LEFT > | |||
-------------------- | |||
\ ^__^ | |||
\ (oo)\_______ | |||
(__)\ )\/\ | |||
||----w | | |||
|| || | |||
____________ | |||
< PLAY RECAP > | |||
------------ | |||
\ ^__^ | |||
\ (oo)\_______ | |||
(__)\ )\/\ | |||
||----w | | |||
|| || | |||
~~~ | |||
Pour avoir les messages de la vache : *cowsay*. | |||
Si installer, pour le désactiver : `export ANSIBLE_NOCOWS=1` | |||
Disponible aussi dans la conf du fichier `/etc/ansible/ansible.cfg` | |||
<https://support.ansible.com/hc/en-us/articles/201957877-How-do-I-disable-cowsay-> | |||
### Conditions dans fichier jinja2 | |||
~~~ | |||
{% if python_is_installed is defined %} | |||
Ansible devrait marcher -pardi! | |||
{% endif %} | |||
~~~ | |||
<http://jinja.pocoo.org/docs/dev/templates/#builtin-tests> | |||
Voir la doc pour plus de features : <http://jinja.pocoo.org/docs/dev/> | |||
### Lire une entrée au clavier | |||
S'il manque une valeur pour la suite du script, soit on le gère en mettant une erreur, ou une valeur par défaut, mais sinon on peut aussi demander une valeur a être tapé sur le clavier : | |||
~~~ | |||
vars_prompt: | |||
- name: 'prenom' | |||
prompt: 'Quel est votre prénom ?' | |||
private: no | |||
tasks: | |||
- debug: var=prenom | |||
~~~ | |||
Malheureusement pour le moment, doit se situer avant `tasks`. | |||
Si on veut utiliser cette variable dans une tâche, il faut simplement utiliser le nom de la variable, et si on veut l'utiliser (explicitement) pour un play ne se trouvant pas dans le même fichier (donc ici la variable dans autre.yml s'appelera _prenom_de_autre_ et non prenom) : | |||
~~~ | |||
- include: './tasks/autre.yml' | |||
vars: | |||
prenom_de_autre: prenom | |||
~~~ | |||
<https://docs.ansible.com/ansible/playbooks_prompts.html> | |||
### Lancer playbook en mode interactif | |||
~~~ | |||
ansible-playbook playbook.yml --step | |||
~~~ | |||
<https://docs.ansible.com/ansible/playbooks_startnstep.html> | |||
### Ne pas lancer une commande shell si le fichier existe | |||
En initialisant le champs *creates* indiquant le chemin de fichier lors de l'utilisation du module shell, cette tâche là ne s'executera seulement si le fichier (chemint *creates* correspondant) n'existe pas. | |||
Et le contraire (si le fichier existe la tâche se lancera), avec le champs *removes*. | |||
Disponible sur certains module (comme *shell*). | |||
Plus simple et rapide que de tester le fichier par le module *stat* juste avant. | |||
### Lancer tâche sur machine précise (voir local) | |||
~~~ | |||
- name: /etc/hosts | |||
shell: cat /etc/hosts | |||
register: tmp | |||
delegate_to: localhost | |||
- debug: var=tmp.stdout | |||
~~~ | |||
Pour local, peut être remplacer par la directive `local_action`. | |||
<https://docs.ansible.com/ansible/playbooks_delegation.html#delegation> | |||
### Lancer tâche qu'une seule fois | |||
~~~ | |||
- name: Début installation, envoie email | |||
run_once: true | |||
... | |||
~~~ | |||
Si ajouter avec `delegate_to`, seule cette machine executera cette tâche, sinon c'est la première dans la liste de l'inventory. | |||
<https://docs.ansible.com/ansible/playbooks_delegation.html#run-once> | |||
### Appliquer une tâche à une liste (tableau) -> boucle | |||
#### with_items | |||
~~~ | |||
- name: Manger les fruits | |||
shell: eat '{{ item }}' | |||
with_items: | |||
- Apple | |||
- Orange | |||
- Strawberry | |||
- Mango | |||
~~~ | |||
Par exemple pour l'installation de plusieurs nouveaux packages : | |||
~~~ | |||
--- | |||
- hosts: localhost | |||
tasks: | |||
- apt: name='{{ item }}' state=present | |||
with_items: [ 'cmatrix', 'tetrinet-server', 'tetrinet-client', 'xtel', 'xtell' ] | |||
~~~ | |||
Même si il y aura plusieurs packages installés, cela ne comptera que pour *un* changement (changed=1). | |||
Cette tâche appellera un par un les éléments de la liste (présent dans with_items) pour le module. | |||
En l'appelant : | |||
~~~ | |||
ansible-playbook -b --ask-become-pass --become-method='su' --become-user='root' apt.yml | |||
~~~ | |||
#### with_nested | |||
Pour croiser les éléments des items -> *"with_nested"*. | |||
~~~ | |||
tasks: | |||
- include: "./ajout_utilisateur_sur_machine.yml" | |||
vars: | |||
user: "{{ item[0] }}" | |||
server: "{{ item[1] }}" | |||
with_nested: | |||
- [ 'alice', 'bob' ] | |||
- [ 'machine1', 'machine2', 'machine-backup' ] | |||
~~~ | |||
Qui aura pour effet d'appeler le include avec comme argument : item[0]=alice, item[1]=machine1; puis item[0]=alice, item[0]=machine2; ... puis item[0]=bob, item[1]=machine1, ... | |||
#### with_dict | |||
Avec hash ... | |||
~~~ | |||
users: | |||
bob: | |||
name: Bob | |||
uid: 1000 | |||
home: /home/bob | |||
alice: | |||
name: Alice | |||
uid: 1001 | |||
home: | |||
tasks: | |||
- user: name="{{ item.key }}" comment="{{ item.value.name }}" uid="{{ item.value.uid }}" home="{{ item.value.home }}" | |||
with_dict: "{{ users }}" | |||
~~~ | |||
### Se connecter sous un autre utilisateur UNIX | |||
Par défaut, l'utilisateur se connectant sur le serveur distant est {{ ansible_user_id }} (càd uid courant UNIX). On peut soit le préciser dans le fichier de conf principal de ansible avec `remote_user : michu` ou en l'indiquant en argument lors de l'éxecution du playbook. | |||
~~~ | |||
ansible-playbook -u michu -k play.yml | |||
~~~ | |||
### Éviter que la commande shell indique élement 'changed' | |||
Sur tout les modules, chaque taches retourne un statut sur son résultat : | |||
* Ok : Tout s'est bien passé | |||
* Changed : Tout s'est bien passé mais il y a eu modification par rapport à l'état précédent (droits fichiers,...) | |||
* Failed : Raté | |||
Le soucis est qu'il parrait bien difficile pour le module shell de connaître après execution de la commande s'il y a eu modification. Par défaut, il y a changement - quand bien même l'utilisation du shell se fait pour afficher un résultat (id, date, ...). | |||
Pour éviter cela on peut mettre : | |||
~~~ | |||
- shell: date | |||
changed_when: false | |||
~~~ | |||
Ou donner une condition | |||
~~~ | |||
- shell: cat > {{ fichier }} </dev/null | |||
changed_when: {{ fichier.stats.exist }} | |||
~~~ | |||
### Voir variables disponibles | |||
~~~ | |||
$ ansible -m setup <hostname> | |||
service.evolix.net | SUCCESS => { | |||
"ansible_facts": { | |||
... | |||
"ansible_architecture": "x86_64", | |||
"ansible_bios_date": "12/01/2006", | |||
"ansible_bios_version": "VirtualBox", | |||
"ansible_cmdline": { | |||
"BOOT_IMAGE": "/b |