Logo carnetderootxzz@carnetderoot.net"La simplicité est la sophistication suprême" - Léonard De Vinci
dimanche 27 juin 2021

:: CloudSHell2 - Installation d'Archlinux ::

Introduction

Toutes les opérations décrites ci-dessous ont été faites à partir d'un portable sous Archlinux et du reader/writer eMMC se branchant sur le port SD (via un adaptateur micro-SD).

La commande lsblk permet de récupérer le nom du périphérique, ici /dev/sdb :

$ lsblk
NAME            MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
[...]
sdb               8:16   1 116,5G  0 disk

Préparation du module eMMC

Remise à zéro

$ sudo dd if=/dev/zero of=/dev/sdb bs=1M count=8

Partitionnement

$ sudo fdisk /dev/sdb

Créer une nouvelle partition primaire vide, en tapant les commandes suivantes :

  1. o : crée une nouvelle table de partition DOS
  2. n : crée une nouvelle partition avec les paramètres suivants :
    • p : type de partition primaire
    • ENTER : numéro de partition (1 par défaut)
    • 4096 : premier secteur
    • ENTER : dernier secteur (par défaut)
  3. w : écrit la table de partition et quitte

Création du système de fichiers ext4

$ sudo mkfs.ext4 /dev/sdb1

Montage du système de fichiers

$ mkdir root  
$ sudo mount /dev/sdb1 root

Téléchargement et extraction du système de fichier root

Téléchargement

$ wget http://os.archlinuxarm.org/os/ArchLinuxARM-odroid-xu3-latest.tar.gz
$ wget http://os.archlinuxarm.org/os/ArchLinuxARM-odroid-xu3-latest.tar.gz.md5

Vérification

$ md5sum -c ArchLinuxARM-odroid-xu3-latest.tar.gz.md5
ArchLinuxARM-odroid-xu3-latest.tar.gz: Réussi

Extraction

$ sudo bsdtar -xpf ArchLinuxARM-odroid-xu3-latest.tar.gz -C root

Flash du bootloader

$ cd root/boot/
$ sudo ./sd_fusing.sh /dev/sdb
/dev/sdb reader is identified.
[...]
U-boot image is fused successfully.

Démontage du système de fichiers

$ cd ../..
$ sudo umount root

Premier démarrage du système

  1. Insérer le module eMMC dans son emplacement sur la carte XU4
  2. Connecter le cable ethernet et brancher l'alimentation
  3. Attendre la fin du démarrage du système puis se connecter en ssh avec le user alarm et le mot de passe alarm

    $ ssh alarm@cloudshell.domaine.lan
  4. Ouvrir une session root avec le mot de passe root

    $ su - root

Gestion de paquets

Pacman

Initialisation du trousseau de clés

# pacman-key --init

Chargement du trousseau de clés

# pacman-key --populate archlinuxarm

Mise à jour du système

# pacman -Syu

Installation de paquets

# pacman -S vim sudo man-pages man-db bash-completion gptfdisk lvm2 git fakeroot binutils unzip wget highlight perl-json-xs fortune-mod uboot-tools

Arch User Repository (AUR) - Facultatif

Attention : Aucun assistant AUR n'est officiellement supporté par les développeurs d'Arch Linux pour la simple raison qu'AUR est un dépôt de paquets non officiellement supportés.

Trizen

trizen est un client pour AUR, léger et écrit en Perl.

Installation de trizen

$ git clone https://aur.archlinux.org/trizen.git
$ cd trizen
$ makepkg -si

Localisation

Fuseau horaire

# ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime

Synchronisation de l'horloge matérielle sur l'horloge système

# hwclock --systohc

Info : cette commande permet de générer le fichier /etc/adjtime, cf. hwclock(8) section "The Adjtime File" pour plus d'information sur ce fichier.

Génération des locales

# vi /etc/locale.gen

Décommenter la ligne fr_FR.UTF-8 UTF-8, puis générer les locales :

# locale-gen
Generating locales...
  fr_FR.UTF-8... done
Generation complete.

Configuration des locales

cf. Locale Variables - ArchWiki pour plus de détails sur les différentes variables supportées.

# vi /etc/locale.conf
LANG=fr_FR.UTF-8

Clavier

# vi /etc/vconsole.conf
KEYMAP=fr

