# Lab 9: System time and Package managers

## Exercise 1: System time

### Task 1: Time zone

- Check the current time zone

      $ timedatectl

  You should get output similar to the following:

                     Local time: Вс 2022-11-06 12:40:33 +04
                 Universal time: Вс 2022-11-06 08:40:33 UTC
                       RTC time: Вс 2022-11-06 08:40:33
                      Time zone: Europe/Samara (+04, +0400)
      System clock synchronized: yes
                    NTP service: active
                RTC in local TZ: no

- Assume that we are in Vladivostok and we want to set the timezone to Vladivostok Standard Time (GMT +10). To do this, first get a list of all available time zones.

      $ timedatectl list-timezones

  You will find the full name for the time zone in Vladivostok from the long list of output:

      Asia/Vladivostok

- Now that we have identified the name of the time zone on our system, switch to that with the following command:

      $ sudo timedatectl set-timezone Asia/Vladivostok

- Run `timedatectl` and you should get output different from what we had initially.

      $ timedatectl
                     Local time: Вс 2022-11-06 18:55:05 +10
                 Universal time: Вс 2022-11-06 08:55:05 UTC
                       RTC time: Вс 2022-11-06 08:55:05
                      Time zone: Asia/Vladivostok (+10, +1000)
      System clock synchronized: yes
                    NTP service: active
                RTC in local TZ: no

- To see how this affects system logging, restart rsyslog to trigger some system log events.

      $ systemctl restart rsyslog

- View the log file `/var/log/syslog`.

      $ tail -n 15 /var/log/syslog

  You should see output similar to the following with noticeable change in the timestamp.

      Nov  6 12:55:35 sna-vm systemd[1]: systemd-timedated.service: Deactivated successfully.
      Nov  6 12:57:44 sna-vm systemd[1606]: Started VTE child process 4376 launched by gnome-terminal-server process 2335.
      Nov  6 18:57:54 sna-vm systemd[1]: Stopping System Logging Service...
      Nov  6 18:57:54 sna-vm rsyslogd: [origin software="rsyslogd" swVersion="8.2112.0" x-pid="889" x-info="https://www.rsyslog.com"] exiting on signal 15.
      Nov  6 18:57:54 sna-vm systemd[1]: rsyslog.service: Deactivated successfully.
      Nov  6 18:57:54 sna-vm systemd[1]: Stopped System Logging Service.
      Nov  6 18:57:54 sna-vm systemd[1]: Starting System Logging Service...

#### Change time zone with symlink

- You can manually change the time zone with a symlink. The symlink at `/etc/localtime` points to the time zone that is currently configured.

      $ ls -l /etc/localtime
      lrwxrwxrwx 1 root root 36 ноя  6 18:54 /etc/localtime -> /usr/share/zoneinfo/Asia/Vladivostok

- Remove the symlink

      $ sudo rm -rf /etc/localtime

- Let’s change time zone to Moscow time. To do this, create a new symlink to the Moscow time `Europe/Moscow` in `/usr/share/zoneinfo/`.

      $ sudo ln -s /usr/share/zoneinfo/Europe/Moscow /etc/localtime

- Check the time zone again.

      $ timedatectl

### Task 2: NTP

We are going to set up an NTP server and then configure a client to use this NTP server. You need two VMs to test this. You can work in pairs to set up the client-sever infrastructure.

#### Installing and configuring an NTP server

- First install NTP and it’s dependencies.

      $ apt install -y ntp
      $ apt install -y ntpstat

- Open the NTP configuration file `/etc/ntp.conf` and configure the remote NTP server.

      $ vi /etc/ntp.conf

  Locate the following lines in the configuration file

  Replace those lines with the following

      pool time1.google.com iburst
      pool time2.google.com iburst
      pool time3.google.com iburst
      pool time4.google.com iburst

  Also place a comment on `pool ntp.ubuntu.com`.
  You should have something similar to the following after this modification:

- Restart and enable the NTP service to apply the change.

      $ systemctl restart ntp
      $ systemctl enable ntp

- Allow NTP port on the firewall.

      $ sudo ufw allow ntp

- It will take some time for your NTP server to synchronize with the google NTP servers. Wait for about a minute and run the following command to check the sync status:

      $ ntpstat

  You should get output similar to the following:

      synchronised to NTP server (185.125.190.56) at stratum 3
         time correct to within 977 ms
         polling server every 64 s

  The local NTP server is ready.

