I am very proud of this little machine. Initially, I had the following things on the list of requirements:
- Fully compatible with Linux (in particular, Arch Linux)
- Silent (in particular, fanless)
- Low-power
- Compact and beautiful
Selected hardware:
- Motherboard: ASRock Q1900DC-ITX
- RAM (2): Kingston KVR16LS11/8
- SSD: Kingston SV300S37A/120G
- HDD (2): Western Digital WD10JFCX
- Power adapter: Targus Compact Laptop & USB Tablet Charger (APA042EU)
- Case: Streacom F1CWS Evo Chassis
The main reasons for choosing this particular motherboard were the low power consumption, convenience of a decent integrated CPU (Intel J1900), fanless design, Mini-ITX form factor, and complete compatibility with Linux. Other interesting features include 4 SATA connectors (2.0 and 3.0), plenty of USB ports (2.0 and 3.0), several graphics outputs (HDMI, DVI-D and D-Sub, all up to a resolution of 1920 by 1200 at 60Hz), and an integrated power supply unit which accepts any voltage between 9 and 19V, ±10%. An additional important detail is that the motherboard supports Wake-on-LAN. In terms of RAM, 2 8GB DDR3L modules were used, resulting in the maximum 16GB supported by the motherboard. As for non-volatile memory, a 120GB SSD and 2 1TB HDDs were used, with the goal of installing the operating system and services on the SSD while leaving the HDDs exclusively for storage. The SSD is just a regular SSD. On the other hand, the HDDs were selected based on reliability and acoustic specifications. The power required by the motherboard is supplied by a very compact and energy-efficient 90W power adapter. Based on the user manual of the motherboard, number of RAM modules and number of disks, 90W are enough to power the system. It is worth noting that the adapter comes with an integrated 2.1A USB fast charging port. Regarding the case, the F1CWS Evo is compatible with the Mini-ITX form factor, robust, and also quite small, especially considering that it can hold up to 3 2.5” disks. The case is made entirely of aluminum with a very beautiful sandblast finish.
The software currently running in the previously described hardware is a minimal install of Arch Linux with remote administration through SSH, RAID 1, LVM, an SMB server for local file sharing and an HTTP server (Apache) with PHP and WebDAV support. Everything is installed based on the following 3 bash scripts. Running the first bash script after booting from an Arch Linux image installs the base system on the SSD and configures SSH. In order for the script to execute properly, there must be internet connectivity and the public key key.pub intended to be used with SSH must be placed in the same directory as the script.
#!/bin/bash if [ ! -f 'key.pub' ]; then exit 1; fi curl -o list 'https://www.archlinux.org/mirrorlist/?country=PT&use_mirror_status=on' if [ ! -f 'list' ]; then exit 2; fi mv list /etc/pacman.d/mirrorlist sed -i -e 's/#Server/Server/' /etc/pacman.d/mirrorlist sgdisk -Z /dev/sda sgdisk -n 1:2048:+512M -t 1:EF00 /dev/sda sgdisk -n 2:0:+16G -t 2:8300 /dev/sda sgdisk -n 3:0:+4G -t 3:8200 /dev/sda sgdisk -n 4:0:0 -t 4:8300 /dev/sda mkfs.fat -F 32 /dev/sda1 mkfs.ext4 -F /dev/sda2 mkswap /dev/sda3 mount /dev/sda2 /mnt mkdir /mnt/boot mount /dev/sda1 /mnt/boot pacstrap /mnt base echo "UUID=$(lsblk -no UUID /dev/sda2) / ext4 rw,relatime,data=ordered 0 1 UUID=$(lsblk -no UUID /dev/sda1) /boot vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro 0 2 UUID=$(lsblk -no UUID /dev/sda3) none swap defaults 0 0" > /mnt/etc/fstab echo 'vm.swappiness=10' > /mnt/etc/sysctl.d/99-sysctl.conf sed -i -e 's/#en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /mnt/etc/locale.gen arch-chroot /mnt locale-gen echo 'LANG=en_US.UTF-8' > /mnt/etc/locale.conf ln -s /usr/share/zoneinfo/Europe/Lisbon /mnt/etc/localtime arch-chroot /mnt hwclock --utc sed -i -e 's/MODULES=""/MODULES="i915"/' /mnt/etc/mkinitcpio.conf arch-chroot /mnt mkinitcpio -p linux arch-chroot /mnt bootctl --path=/boot install echo 'title "Arch Linux" efi /vmlinuz-linux options initrd=/intel-ucode.img initrd=/initramfs-linux.img root=/dev/sda2 rw' > /mnt/boot/loader/entries/arch.conf echo 'default arch' > /mnt/boot/loader/loader.conf echo 'SRV' > /mnt/etc/hostname sed -i -e 's/localhost/localhost SRV/2' /mnt/etc/hosts arch-chroot /mnt pacman -S --needed --noconfirm \ $(echo ' dosfstools efibootmgr gptfdisk intel-ucode ntfs-3g openssh unzip wget zip apache ffmpeg php php-apache rsync samba') echo '[Match] Name=en* [Network] Address=192.168.1.100/24 DHCP=no DNS=192.168.1.254 Gateway=192.168.1.254' > /mnt/etc/systemd/network/10-static.network mv /mnt/etc/resolv.conf /mnt/etc/resolv.conf.default ln -s /run/systemd/resolve/resolv.conf /mnt/etc/resolv.conf cp /mnt/etc/ssh/sshd_config /mnt/etc/ssh/sshd_config.default echo 'AuthorizedKeysFile /etc/ssh/authorized_keys ChallengeResponseAuthentication no LogLevel VERBOSE MaxAuthTries 6 MaxSessions 1 PasswordAuthentication no PermitRootLogin prohibit-password Port 22 Protocol 2 PubkeyAuthentication yes SyslogFacility AUTH UsePAM no' > /mnt/etc/ssh/sshd_config cat key.pub > /mnt/etc/ssh/authorized_keys arch-chroot /mnt systemctl enable systemd-networkd.service systemd-resolved.service sshd.socket echo 'ROOT' arch-chroot /mnt passwd umount -R /mnt
Only the mirrors from Portugal are considered in the script. The root password is requested at the end. After rebooting, the IP will be set to 192.168.1.100 static and SSH will be ready for key-based passwordless login on port 22. The second script configures the last physical partition of the SSD for LVM and creates 2 logical partitions, combines the 2 HDDs in RAID 1, configures the resulting space for LVM and creates 4 logical partitions.
#!/bin/bash pvcreate /dev/sda4 vgcreate vg0 /dev/sda4 lvcreate --name lv0 --size 64G vg0 lvcreate --name lv1 --size 26G vg0 mkfs.ext4 /dev/vg0/lv0 mkfs.ext4 /dev/vg0/lv1 sgdisk -Z /dev/sdb sgdisk -Z /dev/sdc sgdisk -n 1:2048:+931G -t 1:FD00 /dev/sdb sgdisk -n 1:2048:+931G -t 1:FD00 /dev/sdc mdadm --create --metadata=1.2 --raid-devices=2 --level=1 /dev/md0 /dev/sdb1 /dev/sdc1 cp /etc/mdadm.conf /etc/mdadm.conf.default echo -e "DEVICE partitions\n$(mdadm --detail --scan)" > /etc/mdadm.conf mdadm --assemble /dev/md0 pvcreate /dev/md0 vgcreate vg1 /dev/md0 lvcreate --name lv0 --size 512G vg1 lvcreate --name lv1 --size 128G vg1 lvcreate --name lv2 --size 128G vg1 lvcreate --name lv3 --size 128G vg1 mkfs.ext4 /dev/vg1/lv0 mkfs.ext4 /dev/vg1/lv1 mkfs.ext4 /dev/vg1/lv2 mkfs.ext4 /dev/vg1/lv3 mkdir /srv/http/cloud mkdir /srv/smb mkdir /srv/smb/n0 mkdir /srv/smb/n1 mkdir /srv/smb/n2 mkdir /srv/smb/n3 echo "UUID=$(lsblk -no UUID /dev/vg0/lv0) /srv/http/cloud ext4 rw,relatime,data=ordered 0 2 UUID=$(lsblk -no UUID /dev/vg0/lv1) /home ext4 rw,relatime,data=ordered 0 2 UUID=$(lsblk -no UUID /dev/vg1/lv0) /srv/smb/n0 ext4 rw,relatime,data=ordered 0 2 UUID=$(lsblk -no UUID /dev/vg1/lv1) /srv/smb/n1 ext4 rw,relatime,data=ordered 0 2 UUID=$(lsblk -no UUID /dev/vg1/lv2) /srv/smb/n2 ext4 rw,relatime,data=ordered 0 2 UUID=$(lsblk -no UUID /dev/vg1/lv3) /srv/smb/n3 ext4 rw,relatime,data=ordered 0 2" >> /etc/fstab
After rebooting, the partitions will be automatically mounted. The third and last script takes care of configuring the SMB server and the Apache HTTP server.
#!/bin/bash echo '[global] create mask = 0744 directory mask = 0755 disable netbios = yes disable spoolss = yes dns proxy = no force create mode = 0600 force directory mode = 0755 guest account = nobody load printers = no log file = /var/log/samba/samba.log log level = 0 map to guest = Bad User max log size = 5000 printcap name = /dev/null printing = bsd security = user server string = SMB workgroup = GROUP [n0] browseable = no guest ok = yes max connections = 5 only guest = yes path = /srv/smb/n0/n0 writable = yes [n1] browseable = no guest ok = yes max connections = 5 only guest = yes path = /srv/smb/n1/n1 writable = yes [n2] browseable = no guest ok = yes max connections = 5 only guest = yes path = /srv/smb/n2/n2 writable = yes [n3] browseable = no guest ok = yes max connections = 5 only guest = yes path = /srv/smb/n3/n3 writable = yes' > /etc/samba/smb.conf mkdir /srv/smb/n0/n0 mkdir /srv/smb/n1/n1 mkdir /srv/smb/n2/n2 mkdir /srv/smb/n3/n3 chown nobody:nobody /srv/smb/n0/n0 chown nobody:nobody /srv/smb/n1/n1 chown nobody:nobody /srv/smb/n2/n2 chown nobody:nobody /srv/smb/n3/n3 cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.default echo 'ServerRoot "/etc/httpd" Listen 80 LoadModule authz_host_module modules/mod_authz_host.so LoadModule authz_groupfile_module modules/mod_authz_groupfile.so LoadModule authz_user_module modules/mod_authz_user.so LoadModule authz_core_module modules/mod_authz_core.so LoadModule reqtimeout_module modules/mod_reqtimeout.so LoadModule log_config_module modules/mod_log_config.so LoadModule logio_module modules/mod_logio.so LoadModule setenvif_module modules/mod_setenvif.so LoadModule mpm_prefork_module modules/mod_mpm_prefork.so LoadModule unixd_module modules/mod_unixd.so LoadModule dav_module modules/mod_dav.so LoadModule dav_fs_module modules/mod_dav_fs.so LoadModule dav_lock_module modules/mod_dav_lock.so LoadModule dir_module modules/mod_dir.so LoadModule rewrite_module modules/mod_rewrite.so LoadModule php7_module modules/libphp7.so User http Group http ServerAdmin r12624@gmail.com DavLockDB "/etc/httpd/conf/davlock/davlock" DocumentRoot "/srv/http" RewriteEngine on RewriteRule "^/$" "/index.php" [PT] <Directory "/"> Require all denied Options None AllowOverride None DirectoryIndex disabled </Directory> <Directory "/srv/http"> <FilesMatch "^(index|error)\.php$"> Require all granted </FilesMatch> <Files "favicon.ico"> Require all granted </Files> <Files "robots.txt"> Require all granted </Files> </Directory> <Directory "/srv/http/core"> Require all granted Options FollowSymLinks DirectoryIndex index.html index.php </Directory> <Directory "/srv/http/cloud"> Require all granted </Directory> <Directory "/srv/http/cloud/h-?*-end"> Dav On </Directory> <Location "/cloud/lost+found"> DirectorySlash Off </Location> <FilesMatch "\.php$"> SetHandler application/x-httpd-php </FilesMatch> ErrorLog "/var/log/httpd/error_log" LogLevel info LogFormat "%{%Y-%m-%d %H:%M:%S %z}t %h \"%r\" %>s %I %O \"%{Referer}i\" \"%{User-agent}i\"" simple CustomLog "/var/log/httpd/access_log" simple PidFile "/run/httpd/httpd.pid" StartServers 5 MinSpareServers 5 MaxSpareServers 10 MaxRequestWorkers 250 MaxConnectionsPerChild 0 MaxMemFree 2048 ErrorDocument 400 /error.php ErrorDocument 401 /error.php ErrorDocument 402 /error.php ErrorDocument 403 /error.php ErrorDocument 404 /error.php ErrorDocument 405 /error.php ErrorDocument 406 /error.php ErrorDocument 407 /error.php ErrorDocument 408 /error.php ErrorDocument 409 /error.php ErrorDocument 410 /error.php ErrorDocument 411 /error.php ErrorDocument 412 /error.php ErrorDocument 413 /error.php ErrorDocument 414 /error.php ErrorDocument 415 /error.php ErrorDocument 416 /error.php ErrorDocument 417 /error.php ErrorDocument 500 /error.php ErrorDocument 501 /error.php ErrorDocument 502 /error.php ErrorDocument 503 /error.php ErrorDocument 504 /error.php ErrorDocument 505 /error.php BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully BrowserMatch "MS FrontPage" redirect-carefully BrowserMatch "^WebDrive" redirect-carefully BrowserMatch "^WebDAVFS/1.[01234]" redirect-carefully BrowserMatch "^gnome-vfs/1.0" redirect-carefully BrowserMatch "^XML Spy" redirect-carefully BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully BrowserMatch " Konqueror/4" redirect-carefully Timeout 60 KeepAlive On MaxKeepAliveRequests 100 KeepAliveTimeout 5 UseCanonicalName Off AccessFileName .htaccess ServerTokens Full ServerSignature Off HostnameLookups Off RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500' > /etc/httpd/conf/httpd.conf mkdir /srv/http/core mkdir /etc/httpd/conf/davlock chown http:http /etc/httpd/conf/davlock systemctl enable smbd.service httpd.service
Regarding SMB, 4 shares with no password are created. Read-only attributes are automatically removed from any file or folder copied to the SMB server. Regarding the HTTP server, access to the root folder is denied, except for the files index.php, error.php, favicon.ico and robots.txt, and the folders core and cloud. Inside the core directory or any of its subdirectories, any index files named index.html or index.php are automatically interpreted. WebDAV is automatically enabled for any directories inside cloud with names beginning with h-, ending with -end, and with at least 1 character in the middle. Even though the WebDAV folders are not protected by any password, this mechanism based on folder names with a random component is perfectly fine for temporary file transfers from and to the home server.
Lastly, the power consumption of this system, including the power adapter, stabilizes at 12.9W after the boot process is finished. This value drops to 11.2W everytime the HDDs switch to a low power state after a few minutes of inactivity. When the system is powered off but still listening for Wake-on-LAN packets, the power consumption drops to 2.4W.
Sources:
Building a new fanless and silent server and NAS
Round-up of 74 laptop power adapters: original or universal?