Configuration réseau

Nom d'hôte

# vi /etc/hostname
cloudshell

# vi /etc/hosts
127.0.0.1       localhost
::1             localhost
127.0.1.1       cloudshell.domaine.lan cloudshell

Adresse IP

Comme il s'agit d'un serveur installé dans mon réseau local, j'utilise DHCP pour lui assigner une adresse IP (bail statique sur le routeur) et pour diffuser différentes options. Par sécurité, un profil statique est créé dans le cas où le routeur ne serait pas disponible.

# vi /etc/dhcpcd.conf

Ajouter/modifier les lignes suivantes :

# Allow users of this group to interact with dhcpcd via the control socket.
controlgroup wheel
# Inform the DHCP server of our hostname for DDNS.
hostname
# Persist interface configuration when dhcpcd exits.
persistent
# vendorclassid is set to blank to avoid sending the default of
# dhcpcd-<version>:<os>:<machine>:<platform>
vendorclassid
# A list of options to request from the DHCP server.
option domain_name_servers, domain_name, domain_search
option classless_static_routes
# Respect the network MTU. This is applied to DHCP routes.
option interface_mtu
# Most distributions have NTP support.
option ntp_servers
# Rapid commit support.
option rapid_commit
# A ServerID is required by RFC2131.
require dhcp_server_identifier
# Generate Stable Private IPv6 Addresses based from the DUID
slaac private
noipv4ll
# Static profile
profile static_eth0
static ip_address=192.168.0.2/24
static routers=192.168.0.254
static domain_name_servers=192.168.0.254 1.1.1.1
# Fallback to static profile
interface eth0
fallback static_eth0

Mise à jour du firmware JSM561

Téléchargement de l'application de mise à jour

# wget https://wiki.odroid.com/_media/accessory/add-on_boards/xu4_cloudshell2/jms561_fw_updater_onxu4.tgz

Extraction et lancement de la mise à jour

# tar xvzf jms561_fw_updater_onxu4.tgz
# cd JMS561/

On met à jour le firmware pour chaque disque connecté, ici /dev/sda et /dev/sdb :

# ./JMS561FwUpdate -d /dev/sda -f ./jms561_Hardkernel_v158.001.000.004.bin -b ./backup.bin
# ./JMS561FwUpdate -d /dev/sdb -f ./jms561_Hardkernel_v158.001.000.004.bin -b ./backup.bin

Vérification de la version actualisée

# ./JMS561FwUpdate -d /dev/sda -v
Bridge Firmware Version: v158.1.0.4
# ./JMS561FwUpdate -d /dev/sdb -v
Bridge Firmware Version: v158.1.0.4

Installation du gestionnaire de RAID du controleur JMS56X

# wget https://wiki.odroid.com/_media/accessory/add-on_boards/xu4_cloudshell2/raidmgr_static_cloudshell2.zip
# unzip raidmgr_static_cloudshell2.zip
# chmod a+x raidmgr_static
# ./raidmgr_static

JMS56X HW RAID Manager V8.0.0.1
(C) 2008~2011 JMicron Tech, Corp. Command Line Interface RAID Manager For JMS56X.

JMS56X>

Valid commands set are:
=======================

 GC ------------------------------------- Get avail JMS56X
 DC C[n] -------------------------------- Display controller info
 SR C[n] -------------------------------- Show avail RAID info
 SS C[n] -------------------------------- Show avail SATA info
 SM C[n] D[n] --------------------------- Show disk S.M.A.R.T. info
 CR C[n] D[0,..,2] R0|R1|JBOD ----------- Create RAID
 DR C[n] R[n] --------------------------- Delete RAID
 SF C[n] -------------------------------- Show firmware version
 SA C[n] -------------------------------- Set alarm mute
 GR C[n] R[n] --------------------------- Get rebuilding percentage
 ID C[n] D[n] --------------------------- Identify disk
 ST C[n] R[n] timer --------------------- Set standby timer
 AS C[n] D[n] R[n] ---------------------- Add spare disk
 DS C[n] D[n] R[n] ---------------------- Delete spare disk
 EX ------------------------------------- Exit

JMS56X>

Ecran LCD

Activation de l'écran