- View all NTP peers.

      $ ntpq -p
           remote           refid      st t when poll reach   delay   offset  jitter
      ==============================================================================
       time1.google.co .POOL.          16 p    -   64    0    0.000   +0.000   0.004
       time2.google.co .POOL.          16 p    -   64    0    0.000   +0.000   0.004
       time3.google.co .POOL.          16 p    -   64    0    0.000   +0.000   0.004
       time4.google.co .POOL.          16 p    -   64    0    0.000   +0.000   0.004
      +time1.google.co .GOOG.           1 u   15   64    1   70.098   +3.123   8.037
      *time2.google.co .GOOG.           1 u   17   64    1   38.087   +6.703   6.897
      +time3.google.co .GOOG.           1 u   15   64    1   39.216   +4.192   7.641
      +time4.google.co .GOOG.           1 u   18   64    1   62.781   +8.027  13.030

#### Configuring the client

We show two approaches for configuring the client. You can use either the systemd service `systemd-timesyncd` that comes with systemd-based systems by default, or use `chronyd`.

##### 1. Using `systemd-timesyncd`

- Edit the service configuration file:

      $ vi /etc/systemd/timesyncd.conf

  Add the following line to the file

      NTP=<ntp-server-address>

  You should have something like this:
  Save and exit the file.
- Restart the time sync service

      $ systemctl restart systemd-timesyncd

- Check the status of the time synchronisation:

      $ timedatectl timesync-status
             Server: 192.168.132.136 (192.168.132.136)
      Poll interval: 1min 4s (min: 32s; max 34min 8s)
               Leap: normal
            Version: 4
            Stratum: 2
          Reference: D8EF2308
          Precision: 4us (-18)
      Root distance: 33.583ms (max: 5s)
             Offset: -9.704ms
              Delay: 675us
             Jitter: 0
       Packet count: 1
          Frequency: -81,109ppm

##### 2. Using `chrony`

- Install `chrony`

      $ apt -y install chrony

- Edit the `chrony` configuration file:

      $ vi /etc/chrony/chrony.conf

  Locate the following lines and remove them
  Then add the address of the local NTP server we have configured in the form:

      server <ntp-server-address> iburst prefer

  Save the configuration and exit.
- Restart and enable the `chronyd` service.

      $ systemctl restart chrony
      $ systemctl enable chrony

- View all sources

      $ chronyc sources -v

  > Remember that chrony is a client/server utility. Therefore, other devices can be configured to use this “client” as their NTP “server”.

#### Test the setup

- First check the current time on the client system.

      $ timedatectl
                     Local time: Вс 2022-11-06 18:35:16 MSK
                 Universal time: Вс 2022-11-06 15:35:16 UTC
                       RTC time: Пн 2022-11-07 11:49:46
                      Time zone: Europe/Moscow (MSK, +0300)
      System clock synchronized: yes
                    NTP service: active
                RTC in local TZ: no

- Go to the NTP server and change the date to something completely wrong.

      $ timedatectl set-time 2030-06-10

- Go to the client system and restart the timesync service to force an immediate sync with the local NTP server.

      $ systemctl restart systemd-timesyncd
      OR
      $ systemctl restart chrony

- Check the time on the client machine, and you should see that the client has been configured with the new date we added to the server.

      $ timedatectl
                     Local time: Пн 2030-06-10 00:01:19 MSK
                 Universal time: Вс 2030-06-09 21:01:19 UTC
                       RTC time: Вс 2030-06-09 21:01:19
                      Time zone: Europe/Moscow (MSK, +0300)
      System clock synchronized: yes
                    NTP service: active
                RTC in local TZ: no

- The local NTP server will later sync with the Google NTP servers we configured earlier and correct its time. The client machine will then sync with the local NTP server and correct its time too.
- Wait for about a minute or two and check the time on the NTP server to see the change.

      $ timedatectl
                     Local time: Вс 2022-11-06 18:42:19 MSK
                 Universal time: Вс 2022-11-06 15:42:19 UTC
                       RTC time: Вс 2022-11-06 15:42:19
                      Time zone: Europe/Moscow (MSK, +0300)
      System clock synchronized: yes
                    NTP service: n/a
                RTC in local TZ: no

  The time on the client machine will also be corrected after a while.

## Exercise 2: Package managers

A package manager automates the process of installing, configuring, upgrading, and removing packages.
There are several package managers depending on the OS. This lab focuses on Ubuntu package managers.
Note that Ubuntu is based on the Debian distro and it uses the same APT packaging system as Debian and shares a huge number of packages and libraries from Debian repositories.

### Task 3: dpkg

`dpkg` is a tool that allows the installation and analysis of `.deb` packages. It can also be used to package software.

