Pull to refresh

Сетевой жесткий диск с помощью SSHFS и Raspberry Pi

Reading time 11 min
Views 28K


Всем привет!

Хочу поделиться с вами моим опытом создания сетевого жесткого диска на Raspberry Pi. Моя статья отлично подойдет тем, кто использует линукс в качестве основной ОС, т.к. тут я активно использую SSHFS.

Всех заинтересовавшихся прошу под кат.

Шаг 0. Подготовка


Нам необходимо:
  • Raspberry Pi любой модели + SD карточка памяти до 32 GB;
  • Жесткий диск;
  • Если жесткий диск без внешнего питания, то, скорее всего, понадобится хаб с возможностью подключения внешнего питания;
  • Основной компьютер работающей под линуксом (в статье я использую Linux Mint 17);
  • Интернет;
  • Прямые руки.


Шаг 1. Установка


Для начала необходимо установить на Raspberry Pi Raspbian или Arch Linux ARM.
В статье я буду использовать Raspbian.
  1. Идем на сайте Raspberry Pi в раздел загрузок и скачиваем образ Raspbian
  2. Распаковываем архив
  3. Открываем терминал и переходим в папку с образом
  4. Вставляем карточку памяти в компьютер
  5. В терминале вводим df -h и смотри на вывод. В выводе должно присутствовать /dev/mmcblk0p1 или /dev/sdd1. В моем случае это /dev/mmcblk0p1. p1 (или 1, если у вас карточка отображается как /dev/sdd1) это номер раздела, если на карточке несколько разделов, то в выводе еще будет /dev/mmcblk0p2 или /dev/sdd2. Количество записей в выводе зависит от того сколько у вас разделов
  6. Итак, узнав как ваша карточка отображается в системе переходим к записи образа.
    1. В терминале запускаем umount /dev/mmcblk0p1 (или umount /dev/sdd1). Если у вас несколько разделов, то необходимо размонтировать все.
    2. Записывать на карточку образ будем с помощью программы dcfldd. Программа dcfldd работает так же как dd, но периодически сообщает о том сколько уже записано. Введите в терминал следующую команду:

      $ sudo dcfldd bs=4M if=имя_вашего_образа_.img of=путь_к_вашей_карте
      

      В моем случае команда выглядит так:

      $ sudo dcfldd bs=4M if=2014-12-24-wheezy-raspbian.img of=/dev/mmcblk0
      

      Обратите внимание, что в пути к вашей карте не надо указывать номер раздела (даже если он один). Образ записывается на всю карту.
      bs — block size — размер одного блока, записывающегося на карту. Если при установленных 4M запись не работает, то необходимо поставить 1M, но это приведет к увеличению времени записи.
    3. После того как образ будет записан запустите команду:

      $ sync 

      Это позволит убедиться в том что все данные были записаны на карту и очистит буфер
  7. Все. Карточку можно вынимать и вставлять в Raspberry Pi.


Шаг 2. Первое включение


  1. Вставляем карточку в Raspberry Pi;
  2. Подключаем к Raspberry Pi интернет, монитор и клавиатуру;
  3. Включаем Raspberry Pi;
  4. После загрузки системы у вас должно появится окно Raspberry Pi Software Configuration Tool.
    1. Выбираем пункт Expand Filesystem и нажимаем Enter. Это позволит убедиться в том что весь объем карточки доступен ОС
    2. Далее переходим к пункту 2 — Change User Password и вводим новый пароль;
    3. Переходим к пункту 3 — Enable Boot to… и выбираем Console Text console;
    4. Переходим к пункту 4 — Internationalisation Options и затем переходим к пункту Change Locale и ищем в списке ru_RU.UTF-8 UTF-8, помечаем пробелом и нажимаем Enter. Дальше система спросит какую локаль использовать по умолчанию. Выбираем русскую и нажимаем Enter;
    5. Идем снова в Internationalisation Options и затем переходим к пункту Change Timezone. Выбираем Europe и ищем в списке свой город. Затем нажимаем Enter;
    6. Переходим к пункту 7 — Overclock (разгоним немного нашу малышку) и выбираем уровень Medium;
    7. Переходим к пункту 8 — Advanced Options и переходим к пункту A2 — Hostname. Вводим имя под которым мы хотим видеть нашу малышку в локальной сети и жмем Enter;
    8. Идем снова в Advanced Options и переходим к пункту A4 — SSH и включаем SSH;
    9. На этом наши приключения в Raspberry Pi Software Configuration Tool закончены. Нажимаем стрелку вправо и Finish.
  5. Если необходимо снова попасть в эту программу, то нужно ввести:

    $ sudo raspi-config
    
  6. Теперь нужно перезагрузить систему. В консоле вводим команду:

    $ sudo reboot
    
  7. После того как система перезагрузится заходим в учетную запись. Логин pi пароль тот что вы ввели ранее;
  8. Теперь необходимо обновить ОС. Для этого вводим:
    $ sudo rpi-update
    
    и после этого
    $ sudo apt-get update 
    
    и
    $ sudo apt-get upgrade 
    



