13 min read

Расширяем функционал NAS Dlink DNS-325

Стоит у меня дома уже старенький NAS Dlink DNS-325, используется только для того чтобы отдавать в домашнюю сеть содержимое 2 дисков которые у него внутри. На днях наткнулся на статью на хабре про установке полноценного линукса и OpenMediaVault и решил почему бы и нет?
Будем ставить Debian на небольшой домашний NAS 🙂 Скажу сразу — получилось, но не сразу и не без проблем. По этому привожу краткую выжимку статьи с хабра(с разрешения автора), но с некоторыми исправлениями и коментариями от себя.


Этап 1. Подготовка устройства.
Встроенная NAND память не подходит для нашей задумки — слишком маленькая. Хранить систему на вставляемых в хранилище дисках желания нет совсем. Получится смешивание мозгов устройства с периферийными составляющими. А если я захочу диск поменять или он сломается?
Остался единственный адекватный вариант — установить USB-флеш-накопитель, на котором и будет установлена вся система. При таком подходе проще делать резервные копии системы, а флешку в случае поломки легко заменить.

Дополнительное железо.
Для доступа к мозгам извне на плате есть последовательный UART порт. Вместо того, чтобы перепрошивать ROM специальными программаторами, можно подключиться к контактам на плате и через специальный преобразователь общаться с устройством через эмулятор терминала.
Были выбраны и куплены следующие комплектующие:

  • Преобразователь USB — UART на PL2303HX
  • Провода «мама-мама» 20см, 20 шт.
  • Вилка штыревая PLS-40 (DS1021-1×40), прямая черная
  • Флешка 16Гб

Подключение преобразователя:
Вскрываем устройство, достаем плату


Ищем UART порт (4 пина слева)

2


Распиновка такая (в обратном порядке): { RXD, (пусто), 3.3v, GND, TXD }
Припаиваем вилку, вставляем провода

3


Собираем корпус, оставляем снятой только крышку

4


Теперь для доступа к встроенному микрокомпьютеру не надо будет доставать плату — провода уже выведены, останется снять переднюю крышку сетевого хранилища.
UPD. Чтобы в процессе работы не дергать крышку, я сделал дырку снизу и вывел провода наружу, в таком случае можно подключаться не снимая крышки, цепляясь к выведенным проводам с помощью вилок.

Так как это последовательный порт, то и соединяем последовательно.

RX на TX, TX на RX

5


На этом вся механическая работа с оборудованием закончена.

Пробный запуск
Для общения по протоколу UART нам понадобятся:
kwboot — утилита для запуска загрузчика на устройстве «на лету»
minicom — эмулятор терминала для UART протокола

Запускаем minicom на хост системе:

# minicom -D /dev/ttyUSB0 -b 115200 -8

Подключаем блок питания, включаем устройство, наслаждаемся выводом лога загрузки в консоль:

** MARVELL BOARD: DB-88F6281A-BP LE

U-Boot 1.1.4 (Jan 21 2011 — 09:42:39) Marvell version: 3.4.14.DNS-325.02

U-Boot code: 00600000 -> 0067FFF0 BSS: -> 006CEE80

Soc: MV88F6281 Rev 3 (DDR2)
CPU running @ 1200Mhz L2 running @ 400Mhz
SysClock = 400Mhz , TClock = 200Mhz

DRAM CAS Latency = 5 tRP = 5 tRAS = 18 tRCD=6
DRAM CS[0] base 0x00000000 size 256MB
DRAM Total size 256MB 16bit width
Flash: 0 kB
Addresses 8M — 0M are saved for the U-Boot usage.
Mem malloc Initialization (8M — 7M): Done
NAND:128 MB

***

NAND read: device 0 offset 0x100000, size 0x300000
load addr …. =a00000

3145728 bytes read: OK

NAND read: device 0 offset 0x600000, size 0x300000
load addr …. =f00000

3145728 bytes read: OK
## Booting image at 00a00000 …
Image Name: Linux-2.6.31.8
Created: 2012-06-26 3:38:43 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2565784 Bytes = 2.4 MB
Load Address: 00008000
Entry Point: 00008000
Verifying Checksum … OK
OK
## Loading Ramdisk Image at 00f00000 …
Image Name: Ramdisk
Created: 2014-01-21 4:33:41 UTC
Image Type: ARM Linux RAMDisk Image (gzip compressed)
Data Size: 1581012 Bytes = 1.5 MB
Load Address: 00e00000
Entry Point: 00e00000
Verifying Checksum … OK