- View a list of all installed packages

      $ dpkg -l

  You should get an output similar to the following:

- Install a local `.deb` file using the command `dpkg -i <deb-package>`.
  Let’s download and install Google Chrome browser

      $ wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
      $ dpkg -i google-chrome-stable_current_amd64.deb

- Verify the package installation using `dpkg -s <deb-package>`

      $ dpkg -s google-chrome-stable

  You get an output similar to the following

      Package: google-chrome-stable
      Status: install ok installed
      Priority: optional
      Section: web
      Installed-Size: 299404
      Maintainer: Chrome Linux Team <chromium-dev@chromium.org>
      Architecture: amd64
      Version: 107.0.5304.87-1
      Provides: www-browser
      Depends: ca-certificates, fonts-liberation, libasound2 (>= 1.0.17), libatk-bridge2.0-0 (>= 2.5.3), libatk1.0-0 (>= 2.2.0), libatspi2.0-0 (>= 2.9.90), libc6 (>= 2.17), libcairo2 (>= 1.6.0), libcups2 (>= 1.6.0), libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3, libdbus-1-3 (>= 1.5.12), libdrm2 (>= 2.4.60), libexpat1 (>= 2.0.1), libgbm1 (>= 8.1~0), libglib2.0-0 (>= 2.39.4), libgtk-3-0 (>= 3.9.10) | libgtk-4-1, libnspr4 (>= 2:4.9-2~), libnss3 (>= 2:3.26), libpango-1.0-0 (>= 1.14.0), libwayland-client0 (>= 1.0.2), libx11-6 (>= 2:1.4.99.1), libxcb1 (>= 1.9.2), libxcomposite1 (>= 1:0.4.4-1), libxdamage1 (>= 1:1.1), libxext6, libxfixes3, libxkbcommon0 (>= 0.4.1), libxrandr2, wget, xdg-utils (>= 1.0.2)
      Pre-Depends: dpkg (>= 1.14.0)
      Recommends: libu2f-udev, libvulkan1
      Description: The web browser from Google
       Google Chrome is a browser that combines a minimal design with sophisticated technology to make the web faster, safer, and easier.

- List all files installed by a package with the command `dpkg -L <package-name>`

      $ dpkg -L google-chrome-stable

- Remove a package using `dpkg -r <package-name>`

      $ dpkg -r google-chrome-stable

- Check the status of the package again and you should see that it is in the `deinstall` state, but the configuration files are still present.

      $ dpkg -s google-chrome-stable
      Package: google-chrome-stable
      Status: deinstall ok config-files

  The `-r` option simply removes the package but all the configuration files are preserved.

- To remove a package along with its configuration files, specify the `--purge` option.

      $ dpkg --purge google-chrome-stable

- Check the status of the package to verify that the package and all its configuration files have been removed.

      $ dpkg -s google-chrome-stable
      dpkg-query: package 'google-chrome-stable' is not installed and no information is available
      Use dpkg --info (= dpkg-deb --info) to examine archive files.

### Task 4: APT

The Advanced Packaging Tools (APT) is a package manager on Ubuntu systems. `apt` acts as a user friendly tool that interacts with `dpkg`. Unlike `dpkg`, `apt` allows download and installation of packages from online repositories.

- View all available packages in your repository

      $ apt list

- List only installed packages

      $ apt list --installed

- Search for a package using `apt search <package-name>`. Let’s search for “chromium”.

      $ apt search chromium

- After knowing the correct package name, you can find out more details about the package using `apt show <package-name>`

      $ apt show chromium-browser

- Proceed to install the package using `apt install <package-name>`

      $ apt install chromium-browser

- Remove a package using `apt remove <package-name>`

      $ apt remove chromium-browser

> You can install or remove multiple packages in one command by separating them by spaces. e.g `apt install package1 package2 package3`.
> To remove multiple packages is similar e.g `apt remove package1 package2 package3`.

- Specify the `remove` option in combination with the `--purge` option to remove a package along with its configuration.

      $ apt remove --purge chromium-browser

- Specify `autoremove` to remove the package and its dependencies, if not used by any other application. The format is shown below:

      $ apt autoremove <package-name>

- You can update the APT package index to get a list of the available packages. This list can indicate installed packages that need upgrading, as well as new packages that have been added to the repositories.
  The reposiroties are defined in the `/etc/apt/sources.list` file and in the `/etc/apt/sources.list.d` directory.
- View the `sources.list` file to see all the defined repositories.

      $ cat /etc/apt/sources.list

- To update the local package index with latest updates to repositories, use the following command:

      $ apt update