# echo "options fbtft_device name=hktft9340 busnum=1 rotate=270" > /etc/modprobe.d/cloudshell.conf
# echo "spi_s3c64xx" >> /etc/modules-load.d/fbtft_device.conf
# echo "spidev" >> /etc/modules-load.d/fbtft_device.conf
# echo "fbtft_device" >> /etc/modules-load.d/fbtft_device.conf

Script d'affichage d'infos sur l'écran LCD

Note : ce script est un exemple, adaptez-le à votre besoin

$ sudo vim /bin/cloudshell-lcd

Coller les lignes suivantes :

#!/bin/bash

## Configuration

export TERM="linux"

# console font (see /usr/share/kbd/consolefonts)
# export CONSOLE_FONT=""

# Output Console (ttyX)
export OUTPUT_CONSOLE="1"

# Network Interface: eth0, wlan0, ....
export NETIF="eth0"

# SATA HDD mount
export SATA="/dev/sd"

# Mem Card mount
export MEMCARD="/dev/mmcblk0p1"

# Screen refresh in seconds
export REFRESH="3"

# CPU Temperature in C or F
export TEMPERATURE_FORMAT="C"

# External IP Refresh counts
# The time to update the ip in counts is acquired by using the following formula
# seconds_to_refresh = EXT_IP_REFRESH * REFRESH
export EXT_IP_REFRESH="10"

# Message
#export MESSAGE=`/usr/bin/fortune`
export MESSAGE="La simplicité est la sophistication suprême - Léonard De Vinci"

get_external_ip() {
    export EXTERNAL_IP=`/usr/bin/drill myip.opendns.com @resolver1.opendns.com | awk '/^myip/ {print $5}'`
}

get_full_date() {
    export DATE=`/usr/bin/date +"%d-%m-%Y %H:%M:%S"`
}

get_hostname() {
    export HOSTNAME=`/usr/bin/getent ahosts | awk '/127.0.1.1/ {print $2}'`
}

get_internal_ip() {
    export INTERNAL_IP=`/usr/bin/ip -o -4 a | awk '/eth0/ {print $4}'`
}

get_net_tx_rx_realtime() {
    net_txrx=`/usr/bin/sar -n DEV 1 1 | awk '/Moyenne.*eth0/ {gsub(",",".",$0);print $5" "$6}'`
    # in MB/s
    _tx=`echo $net_txrx | awk '{printf $1}'`
    _rx=`echo $net_txrx | awk '{printf $2}'`
    export NET_TX=`echo "scale=1; x=$_tx/1024; if(x<1) print 0; x" | bc -l`
    export NET_RX=`echo "scale=1; x=$_rx/1024; if(x<1) print 0; x" | bc -l`

}

get_disk_info() {
    t=`/usr/bin/df -h | grep $SATA`
    export DISK_SIZE=`echo $t | awk '{printf $2}'`
    export DISK_USED=`echo $t | awk '{printf $3}'`
    export DISK_FREE=`echo $t | awk '{printf $4}'`
    export DISK_USED_PCT=`echo $t | awk '{printf $5}'`
}

get_memcard_info() {
    t=`/usr/bin/df -h | grep $MEMCARD`
    export MEMCARD_SIZE=`echo $t | awk '{printf $2}'`
    export MEMCARD_USED=`echo $t | awk '{printf $3}'`
    export MEMCARD_FREE=`echo $t | awk '{printf $4}'`
    export MEMCARD_USED_PCT=`echo $t | awk '{printf $5}'`
}

get_memory_info() {
    # in Mbytes
    export MEM_FREE=$(/usr/bin/free -h | awk '/Mem:/ {print $7}')
    export MEM_TOTAL=$(/usr/bin/free -h | awk '/Mem:/ {print $2}')
    export MEM_USED=$(/usr/bin/free -h | awk '/Mem:/ {print $3}')
}

get_cpu_usage() {
    cpufree=`mpstat 1 1 | awk '/Moyenne/ {gsub(",",".",$0); print $12}'`
    export CPU_USAGE=`echo "scale=1; x=100-$cpufree; if(x<1) print 0; x" | bc -l`
}

get_cpu_temperature() {
    _t=$[`cat /sys/class/thermal/thermal_zone0/temp` / 1000]
    if [ "$TEMPERATURE_FORMAT" = "C" ]; then
        export CPU_TEMP="$_t"C
    else
        _t1=$[ $_t * 9 / 5 + 32 ]
        export CPU_TEMP="$_t1"F
    fi
}

