Wiki/Guides/Arch/Server.md
2025-05-05 04:21:23 +02:00

88 KiB

title, description, published, date, tags, editor, dateCreated
title description published date tags editor dateCreated
Server true 2024-11-24T11:38:12.406Z markdown 2023-04-28T08:02:53.316Z

Introduction

This guide will set you up with a fresh Arch Linux installation set up as a server with the basics, Once you are done with this guide you can go to the docker guides and host any service you want yourself.

But before we can go there you need to understand a few things.

Basic Instructions

Understand a command before you execute it, Executing code you don't understand is the best way to break your machine, let your machine get raped, get scammed, or end up in prison. So understand every letter of a command before you execute it.

Be sure to read everything, On this page but also the output of the terminal. Not only because you need to know what you are doing, but also because there are a lot of parameters that need to be changed.

No response means everything went well, If you get an error back make sure you typed the command correctly

Basic Commands

Troughout the guide we will use several basic commands, The guide assumes you know what they do, And I do not allow you to run a command you do not understand.

pwd print working directory If you type pwd in a terminal and press enter it will show in which directory you are at the moment.

ls list it will display all contents of the current directory. I would recommend using this with the options -a and -l ls -la would list all files including hidden files in a list with some handy details.

mkdir make directory creates a directory. mkdir bla would create a folder called bla in the current directory

cd change directory change to a different directory. cd bla would move you to the folder bla in the current directory.

touch touch it will create a file and update the time if it already exists. touch bla would create an empty file called bla

cp copy it will copy a file cp file1 file2 would copy file1 to file2, cp -r folder1 ../folder2 would copy folder 1 to folder2 next to this directory.

mv move move does the same as copy, only it will move the file or folder and not leave a duplicate, This command is also used to rename files and folders using mv file1 file2 will rename file1 into file2.

ln link link is used to create links between files, kind of like "Shortcuts" on Windows. we create links like this ln -sf realfile linkfile now linkfile will point to realfile and if you make changes to one both will be affected.

exit exit Kinda obvious, but here we exit the shell, if you open bash by typing bash pressing enter and then type exit and press enter you would be back in the terminal where you started.

reboot reboot Also very obvious, this one reboots your machine, just type reboot and press enter

chmod change mode With this you can change the permissions on a file or folder like so chmod +x file it would make file executable for everyone, you can do + and - to add and remove permissions, r is read, w is write and x is execute. You can also use numbers like so chmod 755 file it would give all permissions to the owner, but only read and execute for the group and others. 4 is read, 2 is write, 1 is execute, you can add them to give multiple rights, so 4 would be read, 6 would be read and write, 7 would be all rights. chmod 421 file would make the file readable for only the owner, writeable for only the group, and executable only for others.

chown change owner This changes the owner of a file, a file has a owner, and a file belongs to a group, you can set both like so chown owner:group file file will now be owned by owner and belong to the group group.

echo echo echo simply repeats whatever argument you give it echo Hello would print back "Hello"

sudo super user do sudo allows you to execute commands as a different user it is mostly used for executing something as the root user sudo bash would open a new terminal as the root user. It is not recommended to use your system as the root user, therefore sudo was invented, just use sudo if you need to do something as root. But again, know what you execute.

There are lots and lots more, but these are all you need to know for this guide.

Basic Syntax

space The space is a seperator, it seperates commands from the options and the options from the arguments, different forms of whitespace can be used

/ forward slash this means next folder if you lead with it you will get an absolute path /home/user/file is an absolute path. ./file or file is a relative path, it will expect file in the current directory

. period Current directory, you can use it as an argument for many commands it is most often used to execute something in or on the current directory like ./executable or chown user .

.. double period Upper Directory, probably most often used for cd like so cd ../.. to go up 2 directories you can also use it to execute a file in a relative directory like so ../folder/executable

\ backslash Escape character, is used for lots of things, but we only use it for when we want to use a character that has a special meaning, for example space, if we want open a file with vim called "A B C" we would run this command vim A\ B\ C

> Is Greater Than overwrite file, when you see this character in a command it is redirecting the output, for the scope of this guide we will use it to redirect output to a file but appending a file behind it, like so echo Hello > file will overwrite the content of file with Hello.

>> Double Is Greater Than add to end of file, it does the same as the Greater Than above, but this one doesn't overwrite but adds the output on a new line in the file.

