0%

Hello Ubuntu Server

Write the Image

Use Raspberry Pi Imager to install Ubuntu Server 20.04.2 LTS (64-bit) to a microSD card.
Raspberry Pi Imager
Click on “Write” and wait until it’s done. This can take a few minutes. Once done, depending on the options you’ve chosen, the card may be ejected.

Setup Wi-Fi

Navigate inside the root folder of the card. The name should be something like system-boot.
Find the file named network-config and open it in a text editor.
network-config
Uncomment line 15-21, and change line 20-21 to your Wi-Fi info.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# This file contains a netplan-compatible configuration which cloud-init
# will apply on first-boot. Please refer to the cloud-init documentation and
# the netplan reference for full details:
#
# https://cloudinit.readthedocs.io/
# https://netplan.io/reference
#
# Some additional examples are commented out below

version: 2
ethernets:
eth0:
dhcp4: true
optional: true
#wifis:
# wlan0:
# dhcp4: true
# optional: true
# access-points:
# myhomewifi:
# password: "S3kr1t"
# myworkwifi:
# password: "correct battery horse staple"
# workssid:
# auth:
# key-management: eap
# method: peap
# identity: "me@example.com"
# password: "passw0rd"
# ca-certificate: /etc/my_ca.pem

Set Static IP

Replace dhcp4: true line with the following:

1
2
3
4
5
6
7
8
ethernets:
eth0:
addresses:
- 192.168.101.23/24
gateway4: 192.168.1.1
nameservers:
addresses: [8.8.8.8, 8.8.4.4]
optional: true

Setup SSH

You should not need to do anything for SSH.
If you open user-data

1
2
3
4
5
6
7
8
9
10
11
12
13
...

# On first boot, set the (default) ubuntu user's password to "ubuntu" and
# expire user passwords
chpasswd:
expire: true
list:
- ubuntu:ubuntu

# Enable password authentication with the SSH daemon
ssh_pwauth: true

...

So, we’ll be able to connect to the Pi via SSH, and we have the initial username and password: ubuntu:ubuntu.

SSH in to PI

There are seveal ways to look for your new device’s IP, I won’t go into details.
On Windows, you can use Advanced IP Scanner.

I got my IP for the PI from my router (look for a device called ubuntu).
Now that you’ve obtained the IP, SSH in!

1
$ ssh ubuntu@192.168.1.2

Password should be ubuntu the first time you login.

Setup Ubuntu

First Things First - Update

1
2
$ sudo apt-get update
$ sudo apt-get upgrade

Set your time zone

Check the time

1
$ date

The default time zone will be UTC0.

List all available time zones.

1
$ timedatectl list-timezones

Run the following command to set the time zone

1
$ timedatectl set-timezone your_time_zone

For example

1
$ timedatectl set-timezone Europe/Paris.

NO-IP (Optional)

https://www.noip.com/support/knowledgebase/installing-the-linux-dynamic-update-client-on-ubuntu/

RAID 1 (Optional)

You can skip this setp if you are not planning to use RAID 1.
Learn about RAID in this article (An Introduction to RAID Terminology and Concepts) from DigitalOcean.

Delete Existing Partitions

Find the identifiers for the raw disks that you will be using:

1
$ lsblk -o NAME,SIZE,FSTYPE,TYPE,MOUNTPOINT

Output

1
2
3
4
5
NAME         SIZE FSTYPE   TYPE MOUNTPOINT
sda 4.5T disk
└─sda1 4.5T ext4 part
sdb 4.5T disk
└─sdb1 4.5T ext4 part

sda and sdb are what I’ll be using, and I want to get rid of the partitions.
Let’s delete it:

1
$ sudo fdisk /dev/sda

To delete partition, run the d command in the fdisk command-line utility.

1
2
Selected partition 1
Partition 1 has been deleted.

Reload the partition table to verify that the partition has been deleted. To do so, run the p command.

1
2
3
4
5
6
7
Disk /dev/sda: 4.55 TiB, 5000981077504 bytes, 9767541167 sectors
Disk model: BUP Portable
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: 0A457385-D922-4012-861A-51F6677BA9EF