get_ssh_connections() {
    export SSH_CONNECTIONS=$(/usr/bin/who | wc -l)
}

get_process_count() {
    export PROCESS_COUNT=`ps xa | wc -l`
}

# local variables
ext_ip_refresh_c=0
COFF=$(tput sgr0)
CGREEN=$(tput setaf 2)
CRED=$(tput setaf 1)
CBLUE=$(tput setaf 6)
oc="/dev/tty$OUTPUT_CONSOLE"

# font setup
#setfont $CONSOLE_FONT > $oc

# Ensure that we are in the right TTY
chvt $OUTPUT_CONSOLE

# infinite loop
while true; do

    # Ensure that we are in the right TTY
    chvt $OUTPUT_CONSOLE

    # check if EXT_IP_REFRESH
    if (( ($ext_ip_refresh_c % $EXT_IP_REFRESH) == 0 )); then
        get_external_ip
    fi

    # increment $ext_ip_refresh_c
    ext_ip_refresh_c=$[$ext_ip_refresh_c+1]

    # get data
    get_internal_ip
    get_hostname
    get_disk_info
    get_memcard_info
    get_full_date
    get_net_tx_rx_realtime
    get_memory_info
    get_cpu_usage
    get_cpu_temperature
    get_ssh_connections
    get_process_count

    # clear the screen every loop
    # we only wipe the screen when we are ready to write data to it
    clear > $oc

    # format the data on screen
    echo "" > $oc
    echo -e "$CBLUE$HOSTNAME $COFF: $DATE" > $oc
    echo "" > $oc
    # line CPU Usage
    echo -e "CPU Usage: $CBLUE$CPU_USAGE%$COFF   CPU Temp: $CBLUE$CPU_TEMP$COFF" > $oc
    # Line Memory
    echo -e "Memory Free: $CBLUE$MEM_FREE$COFF   Used: $CBLUE$MEM_USED$COFF" > $oc
    # Line IP Addresses
    echo -e "IP: $CBLUE$INTERNAL_IP$COFF   Rem: $CBLUE$EXTERNAL_IP$COFF" > $oc
    # Line network usage
    echo -e "TX: $CBLUE$NET_TX MB/s$COFF RX: $CBLUE$NET_RX MB/s$COFF" > $oc
    # Line Disk Space
    echo -e "Disk Used: $CBLUE$DISK_USED$COFF ($CBLUE$DISK_USED_PCT$COFF)  Free: $CBLUE$DISK_FREE$COFF" > $oc
    # Line Memcard Space
    echo -e "Mem Card Used: $CBLUE$MEMCARD_USED$COFF ($CBLUE$MEMCARD_USED_PCT$COFF)  Free: $CBLUE$MEMCARD_FREE$COFF" > $oc
    # Line SSH
    echo -e "SSH Connections: $CBLUE$SSH_CONNECTIONS$COFF" > $oc
    # line Processes
    echo -e "Processes Running: $CBLUE$PROCESS_COUNT$COFF" > $oc
    # Custom Message
    echo -e "$CRED$MESSAGE$COFF" > $oc

    # sleep
    sleep $REFRESH
done

On rend le script exécutable :

$ sudo chmod a+x /bin/cloudshell-lcd

Service systemd

$ sudo vim /etc/systemd/system/cloudshell-lcd.service

Coller les lignes suivantes :

[Unit]
Description="ODROID Cloudshell LCD Info"
DefaultDependencies=no
Requires=sysinit.target
After=sysinit.target

[Service]
Type=simple
ExecStart=/bin/cloudshell-lcd

[Install]
WantedBy=basic.target
WantedBy=sysinit.target

Maintenant on active le service et on le démarre :

$ sudo systemctl enable cloudshell-lcd.service
$ sudo systemctl start cloudshell-lcd.service

Ventilateur

Script de contrôle du ventilateur

$ sudo vim /bin/cloudshell-fan

Coller les lignes suivantes :

#!/bin/bash
REFRESH="1"
DISK_TEMP_THRESHOLD="45"
CPU_TEMP_THRESHOLD="60"
FAN_CHANGED="*"