Шаг 3. Настройка SSH


  1. Прежде всего необходимо сгенерировать ключи (если они еще не сгенерированы). Для этого на основной ОС выполните:

    $ ssh-keygen -t rsa -C "your_email@example.com"
    
  2. После чего ключи необходимо скопировать на вашу Raspberry Pi.
    1. Для этого необходимо узнать под каким ip ваша малышка находится в сети. Это можно узнать зайдя на роутер, например или с помощью команды:
      $ ifconfig
      

      У меня ip 192.168.0.102.
    2. Теперь выполняем команду на основной ОС:

      $ ssh-copy-id pi@192.168.0.102
      

      Вас попросят ввести согласие на продолжение подключения. Нужно ввести yes. После чего вас попросят ввести пароль от учетный записи на Raspberry Pi. Вводим и его.
  3. Теперь можно попробовать подключиться к вашей Raspberry Pi через ssh. Для этого на основной машине введите:

    $ ssh pi@192.168.0.102
    
  4. Если вы увидите сообщение приветствие, то, ура, вы вошли
  5. Теперь можно отключить от Raspberry Pi монитор и клавиатуру. Все дальнейшие действия мы будем проводить через SSH


Шаг 4. Причесывание Raspberry Pi


  1. Во-первый необходимо задать пароль для root'a т.к. по умолчанию он отсутствует. Для этого выполните:
    $ sudo passwd root
    
    И введите новый пароль для root'a
  2. Устанавливаем редактор vim:
    $ sudo apt-get install vim
    
    Вы также можете использовать редактор nano, который уже установлен. Но я предпочитаю vim.
  3. Теперь я хочу изменить имя пользователя. Для этого выходим с помощью команды exit. Снова логинимся через ssh, но уже под рутом.
    $ ssh root@192.168.0.102
    
    и выполняем команду:
    $ usermod -l новое_имя -d /home/новое_имя -m pi
    
    Я использую в качестве нового имени inn0kenty, т.е. в моем случае команда выглядит так:
    $ usermod -l inn0kenty -d /home/inn0kenty -m pi
    



Шаг 5. Статический ip


У меня работает DHCP, поэтому при каждом подключении Raspberry Pi к домашней сети ей будет выдаваться новый ip адрес, что меня конечно не устраивает. Для того чтобы сделать ip статическим необходимо выполнить:
  1. Введите в терминале
    $ sudo vim /etc/network/interfaces
    
    . В открывшемся файле меняем
    iface eth0 inet dhcp
    
    на
    iface eth0 inet static
    address 192.168.0.98 
    netmask 255.255.255.0
    network 192.168.0.0
    broadcast 192.168.0.255
    gateway 192.168.0.1
    
    Указав при этом параметры вашей сети. Netmask и broadcast можно узнать с помощью команды
    $ sudo ifconfig
    

    а gateway с помощью
    $ sudo route -nee
    
  2. После чего перезагружаем Raspberry Pi командой sudo reboot
  3. Теперь для того чтобы подключиться к Raspberry Pi по shh необходимо ввести
    $ ssh inn0kenty@192.168.0.98
    


Шаг 6. Причесываем SSH


На этом шаге я покажу как упростить подключение по ssh и сделать его более безопасным.
  1. Прежде всего откроем файл конфигурации ssh с помощью команды:
    $ sudo vim /etc/ssh/sshd_config
    
    И устанавливаем в нем запрет входить по ssh пользователю root и отключаем аутентификацию по паролю:
    PasswordAuthentication no
    PermitRootLogin no
    
    А также меняем порт
    Port 22226 (например)
    
  2. После чего перезагружаем Raspberry Pi
    $ sudo reboot
    
  3. Теперь для подключении к Raspberry Pi необходимо указывать порт 22226
    $ ssh -p 22226 inn0kenty@192.168.0.98
    
    Но столь длинную команду можно упростить и свести к минимуму. Для этого на вашей основной ОС отредактируем файл config. В домашней директории выполните:
    $ vim .ssh/config 
    
    и вставьте туда следующие строчки:
    Host 192.168.0.98
    	Hostname 192.168.0.98
    	User inn0kenty
    	Port 22226
    

    После этого для подключение к вашей Raspberry Pi необходимо будет набрать только
    $ ssh 192.168.0.98 
    



