Adding Storage to a Linux Server
Some basic tips for adding and working with disks on Linux servers and several examples.
0 . Latest updates and prerequisites.
2023.09.15 – First draft, Ubuntu 22.04 Server.
2024.11.25 – Updated for Ubuntu 24.04 Server.
Check back for updates, if you run into trouble. Leave a comment if the post is missing some detail.
Sudo or root access is needed to manipulate storage devices. Most of this will work with any Linux.
1 . Connecting storage to the server.
SATA, USB, eSATA, SCSI, IDE; directly connected storage. Things like iSCSI are network related, so not covered here. Ensure the storage device has power and is connected. Some USB devices have LEDs to show they are “talking”, some hard disks generate vibrations or a spin “feel” for the motor force to know its working. To be sure, make a note of the model/serial number before closing the computer case.
dmesg or the system logs will be the first place to check if storage is seen. The logs will have much more information than needed, grep will help filter out meaningful lines. For example, a newly connected disk is manufactured by Verbatim:
sudo dmesg | grep Verbatim
Will return all lines with the string “Verbatim”. Beware, this is case-sensitive:
[93537.128269] scsi 6:0:0:0: Direct-Access Verbatim Vi550 S3 010D PQ: 0 ANSI: 6
A disk connected via USB will also register as a USB device. This can be found in the dmesg, too, but a better place is lsusb:
sudo lsusb
Will list all USB connected devices:
...
Bus 004 Device 002: ID 152d:0562 JMicron Technology Corp. / JMicron USA Technology Corp. JMS567 SATA 6Gb/s bridge
...
The JMicron SATA bridge is the SATA controller in the USB disk caddy, so the string “Verbatim” will not appear here.
In almost all cases, the disk is seen using the legacy SCSI protocol (regardless whether M2, SSD or SATA), so the disk and partition identifiers are usually sda, sdb, sdc, etc. and a number after that will identify the partition number in order from beginning to end of disk. IDE disks are typically hda, hdb, hdc, etc.
It is possible to grep for disks with just the “sd” part of the device name:
sudo dmesg | grep sd
Will list all line items with that string:
[ 0.009783] ACPI: SSDT 0x00000000CD839760 002F08 (v01 SaSsdt SaSsdt 00003000 INTL 20091112)
[ 3.893515] sd 0:0:0:0: Attached scsi generic sg0 type 0
[ 3.921343] sd 0:0:0:0: [sda] 937703088 512-byte logical blocks: (480 GB/447 GiB)
[ 3.948518] sd 0:0:0:0: [sda] 4096-byte physical blocks
[ 3.962196] sd 0:0:0:0: [sda] Write Protect is off
[ 3.973983] sd 0:0:0:0: [sda] Mode Sense: 00 3a 00 00
[ 3.974001] sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[ 4.007079] sda: sda1 sda2
[ 4.026696] sd 0:0:0:0: [sda] Attached SCSI disk
[ 6.268778] EXT4-fs (sda2): mounted filesystem with ordered data mode. Opts: (null). Quota mode: none.
[ 6.647630] EXT4-fs (sda2): re-mounted. Opts: (null). Quota mode: none.
[93537.129363] sd 6:0:0:0: Attached scsi generic sg1 type 0
[93537.130320] sd 6:0:0:0: [sdb] 2000409264 512-byte logical blocks: (1.02 TB/954 GiB)
[93537.130528] sd 6:0:0:0: [sdb] Write Protect is off
[93537.130531] sd 6:0:0:0: [sdb] Mode Sense: 67 00 10 08
[93537.130919] sd 6:0:0:0: [sdb] Write cache: enabled, read cache: enabled, supports DPO and FUA
[93537.179051] sd 6:0:0:0: [sdb] Optimal transfer size 33553920 bytes
[93537.183562] sdb: sdb1 sdb5 sdb6 sdb7 sdb8
[93537.185458] sd 6:0:0:0: [sdb] Attached SCSI disk
The above output shows there are two recognised disks in this server, sda and sdb. sda has just two partitions, sda1 and sda2. sdb has many more, sdb1, sdb5, sdb6, sdb7, sdb8.
Partition numbers are 1-4 for primary partitions and 5 upwards for logical partitions.
Another way to see what is connected is with lsblk. This tool lists all block devices detected:
sudo lsblk
Output looks like this:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
loop0 7:0 0 62M 1 loop /snap/core20/1587
loop1 7:1 0 63.7M 1 loop /snap/core20/2434
loop2 7:2 0 87M 1 loop /snap/lxd/29351
loop3 7:3 0 89.4M 1 loop /snap/lxd/31333
loop4 7:4 0 38.8M 1 loop /snap/snapd/21759
sda 8:0 0 447.1G 0 disk
├─sda1 8:1 0 1M 0 part
└─sda2 8:2 0 447.1G 0 part /
sdb 8:16 0 7.3T 0 disk
└─sdb1 8:17 0 7.3T 0 part /mnt/temp
2 . Working with partition tables.
Assuming the disk is in good order and connected, fdisk will usually list what partitions it sees:
sudo fdisk -l
The listed partitions found:
Disk /dev/loop0: 61.96 MiB, 64970752 bytes, 126896 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
...
Disk /dev/sda: 447.13 GiB, 480103981056 bytes, 937703088 sectors
Disk model: INTEL SSDSC2BB48
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: 34815CF5-FCB8-47C8-8CF9-649F1E3C5D80
Device Start End Sectors Size Type
/dev/sda1 2048 4095 2048 1M BIOS boot
/dev/sda2 4096 937699327 937695232 447.1G Linux filesystem
Loop devices are in memory block devices or files mounted as block devices. These can be safely ignored. The output above shows the first disk (sda) is an Intel SSD, about 450GB and it has two partitions, sda1 is a boot partition and sda2 is a Linux filesystem.
Assume a new disk has been added to a server and is seen as sdb, fdisk can identify what is there, too:
sudo fdisk -l /dev/sdb
Lists all of sdb:
GPT PMBR size mismatch (2000409230 != 2000409263) will be corrected by write.
Disk /dev/sdb: 953.87 GiB, 1024209543168 bytes, 2000409264 sectors
Disk model: Vi550 S3
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 4096 bytes / 33553920 bytes
Disklabel type: gpt
Disk identifier: A029EFB1-DA5A-444A-914D-9ED6AB147B48
Device Start End Sectors Size Type
/dev/sdb1 64 204863 204800 100M EFI System
/dev/sdb5 208896 8595455 8386560 4G Microsoft basic data
/dev/sdb6 8597504 16984063 8386560 4G Microsoft basic data
/dev/sdb7 16986112 268435455 251449344 119.9G unknown
/dev/sdb8 268437504 2000409230 1731971727 825.9G VMware VMFS
This disk has an interesting partition table and appears to be a VMware boot disk. Mounting alien partitions is not really in the scope of this post, although it is possible to mount the partition and see or recover the files with the right commands.
In the example below, an 8TB Seagate drive is added to the server.
The drive is connected and can be seen by “fdisk -l”, in this case, the disk is /dev/sdc:
Disk /dev/sdc: 7.28 TiB, 8001563222016 bytes, 15628053168 sectors
Disk model: ST8000VN0022-2EL
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: C40A713E-6255-40C7-8500-93A52BF6BEDB
Device Start End Sectors Size Type
/dev/sdc1 34 32767 32734 16M Microsoft reserved
/dev/sdc2 32768 15627782831 15627750064 7.3T Microsoft basic data
Using fdisk, the disk can be cleaned, then a new partition is created with default settings:
root@server40:~# fdisk /dev/sdc
Welcome to fdisk (util-linux 2.37.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): d
Partition number (1,2, default 2):
Partition 2 has been deleted.
Command (m for help): d
Selected partition 1
Partition 1 has been deleted.
Command (m for help): n
Partition number (1-128, default 1):
First sector (34-15628053134, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-15628053134, default 15628053134):
Created a new partition 1 of type 'Linux filesystem' and of size 7.3 TiB.
Partition #1 contains a ext4 signature.
Do you want to remove the signature? [Y]es/[N]o: y
The signature will be removed by a write command.
Command (m for help): wr
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
Notice, in fdisk, hitting “d” deletes a partition. “n” is short for “new” partition and the default is to use all the free space. Nothing is written to the disk until “wr” which is short for “write” which updates the partition table and exits the application.
In some distributions, fdisk is not adequate for disks larger than 4TB. It might be necessary to use cfdisk, a newer tool. cfdisk has a basic text UI, so it might be easier to use for many.
Using cfdisk with sdb:
sudo cfdisk /dev/sdb
The interface is navigated with arrows, [tab], [spacebar] and [enter] keys:
Disk: /dev/sdb
Size: 953.87 GiB, 1024209543168 bytes, 2000409264 sectors
Label: gpt, identifier: A029EFB1-DA5A-444A-914D-9ED6AB147B48
Device Start End Sectors Size Type
>> /dev/sdb1 64 204863 204800 100M EFI System
Free space 204864 208895 4032 2M
/dev/sdb5 208896 8595455 8386560 4G Microsoft basic data
Free space 8595456 8597503 2048 1M
/dev/sdb6 8597504 16984063 8386560 4G Microsoft basic data
Free space 16984064 16986111 2048 1M
/dev/sdb7 16986112 268435455 251449344 119.9G unknown
Free space 268435456 268437503 2048 1M
/dev/sdb8 268437504 2000409230 1731971727 825.9G VMware VMFS
lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk
x Partition name: BOOT x
x Partition UUID: 3963C570-FFAE-4CC8-B172-D268B648AD13 x
x Partition type: EFI System (C12A7328-F81F-11D2-BA4B-00A0C93EC93B) x
xFilesystem UUID: 58ED-6D45 x
x Filesystem: vfat x
mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj
[ Delete ] [ Resize ] [ Quit ] [ Type ] [ Help ] [ Write ] [ Dump ]
In the above case, the entire disk is going to be reused, so each partition can be deleted by selecting and deleting each.
The option to create a new partition is only visible when some free space is selected:
Disk: /dev/sdb
Size: 953.87 GiB, 1024209543168 bytes, 2000409264 sectors
Label: gpt, identifier: A029EFB1-DA5A-444A-914D-9ED6AB147B48
Device Start End Sectors Size Type
>> Free space 2048 2000409230 2000407183 953.9G
[ New ] [ Quit ] [ Help ] [ Write ] [ Dump ]
The disk will be used with Linux, so the default type is okay. Otherwise it is possible to change the default type. Nothing will be saved unless the changes are written. The idiot proofing requires the word “yes” to be typed out as confirmation.
As a side note, and this post is not about disk recovery, creating a new partition table does not lose all data on the disk. The data is still there, and it can still be recovered.
Check the partition is written as expected with fdisk
sudo fdisk /dev/sdb
The newly created partition is shown:
Disk /dev/sdb: 953.87 GiB, 1024209543168 bytes, 2000409264 sectors
Disk model: Vi550 S3
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 4096 bytes / 33553920 bytes
Disklabel type: gpt
Disk identifier: A029EFB1-DA5A-444A-914D-9ED6AB147B48
Device Start End Sectors Size Type
/dev/sdb1 2048 2000409230 2000407183 953.9G Linux filesystem
3 . Formatting the partition.
The disk partition cannot be written to logically without a disk format of sorts. In this case the use is for typical data, so ext4, a modern filesystem, understood by almost all Linux distributions, will be used. In this case the partition on /dev/sdc, identified as /dev/sdc1 is being formatted with a tool mkfs. The defaults are accepted here because anything else is outside the scope of this post:
sudo mkfs.ext4 /dev/sdc1
The dialogue for formatting is printed:
mke2fs 1.46.5 (30-Dec-2021)
Creating filesystem with 1953506385 4k blocks and 244191232 inodes
Filesystem UUID: 1ce6678e-0aca-4c05-a62b-f3cdf295723d
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
102400000, 214990848, 512000000, 550731776, 644972544, 1934917632
Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done
By default Ubuntu server supports many format tools:
mkfs mkfs.cramfs mkfs.ext4 mkfs.msdos mkfs.xfs
mkfs.bfs mkfs.ext2 mkfs.fat mkfs.ntfs
mkfs.btrfs mkfs.ext3 mkfs.minix mkfs.vfat
Unless there is a particular need, go for ext4. It is a stable and reliable filesystem. Of course other types of operating systems may not see the files, for example, if the disk will be shared with Windows’ systems, then mkfs.vfat (FAT32) or mkfs.ntfs is a better choice.
If there is a problem with the device, this usually comes up while using the format tool:
mke2fs 1.46.5 (30-Dec-2021)
Creating filesystem with 250050897 4k blocks and 62513152 inodes
Filesystem UUID: 7db8a30a-21b7-4c32-aec4-967214280d22
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
102400000, 214990848
Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: mkfs.ext4: Input/output error while writing out and closing file system
4 . Mounting the disk.
To mount a disk temporarily at a server, the mount action must be manual. Desktop distributions have tools to auto-mount and auto-umount, for example, if a USB thumb-drive is used. For servers, the assumption is the disk is there to stay.
In either case a location needs to be made that is referred to when accessing the data, in this example the location will be descriptively called “VerbatimSSD”, it can be anything, anywhere, but most system administrators will look to /mnt/ first for a mount point. This is equivalent to drive letters in Windows.
sudo mkdir /mnt/VerbatimSSD
For a temporary use, at the command line, the disk can be mounted:
sudo mount /dev/sdb1 /mnt/VerbatimSSD
The disk mount can be checked with “mount” and “grep”:
sudo mount | grep Verbatim
And dmesg also has relative information if needed:
sudo dmesg | grep sdb1
The details listed:
[120980.484517] EXT4-fs (sdb1): mounted filesystem with ordered data mode. Opts: (null). Quota mode: none.
Temporary disks must be unmounted before they are removed, this ensures all cached data is written and the device is no longer in use:
sudo umount /dev/sdb1
It might be the case a server is restarted or a disk is removed and added at a later time. In that case the order of disks determines sda, sdb, sdc, etc. For this reason, it is better to mount disks by a partition serial number called a UUID. For example if the computer is rebuilt and the SATA cables are in a different order, it will not matter because the UUID will not change unless the disk is re-partitioned.
Find the disk UUID with the blkid utility:
sudo blkid | grep sdb
The resulting output contains the UUID:
/dev/sdb1: UUID="3284c7d6-f475-4dea-9a41-9f4803ffd532" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="c1258edc-630b-e84c-9d14-5c76f76d0070"
Almost all Linux distributions use a configuration file to detail the mount actions at boot, /etc/fstab. In this file many settings are established around connections to files, partitions and devices.
Assuming this server will mount the SSD, sdb1, as a temporary file location, /mnt/temp. First step is to create the mount path:
sudo mkdir /mnt/temp
Then mount he location by hand to be sure it actually works:
sudo mount /dev/sdb1 /mnt/temp
Check the location can be written to and read from:
sudo ls / > /mnt/temp/somefile.txt
sudo cat /mnt/temp/somefile.txt
To mount a disk permanently, by its UUID, add a line to the /etc/fstab file:
sudo nano /etc/fstab
/dev/disk/by-uuid/3284c7d6-f475-4dea-9a41-9f4803ffd532 /mnt/temp ext4 defaults 0 1
The defaults are used as this post is about a simple operation. IF required, it is possible to add some mount parameters here to change the characteristics of the mounted media, such as permissions, performance tuning, actions to take in error conditions, etc.
Restart the server to check the mount was permanent and successful. Remember the server will wait a long time for a timeout condition if there is a mount error and this will be displayed at the console. This may happen before sshd is loaded so it will only be possible to see with an attached monitor, at the physical server (or a console view if the server is virtual).
5 . Create a space alert with Discord.
If you followed this post with the setup of discord as an alerting service, create a script that contains these lines and runs periodically:
for i in $(df -h |grep /dev/ | grep -wv tmpfs | awk '{print $6}'); do /opt/discord/discord.sh "$(hostname)" "Space free on $(df -h $i | awk '{print $1,sum=100-$5"%"}' | tail -1)"; done;
This short script lists the free space on each mounted disk.
A summary alert can be created and sent once a week using something like crontab.
This post details how to setup a server monitoring tool, Checkmk.
6 . Supporting this blog.
This type of content takes a lot of effort to write. Each post is drafted, researched, then tested multiple times, even a simple step or detail might take more than a few hours to go from the idea to a published blog post.
Did you notice there are no adverts on this site and the posts are not AI generated?
If you feel I have saved you some time, you can support me by;
- hosting with DigitalOcean, like I do – click here to go to DigitalOcean.
- buying me a beer through PayPal – click here to go to PayPal.
©horsefreeglue.com, 2024. Unauthorized use and/or duplication of this material without express and written permission from this site’s author and/or owner is strictly prohibited. Excerpts and links may be used, provided that full and clear credit is given.