get_disk_dev_info() {
    # Pull disk info from /dev/sd*
    fdisk -l > disks.txt 2>/dev/null
    SATA=($(awk '/^\/dev\/sd/ {printf "%s ", $1}' disks.txt))
    rm disks.txt
}

get_disk_temperature() {
    for i in "${!SATA[@]}"
    do
        # declare and assign variable seperately to avoid masking return value
        DISK_TEMP[$i]=" (IDLE)"
        local t
        t=$(smartctl -a "${SATA[$i]}" -d sat | grep "Temp")
        if (( $? == 0 ))
        then
            local temp=$(echo $t | awk '{print $10}')
            DISK_TEMP[$i]="$temp"
        else
            DISK_TEMP[$i]=""
        fi
    done
}

get_cpu_temperature() {
    for i in {0..4}
    do
        _t=$(($(</sys/class/thermal/thermal_zone${i}/temp) / 1000))
        CPU_TEMP[$i]="$_t"
    done
}

fan_on() {
    i2cset -y 1 0x60 0x05 0x00
}

fan_off() {
    i2cset -y 1 0x60 0x05 0x05
}

handle_fan() {
    for i in "${!DISK_TEMP[@]}"
    do
        if (( "${DISK_TEMP[$i]}" > "${DISK_TEMP_THRESHOLD}" ))
        then
            if [ "${FAN_CHANGED}" != "1" ]
            then
                echo "Turning fan on because disk $i has hit the threshold"
            fi

            FAN_CHANGED="1"
            fan_on
            return
        fi
    done

    for i in "${!CPU_TEMP[@]}"
    do
        if (( "${CPU_TEMP[$i]}" > "${CPU_TEMP_THRESHOLD}" ))
        then
            if [ "${FAN_CHANGED}" != "1" ]
            then
                echo "Turning fan on because CPU $i has hit the threshold"
            fi

            FAN_CHANGED="1"
            fan_on
            return
        fi
    done

    # No fuss, fan is off
    if [ "${FAN_CHANGED}" != "0" ]
    then
        echo "All temps nominal, turning fan off"
        FAN_CHANGED="0"
    fi
    fan_off
}

while true; do
    get_disk_dev_info
    get_disk_temperature
    get_cpu_temperature
    handle_fan

    sleep ${REFRESH}
done

On rend le script exécutable :

$ sudo chmod a+x /bin/cloudshell-fan

Service systemd

$ sudo vim /etc/systemd/system/cloudshell-fan.service

Coller les lignes suivantes :

[Unit]
Description="ODROID Cloudshell Fan Control"
DefaultDependencies=no
Requires=sysinit.target
After=sysinit.target

[Service]
Type=simple
ExecStart=/bin/cloudshell-fan

[Install]
WantedBy=basic.target
WantedBy=sysinit.target

Maintenant on active le service et on le démarre :

$ sudo systemctl enable cloudshell-fan.service
$ sudo systemctl start cloudshell-fan.service

Configuration uboot

Afin de supprimer les messages susceptibles d'apparaitre à l'écran une fois le système redémarré, on modifie les fichier /boot/boot.txt :

$ sudo vim /boot/boot.txt

Modifier la ligne suivante en ajoutant les paramètres quiet et splash à la fin de la ligne :

setenv bootargs "console=tty1 console=ttySAC2,115200n8 root=PARTUUID=${uuid} rw rootwait smsc95xx.macaddr=${macaddr} ${videoconfig} quiet splash"

Mettre à jour le fichier boot.scr :

$ cd /boot/
$ sudo ./mkscr

Redémarrage du système

# reboot

Finalisation de la configuration du système

Se connecter en ssh avec le user alarm et le mot de passe alarm

$ ssh alarm@cloudshell.domaine.lan

Ouvrir une session root avec le mot de passe root

$ su - root

Utilisateurs

Définir un mot de passe root

# passwd

Définir un mot de passe pour l'utilisateur alarm et le renommer

# passwd alarm
# usermod -l new_user alarm
# usermod -m -d /home/new_user new_user

Configuration des disques

Le CloudShell2 permet de connecter deux disques SATA au format 3.5" par défaut (et 2.5" avec adaptateur), et supporte les technologies RAID0, RAID1, SPAN ainsi que l'accès direct (mode PM).