Starting kernel …

Uncompressing Linux…………………………………………………….
**Linux version 2.6.31.8** (jack@swtest6) (gcc version 4.2.1) #8 Tue Jun 26 11:38:42
CPU: Feroceon 88FR131 [56251311] revision 1 (ARMv5TE), cr=00053977
CPU: VIVT data cache, VIVT instruction cache
Machine: Feroceon-KW
Using UBoot passing parameters structure
Memory policy: ECC disabled, Data cache writeback
Built 1 zonelists in Zone order, mobility grouping off. Total pages: 65024
Kernel command line: root=/dev/ram console=ttyS0,115200 :::DB88FXX81:egiga0:none
PID hash table entries: 1024 (order: 10, 4096 bytes)
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 256MB = 256MB total
Memory: 246528KB available (4828K code, 323K data, 136K init, 0K highmem)

***

NAND device: Manufacturer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-b)
Scanning device for bad blocks
Using static partition definition
Creating 6 MTD partitions on «nand_mtd»:
0x000000000000-0x000000100000 : «u-boot»
0x000000100000-0x000000600000 : «uImage»
0x000000600000-0x000000b00000 : «ramdisk»
0x000000b00000-0x000007100000 : «image»
0x000007100000-0x000007b00000 : «mini firmware»
0x000007b00000-0x000008000000 : «config»

Если интересно, вот полный вывод:
https://pastebin.com/6SRA6Qgq

Этап 2. Сборка и обновление

Все действия по сборке будут проводиться на основной (хост) системе под управлением Debian Stretch (amd64).
Собирать и обновлять будем:

  1. Загрузчик — U-Boot
  2. Ядро — Linux Kernel 4.10
  3. Корневую файловую систему Debian Jessie
  4. Образ начальной инициализации системы — Initramfs

Основные инструменты для сборки:

  1. Кросс-компилятор для armel архитектуры. В Debian это пакет gcc-arm-linux-gnueabi
  2. Вспомогательные утилиты:
    • git — для скачивания нужных версий с репозиториев проектов
    • make — для выполнения сборочных скриптов
    • debootstrap — для скачивания корневой файловой системы
    • mkimage — утилита для переформатирования файлов в формат, понятный загрузчику
    • BusyBox — набор утилит для начальной инициализации системы
    • сопутствующие зависимости и библиотеки.

Загрузчик
В данном устройстве установлен немного урезанный загрузчик U-Boot 2011 года. Обновлять будем до актуальной стабильной версии.

Скачиваем:

git clone --branch v2017.05 git://git.denx.de/u-boot.git

Настраиваем:

cd u-boot
nano u-boot/include/configs/dns325.h

Добавляем строки:
#define CONFIG_CMD_BOOTZ — для поддержки загрузки zImage ядра.
#define CONFIG_CMD_EXT4 — для поддержки ФС ext4 и связанных команд консоли загрузчика.

$ make dns325_defconfig
#
#configuration written to .config
#
$ make u-boot.kwb CROSS_COMPILE=arm-linux-gnueabi-

На этом этапе нужно знать, сколько весит этот файл:

$ printf «0x%x\n» `stat -c «%s» u-boot.kwb`
0x7315c

Выводим размер образа в шестнадцатеричной системе счисления (HEX), в таком виде он пригодится при записи в NAND память.

Записать полученный образ U-Boot в NAND память можно из работающего в памяти загрузчика. Я решил не делать это из текущего стокового загрузчика, так как хотелось сначала убедиться, что новый образ вообще загрузится на железе, да и поддержка ext4 была включена ранее в новом образе загрузчика, так что можно сделать финт ушами: скопировать этот образ на флешку и загрузить с этого же образа при помощи kwboot. kwboot позволяет запустить плату с передаваемым ей загрузчиком, не записывая ничего физически (только в RAM) и вообще игнорируя NAND память. Этот механизм позволяет аварийно загружать устройство даже когда оно окирпичилось в следствие порчи NAND памяти или неудачной прошивки.

Выключаем устройство, запускаем kwboot, нажимаем на кнопку включения. Должен пойти процесс заливки образа с последующей загрузкой, которую надо будет прервать.