Шаг 7. Подключение к Raspberry Pi извне.


В этом разделе я хочу рассказать как подключаться по ssh к Raspberry Pi не только из локальной сети, но и извне.
Если у вас внешний ip статический, то, ура, можно особо не париться. Достаточно сделать переадресацию с внешнего ip на внутренний.
Но если у вас, как и у меня, внешний ip динамический, то на помощь нам придет dynamic dns.
Лично я пользуюсь noip.com т.к. он бесплатен, хотя и требует периодически заходить на сайт и подтверждать, что вы еще пользуетесь адресом, который они вам дали.
Итак, регистрируйтесь там и переходите в Add a Host.
  1. В hostname введите адрес, который хотите использовать для подключения извне и нажмите на кнопку Add Host ничего больше не меняя
  2. Теперь необходимо чтобы noip знал когда у вас меняется ip. Тут есть два пути. Первый, если ваш роутер поддерживает функцию динамической системы доменных имен (DDNS), то достаточно в настройках роутера ввести данные аккаунта и доменное имя. После чего роутер будет сообщать noip о смене ip адреса. Второй, необходимо поставить программу на ваш основной компьютер. У noip это Dynamic DNS Update Client. Взять ее можно отсюда
  3. Следующий шаг: необходимо сделать переадресацию с внешнего ip на ваш локальный.
    Для этого в моем роутере необходимо перейти в Переадресация -> Виртуальные серверы и добавить туда такую запись:
    Порт сервиса: 22226
    Внутренний порт: 22226
    IP-адрес: 192.168.0.98
    Протокол: все
  4. Теперь необходимо добавить в конфигурационный файл ssh на вашей основной ОС данные для входа извне.
    Открываем файл config
    $ vim .ssh/config
    
    И добавляем туда
    Host доменное_имя
    	Hostname доменное_имя
    	User inn0kenty
    	Port 22226
    
    Сохраняем.
  5. Все. Теперь вы можете подключаться к Raspberry Pi не только из дома


Шаг 8. Подключение HDD


  1. Для начала необходимо на вашей Raspberry Pi создать папку в которую будет монтироваться ваш HDD
    $ mkdir hdd
    
  2. Теперь подключим жесткий диск к Raspberry Pi и введем команду
    $ sudo blkid
    
    В выводе должно быть что-то типа такого:
    /dev/mmcblk0p1: SEC_TYPE="msdos" LABEL="boot" UUID="936C-7154" TYPE="vfat" 
    /dev/mmcblk0p2: UUID="c1398422-7a7c-4863-8a8f-45a1db26b4f2" TYPE="ext4" 
    /dev/sda1: LABEL="Seagate Expansion Drive" UUID="7CD8E7DCD8E792A6" TYPE="ntfs"
    
    Последняя строчка как раз то, что нам нужно. Запоминаем UUID.
  3. Теперь необходимо установить поддержку файловой системы
    $ sudo apt-get install ntfs-3g
    
  4. Открываем файл fstab
    $ sudo vim /etc/fstab
    
  5. Добавляем туда вот такую строчку:
    UUID="*" ** ntfs-3g rw,force,exec,users 0 0
    где * - это ваш UUID (у меня 7CD8E7DCD8E792A6)
    а ** - это путь к вашей папке монтирования (у меня /home/inn0kenty/hdd)
    
  6. Сохраняемся и перезагружаем Raspberry Pi
  7. После перезагрузки в папке hdd должны появиться все файлы и папки с жесткого диска