* Asterisk wildcard, expands to everything you can use it to open all files in the current directory using vim * only open .c files with vim *.c or open all files in every folder vim */* ofcourse this also works with absolute paths.

There are lots and lots more, but this is all the syntax you need to know for this guide

Vim Basics

Vim is this amazing text editor, it is without a doubt the best text editor in existance, you can do more with it than you will ever be able to remember. all in such a nice small extendable package. Yes emacs can do more, But we just want a text editor, not play tetris and browse the web :P

One important thing to know about vim is that it uses different modes, and in the "normal" mode you can't insert characters normally. There are 3 modes in vim; Normal, Insert and Visual.

Normal mode is the default mode in Vim, you can always go back to it from other modes by pressing esc on your keyboard. In Normal mode you can look at the file, execute commands that start with : search for something by pressing / and much much more.

Insert mode is where we edit the file as if it was a normal text editor, you can press i to go into it after the cursor, there are different ways to get into it, but they are out of scope for this guide.

Visual mode is not relevant for this guide, but you can use it, if you press v from normal mode you go into visual mode to select text, d to cut and y to copy. You can also select whole lines with shift + v and select a block with ctrl + v

The last thing you need to know are commands, with these commands you can save a file, quit vim, or manipulate the text in ways you can't imagine, listing all commands and explaining it alone would make this guide much larger than it is now, so just a few relevant ones.

go to the end of the line by pressing $ go to the beginning with 0 go to the end of file with G go back to the beginning with g go to line 34 with 34gg paste content with p cut a line with dd to save a file type :w and press enter to quit vim type :q and press enter to force an action like q and w add ! to your command like this :q! or :w! You can also combine actions like so :wq! to execute a terminal command type :! command and press enter

Preparation

Creating the Bootable USB

First we need to download the latest version of the Arch installation media

Open a webbrowser and go to https://www.archlinux.org/download/

Here you can download the latest image, I recommend using the Torrent or Magnet link, But if you don't have a torrent client you can scroll down for HTTP downloads.

Wait for the download to finish.

Next we need to burn the ISO file to an empty USB

If you are already on Linux you probably know how to flash an image to USB, if not try to right click the .ISO file and open with image writer, Just select the right drive and click write/flash/revert

If you are on Windows I recommend downloading Etcher

https://www.balena.io/etcher/

Just download the portable version or install the normal version and open the program

Select the .ISO file as the image, The USB as the drive and click flash

After it is finished you should have a bootable Arch USB.

Booting the USB

Next we need to boot the USB drive, We need to get in the BIOS for that.

Turn off the device and put the USB in the device and keep pressing f2/Del/etc while turning it on to get into your BIOS, Most of the times you will get a screen where it tells you which button you need to press to enter the BIOS

When you are in the BIOS Navigate to the boot screen and make sure the USB is on top. In most cases you can change their priority with F5/F6 or +/-.

Press F10, select yes and press enter to save the settings and reboot,

Now you just have to wait untill you are logged in as the root user on the arch iso

Check your boot mode

Run the following command to see if you are running in UEFI mode

ls /sys/firmware/efi/efivars

If it shows you a bunch of filenames you are in UEFI mode.

If you get an error you are in BIOS mode. If you are sure your system has UEFI disable legacy boot mode or force UEFI in the BIOS. If you can not get the USB to boot into UEFI you can use the legacy mode.

Remember which boot mode you use, It will be important later on.

Set your Keyboard Layout for the installation

If you use US International as your keyboard layout you can skip this step.

To list all available keyboard layouts run

localectl list-keymaps

navigate with the arrow keys to choose the right keyboard layout for your keyboard when you made your choice press q to quit and run the following command with your keyboard layout

loadkeys layout

for Turkey layout would be replaced with trq for German it would be replaced with de-latin1

If you have set a custom layout remember which layout you set, It will be important later on.

Make sure you have a network connection

If you are wired you can skip the WiFi step But test the connection either way.

If you use Wifi or have no option to connect a cable run the following command

iwctl

You should spawn in an alternative prompt, run the following command to check for devices

device list

Remember the name of the device and use it in the following command to let it scan for networks

station wlan0 scan

Then run the following command to display the scan results

station wlan0 get-networks

And finally you should be able to connect using the Device name and the Network Name (SSID)

station wlan0 connect SSID

Simply enter the password of your wifi if it asks for it.

then exit the alternative prompt with the following command

exit

run the following command to test your network connection.

ping archlinux.org

If you get a ping back hit CTRL + C and go to the next step

It your network device is powered down it is probably soft blocked, in that case run the following command

rfkill unblock all

Make sure the time is set correctly

Not having the right time will prevent your system from installing anything so run the following command

timedatectl set-ntp true

Check which disk you want to install Arch on Run the following command to list all connected drives

fdisk -l

Check which disk you want to install on, /dev/sda or /dev/nvme0n1 for example, I am going to use /dev/nvme0n1 from this point on, Remember or write down the drive you want to install on and always replace /dev/nvme0n1 with the right drive.

Formatting Disks

Partitioning the disk (UEFI)

Only do this part if you are in UEFI boot mode.

Start fdisk with the drive of your choice.

fdisk /dev/nvme0n1

Now we are in fdisk, you can press m for help in the program, But if you do exactly as below everything should be alright

Disk Options

  1. Hit d and then enter untill there are no more partitions left.
  2. Hit g Then press enter, This will make it a gpt disk

Boot Partition

  1. Press n and then enter to make our first partition
  2. press 2 and press enter to give it partition number 2
  3. just press enter to put it in the beginning of the disk
  4. type +2G to give it 2GB for the boot partition and press enter
  5. press t and press enter to set the type
  6. skip this step if 2 is preselected otherwise, press 2 and press enter to select the second partition
  7. type 1 and hit enter this will make the second partition an EFI partition.

Swap Partition

  1. press n and press enter to create our swap partition
  2. press 3 and press enter to give it partition number 3
  3. press enter again to put it next to the previous partition
  4. type +8G to give it 8GB swap, If you have less ram I would recommend making it equal to your ram, So +4G if you have 4GB Ram.
  5. press t and press enter to set the type
  6. press 3 and press enter to select the third partition
  7. type 19 and hit enter this will make the third partition a Swap partition.

Root Partition

  1. press n to create our final root partition
  2. press 1 and press enter to give it partition number 1
  3. press enter again to put it next to the previous partition
  4. press enter again to give it the remaining space on the disk.
  5. press t and press enter to set the type
  6. press 1 and press enter to select the first partition
  7. type 20 and press enter this will make the first partition a Linux filesystem.

Apply changes

  1. Finally hit w and press enter to write all changes to disk

Partitioning the disk (BIOS)

Only do this part if you are in BIOS boot mode.

Start fdisk with the drive of your choice.

fdisk /dev/nvme0n1

Now we are in fdisk, you can press m for help in the program, But if you do exactly as below everything should be alright

Disk Options

  1. Hit d and then enter untill there are no more partitions left.
  2. Hit o Then press enter, This will make it a mbr disk

Boot Partition

  1. Press n and then enter to make our first partition
  2. press p and press enter to make it a primary partition
  3. press 2 and press enter to give it partition number 2
  4. just press enter to put it in the beginning of the disk
  5. type +2G to give it 2GB for the boot partition
  6. press t and press enter to set the type
  7. press 2 and press enter to select the second partition
  8. type 83 and hit enter this will make the second partition an EFI partition.

Swap Partition

  1. press n and press enter to create our swap partition
  2. press p and press enter to make it a primary partition
  3. press 3 and press enter to give it partition number 3
  4. press enter again to put it next to the previous partition
  5. type +8G to give it 8GB swap, If you have less ram I would recommend making it equal to your ram, So +4G if you have 4GB Ram.
  6. press t and press enter to set the type
  7. press 3 and press enter to select the third partition
  8. type a and hit enter this will make the third partition a Swap partition.

Root Partition

  1. press n to create our final root partition
  2. press p and press enter to make it a primary partition
  3. press 1 and press enter to give it partition number 1
  4. press enter again to put it next to the previous partition
  5. press enter again to give it the remaining space on the disk.
  6. press t and press enter to set the type
  7. press 1 and press enter to select the first partition
  8. type 82 and press enter this will make the first partition a Linux filesystem.

Apply changes

  1. Finally hit w and press enter to write all changes to disk

Format Partitions

Now we have set the partitions and the labels now we are going to format them all

Be sure that you replace /dev/nvme0n1p# with the correct drive and partition If if is /dev/sda be sure to include the partition number /dev/sda1, /dev/sda2 and /dev/sda3. For the /dev/nvme0n1 you need to add a p and then the partition number so /dev/nvme0n1p1, /dev/nvme0n1p2 and /dev/nvme0n1p3

First we need to give the root partition a filesystem You can opt for btrfs, f2fs or ext4.

btrfs is a newer filesystem with a lot of very cool features, It is not great for databases tho, so if you plan to go for a server it is not the best choice if your database is going to be on your root partition. I have not tested this one with encryption. But let me know how it goes :)

f2fs is made with SSDs in mind, it might be the best choice for SSDs. Also not tested this one with encryption, But let me know how it goes :)

ext4 is very stable and thourogly tested, you can't really go wrong with this one.

So pick a single one of the following options

mkfs.btrfs /dev/nvme0n1p1
mkfs.f2fs /dev/nvme0n1p1
mkfs.ext4 /dev/nvme0n1p1

Then we make the boot partition fat 32

mkfs.fat -F32 /dev/nvme0n1p2

Make partition 3 swap

mkswap /dev/nvme0n1p3

Then enable swap on partition 3

swapon /dev/nvme0n1p3

Full Disk Encryption (Optional)

Encryption is completely optional, If you don't want it, just skip this step completely.

Many things can go wrong, and if you forget your password the data is lost, Nothing you can do to recover it. Use it at your own risk.

I would recommend Encryption for Mobile devices that hold sensitive data, Laptops you take with you for example.

I would not recommend Encryption for desktops, unless you are worried someone can get physical access.

make the root partition an LUKS partition

cryptsetup -y -v luksFormat /dev/nvme0n1p1

Mount the encrypted partition to cryptroot

cryptsetup open /dev/nvme0n1p1 cryptroot

Create a ext4 filesystem on the encrypted partition

mkfs.ext4 /dev/mapper/cryptroot

You can also encrypt swap if you want to

swapoff /dev/nvme0n1p3

cryptsetup -y -v luksFormat /dev/nvme0n1p3

cryptsetup open /dev/nvme0n1p3 cryptswap

mkswap /dev/mapper/cryptswap

swapon /dev/mapper/cryptswap

You can encrypt any partition you want, just don't encrypt the boot partition because this guide doesn't cover that, and it is pretty useless imho.

Mounting the partitions

now we are going to mount the 2 partitions and create the /boot directory

Be sure that you replace /dev/nvme0n1p# with the correct drive and partition If it is /dev/sda be sure to include the partition number /dev/sda1 and /dev/sda2. If it is /dev/nvme0n1 you need to add a p and then the partition number so /dev/nvme0n1p1 and /dev/nvme0n1p2.

mount the first partition to /mnt, if you use encryption you mount /dev/mapper/cryptroot here

mount /dev/nvme0n1p1 /mnt

create the /boot directory

mkdir /mnt/boot

mount the second partition to /mnt/boot

mount /dev/nvme0n1p2 /mnt/boot

Base Install

Install the base system

The following command will install the base system and a text editor we need later on.

pacstrap /mnt base base-devel vim

Install a Kernel

You can stick to the normal kernel, but you have options

For Desktop use I would recommend the zen kernel

For A Server I would recommend the hardened kernel

so install the kernel you want with one of the following commands

pacstrap /mnt linux linux-headers

pacstrap /mnt linux-zen linux-zen-headers

pacstrap /mnt linux-hardened linux-hardened-headers

Generate the fstab file

Generating the fstab file will take all mounted partitions and add them to a file so they mount at boot so if you have any more drives you want to mount at boot mount it before you run the command.

Run the following command

genfstab -U /mnt > /mnt/etc/fstab

chroot into the new system

chroot is a tool to treat any directory as its root directory, In a way we "break" into the system from the live image, So we will switch from USB to your drive with the following command.

arch-chroot /mnt

Set your timezone and time

If you are unsure about your timezone you can list all timezones with the following command.

timedatectl list-timezones

go up and down with the arrows look for your timezone and hit q to exit.

Next we are going to change the timezone to the one you selected

ln -sf /usr/share/zoneinfo/your/timezone /etc/localtime

Replace your/timezone with your correct timezone Europe/Amsterdam for example

Finally run hwclock to generate the time file

hwclock --systohc

Generate the locale and set the language

run the following command and remove the # in front of en_US.UTF-8 UTF-8 and any other locales you need.

vim /etc/locale.gen

Hit esc then :wq and enter to save and exit

Run the following command to generate the locales

locale-gen

Next we are going to set the language run the following command

vim /etc/locale.conf

The language you want your system to be should be in this file in this form, if you want it Dutch for example you change en_US.UTF-8 to nl_NL.UTF-8

LANG=en_US.UTF-8

Hit esc then :wq and enter to save and quit

If you have not set a different keyboard layout in the earlier part "Set your keyboard layout for installation" you can skip the rest of the commands in this step.

If you have set a different layout back in the earlier part "Set your keyboard layout for installation" run the following command

vim /etc/vconsole.conf

add the keyboard layout you set in the beginning.

KEYMAP=layout

layout should be trq for Turkish and de-latin1 for German

Hit esc then :wq and enter to save and quit

Set the hostname and hosts file

Next we are going to set the hostname, This is the name of your device in the local network.

vim /etc/hostname

enter a good name for your device without any capital letters or spaces. You can just call it laptop or personal-computer

coolcomputername

Hit esc then :wq and enter to save and quit

Now we have to create a file, run

vim /etc/hosts

Type exactly whats below replacing yourdevicename with the name you just gave your device in /etc/hostname

You can use the tab key for the spaces to make it lign up properly

127.0.0.1	localhost
::1				localhost
127.0.1.1	yourdevicename.localdomain	yourdevicename

Hit esc then :wq and enter to save and quit

Set the root password

now we have to set a root password

The root user is like the superuser or administrator account, You will need this password to update your system or change anything outside your personal home folder.

run the following command then type your new password, hit enter, then again to confirm.

passwd

Configure Pacman

Pacman is the PACkage MANager of Arch Linux, It is great, but we can make it even better :)

First we are going to open the pacman.conf file to make some adjustments

vim /etc/pacman.conf

Under Misc Options uncomment UseSysLog, Color and Parallel Downloads You can also up the number. And add ILoveCandy to get the other Pacman to appear too :)

# Misc options
UseSyslog
Color
#NoProgressBar
CheckSpace
#VerbosePkgLists
ParallelDownloads = 16
ILoveCandy

Also add base and grub after HoldPkg

HoldPkg     = pacman glibc base grub

Hit esc then :wq and enter to save and quit

Next up are the mirrors, The defaults are okay and this takes a while, but for faster speeds I would seriously recommend this step. So go ahead and install reflector

pacman -S reflector

then just run reflector with the following command

reflector --latest 200 --protocol https --sort rate --save /etc/pacman.d/mirrorlist

You will see a bunch of errors but that is normal, just let it run and wait untill the prompt shows up again.

Install Microcode (Optional) PROPRIETARY

Now we are going to install the microcode, this is PROPRIETARY but it will improve stability, choose the right one for your CPU, you can install none if you are in doubt or don't want any non free software on your machine.

AMD

pacman -S amd-ucode

Intel

pacman -S intel-ucode

install and configure grub

grub stands for GRand Unified Bootloader just so you know. Now we are going to install grub, only do UEFI or BIOS depending on your system

UEFI

pacman -S grub efibootmgr

grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=Arch

grub-mkconfig -o /boot/grub/grub.cfg

BIOS

pacman -S grub

grub-install --target=i386-pc /dev/nvme0n1

grub-mkconfig -o /boot/grub/grub.cfg

Full Disk Encryption (Optional)

if you did the first Encryption part you can NOT skip this step

If you did not go for disk encryption after formatting the disks you MUST skip this step

First we need to get the UUID of the root partition of /dev/nvme0n1p1 in this case and remember it

blkid

We need to include it in the grub config so open the grub file

vim /etc/default/grub

Look for the following GRUB_CMDLINE_LINUX_DEFAULT somewhere at the top

GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet"

Adjust it so the line looks like this remember that you have to replace UUID with the correct UUID.

GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet rd.luks.name=UUID=root root=/dev/mapper/root"

Now let grub generate a new config file

grub-mkconfig -o /boot/grub/grub.cfg

Open the mkinitcpio.conf file

vim /etc/mkinitcpio.conf

Look for the following HOOKS line, it should be somewhere at the bottom

HOOKS=(base udev autodetect modconf block filesystems fsck)

Make it look like this (order is important)

HOOKS=(base systemd autodetect keyboard modconf block sd-encrypt filesystems fsck)

finally run the following command to generate the new image

mkinitcpio -p linux

Creating the user

Now it is time to create a user account, This is where you log into, It can do almost everything except install software or change things outside of your personal folder.

you need to remember your username and you can not have capital letters in your username

useradd -m yourusername

Set a password for the user, You will log into the device with this password, You can make it the same as the root account.

passwd yourusername

enter a new password and press enter twice

install and configure sudo

Sudo allows you to do root stuff while logged in as a user, It will probably become your most used command so install it.

pacman -S sudo

Now we need to add your username to the sudoers file, run the following command

vim /etc/sudoers

Look for the lines under User Privilege Specification There should be a line root ALL=(ALL) ALL Add your username in the exact same manner one line below it so that part looks like this.

root ALL=(ALL:ALL) ALL
yourusername ALL=(ALL:ALL) ALL

You can also make your computer try to insult you if you enter a wrong password, Just add a line with the following content under the Defaults Specification

Defaults insults

Hit esc then :wq and Enter to save and quit

Installing DHCP

For network capabilities we need a DHCP client so install it

pacman -S dhcpcd

That's it

Reboot into your Installation

Run the following command to escape from the chroot

exit

Run the following command to restart

reboot

Remove the USB when your screen turns black and it should boot into a login prompt

Configure network

Configuring the network is easy with dhcpcd but first we need to know what device we want to enable

ip address

It should show you a bunch of devices, Ignore lo, there can be multiple, for me it is enp4s0.

so I run the following command to activate the network

sudo systemctl enable --now dhcpcd@enp4s0

You can then test with ping if it works, if it works you can go on, if not you can disable it again with sudo systemctl disable --now dhcpcd@enp4s0 and try other network devices listed by the previous command.

Point Domains to your server

If you have any domains, you first need to edit their DNS records to point to your Server.

First we need our public IP so run the following command

host myip.opendns.com resolver1.opendns.com 

Next up you go to your domain registrar, I can recommend Dynadot.com if you don't have one

You simply login go to domain settings, look for the DNS records and let it point to your IP It should look something like this

A    domain.tld      PublicIP
A    *.domain.tld    PublicIP

The A refers to IPv4, If you need IPv6 you just add both records again this time with AAAA

domain.tld should be replaced with your custom domain, the *.domain.tld is for all subdomains.

If you have a TTL setting, just put it on the lowest possible value and don't forget to save.

Set Static IP for Server

You need a Static IP on your internal network so you can open ports on that internal IP without the device switching internal IP randomly

For this you need to login into your router, This can be a pain, If you have no idea I recommend resetting it and use the default password to login.

In the router interface you have to look for Static IP or DHCP reservation or something like that.

run the following command and look at the hardware address or MAC/link/ether address for your network device it should look something like this ab:cd:f0:12:34:56

ip address

Now you need to combine the mac address of the server with a static IP given by you, It might be good to plan out your network create different vlans like 192.168.1.X for your servers 192.168.2.X for your trusted devices 192.168.3.X for your smarthome devices and 192.168.4.X for a free wifi guest network, This way you have a seperated network for your home and servers, you can block all smarthome devices from phoning home by just blocking the subnet with 1 rule and you can seperate guests from your own devices. we are going to assume you made a subnet 192.168.1.X for your servers, and this server is 192.168.1.10.

So Mac Adress ab:cd:f0:12:34:56 needs to be assigned the local IP of 192.168.1.10.

Make sure you save, Then reboot your server and it should move over to the assigned local IP.

Open two ports to your server

For now we are only going to open the ports 80 and 443 for http and https respectively

Still in your router interface you have to look for "port forward", Don't worry about clicking trough the menus, as long as you don't press save anywhere you should be fine :)

If you found the port forwarding screen you need to open ports 80 and 443 over TCP to the local static IP of your server. So in this example case

192.168.1.10 TCP 80 192.168.1.10 TCP 443

Make sure you save and you don't need to reboot anything for this.

Be careful with opening ports here, I would recommend against opening the SSH or the FTP ports, Keep it local which keeps it somewhat safe :)

Also remember that you don't need to open ports for local services, like mysql or any of the proxy ports, You also don't have to open ports for outgoing connections, It is just for incoming connections.

Firewall

IPtables is present in the kernel and installed by default We don't use it since we are using Docker and all networks will be managed by the router.

Enable auto login

To make sure everything is getting started automatically after a reboot you can use autologin

edit the getty service file with the following command

sudo vim /etc/systemd/system/getty.target.wants/getty@tty1.service

Look for the following line

ExecStart=./sbin/agetty -o '-p -- \\u' --noclear - $TERM

And change it into this

ExecStart=-/sbin/agetty -o '-p -- \\u' --noclear --autologin USERNAME - $TERM

Save and exit

You can restart to ensure you are automatically logged in, It will still ask you for a password, but it should say Automatic Login after boot. If you want to log in with another user simply press enter (wrong password) and you can type another user when needed. press enter for your other user password and you are in!

Install and Configure SSH

SSH or Secure SHell is a tool to access your server remotely, In our example we will only use it locally by simply not opening any ports in the router.

Simply install OpenSSH

sudo pacman -S openssh

We need to configure it properly so open the following file

sudo vim /etc/ssh/sshd_config

Uncomment LogLevel and change it to VERBOSE so we can use it with fail2ban

LogLevel VERBOSE

Now start and enable the service

sudo systemctl enable --now sshd

Install Docker

Docker is the containerization software we are going to use, Every service will get its own container and network.

Install it with the following command

sudo pacman -S docker

now we just need to enable it with systemctl

sudo systemctl enable --now docker

Docker should be up and running.

Install Docker Compose

Docker Compose is a front end for Docker, It allows us to set up containers and networks in an easy way.

Install it with the following command

sudo pacman -S docker-compose

Docker Compose parses yaml files, which are designed to be simple configuration files, spaces are everything here, so make sure you get the spacing right. It does allow us to set up containers quick and easy.

We configure 3 main things container details, volumes and networks

container or service details contain the name of the container, which image it should pull, when it should restart, etc.

volumes are like mounting points for persistant storage, For stuff like Configuration files, Databases, File storage, Stuff that must remain intact if you ever remove the container and rebuild it.

Networks are like virtual networks on the local network, they seperate the different services that don't need to talk to eachother. Services can be in multiple networks tho.

I hope the configuration files will make everything more clear, but this is everything you need to know for now.

Shutdown your server

Aside from fail2ban, certbot, banner/motd and updating and the docker services themself your server is done. It is the perfect time to make some changes. mainly becuase the next sections require a lot of typing and the ability to copy/paste will be very welcome.

So shutdown your machine

sudo shutdown now

Remove the power cable and press the power button this will drain any power left in the machine. Now you can remove any GPU you needed for a video output, remove any peripherals like keyboard, monitors, and give your server a nice place in your house, Just connect the ethernet and power cable and simply press the power button once to start your server again.

Wait a minute and you should be able to login to your server from a different machine over your local network in our example the Local IP was 192.168.1.10 so our command will be the following

ssh username@192.168.1.10

Fill in your password associated with your username and press enter. If you run into problems here, double check the Firewall, SSH and static IP steps. Also make sure your home vlan has access to your server vlan if you chose to use different vlans.

Banner and motd

Next up we are going to adjust the banner it will display on SSH password request

sudo vim /etc/issue

Add in the following content (you might need to \ the \ ones)

  _________
 /         \
|  Whatsup? |
 \_______  /
         \/
        .--.
       |o_o |
       |:_/ |
      //   \ \
     (|     | )
    /'\_   _/`\
    \___)=(___/

Then we have the motd which will display after login

for this we will write a little script so it has up to date information

mkdir ~/Scripts 
vim ~/Scripts/updatemotd.sh

Add in the following content

#!/bin/bash

printf "        \e[34m/#\\                     \e[0;0m_        \e[34m_ _
       \e[34m/###\\   \e[0;0m   __ _ _ __ ___| |__    \e[34m| (_)_ __  _   ___  __
      \e[34m/#####\\    \e[0;0m/ _' | '__/ __| '_ \\   \e[34m| | | '_ \\| | | \\ \\/ /
     \e[34m/##.-.##\\  \e[0;0m| (_| | | | (__| | | |  \e[34m| | | | | | |_| |>  <
    \e[34m/##(   )##\\  \e[0;0m\\__,_|_|  \\___|_| |_|  \e[34m|_|_|_| |_|\\__,_/_/\\_\\
   \e[34m/#.--   --.#\\
  \e[34m/'           '\\
" > /etc/motd
printf "\e[34mMemory Usage: \e[0;0m" >> /etc/motd && free -m | grep Mem | awk '{ printf("%dMB/%dMB ", $3, $2) }' >> /etc/motd && free | grep Mem | awk '{ printf("%.2f%% used\n", $3*100/$2) }' >> /etc/motd
printf "\e[34mDisk Free: \e[0;0m" >> /etc/motd && df -h | awk '$NF=="/"{printf "root %s ", $4}' >> /etc/motd
printf "" && df -h | awk '$NF=="/data"{printf "data %s ", $4}' >> /etc/motd
printf "" && df -h | awk '$NF=="/music"{printf "data %s ", $4}' >> /etc/motd
printf "" && df -h | awk '$NF=="/video"{printf "data %s ", $4}' >> /etc/motd
printf "\n\e[34mLast Boot: \e[0;0m$(uptime)\n" >> /etc/motd
exit

Now we are going to create a Systemtimer which will run the script

sudo vim /etc/systemd/system/updatemotd.service

Add in the following (replace USSERNAME with your username!)

[Unit]
Description=Update the motd
Wants=updatemotd.timer

[Service]
Type=oneshot
ExecStart=/bin/bash /home/USERNAME/Scripts/updatemotd.sh

[Install]
WantedBy=multi-user.target

Now we need a timer file

sudo vim /etc/systemd/system/updatemotd.timer

Add in the following content

[Unit]
Description=Runs the update motd service every minute
Requires=updatemotd.service

[Timer]
Unit=updatemotd.service
OnBootSec=1min
OnUnitActiveSec=1min

[Install]
WantedBy=timers.target

And now we finally start the timer

sudo systemctl enable --now updatemotd.timer

You can exit the ssh and log back in to see the results

Install and Configure Certbot

Certbot will create signed SSL certificates for you (For HTTPS websites)

We simply install it with the following command

sudo pacman -S certbot

First we need to open port 80 temporarily so that certbot can verify you own the domain.

sudo iptables -I INPUT -p tcp --dport 80 -j ACCEPT

Next we are going to request a certificate for every domain you pointed to this server.

sudo certbot certonly -d example.com

Just answer the questions and repeat the process for every other domain. Pick 1 if it asks for the authentication method.

Now we can restore the firewall settings again by running the following command

sudo iptables -D INPUT -p tcp -m tcp --dport 80 -j ACCEPT

Your certificates are only valid for 90 days, so we need to update them every once in a while, personally I just run a script every week that makes sure all certificates are valid

Create the script

vim ~/Scripts/renewcerts.sh

Add in the following content (replace USSERNAME with your username!)

#!/bin/bash

docker-compose -f /home/USERNAME/Docker/nginx/docker-compose.yml down
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
certbot renew
iptables -D INPUT -p tcp -m tcp --dport 80 -j ACCEPT
docker-compose -f /home/USERNAME/Docker/nginx/docker-compose.yml up -d

Next we need a service which actually executes the script so create the service file

sudo vim /etc/systemd/system/renewcerts.service

Add in the following content (replace USSERNAME with your username!)

[Unit]
Description=Updates all expiring certificates
Wants=renewcerts.timer

[Service]
Type=oneshot
ExecStart=/bin/bash /home/USERNAME/Scripts/renewcerts.sh

[Install]
WantedBy=multi-user.target

Next we need a timer which actually calls the service so create the timer file

sudo vim /etc/systemd/system/renewcerts.timer

Add in the following content

[Unit]
Description=Runs the update certificates service every week
Requires=renewcerts.service

[Timer]
OnCalendar=Tue 04:00
Persistent=true

[Install]
WantedBy=timers.target

Finally start and enable the timer so it will actually run

sudo systemctl enable --now renewcerts.timer

Install and Configure Fail2Ban

Fail2Ban will read your logs for failed login attempts or other fishy things, when it crosses a certain amount of attempts it will block the IP using the firewall.

So first we are going to install fail2ban

sudo pacman -S fail2ban

Next enable and start the service

sudo systemctl enable --now fail2ban

Create a file where we will store all of our configuration

sudo vim /etc/fail2ban/jail.local

Replace the whole contents with the following

[INCLUDES]

before = paths-arch.conf

[DEFAULT]

## Settings
ignoreip = 127.0.0.1/8 ::1 192.168.1.1/16 172.20.0.0/16
findtime = 1h
maxretry = 3
bantime = 1h
bantime.increment = true
bantime.rndtime = 3600
bantime.multipliers = 1 3 5 12 24 168 4200 999999999 
bantime.overalljails = true
banaction = action

## SSH Jail
[sshd]
enabled = true

For now we only set some default settings you can always overwrite them later on

ignoreip is pretty self explanitory, You can add your own IPs findtime is the period in which these attempts are are allowed maxretry is the number of attempts to trigger a ban bantime is pretty self explanitory bantime.increment this increments the bantime bantime.rndtime adds a random time to the bantime to fool scripts bantime.multipliers sets a custom ban time for repeated offenders bantime.overalljails makes fail2ban check accross all jails so 1 attempt at 3 services is a ban banaction is which action to perform, we will write a custom action in the next section Finally under [sshd] we enabled sshd, we have to enable every service we add. We will add more later depending on the services you want to activate

Save and exit the file

Now we need to create a banaction so fail2ban knows what to do when it needs to ban someone.

sudo vim /etc/fail2ban/action.d/action.conf

Add in the following lines

[Definition]
actionban = iptables -I INPUT -s <ip> -j REJECT
            iptables -I FORWARD -s <ip> -j REJECT
            iptables -I DOCKER-USER -s <ip> -j REJECT
	          echo "<matches>" >> /var/log/fail2ban.log

actionunban = iptables -D INPUT -s <ip> -j REJECT
              iptables -D FORWARD -s <ip> -j REJECT
              iptables -D DOCKER-USER -s <ip> -j REJECT

Here you can see that everytime it needs to ban someone it will simply execute some iptables commands that reject requests for docker and the host system.

I also put in the echo so it prints the why in the fail2ban log it can be handy for debugging but you can remove it.

Don't forget to restart the service to make the changes take effect

sudo systemctl restart fail2ban

You can use fail2ban-client to unban people or view some statistics

sudo fail2ban-client

Lets add some Aliases so viewing the banned list and unbanning people gets easier

WIP!

Install and Configure Nginx

eNGINe X is a very powerful webserver, It can do many things and is highly configurable.

We will use it as a reverse proxy to forward requests to the correct container.

Create some folders in your home directory

mkdir -p ~/Docker/nginx

Now create a docker compose file in that directory

vim ~/Docker/nginx/docker-compose.yml

Add in the following text

version: '3'

services:
  nginx:
    image: nginx:latest
    container_name: nginx
    restart: always
    volumes:
      - /data/nginx/config:/etc/nginx
      - /data/nginx/log/error.log:/var/log/error.log
      - /data/nginx/log/access.log:/var/log/access.log
      - /etc/letsencrypt/:/etc/letsencrypt/
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 80:80
      - 443:443

First we need to create a folder for the configuration

sudo mkdir -p /data/nginx/config

We need to add the nginx configuration file

sudo vim /data/nginx/config/nginx.conf

Add in the following text

# Global Settings
user                 nginx;
pid                  /var/run/nginx.pid;
worker_processes     auto;
worker_rlimit_nofile 65535;

events {
    multi_accept       on;
    worker_connections 1024;
}


# Web Traffic
http {
  charset utf-8;
  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;
  server_tokens off;
  error_log /var/log/error.log warn;
  access_log /var/log/access.log;
  proxy_cache_path /etc/nginx/cache keys_zone=one:500m max_size=1000m;
  types_hash_max_size 2048;
  types_hash_bucket_size 64;
  client_max_body_size 16M;
  client_body_buffer_size 16M;
  client_header_buffer_size 16M;
  large_client_header_buffers 2 16M;

  # MIME
  default_type           application/octet-stream;

  # Limits
  limit_req_log_level    warn;
  limit_req_zone         $binary_remote_addr zone=login:10m rate=10r/m;

  # SSL
  ssl_session_timeout    1d;
  ssl_session_cache      shared:SSL:10m;
  ssl_session_tickets    off;
  ssl_protocols          TLSv1.2 TLSv1.3;
  ssl_stapling           on;
  ssl_stapling_verify    on;

  # Services
  include /etc/nginx/services/*.active;
}

We need to create the 2 log files so docker compose won't create directories

sudo touch /data/nginx/log/access.log /data/nginx/log/error.log

We also nened to create 2 directories which will house our auth

sudo mkdir -p /data/nginx/config/auth /data/nginx/config/services

Nginx should be good now, lets start the container

sudo docker-compose -f ~/Docker/nginx/docker-compose.yml up -d 

Now we only need to setup fail2ban for Nginx, so create the following file

sudo vim /etc/fail2ban/filter.d/nginxx.local

add in the following content

[INCLUDES]
before = common.conf

[Definition]
failregex = ^<HOST>.*"(GET|POST).*" (400|401|403|404|405|406|407|423|429) .*$

This will ban everyone getting any of the error codes in the failregex line.

Now we need to activate the filter in our main fail2ban configuration file

sudo vim /etc/fail2ban/jail.local

Add the following to the bottom

## Nginx
[nginxx]
enabled = true
logpath = /data/nginx/log/access.log

Restart fail2ban to make the changes take effect

sudo systemctl restart fail2ban

Install and Configure MariaDB

MariaDB is a drop in replacement for MySQL, which is a database used by many services.

First we create some folders

mkdir -p ~/Docker/mariadb

First we will create a docker compose file

vim ~/Docker/mariadb/docker-compose.yml

Add in the following text

version: '3'

services:
  mariadb:
    image: mariadb:latest
    container_name: mariadb
    restart: always
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW --skip-innodb-read-only-compressed
    volumes:
      - /data/mariadb/data:/var/lib/mysql
      - /data/mariadb/config:/etc/mysql/conf.d
      - /data/mariadb/logs:/var/log/mysql
      - /etc/localtime:/etc/localtime:ro

    environment:
      - MYSQL_ROOT_PASSWORD=SETAMYSQLROOTPASSWORDHERE

Be sure to set your mysql root password

Lets start the container

sudo docker-compose -f ~/Docker/mariadb/docker-compose.yml up -d 

Now we only need to initialize the database

sudo docker exec -it mariadb mariadb-secure-installation

Answer the first 3 questions with No and the rest with Yes

Install and Configure Nextcloud

Nextcloud is a great application, It is great for storing and syncing data, storing your contacts, bookmarks, passwords, calendar, tasks. It also has a great RSS reader, full office suite and many many more. I truly can't live without it. And neither should you which is why I picked it as the example for this guide

First we need to create a network for the service.

sudo docker network create --subnet=172.20.30.0/24 nextcloud

Next we are going to create some folders

mkdir -p ~/Docker/nextcloud

Now we will create a docker compose file

vim ~/Docker/nextcloud/docker-compose.yml

Add in the following text

version: '3'

services:
  nextcloud:
    image: nextcloud
    container_name: nextcloud
    restart: always
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /data/nextcloud:/var/www/html
    networks:
      nextcloud:
        ipv4_address: 172.20.30.10

networks:
  nextcloud:
    external: true
    name: nextcloud
    ipam:
      config:
        - subnet: 172.20.30.0/24

Now we need to add a server block for nextcloud to the Nginx config file so create a file that will be included by the main nginx config file

And create the file

sudo vim /data/nginx/config/services/nextcloud.active

add in the following text

server {
  server_name example.com;
  listen      443 ssl;

# Settings
  autoindex off;
  client_max_body_size 5000M;

# Locations
  location / {
    proxy_pass http://nextcloud:80;
    proxy_http_version                 1.1;
    proxy_cache_bypass                 $http_upgrade;
    proxy_ssl_server_name              on;
    proxy_set_header Upgrade           $http_upgrade;
    proxy_set_header X-Real-IP         $remote_addr;
    proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host  $host;
    proxy_set_header X-Forwarded-Port  $server_port;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_connect_timeout              600m;
    proxy_send_timeout                 600m;
    proxy_read_timeout                 600m;
  }

  location /.well-known/carddav {
    return 301 $scheme://$host/remote.php/dav;
  }

  location /.well-known/caldav {
    return 301 $scheme://$host/remote.php/dav;
  }

  location ~ /\.(?!well-known) {
    deny all;
  }

  location = /favicon.ico {
    log_not_found off;
  }

  location = /robots.txt {
    log_not_found off;
  }

# GZip
  gzip            on;
  gzip_vary       on;
  gzip_proxied    any;
  gzip_comp_level 6;
  gzip_types      text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;

# Headers
  add_header X-XSS-Protection          "1; mode=block" always;
  add_header X-Content-Type-Options    "nosniff" always;
  add_header X-Frame-Options "SAMEORIGIN";
  add_header Referrer-Policy           "no-referrer-when-downgrade" always;
  add_header Content-Security-Policy   "default-src 'self' http: https: ws: wss: data: blob: 'unsafe-inline'; frame-ancestors 'self';" always;
  add_header Permissions-Policy        "interest-cohort=()" always;
  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

# SSL
  ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
  ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
}

# Redirect
server {
  listen 80;
  server_name example.com;
  return 301 https://example.com$request_uri;
}

Be sure to replace example.com 6 times

Now we need to add nextcloud to the mariadb and nginx networks, because it needs a database and a proxy.

open the nginx compose file

vim ~/Docker/nginx/docker-compose.yml

add the nextcloud network so it looks like this

version: '3'

services:
  nginx:
    image: nginx:latest
    container_name: nginx
    restart: always
    volumes:
      - /data/nginx/config:/etc/nginx
      - /data/nginx/log/error.log:/var/log/error.log
      - /data/nginx/log/access.log:/var/log/access.log
      - /etc/letsencrypt/:/etc/letsencrypt/
      - /etc/localtime:/etc/localtime:ro
    ports:
      - 80:80
      - 443:443
      - 8448:8448
    networks:
      nextcloud:
        ipv4_address: 172.20.30.20

networks:
  nextcloud:
    external: true
    name: nextcloud

open the mariadb compose file

vim ~/Docker/mariadb/docker-compose.yml

add the nextcloud network so it looks like this

version: '3'

services:
  mariadb:
    image: mariadb:latest
    container_name: mariadb
    restart: always
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW --skip-innodb-read-only-compressed
    volumes:
      - /data/mariadb/data:/var/lib/mysql
      - /data/mariadb/config:/etc/mysql/conf.d
      - /data/mariadb/logs:/var/log/mysql
      - /etc/localtime:/etc/localtime:ro

    environment:
      - MYSQL_ROOT_PASSWORD=SETAMYSQLROOTPASSWORDHERE
    networks:
      nextcloud:
        ipv4_address: 172.20.30.30

networks:
  nextcloud:
    external: true
    name: nextcloud

Now we are going to start the nextcloud container and restart the nginx and mariadb containers.

sudo docker-compose -f ~/Docker/nextcloud/docker-compose.yml up -d
sudo docker-compose -f ~/Docker/nginx/docker-compose.yml down && sudo docker-compose -f ~/Docker/nginx/docker-compose.yml up -d
sudo docker-compose -f ~/Docker/mariadb/docker-compose.yml down && sudo docker-compose -f ~/Docker/mariadb/docker-compose.yml up -d

Nextcloud should be accessable from your browser using the domain you chose. If you have not setup your dns records but only adjusted your .active file for nginx you need to do 2 things first before you go on.

  • make sure you have chosen a domain (nextcloud.example.com) and used it in your .active file for nginx.
  • make sure you have valid certificates for this domain. if not go back to the certbot part so you can repeat those instructions for your nextcloud domain.

But first we need to create a database, a user and set the permissions.

You can get into the database with the following command (only if mariadb is running)

sudo docker exec -it mariadb mariadb -p

Enter the Mysql root password you provided during the creation of the mariadb container and you should be in.

Now run the following commands to create a database, create a user with privileges, and make them take effect.

create database nextcloud;
create user nextcloud@'172.20.30.10' identified by 'NEXTCLOUDDATABASEPASSWORD';
grant all privileges on nextcloud.* to nextcloud@'172.20.30.10';
flush privileges;

You can exit the mysql prompt with exit; and then pressing enter.

Now we just need to go to example.com and follow the steps

The Database is nextcloud, the user is nextcloud, The IP is 172.20.30.30:3306 and the password is what you gave it.

We also need to force HTTPS, else it will give problems since we are running from behind a proxy

sudo vim /data/nextcloud/config/config.php

Add in the following line preferrrably under the overwrite.cli.url line.

'overwriteprotocol' => 'https',

Nextcloud requires some tasks to be executed every 5 minutes, for that we are going to use systemd timers, like we did for certbot

Create a little script

vim ~/Scripts/nextcloudcron.sh

add in the following content

#!/bin/bash

docker exec -u 33 -t nextcloud php -f /var/www/html/cron.php
exit

Create a systemd service

sudo vim /etc/systemd/system/nextcloudcron.service

Add in the following content

[Unit]
Description=Runs Nextcloud Cron
Wants=nextcloudcron.timer

[Service]
Type=oneshot
ExecStart=/bin/bash /home/USERNAME/Scripts/nextcloudcron.sh

[Install]
WantedBy=multi-user.target

Create a timer file

sudo vim /etc/systemd/system/nextcloudcron.timer

and add in the following content

[Unit]
Description=Runs Nextcloud Cron
Requires=nextcloudcron.service

[Timer]
Unit=nextcloudcron.service
OnBootSec=5min
OnUnitActiveSec=5min

[Install]
WantedBy=timers.target

Finally start the timer

sudo systemctl enable --now nextcloudcron.timer

Nextcloud should be all good and ready to go, You can check the persistance by completely deleting all containers and all volumes, When you start it again all your stuff should still be there :)

Nextcloud has its own Brute force protection, but we still are going to add a fail2ban filter because we want attackers to be banned from all services and not just nextcloud.

So lets create a new nextcloud filter

sudo vim /etc/fail2ban/filter.d/nextcloud.local

add in the following content

[Definition]
failregex=^{"reqId":".*","remoteAddr":".*","app":"core","message":"Login failed: '.*' \(Remote IP: '<HOST>'\)","level":2,"time":".*"}$
          ^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","user":".*","app":".*","method":".*","url":".*","message":"Login failed: '.*' \(Remote IP: '<HOST>'\)".*}$
          ^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","user":".*","app":".*","method":".*","url":".*","message":"Login failed: .* \(Remote IP: <HOST>\).*}$

Now add the filter to your main fail2ban config file

sudo vim /etc/fail2ban/jail.local

Add the following to the end of the file

## Nextcloud
[nextcloud]
filter = nextcloud
enabled = true
logpath = /data/nextcloud/data/nextcloud.log

restart fail2ban to make it take effect

sudo systemctl restart fail2ban

Updating the Server

To maintain the system we simply need to update it by running the following command

sudo pacman -Syu

To update the docker containers we need to pull every container and then restart it, it would be a lot of work every time you want to upgrade. It is easier to create a script instead of manually typing all the commands every time.

So create a file

vim ~/Scripts/update-docker.sh

put in the following text

#!/bin/bash

# Update Nginx
docker-compose -f /home/USERNAME/Docker/nginx/docker-compose.yml pull
docker-compose -f /home/USERNAME/Docker/nginx/docker-compose.yml down
docker-compose -f /home/USERNAME/Docker/nginx/docker-compose.yml up -d --remove-orphans

# Update MariaDB
docker-compose -f /home/USERNAME/Docker/mariadb/docker-compose.yml pull
docker-compose -f /home/USERNAME/Docker/mariadb/docker-compose.yml down
docker-compose -f /home/USERNAME/Docker/mariadb/docker-compose.yml up -d --remove-orphans

# Update Nextcloud
docker-compose -f /home/USERNAME/Docker/nextcloud/docker-compose.yml pull
docker-compose -f /home/USERNAME/Docker/nextcloud/docker-compose.yml down
docker-compose -f /home/USERNAME/Docker/nextcloud/docker-compose.yml up -d --remove-orphans

You should add any services you add to this simple script so all containers get updated

Save, exit and then make it executable with the following command

sudo chmod u+x update-docker.sh

You can now run the script to update all docker containers

Let the script run with pacman

Why mess around with 2 commands, when you can simply force the docker-update.sh script to run when you update your system using pacman. We can do this very easy with pacman hooks

create a file in the hooks directory for docker

sudo vim /usr/share/libalpm/hooks/docker.hook

Add in the following text

[Trigger]
Operation = Upgrade
Type = Package
Target = *
[Action]
Description = Update Docker Containers
When = PostTransaction
Exec = /bin/bash /home/USERNAME/Scripts/update-docker.sh

Save and exit and try to update your system, if you are lucky you have an update and you can see the script in action after the update.

Terminal

Installing ZSH

ZSH is a pretty cool lightweight shell that is very configurable, Install it with the following command

sudo pacman -S zsh

Now we are going to make ZSH the default shell with the following command

chsh -s $(chsh -l | grep -m1 zsh)

We are going to create zshrc config files in a central config folder for easy backups.

mkdir ~/Config

then create 2 files in there

touch ~/Config/zshrc-global ~/Config/zshrc-user

Now we need to create a new user zsh config folder

mkdir ~/.config/zsh

now we are going to symlink the config files to where zsh expects them to be

sudo ln -sf ~/Config/zshrc-global /etc/zsh/zshrc
ln -sf ~/Config/zshrc-user ~/.config/zsh/.zshrc

Now we need to set the dotfile location in zshenv

sudo vim /etc/zsh/zshenv

Add in the following line

export ZDOTDIR=~/.config/zsh

Save and exit

ZSH should be functional with a terrible prompt, so lets fix that first.

Powerlevel10K

Powerlevel10K is a great theme for ZSH, it is very configurable and has a lot of cool features

Sadly it is unmaintained, but it works fine, we can clone the repo into our /usr/share folder.

sudo git clone https://github.com/romkatv/powerlevel10k.git /usr/share/zsh-theme-powerlevel10k/

Now we need to include the following lines in our zshrc-global file

#P10k
source /usr/share/zsh-theme-powerlevel10k/powerlevel10k.zsh-theme

And the following lines to our zshrc-user file

#P10k
[[ ! -f ~/.config/zsh/.p10k.zsh ]] || source ~/.config/zsh/.p10k.zsh

To configure Powerlevel10K you must run the following command

p10k configure

Have some patience and run trough the interactive configuration

Now we just need to symlink the config file to the expected location

ln -sf ~/Config/p10k.zsh ~/.config/zsh/.p10k.zsh

When you exit the terminal and start it again it should look all nice :)

Installing LSD

lsd is like ls with colors, nice icons and other visual cues that help you.

It is in the repos, simply install it with the following command

sudo pacman -S lsd

You can now run it with lsd, we will later alias ls to lsd in our zsh configuration.

try the following command for example

lsd -la ~

Adding ZSH Options and Keybinds

ZSH options change the default behavior so do keybinds

You can add them all or just the ones you like to your zshrc-global file

Give flag suggestions for programs

autoload -Uz compinit && compinit

Gives you a menu when navigating suggestions

zstyle ':completion:*' menu select
zstyle ':completion::complete:*' gain-privileges 1

History settings for ZSH

export HISTFILE=~/.config/zsh/.zsh_history
export HISTSIZE=1000000
export SAVEHIST=1000000
setopt EXTENDED_HISTORY
setopt HIST_IGNORE_ALL_DUPS
setopt HIST_FIND_NO_DUPS
setopt inc_append_history

Press up and down to search to matching history

bindkey "^[[A" history-beginning-search-backward
bindkey "^[[B" history-beginning-search-forward

Case insensitive tab completion, Also enables cd doc/fo/su to go to /documents/folder/subfolder

zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'

I really don't see the use for Flow Control

unsetopt flow_control

Fix navigation keys

bindkey  "^[[H"   beginning-of-line
bindkey  "^[[F"   end-of-line
bindkey  "^[[3~"  delete-char
bindkey  "^[[5~"  beginning-of-line
bindkey  "^[[6~"  end-of-line

Adding Aliases

Aliases are simply alternatives for a string of text, as an easy example, v will type nvim, and sv will type sudo nvim. You can also chose to remove some or add more.

Simply add the following text to one of your ~/config/zshrc files, user will set it for you, and global will set it for everyone,

alias a="awk"
alias b="btrfs"
alias c="cryptsetup"
alias d="docker"
alias e="echo"
alias f="fdisk"
alias g="git"
alias h="history"
alias j="jobs -l"
alias k="kubectl"
alias l="ls -la" 
alias m="man"
alias n="neofetch"
alias o="openssl"
alias p="pacman"
alias r="reboot"
alias s="sudo"
alias t="tail -f"
alias u="uname"
alias v="nvim"
alias w="whence"
alias sudo="sudo "
alias ffs="sudo !!"
alias distro="cat /etc/*-release"
alias hk="cat ~/config/hotkeys"
alias sv="sudo v"
alias md="mkdir -p"
alias tk="take"
alias rmd="rm -rf"
alias sgrep="grep -R -n -H -C 5 --exclude-dir={.git,.svn,CVS} "
alias hgrep="fc -El 0 | grep"
alias please='sudo'
alias phone='ssh houtworm@pinephone'
alias server='ssh houtworm@server'
alias game='gamemoderun mangohud'
alias ytflac="youtube-dl -x --audio-format flac --prefer-ffmpeg"
alias ytmkv="youtube-dl -F"
alias lol='lolcat'
alias cd1="cd .."
alias cd2="cd ../.."
alias cd3="cd ../../.."
alias cd4="cd ../../../.."
alias cd5="cd ../../../../.."
alias cd6="cd ../../../../../.."
alias cd7="cd ../../../../../../.."
alias cd8="cd ../../../../../../../.."
alias cd9="cd ../../../../../../../../.."
alias scls="systemctl list-unit-files"
alias scs="sudo systemctl status "
alias scre="sudo systemctl restart "
alias scst="sudo systemctl start "
alias scsp="sudo systemctl stop "
alias scen="sudo systemctl enable "
alias scenn="sudo systemctl enable now "
alias scdi="sudo systemctl disable "
alias fwd="firewall-cmd"
alias fwdlist="firewall-cmd --list-all-zones"
alias fwdre="firewall-cmd --reload"
alias gi="git init"
alias ga="git add *"
alias gc="git commit -m"
alias gp="git push"
alias me="ifconfig | grep "inet " | cut -b 9- | cut -d" " -f2"
alias allcolor="for i in {0..255}; do print -Pn "%K{$i}  %k%F{$i}${(l:3::0:)i}%f " ${${(M)$((i%6)):#3}:+$"\n"}; done"
alias rainbow="printf "$BBLA\n$BRED\n$BGRE\n$BYEL\n$BBLU\n$BMAG\n$BCYA\n$BWHI\n\n""
alias dud="du -d 1 -h"
alias duf="du -sh *"
alias :q="exit"
alias ls="lsd" 
alias ports="netstat -tulanp"
alias compr="gcc -Wall -Wextra -Werror *.c && ./a.out && rm a.out" 
alias compra="gcc -Wall -Wextra -Werror *.c && ./a.out" 
alias norme="norminette -R CheckForbiddenSourceHeader" 
alias valg="gcc *.c -ggdb3 && valgrind --show-leak-kinds=all --leak-check=full --track-origins=yes ./a.out && rm a.out"
alias valga="gcc *.c -ggdb3 && valgrind --show-leak-kinds=all --leak-check=full --track-origins=yes ./a.out" 
alias normsh="checkbashisms" 
alias banned='sudo fail2ban-client banned | tr -t "[{" " \n" | tr -d ":]},"'

Adding ZSH Functions

ZSH functions are like tiny scripts that perform a task, you can add the ones you think are useful to you to one of the zshrc files, I suggest global so anyone can use them :)

Press Ctrl + Z to bring stuff to the background but also bring stuff back to the foreground instead of typing fg

backforeswitch () {
  if [[ $#BUFFER -eq 0 ]]; then
    BUFFER="fg"
    zle accept-line -w
  else
    zle push-input -w
    zle clear-screen -w
  fi
}
zle -N backforeswitch
bindkey '^Z' backforeswitch

Press Esc twice to put sudo in front of your previous command.

sudoswitch() {
    [[ -z $BUFFER ]] && zle up-history
    if [[ $BUFFER == sudo\ * ]]; then
        LBUFFER="${LBUFFER#sudo }"
    elif [[ $BUFFER == $EDITOR\ * ]]; then
        LBUFFER="${LBUFFER#$EDITOR }"
        LBUFFER="sudoedit $LBUFFER"
    elif [[ $BUFFER == sudoedit\ * ]]; then
        LBUFFER="${LBUFFER#sudoedit }"
        LBUFFER="$EDITOR $LBUFFER"
    else
        LBUFFER="sudo $LBUFFER"
    fi
}
zle -N sudoswitch
bindkey "\e\e" sudoswitch
bindkey -M vicmd '\e\e' sudoswitch

Make the man pages all colorful

function man() {
    env \
        LESS_TERMCAP_mb=$(printf "\e[1;31m") \
        LESS_TERMCAP_md=$(printf "\e[1;31m") \
        LESS_TERMCAP_me=$(printf "\e[0m") \
        LESS_TERMCAP_se=$(printf "\e[0m") \
        LESS_TERMCAP_so=$(printf "\e[0;37;102m") \
        LESS_TERMCAP_ue=$(printf "\e[0m") \
        LESS_TERMCAP_us=$(printf "\e[4;32m") \
        PAGER="${commands[less]:-$PAGER}" \
        _NROFF_U=1 \
        GROFF_NO_SGR=1 \
        PATH=${HOME}/bin:${PATH} \
    man "$@"
}

Creates a TAR archive of a file or folder.

function maketar() { tar cvzf "${1%%/}.tar.gz"  "${1%%/}/"; }

Create a ZIP archive of a file or folder.

function makezip() { zip -r "${1%%/}.zip" "$1" ; }

Extracts any type of archive automagically

function extract {
 if []; then
    echo "Usage: extract <path/file_name>.<zip|rar|bz2|gz|tar|tbz2|tgz|Z|7z|xz|ex|tar.bz2|tar.gz|tar.xz>"
 else
    if [] ; then
        case $1 in
          *.tar.bz2)   tar xvjf $1    ;;
          *.tar.gz)    tar xvzf $1    ;;
          *.tar.xz)    tar xvJf $1    ;;
          *.lzma)      unlzma $1      ;;
          *.bz2)       bunzip2 $1     ;;
          *.rar)       unrar x -ad $1 ;;
          *.gz)        gunzip $1      ;;
          *.tar)       tar xvf $1     ;;
          *.tbz2)      tar xvjf $1    ;;
          *.tgz)       tar xvzf $1    ;;
          *.zip)       unzip $1       ;;
          *.Z)         uncompress $1  ;;
          *.7z)        7z x $1        ;;
          *.xz)        unxz $1        ;;
          *.exe)       cabextract $1  ;;
          *)           echo "extract: '$1' - unknown archive method" ;;
        esac
    else
        echo "$1 - file does not exist"
    fi
fi
}

The git riddle

function iacp() {
if []
then
	echo "Usage: iacp <name> <link> <comment>"
else
	git init
	git add *
	git commit -m "$3"
	git remote add $1 $2
	git push --set-upstream $1 master
fi
}

The git push

function acp() {
if []
then
	echo "Usage: acp <comment>"
else
	git add *
	git commit -m "$1"
	git push
fi
}

take or tk = mkdir -p and cd in one

function take() {
	md "$1"
	cd "$1"
}

Really clear the screen with Ctrl + L

clearbetter () {
  BUFFER="clear"
  zle accept-line -w
}
zle -N clearbetter
bindkey '^L' clearbetter

Reload ZSH with Ctrl + S

resourcezsh () {
  BUFFER="exec -l zsh"
  zle accept-line -w
  BUFFER="clear"
  zle accept-line -w
}
zle -N resourcezsh
bindkey '^S' resourcezsh

Exit with Ctrl + Q

ctrlqexit () {
  BUFFER=":q"
  zle accept-line -w
}
zle -N ctrlqexit
bindkey '^Q' ctrlqexit

Unban IPs with fail2ban

unban () {
  sudo fail2ban-client unban $@
}

ZSH Plugins

To add plugins to ZSH we simply need to download them and source the main .zsh file of that plugin in one of your zshrc files. Below are the ones I use

Fast Syntax Highlighting is great, it gives your input color based on brackets, if it is correct or not, etc

git clone https://github.com/z-shell/F-Sy-H /usr/share/zsh/plugins/F-Sy-H

Now simply source the .zsh file in your global zshrc by adding the following line to it

source /usr/share/zsh/plugins/F-Sy-H/F-Sy-H.plugin.zsh

Alias Tips helps you remember the aliases you set, if you don't use a set alias it will notify you of the alias in a way that doesn't annoy you.

git clone https://github.com/djui/alias-tips /usr/share/zsh/plugins/alias-tips

Now simply source the .zsh file in your global zshrc by adding the following line to it

source /usr/share/zsh/plugins/alias-tips/alias-tips.plugin.zsh

ZSH Autosuggestions is nice, it tries to complete a command based on your history

git clone https://github.com/zsh-users/zsh-autosuggestions /usr/share/zsh/plugins/zsh-autosuggestions

Now simply source the .zsh file in your global zshrc by adding the following line to it

source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh

Also add the following line to the /etc/zsh/zshenv file to drastically speed up this plugin

export ZSH_AUTOSUGGEST_MANUAL_REBIND

Z is a pretty cool plugin for fast navigation just type z nameoffolder and it will jump to it based on history.

git clone https://github.com/agkozak/zsh-z /usr/share/zsh/plugins/z

Now simply source the .zsh file in your global zshrc by adding the following line to it

source /usr/share/zsh/plugins/z/zsh-z.plugin.zsh

Also be sure to set the ZSHZ_DATA variable in /etc/zsh/zshenv by adding the following line to it

export ZSHZ_DATA=~/.config/zsh/.z

You can install any more you like, just be sure it doesn't slow down your shell.

Updating ZSH Plugins with Pacman

Updating these plugins is important for compatibility and new features.

Create a file for the script

vim ~/Scripts/update-zshplugins.sh

Add in the following content

	git -C /usr/share/zsh/plugins/F-Sy-H pull
	git -C /usr/share/zsh/plugins/alias-tips pull
	git -C /usr/share/zsh/plugins/zsh-autosuggestions pull
	git -C /usr/share/zsh/plugins/z pull

create a file in the pacman hooks directory for zsh plugins

sudo vim /usr/share/libalpm/hooks/zsh.hook

Add in the following text

[Trigger]
Operation = Upgrade
Type = Package
Target = *
[Action]
Description = Update ZSH Plugins
When = PostTransaction
Exec = /bin/bash /home/USERNAME/Scripts/update-zshplugins.sh

Save and exit and try to update your system, if you are lucky you have an update and you can see the script in action after the update.

ZSH Hotkeys

Just a simple overview of all the hotkeys you can use Up and Down Arrow = Browse history matching current line Ctrl + A = Go to start of line Ctrl + B = Move 1 character back Ctrl + C = Cancel, Stop the current operation. Ctrl + D = Quit the session Ctrl + E = Go to end of line Ctrl + F = Move 1 character forward Ctrl + G = Nothing Ctrl + H = DOUBLE Delete Character before the cursor Ctrl + I = Nothing Ctrl + J = Nothing Ctrl + K = Remove everything behind the cursor Ctrl + L = clear screen Ctrl + M = Nothing Ctrl + N = Browse History matching current line Ctrl + O = Nothing Ctrl + P = Browse History matching current line Ctrl + Q = Quit, Types exit and presses enter. Ctrl + R = Search in History Ctrl + S = Nothing Ctrl + T = Nothing Ctrl + U = Delete everything before the cursor Ctrl + V = Nothing Ctrl + W = Delete the word before the cursor Ctrl + X = Nothing Ctrl + Y = Undo Ctrl + Z = toggle program to background and foreground

Installing Neofetch

Neofetch is a cool tool that shows some system information and a asci art logo of your distro. Install it with the following command

sudo pacman -S neofetch

Now you can run it by just typing neofetch in a terminal :)

Programming

Even if you are not into programming and have no interest in learning it, some of these programs might be useful, in the case of Neovim it is a lot easier to read configuration files for example, If you want to get into programming these programs are an absolute must.

Installing Neovim

We are using Neovim over Vim because Neovim has LSP support

install it using pacman

sudo pacman -S neovim

We will configure it later, we will start with ZSH

Neovim Options and Keybinds

We already installed Neovim in the first step, but we still need to configure it the way we want to. First we need create config files

touch ~/Config/init.vim ~/Config/sysinit.vim

Now we are going to create a symlink for the user config file

ln -sf ~/Config/init.vim ~/.config/nvim/init.vim

Do the same for the global config file

sudo ln -sf ~/Config/sysinit.vim /etc/xdg/nvim/sysinit.vim

We can now set some options, I recommend putting them in the system file this way you have the same configuration with the root user

sv ~/Config/init.vim

Add in the following options, Going over them all is beyond the scope of this guide, But you can look them all up to see what they do exactly.

"Options for Neovim"
:setlocal list
set listchars=eol:↓,tab:··▸,trail:●,extends:…,precedes:…,space:·
set updatetime=300
set shortmess+=c
syntax on
set number
set nu rnu
set tabstop=4
set cursorline
set showcmd
filetype indent on
set wildmenu
set showmatch
set incsearch
set hlsearch
set nospell
set spelllang=en_us
set autoindent
set ruler
set confirm
set cmdheight=2
set shiftwidth=4
set noexpandtab
set hidden
set nowrap
set encoding=utf-8
set pumheight=10
set mouse=a
set splitbelow
set splitright
set t_Co=256
set conceallevel=0
set smarttab
set smartindent
set background=dark
set showtabline=0
set noshowmode
set nobackup
set nowritebackup
set clipboard=unnamedplus
set dir=~/tmp,/tmp
set scrolloff=3
set sidescrolloff=7
set sidescroll=1
set ignorecase smartcase
set undofile
set undodir=~/.nvim/undo
set inccommand=nosplit
set signcolumn=number
set backspace=indent,eol,start
set complete-=i

Now add some keyboard remaps

"Keyboard Remaps"
nmap <C-d> :windo bd<CR>
nmap <A-o> :tabnew<CR>
nmap <A-e> :tabp<CR>
nmap <A-w> :tabn<CR>
nmap <C-o> :ene<CR>
nmap <C-w> :bp<CR>
nmap <C-e> :bn<CR>
nmap <C-n> :vs<CR>
nmap <C-b> :split<CR>
nmap <C-q> :q<CR>
nmap <C-s> :w<CR>
nmap <C-p> :set nu! rnu!<CR>
nmap <A-c> :set list!<CR>
nmap <S-up> :resize +3<CR>
nmap <S-down> :resize -3<CR>
nmap <S-left> :vertical resize +3<CR>
nmap <S-right> :vertical resize -3<CR>
nmap <S-k> :resize +3<CR>
nmap <S-j> :resize -3<CR>
nmap <S-h> :vertical resize +3<CR>
nmap <S-l> :vertical resize -3<CR>
nmap <c-k> :wincmd k<CR>
nmap <c-j> :wincmd j<CR>
nmap <c-h> :wincmd h<CR>
nmap <c-l> :wincmd l<CR>
nmap <c-up> :wincmd k<CR>
nmap <c-down> :wincmd j<CR>
nmap <c-left> :wincmd h<CR>
nmap <c-right> :wincmd l<CR>
nmap <A-j> :m .+1<CR>==
nmap <A-k> :m .-2<CR>==
imap <A-j> <Esc>:m .+1<CR>==gi
imap <A-k> <Esc>:m .-2<CR>==gi
vmap <A-j> :m '>+1<CR>gv=gv
vmap <A-k> :m '<-2<CR>gv=gv
nmap <A-down> :m .+1<CR>==
nmap <A-up> :m .-2<CR>==
imap <A-down> <Esc>:m .+1<CR>==gi
imap <A-up> <Esc>:m .-2<CR>==gi
vmap <A-down> :m '>+1<CR>gv=gv
vmap <A-up> :m '<-2<CR>gv=gv
nmap <A-h> <<
nmap <A-l> >>
imap <A-h> <Esc> <<
imap <A-l> <Esc> >>
vmap <A-h> <
vmap <A-l> >
nmap <A-left> <<
nmap <A-right> >>
imap <A-left> <Esc> <<
imap <A-right> <Esc> >>
vmap <A-left> <
vmap <A-right> >

Neovim Plugins

Vim Plug will be our plugin manager, It will handle most of the work

We will install it system wide

sudo mkdir /etc/xdg/nvim/autoload
sudo curl -o /etc/xdg/nvim/autoload/plug.vim https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

Plugins get installed locally so we have to install plugins for every user seperately, We can make it universal, but this will prevent users from adding their own plugins. With our configuration we can set global plugins for everyone and any extra plugins the user may want using their own init.vim file.

We can add plugins to either init.vim or sysinit.vim If you want to Install for yourself or everyone respectively, they do have to be inside a special block like this.

call plug#begin()
Plug '<link plugin 1>'
Plug '<link plugin 2>''
call plug#end()

You can use PlugUpdate to update and install all selected plugins, PlugClean te remove unselected plugins and, PlugUpgrade to update vim plug itself.

Just add whichever plugin you think will improve your workflow, these are the ones I use.

This plugin will add a ton of icons to Neovim, many of the following plugins will use them, but they are optional.

Plug 'kyazdani42/nvim-web-devicons'

vim-airline is a very cool plugin that gives some color to Neovim, it gives you a powerline with a ton of information, clear visual cues in which mode you are, where you are in the document, how big it is, what type it is, etc.

Plug 'vim-airline/vim-airline'

Barbar is a very nice Tab bar for Neovim, It will help you navigate your open tabs visually instead of just guessing the next or previous tab.

Plug 'romgrk/barbar.nvim'

Nvim-Tree is a directory browser, It is very handy if you want to have an overview of the files in the directory, browse and open them for editing.

Plug 'kyazdani42/nvim-tree.lua'

Be sure to add the Ctrl + T keybind

nmap <C-t> :NvimTreeToggle<CR>

Also add the following to your vim.init somewhere after loading the plugins

lua require("nvim-tree").setup()

Floaterm is a simple terminal which is handy for obvious reasons.

Plug 'voldikss/vim-floaterm'

Be sure to add the Ctrl + Y keybind

nmap <C-y> :FloatermNew --autoclose=2 --wintype=split --height=0.3<CR>

Ctrl P is a great plugin that allows you to open files directly with a hotkey typing (part of) the filename you want to open and press enter to edit it directly.

Plug 'ctrlpvim/ctrlp.vim'

Be sure to add the Ctrl + F Keybind

nmap <C-f> :CtrlP<CR>

Also add the following between the plugin options somewhere after the plug block

let g:ctrlp_map = '<c-/>'

Undotree is a great plugin that allows you to look into your undo history see the acctual changes you made and revert to any of the previous stages of your document, You can also go forward after you went back ofcourse.

Plug 'mbbill/undotree'

Be sure to add the Ctrl + U keymap

nmap <C-u> :UndotreeToggle<CR>

GitGutter is a great plugin that can show you git diffs and much much more git functionality

Plug 'airblade/vim-gitgutter'

Be sure to add the CTRL + G toggle as a keymap to your init.vim

nmap <C-g> :GitGutterToggle<CR>

Nerdcommenter is a handy plugin to comment out lines or a bunch of lines with a single key.

Plug 'preservim/nerdcommenter'

Be sure to add the keymaps for Ctrl + C in normal and visual mode

nmap <C-c> <Plug>NERDCommenterInvert
vmap <C-c> <Plug>NERDCommenterInvert

Autopairs is a simple plugin to handle quotes, brackets and other pairs of characters for you.

Plug 'jiangmiao/auto-pairs'

42Header is something we need to use for school, But I made some little changes to it so it supports changing the ascii art to something like a little Tux :)

Plug 'pbondoer/vim-42header'

Neovim LSP Config

Language Server Protocol is used for live code checking using external Language Servers

For the scope of this guide we will set up a few languages but first we need to install the nvim-lspconfig plugin to make it all a bit easier

Add the following line in your init.vim on a empty line inside the plug block

Plug 'neovim/nvim-lspconfig'

Run the following command to install it

nvim +PlugUpdate +qall

Now we can simply install language servers using pacman and add them to the init.vim file accordingly

Lets start with Bash, simply install the language server using pacman

sudo pacman -S bash-language-server

Now add the language server to your init.vim file of choice

lua require'lspconfig'.bashls.setup{}

Next up is C, Install the language server with pacman

sudo pacman -S ccls

And add the language server to your init.vim file of choice

lua require'lspconfig'.ccls.setup{}

Next up is CSS, Install the language server with pacman

sudo pacman -S vscode-css-languageserver

And add the language server to your init.vim file of choice

lua require'lspconfig'.cssls.setup{}

Next up is HTML, Install the language server with pacman

sudo pacman -S vscode-html-languageserver

And add the language server to your init.vim file of choice

lua require'lspconfig'.html.setup{}

Next up is JS, Install the language server with pacman

sudo pacman -S deno

And add the language server to your init.vim file of choice

lua require'lspconfig'.denols.setup{}

Next up is json, Install the language server with pacman

sudo pacman -S vscode-json-languageserver

And add the language server to your init.vim file of choice

lua require'lspconfig'.jsonls.setup{}

Next up is Lua, Install the language server with pacman

sudo pacman -S lua-language-server

And add the language server to your init.vim file of choice

lua require'lspconfig'.sumneko_lua.setup{}

Next up is Python, Install the language server with pacman

sudo pacman -S pyright

And add the language server to your init.vim file of choice

lua require'lspconfig'.pyright.setup{}

Next up is Rust, Install the language server with pacman

sudo pacman -S rust-analyzer

And add the language server to your init.vim file of choice

lua require'lspconfig'.rust_analyzer.setup{}

Next up is YAML, Install the language server with pacman

sudo pacman -S yaml-language-server

And add the language server to your init.vim file of choice

lua require'lspconfig'.yamlls.setup{}

You can add many many more, just look for nvim plugins online

Hotkeys

Just a simple overview of all the hotkeys you can use

a = Append, Enter Insert mode 1 character after the cursor
b = Move 1 word backwards, Works with numbers
c = Nothing
d = Delete, Deletes a character, double press it to delete the line, also works with numbers and move commands
e = Nothing
f = Find, Finds a character and jumps to that position
g = Goto, enter a line press g twice and you will jump to the line, double press it to go to the first line
h = Left, Same function as the left arrow, but closer to your hand.
i = Insert, Enter Insert mode on the cursor
j = Down, Same function as the down arrow, but closer to your hand.
k = Up, Same function as the up arrow, but closer to your hand.
l = Right, Same function as the right arrow, but closer to your hand.
m = Bookmark position, press m, then press another character to bind it to, use ' to go to the section
n = Nothing
o = Enter insert mode on a new line below the current line.
p = Paste, Pastes the buffer after the current cursor position
q = Record, Press a key after hitting q to start recording, do some stuff and press q again in normal mode to save the recording, then type @key to repeat the action, type 20@key to do it 20 times.
r = Nothing
s = Nothing
t = Nothing
u = Undo your previous action.
v = Visual mode, Switch to Visual mode to select stuff character for character.
w = Move 1 word forward, works with numbers
x = Delete character under the cursor
y = Yank, Or Copy in recent terms, press it once to copy the selection, press it twice to copy the entire line and include a number to copy that amount of line.
z = Nothing

Shift + Arrows = Resize Splits
A = Append, Enter insert mode at the end of the line.
B = Move 1 whitespace backwards
C = Nothing
D = Delete everything on line after the cursor
E = Nothing
F = Find, Finds a character going backwards and jumps to that position
G = Move to the end of the file
H = Make split smaller horizontally
I = Nothing
J = Make split smaller vertically
K = Make split bigger vertically
L = Make split bigger horizontally
M = Nothing
N = Nothing
O = Nothing
P = Paste before cursor
Q = Enter insert mode on a new line above the current line
R = Replace Characters instead of Inserting them
S = Nothing
T = Nothing
U = Nothing
V = Visual Line mode, Select lines to edit, yank, or manipulate
W  = Move 1 whitespace forward
X = Nothing
Y = Nothing
Z = Double press it to save and exit

0 = Go to beginning of line
~ = Change case of current character
!
@ = enter @ and then type the letter of the recording made with q to play in
# = Highlight the word you are standing on in the rest of the document
$ = Go to end of line
%
^ = Go to the first character on the line
&
*
( = Jump to previous sentence
) = Jump to next sentence
=
-
[
]
{ = Navigate up a codeblock
} = Navigate down a codeblock
' = Go to bookmark saved earlier with m
"
;
:
<
>
,
.
/ search, type, press enter and press n/N to go to the next/previous result
?

Ctrl + Arrows = Change active split
Ctrl + A = increments ints
Ctrl + B = Split window below
Ctrl + C = Comment out line or selection
Ctrl + D = Delete current buffer
Ctrl + E = Next Buffer
Ctrl + F = Find file and open it quickly
Ctrl + G = Toggle Git
Ctrl + H = Navigate around splits to the left
Ctrl + I = Nothing
Ctrl + J = Navigate around splits to below
Ctrl + K = Navigate around splits to up
Ctrl + L = Navigate around splits to the right
Ctrl + M = Toggle invisible characters
Ctrl + N = Split window next
Ctrl + O = Open new Buffer
Ctrl + P = Toggle Numberline
Ctrl + Q = Quit
Ctrl + R = Redo your previous action
Ctrl + S = Save current buffer
Ctrl + T = Toggle directory tree
Ctrl + U = Open undo history
Ctrl + V = Visual Block Mode, Select a custom block of text to manipulate
Ctrl + W = Previous Buffer
Ctrl + X = Decrements ints
Ctrl + Y = Show Terminal
Ctrl + Z = Places the application in the background

Alt + Arrows = move line or selection
Alt + A = Nothing
Alt + B = Nothing
Alt + C = Toggle Invisible Characters
Alt + D = Nothing
Alt + E = Next Tab
Alt + F = Nothing
Alt + G = Nothing
Alt + H = Remove indent for line or selection
Alt + H = Nothing
Alt + I = Move Tab to the Right
Alt + J = Nothing
Alt + J = Move line or selection to the line below
Alt + K = Move line or selection to the line above
Alt + L = Add indent for line or selection
Alt + M = Nothing
Alt + N = Nothing
Alt + O = Open New Tab
Alt + P = Toggle Autopairs
Alt + Q = Nothing
Alt + R = Nothing
Alt + S = Nothing
Alt + T = Nothing
Alt + U = Move Tab to the Left
Alt + V = Nothing
Alt + W = Previous Tab
Alt + X = Nothing
Alt + Y = Nothing
Alt + Z = Nothing

Pacman Hooks for Updating Plugins

It is important that we update our plugins regularly, I will add more later WIP!

GDB

GDB is the GNU Debugger, It is extremely powerfull, I will add this one later WIP!

Valgrind

Valgrind is the best memory checker I have used, I will add this one later WIP!

Installing Geekbench

Geekbench is a very nice benchmarking toolkit for benchmarking your CPU and GPU, It runs on almost everything, So you can compare your PC against your Phone and your Server for example :)

git clone https://aur.archlinux.org/geekbench.git

Now change the directory to the just downloaded folder

cd geekbench

Now build and install the package

makepkg -si

Now you should be able to benchmark your system by running the following commands, There are more beenchmarks available but these 2 are the important ones :)

CPU

geekbench --cpu

GPU Vulkan

geekbench --compute vulkan

Install MPD

MPD is the Media Player Daemon, It is a media player as a service that needs an mpd client to steer it. It is great for a raspberry connected to your receiver for example. I use it on my PC with Ampache installed on my server controlling it.

sudo pacman -S mpd && systemctl --user enable mpd

If you want media keys to work with MPD

sudo pacman -S mpd-mpris

Cleaning up and maintaining the system

Lastly we are going to clean up a bit, We left a lot of mess in your home directory during in the few hours, You can remove all the folders we used for installing the AUR packages, like pamac-aur, nautilus-nextcloud, numix-square-icons, etc

To maintain your system all you have to do is update it, you can run the following command to update your entire system.

sudo pacman -Syu

If you followed the complete guide and installed Pamac, you can just use pamac to update all packages on your system including the ones from the AUR.

You don't have to update every day, You can ofcourse, But if you want to update every week or every 2 weeks that is fine too, I do think the sweet spot is between 3 days and a week. Unless you don't use the device I would not wait longer than a month with updates, some of the updates are pretty important for the security of the device, Which is the main reason why you MUST update.

You can also remove orphaned packages every once in a while with the following command

sudo pacman -Rnsc $(pacman -Qqdt)

You do this in pamac by going to the installed tab, then click on orphans and then select all to remove them.

I would be careful with executing commands from the internet, especially the sudo command, It is extremely powerful, You could mess up everything with many simple commands.

If you need extra software, always try the repos first! Nothing wrong with needing something from the AUR, but try to keep it to a minimum, and regularly check the "Foreign Packages" under installed in Pamac to check what AUR packages are still installed, If you see anything you don't recognize, try to remove it, If it is a dependency Pamac will warn you and you can always cancel.

I would recommend against Installing software from git, web, trough scripts, make, curl, wget, etc. Don't unless you absolutely need it and know what you are doing, But by that time I would recommend to just add it to the AUR yourself.

I would also recommend keeping your home directory nice and orderly.