Dans ma configuration, j'ai branché deux disques SATA 2To en 2.5" et configuré le 'DIP switch' en accès direct (mode PM). Ces deux disques seront configurés via LVM pour former un volume logique unique de 4To.

Note : Sur un serveur on devrait dans l'idéal créer un volume RAID1 avec deux disques, mais ici on est limité au niveau matériel, en effet le CLoudshell2 connecte les deux disques SATA en USB via UART et à l'heure actuelle la synchronisation des deux disques provoque de nombreuses erreurs fatales, jusqu'à rendre USB indisponible. Les solutions de contournement consistent à limiter la taille et la bande passante allouée à la synchronisation, ce qui induit des pertes de performances non négligeables. Je préfère donc pour le moment sauvegarder les données de manière régulière sur un autre mini-serveur de mon réseau dédié à la sauvegarde (un raspberry Pi avec un disque externe de 4To).

Préparation des disques

$ sudo gdisk /dev/sda

Supprimer toutes les données GPT et MBR du disque, en tapant les commandes suivantes :

  1. x : accéder aux fonctionnalités avancées
  2. z : détruire les données GPT et MBR

Partitionnement

$ sudo gdisk /dev/sda

Créer une nouvelle partition de type 'Linux LVM' (8e00) sur le disque, en tapant les commandes suivantes :

  1. n : créer une nouvelle partition avec les paramètres suivants :
    • Partition number (1-128, default 1):
    • First sector (34-3907029134, default = 2048) or {+-}size{KMGTP}:
    • Last sector (2048-3907029134, default = 3907029134) or {+-}size{KMGTP}:
    • Hex code or GUID (L to show codes, Enter = 8300): 8e00
  2. w : appliquer les changements et quitter

Répéter l'opération sur le 2ème disque (/dev/sdb).

Vérification

$ sudo fdisk -l
[...]
Disk /dev/sda: 1.82 TiB, 2000398934016 bytes, 3907029168 sectors
[...]
Device     Start        End    Sectors  Size Type
/dev/sda1   2048 3907029134 3907027087  1.8T Linux LVM

Disk /dev/sdb: 1.82 TiB, 2000398934016 bytes, 3907029168 sectors
[...]
Device     Start        End    Sectors  Size Type
/dev/sdb1   2048 3907029134 3907027087  1.8T Linux LVM

Création des volumes physiques

$ sudo pvcreate /dev/sda1 /dev/sdb1
  Physical volume "/dev/sda1" successfully created.
  Physical volume "/dev/sdb1" successfully created.

Création du groupe de volume

$ sudo vgcreate system /dev/sda1 /dev/sdb1
  Volume group "system" successfully created

Création du volume logique

Formatage de la partition

# mkfs.ext4 /dev/sda1

Synchronisation du contenu de /home

# mkdir /mnt/data
# mount /dev/sda1 /mnt/data
# rsync -avz /home/ /mnt/data/

Une fois les données synchronisées (et vérifiées !), on peut nettoyer le répertoire /home :

# rm -rf /home/*

Montage de la partition et génération du fstab

# mount /dev/sda1 /home
# genfstab -p -U / > /etc/fstab

Récepteur infrarouge

Références


mercredi 12 février 2020

:: CloudSHell2 - Installation d'Archlinux ::

Introduction

Toutes les opérations décrites ci-dessous ont été faites à partir d'un portable sous Archlinux et du reader/writer eMMC se branchant sur le port SD (via un adaptateur micro-SD).

La commande lsblk permet de récupérer le nom du périphérique, pour ma part /dev/mmcblk0

Préparation du module eMMC

Remise à zéro

$ sudo dd if=/dev/zero of=/dev/mmcblk0 bs=1M count=8

Partitionnement

$ sudo fdisk /dev/mmcblk0

Créer une nouvelle partition primaire vide, en tapant les commandes suivantes :

  1. o : crée une nouvelle table de partition DOS
  2. n : crée une nouvelle partition avec les paramètres suivants :
    • p : type de partition primaire
    • 1 : première partition
    • 4096 : premier secteur de la partition
    • ENTER : dernier secteur de la partition (defaut)
  3. w : écrit la table de partition et quitte

Création du système de fichiers ext4

$ sudo mkfs.ext4 /dev/mmcblk0p1