Заливка и загрузка

# kwboot -p -b u-boot.kwb -B115200 -t /dev/ttyUSB0
Sending boot message. Please reboot the target…/ \
Sending boot image…
0 % […………………………………………………………….]
1 % […………………………………………………………….]
3 % […………………………………………………………….]
***
96 % […………………………………………………………….]
98 % […………………………………….]
[Type Ctrl-\ + c to quit]
U-Boot 2017.05-dirty (May 10 2017 — 02:56:44 +0300)
D-Link DNS-325 SoC: Kirkwood 88F6281_A1
DRAM: 256 MiB WARNING: Caches not enabled
NAND: 128 MiB
In: serial
Out: serial
Err: serial
Net: egiga0
IDE: ide_preinit failed
Hit any key to stop autoboot: 0
=>

Загрузились. Далее надо записать наш u-boot.kwb образ в область NAND. Но чтобы записать его в NAND память, надо сначала считать его и записать в RAM память.

Делаем ext4 флешку и даем разделу имя «rootfs» (чтобы монтировать корневую ФС по имени раздела):

# mkfs.ext4 /dev/sdb1
# e2label /dev/sdb1 rootfs

Копируем файл флешку, вставляем флешку в NAS и инициализируем ее:

=> usb start
starting USB… USB0: USB EHCI 1.00 scanning bus 0 for devices… 2 USB Device(s) found scanning usb for storage devices… 1 Storage Device(s) found

Записываем образ в память. Адрес (смещение) не имеет значения, главное не выходить за пределы RAM). В данном случае будет 0x1000000.

=> ext4load usb 0:1 0x1000000 /u-boot.kwb
471388 bytes read in 77 ms (5.8 MiB/s)

Очищаем область NAND, в которой хранится загрузчик:

=> nand erase 0x000000 0x7315c
NAND erase: device 0 offset 0x0, size 0x7315c Erasing at 0x60000 — 100% complete. OK

(с начала NAND памяти до смещения, равного размеру файла, который мы высчитали ранее)
Записываем загрузчик из области RAM памяти в область NAND памяти:

=> nand write 0x1000000 0x000000 0x7315c
NAND write: device 0 offset 0x0, size 0x7315c 471388 bytes written: OK

0x1000000 — откуда читаем в RAM
0x000000 — куда записываем в NAND
0x73044 — размер

Все, можно перезагружаться и наслаждаться запуском нового загрузчика:

U-Boot 2017.05-dirty (May 10 2017 — 02:56:44 +0300)
D-Link DNS-325 SoC: Kirkwood 88F6281_A1
DRAM: 256 MiB WARNING: Caches not enabled
NAND: 128 MiB In: serial
Out: serial
Err: serial
Net: egiga0
IDE: ide_preinit failed
Hit any key to stop autoboot: 0
=>

Если на данном этапе устройство окирпичилось и отказалось загружаться, например, как сначала получилось у меня (видимо, опечатался, когда вводил размер образа загрузчика при записи из RAM памяти в NAND), не спешите паниковать. Вы также можете загрузить устройство при помощи kwboot и повторить запись.
Upd. тут произошла большая ошибка, я не снял бэкап родного u-boot

Корневая система.

Воспользуемся инструментом debootstrap. Обычно формирование rootfs для систем с другой архитектурой делается в 2 этапа: скачивание в каталог с флагом —foregin, а потом настройка qemu и запуск в нем «debootstrap —second-stage». Мне не хотелось возиться с qemu, и я решил делать второй этап сразу на работающем NAS-е.

Скачиваем содержимое на флешку (примонтирована в /mnt/usb/):

# debootstrap --variant=minbase --foreign --arch=armel --include=dbus,nano jessie /mnt/usb/ http://ftp.ru.debian.org/debian/

Переименуем на время init файл, чтобы наполовину установленая система не запустилась:

# mv /mnt/usb/sbin/init /mnt/usb/sbin/init.bak

Ядро
Пожалуй, самый сложный этап из всех. Очень важно настроить ядро, чтобы все желаемые функции и программы работали правильно. Иначе легко получить какую-нибудь мерзопакастную ошибку со странными симптомами.

Скачивание:

$ git clone --branch v4.10 git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git