Шаг 9. SSHFS


  1. Устанавливаем на вашу основную ОС sshfs
    $ sudo apt-get install sshfs
    
  2. Создаем в домашней директории папку в которую будет монтироваться Raspberry Pi.
    $ mkdir pi
    
  3. Монтируем Raspberry Pi в эту папку:
    $ sshfs 192.168.0.98:/home/inn0kenty/hdd pi
    
    Все. Все наши файлы с жесткого диска оказались в папке pi на вашей основной машине
  4. Для того чтобы размонтировать Raspberry Pi нужно ввести команду
    $ sudo umount pi
    
    или
    $ fusermount -u pi
    
  5. Для того чтобы сделать тоже самое извне достаточно немного изменить команду.
    $ sshfs доменное_имя:/home/inn0kenty/hdd pi
    
  6. Эти команды можно прописать в fstab на вашей основной машине, чтобы монтирование выполнялось каждый раз когда вы включаете компьютер, но для меня это не подходящий вариант т.к. основной компьютер у меня ноутбук и интернет при включении есть не всегда. Поэтому я предлагаю воспользоваться небольшим скриптом, который легко примонтрует вашу Raspberry Pi с помощью одной короткой командой.
    #!/bin/bash
    ABSOLUTE_FILENAME=`readlink -e "$0"` #имя файла
    #имя директории в которой файл находится
    DIRECTORY=`dirname "$ABSOLUTE_FILENAME"` 
    if [ "x$1" = "x-nh" ] || [ "x$1" = "x-nothome" ] ; then
    	sshfs -o nonempty доменное_имя:/home/inn0kenty/hdd $DIRECTORY 
    # -o nonempty говорит sshfs о том что директория в которую
    # монтируют не пуста 
    else
    	sshfs -o nonempty 192.168.0.98:/home/inn0kenty/hdd $DIRECTORY
    fi
    
    1. Сохраним этот скрипт в файл mount.sh и сделаем его исполняемым
      $ chmod +x mount.sh
      
    2. И поместим его в папку pi
      $ mv mount.sh pi/
      
    3. После чего добавим алиас, чтобы запускать скрипт одной командой. Откройте bashrc (если его нет, создайте).
      $ vim .bashrc
      
      И добавьте туда строчку
      alias pimount='/home/inn0kenty/pi/mount.sh'
      
      Разумеется подставив ваши данные.
      Сохраните и перезапустите bash.
      Теперь можно монтировать вашу Raspberry Pi одной командой
      $ pimount
      
      Причем если указать ключ -nh или -nothome, то ваша Raspberry Pi примонтируется через доменное имя т.е. можно использовать вашу Raspberry Pi по полной даже не находясь в одной локальной сети с ней.
      $ pimount -nh
      
      или
      $ pimount -nothome
      


Шаг 10. Deluge