Run the w command to write and save changes made to the disk.

1
2
3
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

Repeat the above steps for other drives, for me, it’s sdb
Check the partitions are gone:

1
$ lsblk -o NAME,SIZE,FSTYPE,TYPE,MOUNTPOINT

Output

1
2
3
NAME         SIZE FSTYPE   TYPE MOUNTPOINT
sda 4.5T disk
sdb 4.5T disk

Creating a RAID 1 Array

Create the Array

1
sudo mdadm --create --verbose /dev/md0 --level=1 --raid-devices=2 /dev/sda /dev/sdb

If the component devices you are using are not partitions with the boot flag enabled, you will likely be given the following warning. It is safe to type y to continue:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
mdadm: partition table exists on /dev/sda
mdadm: partition table exists on /dev/sda but will be lost or
meaningless after creating array
mdadm: Note: this array has metadata at the start and
may not be suitable as a boot device. If you plan to
store '/boot' on this device please ensure that
your boot-loader understands md/v1.x metadata, or use
--metadata=0.90
mdadm: partition table exists on /dev/sdb
mdadm: partition table exists on /dev/sdb but will be lost or
meaningless after creating array
mdadm: size set to 4883638464K
mdadm: automatically enabling write-intent bitmap on large array
Continue creating array? y

The mdadm tool will start to mirror the drives. This can take some time to complete, but the array can be used during this time. You can monitor the progress of the mirroring by checking the /proc/mdstat file:

1
cat /proc/mdstat

Output

1
2
3
4
5
6
7
Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10] 
md0 : active raid1 sdb[1] sda[0]
4883638464 blocks super 1.2 [2/2] [UU]
[===>.................] resync = 16.4% (803331264/4883638464) finish=708.5min speed=95974K/sec
bitmap: 33/37 pages [132KB], 65536KB chunk

unused devices: <none>

In the meanwhile, we can go ahead to create and mount the filesystem.

Create and Mount the Filesystem

Next, create a filesystem on the array:

1
$ sudo mkfs.ext4 -F /dev/md0

Create a mount point to attach the new filesystem:

1
$ sudo mkdir -p /mnt/md0

You can mount the filesystem by typing:

1
$ sudo mount /dev/md0 /mnt/md0

Check whether the new space is available by typing:

1
$ df -h -x devtmpfs -x tmpfs

Output

1
2
Filesystem      Size  Used Avail Use% Mounted on
/dev/md0 4.6T 89M 4.3T 1% /mnt/md0

The new filesystem is mounted and accessible.

Save the Array Layout

1
$ sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf

You can update the initramfs, or initial RAM file system, so that the array will be available during the early boot process:

1
$ sudo update-initramfs -u

Add the new filesystem mount options to the /etc/fstab file for automatic mounting at boot:

1
$ echo '/dev/md0 /mnt/md0 ext4 defaults,nofail,discard 0 0' | sudo tee -a /etc/fstab

RAID 1 array should now automatically be assembled and mounted each boot.

NextCloud

1
$ cd /mnt/md0
1
$ mkdir nextcloud

Replace $DOMAIN with your IP/Domain

1
$ docker run -d -p 4443:4443 -p 443:443 -p 80:80 -v /mnt/md0/nextcloud:/data --name nextcloudpi ownyourbits/nextcloudpi $DOMAIN

Get the container ID

1
$ docker ps
1
$ docker update --restart unless-stopped <container-id>

PLEX (Optional)

If you want to have a media server for streaming and to organize video, audio, and photos, here’s how:
Create a folder

1
2
$ mkdir plex && cd plex
$ touch docker-compose.yml

Use your preferred text editor to open docker-compose.yml, copy and paste the following, make sure to change volumes according to your folder structure.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
---
version: "2.1"
services:
plex:
image: ghcr.io/linuxserver/plex:arm64v8-latest
container_name: plex
network_mode: host
environment:
- PUID=1001
- PGID=100
- VERSION=docker
- PLEX_CLAIM= #optional
volumes:
- /root/docker/plex/config:/config
- /mnt/md0/nextcloud/nextcloud/data/username/files/Media/Movies:/movies
- /mnt/md0/nextcloud/nextcloud/data/username/files/Media/TV Series:/tv
- /mnt/md0/nextcloud/nextcloud/data/username/files/Media/Animate:/animate
- /mnt/md0/nextcloud/nextcloud/data/username/files/Media/Music:/music
restart: unless-stopped