Загружаем предустановленный конфиг для нашей платы (ARMv5). В моем случае это mvebu_v5_defconfig.

$ make ARCH=arm mvebu_v5_defconfig
#
# configuration written to .config
#
$ make ARCH=arm menuconfig

Настраиваем. Настраивать и проверять нужно все, в идеале изучить каждый параметр и решить, нужен он или нет. Мной был выставлен hostname, включена поддержка initramfs/initrd, отключена поддержка звука и USB 3.0, отключены драйвера для ext2 и ext3 (драйвер ext4 умеет монтировать все ранние версии), включены дисковые квоты, включена поддержка плат Kirkwood, Marvell Orion. Также включены обязательные параметры для поддержки systemd, iptables  и NFS. Скорее всего, есть есть что-то, чего я не упомянул, ибо настроек много. Вот мой конфиг ядра: https://pastebin.com/xHePeUks

Многие вещи могут вылезти в процессе установки, настройки и эксплуатации системы. В таком случае можно просто добавить нужные строчки, пересобрать ядро и заменить образ на флешке.

Сборка:

$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j5 zImage kirkwood-dns325.dtb

Получили само ядро zImage и файл kirkwood-dns325.dtb. Последний файл — Device Tree — нужен для правильной работы ядра конкретно с нашей платой.
Копируем эти файлы в каталог /boot на флешке:

# cp arch/arm/boot/zImage arch/arm/boot/dts/kirkwood-dns325.dtb /mnt/usb/boot/

Initramfs
Далее делаем легковесный образ, который будет загружаться в память и инициализировать нашу систему. Его делать вовсе необязательно, загрузчик умеет напрямую стартовать ядро с указанием корневого каталога (root=). Однако полезно, т. к. в случае отсутствия доступа к корневой ФС будет доступна консоль с минимальным набором команд.
Костяк образа составит джентльменский набор BusyBox.
Скачивание:

$ git clone --branch 1_26_2 git://git.busybox.net/busybox/

Настройка:

$ make defconfig
$ make menuconfig

Единственное, что лучше выставить в настройках дополнительно — это статическая линковка библиотеки glibc, чтобы не пришлось запихивать его отдельно в образ.

6
Статическая линковка glibc

Сборка:

$ make ARCH=arm

Далее создаем структуру образа, помещаем в него busybox:

$ mkdir -p initramfs/{bin,sbin,etc,proc,sys,newroot,usr/{bin,sbin}}
$ cp busybox/bin/bisybox initramfs/bin
$ ln -s initramfs/bin/busybox initramfs/bin/sh

Далее необходимо написать init скрипт. Именно тут будет происходить вся магия по инициализации устройств и передаче управлению Debian-у.

Init скрипт:

#!/bin/sh

/bin/busybox —install -s

#Mount things needed by this script
mount -t proc proc /proc
mount -t sysfs sysfs /sys

#Disable kernel messages from popping onto the screen
echo 0 > /proc/sys/kernel/printk

#Clear the screen
clear

#Create device nodes
mknod /dev/null c 1 3
mknod /dev/tty c 5 0

#Pause bebore USB Storage init
sleep 3

#Mount devices
mdev -s

#Defaults
init=»/sbin/init»

#Mount the root device
mount LABEL=rootfs /newroot

#Check if $init exists and is executable
if [ -h «/newroot/${init}» ] ; then
#Unmount all other mounts so that the ram used by
#the initramfs can be cleared after switch_root
umount /sys /proc

#Switch to the new root and execute init
exec switch_root /newroot «${init}»
fi

#This will only be run if the exec above failed
echo «Failed to switch_root, dropping to a shell»
exec setsid sh
exec «${console}» 2>&1
exec sh

Пакуем и преобразуем в понятный для U-Boot-а формат:

$ cd initramfs/
$ find . | cpio -H newc -o > ../initramfs.cpio
$ cd ..
$ cat initramfs.cpio | gzip > initramfs.igz
$ mkimage -n 'uInitramfs' -A arm -O linux -T ramdisk -C gzip -d initramfs.igz initramfs.uImage

Копируем initramfs:

# cp initramfs.uImage /mnt/usb/boot/

UPD. На этом этапе у меня начались проблемы, т.к. initramfs я собрал весьма криво и при загрузке не находился init скрипт и система никак не могла загрузится. Связавшись с автором оригинальной статьи я получил его образ initramfs и смог загрузится. На всякий случай образ оставлю тут.