- APT maintains a list of packages (package index) in `/var/lib/apt/lists/`.

      $ ls -lah /var/lib/apt/lists/

- To upgrade a single package that has been previously installed, run the `apt install <package-name>` command.
- To upgrade all installed packages, run the following command:

      $ apt upgrade

  This command will upgrade all packages that can be upgraded without installing additional packages or removing conflicting installed packages.
- Run `apt full-upgrade` to upgrade the packages, the kernel, and remove conflicting packages or install new ones. The `full-upgrade` option is “smart” and can remove unnecessary dependency packages, or install new ones (if required).

### Task 5: sources.list

- View the `sources.list` file without the comments

      $ grep -o '^[^#]*' /etc/apt/sources.list
      deb http://ru.archive.ubuntu.com/ubuntu/ jammy main restricted
      deb http://ru.archive.ubuntu.com/ubuntu/ jammy-updates main restricted
      deb http://ru.archive.ubuntu.com/ubuntu/ jammy universe
      deb http://ru.archive.ubuntu.com/ubuntu/ jammy-updates universe
      deb http://ru.archive.ubuntu.com/ubuntu/ jammy multiverse
      deb http://ru.archive.ubuntu.com/ubuntu/ jammy-updates multiverse
      deb http://ru.archive.ubuntu.com/ubuntu/ jammy-backports main restricted universe multiverse
      deb http://security.ubuntu.com/ubuntu jammy-security main restricted
      deb http://security.ubuntu.com/ubuntu jammy-security universe
      deb http://security.ubuntu.com/ubuntu jammy-security multiverse

- Each line in the `sources.list` has a structure in the following order: Type, URL, Distribution, and Component. Let’s analyse the first line in the `sources.list` above.
  - The Type is `deb`. The term `deb` indicates that it is a repository of binaries.
  - The repository URL is `http://ru.archive.ubuntu.com/ubuntu/`. This is the location of the repository where the packages will be downloaded.
  - The Distribution is `jammy`. This is the short code name of the release. Run `$ cat /etc/os-release` to view the `VERSION_CODENAME` of your system.
  - The Components are `main` and `restricted`. These are information about the licensing of the packages in the repository.
    - `main` contains Canonical supported free and open source software.
    - `restricted` contains proprietary drivers for devices.
    - `universe` contains community supported free and open source software.
    - `multiverse` contains software restricted by copyright or legal issues.

#### Adding repositories

- Let’s try to install a package that is not in Ubuntu repository by default. Install MongoDB

      $ apt install mongo-db

  You should get an output similar to the following

      Reading package lists... Done
      Building dependency tree... Done
      Reading state information... Done
      E: Unable to locate package mongodb-org

  We need to add the MongoDB repository to our repository sources.
- The basic syntax of the add-apt-repository command is as follows:

      $ add-apt-repository [options] repository

  The `repository` can be a regular repository entry that can be added to `sources.list` in the format `deb http://ru.archive.ubuntu.com/ubuntu/ distro component` or a PPA repository in the `ppa:<user>/<ppa-name>` format.
- First import MongoDB PGP key. The key is used to verify the integrity of packages that are downloaded from this repository.

      $ curl -fsSL https://www.mongodb.org/static/pgp/server-6.0.asc | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/mongodb-6.gpg

- Create a list for MongoDB

      $ add-apt-repository 'deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/6.0 multiverse'

  > Alternatively, you can manually create the list file and add the repository to it.

  >     echo "echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/6.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list