To get it running:

1
$ docker-compose up -d

If you need to update:

1
$ docker-compose pull and then docker-compose down && docker-compose up -d

I will share my experiences below on how I managed to mount a single hard disk that was part of RAID 1 and the issues I’ve encountered during the process.

First, do lsblk to prints all block devices.

1
2
3
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sde 8:64 0 4.5T 0 disk
└─sde1 8:65 0 4.5T 0 part

In this case, sde1 is what I was looking for.
I proceeded to run the following command:

1
$ mdadm --assemble --run /dev/md2 /dev/sde1

And encountered the following:

1
2
mdadm: Found some drive for an array that is already active: /dev/md/ubuntu:0
mdadm: giving up.

This is caused by mdadm complaining that you’re trying to assemble an array with a UUID matching one already running.
We can fix this by changing the UUID on the /dev/sde1 superblock when we assemble it.

To find the old UUID:

1
$ mdadm --examine /dev/sde1

Results

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/dev/sde1:
Magic : a92b4efc
Version : 1.2
Feature Map : 0x1
Array UUID : e1dc032e:d7d02935:71895af8:53eea165
Name : ubuntu:0
Creation Time : Tue Mar 30 18:23:45 2021
Raid Level : raid1
Raid Devices : 2

Avail Dev Size : 9767274496 (4657.40 GiB 5000.84 GB)
Array Size : 4883637248 (4657.40 GiB 5000.84 GB)
Data Offset : 264192 sectors
Super Offset : 8 sectors
Unused Space : before=264112 sectors, after=0 sectors
State : clean
Device UUID : cb083a67:de3131fa:ad29c9a8:7e44fbfb

Internal Bitmap : 8 sectors from superblock
Update Time : Wed Mar 17 17:36:14 2021
Bad Block Log : 512 entries available at offset 32 sectors
Checksum : 6854a473 - correct
Events : 64302


Device Role : Active device 0
Array State : AA ('A' == active, '.' == missing, 'R' == replacing)

Finally, excute ths following command:

1
$ mdadm --assemble /dev/md11 --update=uuid --uuid=<newuuid> /dev/sde1

For me, I just changed the last character to a instead of b:

1
$ mdadm --assemble /dev/md11 --update=uuid --uuid=cb083a67:de3131fa:ad29c9a8:7e44fbfa /dev/sde1

First look for the avalible versions that is installed on your mechine

1
$ archlinux-java status

Available Java environments:
java-11-openjdk
java-8-openjdk (default)

To change to the desired version, we can do

1
$ sudo archlinux-java set java-11-openjdk

Setup docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
version: "3.9"

services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somepassword
MYSQL_DATABASE: db_name
MYSQL_USER: db_user
MYSQL_PASSWORD: password

wordpress:
depends_on:
- db
image: wordpress:latest
volumes:
- ./website:/var/www/html
- ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: db_user
WORDPRESS_DB_PASSWORD: password
WORDPRESS_DB_NAME: db_name
volumes:
db_data: {}

website is the local directory for WordPress, which can be named to something else.

Create uploads.ini

1
2
3
4
5
file_uploads = On
memory_limit = 500M
upload_max_filesize = 500M
post_max_size = 500M
max_execution_time = 600

First look for the drive that you want to mount:

1
$ sudo lsblk

Look for UUID, make sure you replace the name with the one you found using the above:

1
$ sudo blkid /dev/sdNAME

Make an empty folder located at /foldername if one didn’t already exist… if one does exist it needs to be an empty folder.

1
$ sudo mkdir /foldername

Finally, add the following to /etc/fstab:

1
2
# Mount my SSHD
UUID=0AED64E911A2FB1E /foldername ntfs defaults 0 2

Save the file and make sure the partition/drive isn’t already mounted previously, then type:

1
sudo mount -a

CD into the directory where you store your music:

1
$ mid3iconv -e GBK *.mp3

If there is no prompt, try a few more times,
It is possible that the system will prompt:
python-mutagen is not installed.

1
$ sudo apt-get install python-mutagen

Then, retry.
If you want to convert all mp3s in the current directory (including subdirectories):

1
$ find . -iname "*.mp3" -execdir mid3iconv -e gbk {} \;

1
$ dconf write /org/gnome/shell/extensions/dash-to-dock/isolate-workspaces true

Or you can try:

1
$ gsettings set org.gnome.shell.extensions.dash-to-dock isolate-workspaces true

Foreword

Your system may include multiple Python versions, the default alias for python might be using a version that you don’t want to work with.
Use the following command to find out what Python binary executables are avaliable:

1
2
3
$ ls /usr/bin/python*
/usr/bin/python /usr/bin/python2.7 /usr/bin/python3.7 /usr/bin/python3.8
/usr/bin/python2 /usr/bin/python3 /usr/bin/python3.7m

To check what is your default python version execute:

1
2
$ python --version
Python 2.7.8

Change python default on per user basis

Open ~/.bashrc file and add the following alias to change the default python executable:

1
alias python='/usr/bin/python3.4'

Re-login after you made the change.

1
2
$ python --version
Python 3.8.2

Change python default system-wide

To change python version system-wide we can use update-alternatives command. Logged in as a root user, first list all available python alternatives:

1
2
3
$ update-alternatives --list python
/usr/bin/python3.7
/usr/local/bin/python3.8

Adding alternatives

If you don’t have any alternatives, use the following command to add:

1
2
3
4
$ update-alternatives --install /usr/bin/python python /usr/bin/python2.7 1
update-alternatives: using /usr/bin/python2.7 to provide /usr/bin/python (python) in auto mode
$ update-alternatives --install /usr/bin/python python /usr/bin/python3.8 2
update-alternatives: using /usr/bin/python3.8 to provide /usr/bin/python (python) in auto mode

--install is used to create a symbolic link. The number a the end is for setting the priority, the higher the number, the larger the priority.

Switch default

1
$ update-alternatives --config python

Remove alternatives

In case we no longer have an alternative python version installed, we can remove its update-alternatives listing.

1
2
3
$ update-alternatives --remove python /usr/bin/python2.7
update-alternatives: removing manually selected alternative - switching python to auto mode
update-alternatives: using /usr/bin/python3.8 to provide /usr/bin/python (python) in auto mode

Foreword

If you upgraded to the new Pop!_OS 20.04 recently, you might have experienced issues with screen rotations if you have a multi-monitor setup. If you rotate a secondary display from gnome display configuration left or right, it does not rotate.

The issue are being tracked here:
https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/974
https://bugs.launchpad.net/ubuntu/+source/gnome-shell/+bug/1874217

Solution

Use ARandR to create a script and add it to startup applications.

Create a layout script using ARandR and save it into a place you prefer.

This is what I have in my script:

1
2
#!/bin/sh
xrandr --output DVI-D-0 --off --output HDMI-0 --primary --mode 1920x1080 --pos 1080x420 --rotate normal --output DP-0 --off --output DP-1 --off --output DP-2 --off --output DP-3 --off --output DP-4 --off --output DP-5 --mode 1920x1080 --pos 0x0 --rotate right

Important note:
Sometimes xrandr commands can break if they are run too early before the desktop is fully loaded. Therefore you might want to add a break into the command:

1
2
#!/bin/sh
sleep 10&&xrandr --output DVI-D-0 --off --output HDMI-0 --primary --mode 1920x1080 --pos 1080x420 --rotate normal --output DP-0 --off --output DP-1 --off --output DP-2 --off --output DP-3 --off --output DP-4 --off --output DP-5 --mode 1920x1080 --pos 0x0 --rotate right

Add to startup applications

I named my script “dual_monitor.sh” so I will add the following line to the command:

1
/bin/bash /path/to/dual_monitor.sh

Welcome to my blog! This is my very first post.