Копируем initramfs:

# cp initramfs.uImage /mnt/usb/boot/

Со сборкой закончили.

Этап3. Установка и настройка

Переменные окружения загрузчика

В процессе обновления загрузчика затерлись конфиги, надо настроить загрузку нового ядра, Initramfs, Device Tree, также восстановить настройки сети.

Загружаемся с minicom, выполняем на устройстве в консоли U-Boot:

=> setenv console ttyS0,115200
=> setenv bootargs console=${console}
=> setenv bootcmd usb start; run load_kernel; run load_init; run load_dtree; run boot_system
=> setenv load_kernel ext4load usb 0:1 0x1000000 boot/zImage
=> setenv load_init ext4load usb 0:1 0x1800000 boot/initramfs.uImage
=> setenv load_dtree ext4load usb 0:1 0x2000000 boot/kirkwood-dns325.dtb
=> setenv boot_system bootz 0x1000000 0x1800000 0x2000000
=> setenv ethaddr xx:xx:xx:xx:xx:xx
=> setenv ipaddr 192.168.0.32
=> saveenv

Тут все предельно просто: выставляем параметры консоли, загрузки ядра, прописываем куда будут копироваться (ext4load) в память файлы и откуда считываться (bootz). Прописываем ip и mac адреса (mac адрес можно посмотреть на наклейке устройства).

Вставляем флеш накопитель в NAS, перезагружаемся.

Корневая система (этап второй)

Загрузившись, попадаем в BusyBox. Можем завершить формирование rootfs:

# chroot /newroot
# mv /sbin/init.bak /sbin/init
# /debootstrap/debootstrap --second-stage
# passwd

Перезагружаем устройство, логинимся под root-ом. С этого момента мы загружаемся полностью и работаем в Debian-е.
UPD. Тут меня тоже ожидало фиаско т.к. команда chroot /newroot выдала вот такой вывод:

chroot: can’t execute ‘/bin/sh’: No such file or directory

Первая мысль что не примонтировался раздел, монтируем вручную и получаем вывод:

mount: mounting /dev/sda1 on /newroot failed: Device or resource busy

Если у вас тоже так получилось, то меняйте флешку. После замены флешки все заработало.

Настройка сети

Далее следует настроить и включить сеть.

# touch /etc/systemd/network/wired.network
# nano /etc/systemd/network/wired.network

Пишем простой конфиг для статического ip на проводном интерфейсе eth0

[Match]
Name=eth0

[Network]
Address=192.168.0.32/24
Gateway=192.168.0.1

Включаем и запускаем сетевые службы

# systemctl enable systemd-networkd
# systemctl enable systemd-resolved
# systemctl start systemd-networkd
# systemctl start systemd-resolved

Сеть есть.

Настройка вентилятора и кнопок

Прежде чем делать высоконагруженные операции, необходимо настроить вентилятор на охлаждение. Обычно настройка происходит просто: при помощи команды pwmconfig находится датчик температуры ЦП, находится вентилятор, они связывается и выставляются граничные параметры активации режимов охлаждения.

В случае с домашним NAS так делать не стоит, ибо основную долю тепла выделяют жесткие диски, а не процессор.

Проблема вот в чем: fancontrol, служба которая занимается контролем вентилятора, позволяет следить только за датчиками, находящимися непосредственно на плате. На данном устройстве установлен один вентилятор и один датчик температуры.

Выход есть: можно обмануть fancontrol, заставив его считывать информацию из нужного нам места. Для считывания данных с HDD используем пакет smartmontools.

Устанавливаем:

# apt install fancontrol lm-sensors smartmontools

Настраиваем по умолчанию:

# pwmconfig

Тонкости настройки можно почитать, например, здесь.

Далее открываем конфиг /etc/fancontrol, смотрим содержимое. Интересна переменная «FCTEMPS» — она ставит в соответствие устройству место, откуда следует брать температуру:

FCTEMPS=hwmon0/pwm1=hwmon1/temp1_input

Путь относительный, сам файл генерируется в /sys/class/hwmon/hwmon1/temp1_input. Посмотрим в каком формате хранится информация:

# cat /sys/class/hwmon/hwmon1/temp1_input
41500