- View the new list file that has been created

      $ cat /etc/apt/sources.list.d/*mongodb*.list

- The `add-apt-repository` command automatically updates the local package database for you. If you added the repository via an alternative means, you need to run `$ apt update` to update the local package database.
- View the package index directory to see the MongoDB related files created.

      $ ls -lah /var/lib/apt/lists/ | grep mongodb

  > MongoDB requires `libssl1.1 (>= 1.1.1)`. So let’s download and install this package before proceeding

  >     $ wget http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2.16_amd64.deb
  >     $ dpkg -i ./libssl1.1_1.1.1f-1ubuntu2.16_amd64.deb

- You can now proced to install MongoDB from the newly enabled repository.

      $ apt install mongodb-org

  > You can answer the prompt that asks you to type `Y` to verify your choice by adding the option `-y` to your install command in the format `apt install mongodb-org -y`. This is very useful when writing scripts that install packages.

- Verify that MongoDB has been installed

      $ mongod --version

- You can remove a previously enabled repository using the format `add-apt-repository --remove repository`. Let’s remove the MongoDB repository

      $ add-apt-repository --remove 'deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/6.0 multiverse'

- Run the following commands to verify that the repository has been removed.

      $ ls -lah /var/lib/apt/lists/ | grep mongodb
      $ cat /etc/apt/sources.list.d/*mongodb*.list

### Task 6: Creating a custom Ubuntu package

- Create a directory for the package. We will name the package `snalab`.

      $ mkdir snalab

- Create the internal structure by placing your program files where they should be installed to on the target system. In this case, we want to place the program file in `/usr/local/bin` on the target system, therefore we create the directory `snalab11/usr/local/bin`.

      $ mkdir -p snalab/usr/local/bin

- Create the program file (script) `snalab/usr/local/bin/snalab` and add the following to it.

      #!/bin/bash
      echo "Hello World. This is SNA Lab"

- Give the program file execute permission

      chmod +x snalab/usr/local/bin/snalab

- Create a directory `DEBIAN` in `snalab`

      $ mkdir snalab/DEBIAN

- Create the control file in the `DEBIAN` directory. The control file contains package description and information about the maintainer. Create the file `snalab/DEBIAN/control` and add the following content.

      Package: snalab
      Version: 1.0
      Maintainer: Awwal
      Architecture: all
      Description: Hello SNA

  > These are mandatory fields in the control file. There are several other fields that can be defined.

- Build the package with `dpkg`

      $ dpkg-deb --build --root-owner-group snalab

  > The `--root-owner-group` flag makes all deb package content owned by the root user. Without this flag, all files and folders would be owned by your user, which might not exist in the target system the deb package would be installed to.

- You should have a debian package in your CWD named `snalab.deb`. Proceed to install this package.

      $ dpkg -i snalab.deb

  You should get an output similar to the following

      Selecting previously unselected package snalab11.
      (Reading database ... 195723 files and directories currently installed.)
      Preparing to unpack snalab11.deb ...
      Unpacking snalab11 (1.0) ...
      Setting up snalab11 (1.0) ...

- Run the newly installed package.

      $ snalab
      Hello World. This is SNA Lab

> You can have a compiled application in place of the script we have used.

## Questions to answer

> Instruction: Show all steps taken including screenshots of commands executed, files created, and configuration added.

1. What alternative do you have for configuring your NTP server pool if you don’t want to be dependent on NTP servers on the internet. The time must be accurate and appear to be in sync with other devices globally. Describe how you will perform this setup.

   > The accuracy of the time should be strongly considered.

2. You have two Linux servers whose time won’t stay in sync for various reasons. They tend to drift so much that they have a 30 second difference after 7 days of operation. What can you do to ensure that they stay in sync with each other without relying on external devices or servers?

   > Hint: Inaccurate time is not a problem in this case. The goal is to ensure that both servers are in sync.

3. What are the differences between `apt` and `apt-get`?
4. Why should System Administrators prefer `apt upgrade` over `apt full-upgrade`?
5. Show how you will install Atom text editor from the apt repository. Provide explanation for every step you take.
   - After adding the repository, show the output when you run `$ apt search atom`

   > You are not allowed to manually download the debian package and install it.

6. Create an Ubuntu package that meets the following requirements:
   - The package creates the directory `/var/helloworld/` on the target system.
   - The package contains the python script `/var/helloworld/helloworld.py`. The python script is simple:

         #!/usr/bin/env python3
         print("Hello, World!")

   - The package should deploy a bash script `helloworld` that executes `/var/helloworld/hello.py` on the target system.

Take the following steps after building the package

- List the content of the package with the command `$ dpkg -c <package-name>.deb`.
- Install the package and show all artifacts added to your system by the package.

> After a user installs your package, he should be able to run `$ helloworld` from the terminal without additinonal steps.
> The expected flow of execution is `helloworld (bash script) -> helloworld.py -> Output (Hello, World!)`

### Bonus

> The bonus tasks encourage you to failiarize yourself with CentOS and RPM packages. Linux distributions such as Red Hat and CentOS are very common and they utilize RPM packages.

7. Find and add new source repository to be used for yum.
   - Install a package from it (for example MongoDB).
   - Check with the RPM package manager to verify that the package was installed, and provide details such as dependencies needed.
   - Find logs related to all actions from the previous steps.
8. Sometimes you might have access to an open-source application source code but might not have the RPM file to install it on your system. In that situation, you can either compile the source code and install the application from source code or build an RPM file from source code by yourself and use the RPM file to install the application. There might also be a situation where you want to build a custom RPM package for the application that you developed.
   Create an RPM package to deploy any application of your choice.