Debian
Le livre s’appelle Debian mais la majorité des articles peuvent s'appliquer sur d'autres distribution linux. J'utilise juste principalement Debian d'où le nom.
- Les Bases
- Base de Bash
- Processus
- Sudo
- Commande Basiques
- Cron
- Système de fichiers
- Swap
- Curl
- Sed
- AT
- Awk
- Find
- Tmux
- Copie de Fichiers avec scp
- Mise à jours automatique avec unattended-upgrades
- SSH - Ajout de la 2FA
- Connexion Clé SSH
- Comment changer l’ordre du boot avec GRUB
- How to Add a Directory to PATH in Linux
- Ajouter un MOTD dynamique
- Ajouter des couleurs à ses scripts shell
- Exécuter une action à la mise en veille / au réveil
- Antisèche
- Linux General Cheat Sheets
- Firewall
- Installation d'un pare-feu basique avec iptables
- Firewalld : un firewall simple à utiliser
- UFW - Basic Setup
- UFW - Block entire countries by IPs
- Auto Install with scripts
- Auto Install/Update Discord
- Auto Install/Update VSCode
- Auto install pterodactyl
- Auto Docker Install
- Auto GLPI Install
- Manual Install
- Lynis - System Audits
- Installation de GLPI
- Installer Odoo 15 sur Debian 11
- Installer Symfony 6 sur Debian 11
- Installer Composer sur Debian 11
- Installer Plex sur Debian 11
- Installer Nextcloud sur Debian 11
- Installer PhpMyAdmin sur Debian 11
- Installer Npm sur Debian 11
- Installer MariaDB sur Debian 11
- Installer ZSH sur Debian 11
- Créer un serveur Lamp (Apache MariaDB PHP) + PhpMyAdmin Debian
- How to Install Go on Debian 12
- GrubEFIReinstall
- Failover avec Hearbeat, rsync et réplication mysql
- rsync : Synchronisation de Dossiers
- Configure Samba Share on Debian
- SSH - run script or command at login
Les Bases
Base de Bash
Shell
Sous Linux, un shell est l’interpréteur de commandes qui fait office d’interface entre l'utilisateur et le système d’exploitation. Il s’agit d’interpréteurs, cela implique que chaque commande saisie par l’utilisateur et vérifiée puis exécutée. Nous avons déjà parlé des différents types de shell existants (csh, tcsh, sh, bash, ksh, dash, etc.). Nous travaillerons plus avec le bash (Bourne Again SHell).
Pour rappel, un shell possède deux principaux aspects :
- Un aspect environnement de travail
- Un aspect langage de programmation
L’environnement
L’environnement de travail d’un shell doit être agréable et puissant (rappel CLI GUI), bash permet entre autres choses de :
- Rappeler des commandes précédentes (historique)
- Modifier en ligne du texte de la commande courante (bi, emacs, nano)
- Gestion des travaux lancés en arrières-plan (jobs)
- Initialisation adéquate des variables de configuration (chaîne d’appel de l’interpréteur, chemins de recherche par défaut)
Pour illustrer ça, voyons que le shell permet d’exécuter une commande en mode interactif ou bien par l’intermédiaire de fichiers de commandes (scripts). En mode interactif, bash affiche à l’écran une chaîne d’appel (appelée prompt ou invite) qui se termine par défaut par le caractère # pour l’administrateur (root), et par le caractère $ pour les autres utilisateurs. Sous windows le prompt est souvent le nom du chemin où l’on se trouve, suivis de > , par exemple : “C:\Windows\System32>”
Un langage de programmation
Les shells ne sont pas uniquement des interpréteurs de commandes mais de véritables langages de programmation, un shell comme le bash intègre :
- les notions de variables
- les opérateurs arithmétiques
- les structures de contrôle
- les fonctions
- etc.
Par exemple :
$ mavariable=5 #=> affectation de la valeur 5 dans la variable qui a pour nom “mavariable”
$ echo $((mavariable +3)) #=> affiche la valeur de l’expression mavariable
8
Avantages et inconvénients des shells
L’étude d’un shell comme le bash dispose de plusieurs avantages :
- langage interprété, il est facile de trouver les erreurs et de les traiter
- modification rapide sans besoin de recompiler
- langage orienté chaîne de caractères (pas de pointeurs), moins de risque d’avoir des erreurs d’adressage.
- prototypage rapide d’application, il est facile de composer des programmes avec les commandes existantes et l’utilisation des tubes et substitution dans l’environnement Unix
- langage “glu”: on peut connecter des composants écrits dans des langages différents. Ils doivent juste respecter certains standards :
- lire sur l’entrée standard
- accepter des arguments et options éventuels,
- écrire ses résultats sur la sortie standard
- écrire les messages d’erreurs sur la sortie dédiée au erreur.
Voyons maintenant certains inconvénients des shells :
- La syntaxe est “ésotérique” et d’accès difficile pour les débutants
- Suivant le contexte, l’ajout ou l’oubli d’un espace peut provoquer des erreurs de syntaxe ou de traitement
- Plusieurs syntaxes pour implanter la même fonctionnalité (principalement à cause de la compatibilité ascendante avec le Bourne Shell
- Le sens de certains caractères spéciaux, comme les parenthèses, change avec le contexte, elle peuvent définir :
- une liste de commandes
- une définition de fonction
- imposer un ordre d’évaluation
- une expression arithmétique
Si vous voulez connaître le shell qui tourne actuellement, utilisez la commande ps, et si vous voulez connaître la version du bash :bash -- version
Variables
Ils existent différents types de variables utilisables dans le shell. Elles sont identifiées par un nom (suite de lettres, chiffres, caractères espace
ou souligné ne commençant pas par un chiffre. la casse est gérée). On peut classer 3 groupes de variables :
- utilisateurs (ex: a, valeur)
- prédéfinies par le shell (ex; PS1, PATH, REPLY, IFS, HOME)
- prédéfinies pour les commandes unix (ex: TERM)
Pour affecter une variable, on peut utiliser l’opérateur = ou bien la commande interne read (pour demander une saisie utilisateur)
Les variables locales :
Elles ne sont disponibles que dans l’instance du shell dans lesquelles elles ont été créées. (Elles ne sont pas utilisées par les commandes dans ce shell). Par défaut une variable est créée en tant que variable locale, on utilise couramment des lettres minuscules pour nommer ses variables locales.
Exemple : mavariablelocale = 1
Les constantes :
Une constante est une variable en lecture seul d’une certaine manière, elle n’a pas pour but d’être modifié dans le programme (d’où son nom). Pour créer une constante, vous pouvez utiliser la commande declare -r.
Exemple: declare -r pi=3.14159
Les variables d’environnement :
Les variables d’environnement existent dans le shell pour lequel elles sont créées, mais aussi pour toutes les commandes qui sont utilisées dans ce shell. On utilise couramment des majuscules pour nommer ses variables d’environnement.
Exemple1 :
#Transformer une variable
ENVVAR=10 #Création d’une variable locale
export ENVVAR #Transforme la variable locale en variable d’environnement
Exemple 2:
# Créer une variable d’environnement
export ENVVAR2 = 11 # Première solution
declare -x ENVVAR3 = 12 # Deuxième solution
typeset -x ENVVAR4 = 13 # Troisième solution
Commandes utiles pour les variables :
- echo : Vous pouvez utiliser la commande echo si vous souhaitez connaître le contenu d’une variable.
Exemple : echo $PATH
permettra d’afficher le contenu de la variable d’environnement PATH qui contient les chemins de fichier de
commande dans le shell.
$ set param1 param2
$ echo $1
param1
$ set --
$ echo $1
$ #on a perdu les valeurs
Pour connaître le nombre de variables de position, il existe une variable spéciale $#
- shift : permet de décaler les variables de position (sans toucher au $0)
$ set a b c d e f g h i j # param 1 2 3 4 5 6 7 8 9
$ echo $1 $2 $#
a b 9
$ shift 2 # variable deviennent c d e f g h i j
$ echo $1 $2 $#
c d 7
L’utilisation du shift sans argument équivaut à faire un shift 1
- unset : permet de supprimer une variable
$ set myvar=1
$ echo $myvar
1
$ unset myvar
$ echo $myvar
$
Mon premier bash
#!/bin/bash
echo “Nom du programme : $0”
echo “Nombre d’arguments : $#”
echo “Source : $1”
echo “Destination $2”
cp $1 $2
$ chmod u+x monpremierbash.sh
$
$ monpremierbash.sh /etc/passwd /root/copiepasswd
Nom du programme : ./monpremierbash.sh
Nb d’arguments : 2
Source : /etc/passwd
Destination : /root/copiepasswd
$
$ set un deux trois quatre
$
$ echo $* # affiche tous les arguments
un deux trois quatre
$ echo $@ # affiche tous les arguments
un deux trois quatre
$ set un “deux trois” quatre # testons avec 3 paramètres et des guillemets
$ set “$*” # équivalent à set “un deux trois quatre”
$ echo $#
1
$ echo $1
un deux trois quatre
$ set un “deux trois” quatre # testons $@ avec 3 paramètres et des guillemets
$ set “$@” # équivalent à set “bonjour” “deux trois” “quatre”
$ echo $#
3
$ echo $2
deux trois
Si dans un bash on souhaite supprimer les ambiguïtés d’interprétation des paramètres de position, on utilise le ${paramètre}, comme dans l’exemple suivant.
Exemple :
$ x=bon
$ x1=jour
$ echo $x1
jour
$ echo ${x}1
bon1
$ set un deux trois quatre cinq six sept huit neuf dix onze douze
$ echo $11
un1
$ echo ${11}
onze
Indirections
Bash offre la possibilité d’obtenir la valeur d’une variable v1 dont le nom est contenu “v1” dans une autre variable mavar. Il suffit pour cela d’utiliser la syntaxe de substitution : ${!mavar}.
Exemple :
$ var=v1
$ v1=un
$
$ echo ${!var}
un
$
Ce mécanisme, appelé indirection,permet d’accéder de manière indirecte et par conséquent de façon plus souple, à la valeur d’un
deuxième objet. Voyons un autre exemple d’utilisation :
Exemple d’un fichier indir:
#!/bin/bash
agePierre=10
ageJean=20
read -p “Quel âge (Pierre ou Jean) voulez-vous connaître ? “ prenom
rep=age$prenom #construction du nom de la variable
echo ${!rep}
$ indir
Quel âge (Pierre ou Jean) voulez-vous connaître ? Pierre
10
$ indir
Quel âge (Pierre ou Jean) voulez-vous connaître ? Jean
20
$
Ce mécanisme s’applique également aux deux autres types de paramètres : les paramètres de position et les paramètres spéciaux ($1, $2, , ...)
Résultats, Code de retour et opérateur sur les code de retour
Il ne faut pas confondre le résultat d’une commande et son code de retour : le résultat correspond à ce qui est écrit sur sa sortie standard; le code de retour indique uniquement si l’exécution de la commande s’est bien effectuée ou non. Parfois, on est intéressé uniquement par le code de retour d’une commande et non par les résultats qu’elle produit sur la sortie standard ou la sortie d’erreur.
Exemple :
$ grep toto pass > /dev/null 2>&1 #=> ou bien : grep toto pass &>/dev/null
$
$ echo $?
1 #=> on en déduit que la chaîne toto n’est pas présente dans pass
Les opérateurs && et || autorisent l’exécution conditionnelle d’une commande cmd suivant la valeur qu’a pris le code de retour de la dernière commande précédemment exécutée.
Exemple pour && :
$ grep toto pass > /dev/null 2>&1 #=> ou bien : grep toto pass &>/dev/null
$
$ echo $?
1 #=> on en déduit que la chaîne toto n’est pas présente dans pass
La chaîne de caractères daemon est présente dans le fichier pass, le code de retour renvoyé par l’exécution de grep est 0; par conséquent, la commande echo est exécutée.
Exemple pour || :
$ ls pass tutu
ls : impossible d’accéder à tutu: Aucun fichier ou dossier de ce type pass
$ rm tutu || echo tutu non effacé
rm : impossible de supprimer tutu: Aucun fichier ou dossier de ce type
tutu non effacé
$
Le fichier tutu n’existant pas, la commande rm tutu affiche un message d’erreur et produit un code de retour différent de 0; la commande interne echo est exécutée.
Exemple combiné || et || :
$ ls pass || ls tutu || echo fin aussi
pass
$
Le code de retour ls pass est égal à 0 car pass existe, la commande ls tutu ne sera pas exécutée. D’autre part le code de retour de l’ensemble ls pass || ls tutu est le code de retour de la dernière commande exécutée, c’est-à-dire 0 (ls pass). donc echo fini aussi n’est pas exécutée.
Exemple combiné && et || :
$ ls pass || ls tutu || echo suite et && echo fin
pass
fin
$
la commande ls pass a un code de retour égal à 0, donc la commande ls tutu ne sera pas exécutée; le code de retour de l’ensemble ls pass || ls tutu sera donc égal à 0. la commande echo suite et n’est pas exécutée donc le code de retour de l’ensemble reste 0 echo fin sera donc exécutée.
Boucles et structure de contrôle
case, structure de choix multiple
Syntaxe :
case mot in
[modele [ | modele] ...) suite de commandes ;; ] ...
esac
Le shell va étudier la valeur de mot puis la comparer séquentiellement à chaque modèle. Quand un modèle correspond à mot, la suite de commandes associée est exécutée, terminant l’exécution de la commande interne case. Les mots case et esac sont des mots-clés; ils doivent être le premier mot d’une commande. suite de commandes doit se terminer par 2 caractères ; collés de manière à ce qu’il n’y ait pas d’ambiguïté avec l’enchaînement séquentiel de commande cmd1; cmd2; etc. Quand au modèle , il peut-être construit à l’aide de caractères et expressions génériques de bash (*, . , [], etc.). Dans ce contexte le symbole | signifiera OU. Pour indiquer le cas par défaut (si aucun des autres ne survient) on utilisera le modèle *. il doit être placé en dernier modèle. Le code de retour de la commande composée case est égal à 0, si aucun modèle n’a pu correspondre à la valeur de mot. Sinon, c’est celui de la dernière commande exécutée de suite de commandes.
Exemple 1: Programme shell oui affichant OUI si l’utilisateur a saisi le caractère o ou O
#!/bin/bash
read -p “Entrez votre réponse : “ rep
case $rep in
o|O ) echo OUI ;;
* ) echo Indefini
esac
Exemple 2 : Programme shell nombre prenant une chaîne de caractères en argument, et qui affiche cette chaîne si elle est constituée d’une suite de chiffres. ([:digit:] , [:upper:], [:lower:], [:alnum:]
#!/bin/bash
# on autorise l’utilisation des expressions générique
shopt -s extglob
case $1 in
+([[:digit:]]) ) echo ′′$1 est une suite de chiffres′′ ;;
esac
Exemple 3 : Si l’on souhaite ignorer la casse on peut modifier le flash de shopt
#!/bin/bash
read -p “Entrez un mot : “ mot
shopt -s nocasematch
case $mot in
oui ) echo ′′Vous avez écrit oui” ;;
* ) echo “$mot n’est pas le mot oui” ;;
esac
While
La commande interne while correspond à l’itération ‘faire - tant que’ présente dans de nombreux langage de programmation.
Syntaxe :
while suite_cmd1
do
suite_cmd2
done
La suite de commandes suite_cmd1 est exécutée, si son code de retour est égal à 0, alors la suite de commande suite_cmd2 est exécutée, puis suite_cmd1 est re-exécutée. Si son code de retour est différent de 0, la suite se termine. L’originalité de cette méthode est que le test ne porte pas sur une condition booléenne, mais sur le code de retour issu de l’exécution d’une suite de commandes. Une commande while, comme toutes commandes internes, peut être écrite directement sur la ligne de commande.
Exemple :
$ while who | grep root> /dev/null
> do
> echo “Utilisateur root est connecté”
> sleep 5
> done
Utilisateur root est connecté
Utilisateur root est connecté
Utilisateur root est connecté
^C
$
Commande interne while est :
La commande interne : associée à une itération while compose rapidement un serveur (démon) rudimentaire.
Exemple :
$ while : #=> Boucle infinie
> do
> who | cut -d’ ‘-f1 > fic #=> Traitement à effectuer
> sleep 300 #=> Temporiser
> done &
[1] 1123 #=> pour arrêter l’exécution kill -15 1123
$
On peut parfois utilisée la commande while pour lire un fichier texte. La lecture se fait alors ligne par ligne. Pour cela, il suffit de :
- placer la commande read dans suite_cmd1
- de placer les commandes de traitement de la ligne courante dans suite_cmd2
- de rediriger l’entrée standard de la commande while avec le fichier lire
Syntaxe :
while read [var1 ...]
do
Commandes de traitements
done < fichier à lire
Exemple :
#!/bin/bash
who > tmp
while read nom divers
do
echo $nom
done < tmp
rm tmp
Notez que l’utilisation du while pour lire un fichier n’est pas très performante. On préférera en général utiliser une suite de filtre pour obtenir les résultats voulus (cut, awk, ...)
Modificateur de chaîne
Échappement
Différents caractères particuliers servent en shell pour effectuer ses propres traitements ($ pour la substitution, > pour la redirection, * en joker). Pour utiliser ces caractères particuliers en tant que simple caractère, il faut les échapper en les précédant du caractère \
Exemple :
$ ls
tata toto
$ echo *
tata toto
$ echo \*
*
$ echo \\
\
$
Autre particularité, le caractère \ peut aussi échapper les retours à la ligne. On peut donc aller à la ligne sans exécuter la commande.
Comme nous l’avons déjà vu, les caractères “ et ‘ permettre une protection partielle, ou total (‘) d’une chaîne de caractères.
Exemple :
$ echo “< * $PWD ‘ >”
< * /root ‘ >
$
$ echo “\”$PS2\””
“> “
$ echo ‘< * $PWD “ >’
< * $PWD “ >’
$ echo c’est lundi
>
> ‘
cest lundi
$ echo c\’est lundi
c’est lundi
$ echo “c’est lundi”
c’est lundi
Chaîne de caractères longueur
Syntaxe : ${#paramètre}
Cette syntaxe permet d’obtenir la longueur d’une chaîne de caractères.
Exemple :
$ echo $PWD
/root
$ echo ${#PWD}
5
$ set “Bonjour à tous”
$ echo ${#1}
14
$ ls > /dev/null
$
$ echo ${#?}
1 #=> la longueur du code de retour (0) est de 1 caractère
Chaîne de caractères modificateur
On peut modifier les chaîne de caractères directement :
Syntaxe : ${paramètre#modèle} pour supprimer la plus courte sous-chaîne à gauche
Exemple :
$ echo $PWD
/home/christophe
$ echo ${PWD#*/}
home/christophe #=> le premier caractère / a été supprimé
$
$ set “25b75b”
$
$ echo ${1#*b}
75b #=> Suppression de la sous-chaîne 25b
Syntaxe: ${paramètre##modèle}
pour supprimer la plus longue sous-chaîne à gauche
Exemple :
$ echo $PWD
/home/christophe
$ echo ${PWD##*/}
christophe #=> suppression jusqu’au dernier caractère /
$
$ set “25b75b”
$
$ echo ${1##*b}
b
Pour la suppression par la droite, c’est la même chose en utilise le caractère % comme contrôle
Syntaxe :${paramètre%modèle}
pour supprimer la plus courte sous-chaîne à droite${paramètre%%modèle}
pour supprimer la plus longue sous-chaîne à droite
On peut extraire une sous-chaîne également :
Syntaxe:${paramètre:ind}
: extrait la valeur de paramètre de la sous-chaîne débutant à l’indice ind.${paramètre:ind:nb}
: extrait nb caractères à partir de l’indice ind
Exemple :
$ lettres=”abcdefghijklmnopqrstuvwxyz”
$
$ echo {$lettre:20}
uvwxyz
$ echo {$lettre:3:4}
defg
$
Remplacement dans une sous-chaîne
Syntaxe:${paramètre/mod/ch}
bash recherchera dans paramètre la plus longue sous-chaîne satisfaisant le modèle mod puis remplacera cette sous-chaîne par
la chaîne ch. Seule la première sous-chaîne trouvée sera remplacée. mod peut être des caractères ou expressions génériques.${paramètre//mod/ch}
:
Pour replacer toutes les occurrences et pas seulement la première${paramètre/mod/}
:${paramètre//mod/}
:
Supprime au lieu de remplacer
Exemple :
$ v=totito
$ echo {$v/to/lo}
lotito
$ echo {$v//to/lo}
lotilo
Structure de contrôle for et if
Itération et for
Syntaxe 1:
for var
do
suite_de_commandes
done
Syntaxe 2:
for var in liste_mots
do
suite_de_commandes
done
Dans la première forme, la variable var prend successivement la valeur de chaque paramètre de position initialisé
Exemple :
$ cat for_args.sh
#!/bin/bash
for i
do
echo $i
echo “next ...”
done
$ ./for_args.sh first second third
first
next ...
second
next ...
third
next ...
Exemple 2:
$ cat for_set.sh
#!/bin/bash
set $(date)
for i
do
echo $i
done
$ ./for_set.sh
samedi
29
Juin
2019,
12:09:21
(UTC+0200)
$
La deuxième syntaxe permet à var de prendre successivement la valeur de chaque mot de liste_mots.
Exemple :
$ cat for_liste.sh
#!/bin/bash
for a in toto tata
do
echo $a
done
Si liste_mots contient des substitutions, elles sont préalablement traitées par bash
Exemple 2:
$ cat affiche_ls.sh
#!/bin/bash
for i in /tmp ${pwd}
do
echo “ --- $i ---”
ls $i
done
$ ./affiche_ls.sh
--- /tmp ---
toto tutu
--- /home/christophe
for_liste.sh affiche_ls.sh alpha tmp
If et le choix
La commande interne if implante le choix alternatif
Syntaxe :
if suite_commande1
then
suite_commande2
[elif suite_de_commandes; then suite_de_commande] ...
[else suite_de_commandes]
fi
Le principe de fonctionnement est le même que pour le for, on test la valeur de retour d’une commande plutôt qu’une valeur booléenne simple. Donc dans notre exemple, suite_commande2 est exécuté, si suite_commande1 renvoi 0 (pas d’erreur). Sinon c’est elif ou bien else qui sera exécuté.
Exemple :
$ cat rm1.sh
#!/bin/bash
if rm “$1” 2> /dev/null
then echo $1 a été supprimé
else echo $1 n\’a pas été supprimé
fi
$ >toto
$ rm1 toto
toto a été supprimé
$
$ rm1 toto
toto n’a pas été supprimé
$
Lorsque rm1 toto est lancé, si le fichier toto est effaçable, il le sera, et la commande rm renvoi 0.
Notez qu’il est possible d’imbriquer les if ensembles
Exemple :
if...
then....
if...
then ...
fi
else ...
fi
Tests
Dans les bash, vous retrouverez souvent une notation de commande interne [[ souvent utilisé avec le if. Elle permet l’évaluation de d’expressions conditionnelles portant sur des objets aussi différents que les permissions sur une entrée, la valeur d’une chaîne de caractères ou encore l’état d’une option de la commande interne set.
Syntaxe: [[ expr_conditionelle ]]
Les deux caractères crochets doivent être collés et un caractère séparateur doit être présent de part et d’autre de expr_conditionelle. Les mots [[ et ]] sont des mots-clés. On a vu que le if fonctionne selon la valeur de retour d’une commande, et pas d’un booléen, cette syntaxe permet “d'exécuter un test” qui renverra 1 si le test est vrai, 0 sinon. Si l’expression contient des erreurs syntaxique une autre valeur sera retournée. La commande interne [[ offre de nombreuses expressions conditionnelles, c’est pourquoi seules les principales formes de exp_conditionnelle seront présentées, regroupées par catégories.
Permission
-r entrée vraie si entrée existe et est accessible en lecture par le processus courant
-w entrée vraie si entrée existe et est accessible en écriture par le processus courant
-x entrée vraie si entrée existe et est accessible en exécutable par le processus courant ou si le répertoire entrée existe et
le processus courant possède la permission de passage
Exemple :
$ echo coucou > toto
$ chmod 200 toto
$ ls -l toto
--w- --- --- 1 christophe christophe 29 juin 1 14:04 toto
$
$ if [[ -r toto ]]
> then cat toto
> fi
$ => rien ne ce passe
$ echo $?
0 => code de retour de la commande interne if
$
MAIS
$ [[ -r toto ]]
$ echo $?
1 => code de retour de la commande interne [[
$
Type d’une entrée
-f entrée vraie si entrée existe et est un fichier ordinaire
-d entrée vraie si entrée existe et est un répertoire
Exemple :
$ cat afficher.sh
#!/bin/bash
if [[ -f “$1” ]]
then
echo “$1” : fichier ordinaire
cat “$1”
elif [[ -d “$1” ]]
then
echo “$1” : répertoire
ls “$1”
else
echo “$1” : type non traité
fi
$ ./afficher
. : répertoire
afficher.sh test.sh toto alpha rm1.sh
$
Renseignement divers sur une entrée
-a entrée vraie si entrée existe
-s entrée vraie si entrée existe et sa taille est différente de 0 (un répertoire vide > 0)
entrée 1 -nt entrée 2 vraie si entrée 1 existe et sa date de modification est plus récente que celle de entrée2
entrée1 -ot entrée 2 vraie si entrée1 existe et sa date de modification est plus ancienne que celle de entrée2
Exemple :
$ > err
$
$ ls -l err
-rw-rw-r-- 1 christophe christophe 0 juin 29 14:30 err
$ if [[ -a err ]]
> then echo err existe
> fi
err existe
$ if [[ -s err ]]
> then echo err n’est pas vide
> else err est vide
> fi
err est vide
$
Longueur d’une chaîne de caractère
-Z ch vraie si la longueur de ch est égale à 0
ch ou (-n ch) vraie si la longueur de ch est différente de 0
ch1 < ch2 vraie si ch1 précède ch2
ch1 > ch2 vraie si ch1 suit ch2
ch == mod vraie si la chaîne ch correspond au modèle mod
ch != mod vraie si la chaîne ch ne correspond pas au modèle mod
-o opt vraie si l’option interne opt est sur on
Important : il existe un opérateur =~ qui permet de mettre en correspondance une chaîne de caractères ch avec une expression
régulière.
Exemple :
$a=01/01/2010
$[[ $a =~ [0-9]{2}\/[0-9]{2}\/[0-9]{2,4} ]]
$ echo $?
0
$ a=45/54/1
$[[ $a =~ [0-9]{2}\/[0-9]{2}\/[0-9]{2,4} ]]
$ echo $?
1
Expressions conditionnelles
( cond ) vraie si cond est vraie
! cond vraie si cond est fausse
cond1 && cond 2 vraie si cond1 et 2 sont vraie, l’évaluation s’arrête si cond1 est fausse
cond1 || cond2 vraie si cond1 ou 2 sont vraie.
Exemple :
$ ls -l /etc/at.deny
-rw-r----- 1 root daemon 144 oct. 25 2018 /etc/at.deny
$
$ if [[ ! ( -w /etc/at.deny || -r /etc/at.deny ) ]]
> then
> echo OUI
> else
> echo NON
> fi
OUI
Processus
Une commande sous linux crée un processus en mémoire, ce processus est sous la responsabilité du kernel. Tous les traitements effectués par une commande sont en fait traitées par le processus qui est créé lors de l'exécution de cette commande.
Un processus est exécuté (en général) par un utilisateur, il disposera donc des mêmes droits que l’utilisateur qui est responsable de son exécution. Et en général, un utilisateur ne pourra pas agir sur un processus lancé par un autre utilisateur, exception faite de root, évidemment.
La commande qui permet de lister les processus est PS :
PID : Numéro du processus (unique)
TTY : Nom du terminal dans lequel se trouve le processus
TIME : Le temps processeur utilisé par le processus
CMD : La commande qui a créé le processus
On peut déduire de cet exemple, qu’une même commande peut créer plusieurs processus.
Avec la commande ps x on peut voir dans quel état sont les processus
S: en sommeil
D : Sommeil irréversible
R : En cours d’exécution
T : Stoppé
Z : Zombie (processus terminé, mais pas encore totalement libéré)
Pour l’instant, on ne visualise que les processus de l’utilisateur, pour obtenir la liste complète, on va utiliser plutôt la commande :
ps -ef (-e tous les processus, et -f pour full détails)
Processus Foreground
Lorsque vous exécutez une commande comme ps -ef | less, le processus créé est foreground ou d’avant-plan. C’est-à-dire que le shell est bloqué durant l'exécution de la commande. L’utilisateur n’a donc plus la possibilité de faire autre chose. C’est pratique si le traitement est court, mais pas bon du tout si le traitement est long et coûteux en ressource.
Lorsqu'un processus a besoin de lancer un autre processus pour ses traitements, le premier processus est appelé processus parent et le ou les processus créés par le parent sont appelés processus enfant.
Lorsqu’un parent lancé en foreground crée un enfant, le processus enfant bloquera le parent jusqu’à la fin de ses traitements, puis à sa mort, le parent reprendra le relais.
Par exemple, le bash est un processus. Quand on lance une commande dans le bash, le processus parent bash est bloqué jusqu’à la fin des traitements de son processus enfant (par exemple le ls)
Si vous voulez éviter de bloquer le shell (ou le parent). Il est possible de lancer une commande en tâche de fond, dans ce cas, l’enfant rendra immédiatement les droits de continuer les opérations au parent, tout en continuant de faire ses traitements.
Pour se faire, on utilisera le caractère &,
Déplacer un processus
Si l’on fait un script, dont une commande demande à dormir 10.000 secondes, mais malheureusement, j’ai oublié de demander à la commande du script de se lancer en tâche de fond
- Le ctrl+z permet d'interrompre le processus (suspend)
- on fait la commande bg, qui passe le processus en tâche de fond
- on le remet en foreground avec la commande fg
- le ctrl+c permet de lancer une interruption logiciel qui envoi un SIGTERM au processus en foreground
Si vous voulez connaître la liste des jobs en cours de traitement, vous pouvez utiliser la commande jobs
Signaux
Un signal est un message envoyé à un processus pour altérer son état (par exemple stop, start, pause)
Certains signaux peuvent s’envoyer avec un raccourcis clavier (ctrl+z stoppe un processus)
Pour consulter la liste des signaux, kill -l
Donc la commande kill permet d’envoyer un signal à un processus de plusieurs façons :
- Kill -2 → envoi le signal 2 (SIGINT) à un processus
- Kill -SIGINT → envoi le signal SIGINT à un processus
Le SIGINT est l’équivalent du CTRL+Z (stoppe le processus mais ne le détruit pas)
Pour tuer (détruire) un processus, on utilisera plutôt le SIGTERM (15)
Killall - tuer un processus par user
La commande killall -u permet de demander à tuer tous les processus appartenant à un utilisateur.
killall -u root
Supprimera tous les processus lancés par le compte root.
Conserver un processus en quittant
Quand un utilisateur se déconnecte de sa session, tous les processus rattachés à l’utilisateur reçoivent un SIGHUP (1) qui va finalement tuer
tous les processus rattachés.
Si l’opération de sauvegarde est très longue et que l’administrateur doit se déconnecter, sa sauvegarde s’arrêtera par exemple.
Pour éviter ce phénomène, on utilisera la commande nohup
Priorité d’un processus
Un processus a besoin de temps processeur pour faire ses calculs. Certains d’entre eux ont droits à plus de CPU que d’autres, ceci se règle
avec un mécanisme de priorité. Les processus lancés par le système auront en général plus de priorité que les autres.
C’est le kernel qui s’occupe d’ajuster dynamiquement la priorité et essaie de fournir les bonnes priorités selon les besoins.
L’utilisateur pourra influencer dans une certaines mesure cette priorité en faisant varier une valeur de “gentillesse” niceness !
niceness -20 => Donne la priorité la plus haute possible
niceness 0 => valeur par défaut
niceness 19 => priorité la plus basse
Un utilisateur standard aura le droit de régler l’indice entre 19 et 0. Seul le root peut faire des réglages entre -1 et -20.
Pour affecter un indice de gentillesse, on utilise la commande nice avec l’option -n (régler la gentillesse) et une valeur.
Sudo
Sudo (Parfois considéré comme l'abréviation de Super-user do) est un programme dont l'objectif de permettre à l'administrateur du système d'autoriser certains utilisateurs à exécuter des commandes en tant que superutilisateur (ou qu'un autre utilisateur). La philosophie qui sous-tend cela est de donner aussi peu que possible de droits, mais de permettre quand même aux utilisateurs de faire leur travail. Sudo est aussi un moyen efficace d'enregistrer qui a exécuté quelle commande et quand.
Notes pour les nouveaux utilisateurs de Debian
Certains nouveaux utilisateurs de Debian, venant généralement de Ubuntu, sont choqués par les problèmes du type : « sudo ne fonctionne pas dans Debian ». Cette situation n'arrive cependant que si vous avez configuré un mot de passe superutilisateur (root) durant l'installation de Debian.
Si vous aimez sudo que vous voulez l'installer (même si vous l'avez sauté durant l'installation de votre Debian), vous pouvez, devenir superutilisateur avec la commande su, l'installer, et vous ajouter votre propre nom d'utilisateur dans le groupe sudo et faire une déconnexion puis une reconnexion complète.
Exemple :
-
su - #Password: (entrez ici le mot de passe superutilisateur que vous avez défini dans l'installation de votre Debian et appuyez sur la touche #Entrée) apt install sudo sudo adduser USER sudo
Puis veuillez effectuer une complète déconnexion et reconnexion.
Pourquoi pas sudo ?
Notez que, historiquement, tous les systèmes de type Unix fonctionnaient parfaitement même avant que « sudo » ne doit inventé. De plus, avoir un système sans sudo pourrait apporter encore plus de sécurité car le paquet sudo pourrait être affecté par des bogues de sécurité, comme toute partie additionnel de votre système.
Nombre d'utilisateur de Debian n'installent pas sudo. Ils ouvrent à la place un terminal en tant que supertulisateur (par exemple avec la commande su - à partir d'un utilisateur normal). Ainsi, vous n'avez pas placer « sudo » devant n'importe quelle commande.
Pourquoi sudo ?
Utiliser sudo pourrait être un plus familier pour les nouveaux utilisateur et est meilleur (plus sûr) que d'ouvrir une session en tant que superutilisateur pour un certain nombre de raisons dont :
-
Personne n'a à connaitre le mot de passe du superutilisateur (sudo demande le mot de passe de l'utilisateur courant). Des droits supplémentaires peuvent être accordés temporairement à des utilisateurs puis retirés sans qu'il soit besoin de changer de mot de passe.
-
Il est facile de n'exécuter que les commandes qui nécessitent des droits spéciaux avec sudo et le reste du temps, on travaille en tant qu'utilisateur non-privilégié, ce qui réduit les dommages que l'on peut commettre par erreur.
- Contrôler et enregistrer : quand une commande sudo est exécutée, le nom de l'utilisateur et la commande sont enregistrés.
Pour toutes les raisons ci-dessus, la possibilité de basculer en superutilisateur en utilisant sudo -i (ou sudo su) est habituellement désapprouvée parce que cela annule la plupart les avantages cités ci-dessus.
Commande Basiques
Passer en super utilisateur.
sudo -s
Afficher le répertoire de travail courant.
pwd
Se déplacer dans un répertoire.
cd (Dossier)
Aller à la racine du disque dur.
cd /
Se déplacer dans le répertoire parent.
cd ..
Visualiser le contenu du répertoire.
ls
Permet de créer un répertoire.
mkdir (Dossier)
Supprimer un répertoire.
rmdir (Dossier)
Permet de supprimer un dossier avec des fichiers dedans.
rm -rf dossier
Affiche l’aide d’une commande.
man (Logiciel)
Permet d’afficher un fichier texte (page par page ou en entier).
more (Fichier)
cat (Fichier)
Permet de modifier un fichier texte.
nano (Fichier)
vi (Fichier)
Permet de copier un fichier ou un dossier.
cp /etc/fichier (source) /tmp/fichier (destination)
Permet de déplacer un fichier ou un dossier ou de le renommer
mv /etc/fichier (source) /tmp/fichier (destination)
mv fichier fichierrenommer
Créer un fichier
touch fichier
Permet de supprimer un fichier.
rm fichier
Cron
Le démon crond est le processus qui permet d’exécuter des tâches planifiées automatiquement à des instants précis prévus à l’avance (date,
heure, minute) et en gérant une chronicité.
Si par exemple je veux qu’une machine PC-560 s’éteigne tous les jours à 20h51, je peux le faire avec cron. Pour cela, il me faut une entrée
dans la crontab de la machine qui indiquera la commande à exécuter pour éteindre la machine.
Normalement, cron est installé par défaut sur les systèmes, sinon vous pouvez l’installer comme d’habitude.
Toutes les configurations exécutées par cron vont se retrouver dans la table de cron (crontab). Seul la syntaxe particulière est complexe à
utiliser.
Utilisation de la crontab
Pour paramétrer une tâche planifiée, il faut écrire une entrée dans la crontab. Cette entrée spécifie la (ou les) date d’exécution de cette tâche,
ainsi que la tâche à exécuter et d’autres paramètres si nécessaire.
Pour chaque utilisateur du système, on peut éditer un fichier de crontab, relatif aux tâches planifiées de ce dernier. Ces fichiers se trouvent en
général dans “/var/spool/cron/crontabs/” ou un équivalent et portent le nom de l’utilisateur en question.
L’édition du fichier ne se fait pas en direct dans le spool, on utilisera une commande dédié pour ça :
- crontab -e pour éditer le fichier de crontab de l’utilisateur courant
- crontab -e -u root pour éditer la crontab d’un utilisateur spécifique (root)
- crontab -l pour afficher la crontab de l’utilisateur courant.
- crontab -r qui va effacer la crontab de l’utilisateur
En général au premier lancement, le système vous demandera quel moteur de texte vous souhaitez utiliser (nano, vi, ...) en fonction de ceux
installé. En sortie du fichier, le système vérifiera que la syntaxe de vos entrées est correct.
Il est important de noter, que le système dispose, en plus du crontab utilisateurs, de ses propres fichiers et tâches planifiées dans les
répertoires “/etc/cron.*” l’étoile représente les différents dossiers utilisés (qui sont référencés dans /etc/crontab) :
- cron.hourly toutes les heures
- cron.daily tous les jours
- cron.weekly toutes les semaines
- cron.monthly tous les mois
- cron.d contient des fichiers au format crontab pour des utilisations plus spécifiques.
Syntaxe de cron
Chaque entrée dans la crontab correspond à une tâche à exécuter. Et chaque entrée de la crontab est une ligne dans un des fichiers cités plus
haut. Si nous regardons une ligne en détail :
Exemple :51 19 * * 0 root /usr/local/bin/backupbackup
Cette ligne signifie de lancer le programme /usr/local/bin/backupbackup tous les dimanches à 19h51.
La syntaxe générale d’écrit sous cette forme :
mm hh jj MMM JDS commande
mm : Codé sur 2 chiffres représente les minutes de 0 à 59, ou * pour décrire toutes les minutes
hh : Codé sur 2 chiffres représente les heures de 0 à 23, ou * pour décrire toutes les heures
jj : Codé sur 2 chiffres représente la date du jour de 1 à 31, * pour décrire tous les jours
MMM : Codé sur 2 chiffres ou 3 lettres représente le mois de 1 à 12 ou de jan à dec, * pour décrire tous les mois
JDS : représente le jour de la semaine codé par 1 chiffre ou 3 lettres (de 0 à 7 ou de sun à sun, le 0 et le 7 représente sunday)
commande : la commande qui sera exécutée.
On peut trouver des caractères spéciaux dans les champs prévus pour :
- * : signifie tout ou chaque unité de temps.
- , : permet de décrire une liste. Exemple 3,5,17
- - : permet de décrire un intervalle. Exemple de 1 à 10 se note 1-10
- */ : permet de décrire un intervalle avec des pas différents de 1. Par exemple : */10 signifie 0,10,20,30, ...
- @reboot : permet de lancer la commande au démarrage de la machine
- @yearly : tous les ans
- @daily : tous les jours
Vous pouvez également vous renseigner sur anacron, pour que les tâches soient exécutées même si la machine est éteinte (ou au moins au
redémarrage de celle-ci).
Système de fichiers
Un système de fichiers est une façon d’organiser et de stocker une arborescence sur un support (disque, cd, ...). Chaque OS a sa propre organisation.
Linux possède son système appelé ext2 mais peut en gérer d’autres. La liste se trouve en général dans /proc/filesystems. L’utilisateur peut donc accéder sous Linux à d’autres systèmes de fichiers (DOS, Vfat, NTFS, ...) provenant d’un périphérique ou importé par le réseau.
Tout est fichier
Comme nous l’avons vu précédemment, dans le système linux, tout est considéré comme un fichier :
- Les fichiers
- Les dossiers
- Un disque dur
- La mémoire
- Un port USB aussi .
Mais parmi ces fichiers, tous n’ont pas la même catégorie. On peut en effet retrouver :
- fichiers normaux (texte, exécutables, ...); symbole “-”
- fichiers répertoires, ce sont des fichiers conteneurs qui contiennent des références à d’autres fichiers. Véritable charpente de
l’arborescence.; symbole “d”
- fichiers spéciaux, ils sont situés dans /dev, ce sont les points d’accès préparés par le système aux périphériques. Le montage va
réaliser une correspondance de ces fichiers spéciaux vers leur répertoire “point de montage”. Par exemple, le fichier /dev/hda permet l’accès et le chargement du 1er disque IDE.
- Accès caractère par caractère; symbole “c”
- Dispositif de communication ; symbole “p”
- Accès par bloc ; symbole “b”
- fichier lien symboliques, ce sont des fichiers qui ne contiennent qu’une référence (un pointeur) à un autre fichier. Cela permet d’utiliser un même fichier sous plusieurs noms sans avoir à le dupliquer sur le disque. ; symbole “l”
Le processus de montage que l’on évoque pour les fichiers spéciaux, avec sa commande mount est le moyen de faire correspondre les parties de l’arborescence et les partitions physiques de périphérique. Il permet de plus d’affecter tout système extérieur (cd, zip, réseau) à un répertoire créé pour cela dans l’arborescence. Il suffira ensuite de se déplacer à ce répertoire, appelé point de montage, qui est en fait un répertoire “d’accrochage”, pour accéder à ses fichiers (bien sûr, conformément aux permissions que possède l’utilisateur).
FHS (Filesystem hierarchy standard)
C’est la standardisation des noms et des emplacements des dossiers, et de leurs contenus.
Voici la structure qui est recommandée d’après les spécifications
SI l’on détaille :
- /bin : Les fichiers binaires les plus importants
- /boot : le Kernel et le bootloader
- /dev : les périphériques
- /etc : les fichiers de configurations spécifiques à l’ordinateur
- /home : Emplacement contenant les profils dossiers utilisateur
- /mnt : Emplacement d’accès aux systèmes de fichiers montés dans l’OS
- /lib : Bibliothèques de fonctions utilisées par les commandes /bin et /sbin
- /proc : Le kernel place ici l’état en temps réel du fonctionnement du système et des processus
- /root : Dossier du profil “root”
- /sbin : Contient des exécutables
- /tmp : à utiliser pour la création de fichiers temporaires
- /usr : Applications installées par les utilisateurs (et souvent les données qui vont avec) souvent un des plus lourds!
- /var/log : Fichiers logs
- /var/spool : File d’attente d’impression
- /var/tmp : Fichiers temporaires
Gob et Jokers
Le file globing, est l’opération qui transforme un caractère joker en une liste de chemins, et de fichiers correspondants qui formeront le résultat.
Le file globing est l’ancêtre des expressions régulières. Sous Bash, les jokers possibles sont :
- Le caractère *
- Le caractère ?
- Les caractères []
Le caractère * est utilisé pour obtenir la liste de tout le contenu
Ex : ls => ls *
Il est possible de préciser plus de caractéristiques :
ls D* => Tous les fichiers commençant par un D
ls d*v* => Tous les fichiers commençant par un d minuscule mais contenant aussi la lettre v
Le caractère ?, est utilisé pour préciser que le résultat doit contenir un seul ou plusieurs caractères (un par joker ?)
Exemple :
ls ? => liste tout ce qui ne contient qu’un seul caractère
ls ?? => liste tous les fichiers qui n’ont que 2 caractères
ls w?? => liste tous les fichiers qui ont 3 caractères et commençant par w
ls w??* => liste tous les fichiers qui commencent par w et contiennent au moins 3 caractères.
Le joker [], est utilisé pour spécifier une plage de caractères admissibles.
ls [a-f]?? => liste tous les fichiers dont la première lettre commence par a,b,c,d,e ou f et faisant 3 caractères.
ls [w]* => liste tous les fichiers commençant par w
ls [*] => ici l’étoile est son propre caractère, liste tous les fichiers commençant par *
ls *[0-9][0-9]* => liste tous les fichiers contenant 2 chiffres
ls [!a-y]* => ne liste que les fichiers commençant par autre chose que les lettres a à y. le ! inverse le résultat
ls *[^3-9] => liste tous les fichiers excluant ceux contenant les chiffres 3 à 9
Droit d’accès et permissions
Droits
Un fichier est caractérisé par un certain nombre de droits d’utilisation. Lorsque que l’on fait un ls -l, on remarque les éléments suivants :
le premiers bloc est définie comme suit :
_ Type de fichier (d, -, p, l, ...)
_ _ _ Droits du propriétaire du fichier (owner), dans l’ordre (lecture, écriture, exécution)
_ _ _ Droits du groupe auquel appartient le fichier (group), dans l’ordre (lecture, écriture, exécution)
_ _ _ Droits d’un utilisateur quelconque (user), dans l’ordre (lecture, écriture, exécution)
Pour rappel :
Permission | Effet sur le fichier | Effet sur le dossier |
r (read) | Autorise la lecture ou la copie du fichier et son contenu |
Sans droit d'exécution : autorisation de liste les fichiers dans le dossier |
w (write) |
Autorise à supprimer ou modifier le contenu du fichier. Permet de supprimer le fichier |
Sur un dossier, il faut également l’attribut “execute” afin d’opérer des modifications |
x (execute) |
Autorise un fichier d’être lancé comme un processus |
Autorise un utilisateur à entrer dans ce dossier |
L’attribut suivant (1 par exemple) est le nombre de lien symbolique vers ce fichier
Les 2 attributs d’après : root root définissent le propriétaire suivis par le groupe
L’utilisateur qui crée le fichier est considéré comme son propriétaire. Il faut savoir que seul root est habilité à modifier le propriétaire d’un fichier, avec la commande “chown”
Le groupe du fichier sera celui du groupe principal auquel appartient l’utilisateur qui crée ce fichier.
la commande “id” indique l’identité de l’utilisateur actuel, son group principal, et tous les groupes auxquels il appartient. Pour changer le groupe d’un fichier, on utilise la commande “chgrp” seuls root et le propriétaire du fichier peuvent changer le groupe d’un fichier.
Permissions
Seul root et le propriétaire du fichier disposent de la possibilité de modifier les permissions d’un fichier au moyen de la commande chmod
Exemples :
Ajouter les droits d’exécution au propriétaire du fichierchmod u+x monfichier
Supprimer les droits d’écriture pour le groupe :chmod g-w monfichier
Assigner des droits à plusieurs sections des attributs ;chmod o=r,g-w,u+x monfichier
Supprimer toutes les permissionschmod a=- monfichier
La méthode octale reste la plus rapide pour l’attribution, avec
r=4; w=2 et x=1
Pour donner les permissions rwx r-x r-x à un fichier, on va additionner les valeurs :
Owner: 4+2+1 => 7
Group : 4+1 => 5
Other : 4+1 => 5
=> chmod 755 monfichier
Attribut spéciaux -setuid
Cet attribut spécial permet d’appliquer à un fichier exécutable, d’autoriser d’autres utilisateurs à lancer l’exécutable, comme s’il étaient l’utilisateur root.chmod 4000
Exemple avec la commande passwd :
s -> permissions x+setuids (s)
S -> seule la permission setuid existe (pasx)
Attribut spéciaux -setgid
Même chose qu’avec setuid, mais pour le groupe utilisateurchmod 2000
- Appliqué à un fichier exécutable, afin de s’exécuter via le group du propriétaire, au lieu de celui de l'utilisateur qui lance l’exécutable
- Appliqué à un dossier, fait en sorte que le contenu créé dans ce dossier appartient au groupe qui possède le dossier (et pas celui de l’utilisateur qui crée le contenu dans ce dossier)
Attribut spéciaux -sticky
chmod 1000
L’utilité de cet attribut est d’empêcher d’autres utilisateurs de supprimer le contenu d’un autre utilisateur.
Pour supprimer un fichier, il faut les autorisations d’écriture sur le dossier parent. Ainsi, un admin crée un dossier accessible et modifiable par tous les utilisateurs. Tout le monde pourra supprimer le contenu de ce dossier ...
L’utilisation de cette permission sticky permet de définir pour un dossier que :
- L’utilisateur propriétaire d’un fichier, dans ce dossier, pourra supprimer le fichier
- root et l’utilisateur propriétaire du dossier parent pourra aussi
Héritage vs umask
Lorsque l’on crée un sous-dossier sous windows, ce dernier hérite des droits d’accès du dossier parent (par défaut). Il faut savoir que sous linux : NON ! ce n’est pas le cas! En effet le sous-dossier aura les droits créés selon la valeur umask de l’utilisateur créant le sous dossier.
Read vaut 4, write 2, execute 1, rien vaut 0.
Dans le cas de umask, ces valeurs précisent les permissions à supprimer des permissions “maximum” à la création !
Sur un fichier, les permissions maximales sont : rw- rw- rw- soit 666 en octal. La valeur umask de l’utilisateur créant le fichier va donc
permettre de supprimer certaines de ces valeurs! Cette valeur se code avec trois nombres de base en octale.
Ex, Si l’on souhaite que par défaut l’utilisateur sisr, crée des fichiers avec les permissions rw- r-- --- :
- Le premier nombre octal sera 0 (on ne change rien à rw-)
- Le second nombre (groupe) sera 2 (on supprime la permission w, donc 2, il reste r--)
- Le troisième nombre (others) sera 6 (on supprime r soit 4 et w soit 2, il reste ---)
Le umask de l’utilisateur sisr doit donc être 026
Sur un dossier, sans droits d’exécution, il est impossible d’agir dans le dossier, et les éventuels droits en écriture dans ce dossier ne seront pas appliqués.
De ce fait, les permissions “maximales” par défaut accordées à la création d’un dossier sont : rwx rwx rwx soit 777 en octal
Exemple: Le propriétaire doit disposer des droits complets sur le dossier, seulement des droits d’exécution et lecture pour le groupe, et aucun droits pour les autres. Ceci se traduit par : rwx r-x ---
Le umask de l’utilisateur devra retirer les droits en écriture sur le groupe (-2) et les droit rwx à others (-7). Le umask sera donc 027
Umask propose un comportement différent sur les fichiers et sur les dossiers. Mais cette valeur umask est la même pour les fichiers et les dossiers ! On utilise des valeurs “classiques” pour régler umask
Jusqu’ici, nous avons précisé des valeurs sur trois chiffres en base octale. La commande umask affiche le umask de l’utilisateur actuel, mais sur 4 chiffres !
Le premier représente en faite les attributs spéciaux (setuid, setgid, sticky). Cependant, ces attributs spéciaux ne sont pas spécifiables par défaut (lors de la création d’un fichier ou dossier). Il n’est donc pas nécessaire de la préciser ou la calculer lors de l’utilisation de umask.
/!\ Umask n’est utilisé qu’à la création, les fichier existant ne sont pas touchés!
Gestion des archives
Une archive est un fichier contenant un ou plusieurs fichiers ou dossiers, la plupart du temps “compressés” ce afin de diminuer la
consommation d’espace disque. Il existe de nombreux algorithmes de compression et d’archivage, vous connaissez probablement le zip et le rar connu sous windows. Voyons certains des plus utilisés sous les système linux :
Tar
Tar est une très ancienne commande (Tape Archive), utilisée autrefois pour la sauvegarde de contenu sur des bandes magnétiques. Les
premières versions permettaient uniquement l’archivage, mais depuis l'arrivée de gzip (-z) et bzip2(-j) c’est maintenant possible.
Principaux attributs de tar (extension de fichier .tar en général):
- tar -c : Créer une archive
- tar -cf : Créer une archive et spécifier son nom
- tar -cvf : Créer une archive et afficher un diagnostic à l’écran
- tar -cvzf : Créer une archive, compresser avec gzip et afficher le diagnostic
- tar -tf : Lister (option t) le contenu de l’archive en argument (option f)
- tar -vtf : Lister (t) de façon détaillée (v) l’archive (f)
- tar -xf : Extraire (option x) le contenu de l’archive (f)
Gzip et gunzip
Par défaut l’utilisation de gzip remplace un fichier par sa version compressée ! qui aura l’extension “.gz”. Pour éviter ce comportement si l’on
veut conserver le fichier d’origine, on utilise l’option -c qui va rediriger le contenu extrait vers stdout !) il faudra donc faire soi-même la
redirection vers un fichier :
gzip -c monfichieraziper > monfichieraziper.gz
gzip -cr /etc > etc.gz
Gunzip quand à lui effectue l’opération inverse de gzip, il décompresse une archive gz. Et par défaut comme gzip, il remplace le fichier
d’origine “.gz” par sa version décompressé.
bzip2 et bunzip2
Le fonctionnement est similaire au gzip et gunzip, l'algorithme de compression utilisé est différent cependant. L’extension par défaut que l’on
rencontrera sera : bz2. L’option de récursion -r n’est pas disponible non plus, on utilisera le * à la place.
zip et unzip
Même si ce format est surtout utilisé sous windows, linux dispose de son équivalent :
zip ./test.zip ./test/* va compresser le contenu du dossier test dans le fichier test.zip
zip -r /etc/etc.zip /etc va compresser tout le contenu du dossier /etc
xz
xz -z * permet de compresser des fichiers individuellement (autant d’archives que de fichiers) avec l’extension .xz
xz -d permet de décompresser les fichier
cpio
cpio: copy-in copy-out
En mode copy-out (option -o), les fichiers dans un dossier seront recopiés vers une archive
En mode copy-in (option -i) le contenu d’une archive est listé ou copie les fichiers d’une archive vers un dossier.
dd
Permet d’effectuer la copie d’un fichier un d’une partition complète bit à bit. Cela permet de :
- Cloner un disque ou une partition
- Sauvegarder la MBR (master boot record)
- Création d’un fichier d’une taille précise rempli de 0
Recherche de fichier grâce aux commandes locate et find
locate et find sont les deux commandes principales pour chercher des fichiers dans la table d’inode de linux. Elles fonctionnent différemment
mais permettent le même résultat. Nous verrons aussi les commandes whereis / which / type
locate
Cette commande utilise une base de données mise à jour quotidiennement par l’OS. Si vous désirez mettre à jour cette base de données, vous
pouvez utiliser la commande updatedb
Les particularités de cette commande :
- N’affiche que les fichiers lisibles par l’utilisateur
- Très rapide pour la recherche, mais les fichiers récents seront absent à moins d’utiliser l’updatedb
- peut nécessité d’être installé apt-get install locate
find
La commande a besoin de plusieurs choses pour travailler :
- Un nom de dossier comme point de départ de la recherche (sinon travail depuis le dossier courant)
- Pour rechercher un fichier on utilise l’option -name
- Plus lent que locate mais permet de se positionner où l’on veut et n’oubliera aucun fichier
Vous remarquez qu’il y a beaucoup moins de fichiers, c’est qu’il faut utiliser le globing :
exemple : find / -name *passwd*
Voici différents options pour le find :
Options | Exemple | Description |
-iname | -iname Hello | recherche les fichiers en ignorant la casse |
-mtime | -mtime -7 | Les fichiers modifiés il y a moins de 7 jours |
-mmin | -mmin 5 |
Les fichiers modifiés il y a moins de 5 minutes |
-size | -size +10M | Les fichiers pesant plus de 10Mo |
-user | -user sisr | Les fichiers possédés par l’utilisateur sisr |
-empty | -empty | liste les fichiers vides |
-type | -type d | Liste les fichiers qui sont des dossiers |
-maxdepth | -maxdepth 1 | Profondeur de recherche limité à 1, ne parcourt pas les sous-dossiers |
Si l’on veut tous les fichiers créés par l’utilisateur sisr qui s’appelle hosts :
find / -user sisr -name hosts
Ou une syntaxe plus compliquée :
find / -iname ‘ifconfig*’ -o \( -name hosts -user sisr \)
cette commande trouvera à partir du dossier racine :
- Tous les fichiers commençant par ifconfig
- OU Tous les fichiers intitulés hosts appartenant à l’utilisateur sisr
Pour définir sur quels attributs effectués un OU, il faut mettre les attributs entre parenthèses. Le problème c’est que le shell interprète la parenthèse comme un caractère spécial, il faut donc le protéger en utilisant \ devant chaque parenthèse pour dire au shell de ne pas l'interpréter mais de l’envoyer directement à la commande find. Le caractère \ est remplaçable par le ‘ find . -name host* -exec ls -l {} \;
- Trouver tous les fichiers commençant par host dans le dossier actuel et ses sous-dossiers
- Puis lancer la commande ls -l pour chaque fichier trouvé
- le {} permet de passer, fichier par fichier, la main à la commande ls
- Pour que ceci fonctionne, il faut rajouter un ; à la fin de chaque fichier passé en argument, donc \;
whereis et which
- whereis trouve deux binaire au nom de base
- which nous indique que seul bash est utilisé quand on utilise la commande base et non pas bash.bashrc. Ce dernier est un script
automatiquement lancé lorsqu'on se connecte à la ligne de commande en mode interactif.
Swap
Le swap est un espace d’échange qui recueille des données normalement en RAM lorsque l’utilisation de celle-ci dépasse un certain point.
Gérer les espaces d’échange
Voir l’utilisation des espaces d’échanges
cat /proc/swaps
Cela va donner quelque chose comme :
Filename Type Size Used Priority
/dev/dm-3 partition 3911676 3906776 -2
/var/swap file 5242876 310324 -3
Monter et démonter un espace d’échange
Les termes de montage/démontage ne sont pas corrects car les espaces d’échange ne sont pas montés sur le système. Vous ne les verrez pas avec la commande mount
.
Pour ne plus utiliser un espace d’échange :
swapoff /dev/dm-3
Cette commande peut prendre un peu de temps car le contenu de l’espace d’échange va être déplacé dans la RAM ou dans un autre espace d’échange, ou oublié par le système s’il n’y a plus de place disponible.
Pour le réutiliser :
swapon /dev/dm-3
L’option -a
permet d’agir sur tous les espaces d’échanges connus du système (dans /etc/fstab
la plupart du temps. Systemd a un truc pour ça aussi, mais je ne l’ai encore jamais rencontré). Exemple :
swapoff -a
swapon -a
Modifier le recours aux espaces d’échange
Les espaces d’échanges vont être utilisés avec plus ou moins d’agressivité selon la valeur de vm.swappiness
de votre système (pour voir cette valeur : sysctl vm.swappiness
). Cette valeur peut être comprise entre 0 et 100.
Un nombre élevé veut dire que le noyau va avoir plus tendance à décharger la RAM dans les espaces d’échanges que dans un système avec un nombre bas.
Pour modifier temporairement la valeur :
sysctl -w vm.swappiness=10
Pour la modifier de façon permanente :
echo "vm.swappiness = 10" > /etc/sysctl.d/99-swappiness.conf
sysctl -p /etc/sysctl.d/99-swappiness.conf
(le sysctl -p
est là pour appliquer la valeur que vous venez de mettre dans le fichier)
Les différents supports d’espaces d’échanges
On peut avoir du swap avec une partition comme le propose Debian lors de l’installation ou via un fichier swap, comme le fait Ubuntu. On peut aussi avoir du swap… sur la RAM ! (voir plus bas)
L’avantage du fichier sur la partition est sa manipulation plus facile. Je pense en particulier à la modification de la taille du swap.
Créer un fichier swap
C’est excessivement simple : on crée un fichier, on le prépare comme il faut, on le déclare dans /etc/fstab
et on l’utilise.
fallocate -l 2G /var/swap
mkswap /var/swap
chmod 600 /var/swap
echo "/var/swap none swap sw 0 0" >> /etc/fstab
swapon /var/swap
Utiliser de la RAM pour l’espace d’échange
Cela paraît contre-intuitif, mais c’est très simple : l’espace d’échange sera compressé et conservé en RAM. Le coût en performances de la compression/décompression des données est, avec nos processeurs actuels, généralement moindre que celui de l’utilisation d’un disque, fut-il SSD : la RAM permet des accès beaucoup, beaucoup plus rapides que n’importe quel disque.
Comme les espaces d’échanges sont utilisés comme de la RAM supplémentaire, mais lente, avoir ceux-ci sur la RAM, mais compressés équivaut plus ou moins à une augmentation de taille de RAM au prix de quelques cycles CPU.
Pour utiliser ce mécanisme, il suffit, sur Debian, d’installer le paquet zram-tools
, de modifier /etc/default/zramswap
à son goût et de relancer le service zramswap
.
Curl
Ceci constitue un petit inventaire des commandes les plus utiles de curl
.
Utilisation de base
curl http://example.org
La commande curl
télécharge la ressource demandée (qui n’est pas nécessairement une adresse web, car curl
est capable de télécharger des ressources d’autres protocoles, comme ftp
par exemple) et en affiche le contenu sur la sortie standard, si ce contenu n’est pas un contenu binaire.
Rediriger la ressource vers un fichier
curl http://example.org > fichier.html
curl http://example.org --output fichier.html
curl http://example.org -o fichier.html
Réduire la verbosité de curl
Lorsque la sortie est redirigée vers un fichier, curl
affiche une barre de progression donnant certaines indications sur le téléchargement de la ressource (le temps restant, la taille…).
Pour ne pas afficher ces informations, on utilise l’option --silent
ou son abbréviation -s
.
curl --silent http://example.org -o fichier.html
curl -s http://example.org -o fichier.html
Faire autre chose qu’un GET
Pour utiliser une autre méthode HTTP que GET
, on utilise l’option --request
ou son abbréviation -X
.
curl --request POST http://example.org
curl -X POST http://example.org
Faire une requête HEAD
Si on tente de faire une requête HEAD
avec l’option --request
, curl
affichera un message d’erreur :
Warning: Setting custom HTTP method to HEAD with -X/--request may not work the
Warning: way you want. Consider using -I/--head instead.
Il convient d’utiliser l’option --head
ou son abbréviation -I
:
curl --head http://example.org
curl -I http://example.org
Pour faire une requête avec authentification HTTP
On spécifie l’identifiant et le mot de passe avec l’option --user
ou son abbréviation -u
, en les séparant par un caractère :
.
curl --user login:password http://example.org
curl -u login:password http://example.org
Forcer la connexion en IPv6 ou en IPv4
On utilise pour cela les options -6
et -4
.
curl -6 http://example.org
curl -4 http://example.org
Utilisation avancée
Forcer la connexion sur une autre adresse IP
Il est possible de dire à curl
d’utiliser une adresse IP particulière au lieu de la véritable adresse IP d’un domaine. Il faut voir cela comme une alternative à la manipulation du fichier /etc/hosts
.
curl --resolve example.org:80:127.0.0.1 http://example.org
curl --resolve "example.org:80:[::1]" http://example.org
La syntaxe de l’option est host:port:addr
. Le port est celui qui sera utilisé par le protocole. Spécifier le port 80
pour le protocole https
serait inutile : il faut dans ce cas utiliser le port 443
.
Forcer la connexion sur une autre adresse IP et un autre port
On utilise pour cela l’option --connect-to
, relativement similaire à l’option --resolve
. La syntaxe de l’option est host1:port1:host2:port2
curl --connect-to example.org:80:127.0.0.1:8080 http://example.org
curl --connect-to "example.org:80:[::1]:8080" http://example.org
Forcer la connexion depuis une certaine interface réseau
On utilise pour cela l’option --interface
suivi du nom d’une interface, d’une adresse IP ou d’un nom d’hôte.
curl --interface wlo1 http://example.org
curl --interface 203.0.113.42 http://example.org
curl --interface example.com http://example.org
Ne pas vérifier la sécurité du certificat du site
Que ce soit parce qu’un certificat est expiré ou parce qu’on utilise un certificat autosigné, on peut avoir besoin que curl
effectue bien la requête sans se préoccuper de la validité du certificat utilisé par le site. On utilise alors l’option --insecure
ou son abbréviation -k
.
curl --insecure https://example.org
curl -k https://example.org
Utiliser un fichier d’autorités de certification spécifique
Si on utilise, par exemple, un certificat autosigné, ou signé par une autorité de certification (AC) personnelle, et qu’on souhaite s’assurer que le certtificat utilisé par le site est bien valide, on peut donner à curl
un fichier contenant le certificat public de l’AC (il est possible d’y mettre plusieurs certificats) au format PEM. On utilise l’option --cacert
.
curl --cacert fichier_AC.pem https://example.org
On peut aussi utiliser l’option --capath
dont l’argument est un dossier contenant des fichiers de certificats d’AC.
curl --capath ~/ACs https://example.org
Sed
C’est l’outil absolu pour modifier du texte en le passant par un pipe ! Ou pour effectuer des changements en masses sur un fichier sans l’ouvrir.
Il est possible de faire des trucs de tarés avec c’est pas juste un truc pour faire des substitutions à coup d’expressions rationnelles, c’est un vrai éditeur de texte, on peut se balader dans le texte, faire des copier/coller, etc.
Syntaxe de base
Avec un fichier :
sed <commande> fichier.txt [fichier2.txt] [fichier3.txt]
En utilisant la sortie d’une autre commande :
find . -name \*.txt | sed <commande>
NB : sed
, par défaut, ne modifie pas le fichier utilisé.
Il affichera sur la sortie standard le fichier modifié par la commande passée à sed
.
Si on souhaite que le fichier soit modifié, on utilise l’option --in-place
ou son abbréviation -i
(on peut indifféremment placer l’option avant ou après la commande) :
sed <commande> --in-place fichier.txt
sed -i <commande> fichier.txt
Expression régulières
Si sed
est un éditeur de texte (son nom veut dire Stream EDitor) et qu’il est utilisable en lui donnant des commandes équivalentes à « Va à ligne 3, supprime 4 caractères, descend à la ligne suivante… », on l’utilise souvent avec des expressions régulières.
Rappel sur les expressions régulières
Les expressions régulières permettent de rechercher des correspondances avec un motif, écrit avec une syntaxe spéciale.
Les éléments de syntaxe suivants appartiennent aux Perl Compatible Regular Expression (PCRE), qui sont le standard de la très grande majorité des langages de programmation.
sed
utilisant une syntaxe légèrement différente, certains caractères devront être échappés (voir plus bas).
NB : les expressions régulières de cette section sont placé entre des /
pour les distinguer des chaînes de caractères simples.
.
: correspond à un caractère, n’importe lequel././
correspondra à tout sauf à une chaîne vide?
: quantificateur, modifie la correspondance du caractère qui le précède : celui ci peut être présent zéro ou une fois./a?/
correspondra à une chaîne vide ou àa
+
: quantificateur : le caractère précédent sera présent une ou plusieurs fois./a+/
correspondra àa
,aa
,aaa
…*
: quantificateur : le caractère précédent sera présent zéro ou plusieurs fois./a*/
correspondra à une chaîne vide, àa
,aa
,aaa
…{n}
: quantificateur : le caractère précédent sera présentn
fois./a{3}/
correspondra àaaa
{n,m}
: quantificateur : le caractère précédent sera présent den
àm
fois./a{3,5}/
correspondra àaaa
,aaaa
ouaaaaa
{n,}
: quantificateur : le caractère précédent sera présent au moinsn
fois./a{3,}/
correspondra àaaa
,aaaa
,aaaaa
,aaaaaa
…|
: séparateur d’expression./bonjour|hello/
correspondra àbonjour
ou àhello
[^liste]
: correspond aux caractères n’étant pas entre crochets./[^ae]/
correspondra à n’importe quel caractère sauf àa
et àe
[liste]
: correspond à un des caractères entre crochets./[ae]/
correspondra àa
ou àe
. Pour que le caractère^
soit un choix possible, il faut le placer à une autre place que la première place :[liste^]
,[lis^te]
… On peut aussi spécifier des plages de caractères :[0-9a-zA-Z]
^
: ancre, correspond au début de la ligne./^a/
correspondra àa
si celui-ci est le premier caractère de la ligne$
: ancre, correspond à la fin de la ligne./a$/
correspondra àa
si celui-ci est le dernier caractère de la ligne(…)
: groupe l’expression. On peut s’en servir, par exemple, pour capturer des éléments (ce qui permet de les réutiliser plus tard) ou faire des sous-expressions./Bonjour (foo|bar), ça va \?/
correspondra àBonjour foo, ça va ?
et àBonjour bar, ça va ?
Pour utiliser les caractères de manière littérale (exemple : pour correspondre à un point), on les échappera avec un \
. /\./
correspondra au caractère point (.
).
Caractères à échapper dans sed
La version GNU de sed
utilise les Basic Regular Expression (BRE), qui ont une syntaxe légèrement différentes des PCRE.
Certains caractères doivent donc être échappés dans les BRE, qui sont utilisables tels quels pour des PCRE :
- le quantificateur
+
. Exemple :/a\+/
- le quantificateur
?
. Exemple :/a\?/
- le quantificateur
{i}
. Exemple :/a\{5\}/
- les parenthèses
(…)
. Exemple :/\(a\)/
- le séparateur d’expressions régulières
|
. Exemple :/a\|b/
Effectuer une substitution de texte
La commande à utiliser est 's/expression régulière/substitution/'
:
sed 's/foo/bar/' foo.txt
Cette commande remplacera la 1ère occurrence de foo
de chaque ligne du fichier par bar
.
Si on souhaite remplacer toutes les occurrences de chaque ligne, on emploie le modificateur g
:
sed 's/foo/bar/g' foo.txt
Si on ne souhaite remplacer que l’occurrence n°X de chaque ligne :
sed 's/foo/bar/X' foo.txt
## Exemple avec la 2e occurrence :
sed 's/foo/bar/2' foo.txt
Si on ne souhaite remplacer l’occurrence n°X de chaque ligne, ainsi que les suivantes :
sed 's/foo/bar/gX' foo.txt
## Exemple avec la 2e occurrence et les suivantes :
sed 's/foo/bar/g2' foo.txt
Ajouter quelque chose au début de chaque ligne :
sed 's/^/FooBar /' foo.txt
Ajouter quelque chose à la fin de chaque ligne :
sed 's/$/ BazQux/' foo.txt
Si on souhaite que l’expression régulière soit insensible à la casse (ex : s
qui correspond aussi à S
), on emploie le modificateur i
:
sed 's/foo/bar/i' foo.txt
On peut utiliser plusieurs modificateurs en même temps :
sed 's/foo/bar/gi' foo.txt
Pour réutiliser ce qui a correspondu à l’expression régulière dans la chaîne de substitution, on utilise le caractère &
:
sed 's/foo/& et bar/' foo.txt
Pour réutiliser ce qui a correspondu à un groupe d’expression, on utilise \1
pour le 1er groupe, \2
pour le 2e groupe… :
sed 's/Bonjour (foo|bar). Il fait beau./Bonsoir \1. À demain./' foo.txt
NB : on peut utiliser d’autres séparateurs que le caractère /
, ce qui rend l’écriture d’une commande plus simple si l’expression régulière ou la substitution comportent des /
: plus besoin de les échapper.
Exemple :
sed 's@/home/foo@/var/bar@' foo.txt
Supprimer des lignes
Supprimer la ligne n
:
sed 'nd' foo.txt
## Exemple avec la 3e ligne :
sed '3d' foo.txt
Supprimer les lignes n
à m
:
sed 'n,md' foo.txt
## Exemple :
sed '3,5d' foo.txt
Supprimer toutes les lignes sauf la ligne n
:
sed 'n!d' foo.txt
## Exemple :
sed '6!d' foo.txt
NB : attention, le caractère !
est un caractère spécial pour bash
(et les autres shells).
Si vous utilisez des apostrophes ('
) pour votre commande sed
, tout ira bien, mais si vous utilisez des guillemets doubles ("
), il faut l’échapper avec un \
.
Supprimer toutes les lignes sauf les lignes n
à m
:
sed 'n,m!d' foo.txt
## Exemple :
sed '6,8!d' foo.txt
Supprimer les lignes qui correspondent à une expression régulière :
sed '/regex/d' foo.txt
## Exemple :
sed '/foobar/d' foo.txt
Pour supprimer les lignes vides, d’un fichier, il suffit d’utiliser l’expression régulière qui signifie que la ligne est vide :
sed '/^$/d' foo.txt
Pour supprimer la première ligne correspondant à une expression régulière, ainsi que toutes les lignes suivantes :
sed '/regex/,$d' foo.txt
## Exemple :
sed '/foobar/,$d' foo.txt
NB : attention encore une fois aux guillemets doubles, il faudrait échapper $
dans cette commande car le shell essayerait d’interpréter $d
comme une variable.
AT
Elle est utilisée pour planifier des actions qui doivent se réaliser ultérieurement et une seule fois. (Une sorte de tache planifié mais sans la répétition).
Par défaut elle n’est pas forcément installé sur votre distribution, pour l’installer :
apt install at
Si ca ne marche pas , faites avant un apt-get update.
Puis lancer le service avec :
service atd start
ou
systemctl start atd.service
systemctl enable atd.service
Exemple d’utilisation :
at now +2 minutes
Au prompt, entrer la commande désirée, par exemple :
at> echo “A noter” > /root/exercicesAT.txt
Pour sortir du prompt, faire un CTRL+D
Le système vous renverra un message de la forme :
Job 1 at JOUR MOI NUMJOUR HEURE ANNEE
Avec la commande atq
, vous pouvez visualiser la file de traitement, le premier numéro est le numéro du job dans la file de traitement, suivi de l’horodatage, puis de l’utilisateur ayant lancé le job.
exemple 2 :
at 4:00 AM tomorrow
at> rm /root/exercicesAT.txt
at> <EOT>
Pour supprimer un job at, il faut utiliser son numéro obtenu avec atq :
atrm numjob
Grâce à l’option -f, suivi du script puis de l’heure on peut lancé directement un bash :
ex :
at -f /root/test.sh 10:30 PM
Vous pouvez sécuriser la commande at, grâce au fichier /etc/at.allow pour placer dans ce
fichier les utilisateurs autorisés (whitelist)
Ex :
nano /etc/at.allow
Awk
Cette commande agit comme un filtre programmable, prenant une série de lignes en entrée (par fichier, ou via l’entrée standard) et écrivant sur la sortie standard (redirigeable). Awk prend en entrée les lignes une par une et choisit les lignes à traiter (ou non) par des expressions rationnelles ou des numéros de lignes. Une fois la ligne sélectionnée, elle est découpée en champs, selon un séparateur d’entrée indiqué dans le programme awk par le symbole FS (par défaut espace et tabulation). Puis les différents champs sont disponibles dans les variables ($1, $2, $3, $NF pour le dernier). Vous pourrez aussi trouver des fichiers .awk qui sont des scripts écrits dans ce langage.awk [-F] '{action-awk}' [ fichier1 fichier2 ..... fichiern ]
La commande prend en paramètre la liste des fichiers à traiter, si des fichiers ne sont pas spécifiés, awk travaillera sur l’entrée standard. On peut donc placé la commande derrière un tube de communication. L’option “-F” permet d'initialiser si besoin la variable “FS” (Field Separator).
Voici une liste des variables prédéfinies au lancement de awk:
Variables | Valeur par défaut | Rôle |
RS | Newline (\n) |
Record Separator : Caractère séparateur d’enregistrement (lignes) |
FS | Suite d’espaces et ou de tabulation | Field Separator : caractères séparateurs de champs. |
OFS | Espace |
Output Field Separator: Séparateur de champ pour l’affichage |
ORS | Newline (\b) |
Output Record Separator : Séparateur de ligne pour la sortie |
ARGV | - |
Tableau initialisé avec les arguments de la ligne de commande (awk inclus) |
ARGC | - | Nombre d’arguments dans le tableau ARGV |
ENVIRON | Variables d’environnement exportées par le shell | Tableau contenant les variables d’environnement exportées par le shell. |
CONVFMT | %.6g | Format de conversion des nombres en string |
OFTM | %.6g | Format de sortie des nombres. |
SUBSEP | \0.34 |
Caractère de séparation pour les routines internes de tableaux. |
Attention : Lorsque que la variable FS a plus de 2 caractères, elle sera interprété comme une expression régulière
Voici les variables qui sont initialisées lors du traitement d’une ligne
Variable | Rôle |
$0 | Valeur de l’enregistrement courant |
NF | $1 contient la valeur du 1er champ, $2 du 2ème, ... et $NF le dernier |
$1,$2, .. $NF |
$1 contient la valeur du 1er champ, $2 du 2ème, ... et $NF le dernier |
NR |
Number : indice de l’enregistrement courant (NR vaut 1 quand la 1ère ligne est en cours de traitement) |
FNR |
File Number : indice de l’enregistrement courant relatif au fichier en cours de traitement |
FILENAME |
Nom du fichier en cours de traitement |
RLENGTH |
Longueur en string trouvé par la fonction match() |
RSTART |
Première position du string trouvé par la fonction match |
Exemple d’utilisation :ps -ef| awk ‘{print $1,$8}’
La partie en gras représente entre quote permet d’éviter l’interprétation par le shell et indique à awk quelle fonction exécuter sur le traitement du awk. Les instructions doivent être placées entre accolades. La fonction intégrée print va afficher à l’écran les champs 1 et 8 de chaque ligne.
Voici un autre exemple :ps -ef | awk ‘{print “User : “, $1, “\tCommande : “, $8}’
Critères de sélection :
Il est possible de sélectionner les enregistrements sur lesquels l’action doit être exécutée : awk [-F] 'critère {action-awk}' [fichier1 fichier2 ... fichiern]
Le critère de sélection peut s’exprimer de différentes manières.
Expression régulières :awk -F’:’ ‘/\/bin\/false/ {print $0}’ /etc/passwd
Par défaut, c’est le champ correspondant au $0 qui est mis en correspondance avec
l’expression régulière., mais il est possible de le spécifier avec l’opérateur de concordance
“~” ou de non concordance “!~”.
awk -F ':' '$6 ~ /^\/usr/ {print $0}' /etc/passwd
Test logiques :
Le critère peut être une expression d’opérateurs renvoyant vrai ou faux.
Par exemple, pour afficher uniquement les lignes impaires du fichier /etc/passwdawk -F':' 'NR%2 {print $0}' /etc/passwd
Find
Introduction
Les exemples de ce tuto sont tous à faire en user sauf spécification.
Cette commande permet de faire des recherches de fichier ou de dossier dans une hiérarchie de répertoires.
Par exemple, je voudrais chercher le log messages, mais je sais pas où se trouve ce fichier, faites :
find / -name 'messages'
- résultat de la commande précédente
-
/var/log/messages
Voilà la réponse :
Il se trouve dans le répertoire /var/log
.
Nota
Notez l'utilisation des apostrophes afin d'éviter que l'interpréteur de commande n'étende le motif.
Elles sont inutiles dans ce cas-ci mais c'est une bonne pratique de toujours les utiliser afin d'éviter l'extension motif.
Quelques options
Options | Fonctions |
---|---|
-atime n ou +n ou -n | trouve les fichiers auxquels on a accédé il y a strictement n jours, ou plus de n jours, ou moins de n jours |
-mtime n ou +n ou -n | trouve les fichiers modifiés il y a strictement n jours, ou plus de n jours, ou moins de n jours |
-maxdepth n | définit le niveau maximum de sous-répertoire à explorer |
-type l ou d ou f | indique le type de fichier à rechercher (l pour lien symbolique, d pour répertoire (directory), f pour fichier) |
-name | recherche par motif en respectant la casse |
-iname | recherche par motif sans respecter la casse |
Recherche simple par nom
Example simple : comment trouver un fichier portant le nom note
?
find / -name 'note'
Décomposition de la commande de l'exemple :
-
“
/
” indique que nous voulons chercher notre fichier à partir de la racine. -
“
-name
” est l'option qui indique ici que nous voulons spécifier le nom d'un fichier.
Après un long délai d'attente, la recherche se faisant dans toute l'arborescence de la partition, la réponse finit par venir :
- résultat de la commande précédente
-
/home/martin/note
Si l'on n'est pas sûr de la casse (Majuscule ou minuscule) on utilise l'option -iname
.
Prenons un autre exemple.
Pour chercher tous les fichiers commençant par note et définir à partir de quel répertoire on souhaite effectuer la recherche on utilise cette syntaxe :
find /home/martin -name 'note*'
Recherche par nom simple & multiple
Maintenant, regardons, encore une fois à l'aide d'un exemple, la syntaxe de la commande find si l'on recherche plutôt un ou plusieurs répertoires.
Je cherche à trouver les répertoires archives dans /media/homebis. Première chose à noter, il peut-être nécessaire de se mettre en root pour avoir accès à tous les répertoires.
find /media/homebis -type d -name 'archives'
Dans ce cas-ci, je demande donc à find de trouver les répertoires
-
option : -type
-
argument : “d” (comme “directory”)
indiquant que l'on cherche un répertoire du nom de archives à partir du répertoire /media/homebis.
La réponse :
- résultat de la commande précédente
-
/media/homebis/martin/textes/mes_archives/Baseball/archives /media/homebis/martin/archives /media/homebis/Documents_gr/Mots_croises/archives /media/homebis/Documents_gr/archives /media/homebis/Documents_gr/mes_fichiers/archives
Autre exemple un peu plus complexe cette fois.
Je désire faire une recherche de tous les fichiers audio de type .mp3 et .ogg
Il existe plus d'une façon d'y arriver.
Voyons comment on peut s'y prendre.
Première façon :
find /home/martin/ \( -name '*.mp3' -o -name '*.ogg' \)
Cela me donnera toute une liste de fichiers /home/martin/…
Deuxième façon :
Une autre manière d'écrire la commande ci-dessus est la suivante :
find -type f -name "*.mp3" -o -name "*.ogg"
Si je tape cette commande en étant dans mon répertoire /home/martin, le résultat sera une liste de fichiers ./….
Il est intéressant de savoir que l'on peut étendre la recherche aux fichiers mp3 et mp4 en remplaçant le 3 par un ?2). La commande deviendrait donc :
find -type f -name "*.mp?" -o -name "*.ogg"
Rechercher pour supprimer
Une fonction intéressante de find est de supprimer en lot les fichiers trouvés.
Il n'est point rare de télécharger ou d'installer de nombreux fichiers qui ne nous servent plus, mais devant le travail pénible de devoir supprimer tous ces fichiers, on repousse au lendemain cette charge. Heureusement grâce à la fonction -delete de find, c'est un pur bonheur.
Paramètre -delete
Exemple, si dans votre home ou autre dossier vous avez beaucoup de fichier .tar.gz qui ne vous servent plus à rien. Il suffit de lancer la commande suivante :
find -iname "*.tar.gz" -delete
Supprimer avec demande de confirmation
Pour une demande de confirmation avant suppression de chaque fichier “.tar.gz” trouvés :
find -iname "*.tar.gz" -ok rm {} \;
Merci à MicP pour cette trouvaille :)
Filtrer en fonction des droits
Une option très pratique est -perm
qui permet de sélectionner des fichiers en fonctions de leurs droits.
Les droits peuvent être donné en forme octale, par exemple 0755 ou littérale, u=rwx,g=rw,o=rw.
Voici par exemple comment obtenir la liste de tout les fichiers dans le repertoire /bin
qui ont le bit setuid valant 1
:
find /bin -perm /5000 -user root
- résultat de la commande précédente
-
/bin/su /bin/mount /bin/umount /bin/ping /bin/ping6
Cette option est intéressante pour la sécurité. Les fichiers listés dans la commande précédente sont tous exécuté avec les droits root
.
perm
, sans préfixe, précédé du signe – ou précédé du signe /-
sans préfixe :
le mode du fichier doit être exactement celui passé à l’option -perm.
Par exemple, si on cherche les fichiers ayant le mode u=rwx (0700), tous les fichiers que l’on trouvera auront exactement le mode u=rwx (0700).
-
avec le signe – :
le mode du fichier doit être au moins égal à celui passé à l’option -perm
-u=r (-0400) → u=r ou u=rw ou u=rx ou u=rwx ou u=r,g=x …
-
avec le signe / :
un des modes (user, group ou other) doit être au moins égal à ceux passés à l’option -perm
/u=w,g=w,o=w → u=w ou g=w ou o=w ou u=w,g=w,o=w ou u=rw,g=rwx …
Recherche par motif
Pour rechercher un motif, il faut utiliser la même option, et utiliser les REGEXP.
Voici par exemple la recherche de tous les fichiers terminant par .java
dans le dossier courant:
find . -name '*.java'
- résultat de la commande précédente
-
./java/jdk1.5.0_06/demo/applets/Animator/Animator.java ./java/jdk1.5.0_06/demo/applets/ArcTest/ArcTest.java ./java/jdk1.5.0_06/demo/applets/BarChart/BarChart.java ./java/jdk1.5.0_06/demo/applets/Blink/Blink.java ./java/jdk1.5.0_06/demo/applets/CardTest/CardTest.java ...
Rechercher les fichiers n'appartenant pas à l'utilisateur
Il peut parfois être utile de rechercher les fichiers n'appartenant pas à l'utilisateur, en vue de corriger un problème rencontré avec une application (par exemple, un fichier peut appartenir à root au lieu d'appartenir à l'utilisateur ; ce dernier risque de ne pas avoir de droits dessus, ce que peut alors provoquer une erreur dans une application cherchant à modifier le dit fichier).
Pour ce faire, il suffit d'exécuter là commande suivante, où « utilisateur » est à remplacer par votre nom d'utilisateur :
find /home/utilisateur ! -user utilisateur
ou bien, en utilisant des variables :
find $HOME ! -user $USER
Pour avoir davantage d'informations sur les fichiers ainsi trouvés, vous pouvez ajouter l'option ls
:
find $HOME ! -user $USER -ls
-exec - Exécuter une commande
La commande find permet d'effectuer toute sorte d'action avec les fichiers trouvés.
Une action très utile est “-exec
” qui permet d'exécuter une commande sur les fichiers sélectionnés.
La syntaxe de exec
est particulière car il faut pouvoir fournir le nom du fichier trouvé.
À la suite de la commande find habituelle, la syntaxe est :
find /chemin/du/fichier/ <option> <caractéristique fichier> -exec commande {} \;
-
La paire d'accolade est automatiquement remplacée par le nom du fichier,
-
et le point-virgule final permet de marquer la fin de la commande.
Au cas où plusieurs fichiers sont traités dans un même répertoire, pour éviter une relance de la commande après chaque fichier trouvé, remplacer le ;
(point-virgule) final par le signe positif : +
.
Par exemple ainsi :
find /home/mon_user/test/ -type f -exec echo {} \+
De la même manière, évitez les références vides ou les noms de répertoires exprimés en relatif dans $PATH.
Avec Bash, la paire d'accolades sans espace ({}
) ne doit pas être protégée, au contraire du point-virgule qui doit être échappé à l'aide d'un backslash: \;
.
Voici par exemple comment on peut compter le nombre de lignes de chaque fichier de code Python de ce site:
find developpement/django/certif -name '*.py' -exec wc -l {} \;
- résultat de la commande précédente
-
1 developpement/django/certif/__init__.py 0 developpement/django/certif/acronym/__init__.py 48 developpement/django/certif/acronym/models.py 82 developpement/django/certif/acronym/tools.py 13 developpement/django/certif/acronym/urls.py 42 developpement/django/certif/acronym/views.py .../...
-
Ici la commande find est utilisée avec l'option
-name
pour ne sélectionner que les fichiers se terminant par “.py
” (extension de Python). -
La commande “
wc
” (qui compte le nombre de ligne avec -l) est invoquée à l'aide “-exec
” sur chacun de ces fichiers.
Il existe d'autres variantes de l'exécution de commande comme l'option -execdir
qui exécute la commande à partir du répertoire du fichier.
Comme d'habitude vous avez aussi le :
man find
Entièrement disponible à votre curiosité !
Tmux
Tmux est un multiplexeur de terminal. Il permet d'utiliser plusieurs terminaux virtuels dans une seule fenêtre de terminal ou une session sur un terminal distant.
Ligne de commande
Lancement
Rien de plus simple :
tmux
Pour nommer une session :
tmux new-session -s <nom de la session>
Voir les sessions tmux existantes
tmux ls
Se rattacher à une session tmux existante
S’il n’y a qu’une seule session, ou si vous voulez vous rattacher à la dernière auquelle vous étiez rattaché :
tmux at
Si vous souhaitez cibler une autre session :
tmux at -t <nom de la session>
Bonus : vous pouvez être plusieurs personnes sur une même session. C’est très pratique quand on doit faire des manipulations à plusieurs, ou dans un but didactique.
Couper une session tmux existante
S’il n’y a qu’une seule session, ou si vous voulez couper la dernière auquelle vous étiez rattaché :
tmux kill-session
Si vous souhaitez cibler une autre session :
tmux kill-session -t <nom de la session>
Aide
Faites Ctrl
+b
puis ?
et tmux vous affichera une liste de commande accesibles avec des raccourcis claviers
Raccourcis claviers usuels
Se détacher de la session tmux
Tmux peut continuer à fonctionner même quand on est déconnecté ou qu’on se détache de la session, ce qui est très pratique pour :
- les connexions réseaux moisies qui vous déconnectent de votre session SSH
- lancer une commande qui va durer longtemps
Ctrl
+b
puis d
Ouvrir une nouvelle fenêtre
Ctrl
+b
puis c
Naviguer entre les fenêtres
Ctrl
+b
puis n
(-> next
) pour passer à la fenêtre suivante.
Ctrl
+b
puis p
(-> previous
) pour passer à la fenêtre précédente
Renommer une fenêtre
Ctrl
+b
puis ,
, vous aurez un prompt dans la barre en bas, tapez ce que vous voulez et appuyez sur la touche Entrée
.
Pour sortir du prompt sans valider, appuyez sur la touche Esc
.
Créer un nouveau panneau
En coupant la fenêtre horizontalement
Le nouveau panneau sera créé à droite du panneau courant.
Ctrl
+b
puis %
En coupant la fenêtre verticalement
Le nouveau panneau sera créé en dessous du panneau courant.
Ctrl
+b
puis "
Zoomer sur un panneau
Si les panneaux sont pratiques, on a parfois envie d’en prendre un et de l’avoir temporairement en plein écran. Pour ça :
Ctrl
+b
puis z
Et on utilise le même raccourci pour remettre le panneau en petit comme avant.
Naviguer entre les panneaux
Ctrl
+b
puis utiliser les flèches du clavier
Commandes
Pour entrer en mode commande, faites Ctrl
+b
puis :
.
Vous aurez un prompt dans la barre en bas.
Afficher toutes les commandes disponibles
Utiliser la commande list-commands
.
Changer le répertoire de départ
Quand on ouvre un tmux, chaque nouvelle fenêtre ou nouveau panneau s’ouvrira dans le répertoire depuis lequel vous avez créé le tmux.
Pour changer ce répertoire de départ, utiliser la commande attach -c /le/dossier/que/vous/voulez
.
Afficher les variables d’environnement de la session
Utilisez la commande show-environnement
ou son alias showenv
.
Ce sont les variables d’environnement de tmux : il y a aussi les variables d’environnement du système, qui sont copiées par tmux au démarrage d’une session et qui sont fusionnées avec les variables d’environnement de tmux, celles-ci ayant la priorité si une variable existe dans les deux environnements.
Paramétrer une variable d’environnement pour la session
Pour modifier ou ajouter une variable d’environnement à la session, utilisez la commande set-environnement NOM_VAR valeur
ou son alias setenv NOM_VAR valeur
.
Copie de Fichiers avec scp
Voici la syntaxe générale de la commande scp
:
scp [[user@]host1:]file1 ... [[user@]host2:]file2
Cette commande permet de copier un fichier d'une machine host1 vers la machine host2... Ccnsultez la manuel pour plus de détails : man scp
. En général, on l'utilise plus simplement pour copier un fichier file1 de la machine locale vers le home (~) distant de user sur la machine cible host2 :
scp file1 user@host2:~/
Ou inversement, pour copier un fichier file1 de la machine distante host1 vers le répertoire courant (.) de votre machine locale : locale :
scp user@host1:~/file1 .
Nota Bene : Dans chaque commande, il faut remplacer user par le login associé à votre compte sur la machine source / cible.
Mise à jours automatique avec unattended-upgrades
Objectif
Configurer des mises à jour de sécurité automatiques sur une machine Debian/Proxmox à l’aide de unattended-upgrades
.
Installation des paquets
apt update
apt install unattended-upgrades apt-listchanges -y
Activation automatique avec dpkg-reconfigure
dpkg-reconfigure unattended-upgrades
Répondre "Oui" à la question pour activer les mises à jour de sécurité automatiques.
Vérification et configuration automatique
L’outil dpkg-reconfigure
crée ou met à jour ce fichier :
/etc/apt/apt.conf.d/20auto-upgrades
Avec un contenu équivalent à :
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";
Test de fonctionnement
Lancer une simulation de mise à jour automatique :
unattended-upgrade --dry-run --debug
Fichier de configuration avancée (facultatif)
Il est possible de personnaliser les origines de mise à jour et les paquets à exclure dans :
/etc/apt/apt.conf.d/50unattended-upgrades
Par exemple, pour Proxmox, on peux ajouter une blacklist :
Unattended-Upgrade::Package-Blacklist {
"proxmox-ve";
"pve-kernel";
"pve-manager";
"pve-qemu-kvm";
"lxc-pve";
"libpve*";
};
Et activer les origines pertinentes si on veux inclure les mises à jour Proxmox (avec ou sans abonnement) :
Unattended-Upgrade::Allowed-Origins {
"Debian stable";
"Debian stable-updates";
"Debian-security stable-security";
"PVE pve-no-subscription"; // ou "PVE pve-enterprise"
};
SSH - Ajout de la 2FA
La double authentification permet d'ajouter au système d'authentification classique (mot de passe ou clé SSH) une couche supplémentaire unique avec un code unique générer régulièrement.
Personnellement je l'utilise sur toutes les machines ou le SSH est activé sur le port publique.
Installation du module PAM Google Authenticator
! Ce produit est développé par Google mais aucune information personnelle ou donnée de tracking n'est envoyé à Google lors de son installation ou de son utilisation ! #RGPD
Le module s'installe de la manière la plus classique:
apt install libpam-google-authenticator -y
Configuration de PAM
Modifier le fichier /etc/pam.d/sshd
pour ajouter:
auth required pam_google_authenticator.so
Configuration de sshd
Modifier le fichier /etc/ssh/sshd_config
pour modifier la ligne:
ChallengeResponseAuthentication no
Par:
ChallengeResponseAuthentication yes
Initialisation de la 2FA
Il faut être connecté avec le compte sur lequel on souhaite activer la 2FA en ssh !
Lancer la commande suivante:
google-authenticator
Et répondre aux questions de la manière suivante:
Do you want authentication tokens to be time-based (y/n) y
# A ce moment le QR-Code apparait, pour évité qu'un écran petit cache le code après avoir répondu au question, il est recommander d'ajouter le code maintenant avec la "Ajout de la 2FA sur son mobile"
Do you want me to update your "/root/.google_authenticator" file? (y/n) y
# La réponse à la prochaine question dépant de vous
# Si vous réponder 'n' vous accepter qu'un code puisse être utiliser plusieurs fois
Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y
# La question suivante défini la possibilité d'utiliser un code dans les 4 minutes qui suive afin de compenser une de-synchronisation de temps
# Répondre 'y' autorise les 4 minutes mais augment les chances d'attaque
By default, a new token is generated every 30 seconds by the mobile app.
In order to compensate for possible time-skew between the client and the server,
we allow an extra token before and after the current time. This allows for a
time skew of up to 30 seconds between authentication server and client. If you
experience problems with poor time synchronization, you can increase the window
from its default size of 3 permitted codes (one previous code, the current
code, the next code) to 17 permitted codes (the 8 previous codes, the current
code, and the 8 next codes). This will permit for a time skew of up to 4 minutes
between client and server.
Do you want to do so? (y/n) n
# Ici on indique si oui ou non on veut limité le nombre d'essaie à la 2FA
# Très fortement déconseillier de mettre non car cela autoriserais un robot à faire une attaque brut-force
If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting? (y/n) y
Redémarrage du service sshd
Redémarrer le service sshd afin d'appliquer les paramètres:
systemctl restart sshd
Connexion Clé SSH
Génération de la paire de clés:
Pour générer la paire de clé utiliser ssh-keygen
. On préfèreras générer une clé en ECSDA d'une longueur supérieur à 256 bits pour respecter les recommandations R9 et R10 du guide de l'ANSSI sur OpenSSH. La clé publique est facilement reconnaissable car elle se fini en .pub.
ssh-keygen -t ecdsa -b 521
Il est possible de protéger les clés avec une phrase de passe. Cette phrase de passe doit être rentrée à chaque utilisation de la clé, ce qui n'est pas une bonne chose pour l'automatisation. Pour palier ce problème il est possible d'utiliser l'agent SSH ssh-agent
qui va servir de trousseau de clé.
Partage de la clé publique
La clé publique est celle qui doit être présente dans le fichier authorized_keys sur le serveur distant. Il est recommander d'utiliser ssh-copy-id qui vas créer les fichier nécessaires et ajouter la clé automatiquement. Ce dernier n'est pas toujours disponible, alors il faut s'orienter vers des méthodes plus manuel.
ssh-copy-id:
ssh -i ~/.ssh/mykey user@host
Manuel:
Commencer par copier la clé publique sur le serveur distant, pas exemple avec scp:
scp mykey.pub user@host:/home/user
Puis ajouter la clé au fichier authorized_keys:
echo -e "\n"`cat mykey.pub` >> .ssh/authorized_keys
Agent SSH:
L'agent SSH permet de garder les clés de manière protégé en mémoire pour qu'elles puissent être utilisées sans entrer la phrase de passe. (Les clés sont gardée même après un redémarrage.)
Sous Windows :
Élévation de privilège requise
Sous Windows l'agent SSH est désactivé par défaut. Il est possible de l'activer avec une commande Powershell:
Set-Service ssh-agent -StartupType Automatic
Cette commande est l'équivalent d'aller dans le gestionnaire des services et de passer le démarrage du service OpenSSH Authentication Agent en "Automatique". Le démarrage "Automatique" veut dire que le service démarreras au démarrage de Windows.
Si l'on veut uniquement démarrer l'agent juste pour la durée de la session il est nécessaire de premièrement activer le service, puis de le démarrer :
Set-Service ssh-agent -StartupType Manual; Start-Service ssh-agent
Comment changer l’ordre du boot avec GRUB
Après l’installation d’un nouveau système d’exploitation avec une nouvelle partition sur votre système, il peut arriver que vous vouliez changer l’ordre de démarrage des systèmes d’exploitation.
Donc, d’abord il faut vérifier l’ordre par défaut.
Pour ce faire, il faut regarder au démarrage de votre ordinateur, il affiche pendant quelques secondes le choix pour les différents systèmes d’exploitation.
Regardez bien l’ordre !
Comme le montre ma capture d’écran, il faut noter que la première ligne correspond à 0, la deuxième à 1, et ainsi de suite.
Maintenant tapez cette commande :
sudo gedit /boot/grub/grub.cfg
Cherchez « set default= »0″ »
modifiez cette valeur par le numéro de la partition du système qui doit se lancer par défaut (pour moi c’est le numéro 4 si je veux que Windows se lance par défaut au lieu de Fedora).
Enregistrez votre fichier et redémarrez l’ordinateur et normalement l’ordre de boot est changé
How to Add a Directory to PATH in Linux
When you type a command on the command line, you’re basically telling the shell to run an executable file with the given name. In Linux, these executable programs, such as ls
, find
, file
, and others, usually live inside several different directories on your system. All file with executable permissions stored in these directories can be run from any location. The most common directories that hold executable programs are /bin
, /sbin
, /usr/sbin
, /usr/local/bin
and /usr/local/sbin
.
But how does the shell knows, what directories to search for executable programs? Does the shell search through the whole filesystem?
The answer is simple. When you type a command, the shell searches through all directories specified in the user $PATH
variable for an executable file of that name.
This article explains how to add directories to the $PATH
variable in Linux systems.
What is $PATH
in Linux ?
The $PATH
environmental variable is a colon-delimited list of directories that tells the shell which directories to search for executable files.
To check what directories are in your $PATH
, you can use either the printenv
or echo
command:
echo $PATH
The output will look something like this:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
If you have two executable files sharing the same name located in two different directories, the shell will run the file that is in the directory that comes first in the $PATH
.
Adding a Directory to $PATH
There are situations where you may want to add other directories to the $PATH
variable. For example, some programs may be installed in different locations, or you may want to have a dedicated directory for your personal scripts but be able to run them without specifying the absolute path to the executable files. To do this, you simply need to add the directory to your $PATH
.
Let’s say you have a directory called bin
located in your Home directory in which you keep your shell scripts. To add the directory to your $PATH
, type in:
export PATH="$HOME/bin:$PATH"
The export
command will export the modified variable to the shell child process environments.
You can now run your scripts by typing the executable script name without specifying the full path to the file.
However, this change is only temporary and valid only in the current shell session.
To make the change permanent, you need to define the $PATH
variable in the shell configuration files. In most Linux distributions, when you start a new session, environment variables are read from the following files:
-
Global shell-specific configuration files such as
/etc/environment
and/etc/profile
. Use this file if you want the new directory added to all system users$PATH
. -
Per-user shell-specific configuration files. For example, if you use Bash, you can set the
$PATH
variable in the~/.bashrc
file. If you are using Zsh the file name is~/.zshrc
.
In this example, we’ll set the variable in the ~/.bashrc
file. Open the file with your text editor and add the following line at the end of it:
nano ~/.bashrc
export PATH="$HOME/bin:$PATH"
Save the file and load the new $PATH
into the current shell session using the source
command:
source ~/.bashrc
To confirm that the directory was successfully added, print the value of your $PATH
by typing:
echo $PATH
Removing a Directory from $PATH
To remove a directory from the $PATH
variable, you need to open the corresponding configuration file and delete the directory in question from the $PATH
variable. The change will be active in the new shell sessions.
Another rare situation is if you want to remove a directory from the $PATH
only for the current session. You can do that by temporarily editing the variable. For example, if you want to remove the /home/lina/bin
directory from the $PATH
variable, you would do the following:
PATH=$(echo "$PATH" | sed -e 's/:\/home\/lina\/bin$//')
In the command above, we’re passing the current $PATH
variable to the sed
command, which will remove the specified string (directory path).
If you temporarily added a new directory to the $PATH
, you can remove it by exiting the current terminal and opening a new one. The temporary changes are valid only in the current shell session.
Conclusion
Adding new directories to your user or global $PATH
variable is pretty simple. This allows you to execute commands and scripts stored on nonstandard locations without needing to type the full path to the executable.
The same instructions apply for any Linux distribution, including Ubuntu, CentOS, RHEL, Debian, and Linux Mint.
Ajouter un MOTD dynamique
C’est quoi un MOTD ?
Comme indiqué plus haut, lorsque l’on se connecte sur une machine Linux (Débian dans mon cas) en ligne de commande (ici en SSH donc), il y a tout un message qui s’affiche. C’est celui-ci que l’on va modifier afin d’y afficher les valeurs de notre choix !
MOTD de base
Dans mon cas, je souhaite afficher le nom de la machine, ainsi que quelques informations sur la machine comme le CPU, la mémoire libre, l’adresse IP, etc…
Voici un exemple du résultat que j’ai obtenu.
MOTD Personnalisé
Comment changer ce fameux MOTD ?
En fait, lorsque l’on creuse, on se rend compte que c’est intégré nativement à Linux (je le rappelle, dans mon cas ce sont des distributions Débian). Pour faire simple, il suffit de créer des scripts, et de les mettre dans un dossier bien spécifique. Lorsque c’est fait, ils seront automatiquement exécutés lorsque vous allez vous connecter.
Ici, je souhaite avoir le nom de ma machine avec une police originale et en couleur. Je vais donc commencer par installer l’utilitaire qui permet d’écrire de cette façon, à savoir « figlet« .
Pour cela, il faut saisir apt-get update && apt-get install figlet
Une fois installé, vous pouvez tester afin de valider le bon fonctionnement via la commande figlet test
par exemple.
Exemple d’utilisation de Figlet
On se déplace ensuite dans le dossier /etc
dans lequel doit se trouver un dossier nommé update-motd.d
.
Le dossier est bien présent
Si celui-ci n’existe pas, il faut alors le créer et lui donner les droits en exécution via mkdir /update-motd.d && chmod 644 /update-motd.d
.
Si ce dossier existe déjà, vous pouvez vous apercevoir qu’il y a déjà un script 10-uname
. Personnellement je ne vais pas l’utiliser je vais donc le supprimer via rm 10-uname
.
Le principe est simple, tous les scripts se trouvant dans ce dossier sont exécutés lors de la connexion. Il suffit de les nommés 00-xxx, 10-xxx, 20-xxx, etc. pour qu’ils soient exécutés dans l’ordre de votre choix.
Pour créer mon MOTD, je me suis basé sur plusieurs sources (je vous les donnerais toutes à la fin de l’article). Dans l’une de ces sources, il y avait un fichier permettant d’utiliser de la couleur, ce qui est plus sympa !
Je vais donc créer ce fameux fichier, dans mon dossier /etc/update-motd.d
via la commande nano colors
.
On va ensuite y coller le code suivant :
NONE="\033[m"
WHITE="\033[1;37m"
GREEN="\033[1;32m"
RED="\033[0;32;31m"
YELLOW="\033[1;33m"
BLUE="\033[34m"
CYAN="\033[36m"
LIGHT_GREEN="\033[1;32m"
LIGHT_RED="\033[1;31m"
On va maintenant passer au script pour afficher le nom du serveur. Toujours dans le dossier /update-motd.d
nous allons créer un fichier 00-hostname
via nano 00-hostname
et dont le code est le suivant :
#!/bin/sh
. /etc/update-motd.d/colors
printf "\n"$LIGHT_RED
figlet " "$(hostname -s)
printf $NONE
printf "\n"
Ensuite, on passe au second fichier, qui se nomme 10-banner
, et qui va afficher la version Debian qui est utilisée. On le créer donc avec la commande nano 10-banner
, et on y ajoute le code suivant :
#!/bin/bash
#
# Copyright (C) 2009-2010 Canonical Ltd.
#
# Authors: Dustin Kirkland <kirkland@canonical.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
. /etc/update-motd.d/colors
[ -r /etc/update-motd.d/lsb-release ] && . /etc/update-motd.d/lsb-release
if [ -z "$DISTRIB_DESCRIPTION" ] && [ -x /usr/bin/lsb_release ]; then
# Fall back to using the very slow lsb_release utility
DISTRIB_DESCRIPTION=$(lsb_release -s -d)
fi
re='(.*\()(.*)(\).*)'
if [[ $DISTRIB_DESCRIPTION =~ $re ]]; then
DISTRIB_DESCRIPTION=$(printf "%s%s%s%s%s" "${BASH_REMATCH[1]}" "${YELLOW}" "${BASH_REMATCH[2]}" "${NONE}" "${BASH_REMATCH[3]}")
fi
echo -e " "$DISTRIB_DESCRIPTION "(kernel "$(uname -r)")\n"
# Update the information for next time
printf "DISTRIB_DESCRIPTION=\"%s\"" "$(lsb_release -s -d)" > /etc/update-motd.d/lsb-release &
Maintenant, je souhaite dans mon cas, ajouter différentes informations comme le CPU, la charge du système, la RAM libre, etc. J’ai donc pour cela, créé un script que j’ai nommé 20-sysinfo
dont le code est le suivant :
#!/bin/bash
proc=`cat /proc/cpuinfo | grep -i "^model name" | awk -F": " '{print $2}'`
memfree=`cat /proc/meminfo | grep MemFree | awk {'print $2'}`
memtotal=`cat /proc/meminfo | grep MemTotal | awk {'print $2'}`
uptime=`uptime -p`
addrip=`hostname -I | cut -d " " -f1`
# Récupérer le loadavg
read one five fifteen rest < /proc/loadavg
# Affichage des variables
printf " Processeur : $proc"
printf "\n"
printf " Charge CPU : $one (1min) / $five (5min) / $fifteen (15min)"
printf "\n"
printf " Adresse IP : $addrip"
printf "\n"
printf " RAM : $(($memfree/1024))MB libres / $(($memtotal/1024))MB"
printf "\n"
printf " Uptime : $uptime"
printf "\n"
printf "\n"
Comment afficher de façon plus sympa les caractéristiques CPU. En effet, lorsque que l'ont a plusieurs coeurs,on fini par avoir plusieurs fois la ligne qui s’affichait. Ici, cela permet d’indiquer le nombre de coeurs/processeurs avant le type de CPU. Dans le script 20-sysinfo, il faut remplacer la ligne proc par :
proc=`(echo $(more /proc/cpuinfo | grep processor | wc -l ) "x" $(more /proc/cpuinfo | grep 'model name' | uniq |awk -F":" '{print $2}') )`
Maintenant, nous devons rendre ces fichiers exécutable, afin qu’ils soient interprétés à la connexion. Pour cela, on utilise la commande chmod 755 00-hostname
, même chose pour les deux autres fichiers en changeant bien sûr le nom du fichier.
Nos 3 scripts sont maintenant exécutables.
Il nous reste à supprimer l’ancien MOTD, via la commande rm /etc/motd
. Il faut maintenant le récréer via la commande ln -s /var/run/motd /etc/motd
.
Suppression de l’ancien MOTD
Et voilà, à partir de maintenant, lors de la prochaine connexion en SSH, vous devriez avoir votre MOTD, qui correspond aux différents scripts que nous avons vus juste avant.
Voilà notre beau MOTD 🙂
Ajouter des couleurs à ses scripts shell
Les codes
Remise à zéro du formatage
NC='\033[0m'
Couleurs de base
BLACK='\033[0;30m'
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
WHITE='\033[0;37m'
En couleur et en gras
En gras, c’est bold en anglais, d’où le préfixe B
.
BBLACK='\033[1;30m'
BRED='\033[1;31m'
BGREEN='\033[1;32m'
BYELLOW='\033[1;33m'
BBLUE='\033[1;34m'
BPURPLE='\033[1;35m'
BCYAN='\033[1;36m'
BWHITE='\033[1;37m'
Utilisation
RED='\033[0;31m'
NC='\033[0m'
echo -e "${RED}Hello world${NC}"
On notera ici trois choses :
- l’encadrement de la variable par des accolades, pour la séparer du texte (sinon le shell essayerait d’interpréter la variable
$REDHello
, qui n’existe pas) ; - l’utilisation de l’option
-e
d’echo : selon le shell utilisé, le comportement sera différent (les shells bash, dash, zsh (et les autres aussi, sans doute) utilisent leur propre commandeecho
). L’option-e
est nécessaire pour activer l’interprétation des backslash pour/usr/bin/echo
, pas pour leecho
de zsh. Dans le doute, il faut utiliser cette option. - l’utilisation de la variable de remise à zéro à la fin de la phrase. Certains shells vont conserver le changement de formatage de texte après le
echo
(bash, dash), d’autres non (zsh). Encore une fois, dans le doute, on remet le formatage à zéro.
sachant que printf
est plus standardisé, donc au comportement plus constant entre les shells.
Avec printf
, ça donne :
RED='\033[0;31m'
NC='\033[0m'
printf "${RED}Hello world${NC}\n"
À noter, le \n
final, car printf
ne fait pas de retour à la ligne automatiquement.
Exécuter une action à la mise en veille / au réveil
Systemd
On mettra un script dans /lib/systemd/system-sleep/
:
Exemple de script :
#!/bin/sh
case "${1}" in
pre)
echo "Suspension ou hibernation"
;;
post)
echo "Réveil ou dégel"
;;
esac
Le 2e argument ($2
) pourra être suspend
, hibernate
, suspend-then-hibernate
ou hybrid-sleep
, si vous voulez effectuer des actions différentes pour ces cas.
Pour plus d’informations, voir la page de manuel de systemd-sleep
.
InitV
On mettra un script dans /etc/pm/sleep.d/
.
Exemple de script :
#!/bin/sh
case "${1}" in
suspend|hibernate)
echo "Suspension ou hibernation"
;;
resume|thaw)
echo "Réveil ou dégel"
;;
esac
Antisèche
Linux General Cheat Sheets
Information système
Commande | Commentaire |
---|---|
uname -a | Afficher les informations systèmes de linux |
uname -r | Afficher la version du noyau |
uptime | Afficher le temps d'activité du système et affiche la charge |
hostname | Affiche le nom d'hôte de la machine |
hostname -I | Affiche l'adresse IP de l'hôte |
last reboot | Afficher l'historique des redémarrages |
date | Afficher la date et l'heure du système |
cal | Affiche le calendrier du mois |
w | Affiche qui est en ligne |
whoami | Affiche où nous sommes loggué en tant que qui |
Information matérielle
Commande | Commentaire |
---|---|
dmesg | Affiche les messages du noyau |
cat /proc/cpuinfo | Affiche les informations du CPU |
cat /proc/meminfo | Affiche les informations de la RAM |
free -h | Affiche la mémoire libre et utilisé (-h pour lisible par l'homme, -m for MB et -g pour GB) |
lspci -tv | Affiche les périphériques PCI |
lsusb -tv | Affiche les périphériques USB |
dmidecode | Affiche les information DMI/SMBIOS (informations systèmes) depuis le BIOS |
hdparm -i /dev/sda | Affiche les informations du disque /dev/sda |
hdparm -rT /dev/sda | Faire un test de vitesse de lecture sur le disque /dev/sda |
badblocks -s /dev/sda | Test le disque /dev/sda pour d'éventuels blocks défectueux |
ls - Lister le contenu d'un répertoire
Permet de lister le contenu d'un répertoire
Syntaxe :
ls <option> répertoire
Option | Commentaire |
---|---|
-a | Lister tout le répertoire (y compris fichier caché) |
-l | Afficher le répertoire sous forme de tableau, avec permission, ... |
-i | Affiche les inodes |
-h | Affiche la taille dans un format lisible par l'homme (Mo par exemple) |
-R | Liste également les sous-répertoires |
-s | Affiche la taille des répertoires |
pwd - Afficher le répertoire courant
Affiche le répertoire dans lequel on se situe.
Syntaxe :
pwd
mkdir - Créer un répertoire
Créer un répertoire.
mkdir -p /chemin/répertoire/à/créer
Option | Commentaire |
---|---|
-p | Créer les répertoires parents si ces derniers n'existent pas |
Exemple : Je souhaite créer un répertoire truc dans /home/user1/test1, mais le fichier test1 n'existe pas.
Syntaxe :
mkdir -p /home/user1/test1/truc
cd - Changer de répertoire
Permet de se déplacer dans l'arborescence
Syntaxe :
cd /répertoire/de/destination
cat - Afficher le contenu d'un fichier
Permet d'ouvrir un fichier et d'afficher son contenu.
Syntaxe :
cat <option> fichier
Option | Commentaire |
---|---|
-b | Numéroter toutes les lignes non vides |
-n | Numéroter toutes les lignes |
df - Afficher la taille d'un répertoire
Permet d'afficher la taille d'un répertoire.
Syntaxe :
df <option> répertoire
Option | Commentaire |
---|---|
-h | Permet d'obtenir un résultat plus lisible pour un humain (ex Mo, Ko,...) |
-i | Affiche les inodes |
-k | Affiche le résultat en kilobytes |
-m | Affiche le résultat en megabytes |
-d n. | Affiche la taille des sous-répertoires jusqu'au nème |
mv - Déplacer un fichier ou dossier
Permet de déplacer un fichier ou un répertoire.
Syntaxe :
mv <option> /chemin/source /chemin/destination
Option | Commentaire |
---|---|
-f | Forcer le déplacement |
-i | Demander la confirmation de l'utilisateur |
rm - Supprimer un fichier ou dossier
Permet de supprimer un fichier ou un dossier
Syntaxe :
rm <option> /chemin/truc/a/supprimer
Option | Commentaire |
---|---|
-d | Efface un répertoire |
-f | Force la suppression |
-i | Demande confirmation à l'utilsateur (Inutile avec -f ) |
-r | Récursif |
groups - Afficher les groupes d'appartenance d'un utilisateur
Permet d'afficher dans quels groupes se trouve l'utilisateur
Syntaxe :
groups utilisateur
passwd - Changer le mot de passe
**Permet de changer le mot de passe d'un utilisateur
Syntaxe :
passwd <option> utilisateur
Option | Commande |
---|---|
-d | Supprimer le mot de passe |
-e | Faire expirer le mot de passe |
-i | Rendre un compte inactif |
-l | Verouille le mot de passe et empêche sa modification par l'utilisateur |
-S | Affiche le status du compte |
-u | Déverouille un mot de passe |
Faire un rechercher remplacer récursif :
Remplacer "texte1" par "texte2".
find . -name "*" -exec sed -i 's/texte1/texte2/g' {} \;
Rechercher une chaine présente dans des fichiers d'un dossier de manière récursive :
grep -rnw /PATH/TO/THE/FOLDER -e 'MA-CHAÎNE'
Répéter une commande en boucle :
watch macommande [options]
Couper le début d'une réponse
cat /mon/fichier | cut -c 19-
--> On retire les 18 premiers chars
Envoyer une commande à un autre utilisateur :
su - UTILISATEUR -c "MA COMMANDE"
Mettre à jour à la fois les paquets mais aussi la version de la distribution :
apt-get full-upgrade
Lister les IP D'un CIDR :
nmap -sL -n 10.10.64.0/27 | awk '/Nmap scan report/{print $NF}'
# Résultat :
10.10.64.0
10.10.64.1
10.10.64.2
10.10.64.3
10.10.64.4
10.10.64.5
10.10.64.6
10.10.64.7
10.10.64.8
10.10.64.9
10.10.64.10
10.10.64.11
10.10.64.12
10.10.64.13
10.10.64.14
10.10.64.15
10.10.64.16
10.10.64.17
10.10.64.18
10.10.64.19
10.10.64.20
10.10.64.21
10.10.64.22
10.10.64.23
10.10.64.24
10.10.64.25
10.10.64.26
10.10.64.27
10.10.64.28
10.10.64.29
10.10.64.30
10.10.64.31
Supprimer les dossier datant de plus de quinze jours :
DIR=/backup
find $DIR -type d -ctime +15 -exec rm -rf {};
Savoir le load du proc :
cat /proc/loadavg
Installer un environnement graphique :
apt-get install task-lxde-desktop
Ajouter un utilisateur à la liste des Sudoers :
Avec l'utilisateur Root exécutez la commande ci-dessous :
sudo usermod -a -G sudo <username>
L'utilisateur peut désormais faire la commande sudo !
Mettre une adresse IP fixe sur Linux :
On modifie le fichier situé dans /etc/network/interfaces :
nano /etc/network/interfaces
auto eth1
iface eth1 inet static
address 192.168.0.42
network 192.168.0.0
netmask 255.255.255.0
gateway 192.168.0.1
Puis on redémarre le service :
service networking restart
L'IP est désormais fixe !
Grep toutes les IPS d'un fichier
cat mon_super_fichier | grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
Savoir son adresse IP d'une manière lisible :
ip -br a
Savoir la taille totale de RAM non-utilisée :
free
Détails de la RAM :
sudo dmidecode -t 17
Savoir le nombre de processeurs :
nproc
Détails du CPU :
lscpu
Changer le fuseau d'horaire :
dpkg-reconfigure tzdata
Changer le fuseau horaire sans intéraction :
ln -fs /usr/share/zoneinfo/Europe/Paris /etc/localtime
dpkg-reconfigure --frontend noninteractive tzdata
Générer une chaine aléatoire :
< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo;
Filtrer le résultat d'une commande : Récupérer la X ième collone
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b47869c06afa local_ansible:latest "tail -F anything" 4 days ago Up 4 days XXXXXXXXXX.1.xkdfozjzesx3i9tiiwi7v4mx2
98d251874810 local_ansible:latest "tail -F anything" 4 days ago Up 4 days XXXXXXXXXX.1.30q690xvddk600wt35tuii2qr
e59db4bf005e local_ansible:latest "tail -F anything" 4 days ago Up 4 days XXXXXXXXXX.1.wf6mpbnyl3fmvvl1dm6rvgx7q
d5bb4b393058 local_ansible:latest "tail -F anything" 4 days ago Up 4 days XXXXXXXXXX.1.ug7xuyrdx61jz2hyir01i85dl
c7e24c57b1c3 local_ansible:latest "tail -F anything" 4 days ago Up 4 days XXXXXXXXXX.1.xgn2wopz174n4vsq8sfu1hbuz
docker ps | awk '{print $1}'
CONTAINER
b47869c06afa
98d251874810
e59db4bf005e
d5bb4b393058
c7e24c57b1c3
$1 représente la première collone ; pour la suivante ce sera $2 etc.
Lister les processus :
ps aux
KILL un processus :
sudo kill -9 ID
Faire un SSH via un proxy :
# Forward le trafic sur le port 8080 de mon ordinateur vers le port 80 de l'hote distant
ssh -L 8080:localhost:80 remote_host
Afficher les logs du boot précédent et ainsi voir à la toute fin, les logs de la dernière extinction du système.
journalctl -b -1
Actualiser le /etc/fstab :
sudo mount -a
Couper un affichage à partir d'un caractère :
cat monfichier.log | cut -d "|" -f 2
Journalclt purge :
- Per days
journalctl --vacuum-time=2d
- Per size
journalctl --vacuum-size=500M
--> Après purge des fichiers de logs, pour libérer l'espace (uniquement si on supprime rsyslog ou daemon.log ):
systemctl restart rsyslog
Taille dossier d'un niveau uniquement :
du -h --max-depth=1
Supprimer un hostname des know_host ssh :
ssh-keygen -R hostname
Lister les services actuellement fonctionnels :
sudo systemctl --type=service --state=running | awk '{print $1}'
UNIT
chrony.service
containerd.service
cron.service
dbus.service
docker.service
getty@tty1.service
google-cloud-ops-agent-diagnostics.service
google-cloud-ops-agent-fluent-bit.service
google-cloud-ops-agent-opentelemetry-collector.service
google-guest-agent.service
google-osconfig-agent.service
haveged.service
mariadb.service
nmbd.service
polkit.service
rsyslog.service
serial-getty@ttyS0.service
smbd.service
ssh.service
systemd-journald.service
systemd-logind.service
Certificats :
Etablir une connexion ssl pour tester les certificats :
openssl s_client -connect host:port -CAfile chemin_vers_certificat_public_de_la_ca.pem
Debug Deep :
Afficher les logs du noyeau linux :
dmesg
Kernel :
--> On va lister les vieux kernels présents sur le system. Puis on va les supprimer pour faire de l'espace dans /boot.
Kernel actuellement en cours d'execution :
uname -r
X.X.X-26-amd64
J'utilise donc le kernel : X.X.X-26-amd64
Liste des kernels présents dans le système (exépté le kernel actuellement utilisé) :
sudo dpkg --list 'linux-image*'|awk '{ if ($1=="ii") print $2}'|grep -v `uname -r`
linux-image-X.X.X-18-amd64
linux-image-X.X.X-19-amd64
linux-image-X.X.X-20-amd64
linux-image-X.X.X-21-amd64
linux-image-X.X.X-22-amd64
linux-image-X.X.X-23-amd64
Ici, nous allons pouvoir supprimer les versions X.X-18-amd64 à X.X-23-amd64 compris. Il faut toujours garder deux versions de kernels précédentes.
Pour supprimer les anciens kernels, je vais réaliser les commandes suivantes :
sudo apt purge linux-image-X.X.X-18-amd64
sudo apt purge linux-image-X.X.X-19-amd64
sudo apt purge linux-image-X.X.X-20-amd64
sudo apt purge linux-image-X.X.X-21-amd64
sudo apt purge linux-image-X.X.X-22-amd64
sudo apt purge linux-image-X.X.X-23-amd64
sudo apt purge linux-image-X.X.X-24-amd64
Puis, je vais réaliser une purge des packets qui sont désormais obsolètes :
sudo apt autoremove
Enfin, on met à jour la liste des noyeaux grub :
sudo update-grub
Conclusion :
Mon /boot est passé de 427 Mo utilisés à 168 Mo.
TCPDUMP :
ARP:
sudo tcpdump -nni any vrrp
--> Sur toutes les interfaces.
Récupérer un fichier perdu, supprimé :
Foremost permet de récupérer les fichiers supprimés. Cette récupération n'est pas parfaite car les données perdues peuvent être écrasés par une réécriture :
foremost -t all -i /dev/sda1
Gestion du disque linux (LVM) :
Afficher les volumes physiques :
pvdisplay
Afficher le groupe :
vgdisplay
Afficher les volumes logiques :
lvdisplay
Augmenter la taille d'un volume :
# Taille définie :
lvextend -L '+9G' /dev/vg0/lib
# Taille relative :
lvextend -l '+100%FREE' /dev/vg0/lib
Affecter la nouvelle taille :
xfs_growfs /var/lib
Supprimer un volume récalsitrant :
# Eteindre le volume.
lvchange -an -v /dev/vg0/lib
# Afficher les process qui utilisent le volume
lsof | grep /var/lib
# Si besoin de debug : Afficher les processus cachés qui utilisent le volume
grep -l /var/lib /proc/*/mountinfo
# --> Cette commande nous retounre des PID. Faire : ps -aux | grep <PID_ID> ; pour connaitre les service qui continuent d'utiliser le volume.
# Maintenant que nous avons éteinds tous les services qui posent problème, nous pouvons supprimer le volume.
lvremove -f vg0/lib
lvcreate -n lib -l 100%FREE vg0
mkfs.xfs /dev/vg0/lib
Procédure pour augmenter la SWAP :
free -h
swapoff /dev/vg0/swap
lvextend -L '+6G' /dev/vg0/swap
mkswap /dev/vg0/swap
swapon /dev/vg0/swap
free -h
Procédure pour supprimer un volume "100%FREE" qui nous empéche forcément de créer un volume /home de 20 Go :
# Démonter /var/lib ; sauvegarder ; préparer au redémarrage
cp -pR /home /root/
cp -pR /var/lib /root/
umount /var/lib
cp -pR /root/lib/* /var/lib/
############################
############################
COMMENER LE /ETC/FSTAB (ligne lib) :
#/dev/vg0/lib /var/lib xfs rw,noatime,logbufs=8,logbsize=256k,inode64 1 2
############################
############################
Reboot
############################
############################
# Supprimer le volume
lvremove -f vg0/lib
##############################
# Créer les volumes qu'il faut
lvcreate -n home -L "20G" vg0
mkfs.xfs /dev/vg0/home
#...
lvcreate -n lib -l 100%FREE vg0
mkfs.xfs /dev/vg0/lib
##############################
# supprimer les données résiduelles avant remontage
rm -r /var/lib/*
rm -r /home/*
############################
DECOMMENTER LE /ETC/FSTAB !
+
AJOUTER LES MONTAGES neccessaires :
/dev/vg0/lib /var/lib xfs rw,noatime,logbufs=8,logbsize=256k,inode64 1 2
/dev/vg0/home /home xfs rw,noatime,logbufs=8,logbsize=256k,inode64 1 2
############################
mount -a
# VERIFIER
mount | grep /home
mount | grep /var/lib
# Réimporter les datas dans les volumes
cp -pR /root/lib/* /var/lib/
cp -pR /root/home/* /home/
# Reboot
reboot
# vérification
ls -lisa /var/lib
ls -lisa /home
# suppression des données dupliquées
rm /root/home -r
rm /root/lib -r
SSHD - Only sftp
Prérequits :
- home de l'user toto : /opt/toto
Configuration /etc/ssh/sshd_config :
Match User toto
ChrootDirectory /opt/toto
X11Forwarding no
AllowTcpForwarding no
AllowAgentForwarding no
PasswordAuthentication no
ForceCommand internal-sftp -d /%u
Commandes pour rendre la chose fonctionelle :
mkdir /opt/toto/data
chown root:root /opt/toto
chown -R toto:toot /opt/toto/*
systemctl restard sshd
Test :
sftp -i id_rsa toto@SERVEUR <<< 'put fichier.txt /data/'
# Test de perms
ssh -i id_rsa toto@SERVEUR
This service allows sftp connections only.
Connection to SERVEUR closed.
Gérer les ACL
Récupérer les informations d'un fichier :
stat launch_kee.sh
====================================================
Fichier : launch_kee.sh
Taille : 82 Blocs : 8 Blocs d'E/S : 4096 fichier
Périphérique : 254/1 Inœud : 4718858 Liens : 1
Accès : (0755/-rwxr-xr-x) UID : ( 0/ root) GID : ( 0/ root)
Accès : 2024-06-10 11:24:44.881570498 +0200
Modif. : 2024-06-10 11:24:33.865592246 +0200
Changt : 2024-06-10 11:24:41.201577761 +0200
Créé : 2024-06-10 11:24:29.949599980 +0200
Récupérer les ACL d'un fichier :
getfacl launch_kee.sh
=========================
# file: launch_kee.sh
# owner: root
# group: root
user::rwx
group::r-x
other::r-x
Ajouter les perms à un utilisateur :
sudo setfacl -m user:nehemie:rw- launch_kee.sh
Constat :
getfacl launch_kee.sh
==============================
# file: launch_kee.sh
# owner: root
# group: root
user::rwx
user:nehemie:rw-
group::r-x
mask::rwx
other::r-x
Supprimer les perms à un utilisateur :
sudo setfacl -Rm user:nehemie:--- launch_kee.sh
- - R : ACL Récurcif
Constat :
getfacl launch_kee.sh
====================================
# file: launch_kee.sh
# owner: root
# group: root
user::rwx
user:nehemie:---
group::r-x
mask::r-x
other::r-x
Réduire la valeur des ports privilégiés:
echo 80 | sudo tee /proc/sys/net/ipv4/ip_unprivileged_port_start
Lister les démons qui utilisent le dossier :
sudo lsof /var/lib/
Convertir des timestamps milisencondes en date humaines :
# dans mon fichier tmp j'ai des lignes de timestamp en format ms
for line in $(cat /var/lib/db_backup/tmp); do date -ud @$(($line / 1000)); done;
vmware-toolbox-cmd timesync enable
Installer un packet dans un conteneur debian bizzare :
apk add curl
apk add jq
Firewall
Installation d'un pare-feu basique avec iptables
Installation de iptables
apt install iptables
Création du process et des règles
Je créer un fichier firewall qui va être exécuter au démarrage et gérer par systemctl.
Son but et d'indiquer quoi faire quand on start le process et quand on le stop et la gestion du status.
nano /etc/init.d/firewall
#! /bin/sh
### BEGIN INIT INFO
# Provides: Firewall
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Firewall
# Description: Firewall
### END INIT INFO
IPT=/sbin/iptables
IP6T=/sbin/ip6tables
do_start() {
# Efface toutes les regles en cours. -F toutes. -X utilisateurs
$IPT -t filter -F
$IPT -t filter -X
$IPT -t nat -F
$IPT -t nat -X
$IPT -t mangle -F
$IPT -t mangle -X
$IP6T -t filter -F
$IP6T -t filter -X
$IP6T -t mangle -F
$IP6T -t mangle -X
# strategie (-P) par defaut : bloc tout l'entrant le forward et autorise le sortant
$IPT -t filter -P INPUT DROP
$IPT -t filter -P FORWARD DROP
$IPT -t filter -P OUTPUT ACCEPT
$IP6T -t filter -P INPUT DROP
$IP6T -t filter -P FORWARD DROP
$IP6T -t filter -P OUTPUT ACCEPT
# Loopback
$IPT -t filter -A INPUT -i lo -j ACCEPT
$IPT -t filter -A OUTPUT -o lo -j ACCEPT
$IP6T -t filter -A INPUT -i lo -j ACCEPT
$IP6T -t filter -A OUTPUT -o lo -j ACCEPT
# Permettre a une connexion ouverte de recevoir du trafic en entree
$IPT -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IP6T -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
echo "firewall started [OK]"
}
# fonction qui arrete le firewall
do_stop() {
# Efface toutes les regles
$IPT -t filter -F
$IPT -t filter -X
$IPT -t nat -F
$IPT -t nat -X
$IPT -t mangle -F
$IPT -t mangle -X
$IP6T -t filter -F
$IP6T -t filter -X
$IP6T -t mangle -F
$IP6T -t mangle -X
# remet la strategie
$IPT -t filter -P INPUT ACCEPT
$IPT -t filter -P OUTPUT ACCEPT
$IPT -t filter -P FORWARD ACCEPT
$IP6T -t filter -P INPUT ACCEPT
$IP6T -t filter -P OUTPUT ACCEPT
$IP6T -t filter -P FORWARD ACCEPT
#
echo "firewall stopped [OK]"
}
# fonction status firewall
do_status() {
# affiche les regles en cours
clear
echo Status IPV4
echo -----------------------------------------------
$IPT -L -n -v
echo
echo -----------------------------------------------
echo
echo status IPV6
echo -----------------------------------------------
$IP6T -L -n -v
echo
}
case "$1" in
start)
do_start
exit 0
;;
stop)
do_stop
exit 0
;;
restart)
do_stop
do_start
exit 0
;;
status)
do_status
exit 0
;;
*)
echo "Usage: /etc/init.d/firewall {start|stop|restart|status}"
exit 1
;;
esac
Nous avons ici la configuration la plus bloquante (trafic sortant uniquement): Uniquement le trafic local et les connexion établie vers l'extérieur en IPv4 et IPv6.
Pour ajouter des autorisation, par exemple l'ICMP (ping), dans do_start()
ajouter:
# ICMP
$IPT -t filter -A INPUT -p icmp -j ACCEPT
$IP6T -t filter -A INPUT -p ipv6-icmp -j ACCEPT
Votre do_start()
ressemble à ça:
do_start() {
# Efface toutes les regles en cours. -F toutes. -X utilisateurs
$IPT -t filter -F
$IPT -t filter -X
$IPT -t nat -F
$IPT -t nat -X
$IPT -t mangle -F
$IPT -t mangle -X
$IP6T -t filter -F
$IP6T -t filter -X
$IP6T -t mangle -F
$IP6T -t mangle -X
# strategie (-P) par defaut : bloc tout l'entrant le forward et autorise le sortant
$IPT -t filter -P INPUT DROP
$IPT -t filter -P FORWARD DROP
$IPT -t filter -P OUTPUT ACCEPT
$IP6T -t filter -P INPUT DROP
$IP6T -t filter -P FORWARD DROP
$IP6T -t filter -P OUTPUT ACCEPT
# Loopback
$IPT -t filter -A INPUT -i lo -j ACCEPT
$IPT -t filter -A OUTPUT -o lo -j ACCEPT
$IP6T -t filter -A INPUT -i lo -j ACCEPT
$IP6T -t filter -A OUTPUT -o lo -j ACCEPT
# Permettre a une connexion ouverte de recevoir du trafic en entree
$IPT -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IP6T -t filter -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# ICMP
$IPT -t filter -A INPUT -p icmp -j ACCEPT
$IP6T -t filter -A INPUT -p ipv6-icmp -j ACCEPT
echo "firewall started [OK]"
}
Voici une liste de règles souvent utile
# ICMP
$IPT -t filter -A INPUT -p icmp -j ACCEPT
$IP6T -t filter -A INPUT -p ipv6-icmp -j ACCEPT
# DNS:53
$IPT -t filter -A INPUT -p tcp --dport 53 -j ACCEPT
$IPT -t filter -A INPUT -p udp --dport 53 -j ACCEPT
$IP6T -t filter -A INPUT -p tcp --dport 53 -j ACCEPT
$IP6T -t filter -A INPUT -p udp --dport 53 -j ACCEPT
#FTP:20+21 - FTP pasv: 10 090 - 10 100
$IPT -t filter -A INPUT -p tcp --dport 20 -j ACCEPT
$IP6T -t filter -A INPUT -p tcp --dport 20 -j ACCEPT
$IPT -t filter -A INPUT -p tcp --dport 21 -j ACCEPT
$IP6T -t filter -A INPUT -p tcp --dport 21 -j ACCEPT
$IPT -t filter -A INPUT -p tcp --dport 10090:10100 -j ACCEPT
$IP6T -t filter -A INPUT -p tcp --dport 10090:10100 -j ACCEPT
# SSH:22
# ATTENTION, indiques bien ton port personnalisé si tu l'as changé
$IPT -t filter -A INPUT -p tcp --dport 22 -j ACCEPT
$IP6T -t filter -A INPUT -p tcp --dport 22 -j ACCEPT
# HTTP:80 (Serveur Web)
$IPT -t filter -A INPUT -p tcp --dport 80 -j ACCEPT
$IP6T -t filter -A INPUT -p tcp --dport 80 -j ACCEPT
# HTTPS:443 (Serveur Web)
$IPT -t filter -A INPUT -p tcp --dport 443 -j ACCEPT
$IP6T -t filter -A INPUT -p tcp --dport 443 -j ACCEPT
# SNMP:161 (Monitoring)
$IPT -t filter -A INPUT -p udp --dport 161 -j ACCEPT
$IP6T -t filter -A INPUT -p udp --dport 161 -j ACCEPT
# SMTP:25 (Mail)
$IPT -t filter -A INPUT -p tcp --dport 25 -j ACCEPT
$IP6T -t filter -A INPUT -p tcp --dport 25 -j ACCEPT
# POP3:110 (Mail)
$IPT -t filter -A INPUT -p tcp --dport 110 -j ACCEPT
$IP6T -t filter -A INPUT -p tcp --dport 110 -j ACCEPT
# IMAP:143 (Mail)
$IPT -t filter -A INPUT -p tcp --dport 143 -j ACCEPT
$IP6T -t filter -A INPUT -p tcp --dport 143 -j ACCEPT
Il faut maintenant rendre exécutable de fichier
chmod +x /etc/init.d/firewall
Les prochaines étapes vont rendre actif le pare-feu. Si vous êtes en SSH et que une règle n'autorise pas le SSH vous risquer de vous auto bloqué a la prochaine connexion. Assurez-vous d'avoir un accès directe à la machine pour gérer le cas ou vous seriez dans l'incapacité de vous reconnecter.
Premier démarrage du pare-feu
/etc/init.d/firewall start
Gestion par systemctl
update-rc.d firewall defaults
systemctl enable firewall
systemctl start firewall
systemctl status firewall
Cela devrais vous indiquer quelque chose du genre:
● firewall.service - LSB: Firewall
Loaded: loaded (/etc/init.d/firewall; generated)
Active: active (exited) since *** ****-**-** **:**:** ****; * ago
Docs: man:systemd-sysv-generator(8)
Process: ***** ExecStart=/etc/init.d/firewall start (code=exited, status=0/SUCCESS)
***. ** **:**:** monitor systemd[1]: Starting LSB: Firewall...
***. ** **:**:** monitor firewall[30462]: firewall started [OK]
***. ** **:**:** monitor systemd[1]: Started LSB: Firewall.
Firewalld : un firewall simple à utiliser
Firewalld est un pare-feu que je trouve très agréable à utiliser, où on peut « cacher » la complexité de certains éléments de configuration derrière des noms simples à utiliser.
Par exemple, je peux avoir un service qui n’a pas spécialement de port dédié, donc qui n’est pas proposé par firewall. Mettons un wireguard qui écoute sur le port 9879. Plutôt que d’utiliser 9879/udp
dans ma configuration, je vais créer un service wireguard
, et c’est ce service que j’autoriserai.
Ce sera bien plus parlant quand je relirai la configuration.
Liens :
- Documentation officielle : https://firewalld.org/documentation/
- https://www.linuxtricks.fr/wiki/firewalld-le-pare-feu-facile-sous-linux
- https://www.rootusers.com/how-to-use-firewalld-rich-rules-and-zones-for-filtering-and-nat/
- https://kb.vander.host/security/firewalld-cheat-sheet/
Principes
En très gros et en très résumé, on va avoir des zones, qui sont des ensembles d'adresses IP et la zone public
qui concerne toutes les IPs, sauf celles qui sont dans d’autres zones.
On va aussi avoir des services, qui décrivent... des services : port et protocole (ex: 5666
et tcp
pour nrpe).
On va aussi avoir des « rich rules » dans les zones, des exceptions aux règles appliquées dans la zone.
Toute la configuration est dans des fichiers XML très simples à lire, c'est très agréable. Tant qu'on ne surcharge pas la configuration par défaut, les fichiers sont dans /usr/lib/firewalld/
mais dès qu'on modifie un élément de configuration, celui-ci se retrouvera copié dans /etc/firewalld/
et modifié.
Test de configuration
Si on modifie de la configuration à la main (en écrivant dans /etc/firewalld
, on prendra soin de tester la configuration avec les commandes suivantes :
Si firewalld
est coupé :
firewall-offline-cmd --check-config
Si firewalld
est lancé :
firewall-cmd --check-config
Attention
Quand on installe firewalld, le firewall démarre de suite en n’autorisant en public que ssh
(et dhcpv6-client
).
Il est donc préférable de l’installer et de le couper directement après :
apt install firewalld &&
systemctl stop firewalld
On pourra créer la configuration tranquillement avec la commande firewall-offline-cmd
et lancer le service une fois la configuration terminée.
Changements permanents
Si on veut rendre un changement permanent (c-à-d qu'il soit écrit dans la config au lieu d'être juste appliqué jusqu'au redémarrage), il faut ajouter ça aux commandes :
--permanent
Par contre, avec --permanent
, il faut recharger la configuration pour appliquer les modifications (ou alors on applique une fois avec --permanent
et une fois sans) :
firewall-cmd --reload
À l’inverse, on peut créer des règles sans le --permanent
et ensuite écrire ces règles dans la configuration permanent avec la commande suivante :
firewall-cmd --runtime-to-permanent
NB : certaines commandes nécessitent forcément le --permanent
.
Bloquer une adresse IP
On peut soit ajouter les adresses aux zones drop
ou block
:
firewall-cmd --zone=drop --add-source 192.0.2.0/24
firewall-cmd --zone=drop --add-source 192.0.2.0/24 --permanent
Soit ajouter une rich-rule
(man firewalld.richlanguage
) à la zone public
:
firewall-cmd --zone public --add-rich-rule "rule family=ipv4 source address=192.0.2.0/24 reject"
firewall-cmd --zone public --add-rich-rule "rule family=ipv4 source address=192.0.2.0/24 reject" --permanent
Pour enlever un blocage :
firewall-cmd --zone drop --remove-source 51.159.0.0/16
firewall-cmd --zone drop --remove-source 51.159.0.0/16 --permanent
firewall-cmd --zone public --remove-rich-rule "rule family=ipv4 source address=51.159.0.0/16 reject"
firewall-cmd --zone public --remove-rich-rule "rule family=ipv4 source address=51.159.0.0/16 reject" --permanent
Pour voir les blocages par rich-rule
(la 1ère commande donne les blocages actuellement activés, l’autre ceux qui sont dans les fichiers de configuration. Il peut y avoir une différence… ou pas !) :
firewall-cmd --list-rich-rules
firewall-cmd --list-rich-rules --permanent
Pour bloquer un ipset (voir plus bas) :
firewall-cmd --zone=drop --add-source ipset:le_nom_de_l_ipset
firewall-cmd --zone=drop --add-source ipset:le_nom_de_l_ipset --permanent
Zones
Voir les zones disponibles :
firewall-cmd --get-zones
NB : la zone public
, par défaut, n'autorise que le SSH et dhcpv6-client. L'installation de firewalld sur une machine va donc couper l'accès aux services. Il faut donc stopper firewalld juste après son installation, regarder les ports utilisés sur la machine et modifier la zone public
soit en copiant /usr/lib/firewalld/zones/public.xml
dans /etc/firewalld/zones/
, soit en préparant une ligne de commande à lancer juste après le démarrage de firewalld.
NB : les zones peuvent avoir une target
, l'action à appliquer aux connexions qui correspondent à la zone. Voir la doc.
NB : Une adresse IP ne peut se trouver que dans une seule zone mais on peut ajouter dans une zone un réseau qui contient une adresse IP déjà présente dans une autre zone. Cependant, le comportement peut ne pas être celui attendu. Il vaut mieux ajouter une rich-rule
à la zone pour faire une exception aux règles de la zone.
Voir la zone par défaut (celle sur laquelle s'appliqueront les modifications si on ne spécifie pas la zone) :
firewall-cmd --get-default-zone
Définir la zone par défaut :
firewall-cmd --set-default-zone work
Voir la configuration de la zone :
firewall-cmd --info-zone lazone
Voir la configuration de toutes les zones :
firewall-cmd --list-all-zones
Créer une zone :
firewall-cmd --permanent --new-zone mazone
firewall-cmd --reload
Supprimer une zone :
firewall-cmd --permanent --delete-zone mazone
firewall-cmd --reload
Chaque interface du système peut être attribuée à une zone. Pour ajouter l’interface ens192 à la zone work en l’enlevant de sa précédente zone :
firewall-cmd --change-interface ens192 --zone work [--permanent]
Pour retirer l’interface ens192 de la zone work :
firewall-cmd --remove-interface ens192 --zone work [--permanent]
Pour ajouter l’interface ens192 à la zone work (interface qui ne soit pas être affectée à une zone) :
firewall-cmd --add-interface ens192 --zone work [--permanent]
Ajouter des adresses IP ou un réseau à une zone :
firewall-cmd --zone work --add-source 192.0.2.0/24 [--permanent]
firewall-cmd --zone work --add-source 192.0.2.200 [--permanent]
Retirer des adresses IP ou un réseau d'une zone :
firewall-cmd --zone work --remove-source 192.0.2.0/24 [--permanent]
firewall-cmd --zone work --remove-source 192.0.2.200 [--permanent]
Pour basculer une adresse IP ou un réseau d'une zone à une autre :
firewall-cmd --zone l_autre_zone --change-source 192.0.2.0/24 [--permanent]
firewall-cmd --zone l_autre_zone --change-source 192.0.2.200 [--permanent]
Si l'adresse IP / le réseau était dans une autre zone, ça équivaut à un --remove-source
suivi d'un --add-source
, si ce n'était pas le cas, ça fait juste comme un --add-source
.
Voir la target
d'une zone :
firewall-cmd --permanent --get-target --zone drop
Définir la target
d'une zone :
firewall-cmd --permanent --set-target [default|ACCEPT|DROP|REJECT] --zone drop
Pour voir dans quelle zone est une adresse IP :
firewall-cmd --get-zone-of-source=<adresse IP ou réseau en notation CIDR ou adresse MAC ou ipset>
Si ça répond no zone
, c’est que l’IP ou le réseau n’est pas explicitement associé à une zone.
Attention : si un réseau est enregistré dans une zone, lancer la commande sur une IP du réseau ne renverra pas la zone en question !
Services
Voir les services existants :
firewall-cmd --get-services
Voir le détail d'un service :
firewall-cmd --info-service ssh
Créer un nouveau service :
firewall-cmd --permanent --new-service influxdb
firewall-cmd --permanent --service influxdb --set-description InfluxDB
firewall-cmd --permanent --service influxdb --add-port 8086/tcp
Ajouter un service à une zone :
firewall-cmd --zone public --add-service nrpe [--permanent]
Retirer un service d'une zone :
firewall-cmd --zone public --remove-service nrpe [--permanent]
Voir les services d'une zone :
firewall-cmd --list-services --zone work
Si on ne souhaite pas créer de service mais autoriser un certain port et protocole, on peut les ajouter directement à la zone :
firewall-cmd --zone work --add-port 1234/udp [--permanent]
Et pour les supprimer :
firewall-cmd --zone work --remove-port 1234/udp [--permanent]
Pour voir les ports/protocoles d'une zone (ça ne listera pas les services !) :
firewall-cmd --list-ports --zone work
IPSet : groupes d'adresses
Cas d'usage : on voit plein de spammeurs venant du VPN d'Avast. On fait un whois
, on voit le numéro d'AS des serveurs d'Avast, on va sur https://asnlookup.com/ pour choper leur liste d'adresses IP et on en fait un ipset pour les bloquer.
NB : un ipset ne peut contenir qu'un type d'adresses, IPv4 ou IPv6, pas les deux.
NB : Fail2ban, lorsqu'il utilise firewalld, utilise des ipset, mais à un niveau un peu plus bas (nftables). Ces ipset ne sont pas vus par firewalld. On peut voir tous les ipset, même bas niveau avec la commande ipset list -name
(ipset list le_nom_de_l_ipset
pour voir les adresses et le détail de l'ipset).
Un ipset sert à regrouper des adresses pour leur appliquer des règles facilement.
Voir les types d'ipset disponibles :
firewall-cmd --get-ipset-types
Voir les ipsets existants :
firewall-cmd --permanent --get-ipsets
Créer un ipset :
firewall-cmd --permanent --type hash:net --new-ipset test
Pour un ipset IPv6 :
firewall-cmd --permanent --type hash:net --option "family=inet6" --new-ipset test-v6
Supprimer un ipset :
firewall-cmd --permanent --delete-ipset test
Voir les infos d'un ipset :
firewall-cmd --info-ipset test [--permanent]
Ajouter une adresse IP à un ipset :
firewall-cmd --ipset test --add-entry 192.0.2.1 [--permanent]
Supprimer une adresse IP d'un ipset :
firewall-cmd --ipset test --remove-entry 192.0.2.1 [--permanent]
Voir les adresses IP d'un ipset :
firewall-cmd --ipset test --get-entries [--permanent]
Ajouter un paquet d'IP d'après un fichier :
cat > iplist.txt <<EOL
192.0.2.2
192.0.2.3
198.51.100.0/24
203.0.113.254
EOL
firewall-cmd --ipset test --add-entries-from-file iplist.txt [--permanent]
Supprimer un paquet d'IP d'après un fichier :
firewall-cmd --ipset test --remove-entries-from-file iplist.txt [--permanent]
Ajouter un ipset dans une zone :
firewall-cmd --zone drop --add-source ipset:test [--permanent]
Supprimer un ipset d'une zone :
firewall-cmd --zone drop --remove-source ipset:test [--permanent]
Créer des exceptions avec des règles riches
Cas classique : on bloque un pays avec des ipset et quelqu'un a besoin d'accéder à nos services depuis là-bas.
L'ipset est dans la zone drop
. On va ajouter une rich-rule
pour faire une exception :
firewall-cmd --zone drop --add-rich-rule='rule family="ipv4" source address="192.0.2.29" port port="443" protocol="tcp" accept'
firewall-cmd --zone drop --add-rich-rule='rule family="ipv4" source address="192.0.2.29" port port="80" protocol="tcp" accept'
firewall-cmd --zone drop --permanent --add-rich-rule='rule family="ipv4" source address="192.0.2.29" port port="443" protocol="tcp" accept'
firewall-cmd --zone drop --permanent --add-rich-rule='rule family="ipv4" source address="192.0.2.29" port port="80" protocol="tcp" accept'
Pour supprimer l'exception :
firewall-cmd --zone drop --remove-rich-rule 'rule family="ipv4" source address="192.0.2.29" port port="80" protocol="tcp" accept'
firewall-cmd --zone drop --remove-rich-rule 'rule family="ipv4" source address="192.0.2.29" port port="443" protocol="tcp" accept'
firewall-cmd --zone drop --permanent --remove-rich-rule 'rule family="ipv4" source address="192.0.2.29" port port="80" protocol="tcp" accept'
firewall-cmd --zone drop --permanent --remove-rich-rule 'rule family="ipv4" source address="192.0.2.29" port port="443" protocol="tcp" accept'
On peut utiliser des services dans les règles riches :
firewall-cmd --zone drop --add-rich-rule='rule family="ipv4" source address="192.0.2.29" service name=https accept'
On peut utiliser des ipset dans les règles riches :
firewall-cmd --zone drop --add-rich-rule='rule family="ipv4" source ipset="test-v6" service name=https accept'
NB : ajouter l'adresse IP en source dans la zone public
ne servirait strictement à rien.
Blocage geoIP
On peut se baser sur le script de https://github.com/simonbouchard/geoip-blocking-w-firewalld (le fork de Framasoft).
On modifie les pays à bloquer dans /etc/default/firewalld-geoip
et on lance le script. À mettre dans un cron pour mettre à jour les adresses.
Faire du NAT
Voir la partie Network Address Translation (NAT)
de https://www.rootusers.com/how-to-use-firewalld-rich-rules-and-zones-for-filtering-and-nat/.
UFW - Basic Setup
1. Installation and Configuration
First, install UFW
sudo apt -y install ufw
Before enabling the setup, we will set up some basic rules. I will deny all outgoing, as well as all incoming traffic as a default. After that we have to make sure, that we enable all the necessary protocols to communicate, otherwise, basic services, like DNS resolution no longer work. UFW is basically just a script, that generates IP-Table entries for you.
Disable all outgoing and incoming traffic:
sudo ufw default deny incoming
sudo ufw default deny outgoing
Now enable logging
sudo ufw logging FULL
Next, you have to decide, which outgoing traffic to allow. Here is an overview of some services, and which default ports and protocols they use. This overview is only for OUTGOING traffic.
Service | Port | Protocol |
SMTP | 25 | tcp/udp |
SMTPs | 465 | tcp/udp |
DNS | 53 | tcp/udp |
HTTP | 80 | tcp (UDP usually not needed) |
HTTPS | 443 | tcp (UDP usually not needed) |
You can enable outgoing traffic like this:
sudo ufw allow out PORT/Protocol
So to enable DNS, run
sudo ufw allow out 53
To enable ICMP, you'll have to edit the IP-Tables yourself, since UFW doesn't offer you this feature. Just add the following lines to /etc/ufw/before.rules
and /etc/ufw/before6.rules
-A ufw-before-output -p icmp -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
-A ufw-before-output -p icmp -m state --state ESTABLISHED,RELATED -j ACCEPT
After that, you can enable incoming traffic. On a freshly installed system, that's usually just SSH, but if you are running, e.g. a webserver, you should also enable traffic on Ports 80 and 443. UFW comes with an App-List, which makes adding UFW rules for default ports easier. You can view the list by running
sudo ufw app list
Allow incoming traffic like this:
sudo ufw allow in Port/Protocol
If you want to allow a range of ports, you can use PORTX:PORTY
. If you want only a certain host to be able to connect to your client via some Port, you can use the following rule:
sudo ufw allow in from 10.10.10.10 to any port 22
You can also use netmasks in CIDR format
You can do much more. I recommend you to read through this manpage.
Lastly, to enable UFW, run
sudo ufw enable
2. Tips and Tricks
To quickly delete all rules for a port, you can use the following script:
#!/bin/bash
for NUM in $(ufw status numbered | grep "$1" | awk -F"[][]" '{print $2}' | tr --delete "[:blank:]" | sort -rn); do
ufw --force delete "$NUM"
done
This will instantly delete all rules for the specified ports, without any prompts.
You can simply delete all rules for e.g. Port 80, by running.
sudo ./your-script-name.sh 80
UFW - Block entire countries by IPs
If you don't want one explicit or even multiple countries, to connect to your server, you can block all their requests, by using UFW. This will, however, make your UFW status output extremely long, as well as taking some time to set up.
Doing this, is, of course, no guarantee, because it only blocks IPv4 and often enough, attackers mask/spoof their IP anyway. Moreover, this is quite a drastic step to take. You should rather control access on a different level, e.g. using a WAF.
First, you need to download a list of all the IPv4 Subnets, a country has assigned. You can download said list here and make sure to choose CIDR as output format. After that, simply run the following command (This may take a while)
cat yourList.txt | awk '/^[^#]/ { print $1 }' | sudo xargs -I {} ufw deny from {} to any
To remove all the rules, run
cat yourList.txt | awk '/^[^#]/ { print $1 }' | sudo xargs -I {} ufw delete deny from {}
Auto Install with scripts
Auto Install/Update Discord
Just run this script
#!/bin/bash
# Vérifiez si l'utilisateur a les droits administateurs
if [ "$(id -u)" != "0" ]; then
echo "Ce script doit être exécuté en tant qu'administrateur" 1>&2
exit 1
fi
# Vérifier si Discord est déjà installé
if dpkg -l | grep -q discord; then
echo "Discord est déjà installé sur votre système."
# Vérifier s'il y a une mise à jour disponible
current_version=$(dpkg -s discord | grep '^Version' | awk '{print $2}')
latest_version=$(curl -s "https://discord.com/api/download?platform=linux&format=deb" | grep -oP '(\d+\.)+\d+' | tail -1)
if [[ "$current_version" == "$latest_version" ]]; then
echo "Vous avez déjà la dernière version de Discord."
else
echo "Une nouvelle version de Discord est disponible."
# Mettre à jour les paquets du système
apt update
apt upgrade -y
# Télécharger la dernière version de Discord depuis leur site Web
wget -O /tmp/discord.deb "https://discord.com/api/download?platform=linux&format=deb"
# Installer la nouvelle version de Discord
dpkg -i /tmp/discord.deb
# Effacer le fichier .deb téléchargé
rm /tmp/discord.deb
echo "Discord a été mis à jour avec succès !"
fi
else
# Installer Discord
echo "Discord n'est pas installé sur votre système. Installation en cours..."
# Mettre à jour les paquets du système
apt update
apt upgrade -y
# Télécharger la dernière version de Discord depuis leur site Web
wget -O /tmp/discord.deb "https://discord.com/api/download?platform=linux&format=deb"
# Installer la nouvelle version de Discord
dpkg -i /tmp/discord.deb
# Effacer le fichier .deb téléchargé
rm /tmp/discord.deb
# Afficher un message de confirmation
echo "Discord a été installé avec succès !"
fi
Auto Install/Update VSCode
Just run this script
#!/bin/bash
sudo apt install -y wget gpg
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg
sudo install -D -o root -g root -m 644 packages.microsoft.gpg /etc/apt/keyrings/packages.microsoft.gpg
echo "deb [arch=amd64,arm64,armhf signed-by=/etc/apt/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" |sudo tee /etc/apt/sources.list.d/vscode.list > /dev/null
rm -f packages.microsoft.gpg
sudo apt install -y apt-transport-https
sudo apt update
sudo apt install -y code # or code-insiders
Auto install pterodactyl
Just run this script
#!/bin/bash
set -e
######################################################################################
# #
# Project 'pterodactyl-installer' #
# #
# Copyright (C) 2018 - 2024, Vilhelm Prytz, <vilhelm@prytznet.se> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
# #
# https://github.com/pterodactyl-installer/pterodactyl-installer/blob/master/LICENSE #
# #
# This script is not associated with the official Pterodactyl Project. #
# https://github.com/pterodactyl-installer/pterodactyl-installer #
# #
######################################################################################
export GITHUB_SOURCE="v1.1.1"
export SCRIPT_RELEASE="v1.1.1"
export GITHUB_BASE_URL="https://raw.githubusercontent.com/pterodactyl-installer/pterodactyl-installer"
LOG_PATH="/var/log/pterodactyl-installer.log"
# check for curl
if ! [ -x "$(command -v curl)" ]; then
echo "* curl is required in order for this script to work."
echo "* install using apt (Debian and derivatives) or yum/dnf (CentOS)"
exit 1
fi
# Always remove lib.sh, before downloading it
[ -f /tmp/lib.sh ] && rm -rf /tmp/lib.sh
curl -sSL -o /tmp/lib.sh "$GITHUB_BASE_URL"/master/lib/lib.sh
# shellcheck source=lib/lib.sh
source /tmp/lib.sh
execute() {
echo -e "\n\n* pterodactyl-installer $(date) \n\n" >>$LOG_PATH
[[ "$1" == *"canary"* ]] && export GITHUB_SOURCE="master" && export SCRIPT_RELEASE="canary"
update_lib_source
run_ui "${1//_canary/}" |& tee -a $LOG_PATH
if [[ -n $2 ]]; then
echo -e -n "* Installation of $1 completed. Do you want to proceed to $2 installation? (y/N): "
read -r CONFIRM
if [[ "$CONFIRM" =~ [Yy] ]]; then
execute "$2"
else
error "Installation of $2 aborted."
exit 1
fi
fi
}
welcome ""
done=false
while [ "$done" == false ]; do
options=(
"Install the panel"
"Install Wings"
"Install both [0] and [1] on the same machine (wings script runs after panel)"
# "Uninstall panel or wings\n"
"Install panel with canary version of the script (the versions that lives in master, may be broken!)"
"Install Wings with canary version of the script (the versions that lives in master, may be broken!)"
"Install both [3] and [4] on the same machine (wings script runs after panel)"
"Uninstall panel or wings with canary version of the script (the versions that lives in master, may be broken!)"
)
actions=(
"panel"
"wings"
"panel;wings"
# "uninstall"
"panel_canary"
"wings_canary"
"panel_canary;wings_canary"
"uninstall_canary"
)
output "What would you like to do?"
for i in "${!options[@]}"; do
output "[$i] ${options[$i]}"
done
echo -n "* Input 0-$((${#actions[@]} - 1)): "
read -r action
[ -z "$action" ] && error "Input is required" && continue
valid_input=("$(for ((i = 0; i <= ${#actions[@]} - 1; i += 1)); do echo "${i}"; done)")
[[ ! " ${valid_input[*]} " =~ ${action} ]] && error "Invalid option"
[[ " ${valid_input[*]} " =~ ${action} ]] && done=true && IFS=";" read -r i1 i2 <<<"${actions[$action]}" && execute "$i1" "$i2"
done
# Remove lib.sh, so next time the script is run the, newest version is downloaded.
rm -rf /tmp/lib.sh
Auto Docker Install
Just run this script
#!/bin/sh
set -e
# Docker Engine for Linux installation script.
#
# This script is intended as a convenient way to configure docker's package
# repositories and to install Docker Engine, This script is not recommended
# for production environments. Before running this script, make yourself familiar
# with potential risks and limitations, and refer to the installation manual
# at https://docs.docker.com/engine/install/ for alternative installation methods.
#
# The script:
#
# - Requires `root` or `sudo` privileges to run.
# - Attempts to detect your Linux distribution and version and configure your
# package management system for you.
# - Doesn't allow you to customize most installation parameters.
# - Installs dependencies and recommendations without asking for confirmation.
# - Installs the latest stable release (by default) of Docker CLI, Docker Engine,
# Docker Buildx, Docker Compose, containerd, and runc. When using this script
# to provision a machine, this may result in unexpected major version upgrades
# of these packages. Always test upgrades in a test environment before
# deploying to your production systems.
# - Isn't designed to upgrade an existing Docker installation. When using the
# script to update an existing installation, dependencies may not be updated
# to the expected version, resulting in outdated versions.
#
# Source code is available at https://git.vainsta.xyz/nicolaslespinasse/docker-install
#
# Usage
# ==============================================================================
#
# To install the latest stable versions of Docker CLI, Docker Engine, and their
# dependencies:
#
# 1. download the script
#
# at https://git.vainsta.xyz/nicolaslespinasse/docker-install
#
# 2. verify the script's content
#
# $ cat install-docker.sh
#
# 3. run the script with --dry-run to verify the steps it executes
#
# $ sh install-docker.sh --dry-run
#
# 4. run the script either as root, or using sudo to perform the installation.
#
# $ sudo sh install-docker.sh
#
# Command-line options
# ==============================================================================
#
# --version <VERSION>
# Use the --version option to install a specific version, for example:
#
# $ sudo sh install-docker.sh --version 23.0
#
# --channel <stable|test>
#
# Use the --channel option to install from an alternative installation channel.
# The following example installs the latest versions from the "test" channel,
# which includes pre-releases (alpha, beta, rc):
#
# $ sudo sh install-docker.sh --channel test
#
# Alternatively, use the script at https://test.docker.com, which uses the test
# channel as default.
#
# --mirror <Aliyun|AzureChinaCloud>
#
# Use the --mirror option to install from a mirror supported by this script.
# Available mirrors are "Aliyun" (https://mirrors.aliyun.com/docker-ce), and
# "AzureChinaCloud" (https://mirror.azure.cn/docker-ce), for example:
#
# $ sudo sh install-docker.sh --mirror AzureChinaCloud
#
# ==============================================================================
# Git commit from https://github.com/docker/docker-install when
# the script was uploaded (Should only be modified by upload job):
SCRIPT_COMMIT_SHA="${LOAD_SCRIPT_COMMIT_SHA}"
# strip "v" prefix if present
VERSION="${VERSION#v}"
# The channel to install from:
# * stable
# * test
# * edge (deprecated)
# * nightly (deprecated)
DEFAULT_CHANNEL_VALUE="stable"
if [ -z "$CHANNEL" ]; then
CHANNEL=$DEFAULT_CHANNEL_VALUE
fi
DEFAULT_DOWNLOAD_URL="https://download.docker.com"
if [ -z "$DOWNLOAD_URL" ]; then
DOWNLOAD_URL=$DEFAULT_DOWNLOAD_URL
fi
DEFAULT_REPO_FILE="docker-ce.repo"
if [ -z "$REPO_FILE" ]; then
REPO_FILE="$DEFAULT_REPO_FILE"
fi
mirror=''
DRY_RUN=${DRY_RUN:-}
while [ $# -gt 0 ]; do
case "$1" in
--channel)
CHANNEL="$2"
shift
;;
--dry-run)
DRY_RUN=1
;;
--mirror)
mirror="$2"
shift
;;
--version)
VERSION="${2#v}"
shift
;;
--*)
echo "Illegal option $1"
;;
esac
shift $(( $# > 0 ? 1 : 0 ))
done
case "$mirror" in
Aliyun)
DOWNLOAD_URL="https://mirrors.aliyun.com/docker-ce"
;;
AzureChinaCloud)
DOWNLOAD_URL="https://mirror.azure.cn/docker-ce"
;;
"")
;;
*)
>&2 echo "unknown mirror '$mirror': use either 'Aliyun', or 'AzureChinaCloud'."
exit 1
;;
esac
case "$CHANNEL" in
stable|test)
;;
edge|nightly)
>&2 echo "DEPRECATED: the $CHANNEL channel has been deprecated and is no longer supported by this script."
exit 1
;;
*)
>&2 echo "unknown CHANNEL '$CHANNEL': use either stable or test."
exit 1
;;
esac
command_exists() {
command -v "$@" > /dev/null 2>&1
}
# version_gte checks if the version specified in $VERSION is at least the given
# SemVer (Maj.Minor[.Patch]), or CalVer (YY.MM) version.It returns 0 (success)
# if $VERSION is either unset (=latest) or newer or equal than the specified
# version, or returns 1 (fail) otherwise.
#
# examples:
#
# VERSION=23.0
# version_gte 23.0 // 0 (success)
# version_gte 20.10 // 0 (success)
# version_gte 19.03 // 0 (success)
# version_gte 21.10 // 1 (fail)
version_gte() {
if [ -z "$VERSION" ]; then
return 0
fi
eval version_compare "$VERSION" "$1"
}
# version_compare compares two version strings (either SemVer (Major.Minor.Path),
# or CalVer (YY.MM) version strings. It returns 0 (success) if version A is newer
# or equal than version B, or 1 (fail) otherwise. Patch releases and pre-release
# (-alpha/-beta) are not taken into account
#
# examples:
#
# version_compare 23.0.0 20.10 // 0 (success)
# version_compare 23.0 20.10 // 0 (success)
# version_compare 20.10 19.03 // 0 (success)
# version_compare 20.10 20.10 // 0 (success)
# version_compare 19.03 20.10 // 1 (fail)
version_compare() (
set +x
yy_a="$(echo "$1" | cut -d'.' -f1)"
yy_b="$(echo "$2" | cut -d'.' -f1)"
if [ "$yy_a" -lt "$yy_b" ]; then
return 1
fi
if [ "$yy_a" -gt "$yy_b" ]; then
return 0
fi
mm_a="$(echo "$1" | cut -d'.' -f2)"
mm_b="$(echo "$2" | cut -d'.' -f2)"
# trim leading zeros to accommodate CalVer
mm_a="${mm_a#0}"
mm_b="${mm_b#0}"
if [ "${mm_a:-0}" -lt "${mm_b:-0}" ]; then
return 1
fi
return 0
)
is_dry_run() {
if [ -z "$DRY_RUN" ]; then
return 1
else
return 0
fi
}
is_wsl() {
case "$(uname -r)" in
*microsoft* ) true ;; # WSL 2
*Microsoft* ) true ;; # WSL 1
* ) false;;
esac
}
is_darwin() {
case "$(uname -s)" in
*darwin* ) true ;;
*Darwin* ) true ;;
* ) false;;
esac
}
deprecation_notice() {
distro=$1
distro_version=$2
echo
printf "\033[91;1mDEPRECATION WARNING\033[0m\n"
printf " This Linux distribution (\033[1m%s %s\033[0m) reached end-of-life and is no longer supported by this script.\n" "$distro" "$distro_version"
echo " No updates or security fixes will be released for this distribution, and users are recommended"
echo " to upgrade to a currently maintained version of $distro."
echo
printf "Press \033[1mCtrl+C\033[0m now to abort this script, or wait for the installation to continue."
echo
sleep 10
}
get_distribution() {
lsb_dist=""
# Every system that we officially support has /etc/os-release
if [ -r /etc/os-release ]; then
lsb_dist="$(. /etc/os-release && echo "$ID")"
fi
# Returning an empty string here should be alright since the
# case statements don't act unless you provide an actual value
echo "$lsb_dist"
}
echo_docker_as_nonroot() {
if is_dry_run; then
return
fi
if command_exists docker && [ -e /var/run/docker.sock ]; then
(
set -x
$sh_c 'docker version'
) || true
fi
# intentionally mixed spaces and tabs here -- tabs are stripped by "<<-EOF", spaces are kept in the output
echo
echo "================================================================================"
echo
if version_gte "20.10"; then
echo "To run Docker as a non-privileged user, consider setting up the"
echo "Docker daemon in rootless mode for your user:"
echo
echo " dockerd-rootless-setuptool.sh install"
echo
echo "Visit https://docs.docker.com/go/rootless/ to learn about rootless mode."
echo
fi
echo
echo "To run the Docker daemon as a fully privileged service, but granting non-root"
echo "users access, refer to https://docs.docker.com/go/daemon-access/"
echo
echo "WARNING: Access to the remote API on a privileged Docker daemon is equivalent"
echo " to root access on the host. Refer to the 'Docker daemon attack surface'"
echo " documentation for details: https://docs.docker.com/go/attack-surface/"
echo
echo "================================================================================"
echo
}
# Check if this is a forked Linux distro
check_forked() {
# Check for lsb_release command existence, it usually exists in forked distros
if command_exists lsb_release; then
# Check if the `-u` option is supported
set +e
lsb_release -a -u > /dev/null 2>&1
lsb_release_exit_code=$?
set -e
# Check if the command has exited successfully, it means we're in a forked distro
if [ "$lsb_release_exit_code" = "0" ]; then
# Print info about current distro
cat <<-EOF
You're using '$lsb_dist' version '$dist_version'.
EOF
# Get the upstream release info
lsb_dist=$(lsb_release -a -u 2>&1 | tr '[:upper:]' '[:lower:]' | grep -E 'id' | cut -d ':' -f 2 | tr -d '[:space:]')
dist_version=$(lsb_release -a -u 2>&1 | tr '[:upper:]' '[:lower:]' | grep -E 'codename' | cut -d ':' -f 2 | tr -d '[:space:]')
# Print info about upstream distro
cat <<-EOF
Upstream release is '$lsb_dist' version '$dist_version'.
EOF
else
if [ -r /etc/debian_version ] && [ "$lsb_dist" != "ubuntu" ] && [ "$lsb_dist" != "raspbian" ]; then
if [ "$lsb_dist" = "osmc" ]; then
# OSMC runs Raspbian
lsb_dist=raspbian
else
# We're Debian and don't even know it!
lsb_dist=debian
fi
dist_version="$(sed 's/\/.*//' /etc/debian_version | sed 's/\..*//')"
case "$dist_version" in
12)
dist_version="bookworm"
;;
11)
dist_version="bullseye"
;;
10)
dist_version="buster"
;;
9)
dist_version="stretch"
;;
8)
dist_version="jessie"
;;
esac
fi
fi
fi
}
do_install() {
echo "# Executing docker install script, commit: $SCRIPT_COMMIT_SHA"
if command_exists docker; then
cat >&2 <<-'EOF'
Warning: the "docker" command appears to already exist on this system.
If you already have Docker installed, this script can cause trouble, which is
why we're displaying this warning and provide the opportunity to cancel the
installation.
If you installed the current Docker package using this script and are using it
again to update Docker, you can safely ignore this message.
You may press Ctrl+C now to abort this script.
EOF
( set -x; sleep 20 )
fi
user="$(id -un 2>/dev/null || true)"
sh_c='sh -c'
if [ "$user" != 'root' ]; then
if command_exists sudo; then
sh_c='sudo -E sh -c'
elif command_exists su; then
sh_c='su -c'
else
cat >&2 <<-'EOF'
Error: this installer needs the ability to run commands as root.
We are unable to find either "sudo" or "su" available to make this happen.
EOF
exit 1
fi
fi
if is_dry_run; then
sh_c="echo"
fi
# perform some very rudimentary platform detection
lsb_dist=$( get_distribution )
lsb_dist="$(echo "$lsb_dist" | tr '[:upper:]' '[:lower:]')"
if is_wsl; then
echo
echo "WSL DETECTED: We recommend using Docker Desktop for Windows."
echo "Please get Docker Desktop from https://www.docker.com/products/docker-desktop/"
echo
cat >&2 <<-'EOF'
You may press Ctrl+C now to abort this script.
EOF
( set -x; sleep 20 )
fi
case "$lsb_dist" in
ubuntu)
if command_exists lsb_release; then
dist_version="$(lsb_release --codename | cut -f2)"
fi
if [ -z "$dist_version" ] && [ -r /etc/lsb-release ]; then
dist_version="$(. /etc/lsb-release && echo "$DISTRIB_CODENAME")"
fi
;;
debian|raspbian)
dist_version="$(sed 's/\/.*//' /etc/debian_version | sed 's/\..*//')"
case "$dist_version" in
12)
dist_version="bookworm"
;;
11)
dist_version="bullseye"
;;
10)
dist_version="buster"
;;
9)
dist_version="stretch"
;;
8)
dist_version="jessie"
;;
esac
;;
centos|rhel|sles)
if [ -z "$dist_version" ] && [ -r /etc/os-release ]; then
dist_version="$(. /etc/os-release && echo "$VERSION_ID")"
fi
;;
*)
if command_exists lsb_release; then
dist_version="$(lsb_release --release | cut -f2)"
fi
if [ -z "$dist_version" ] && [ -r /etc/os-release ]; then
dist_version="$(. /etc/os-release && echo "$VERSION_ID")"
fi
;;
esac
# Check if this is a forked Linux distro
check_forked
# Print deprecation warnings for distro versions that recently reached EOL,
# but may still be commonly used (especially LTS versions).
case "$lsb_dist.$dist_version" in
debian.stretch|debian.jessie)
deprecation_notice "$lsb_dist" "$dist_version"
;;
raspbian.stretch|raspbian.jessie)
deprecation_notice "$lsb_dist" "$dist_version"
;;
ubuntu.xenial|ubuntu.trusty)
deprecation_notice "$lsb_dist" "$dist_version"
;;
ubuntu.impish|ubuntu.hirsute|ubuntu.groovy|ubuntu.eoan|ubuntu.disco|ubuntu.cosmic)
deprecation_notice "$lsb_dist" "$dist_version"
;;
fedora.*)
if [ "$dist_version" -lt 36 ]; then
deprecation_notice "$lsb_dist" "$dist_version"
fi
;;
esac
# Run setup for each distro accordingly
case "$lsb_dist" in
ubuntu|debian|raspbian)
pre_reqs="apt-transport-https ca-certificates curl"
if ! command -v gpg > /dev/null; then
pre_reqs="$pre_reqs gnupg"
fi
apt_repo="deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] $DOWNLOAD_URL/linux/$lsb_dist $dist_version $CHANNEL"
(
if ! is_dry_run; then
set -x
fi
$sh_c 'apt-get update -qq >/dev/null'
$sh_c "DEBIAN_FRONTEND=noninteractive apt-get install -y -qq $pre_reqs >/dev/null"
$sh_c 'install -m 0755 -d /etc/apt/keyrings'
$sh_c "curl -fsSL \"$DOWNLOAD_URL/linux/$lsb_dist/gpg\" | gpg --dearmor --yes -o /etc/apt/keyrings/docker.gpg"
$sh_c "chmod a+r /etc/apt/keyrings/docker.gpg"
$sh_c "echo \"$apt_repo\" > /etc/apt/sources.list.d/docker.list"
$sh_c 'apt-get update -qq >/dev/null'
)
pkg_version=""
if [ -n "$VERSION" ]; then
if is_dry_run; then
echo "# WARNING: VERSION pinning is not supported in DRY_RUN"
else
# Will work for incomplete versions IE (17.12), but may not actually grab the "latest" if in the test channel
pkg_pattern="$(echo "$VERSION" | sed 's/-ce-/~ce~.*/g' | sed 's/-/.*/g')"
search_command="apt-cache madison docker-ce | grep '$pkg_pattern' | head -1 | awk '{\$1=\$1};1' | cut -d' ' -f 3"
pkg_version="$($sh_c "$search_command")"
echo "INFO: Searching repository for VERSION '$VERSION'"
echo "INFO: $search_command"
if [ -z "$pkg_version" ]; then
echo
echo "ERROR: '$VERSION' not found amongst apt-cache madison results"
echo
exit 1
fi
if version_gte "18.09"; then
search_command="apt-cache madison docker-ce-cli | grep '$pkg_pattern' | head -1 | awk '{\$1=\$1};1' | cut -d' ' -f 3"
echo "INFO: $search_command"
cli_pkg_version="=$($sh_c "$search_command")"
fi
pkg_version="=$pkg_version"
fi
fi
(
pkgs="docker-ce${pkg_version%=}"
if version_gte "18.09"; then
# older versions didn't ship the cli and containerd as separate packages
pkgs="$pkgs docker-ce-cli${cli_pkg_version%=} containerd.io"
fi
if version_gte "20.10"; then
pkgs="$pkgs docker-compose-plugin docker-ce-rootless-extras$pkg_version"
fi
if version_gte "23.0"; then
pkgs="$pkgs docker-buildx-plugin"
fi
if ! is_dry_run; then
set -x
fi
$sh_c "DEBIAN_FRONTEND=noninteractive apt-get install -y -qq $pkgs >/dev/null"
)
echo_docker_as_nonroot
exit 0
;;
centos|fedora|rhel)
if [ "$(uname -m)" != "s390x" ] && [ "$lsb_dist" = "rhel" ]; then
echo "Packages for RHEL are currently only available for s390x."
exit 1
fi
if [ "$lsb_dist" = "fedora" ]; then
pkg_manager="dnf"
config_manager="dnf config-manager"
enable_channel_flag="--set-enabled"
disable_channel_flag="--set-disabled"
pre_reqs="dnf-plugins-core"
pkg_suffix="fc$dist_version"
else
pkg_manager="yum"
config_manager="yum-config-manager"
enable_channel_flag="--enable"
disable_channel_flag="--disable"
pre_reqs="yum-utils"
pkg_suffix="el"
fi
repo_file_url="$DOWNLOAD_URL/linux/$lsb_dist/$REPO_FILE"
(
if ! is_dry_run; then
set -x
fi
$sh_c "$pkg_manager install -y -q $pre_reqs"
$sh_c "$config_manager --add-repo $repo_file_url"
if [ "$CHANNEL" != "stable" ]; then
$sh_c "$config_manager $disable_channel_flag 'docker-ce-*'"
$sh_c "$config_manager $enable_channel_flag 'docker-ce-$CHANNEL'"
fi
$sh_c "$pkg_manager makecache"
)
pkg_version=""
if [ -n "$VERSION" ]; then
if is_dry_run; then
echo "# WARNING: VERSION pinning is not supported in DRY_RUN"
else
pkg_pattern="$(echo "$VERSION" | sed 's/-ce-/\\\\.ce.*/g' | sed 's/-/.*/g').*$pkg_suffix"
search_command="$pkg_manager list --showduplicates docker-ce | grep '$pkg_pattern' | tail -1 | awk '{print \$2}'"
pkg_version="$($sh_c "$search_command")"
echo "INFO: Searching repository for VERSION '$VERSION'"
echo "INFO: $search_command"
if [ -z "$pkg_version" ]; then
echo
echo "ERROR: '$VERSION' not found amongst $pkg_manager list results"
echo
exit 1
fi
if version_gte "18.09"; then
# older versions don't support a cli package
search_command="$pkg_manager list --showduplicates docker-ce-cli | grep '$pkg_pattern' | tail -1 | awk '{print \$2}'"
cli_pkg_version="$($sh_c "$search_command" | cut -d':' -f 2)"
fi
# Cut out the epoch and prefix with a '-'
pkg_version="-$(echo "$pkg_version" | cut -d':' -f 2)"
fi
fi
(
pkgs="docker-ce$pkg_version"
if version_gte "18.09"; then
# older versions didn't ship the cli and containerd as separate packages
if [ -n "$cli_pkg_version" ]; then
pkgs="$pkgs docker-ce-cli-$cli_pkg_version containerd.io"
else
pkgs="$pkgs docker-ce-cli containerd.io"
fi
fi
if version_gte "20.10"; then
pkgs="$pkgs docker-compose-plugin docker-ce-rootless-extras$pkg_version"
fi
if version_gte "23.0"; then
pkgs="$pkgs docker-buildx-plugin"
fi
if ! is_dry_run; then
set -x
fi
$sh_c "$pkg_manager install -y -q $pkgs"
)
echo_docker_as_nonroot
exit 0
;;
sles)
if [ "$(uname -m)" != "s390x" ]; then
echo "Packages for SLES are currently only available for s390x"
exit 1
fi
if [ "$dist_version" = "15.3" ]; then
sles_version="SLE_15_SP3"
else
sles_minor_version="${dist_version##*.}"
sles_version="15.$sles_minor_version"
fi
repo_file_url="$DOWNLOAD_URL/linux/$lsb_dist/$REPO_FILE"
pre_reqs="ca-certificates curl libseccomp2 awk"
(
if ! is_dry_run; then
set -x
fi
$sh_c "zypper install -y $pre_reqs"
$sh_c "zypper addrepo $repo_file_url"
if ! is_dry_run; then
cat >&2 <<-'EOF'
WARNING!!
openSUSE repository (https://download.opensuse.org/repositories/security:SELinux) will be enabled now.
Do you wish to continue?
You may press Ctrl+C now to abort this script.
EOF
( set -x; sleep 30 )
fi
opensuse_repo="https://download.opensuse.org/repositories/security:SELinux/$sles_version/security:SELinux.repo"
$sh_c "zypper addrepo $opensuse_repo"
$sh_c "zypper --gpg-auto-import-keys refresh"
$sh_c "zypper lr -d"
)
pkg_version=""
if [ -n "$VERSION" ]; then
if is_dry_run; then
echo "# WARNING: VERSION pinning is not supported in DRY_RUN"
else
pkg_pattern="$(echo "$VERSION" | sed 's/-ce-/\\\\.ce.*/g' | sed 's/-/.*/g')"
search_command="zypper search -s --match-exact 'docker-ce' | grep '$pkg_pattern' | tail -1 | awk '{print \$6}'"
pkg_version="$($sh_c "$search_command")"
echo "INFO: Searching repository for VERSION '$VERSION'"
echo "INFO: $search_command"
if [ -z "$pkg_version" ]; then
echo
echo "ERROR: '$VERSION' not found amongst zypper list results"
echo
exit 1
fi
search_command="zypper search -s --match-exact 'docker-ce-cli' | grep '$pkg_pattern' | tail -1 | awk '{print \$6}'"
# It's okay for cli_pkg_version to be blank, since older versions don't support a cli package
cli_pkg_version="$($sh_c "$search_command")"
pkg_version="-$pkg_version"
fi
fi
(
pkgs="docker-ce$pkg_version"
if version_gte "18.09"; then
if [ -n "$cli_pkg_version" ]; then
# older versions didn't ship the cli and containerd as separate packages
pkgs="$pkgs docker-ce-cli-$cli_pkg_version containerd.io"
else
pkgs="$pkgs docker-ce-cli containerd.io"
fi
fi
if version_gte "20.10"; then
pkgs="$pkgs docker-compose-plugin docker-ce-rootless-extras$pkg_version"
fi
if version_gte "23.0"; then
pkgs="$pkgs docker-buildx-plugin"
fi
if ! is_dry_run; then
set -x
fi
$sh_c "zypper -q install -y $pkgs"
)
echo_docker_as_nonroot
exit 0
;;
*)
if [ -z "$lsb_dist" ]; then
if is_darwin; then
echo
echo "ERROR: Unsupported operating system 'macOS'"
echo "Please get Docker Desktop from https://www.docker.com/products/docker-desktop"
echo
exit 1
fi
fi
echo
echo "ERROR: Unsupported distribution '$lsb_dist'"
echo
exit 1
;;
esac
exit 1
}
# wrapped up in a function so that we have some protection against only getting
# half the file during "curl | sh"
do_install
Auto GLPI Install
just run this script
#!/bin/bash
#
# GLPI install script
#
#Author Masaru_M
#Ver 1.0.R
function warn(){
echo -e '\e[31m'$1'\e[0m';
}
function info(){
echo -e '\e[36m'$1'\e[0m';
}
function check_root()
{
# Vérification des privilèges root
if [[ "$(id -u)" -ne 0 ]]
then
warn "This script must be run as root" >&2
exit 1
else
info "Root privilege: OK"
fi
}
function check_distro()
{
# Constante pour les versions de Debian acceptables
DEBIAN_VERSIONS=("11" "12")
# Constante pour les versions d'Ubuntu acceptables
UBUNTU_VERSIONS=("22.04")
# Récupération du nom de la distribution
DISTRO=$(lsb_release -is)
# Récupération de la version de la distribution
VERSION=$(lsb_release -rs)
# Vérifie si c'est une distribution Debian
if [ "$DISTRO" == "Debian" ]; then
# Vérifie si la version de Debian est acceptable
if [[ " ${DEBIAN_VERSIONS[*]} " == *" $VERSION "* ]]; then
info "Your operating system version ($DISTRO $VERSION) is compatible."
else
warn "Your operating system version ($DISTRO $VERSION) is not noted as compatible."
warn "Do you still want to force the installation? Be careful, if you choose to force the script, it is at your own risk."
info "Are you sure you want to continue? [yes/no]"
read response
if [ $response == "yes" ]; then
info "Continuing..."
elif [ $response == "no" ]; then
info "Exiting..."
exit 1
else
warn "Invalid response. Exiting..."
exit 1
fi
fi
# Vérifie si c'est une distribution Ubuntu
elif [ "$DISTRO" == "Ubuntu" ]; then
# Vérifie si la version d'Ubuntu est acceptable
if [[ " ${UBUNTU_VERSIONS[*]} " == *" $VERSION "* ]]; then
info "Your operating system version ($DISTRO $VERSION) is compatible."
else
warn "Your operating system version ($DISTRO $VERSION) is not noted as compatible."
warn "Do you still want to force the installation? Be careful, if you choose to force the script, it is at your own risk."
info "Are you sure you want to continue? [yes/no]"
read response
if [ $response == "yes" ]; then
info "Continuing..."
elif [ $response == "no" ]; then
info "Exiting..."
exit 1
else
warn "Invalid response. Exiting..."
exit 1
fi
fi
# Si c'est une autre distribution
else
warn "Il s'agit d'une autre distribution que Debian ou Ubuntu qui n'est pas compatible."
exit 1
fi
}
function network_info()
{
INTERFACE=$(ip route | awk 'NR==1 {print $5}')
IPADRESS=$(ip addr show $INTERFACE | grep inet | awk '{ print $2; }' | sed 's/\/.*$//' | head -n 1)
HOST=$(hostname)
}
function confirm_installation()
{
warn "This script will now install the necessary packages for installing and configuring GLPI."
info "Are you sure you want to continue? [yes/no]"
read confirm
if [ $confirm == "yes" ]; then
info "Continuing..."
elif [ $confirm == "no" ]; then
info "Exiting..."
exit 1
else
warn "Invalid response. Exiting..."
exit 1
fi
}
function install_packages()
{
info "Installing packages..."
sleep 1
apt update
apt install --yes --no-install-recommends \
apache2 \
mariadb-server \
perl \
curl \
jq \
php
info "Installing php extensions..."
apt install --yes --no-install-recommends \
php-ldap \
php-imap \
php-apcu \
php-xmlrpc \
php-cas \
php-mysqli \
php-mbstring \
php-curl \
php-gd \
php-simplexml \
php-xml \
php-intl \
php-zip \
php-bz2
systemctl enable mariadb
systemctl enable apache2
}
function mariadb_configure()
{
info "Configuring MariaDB..."
sleep 1
SLQROOTPWD=$(openssl rand -base64 48 | cut -c1-12 )
SQLGLPIPWD=$(openssl rand -base64 48 | cut -c1-12 )
systemctl start mariadb
sleep 1
# Remove anonymous user accounts
mysql -e "DELETE FROM mysql.user WHERE User = ''"
# Disable remote root login
mysql -e "DELETE FROM mysql.user WHERE User = 'root' AND Host NOT IN ('localhost', '127.0.0.1', '::1')"
# Remove the test database
mysql -e "DROP DATABASE test"
# Reload privileges
mysql -e "FLUSH PRIVILEGES"
# Create a new database
mysql -e "CREATE DATABASE glpi"
# Create a new user
mysql -e "CREATE USER 'glpi_user'@'localhost' IDENTIFIED BY '$SQLGLPIPWD'"
# Grant privileges to the new user for the new database
mysql -e "GRANT ALL PRIVILEGES ON glpi.* TO 'glpi_user'@'localhost'"
# Reload privileges
mysql -e "FLUSH PRIVILEGES"
# Initialize time zones datas
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql mysql
#Ask tz
dpkg-reconfigure tzdata
systemctl restart mariadb
sleep 1
mysql -e "GRANT SELECT ON mysql.time_zone_name TO 'glpi_user'@'localhost'"
mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '$SLQROOTPWD'"
}
function install_glpi()
{
info "Downloading and installing the latest version of GLPI..."
# Get download link for the latest release
DOWNLOADLINK=$(curl -s https://api.github.com/repos/glpi-project/glpi/releases/latest | jq -r '.assets[0].browser_download_url')
wget -O /tmp/glpi-latest.tgz $DOWNLOADLINK
tar xzf /tmp/glpi-latest.tgz -C /var/www/html/
touch /var/www/html/glpi/files/_log/php-errors.log
# Add permissions
chown -R www-data:www-data /var/www/html/glpi
chmod -R 775 /var/www/html/glpi
# Setup vhost
cat > /etc/apache2/sites-available/000-default.conf << EOF
<VirtualHost *:80>
DocumentRoot /var/www/html/glpi/public
<Directory /var/www/html/glpi/public>
Require all granted
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [QSA,L]
</Directory>
LogLevel warn
ErrorLog \${APACHE_LOG_DIR}/error-glpi.log
CustomLog \${APACHE_LOG_DIR}/access-glpi.log combined
</VirtualHost>
EOF
#Disable Apache Web Server Signature
echo "ServerSignature Off" >> /etc/apache2/apache2.conf
echo "ServerTokens Prod" >> /etc/apache2/apache2.conf
# Setup Cron task
echo "*/2 * * * * www-data /usr/bin/php /var/www/html/glpi/front/cron.php &>/dev/null" >> /etc/cron.d/glpi
#Activation du module rewrite d'apache
a2enmod rewrite && systemctl restart apache2
}
function setup_db()
{
info "Setting up GLPI..."
cd /var/www/html/glpi
php bin/console db:install --db-name=glpi --db-user=glpi_user --db-password=$SQLGLPIPWD --no-interaction
rm -rf /var/www/html/glpi/install
}
function display_credentials()
{
info "=======> GLPI installation details <======="
warn "It is important to record this informations. If you lose them, they will be unrecoverable."
info "==> GLPI:"
info "Default user accounts are:"
info "USER - PASSWORD - ACCESS"
info "glpi - glpi - admin account,"
info "tech - tech - technical account,"
info "normal - normal - normal account,"
info "post-only - postonly - post-only account."
echo ""
info "You can connect access GLPI web page from IP or hostname:"
info "http://$IPADRESS or http://$HOST"
echo ""
info "==> Database:"
info "root password: $SLQROOTPWD"
info "glpi_user password: $SQLGLPIPWD"
info "GLPI database name: glpi"
info "<==========================================>"
echo ""
info "If you encounter any issue with this script, please report it to "Masaru_M" on discord."
}
check_root
check_distro
confirm_installation
network_info
install_packages
mariadb_configure
install_glpi
setup_db
display_credentials
Manual Install
Lynis - System Audits
Lynis is a tool, that scans your local system for misconfigurations. At the end, you will get an index score, that indicates how safe your system is. Anything above 80 is fine. Everything below 70 is worrisome. You can install Lynis the following way:
sudo apt install apt-transport-https ca-certificates host gnupg
sudo wget -O - https://packages.cisofy.com/keys/cisofy-software-public.key | sudo apt-key add -
sudo echo "deb https://packages.cisofy.com/community/lynis/deb/ stable main" | sudo tee /etc/apt/sources.list.d/cisofy-lynis.list
sudo apt update
sudo apt install lynis host
Update the database:
sudo lynis update info
To audit your system run
sudo lynis audit system
Below your score, you will also see a list of recommended actions to take. Keep in mind, that Lynis is not perfect, so it might also show errors, for stuff you fixed in a different way than Lynis expected.
Installation de GLPI
Présentation
GLPI (Gestionnaire Libre de Parc Informatique) est un logiciel libre de gestion des services informatiques et de gestion des services d'assistance.
Parmi ses caractéristiques, cette solution est capable de construire un inventaire de toutes les ressources de la société et de réaliser la gestion des tâches administratives et financières. Les fonctionnalités de cette solution aident les administrateurs informatique à créer une base de données regroupant des ressources techniques et de gestion, ainsi qu’un historique des actions de maintenance. La fonctionnalité de gestion d'assistance ou helpdesk fournit aux utilisateurs un service leur permettant de signaler des incidents ou de créer des demandes basées sur un actif ou non, ceci par la création d'un ticket d’assistance.
Prérequis
GLPI est une application web. Nous allons l’installer sur Debian 9, et nécessite donc plusieurs paquets:
-
- Apache 2
- Php et ses dépendances
- MySQL, qui peut être soit en local, soit en déporté sur un autre serveur
Installation de base
On fait d’abord les mises à jours
apt-get update && apt-get upgrade
On installe ensuite tous les paquets nécessaire
apt-get install apache2 php php-gd php-mysql mysql-server php-mbstring php-curl php-xml
Initialisation de la base de données
Pour créer une base de donnée il faut d'abord rentrer dans la console mysql:
$ mysql -u root -p
On crée la base de donnée bddglpi
> create database bddglpi character set utf8;
On donne tous les privilèges sur la bddglpi à l’user glpi avec le mot de passe glpi
> grant all privileges on bddglpi.* to glpi@localhost identified by 'glpi';
> exit
Installation de GLPI
Pour télécharger GLPI nous devons d’abord récupérer le code source compressée
wget https://github.com/glpi-project/glpi/releases/download/9.3.3/glpi-9.3.3.tgz
Pour le décompresser
tar xzvf glpi-9.3.3.tgz
On déplace ensuite le dossier GLPI vers le dossier web
mv glpi /var/www/html
Pour finir, on ajoute les droit à l’utilisateur apache pour qu’il puisse l’afficher et le modifier
chown -R www-data /var/www/html/glpi
Installer Odoo 15 sur Debian 11
Odoo est ERP (Enterprise Ressource Planning), un progiciel open-source de gestion intégré. Il fonctionne avec des modules qui répondent aux besoins de la gestion d’une entreprise et la gestion de la relation client. Odoo fonctionne avec le SGBD PostgreSQL. Dans cette procédure, je vais vous montrer comment installer Odoo 15 ainsi que PostgreSQL14 sur une machine Debian 11.
Prérequis :
- Une machine sur Debian 11
- Les accès root sur la machine Debian
Installer Odoo 15 sur Debian 11 :
Avant de commencer l’installation de Odoo, il faut mettre à jour la machine avec la commande :
apt update && apt upgrade -y
Après avoir mis à jour la machine, on va avoir besoin de dépendances :
apt install gnupg gnupg1 gnupg2 wget vim sudo -y apt-get install -y lsb-release && apt-get clean all
Installation de PostgreSQL sur Debian (pour Odoo) :
Il faut installer Postgresql 14 sur la machine :
On commence par ajouter les sources de PostgreSQL :
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
Puis on ajoute la clé de GPG :
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
Ensuite on met à jour les sources :
sudo apt -y update
Après avoir mis à jour les sources, il est possible d’installer PostgreSQL avec la commande :
sudo apt install postgresql-14 -y
On peut enfin vérifier que l’installation c’est bien effectuée :
sudo -u postgres psql
Pour quitter la console PostgreSQL :
exit
Changement de la pair de confiance :
sudo sed -i '/^local/s/peer/trust/' /etc/postgresql/14/main/pg_hba.conf
Autorisation de la connexion avec un mot de passe :
sudo sed -i '/^host/s/ident/md5/' /etc/postgresql/14/main/pg_hba.conf
Puis modifier le fichier « /etc/postgresql/14/main/pg_hba.conf » :
sudo vim /etc/postgresql/14/main/pg_hba.conf
Ajoutez ces lignes :
# IPv4 local connections: host all all 127.0.0.1/32 scram-sha-256 host all all 0.0.0.0/24 md5 # IPv6 local connections: host all all ::1/128 scram-sha-256 host all all 0.0.0.0/0 md5
Ensuite on peut redémarrer et activer le service PostgreSQL :
sudo systemctl restart postgresql sudo systemctl enable postgresql
Après avoir configurer PostgreSQL on peut se créer un compte administrateur pour gérer la base de données :
D’abord on va se connecter à PostgreSQL :
sudo -u postgres psql
Puis on va envoyer la requête SQL pour créer le compte utilisateur (pensez à changer le nom d’utilisateur et le mot de passe).
CREATE ROLE administrateur WITH LOGIN SUPERUSER CREATEDB CREATEROLE PASSWORD 'M0t de p@sse';
Installation de Odoo sur Debian :
Avant d’installer Odoo sur la machine, on va d’abord installer la clé GPG du repository :
wget https://nightly.odoo.com/odoo.key cat odoo.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/odoo.gpg >/dev/null
Après on ajoute le repository et on met à jour les paquets de la machine :
echo "deb http://nightly.odoo.com/15.0/nightly/deb/ ./" | sudo tee /etc/apt/sources.list.d/odoo.list sudo apt update
Ensuite on peut installer Odoo 15 :
sudo apt install odoo -y
Une fois Odoo installer on peut vérifier son bon fonctionnement et l’activer au démarrage :
systemctl status odoo sudo systemctl enable --now odoo
Odoo fonctionne avec le port 8069 en TCP (A autorisé dans votre firewall si vous en utilisez un, je vous conseil d’utiliser UFW ).
Pour accèder à Odoo depuis un navigateur web utilisez l’url : http://ip-de-la-machine:8069
Voici l’interface après l’installation :
Installer Symfony 6 sur Debian 11
Symfony est un framework PHP structuré en MVC accompagné de composants. Symfony permet de développer rapidement une application Web. Symfony peut permettre de créer des applications web et des API. Dans cette procédure, je vais vous expliquer comment installer Symfony 6 sur une machine Debian 11.
Prérequis pour installer de Symfony 6 sur Debian 11 :
- Une machine Debian 11
Installer de Symfony 6 sur Debian 11 :
Avant de commencer l’installation de Symfony 6 sur Debian Bullseye, on va commencer par mettre à jour les paquets
apt update && apt full-upgrade -y
Installer PHP 8 :
Avant d’installer PHP 8, on va avoir besoin des d’installer les paquets suivants :
apt install -y lsb-release ca-certificates apt-transport-https software-properties-common gnupg2
Ensuite, on ajoute un nouveau dépôts de paquets :
echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" | tee /etc/apt/sources.list.d/sury-php.list
Ajout de la clé du dépot :
wget -qO - https://packages.sury.org/php/apt.gpg | apt-key add -
Mise à jour des paquets :
apt update && apt upgrade -y
Installation de PHP 8 :
apt install php
Installation de Composer :
Pour fonctionner, Symfony à besoin de Composer, et Composer à besoin de PHP pour l’installer :
apt install wget php-cli php-xml php-zip php-mbstring unzip -y
Ensuite on télécharge le programme d’installation de Composer :
wget -O composer-setup.php https://getcomposer.org/installer
Puis on exécute le programme d’installation de Composer
php composer-setup.php --install-dir=/usr/local/bin --filename=composer
Vérification que composer est bien installé
composer --version
Installer Symfony 6 sur Debian 11 :
D’abord on télécharge et on exécute le programme d’installation fournis par Symfony :
curl -1sLf 'https://dl.cloudsmith.io/public/symfony/stable/setup.deb.sh' | sudo -E bash
Puis on Installe la CLI (Interface en ligne de commande) Symfony.
apt install symfony-cli
Enfin on vérifie que Symfony à bien installé.
symfony -V
Création d’un projet de test :
Pour vérifier que Symfony 6 fonctionne normalement, on va créer un projet Symfony 6 à l’aide de la CLI Symfony.
symfony new --webapp test
Puis rendez-vous dans le dossier du projet Symfony qui vient d’être créer (test).
cd test
Ensuite, on démarre le serveur web de Symfony 6 :
symfony serve
Enfin, le port utilisé sera indiqué dans le terminal et après avoir démarrer le serveur web sera disponible depuis un navigateur Web.
Installer Composer sur Debian 11
Dans cette procédure, je vais vous expliquer comment installer composer sur une machine Debian 11. Composer est un outils qui permet d’installer des Bibliothèques PHP rapidement en ligne de commandes.
Composer a lui même été coder dans le langage PHP. L’outil Composer est gestionnaire de Librairie (PHP) très populaire, il est également utiliser par les développeur qui utilisent le framework PHP Symfony.
Prérequis :
- Une machine sous Debian 11
- Avoir PHP d’installer (Installer un serveur Lamp sous Debian 11)
Installer Composer sur Debian 11 :
Dans un premier temps, nous allons récupérer le fichier d’installation de composer.
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
Puis nous allons l’exécuter afin d’installer composer sur notre machine.
php composer-setup.php --install-dir=/usr/local/bin --filename=composer
Ensuite nous allons donner les droits a composer de d’exécuter sur notre machine.
chmod +x /usr/local/bin/composer
Ensuite vous pouvez vérifier que composer c’est bien installer :
composer --version
Enfin vous pouvez mettre à jour composer avec :
composer self-update
Une fois que vous avez installer Composer sur votre machine et vous pouvez vous rendre dans le dossier de votre projet.
cd mon-projet
Puis vous pouvez inclure la librairie que vous avez besoin :
composer require --dev phpunit/phpunit
Le drapeau « dev » est appelé pour informer que la librairie ne sera donc utilisée uniquement sur la version de développement.
Installer Plex sur Debian 11
Dans cette procédure, je vais vous montrer comment installer Plex sur une machine Debian 11. Plex est un service de médias-center permettant de centraliser ses médias. Plex dispose également d’un agent qui récupère les informations sur les médias pour obtenir des détails sur les médias. Plex est un médias-center open-source et gratuit pour une utilisation limitée mais il est possible de rémunérer les créateurs afin de débloquer des fonctionnalités. Je ne serais en aucun cas responsable si vous utilisez cette procédure dans le but d’une utilisation illégale de cette procédure.
Prérequis pour l’installation de Plex :
- Une machine Debian 11
- Des accès root sur la machine
Installer Plex sur Debian 11 :
Avant de débuter l’installation de Plex sur la machine, on va d’abord la mettre à jour et installer des paquets :
apt update -y && apt upgrade -y && apt install sudo -y
Ensuite on va ajouter Plex dans les sources :
echo "deb https://downloads.plex.tv/repo/deb/ public main" > /etc/apt/sources.list.d/plexmediaserver.list
Puis avec une mise à jour des paquets, il sera possible d’installer plexmediaserver :
sudo apt update && sudo apt install plexmediaserver
Après on va activer puis démarrer Plex :
sudo systemctl enable plexmediaserver sudo systemctl start plexmediaserver
Ensuite il sera possible de se connecter sur l’interface Web depuis un navigateur à l’adresse suivante :
http://ip-du-serveur:32400/web
Ensuite depuis l’interface Web il faut configurer l’emplacement des médias. Puis après vous aurez la possibilité de créer des comptes pour vos utilisateurs et vous aurez également la possibilité de gérer les droits.
Après avoir été connecter sur son compte Plex depuis votre serveur, vous pouvez également vous connecter à votre serveur Plex depuis l’url suivante : https://app.plex.tv/desktop
Cette méthode permet un accès depuis l’extérieur, sans avoir besoin de retenir l’adresse Ip public/dns et le port utilisé.
Installer Nextcloud sur Debian 11
Dans cette procédure, je vais vous montrer comment installer Nexcloud sur Debian 11. Après avoir installé Nextcloud sur Debian 11 vous aurez une solution cloud à votre disposition. Installer Nextcloud sur Debian 11 permet de travailler avec vos collaborateur sur votre solution cloud open-sources. Nextcloud utilise la suite OnlyOffice qui est intégré lors de l’installation.
Prérequis :
- Une machine Debian 11
- Les permissions administrateur
Installer Nextcloud sur Debian 11 :
Pour débuter l’installation de Nextcloud sur Debian 11, nous allons mettre à jour notre machine Debian :
sudo apt update && sudo apt upgrade -y
Puis on va télécharger les dépendances :
sudo apt install wget unzip
Ensuite, on va installer Apache2 comme serveur Web :
sudo apt install apache2 libapache2-mod-php
Après, on va installer php :
sudo apt install -y php php-gd php-curl php-zip php-dom php-xml php-simplexml php-mbstring php-mysql
Et la base de données (Mariadb) :
sudo apt install mariadb-server
Ensuite on va changer le mot de passe root de Mariadb avec :
mysql_secure_installation
Enfin on va créer une base de données nextcloud et un utilisateur :
mariadb -u root -p
CREATE DATABASE nextclouddb; GRANT ALL ON nextclouddb.* TO 'usernextcloud'@'localhost' IDENTIFIED BY 'password'; FLUSH PRIVILEGES; EXIT;
Puis on va se rendre dans un emplacement temporaire pour télécharger Nextcloud :
cd /tmp
Ensuite, on va télécharger Nextcloud :
wget https://download.nextcloud.com/server/releases/nextcloud-22.2.3.zip
Après avoir télécharger l’archive, on va la dézipper :
unzip nextcloud-22.2.3.zip
Puis on va déplacer le dossier dans le répertoire Web :
mv nextcloud /var/www/html
Après on peut se rendre sur le site avec l’adresse ip de la machine pour poursuivre : http://votre-ip/
Enfin on ajoute les droits à l’utilisateur web sur le répertoire de Nextcloud :
chown -R www-data:www-data /var/www/html/nextcloud
Créer un compte administrateur pour Nextcloud :
Puis saisissez vos accès à votre base de données :
Après avoir saisis vos informations, l’installation de Nextcloud est terminée.
Vous pouvez désormais utiliser Nextcloud.
Installer PhpMyAdmin sur Debian 11
PhpMyAdmin est une interface Web qui permet de gérer ses bases de données Mysql et Mariadb de manière graphique. Dans cette procédure je vais vous montrer deux manières d’installer PhpMyAdmin sur Debian 11 (Bullseye).
Prérequis :
- Une machine Debian 11 (Bullseye)
- Une base de données Mariadb ou Mysql
Installer PhpMyAdmin sur Debian 11 :
L’installation de PhpMyAdmin peut se faire de deux manières différentes sur Debian, l’une d’elles se fait à l’aide à l’aide d’un dépôt ou sinon elle peut se faire en en saisissant une suite d’instruction dans votre terminal. Cette dernière méthode est plus longue mais personnalisable à vos besoins et elle est également plus sûre.
Avant de commencer à suivre la procédure, pensez à la liste de vos paquets à jour :
sudo apt update
Ces deux manières de procéder nécessitent une base de données Mariadb ou Mysql, Apache2 et aussi des paquets Php.
sudo apt install apache2 php libapache2-mod-php php-cli php-mysql php-zip php-curl php-xml wget -y
Installation de PhpMyAdmin avec dépôt sur Debian 11 :
Il est possible de d’installer PhpMyAdmin à l’aide d’un dépôt, avec la commande suivante :
apt install phpmyadmin
Installation de PhpMyAdmin manuellement sur Debian 11 :
Après avoir téléchargé les paquets, nous allons récupérer la dernière version de PhpMyAdmin :
DATA="$(wget https://www.phpmyadmin.net/home_page/version.txt -q -O-)" URL="$(echo $DATA | cut -d ' ' -f 3)" VERSION="$(echo $DATA | cut -d ' ' -f 1)" wget https://files.phpmyadmin.net/phpMyAdmin/${VERSION}/phpMyAdmin-${VERSION}-all-languages.tar.gz
Puis on extrait l’archive :
tar xvf phpMyAdmin-${VERSION}-all-languages.tar.gz
Ensuite on déplace le dossier dans le répertoire /usr/share/ :
mv phpMyAdmin-*/ /usr/share/phpmyadmin
Après avoir réalisé cette étape nous devons créer un répertoire pour les fichiers temporaires de PhpMyAdmin et attribuer l’utilisateur d’apache comme propriétaire de l’emplacement de PhpMyAdmin :
mkdir -p /var/lib/phpmyadmin/tmp chown -R www-data:www-data /var/lib/phpmyadmin
Puis on peut copier le template de fichier de configuration de PhpMyAdmin afin de l’utiliser :
cp /usr/share/phpmyadmin/config.sample.inc.php /usr/share/phpmyadmin/config.inc.php
Et ensuite nous devrons éditer ce nouveau fichier :
nano /usr/share/phpmyadmin/config.inc.php
Définissez votre phrase secrète en y ajoutant la ligne :
$cfg['blowfish_secret'] = 'xxxxxxxxxxxxxxxx';
Et ajouter la ligne suivante pour spécifier à PhpMyAdmin de l’emplacement temporaire que nous avions créé :
$cfg['TempDir'] = '/var/lib/phpmyadmin/tmp';
Ensuite nous allons créer un virtualhost dans apache pour pouvoir avoir un accès à PhpMyAdmin :
nano /etc/apache2/conf-enabled/phpmyadmin.conf
Collez cette configuration dans le fichier :
Alias /phpmyadmin /usr/share/phpmyadmin <Directory /usr/share/phpmyadmin> Options SymLinksIfOwnerMatch DirectoryIndex index.php <IfModule mod_php5.c> <IfModule mod_mime.c> AddType application/x-httpd-php .php </IfModule> <FilesMatch ".+\.php$"> SetHandler application/x-httpd-php </FilesMatch> php_value include_path . php_admin_value upload_tmp_dir /var/lib/phpmyadmin/tmp php_admin_value open_basedir /usr/share/phpmyadmin/:/etc/phpmyadmin/:/var/lib/phpmyadmin/:/usr/share/php/php-gettext/:/usr/share/php/php-php-gettext/:/usr/share/javascript/:/usr/share/php/tcpdf/:/usr/share/doc/phpmyadmin/:/usr/share/php/phpseclib/ php_admin_value mbstring.func_overload 0 </IfModule> <IfModule mod_php.c> <IfModule mod_mime.c> AddType application/x-httpd-php .php </IfModule> <FilesMatch ".+\.php$"> SetHandler application/x-httpd-php </FilesMatch> php_value include_path . php_admin_value upload_tmp_dir /var/lib/phpmyadmin/tmp php_admin_value open_basedir /usr/share/phpmyadmin/:/etc/phpmyadmin/:/var/lib/phpmyadmin/:/usr/share/php/php-gettext/:/usr/share/php/php-php-gettext/:/usr/share/javascript/:/usr/share/php/tcpdf/:/usr/share/doc/phpmyadmin/:/usr/share/php/phpseclib/ php_admin_value mbstring.func_overload 0 </IfModule> </Directory> # Authorize for setup <Directory /usr/share/phpmyadmin/setup> <IfModule mod_authz_core.c> <IfModule mod_authn_file.c> AuthType Basic AuthName "phpMyAdmin Setup" AuthUserFile /etc/phpmyadmin/htpasswd.setup </IfModule> Require valid-user </IfModule> </Directory> # Disallow web access to directories that don't need it <Directory /usr/share/phpmyadmin/templates> Require all denied </Directory> <Directory /usr/share/phpmyadmin/libraries> Require all denied </Directory> <Directory /usr/share/phpmyadmin/setup/lib> Require all denied </Directory>
Puis ensuite on peut redémarrer le service Apache2 :
sudo systemctl restart apache2
Enfin vous pouvez vérifier que PhpMyAdmin est bien installé en vous rendant depuis un navigateur sur l’url : http://votre-adresse-ip/phpmyadmin
Vos accès sont les mêmes que ceux de votre base de données Mysql ou MariaDB.
Attention si vous avez refusé la connexion en tant qu’utilisateur root, il faudra créer et utiliser un autre compte utilisateur.
Installer Npm sur Debian 11
Node Package Manager (NPM), est un gestionnaire de paquets pour Javascript (Node.js). Dans cette procédure, je vais vous montrer comment installer Npm sur une machine Debian 11, de deux manières différentes. Nous allons voir l’installation via les dépôts Debian 11 et depuis les dépôts Node. Npm est un outil très pratique pour les développeurs, car il leur permet de se focaliser sur leurs codes, en leur permettant d’importer rapidement les dépendances dont ils peuvent avoir besoin.
Prérequis :
- Une machine Debian 11
Installer Npm sur Debian 11 :
Il y a plusieurs manières d’installer Npm sur une machine Debian, dans cette procédure nous allons voir l’installation de Npm via les dépôts Debian ainsi que via les dépôts de Node.
Dans les deux cas avant de procéder à l’installation de Npm, nous allons d’abord mettre à jour notre gestionnaire de paquets :
sudo apt update
Installer Npm à l’aide des dépôts de Debian :
Nous allons télécharger Npm et Node.JS depuis les dépôts Debian :
sudo apt install nodejs npm -y
Ensuite nous pouvons vérifier que NodeJs est bien installé sur la machine :
nodejs --version
Puis nous pouvons vérifier que Npm c’est également bien installer sur la machine :
npm --version
Installer Npm via les dépôts Node :
Pour récupérer les dépôts de Node, il vous suffit d’exécuter cette commande :
curl -sL https://deb.nodesource.com/setup_12.x | sudo bash -
Puis vous pouvez télécharger Nodejs et Npm :
sudo apt install nodejs npm -y
Enfin après avoir téléchargé NodeJs et Npm, vous pouvez vérifier qu’ils ont bien été installés à l’aide des commandes suivantes :
nodejs --version npm --version
Si ces deux commandes vous retournent la version de chacun des paquets alors ils ont bien été installés !
Installer l’outil de développement Npm sur Debian 11:
L’outil de développement est utilisé pour compiler et installer des modules complémentaires.
L’installation est très simple, il suffit de télécharger le paquet build-essential
sudo apt install build-essential -y
Sources :
https://www.npmjs.com/
https://nodejs.org/en/docs/
Mettre à jour Nodejs :
Pour mettre à jour Nodejs, nous allons utiliser le module n :
sudo npm install n -g
Ensuite pour passer sur une version stable :
n stable
Pour passer sur la dernière version :
n latest
Installer MariaDB sur Debian 11
Mariadb est Système de Gestion de Base de Données (SGBD) communautaire de Mysql. Dans cette procédure, nous allons voir comment installer MariaDB sur une machine Debian 11.
Prérequis pour installer MariaDB sur Debian 11 :
- Une machine Debian 11 (Bullseye)
Installer MariaDB sur Debian 11 :
Avant de commencer l’installation de Mariadb sur notre machine Debian, nous allons d’abord mettre à jour la liste des paquets de notre machine.
sudo apt update
Puis nous allons installer les paquets serveurs et clients de Mariadb :
sudo apt install mariadb-server mariadb-client -y
Ensuite nous allons activer le service Mariadb et le démarrer
sudo systemctl enable mariadb sudo systemctl start mariadb
Puis nous vérifions que le service est bien démarré et actif :
sudo systemctl status mariadb
Une fois que ces étapes sont réalisées, nous pouvons configurer Mariadb.
mysql_secure_installation
Enter current password for root (enter for none): Change the root password? [Y/n] Y New password: votre_mdp Re-enter new password: votre_mdp Remove anonymous users? [Y/n] Y Disallow root login remotely? [Y/n] Y Remove test database and access to it? [Y/n] Y Reload privilege tables now? [Y/n] Y
Après avoir rempli le questionnaire nous pouvons nous connecter au SGBD à l’aide de l’utilisateur root et du mot de passe choisis précédemment.
mariadb -u root -p
Ensuite votre mot de passe vous sera demandé puis vous allez avoir la possibilité d’exécuter vos requêtes SQL.
La première chose à faire est de créer un autre utilisateur qui aura moins de permissions que l’utilisateur root.
CREATE USER 'utilisateur'@'localhost' IDENTIFIED BY 'mot_de_passe_utilisateur';
« utilisateur » est le nom d’utilisateur
« mot_de_passe_utilisateur » est le mot de passe de l’utilisateur
Ensuite il faudra attribuer des permissions à votre utilisateur à l’aide de la requête GRANT (exemple à adapter en fonction de vos besoins) :
GRANT ALL PRIVILEGES ON *.* to 'utilisateur'@'localhost';
Enfin on applique les privilèges :
FLUSH PRIVILEGES;
Et enfin on peut quitter la console Mariadb :
EXIT;
Installer ZSH sur Debian 11
ZSH est un Shell interactif qui vus permet de gagner du temps lors de l’utilisation de ce Shell. Dans cette procédure, je vais vous montrer comment installer ZSH sur une machine Debian 11 (Bullseye). Ainsi que l’installation de Oh My Zsh qui nous permettra d’installer des thèmes et des plugins afin de rendre notre Shell dynamique. D’autres shell dynamiques existent (comme Fish) mais sont moins réputés que ZSH.
Prérequis :
- Avoir une machine sous le système d’exploitation Debian 11 (Bullseye)
- Avoir les permissions root sur la machine
Installer ZSH sur Debian 11:
Avant de commencer l’installation de ZSH, nous allons d’abord mettre à jours la liste des paquets :
apt update
Ensuite vous pouvez télécharger le paquet zsh :
apt install zsh -y
Puis nous allons changer le Shell utilisé par l’utilisateur actuel (cette commande doit être exécuté sur tous les utilisateurs de la machine afin d’avoir ZSH) :
chsh -s $(which zsh)
Fermer le terminal actuel et ouvrer un nouveau terminal pour que ZSH soit utilisé.
Installer OMZ (OH MY ZSH) sur Debian 11 :
Nous allons installer OH MY ZSH qui permet d’ajouter des thèmes et des plugins dans ZSH.
Pour commencer, nous allons d’abord installer git et curl :
apt install curl git
Puis nous allons installer OMZ :
sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
Configuration de OMZ sur Debian 11 :
Les configurations de OMZ se font dans le fichier ~/.zshrc
Pour changer le thème (liste de thèmes OMZ), modifier la ligne :
nano ~/.zshrc
ZSH_THEME="robbyrussell"
# Par
ZSH_THEME="nouveau_theme"
Puis nous allons installer les plugins d’autocomplétion ainsi que de surlignage :
git clone https://github.com/zsh-users/zsh-autosuggestions.git $ZSH_CUSTOM/plugins/zsh-autosuggestions
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git $ZSH_CUSTOM/plugins/zsh-syntax-highlighting
Ensuite nous ajoutons les plugins dans la configurations de zsh (~/.zshrc) en modifiant la ligne :
nano ~/.zshrc
plugins=(git)
# par
plugins=(git zsh-autosuggestions zsh-syntax-highlighting)
Puis après avoir redémarrer le terminal, nous aurons les fonctionnalités des plugins.
D’autres plugins ZSH sont disponibles ici : https://github.com/ohmyzsh/ohmyzsh/wiki/Plugins en procédant de la même manière qu’avec l’installation des plugins précédemment.
Vous pouvez également mettre à jour votre Shell avec la commande suivant :
omz update
Pour retirer ZSH de Debian il faut exécuter cette commande :
apt --purge remove zsh && chsh -s $(which "BASH")
Créer un serveur Lamp (Apache MariaDB PHP) + PhpMyAdmin Debian
Dans cette procédure sera présenté étape par étape comment créer un serveur Lamp (Linux, Apache, Mariadb, Php) avec PhpMyAdmin sur une machine Debian 11. Après avoir suivis cette procédure vous aurez votre propre serveur Lamp sur votre machine Debian.
Prérequis :
- une machine Debian 11
Installation :
Mise à jour du système :
apt update && apt full-upgrade -y
Installation des services :
apt install apache2 mariadb-server mariadb-client php libapache2-mod-php php-cli php-mysql php-zip php-curl php-xml wget -y
Apache2 :
Après l’installation des paquets, le service apache2 est disponible depuis un navigateur Web :
http://[ServerIP]/
La page ci-dessous montre l’installation réussie :
Php :
Après l’installation des paquets php est disponible, pour vérifier que le service fonctionne il faudra créer un fichier php et le tester :
Créer le fichier php :
echo "<?php phpinfo(); ?>" > /var/www/html/test.php
http://[ServerIP]/test.php
Une page ressemblent à celle ci-dessous correspondra une installation réussis :
MariaDB :
Installation et configuration des accès à la base de données :
mysql_secure_installation
Enter current password for root (enter for none): Change the root password? [Y/n] Y New password: Re-enter new password: Remove anonymous users? [Y/n] Y Disallow root login remotely? [Y/n] Y Remove test database and access to it? [Y/n] Y Reload privilege tables now? [Y/n] Y
Connexion avec l’utilisateur root à la base de données :
mysql -u root -p
Saisir votre mot de passe de l’utilisateur root de MariaDB
Enter password: Welcome to the MariaDB monitor. Commands end with ; or \g. Your MariaDB connection id is 64 Server version: 10.5.11-MariaDB-1 Debian 11 Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
Création d’un utilisateur et attribution de droits sur la base :
CREATE USER 'user'@'localhost' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON *.* to 'user'@'localhost'; FLUSH PRIVILEGES; EXIT;
Si vous avez un soucis lors de l’installation de MariaDB avec un conteneur LXC vous pouvez voir ce post StackOverflow.
PhpMyAdmin :
Téléchargement de l’archive de PhpMyAdmin :
DATA="$(wget https://www.phpmyadmin.net/home_page/version.txt -q -O-)" URL="$(echo $DATA | cut -d ' ' -f 3)" VERSION="$(echo $DATA | cut -d ' ' -f 1)" wget https://files.phpmyadmin.net/phpMyAdmin/${VERSION}/phpMyAdmin-${VERSION}-all-languages.tar.gz
Extraction de l’archive :
tar xvf phpMyAdmin-${VERSION}-all-languages.tar.gz
Déplacer le dossier dans le répertoire : /usr/share/
mv phpMyAdmin-*/ /usr/share/phpmyadmin
Création d’un emplacement temporaire pour les fichiers PhpMyAdmin :
mkdir -p /var/lib/phpmyadmin/tmp chown -R www-data:www-data /var/lib/phpmyadmin
Création d’un emplacement pour les fichier de configuration de PhpMyAdmin :
mkdir /etc/phpmyadmin/
Copie d’un fichier de configuration :
cp /usr/share/phpmyadmin/config.sample.inc.php /usr/share/phpmyadmin/config.inc.php
Edition du nouveau fichier de configuration et définir une phrase secrète :
Avec Nano ou Vim
nano /usr/share/phpmyadmin/config.inc.php vim /usr/share/phpmyadmin/config.inc.php
$cfg['blowfish_secret'] = 'xxxxxxxxxxxxxxxx';
Configuration d’un emplacement temporaire :
$cfg['TempDir'] = '/var/lib/phpmyadmin/tmp';
Création d’un VirtualHost pour accèder à PhpMyAdmin avec Nano ou Vim :
nano /etc/apache2/conf-enabled/phpmyadmin.conf Ou vim /etc/apache2/conf-enabled/phpmyadmin.conf
Coller cette configuration :
Alias /phpmyadmin /usr/share/phpmyadmin <Directory /usr/share/phpmyadmin> Options SymLinksIfOwnerMatch DirectoryIndex index.php <IfModule mod_php5.c> <IfModule mod_mime.c> AddType application/x-httpd-php .php </IfModule> <FilesMatch ".+\.php$"> SetHandler application/x-httpd-php </FilesMatch> php_value include_path . php_admin_value upload_tmp_dir /var/lib/phpmyadmin/tmp php_admin_value open_basedir /usr/share/phpmyadmin/:/etc/phpmyadmin/:/var/lib/phpmyadmin/:/usr/share/php/php-gettext/:/usr/share/php/php-php-gettext/:/usr/share/javascript/:/usr/share/php/tcpdf/:/usr/share/doc/phpmyadmin/:/usr/share/php/phpseclib/ php_admin_value mbstring.func_overload 0 </IfModule> <IfModule mod_php.c> <IfModule mod_mime.c> AddType application/x-httpd-php .php </IfModule> <FilesMatch ".+\.php$"> SetHandler application/x-httpd-php </FilesMatch> php_value include_path . php_admin_value upload_tmp_dir /var/lib/phpmyadmin/tmp php_admin_value open_basedir /usr/share/phpmyadmin/:/etc/phpmyadmin/:/var/lib/phpmyadmin/:/usr/share/php/php-gettext/:/usr/share/php/php-php-gettext/:/usr/share/javascript/:/usr/share/php/tcpdf/:/usr/share/doc/phpmyadmin/:/usr/share/php/phpseclib/ php_admin_value mbstring.func_overload 0 </IfModule> </Directory> # Authorize for setup <Directory /usr/share/phpmyadmin/setup> <IfModule mod_authz_core.c> <IfModule mod_authn_file.c> AuthType Basic AuthName "phpMyAdmin Setup" AuthUserFile /etc/phpmyadmin/htpasswd.setup </IfModule> Require valid-user </IfModule> </Directory> # Disallow web access to directories that don't need it <Directory /usr/share/phpmyadmin/templates> Require all denied </Directory> <Directory /usr/share/phpmyadmin/libraries> Require all denied </Directory> <Directory /usr/share/phpmyadmin/setup/lib> Require all denied </Directory>
Redémarrer le service Apache2 :
sudo systemctl restart apache2
Si vous avez un soucis avec Apache2 et que vous utilisez des conteneur LXC vous pouvez utilisez ce Post du forum Proxmox.
Accès à PhpMyAdmin :
http://[ServerIP]/phpmyadmin
Les identifiants / mots de passe sont les mêmes que dans Mariadb.
Après avoir suivi cette procédure, je vous conseille de créer des Virtualhost apache afin de limiter les accès a vos sites uniquement par des noms de domaines, ainsi que l’ajout d’un firewall tel que Ufw pour limiter les accès a vos services.
How to Install Go on Debian 12
Introduction
Go, or Golang, is a relatively new, open-source language created by Google. Its purpose is to streamline software development and enable users to create simple and reliable apps.
As a modern language, Go offers memory allocation, concurrency support, garbage collection, coordination avoidance, etc.
This article explains how to install Go on Debian 12 in a few simple steps.
Prerequisites
- Debian system (this tutorial uses Debian 12).
- A sudo user.
- Access to the command line.
How to Install Go on Debian 12
Before starting the installation, ensure the Debian server is up to date. Update the repository with the following:
sudo apt update -y
Step 1: Download Go
To start the installation process:
1. Visit the Go downloads page.
2. Click the Linux box under Featured downloads to start the download.
Note: Use wget or curl to download Go without accessing the browser.
Step 2: Extract Files
Extract files to the /usr/local directory. To do that, take the following steps:
cd ~/Downloads
2. Run the following command to extract files:
sudo tar -C /usr/local -xzf go1.22.5.linux-amd64.tar.gz
The command doesn't print any output. However, tar extracts the specified file (go1.19.2.linux-amd64.tar.gz) to the desired directory.
Step 3: Set the Environment
To set the environment variable, add /usr/local/go/bin to PATH.
Take the following steps:
1. Access .profile in Vim or another text editor.
vim .profile
2. At the end of the file, paste the following lines:
export PATH=$PATH:/usr/local/go/bin
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
3. Save and close the file.
4. Reload your shell configuration to apply the changes with:
source ~/.profile
The command has no output.
Note: To install Go system-wide, edit /etc/profile. To install it for the current user, access $HOME/.profile.
GrubEFIReinstall
Starting with Windows 8 most Desktop PC have EFI as firmware instead of the legacy BIOS. If your EFI based PC is not booting Debian, here are some ways to reinstall grub-efi, the bootloader used by Debian on these PCs.
To reinstall grub, you need either a live CD/USB to access your current system, or you can use the rEFInd boot manager on a live CD/USB to boot your current system.
Using A Live CD/USB To Fix Your Current System
(The following procedure is described in greater detail here.)
-
Boot (using UEFI) into a live system, such as a DebianLive CD/USB or the Debian installer in rescue mode. You can verify that the system has booted using UEFI by checking for the existence of the directory /sys/firmware/efi or by running efibootmgr.
- If the directory /sys/firmware/efi/efivars is empty, you need to boot the rescue system including the kernel option "efi=runtime" and mount the EFI variables before proceeding:
# mount -t efivarfs none /sys/firmware/efi/efivars
- Mount the broken system somewhere into the running filesystem. The exact details of how to do this depend on the particulars of your installation.
For example, for a system with an EFI partition on /dev/sdb1, an unencrypted /boot partition on /dev/sdb2, and an unencrypted / partition on /dev/sdb3, do:
# mount /dev/sdb3 /mnt # mount /dev/sdb2 /mnt/boot # mount /dev/sdb1 /mnt/boot/efi
Another example - for a system with an EFI partition on /dev/sdb1 and / partition on /dev/sdb2, do:
# mount /dev/sdb2 /mnt/ # mount /dev/sdb1 /mnt/boot/efi
In case of a LUKS-encrypted / partition, please follow this guide: GrubEFIReinstallOnLUKS.
- Bind mount various virtual filesystems:
# for i in /dev /dev/pts /proc /sys /sys/firmware/efi/efivars /run; do mount -B $i /mnt/$i; done
The mount executable supplied with busybox does not support the -B option, use "mount -o bind" in this case. - Chroot into the broken system:
# chroot /mnt
- Reinstall GRUB to the appropriate disk (without partition number):
# grub-install /dev/sdb
- Generate the GRUB configuration file:
# update-grub
-
Exit the chroot environment (<CTRL>-D).
- If everything worked, reboot.
Using the rEFInd rescue media
At the author's web page, http://www.rodsbooks.com/refind/getting.html, you will find updated direct links to all sorts of packaging. To boot from a rescue media, select either the CD ISO image or the image for USB sticks. Most firmware offers the choice nowadays. If choosing the latter, make sure to follow the instructions in the README. It is recommended to read the author's web pages to get a better understanding of what you are doing.
Boot your computer with the Refind media
rEFInd will parse your hard drive for installed kernels, and provide you a graphic menu to boot them. Choose your Linux Kernel and boot it.
Reinstalling grub-efi on your hard drive
Check that the computer booted in computer in EFI mode:
[ -d /sys/firmware/efi ] && echo "EFI boot on HDD" || echo "Legacy boot on HDD" should return "EFI boot on HDD".
After starting a root shell (if you boot from a live media, you should start a chroot shell instead, as explained here) check that your EFI system partition (most probably /dev/sdb1) is mounted on /boot/efi. If the /boot/efi directory does not exist, you will need to create it.
mount /dev/sdb1 /boot/efi
Reinstall the grub-efi package
apt-get install --reinstall grub-efi
Put the Debian bootloader in /boot/efi and create an appropriate entry in the computer NVRAM
grub-install
Re create a grub config file based on your disk partitioning schema
update-grub
You should check afterwards that:
Check 1. the bootloader is existing in /boot/efi/EFI/debian/grubx64.efi
file /boot/efi/EFI/debian/grubx64.efi /boot/efi/EFI/debian/grubx64.efi: PE32+ executable (EFI application) x86-64 (stripped to external PDB), for MS Windows
Check 2. the NVRAM entry was properly created.
efibootmgr --verbose | grep debian
You can now reboot, and Grub should greet you.
Troubleshooting
If after this steps you're not booting, the EFI of your PC might have some bugs.
Problem1: Weak EFI implementation only recognizes the fallback bootloader
The UEFI firmware refuses to boot the debian/grubx64.efi bootloader, and so we have to hijack the UEFI fallback boot loader. See http://mjg59.livejournal.com/138188.html for details.
Using Debian installer in rescue mode, /dev/sdb1 being the FAT32 ESP partition, /dev/sdb2 the root partition
mkdir /target mount /dev/sdb2 /target mount /dev/sdb1 /target/boot/efi for i in /sys /proc /dev; do mount --bind $i /target$i; done chroot /target
cd /boot/efi/EFI mkdir boot cp debian/grubx64.efi boot/bootx64.efi exit for i in /sys /proc /dev; do umount /target$i; done umount /target/boot/efi umount /target
Once booted into your normal Debian, tell grub to ensure the fallback boot loader up to date. To do that, run the following:
echo "grub-efi-amd64 grub2/force_efi_extra_removable boolean true" | sudo debconf-set-selections
Note: The above command will permanently hijack the fallback bootloader, which might be undesirable in dual-boot setups.
Problem2: EFI boot entries disappear after reboot
The UEFI firmware did not create a proper boot entry in NVRAM. This has been seen in a Lenovo Thinkcenter M92Z. The symptom for this will be a missing HD path after the Debian entry in the efibootmgr --verbose output.
BootCurrent: 0024 Timeout: 0 seconds BootOrder: 0024,0022,0023,0016,0000,0001 Boot0000* debian Vendor(99e275e7-75a0-4b37-a2e6-c5385e6c00cb,) Boot0016* Generic Usb Device Vendor(99e275e7-75a0-4b37-a2e6-c5385e6c00cb,) Boot0022* UEFI: IPv4 Intel(R) 82579LM Gigabit Network Connection ACPI(a0341d0,0)PCI(19,0)MAC(d43d7e6d8bfc,0)IPv4(0.0.0.0:0<->0.0.0.0:0,0, 0AMBO Boot0023* UEFI: IPv6 Intel(R) 82579LM Gigabit Network Connection ACPI(a0341d0,0)PCI(19,0)MAC(d43d7e6d8bfc,0)030d3c000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000AMBO Boot0024* UEFI: Generic Flash Disk 8.00 ACPI(a0341d0,0)PCI(1d,0)USB(1,0)USB(1,0)HD(1,800,2a5f,02f23208-1aa9-4b6c-b6e1-8155390eb9db)AMBO
You can then try to install rEFInd as your bootloader in the hard drive, following the steps at this gist: https://gist.github.com/EmmanuelKasper/9590327.
Failover avec Hearbeat, rsync et réplication mysql
Pour mieux expliquer ce TP, j'ai pris un exemple concret: une installation de Wordpress, qui nous permettra de tester la réplication des fichiers et de la BDD !
Prérequis :
- Installer Debian 10 et ses mises à jour
- Cloner la VM pour en créer une autre, identique
- Renommer le clone /etc/hostname
- Configurer les IP statiques sur les 2 VM
- Choisir une IP virtuelle pour le cluster
Installation d'Heartbeat
(a faire sur chaque node)
apt install heartbeat
Création du fichier de configuration:
nano /etc/heartbeat/ha.cf
Ajoutez les paramètres suivants:
# Indication du fichier de log
logfile /var/log/heartbeat.log
# Les logs heartbeat ne seront pas gérés par syslog
logfacility none
# On liste tous les membres de notre cluster heartbeat (par les noms de préférences)
node NOM_DU_NODE1
node NOM_DU_NODE2
# On défini la périodicité de controle des noeuds entre eux (en seconde)
keepalive 1
# Au bout de combien de seconde un noeud sera considéré comme "mort"
deadtime 10
# Quelle carte résau utiliser pour les broadcasts Heartbeat (ens33 dans mon cas)
bcast ens18
# Adresse du routeur pour vérifier la connexion au net
ping 10.10.1.254
# Rebascule-t-on automatiquement sur le primaire si celui-ci redevient vivant ? oui*
auto_failback yes
Création du fichier de clé:
nano /etc/heartbeat/authkeys
Ajoutez les paramètres suivants:
auth 1
1 sha1 UneCle
Édition des droits sur le fichier:
chmod 600 /etc/heartbeat/authkeys
Création du fichier haressources:
nano /etc/heartbeat/haresources
On indique le nom du node primaire et son IP
NODE1 10.10.1.127
Démarrage d'Heartbeat:
systemctl start heartbeat
Si tout se passe bien, sur le premier node l'IP virtuel apparaît
Installation de Wordpress
(Vous pouvez passer cette étape si vous avez votre propre site)
Idem, à faire sur les deux nodes
Installation du serveur LAMP:
apt install apache2 mariadb-server php libapache2-mod-php php-cli php-common php-curl php-gd php-json php-mbstring php-mysql php-xml php-xmlrpc php-soap php-intl php-zip
Création de la base de donnée:
mysql -u root -p
CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
GRANT ALL ON wordpress.* TO 'wordpress_user'@'localhost' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
EXIT;
Téléchargement et décompression de WordPress:
cd /tmp
wget https://wordpress.org/latest.tar.gz
tar xzvf latest.tar.gz
Création du fichier .htaccess
touch /tmp/wordpress/.htaccess
Copie du fichier config exemple en fichier config :
cp /tmp/wordpress/wp-config-sample.php /tmp/wordpress/wp-config.php
Copie du dossier temporaire vers le dossier définitif :
cp -a /tmp/wordpress/. /var/www/html/wordpress
Donner les permissions au dossier /wordpress :
chown -R www-data:www-data /var/www/html/wordpress
Configurer le fichier de config Wordpress :
nano /var/www/html/wordpress/wp-config.php
Remplacer :
- database_name_here
- user_name_here
- password_here
- régler la collation de la base de donnée comme configurée plus tôt
Redémarrer Apache, se connecter via navigateur, vérifier que le site wordpress est accessible. (Sur les deux Nodes)
Ne finissez pas la configuration de WordPress !
Réplication du dossier de l’application avec Rsync
Synchronisation des dossiers wordpress avec Rsync
Installation de Rsync (par defaut il y est deja, au cas ou)
apt install rsync
Test de Rsync à partir du Node secondaire :
rsync --delete -avzhe ssh root@10.10.1.167:/var/www/html/wordpress/ /var/www/html/wordpress/
Mise en place du login SSH sans mot de passe, par certificat, sur le node secondaire :
ssh-keygen -t rsa -b 2048
ssh-copy-id -i /root/.ssh/id_rsa.pub root@10.10.1.158
Test de la connexion sans mot de passe
ssh root@10.10.1.158
Vous avez accès directement au shell sans rentrer de mot de passe
Automatisation de la synchro entre les deux Nodes :
Créer un script /scripts/rsync.sh
Y coller la commande rsync précédente
Si besoin on ajoute les droits d’exécution:
chmod +x rsync.sh
On ajoute la cron:
crontab -e
On teste en créant un fichier dans le dossier wordpress sur le Node principal, il devrait être créé sur le Node secondaire moins d’une miute après.
On le supprime et on vérifie qu’il soit bien supprimé.
Réplication des bases de donnée :
Sur le Node principal (base Master) :
On active les binary logs
mysql -u root -p
SET sql_log_bin = 1;
exit
A la fin du fichier /etc/mysql/my.cnf
an ajoute les paramètres suivants :
[mariadb]
log-bin
server_id=1
log-basename=master1
On redémarre le service MySQL
systemctl restart mysql
On crée un utilisateur pour la réplication :
CREATE USER 'replication_user'@'%' IDENTIFIED BY 'repli_password';
GRANT REPLICATION SLAVE ON *.* TO 'replication_user'@'%';
Sur le Node secondaire :
Même principe, a la fin du fichier /etc/mysql/my.cnf
an ajoute les paramètres suivants (pensez à changer l'ID):
[mariadb]
log-bin
server_id=2
log-basename=master1
On redémarre le service MySQL
systemctl restart mysql
On configure la base en esclave :
mysql -u root -p
CHANGE MASTER TO
MASTER_HOST='10.10.1.158',
MASTER_USER='replication_user',
MASTER_PASSWORD='repli_password',
MASTER_PORT=3306,
MASTER_CONNECT_RETRY=10;
On démarre le mode esclave :
START SLAVE;
On vérifie l’état de la synchronisation :
SHOW SLAVE STATUS;
Si la synchronisation est fonctionnelle, on peut tester en terminant la configuration sur le Node primaire. Celle ci devrait s’appliquer automatiquement sur le Node secondaire.
On crée un article Wordpress, il devrait être dupliqué sur le second serveur.
Voila, votre site web est répliqué !
rsync : Synchronisation de Dossiers
Introduction
rsync est un outil qui permet de sauvegarder par copies vos données. Il copie tous les fichiers sources vers la destination choisie, puis ne met à jour que ceux qui ont été modifiés ou ajoutés, offrant ainsi un gain de temps. rsync peut aussi être utilisé à travers un réseau.
Installation
apt-get update && apt-get install rsync
Utilisation
Syntaxe de base
rsync [option] /source /destination
Exemples :
- Copie intégralement le fichier ou répertoire source :
rsync -av /source /destination
- Copie seulement le contenu du répertoire source :
rsync -av /source/ /destination
Téléchargement distant par SSH
rsync --partial --progress --rsh=ssh [source] [user]@[host]:[destination]
Exemple :
rsync --partial --progress --rsh=ssh fichier nom_user@hostName:/repertoire_receveur/
Options principales
Option | Action |
---|---|
-r | Visite récursive des répertoires |
-l | Copie les liens symboliques |
-p | Préserve les permissions |
-t | Préserve les dates |
-g | Préserve le groupe |
-o | Préserve le propriétaire (root uniquement) |
-z | Compresse les fichiers pour un meilleur transfert |
Exemple de sauvegarde
rsync -r -t -x -v --progress -l -s \ --filter "- /.cache/" \ --filter "- /.thumbnails/" \ /home/utilisateur/ /media/DisqueExterne/repertoire_sauvegarde/
Interfaces graphiques pour rsync
- grsync : une interface simple et conviviale
- luckybackup : disponible à partir de Squeeze uniquement
Configure Samba Share on Debian
Normally when you launch the system’s file manager on Linux/Windows system, you will see network shares advised on your network. These shares are only allowed if remote users are connected to the machine.
Samba is a free software that enables one to share files across the network using the SMB(Server Message Block) protocol. This tool was developed by Andrew Tridgell in December 1991 and January 1992.
The cool features associated with Samba are:
- It is easy and quick to deploy
- It offers secured data transfer
- Multichanel technology
- Message signing-with digital signing – users who receive the data packets are assured of the origin point authenticity.
- Allows concurrent operations.(simultaneous access to the files)
- It offers good performance under heavy loads.
- Samba supports POSIX extensions for CIFS/SMB
- Supports NetBIOS over TCP/IP (NBT)
- It supports the NT-style printing service (SPOOLSS)
Samba is supported on various platforms such as Windows and Unix operating systems i.e Solaris, Linux, AIX, and BSD variants.
This guide will equip you with the required knowledge on how to configure Samba Share on Debian.
1 – Install Samba Packages
We will start off by installing Samba on Debian Linux system. This is easy since it is available in the default Debian repositories.
sudo apt update
sudo apt install samba smbclient cifs-utils
Dependency tree:
...
The following NEW packages will be installed:
attr cifs-utils ibverbs-providers keyutils libcephfs2 libgfapi0 libgfrpc0
libgfxdr0 libglusterfs0 libibverbs1 librados2 librdmacm1
python3-cffi-backend python3-cryptography python3-dnspython python3-gpg
python3-markdown python3-pygments python3-requests-toolbelt python3-samba
python3-tdb python3-yaml samba samba-common samba-common-bin
samba-dsdb-modules samba-vfs-modules smbclient tdb-tools
0 upgraded, 29 newly installed, 0 to remove and 0 not upgraded.
Need to get 24.4 MB of archives.
After this operation, 84.7 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
2 – Set the Samba Global settings
The Samba configuration file is located under /etc/samba/smb.conf. In this file, there are several changes we need to make. Although Debian is intelligent enough to provide default configurations, it is also good to verify this.
Open the file using a preferred editor.
sudo nano /etc/samba/smb.conf
In the file, make make adjustments as you deem fit, example for workgroup.
workgroup = WORKGROUP
3 – Create Shared Samba Directory
sudo mkdir /public
sudo mkdir /private
Now edit the Samba conf and add the two directories.
sudo nano /etc/samba/smb.conf
At the end of the file, add the shares and authentication methods to access it.
[public]
comment = Public Folder
path = /public
writable = yes
guest ok = yes
guest only = yes
force create mode = 775
force directory mode = 775
[private]
comment = Private Folder
path = /private
writable = yes
guest ok = no
valid users = @smbshare
force create mode = 770
force directory mode = 770
inherit permissions = yes
4 – Create Samba User and Group
We need the Samba share user group to access the Private share as specified in the conf above. So we will create the group as below.
sudo groupadd smbshare
Add the necessary permissions for the private share.
sudo chgrp -R smbshare /private/
sudo chgrp -R smbshare /public
Set the right directory permissions.
sudo chmod 2770 /private/
sudo chmod 2775 /public
In the above command, the value 2 at the beginning, stands for the SGID bit. This allows newly created files to inherit the parent group.
Next, create a no login local user to access the private share.
sudo useradd -M -s /sbin/nologin sambauser
Add the user to the Samba share group created above.
sudo usermod -aG smbshare sambauser
Now create an SMB password for the user.
sudo smbpasswd -a sambauser
Enable the created account:
sudo smbpasswd -e sambauser
5 – Verify the Samba configuration
Once changes have been made to the config file, it is recommended that you test it using the below command:
sudo testparm
Execution output:
Load smb config files from /etc/samba/smb.conf
Loaded services file OK.
Weak crypto is allowed
Server role: ROLE_STANDALONE
Press enter to see a dump of your service definitions
# Global parameters
[global]
interfaces = 192.168.205.0/24 eth0
log file = /var/log/samba/log.%m
logging = file
map to guest = Bad User
max log size = 1000
obey pam restrictions = Yes
pam password change = Yes
panic action = /usr/share/samba/panic-action %d
passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .
passwd program = /usr/bin/passwd %u
server role = standalone server
unix password sync = Yes
usershare allow guests = Yes
idmap config * : backend = tdb
.....
[public]
comment = Public Folder
force create mode = 0775
force directory mode = 0775
guest ok = Yes
guest only = Yes
path = /public
read only = No
[private]
comment = Private Folder
force create mode = 0770
force directory mode = 0770
inherit permissions = Yes
path = /private
read only = No
valid users = @smbshare
The above output shows that everything is configured appropriately. Now proceed as below.
Create demo files in the Samba shares:
sudo mkdir /private/demo-private /public/demo-public
sudo touch /private/demo1.txt /public/demo2.txt
Restart the Samba service for the changes to apply.
sudo systemctl restart nmbd
If you have a firewall running, you need to allow remote access from the specified IP range:
sudo ufw allow from 192.168.205.0/24 to any app Samba
SSH - run script or command at login
There a multiple use cases to run a script on login. Configuration, starting services, logging, sending a notification, and so on. I want to show you different ways to do so.
Example script
The example script will notify me via push notification on my smartphone as soon as a new SSH connection is established. You can use a simple command or a script, and I will use a script for this blog post.
/path/to/script/notify-at-login.sh
#!/bin/bash
# 1 - Script without output!
# IMPORTANT: Script with output break non-interactive sessions (scp, rsync, etc)
curl -d "\"$SSH_CONNECTION\" - \"$USER\" logged in" ntfy.sh/reallyecurestringfornotifications >/dev/null 2>&1
# If you only want to run the script for an interactive SSH login and need the output displayed, place the script right after section 2 and remove the redirect.
# 2 - Check if session is non-interactive (remote command, rsync, scp, etc)
if [[ $SSH_ORIGINAL_COMMAND ]]; then
eval "$SSH_ORIGINAL_COMMAND"
exit
fi
# 3 - choose your favorite shell for the SSH session
/bin/bash
- Remember to make it executable:
sudo chmod +x /path/to/script/notify-at-login.sh
Side note: I am using ntfy to send push notifications to my smartphone. In this example, the push notification would look this:
92.160.50.201 40248 195.21.0.14 22 - <user> logged in
Output on non-interactive connections
Just a reminder that you have to avoid any output of your script or command on non-interactive connections like rsync. Either prevent output from being displayed for non-interactive connections or all connections. The example script shows you one way to do so.
ForceCommand
I prefer this method, and had been working pretty well so far. The user will run the command and it can’t really be avoided by the client.
- Use the
ForceCommand
option in your/etc/ssh/sshd_config
file to run the script: ForceCommand /path/to/script/notify-at-login.sh
ForceCommand ignores any command or script supplied by the client and ~/.ssh/rc by default.
PAM_exec
Put the script into a new directory /etc/pam_scripts
, set the directory’s permission to 0755
and the owner and group must be root
. The files permissions are 0700
, must be executable and the owner and group must be root
as well.
- Directory:
sudo mkdir /etc/pam_scripts
sudo chmod 0755 /etc/pam_scripts
sudo chown root:root /etc/pam_scripts
- Script:
sudo chmod 0700 /etc/pam_scripts/notify-at-login.sh
sudo chown root:root /etc/pam_scripts/notify-at-login.sh
- Enable
UsePAM
in the/etc/ssh/sshd_config
: UsePAM yes
- Tell PAM to run the script at SSH login by adding the following line to
etc/pam.d/sshd
: session required pam_exec.so /etc/pam_scripts/notify-at-login.sh
All scripts added to the /etc/pam_scripts/
directory will be run as root
at login.
Shell startup & sshrc file
You can run the script by your preferred startup file (.profile
/ .bashrc
, etc) or use the SSH-specific profiles that run additionally before the user shell is loaded.
- For all users:
/etc/ssh/sshrc
# runs only if there is no user-specific configuration file~/.ssh/rc
- Per user configuration in home dir:
~/.ssh/rc
~/.ssh/rc
Commands in this file are executed by ssh when the user
logs in, just before the user's shell (or command) is
started. See the sshd(8) manual page for more information.
- Run the script via the startup file by adding the following line to it:
. /path/to/script/notify-at-login.sh
Both the shell startup and sshrc files will be run by the user.
Side note: if security is a concern - like a login notification - it is not recommended to use this method. Profile config files can be avoided by ssh user@server bash --norc --noprofile
and ~/.ssh/rc
can be changed by the user after the first login.