Montage du système de fichiers

$ mkdir root  
$ sudo mount /dev/mmcblk0p1 root

Téléchargement et extraction du système de fichier root

$ wget http://os.archlinuxarm.org/os/ArchLinuxARM-odroid-xu3-latest.tar.gz  
$ sudo bsdtar -xpf ArchLinuxARM-odroid-xu3-latest.tar.gz -C root

Flash du bootloader

$ cd root/boot/
$ sudo ./sd_fusing.sh /dev/mmcblk0

Démontage du système de fichiers

$ cd ../..
$ sudo umount root

Premier démarrage du système

  1. Insérer le module eMMC dans son emplacement sur la carte XU4
  2. Connecter le câble ethernet et brancher l'alimentation
  3. Attendre la fin du démarrage du système puis se connecter en ssh avec le user alarm et le mot de passe alarm

    $ ssh alarm@cloudshell.domaine.lan
  4. Ouvrir une session root avec le mot de passe root

    $ su - root

Initialisation

Création du trouseau de clés et enrichissement des certificats des dépôts Arch Linux ARM

# pacman-key --init
# pacman-key --populate archlinuxarm

Gestion de paquets

Mise à jour du système

# pacman -Syu

Paquets supplémentaires

# pacman -S vim

Localisation

Timezone

# ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime

Horloge

hwclock --systohc

Cette commande permet de générer le fichier /etc/adjtime.

Locales

Décommenter la ligne fr_FR.UTF-8 UTF-8 dans le fichier /etc/locale.gen.

  • /etc/locale.gen

    fr_FR.UTF-8 UTF-8

Générer les locales :

 # locale-gen
 Generating locales...
 fr_FR.UTF-8... done
 Generation complete.

Configuration réseau

Nom d'hôte

  • /etc/hostname

    cloudshell
  • /etc/hosts

    127.0.0.1       localhost
    ::1             localhost
    127.0.1.1       cloudshell.domaine.lan cloudshell

Adresse IP

Comme il s'agit d'un serveur installé dans mon réseau local, je préfère lui assigner une adresse ip fixe tout en gardant la possibilité de demander une adresse ip dynamique (si je le déplace par exemple). J'ai donc créé un profil statique en ajoutant les lignes suivantes à la fin du fichier /etc/dhcpcd.conf :

  • /etc/dhcpcd.conf

    # Static profile
    interface eth0
    static ip_address=192.168.0.2/24 
    static routers=192.168.0.254
    static domain_name_servers=192.168.0.254 8.8.8.8

Configuration des disques

Le CloudShell2 permet de connecter deux disques SATA au format 3.5" et supporte les technologies RAID0, RAID1, SPAN ainsi que l'accès direct (mode PM).

Dans ma configuration, j'ai branché deux disques SATA de 3To et configuré le 'DIP switch' en RAID1. Le volume RAID est accessible via /dev/sda et sera monté sur /home.

Partitionnement

# fdisk /dev/sda

Créer une nouvelle partition primaire sur le volume, en tapant les commandes suivantes :

  1. n : crée une nouvelle partition avec les paramètres suivants :
    • p : partition de type primaire
    • 1 : numéro de partition
    • ENTER (2048) : premier secteur par defaut
    • ENTER (dernier secteur) : dernier secteur par defaut
  2. w : applique les changements et quitte

Formatage de la partition

# mkfs.ext4 /dev/sda1

Synchronisation du contenu de /home

# mkdir /mnt/data
# mount /dev/sda1 /mnt/data
# rsync -avz /home/ /mnt/data/

Une fois les données synchronisées (et vérifiées !), on peut nettoyer le répertoire /home :

# rm -rf /home/*

Montage de la partition et génération du fstab

# mount /dev/sda1 /home
# genfstab -p -U / > /etc/fstab

Ecran LCD

# echo "options fbtft_device name=hktft9340 busnum=1 rotate=270" > /etc/modprobe.d/cloudshell.conf
# echo "spi_s3c64xx" >> /etc/modules-load.d/fbtft_device.conf
# echo "spidev" >> /etc/modules-load.d/fbtft_device.conf
# echo "fbtft_device" >> /etc/modules-load.d/fbtft_device.conf

Ventilateur

Récepteur infrarouge

Références