Значение в цельсиях, умноженное на 1000 (для точности). Значит нужен файл, в котором периодически будет обновляться значение температуры жестких дисков. Значение допускается одно, а жеских дисков у нас может быть 2. Значит, будем считать максимальное, записывать в файл.

Напишем небольшой скрипт:

#!/bin/bash

while sleep 60
do
TEMP1=`smartctl -A /dev/disk/by-id/ata-Hitachi_HDS723030ALA640_MK0311YHG1ZGJA | grep Temperature_Celsius | awk ‘{print $10 «000»}’`
TEMP2=`smartctl -A /dev/disk/by-id/ata-WDC_WD2003FYYS-02W0B1_WD-WMAY05168428 | grep Temperature_Celsius | awk ‘{print $10 «000»}’`
echo $(( $TEMP1 > $TEMP2 ? $TEMP1 : $TEMP2 )) > /etc/temp_hdd
done

Каждую минуту считывается S.M.A.R.T. информация с датчиков HDD, из всей информации выделяется только значение температуры, и в нужном формате наиболшее из 2-х записывается в файл /etc/temp_hdd. Диски я указал по id, потому что буквы дисков /dev/sd[a-z] могут меняться в зависимости от порядка и кол-ва вставленных физических дисков.

Записываем скрипт в /etc/temp_hdd.sh. Дальше нужно его каким-то образом запускать при старте. Для этого как раз подойдет файл /etc/rc.local
Прописываем прямо перед «exit 0» строчку

/etc/temp_hdd.sh &

Теперь процесс будет запускаться при старте системы и выполняться в фоне.
Когда есть файл с актуальной температурой, впишем это в конфиг /etc/fancontrol, настроив при этом граничные значения температуры. Получилось как-то так:

# Configuration file generated by pwmconfig, changes will be lost
INTERVAL=10
DEVPATH=hwmon0=devices/platform/gpio_fan hwmon1=devices/platform/ocp@f1000000/f1011000.i2c/i2c-0/0-0048
DEVNAME=hwmon0=gpio_fan hwmon1=lm75
FCTEMPS=hwmon0/pwm1=/etc/temp_hdd
FCFANS= hwmon0/pwm1=hwmon0/fan1_input
MINTEMP=hwmon0/pwm1=45
MAXTEMP=hwmon0/pwm1=55
MINSTART=hwmon0/pwm1=4
MINSTOP=hwmon0/pwm1=0

Реакцию на кнопки настроить гораздо проще. Устанавливаем пакет esekeyd и настраиваем:

# apt install esekeyd
# nano /etc/esekeyd.conf

Ставим команды на выключение и перезагрузку:

POWER:/sbin/shutdown -h now
RESTART:/sbin/reboot

Сохраняем, перезагружаем устройство. Теперь основные важные области системы установлены и настроены.

Послесловие.

Далее автор описывал установку OpenMediaVault, но я решил его не ставить, а пользоваться системой как есть т.к. практика показала то при работе OMV грузит процессор и иногда выдает ошибки. В качестве альтернативы можно использовать Webmin или другую систему управления серверами через Web-интерфейс, либо один раз настроить все по ssh и забыть:)

UPD. Как и автор оригинальной статьи я попробовал пользоваться OMV, не скажу что вышло удачно т.к. процессор грузит под 100% и панель управления начинает сыпать различными ошибками. Так же пробовал пользоваться Webmin, тут немного лучше, работает в целом стабильно, но не быстро и опять же при работе с web-интерфейсом процессор загружается на 80-100%, но в отличии от OMV ошибок нет, тем не менее мне кажется это не очень правильно.
По началу появлялись ошибки вида:

perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LANGUAGE = (unset),
LC_ALL = (unset),
LC_MEASUREMENT = "ru_RU.UTF-8",
LC_PAPER = "ru_RU.UTF-8",
LC_MONETARY = "ru_RU.UTF-8",
LC_NUMERIC = "ru_RU.UTF-8",
LC_TIME = "ru_RU.UTF-8",
LANG = "ru_RU.UTF-8"
are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory

Устраняется это запуском dpkg-reconfigure locales и выбором нужной локали, я установил en_US.UTF-8 и ru_RU.UTF-8, после чего ошибки пропали.

Оригинальная статья на Habrahabr.