Последний шаг — установка торрент-качалки. Я предпочитаю Deluge.
  1. Вводим по очереди команды:
    $ sudo apt-get install deluged deluge-webui
    
  2. После чего выполняем
    $ sudo vim /etc/default/deluge-daemon
    
    и вводим туда следующее:
    # Configuration for /etc/init.d/deluge-daemon
    
    # The init.d script will only run if this variable non-empty.
    DELUGED_USER="ваше_имя_пользователя"             # !!!CHANGE THIS!!!!
    
    # Should we run at startup?
    RUN_AT_STARTUP="YES"
    
    Затем сохраняем и закрываем
  3. И выполняем:
    $ sudo vim /etc/init.d/deluge-daemon
    
    и вводим туда следующее:
    Большой скрипт
    #!/bin/sh
    ### BEGIN INIT INFO
    # Provides:          deluge-daemon
    # Required-Start:    $local_fs $remote_fs
    # Required-Stop:     $local_fs $remote_fs
    # Should-Start:      $network
    # Should-Stop:       $network
    # Default-Start:     2 3 4 5
    # Default-Stop:      0 1 6
    # Short-Description: Daemonized version of deluge and webui.
    # Description:       Starts the deluge daemon with the user specified in
    #                    /etc/default/deluge-daemon.
    ### END INIT INFO
    
    # Author: Adolfo R. Brandes 
    # Updated by: Jean-Philippe "Orax" Roemer
    
    PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
    DESC="Deluge Daemon"
    NAME1="deluged"
    NAME2="deluge"
    DAEMON1=/usr/bin/deluged
    DAEMON1_ARGS="-d"             # Consult `man deluged` for more options
    DAEMON2=/usr/bin/deluge-web
    DAEMON2_ARGS=""               # Consult `man deluge-web` for more options
    PIDFILE1=/var/run/$NAME1.pid
    PIDFILE2=/var/run/$NAME2.pid
    UMASK=022                     # Change this to 0 if running deluged as its own user
    PKGNAME=deluge-daemon
    SCRIPTNAME=/etc/init.d/$PKGNAME
    
    # Exit if the package is not installed
    [ -x "$DAEMON1" -a -x "$DAEMON2" ] || exit 0
    
    # Read configuration variable file if it is present
    [ -r /etc/default/$PKGNAME ] && . /etc/default/$PKGNAME
    
    # Load the VERBOSE setting and other rcS variables
    [ -f /etc/default/rcS ] && . /etc/default/rcS
    
    # Define LSB log_* functions.
    # Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
    . /lib/lsb/init-functions
    
    if [ -z "$RUN_AT_STARTUP" -o "$RUN_AT_STARTUP" != "YES" ]
    then
       log_warning_msg "Not starting $PKGNAME, edit /etc/default/$PKGNAME to start it."
       exit 0
    fi
    
    if [ -z "$DELUGED_USER" ]
    then
        log_warning_msg "Not starting $PKGNAME, DELUGED_USER not set in /etc/default/$PKGNAME."
        exit 0
    fi
    
    #
    # Function to verify if a pid is alive
    #
    is_alive()
    {
       pid=`cat $1` > /dev/null 2>&1
       kill -0 $pid > /dev/null 2>&1
       return $?
    }
    
    #
    # Function that starts the daemon/service
    #
    do_start()
    {
       # Return
       #   0 if daemon has been started
       #   1 if daemon was already running
       #   2 if daemon could not be started
    
       is_alive $PIDFILE1
       RETVAL1="$?"
    
       if [ $RETVAL1 != 0 ]; then
           rm -f $PIDFILE1
           start-stop-daemon --start --background --quiet --pidfile $PIDFILE1 --make-pidfile \
           --exec $DAEMON1 --chuid $DELUGED_USER --user $DELUGED_USER --umask $UMASK -- $DAEMON1_ARGS
           RETVAL1="$?"
       else
           is_alive $PIDFILE2
           RETVAL2="$?"
           [ "$RETVAL2" = "0" -a "$RETVAL1" = "0" ] && return 1
       fi
    
       is_alive $PIDFILE2
       RETVAL2="$?"
    
       if [ $RETVAL2 != 0 ]; then
            sleep 2
            rm -f $PIDFILE2
            start-stop-daemon --start --background --quiet --pidfile $PIDFILE2 --make-pidfile \
            --exec $DAEMON2 --chuid $DELUGED_USER --user $DELUGED_USER --umask $UMASK -- $DAEMON2_ARGS
            RETVAL2="$?"
       fi
       [ "$RETVAL1" = "0" -a "$RETVAL2" = "0" ] || return 2
    }
    
    #
    # Function that stops the daemon/service
    #
    do_stop()
    {
       # Return
       #   0 if daemon has been stopped
       #   1 if daemon was already stopped
       #   2 if daemon could not be stopped
       #   other if a failure occurred
    
       start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --user $DELUGED_USER --pidfile $PIDFILE2
       RETVAL2="$?"
       start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --user $DELUGED_USER --pidfile $PIDFILE1
       RETVAL1="$?"
       [ "$RETVAL1" = "2" -o "$RETVAL2" = "2" ] && return 2
    
       rm -f $PIDFILE1 $PIDFILE2
    
       [ "$RETVAL1" = "0" -a "$RETVAL2" = "0" ] && return 0 || return 1
    }
    
    case "$1" in
      start)
       [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME1"
       do_start
       case "$?" in
          0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
          2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
       esac
       ;;
      stop)
       [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME1"
       do_stop
       case "$?" in
          0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
          2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
       esac
       ;;
      restart|force-reload)
       log_daemon_msg "Restarting $DESC" "$NAME1"
       do_stop
       case "$?" in
         0|1)
          do_start
          case "$?" in
             0) log_end_msg 0 ;;
             1) log_end_msg 1 ;; # Old process is still running
             *) log_end_msg 1 ;; # Failed to start
          esac
          ;;
         *)
            # Failed to stop
          log_end_msg 1
          ;;
       esac
       ;;
      *)
       echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
       exit 3
       ;;
    esac
    
    :
    

  4. Даем права на выполнение этому скрипту:
    $ sudo chmod 755 /etc/init.d/deluge-daemon
    
  5. Добавляем его в автозагрузку:
    $ sudo update-rc.d deluge-daemon defaults
    
  6. И запускаем:
    $ sudo invoke-rc.d deluge-daemon start
    
  7. После чего перезагружаемся.
    Теперь если зайти на 192.168.0.98:8112, то можно попасть в web ui торрент-качалки.
  8. Откроем доступ извне для нашего web ui. Для этого вернемся в наш роутер в Переадрессация -> Виртуальные серверы и добавим еще одну запись:
    Порт сервиса: 80
    Внутренний порт: 8112
    IP-адрес: 192.168.0.98
    Протокол: все

    После сохранения можно будет попасть на web ui просто вбив ваше доменное имя в адресную строку браузера.


Заключение


Я надеюсь, что моя статья хоть кому-то окажется полезной. Спасибо за уделенное внимание и потраченное время.
Tags:
Hubs:
-5
Comments 9
Comments Comments 9

Articles