Skip to main content

Resources

Adding group members in Ubuntu

Once you have groups in place, you can add existing users as well as new users to that group. All access rights and permissions assigned to the group will be automatically available to all the members of the group.

Getting ready

You will need super user or root privileges to add a group member to the Ubuntu server.

How to do it…

Follow these steps to add group members:

  1. Here, you can use adduser command with two non-option arguments:
    $ sudo adduser john guest
  2. Enter your password to complete addgroup with root privileges.

How it works…

As mentioned previously, you can use the adduser command to add an existing user to an existing group. Here, we have passed two non-option arguments:

  • john: This is the name of the user to be added to the group
  • guest: This is the name of the group

There's more…

Alternatively, you can use the command usermod to modify the group assigned to the user:

$ sudo usermod -g

To add a user to multiple groups, use the following command:

$ sudo usermod -a -G ,,

This will add to , , and . Without flag –a, any previously assigned groups will be replaced with new groups.

Setting resource limits on LXD containers in Ubuntu

In this recipe, we will learn to set resource limits on containers. LXD uses the cgroups feature in the Linux kernel to manage resource allocation and limits. Limits can be applied to a single container through configuration or set in a profile, applying limits to a group of containers at once. Limits can be dynamically updated even when the container is running.

How to do it…

We will create a new profile and configure various resource limits in it. Once the profile is ready, we can use it with any number of containers. Follow these steps:

Create a new profile with the following command:

$ lxc profile create cookbook

Profile cookbook created

Next, edit the profile with lxc profile edit. This will open a text editor with a default profile structure in YML format:

$ lxc profile edit cookbook

Add the following details to the profile. Feel free to select any parameters and change their values as required:

name: cookbook

config:

boot.autostart: "true"

limits.cpu: "1"

limits.cpu.priority: "10"

limits.disk.priority: "10"

limits.memory: 128MB

limits.processes: "100"

description: A profile for Ubuntu Cookbook Containers

devices:

eth0:

nictype: bridged

parent: lxdbr0

type: nic

Save your changes to the profile and exit the text editor.

Optionally, you can check the created profile, as follows:

$ lxc profile show cookbook

Now, our profile is ready and can be used with a container to set limits. Create a new container using our profile:

$ lxc launch ubuntu:xenial c4 -p cookbook

This should create and start a new container with the cookbook profile applied to it. You can check the profile in use with the lxc info command:

$ lxc info c4

Check the memory limits applied to container c4:

$ lxc exec c4 -- free -m

Profiles can be updated even when they are in use. All containers using that profile will be updated with the respective changes, or return a failure message. Update your profile as follows:

$ lxc profile set cookbook limits.memory 256MB

How it works…

LXD provides multiple options to set resource limits on containers. You can apply limits using profiles or configure containers separately with the lxc config command. The advantage of creating profiles is that you can have various parameters defined in one central place, and all those parameters can be applied to multiple containers at once. A container can have multiple profiles applied and also have configuration parameters explicitly set. The overlapping parameters will take a value from the last applied profile. Also the parameters that are set explicitly using lxc config will override any values set by profiles.

The LXD installation ships with two preconfigured profiles. One is default, which is applied to all containers that do not receive any other profile. This contains a network device for a container. The other profile, named docker, configures the required kernel modules to run Docker inside the container. You can view the parameters of any profile with the lxc profile show profile_name command.

In the previous example, we used the edit option to edit the profile and set multiple parameters at once. You can also set each parameter separately or update the profile with the set option:

$ lxc profile set cookbook limits.memory 256MB

Similarly, use the get option to read any single parameter from a profile:

$ lxc profile get cookbook limits.memory

Profiles can also be applied to a running container with lxc profile apply. The following command will apply two profiles, default and cookbook, to an existing container, c6:

$ lxc profile apply c6 default,cookbook

Updating the profiles will update the configuration for all container using that profile. To modify a single container, you can use lxc config set or pass the parameters directly to a new container using the -c flag:

$ lxc launch ubuntu:xenial c7 -c limits.memory=64MB

Similar to lxc profile, you can use the edit option with lxc config to modify multiple parameters at once. The same command can also be used to configure or read server parameters. When used without any container name, the command applies to the LXD daemon.

There's more…

The lxc profile and lxc config commands can also be used to attach local devices to containers. Both commands provide the option to work with various devices, which include network, disk IO, and so on. The simplest example will be to pass a local directory to a container, as follows:

$ lxc config device add c1 share disk \

source=/home/ubuntu path=home/ubuntu/shared

See also

Read more about setting resource limits at https://www.stgraber.org/2016/03/26/lxd-2-0-resource-control-412

For more details about LXC configuration, check the help menu for the lxc profile and lxc config commands, as follows:

$ lxc config --help

Installing Network File System in Ubuntu

Network File System (NFS) is a distributed filesystem protocol that allows clients to access remote files and directories as if they are available on the local system. This allows client systems to leverage large centrally shared storage. Users can access the same data from any system across the network. A typical setup for NFS includes a server that runs the NFS daemon, nfsd, and lists (export) files and directories to be shared. A client system can mount these exported directories as their local file system.

In this recipe, we will learn how to install the NFS server and client systems.

Getting ready

You will need two Ubuntu systems: one as a central NFS server and another as a client. For this recipe, we will refer to the NFS server with the name Host and the NFS client with the name Client. The following is an example IP address configuration for the Host and Client systems:

Host - 10.0.2.60

Client - 10.0.2.61

You will need access to a root account on both servers, or at least an account with sudo privileges.

How to do it…

Follow these steps to install NFS:

First, we need to install the NFS server:

$ sudo apt-get update

$ sudo apt-get install nfs-kernel-server

Create the directories to be shared:

$ sudo mkdir /var/nfs

Add this directory to NFS exports under /etc/exports:

$ sudo nano /etc/exports

Add the following line to /etc/exports:

/var/nfs *(rw,sync,no_subtree_check)

Save and close the exports file.

Now, restart the NFS service:

$ sudo service nfs-kernel-server restart

Next, we need to configure the client system to access NFS shares.

Create a mount point for NFS shares.

Install the nfs-common package on the client side:

$ sudo apt-get install nfs-common

$ sudo mkdir -p /var/nfsshare

Mount the NFS shared directory on the newly-created mount point:

$ sudo mount 10.0.2.60:/var/nfs /var/nfsshare

Confirm the mounted share with the following command:

$ mount -t nfs

Now, change the directory to /var/nfsshare, and you are ready to use NFS.

How it works…

In the preceding example, we have installed the NFS server and then created a directory that will share with clients over the network. The configuration file /etc/exports contains all NFS shared directories. The syntax to add new exports is as follows:

directory_to_share client_IP_or_name(option1, option2, option..n)

The options used in exports are as follows:

rw: This enables read/write access. You can enable read-only access with the ro option.

sync: This forces the NFS server to write changes to disk before replying to requests. sync is the default option; you can enable async operations by explicitly stating async. Async operations may get a little performance boost but at the cost of data integrity.

no_subtree_check: This disables subtree checking, which provides more stable and reliable NFS shares.

You can check the exports documentation for more export options. Use the man command to open the exports manual pages, as follows:

$ man exports

In the preceding example, we have used the mount command to mount the NFS share. Once the client system has restarted, this mount will be removed. To remount the NFS share on each reboot, you can add the following line to /etc/fstab file:

10.0.2.60:/var/nfs /var/nfsshare nfs4 _netdev,auto 0 0

To mount all shares exported by the NFS server, you can use the following command:

$ sudo mount 10.0.2.60:/ /var/nfsshare

There's more…

NFS 4.1 adds support for pNFS, which enables clients to access the storage device directly and in parallel. This architecture eliminates scalability and performance issues with NFS deployments.

See also

NFS exports options at http://manpages.ubuntu.com/manpages/trusty/man5/exports.5.html

Parallel NFS at http://www.pnfs.com/

NFS documentation in manual pages, by using the following command:

$ man nfs

Installing web access for MySQL in Ubuntu

In this recipe, we will set up a well-known web-based MySQL administrative tool—phpMyAdmin.

Getting ready

You will need access to a root account or an account with sudo privileges.

You will need a web server set up to serve PHP contents.

How to do it…

Follow these steps to install web access for MySQL:

Enable the mcrypt extension for PHP:

$ sudo php5enmod mcrypt

Install phpmyadmin with the following commands:

$ sudo apt-get update

$ sudo apt-get install phpmyadmin

The installation process will download the necessary packages and then prompt you to configure phpmyadmin:

Choose to proceed with the configuration process.

Enter the MySQL admin account password on the next screen:

Another screen will pop up; this time, you will be asked for the new password for the phpmyadmin user. Enter the new password and then confirm it on the next screen:

Next, phpmyadmin will ask for web server selection:

Once the installation completes, you can access phpMyAdmin at http://server-ip/phpmyadmin. Use your admin login credentials on the login screen. The phpmyadmin screen will look something like this:

How it works…

PHPMyAdmin is a web-based administrative console for MySQL. It is developed in PHP and works with a web server such as Apache to serve web access. With PHPMyAdmin, you can do database tasks such as create databases and tables; select, insert, update data; modify table definitions; and a lot more. It provides a query console which can be used to type in custom queries and execute them from same screen.

With the addition of the Ubuntu software repository, it has become easy to install PHPMyAdmin with a single command. Once it is installed, a new user is created on the MySQL server. It also supports connecting to multiple servers. You can find all configuration files located in the /etc/phpmyadmin directory.

There’s more…

If you want to install the latest version of phpMyAdmin, you can download it from their official website, https://www.phpmyadmin.net/downloads/ . You can extract downloaded contents to your web directory and set MySQL credentials in the config.inc.php file.

See also

Read more about phpMyAdmin in the Ubuntu server guide at https://help.ubuntu.com/lts/serverguide/phpmyadmin.html

Install and secure phpMyAdmin at https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-phpmyadmin-on-ubuntu-14-04

Introduction on Centralized Authentication Service

When you have a large user base using multiple services across the organization, a centralized authentication service becomes a need rather than a luxury. It becomes necessary to quickly add new user accounts across multiple services when a new user comes in, and deactivate the respective access tokens when a user leaves the organization. A centralized authentication service enables you to quickly respond by updating the user database on a single central server.

Various different services are available to set up centralized authentication. In this article, we will learn how to set up a centralized authentication service using a Lightweight Directory access Protocol (LDAP). A directory is a special database designed specifically for high volume lookups. LDAP directories are tree-based data structures, also known as Directory Information Trees (DIT). Each node in a tree contains a unique entry with its own set of attributes.

LDAP is specifically designed for high volume read systems with limited write activities. These directories are commonly used for storing details of users with their respective access control lists. Some examples include shared address books, shared calendar services, centralized authentication for systems such as Samba, and storage DNS systems. LDAP provides lightweight access to the directory services over the TCP/IP stack. It is similar to the X.500 OSI directory service, but with limited features and limited resource requirements. For more details on LDAP, check out the OpenLDAP admin guide at http://www.openldap.org/doc/admin24/intro.html .

Securing Ubuntu web server

In this recipe, we will learn some steps for securing web server installation.

Getting ready

You will need access to a root account or an account with sudo privileges.

You may need to have a web server stack installed and running.

How to do it…

Follow these steps to secure the web server:

Disable any unwanted modules. You can check all enabled modules with the following command:

$ a2query -m

Disable modules with the following command:

$ sudo a2dismod status

Hide the web server's identity. For Apache, edit /etc/apache2/conf-available/security.conf and set the following values:

ServerSignature Off

ServerTokens Prod

You may want to check other options under security.conf.

Next, disable the Apache server status page:

$ sudo a2dismod status

For Nginx, edit /etc/nginx/nginx.conf and uncomment the following line:

# server_tokens off;

In production environments, minimize the detail shown on error pages. You can enable the PHP Suhosin module and strict mode.

Disable directory listing. On Apache, add the following line to the virtual host configuration:

Options -Indexes

You can also disable directory listing globally by setting Options -Indexes in /etc/apache2/apache2.conf.

Restrict access to the following directories:

Order deny,allow # order of Deny and Allow

Deny from all # Deny web root for all

Disable directory level settings and the use of .htaccess. This also helps improve performance:

AllowOverride None # disable use of .htaccess

Disable the following symbolic links:

Options -FollowSymLinks

You can also install mod_security and mod_evasive for added security. mod_security acts as a firewall by monitoring traffic in real time, whereas mod_evasive provides protection against Denial of Service attacks by monitoring request data and requester IP.

For Apache, you can install mod_security as a plugin module as follows:

$ sudo apt-get install libapache2-modsecurity

$ sudo a2enmod mod-security

On Nginx, you need to first compile mod_security and then compile Nginx with mod_security enabled.

Turn of server side includes and CGI scripts:

Options -ExecCGI -Includes

Limit request body, headers, request fields, and max concurrent connections; this will help against DOS attacks.

Set the following variables on Apache:

TimeOut

KeepAliveTimeout

RequestReadTimeout

LimitRequestBody

LimitRequestFields

LimitRequestFieldSize

LimitRequestLine

MaxRequestWorkers

For Nginx, configure the following variables to control buffer overflow attacks:

client_body_buffer_size

client_header_buffer_size

client_max_body_size

large_client_header_buffers

Enable logging and periodically monitor logs for any new or unrecognized events:

ErrorLog /var/log/httpd/example.com/error_log

CustomLog /var/log/httpd/example.com/access_log combined

Set up HTTPs and set it to use modern ciphers. You can also disable the use of SSL and enforce TLS.

How it works…

In this recipe, I have listed the various options available to make your web server more secure. It is not necessary to set all these settings. Disabling some of these settings, especially FollowSymlinks and AllowOverride, may not suit your requirements or your environment. You can always choose the settings that apply to your setup.

Various settings listed here are available in their respective configuration files, mostly under /etc/apache2 for the Apache web server and /etc/nginx for the Nginx server.

Also, do not forget to reload or restart your server after setting these options.

You should also set your Ubuntu environment to be more secure. You can find more details on securing Ubuntu in article 2, Networking.

See also

Installing mod_evasive at https://www.linode.com/docs/websites/apache-tips-and-tricks/modevasive-on-apache

Apache security tips at http://httpd.apache.org/docs/2.4/misc/security_tips.html

Setting up mod_security at https://www.digitalocean.com/community/tutorials/how-to-set-up-mod_security-with-apache-on-debian-ubuntu

Creating repository with GitLab

Now that we have set up our own Git hosting and created a new user account, we can start using our Git hosting by creating a new Git repository.

Getting ready

This recipe uses the GitLab setup. Make sure that you have followed the previous recipe and installed your GitLab server.

Log in with your user account on the GitLab server. You can choose the admin account, but a normal user account is recommended.

If you need to use SSH to clone and push to your repositories, you will need to set up your SSH key. From the dashboard, click on Profile Settings and then select SSH Keys to add a new SSH key. Check article 2, Networking, for more details on how to create an SSH key.

How to do it…

In the previous recipe, we learned how to create a local repository and then push it to the remote. Here, we will first create a remote or hosted repository and then clone it to our local system:

Log in to your GitLab account. You will be greeted with the Welcome screen detailing your projects.

Click on the NEW PROJECT button to create a new repository:

On a new screen, enter the project or repository name in the project path field. Add an optional descriptive message and select the proper checkbox to make your repository public or private:

Next, click on the Create Project button to create a new repository. This will redirect you to the repository page.

A URL for your repository is listed, with some details on how to use your new repository. You can use HTTP URL if you have not set up SSH keys. Additionally, you may need to replace the hostname with the server IP from the repository URL:

Alternatively, you can create a readme file from the GitLab interface itself. Click on the README link to open a file editor in your browser.

When you clone the private repository using its HTTP URL, a local Git daemon will ask you for the username and password details for authentication.

Tuning TCP stack for Ubuntu

Transmission Control Protocol and Internet Protocol (TCP/IP) is a standard set of protocols used by every network-enabled device. TCP/IP defines the standards to communicate over a network. TCP/IP is a set of protocols and is divided in two parts: TCP and IP. IP defines the rules for IP addressing and routing packets over network and provides an identity IP address to each host on the network. TCP deals with the interconnection between two hosts and enables them to exchange data over network. TCP is a connection-oriented protocol and controls the ordering of packets, retransmission, error detection, and other reliability tasks.

TCP stack is designed to be very general in nature so that it can be used by anyone for any network conditions. Servers use the same TCP/IP stack as used by their clients. For this reason, the default values are configured for general uses and not optimized for high-load server environments. New Linux kernel provides a tool called sysctl that can be used to modify kernel parameters at runtime without recompiling the entire kernel. We can use sysctl to modify and TCP/IP parameters to match our needs.

In this recipe, we will look at various kernel parameters that control the network. It is not required to modify all parameters listed here. You can choose ones that are required and suitable for your system and network environment.

It is advisable to test these modifications on local systems before doing any changes on live environment. A lot of these parameters directly deal with network connections and related CPU and memory uses. This can result in connection drops and/or sudden increases in resource use. Make sure that you have read the documentation for the parameter before you change anything.

Also, it is a good idea to set benchmarks before and after making any changes to sysctl parameters. This will give you a base to compare improvements, if any. Again, benchmarks may not reveal all the effects of parameter changes. Make sure that you have read the respective documentation.

Getting ready…

You will need root access.

Note down basic performance metrics with the tool of your choice.

How to do it…

Follow these steps to tune the TCP stack:

Set the maximum open files limit:

$ ulimit -n # check existing limits for logged in user

# ulimit -n 65535 # root change values above hard limits

To permanently set limits for a user, open /etc/security/limits.conf and add the following lines at end of the file. Make sure to replace values in brackets, >:

soft nofile # soft limits

hard nofile # hard limits

Save limits.conf and exit. Then restart the user session.

View all available parameters:

# sysctl -a

Set the TCP default read-write buffer:

# echo 'net.core.rmem_default=65536' >> /etc/sysctl.conf

# echo 'net.core.wmem_default=65536' >> /etc/sysctl.conf

Set the TCP read and write buffers to 8 MB:

# echo 'net.core.rmem_max=8388608' >> /etc/sysctl.conf

# echo 'net.core.wmem_max=8388608' >> /etc/sysctl.conf

Increase the maximum TCP orphans:

# echo 'net.ipv4.tcp_max_orphans=4096' >> /etc/sysctl.conf

Disable slow start after being idle:

# echo 'net.ipv4.tcp_slow_start_after_idle=0' >> /etc/sysctl.conf

Minimize TCP connection retries:

# echo 'net.ipv4.tcp_synack_retries=3' >> /etc/sysctl.conf

# echo 'net.ipv4.tcp_syn_retries =3' >> /etc/sysctl.conf

Set the TCP window scaling:

# echo 'net.ipv4.tcp_window_scaling=1' >> /etc/sysctl.conf

Enable timestamps:

# echo 'net.ipv4.tcp_timestamp=1' >> /etc/sysctl.conf

Enable selective acknowledgements:

# echo 'net.ipv4.tcp_sack=0' >> /etc/sysctl.conf

Set the maximum number of times the IPV4 packet can be reordered in the TCP packet stream:

# echo 'net.ipv4.tcp_reordering=3' >> /etc/sysctl.conf

Send data in the opening SYN packet:

# echo 'net.ipv4.tcp_fastopen=1' >> /etc/sysctl.conf

Set the number of opened connections to be remembered before receiving acknowledgement:

# echo 'tcp_max_syn_backlog=1500' >> /etc/sysctl.conf

Set the number of TCP keep-alive probes to send before deciding the connection is broken:

# echo 'tcp_keepalive_probes=5' >> /etc/sysctl.conf

Set the keep-alive time, which is a timeout value after the broken connection is killed:

# echo 'tcp_keepalive_time=1800' >> /etc/sysctl.conf

Set intervals to send keep-alive packets:

# echo 'tcp_keepalive_intvl=60' >> /etc/sysctl.conf

Set to reuse or recycle connections in the wait state:

# echo 'net.ipv4.tcp_tw_reuse=1' >> /etc/sysctl.conf

# echo 'net.ipv4.tcp_tw_recycle=1' >> /etc/sysctl.conf

Increase the maximum number of connections:

# echo 'net.ipv4.ip_local_port_range=32768 65535' >> /etc/sysctl.conf

Set TCP FIN timeout:

# echo 'tcp_fin_timeout=60' >> /etc/sysctl.conf

How it works…

The behavior of Linux kernel can be fine tuned with the help of various Linux kernel parameters. These are the options passed to the kernel in order to control various aspects of the system. These parameters can be passed while compiling the kernel, at boot time, or at runtime using the /proc filesystem and tools such as sysctl.

In this recipe, we have used sysctl to configure network-related kernel parameters to fine tune network settings. Again, you need to cross check each configuration to see if it's working as expected.

Along with network parameters, tons of other kernel parameters can be configured with the sysctl command. The -a flag to sysctl will list all the available parameters:

$ sysctl -a

All these configurations are stored in a filesystem at the /proc directory, grouped in their respective categories. You can directly read/write these files or use the sysctl command:

ubuntu@ubuntu:~$ sysctl fs.file-max

fs.file-max = 98869

ubuntu@ubuntu:~$ cat /proc/sys/fs/file-max

98869

See also

Find the explanation of various kernel parameters at the following websites:

http://www.cyberciti.biz/files/linux-kernel/Documentation/networking/ip-sysctl.txt

https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt

Creating group in Ubuntu Server

Group is a way to organize and administer user accounts in Linux. Groups are used to collectively assign rights and permissions to multiple user accounts.

Getting ready

You will need super user or root privileges to add a group to the Ubuntu server.

How to do it...

Follow these steps to create a group:

  1. Enter the following command to add a new group:
    $ sudo addgroup guest
  2. Enter your password to complete addgroup with root privileges.

How it works…

Here, we are simply adding a new group guest to the server. As addgroup needs root privileges, we need to use sudo along with the command. After creating a new group, addgroup displays the GID of the new group.

There's more…

Similar to adduser, you can use addgroup in different modes:

  • Add a normal group when used without any options
  • Add a system group with the--system option
  • Add an existing user to an existing group when called with two non-option arguments

Check out the manual page for the addgroup(man addgroup) to get more details.

Check out groupadd, a low level utility to add new group to the server

Managing LXD containers – advanced options in Ubuntu

In this recipe, we will learn about some advanced options provided by LXD.

How to do it…

Follow these steps to deal with LXD containers:

Sometimes, you may need to clone a container and have it running as a separate system. LXD provides a copy command to create such clones:

$ lxc copy c1 c2 # lxc copy source destination

You can also create a temporary copy with the --ephemeral flag and it will be deleted after one use.

Similarly, you can create a container, configure it as per you requirements, have it stored as an image, and use it to create more containers. The lxc publish command allows you to export existing containers as a new image. The resulting image will contain all modifications from the original container:

$ lxc publish c1 --alias nginx # after installing nginx

The container to be published should be in the stopped state. Alternatively, you can use the --force flag to publish a running container, which will internally stop the container before exporting.

You can also move the entire container from one system to another. The move command helps you with moving containers across hosts. If you move a container on the same host, the original container will be renamed. Note that the container to be renamed must not be running:

$ lxc move c1 c2 # container c1 will be renamed to c2

Finally, we have the snapshot and restore functionality. You can create snapshots of the container or, in simple terms, take a backup of its current state. The snapshot can be a stateful snapshot that stores the container's memory state. Use the following command to create a snapshot of your container:

$ lxc snapshot c1 snap1 # lxc snapshot container cnapshot

The lxc list command will show you the number of snapshots for a given container. To get the details of every snapshot, check the container information with the lxc info command:

$ lxc info c1

...

Snapshots:

c1/shap1 (taken at 2016/05/22 10:34 UTC) (stateless)

Once you have the snapshots created, you can restore it to go back to a point or create new containers out of your snapshots and have both states maintained. To restore your snapshot, use lxc restore, as follows:

$ lxc restore c1 snap1 # lxc restore container snapshot

To create a new container out of your snapshot, use lxc copy, as follows:

$ lxc copy c1/snap1 c4 # lxc copy container/snapshot new_container

When you no longer need a snapshot, delete it with lxc delete, as follows:

$ lxc delete c1/snap1 # lxc delete container/snapshot

How it works…

Most of these commands work with the rootfs or root filesystem of containers. The rootfs is stored under the /var/lib/lxd/containers directory. Copying creates a copy of the rootfs while deleting removes the rootfs for a given container. These commands benefit with the use of the ZFS file system. Features such as copy-on-write speed up the copy and snapshot operations while reducing the total disk space use.

Troubleshooting Samba server in Ubuntu

In this recipe, we will look at the various tools available for troubleshooting Samba shares.

How to do it…

Samba troubleshooting can be separated in to three parts: network connectivity, Samba process issues, and Samba configuration issues. We will go through each of them step by step. As a first step for troubleshooting, let's start with network testing.

Checking network connectivity

Follow these steps to check network connectivity:

Send ping requests to the Samba server to check network connectivity:

$ ping samba-server-ip

Check name resolution. Ping the Samba server by its name. Windows uses netbios for name resolution:

$ ping samba-server-name

Check the Samba configuration for network restrictions. Temporarily open Samba to all hosts.

Use tcpdump to check Samba network communication. Start tcpdump as follows and let it run for some time while accessing the Samba server from clients. All packets will be logged in a file named tcpdump in the current directory:

$ sudo tcpdump -p -s 0 -w tcpdumps port 445 or port 139

If you know the client IP address, you can filter tcpdumps with the following command:

$ sudo tcpdump -s 0 -w tcpdumps host client_IP

Connect to the Samba process with telnet:

$ echo "hello" | telnet localhost 139

Check whether your Samba server uses a firewall. If so, check the allowed ports on your firewall. If the firewall is on, make sure you have allowed the Samba ports as follows:

Try connecting to FTP or a similar TCP service on the Samba server. This may identify the problems with the TCP stack.

Use nmblookup to test netbios name resolution for Windows systems.

Checking the Samba service

Follow these steps to check Samba service:

Check whether the Samba service has started properly:

$ sudo service samba status

Use netstat to check the Samba daemon is listening on the network:

$ sudo netstat -plutn

Use ps to check the Samba processes. Look for the process name, smbd, in the output of the following command:

$ ps aux

Use strace to view the Samba process logs. This will list all filesystem activities by smbd process:

$ strace smbd

Checking Samba logs

Follow these steps to check Samba logs:

Check Samba log files for any warning or errors.

Increase the log level to get more debugging information:

[global]

log level = 3

Enable logging for a specific client with client-specific configuration. First, set the following options under smb.conf to enable client-specific configuration:

[global]

log level = 0

log file = /var/log/samba/log.%m

include = /etc/samba/smb.conf.%m

Now create a new configuration file for a specific client:

$ sudo vi /etc/samba/smb.conf.client1

[global]

log level = 3

Similarly, you can create separate logs for each Samba user:

[global]

log level = 0

log file = /var/log/samba/log.%u

include = /etc/samba/smb.conf.%u

Checking Samba configuration

Follow these steps to check Samba configuration:

Check the registered users and accounts in the Samba server user database with the pdbedit command:

$ sudo pdbedit -L

Check the shares with the smbtree command:

Use the testparm command to find any errors in the Samba configuration:

$ testparm

Check for allowed users and group names. Make sure that group names start with the @ symbol.

Back up your configuration files and then use minimal configuration to test Samba:

[global]

workgroup = WORKGROUP

security = user

browsable = yes

[temp]

path = /tmp

public = yes

Publicly writable directories are not good for server security.

Remove the preceding configuration as soon as testing is finished.

Test your configuration with smbcclient. It should list all Samba shares:

$ smbclient -L localhost -U%

See also

Samba docs troubleshooting at https://www.samba.org/samba/docs/using_samba/ch12.html

Adding users and assigning access rights in Ubuntu server

In this recipe, we will learn how to add new users to the MySQL database server. MySQL provides very flexible and granular user management options. We can create users with full access to an entire database or limit a user to simply read the data from a single database. Again, we will be using queries to create users and grant them access rights. You are free to use any tool of your choice.

Getting ready

You will need a MySQL user account with administrative privileges. You can use the MySQL root account.

How to do it…

Follow these steps to add users to MySQL database server and assign access rights:

Open the MySQL shell with the following command. Enter the password for the admin account when prompted:

$ mysql -u root -p

From the MySQL shell, use the following command to add a new user to MySQL:

mysql> create user ‘dbuser’@’localhost’ identified by ‘password’;

You can check the user account with the following command:

mysql> select user, host, password from mysql.user where user = ‘dbuser’;

Next, add some privileges to this user account:

mysql> grant all privileges on *.* to ‘dbuser’@’localhost’ with grant option;

Verify the privileges for the account as follows:

mysql> show grants for ‘dbuser’@’localhost’

Finally, exit the MySQL shell and try to log in with the new user account. You should log in successfully:

mysql> exit

$ mysql -u dbuser -p

How it works…

MySQL uses the same database structure to store user account information. It contains a hidden database named MySQL that contains all MySQL settings along with user accounts. The statements create user and grant work as a wrapper around common insert statements and make it easy to add new users to the system.

In the preceding example, we created a new user with the name dbuser. This user is allowed to log in only from localhost and requires a password to log in to the MySQL server. You can skip the identified by ‘password’ part to create a user without a password, but of course, it’s not recommended.

To allow a user to log in from any system, you need to set the host part to a %, as follows:

mysql> create user ‘dbuser’@’%’ identified by ‘password’;

You can also limit access from a specific host by specifying its FQDN or IP address:

mysql> create user ‘dbuser’@’host1.example.com’ identified by ‘password’;

Or

mysql> create user ‘dbuser’@’10.0.2.51’ identified by ‘password’;

Note that if you have an anonymous user account on MySQL, then a user created with username’@’% will not be able to log in through localhost. You will need to add a separate entry with username’@’localhost.

Next, we give some privileges to this user account using a grant statement. The preceding example gives all privileges on all databases to the user account dbuser. To limit the database, change the database part to dbname.*:

mysql> grant all privileges on dbname.* to ‘dbuser’@’localhost’ with grant option;

To limit privileges to certain tasks, mention specific privileges in a grant statement:

mysql> grant select, insert, update, delete, create

-> on dbname.* to ‘dbuser’@’localhost’;

The preceding statement will grant select, insert, update, delete, and create privileges on any table under the dbname database.

There’s more…

Similar to preceding add user example, other user management tasks can be performed with SQL queries as follows:

Removing user accounts

You can easily remove a user account with the drop statement, as follows:

mysql> drop user ‘dbuser’@’localhost’;

Setting resource limits

MySQL allows setting limits on individual accounts:

mysql> grant all on dbname.* to ‘dbuser’@’localhost’

-> with max_queries_per_hour 20

-> max_updates_per_hour 10

-> max_connections_per_hour 5

-> max_user_connections 2;

See also

MySQL user account management at https://dev.mysql.com/doc/refman/5.6/en/user-account-management.html

Benchmarking and performance tuning of Apache in Ubuntu

In this recipe, we will learn some performance tuning configurations that may help to squeeze out the last bit of performance from the available hardware. Before diving into performance tuning, we need to evaluate our servers and set a benchmark which can be used to measure improvements after any changes. We will be using a well known HTTP benchmarking tool, Apache Bench (ab). Various other benchmarking tools are available and each one has its own feature set. You can choose the one that best suits your needs.

Getting ready

You will need two systems: one with the web server software installed and another to run Apache Bench. You will need root access or access to an account with similar privileges.

You will also need to modify a few network parameters to handle a large network load. You will also need to set a higher open files limit, in limits.conf, on both systems. Check the Tuning TCP Stack recipe in article 2, Networking.

How to do it…

Install the Apache Bench tool. This is available with the package apache2-utils:

$ sudo apt-get install apache2-utils

If you need to, you can check all the available options of the ab tool as follows:

$ ab -h

Now we are ready to generate network load. Execute the following command to start ab:

$ ab -n 10000 -c 200 -t 2 -k "http://192.168.56.103/index.php"

It will take some time to complete the command depending on the parameters. You should see similar results to the following (partial) output:

Additionally, you may want to benchmark your server for CPU, memory, and IO performance. Check the Setting performance benchmarks recipe in article 13, Performance Monitoring.

Now that we have a benchmark for server performance with stock installation, we can proceed with performance optimization. The following are some settings that are generally recommended for performance tuning:

Apache related settings:

Remove/disable any unused modules

Enable mod_gzip/mod_deflate

Turn HostnameLookups off

Use IP address in configuration files

Use persistence connection by enabling keepalive, then set keepalive timeout

Limit the uses of AllowOverride or completely disable it with AllowOverride none

Disable ExtendedStatus; this is useful while testing but not in production

Nginx related settings:

Set worker_processes to the count of your CPU cores or simply set it to auto

Set the number of worker_connections to test multiple values to find the best match for your servers

Set the keepalive_requests and keepalive_timeout values; these reduce the overhead of creating new connections

Enable idle connections with upstream servers by setting the keepalive value

Enable log buffering with buffer and flush parameters to access_log; this will reduce IO requests while logging

Reduce the log-level - you can set it to warn the user or display an error while in production

Set the sendfile directive to use an efficient sendfile() call from the operating system

Enable caching and compression

Make sure that you track the performance changes after each set of modifications; this way you will have exact knowledge regarding what worked and what not

You should also tune the TCP stack. The details of the TCP stack settings are covered in article 2, Networking.

There's more…

Various other tools are available for benchmarking different features of the web server. The following are some well known tools, as well as a few latest additions:

Httperf: A web server benchmarking tool with some advanced options

Perfkit: a cloud benchmark tool by Google

Wrk: https://github.com/wg/wrk

H2load: HTTP2 load testing tool at https://nghttp2.org/documentation/h2load-howto.html

See also

Apache performance tuning guide at https://httpd.apache.org/docs/2.4/misc/perf-tuning.html

Nginx performance tuning guide at https://www.nginx.com/blog/tuning-nginx/

Adding users to GitLab server

We have set up our own Git hosting server with GitLab, but it still contains a single admin user account. You can start using the setup and create a new repository with an admin account, but it is a good idea to set up a separate non-root account. In this recipe, we will cover the user management and access control features of the GitLab server.

Getting ready

Make sure you have followed the previous recipe and installed the GitLab server.

Login to GitLab with your root or admin account.

You will need to configure the email server before creating a user account. You can use an external email service, such as sendgrid or mailgun. Update your GitLab email server configuration and reconfigure the server for the changes to take effect.

How to do it…

The default landing page for GitLab is a projects page. The same page is listed even when you log in as root. To create a new user, we need to access the admin area:

To open the admin console, click on the admin area icon located at the top-right corner of the screen. Alternatively, you can add /admin to the base URL and access the admin area.

The admin dashboard will greet you with details about your installation and the features and components list. The left-hand menu will list all available options.

Click on the Users menu to get user account-related options.

Next, click on the big green New User button to open a new user form.

Now fill in the required details such as name, username, and email. The form should looks something like this:

You cannot set a password for a new user account on the create user form. The reset password link will be mailed to the user at a given email ID. A new user can set his password through that link:

Under the Access section, you can mark this user as admin and set a limit on projects created by him:

Next, under the profile section, you can add some more details for this user account.

Now, click on the Create User button at the bottom-left of the form. This will save the given details and trigger a password reset email. A screen will change to the User Details page where you can see the account details, groups, and projects of a given user, as well as other details. From the same page, you can block or remove the user account.

The new user account is ready to be used. Open the login page in a new window or private browser and use the email or username and newly set password to log in.

Discussing load balancing with HAProxy in Ubuntu

When an application becomes popular, it sends an increased number of requests to the application server. A single application server may not be able to handle the entire load alone. We can always scale up the underlying hardware, that is, add more memory and more powerful CUPs to increase the server capacity; but these improvements do not always scale linearly. To solve this problem, multiple replicas of the application server are created and the load is distributed among these replicas. Load balancing can be implemented at OSI Layer 4, that is, at TCP or UDP protocol levels, or at Layer 7, that is, application level with HTTP, SMTP, and DNS protocols.

In this recipe, we will install a popular load balancing or load distributing service, HAProxy. HAProxy receives all the requests from clients and directs them to the actual application server for processing. Application server directly returns the final results to the client. We will be setting HAProxy to load balance TCP connections.

Getting ready

You will need two or more application servers and one server for HAProxy:

You will need the root access on the server where you want to install HAProxy

It is assumed that your application servers are properly installed and working

How to do it…

Follow these steps to discus load balancing with HAProxy:

Install HAProxy:

$ sudo apt-get update

$ sudo apt-get install haproxy

Enable the HAProxy init script to automatically start HAProxy on system boot. Open /etc/default/haproxy and set ENABLE to 1:

Now, edit the HAProxy /etc/haproxy/haproxy.cfg configuration file. You may want to create a copy of this file before editing:

$ cd /etc/haproxy

$ sudo cp haproxy.cfg haproxy.cfg.copy

$ sudo nano haproxy.cfg

Find the defaults section and change the mode and option parameters to match the following:

mode tcp

option tcplog

Next, define frontend, which will receive all requests:

frontend www

bind 57.105.2.204:80 # haproxy public IP

default_backend as-backend # backend used

Define backend application servers:

backend as-backend

balance leastconn

mode tcp

server as1 10.0.2.71:80 check # application srv 1

server as2 10.0.2.72:80 check # application srv 2

Save and quit the HAProxy configuration file.

We need to set rsyslog to accept HAProxy logs. Open the rsyslog.conf file, /etc/rsyslog.conf, and uncomment following parameters:

$ModLoad imudp

$UDPServerRun 514

Next, create a new file under /etc/rsyslog.d to specify the HAProxy log location:

$ sudo nano /etc/rsyslog.d/haproxy.conf

Add the following line to the newly created file:

local2.* /var/log/haproxy.log

Save the changes and exit the new file.

Restart the rsyslog service:

$ sudo service rsyslog restart

Restart HAProxy:

$ sudo service haproxy restart

Now, you should be able to access your backend with the HAProxy IP address.

How it works…

Here, we have configured HAProxy as a frontend for a cluster of application servers. Under the frontend section, we have configured HAProxy to listen on the public IP of the HAProxy server. We also specified a backend for this frontend. Under the backend section, we have set a private IP address of the application servers. HAProxy will communicate with the application servers through a private network interface. This will help to keep the internal network latency to a minimum.

HAProxy supports various load balancing algorithms. Some of them are as follows:

Round-robin distributes the load in a round robin fashion. This is the default algorithm used.

leastconn selects the backend server with fewest connections.

source uses the hash of the client's IP address and maps it to the backend. This ensures that requests from a single user are served by the same backend server.

We have selected the leastconn algorithm, which is mentioned under the backend section with the balance leastconn line. The selection of a load balancing algorithm will depend on the type of application and length of connections.

Lastly, we configured rsyslog to accept logs over UDP. HAProxy does not provide separate logging system and passes logs to the system log daemon, rsyslog, over the UDP stream.

There's more …

Depending on your Ubuntu version, you may not get the latest version of HAProxy from the default apt repository. Use the following repository to install the latest release:

$ sudo apt-get install software-properties-common

$ sudo add-apt-repository ppa:vbernat/haproxy-1.6 # replace 1.6 with required version

$ sudo apt-get update && apt-get install haproxy

See also

An introduction to load balancing the HAProxy concepts at https://www.digitalocean.com/community/tutorials/an-introduction-to-haproxy-and-load-balancing-concepts

Streaming music with Ampache in Ubuntu

We have set up the Ampache server and configured it for streaming. In this recipe, we will learn how to set up an Android client to play content from our Ampache server.

Getting ready

You will need an Android or iOS phone or tablet. We will focus on the configuration of an Android client, but the same configuration should work with an iOS device, and even desktop clients such as VLC.

How to do it…

Follow these steps to stream music with Ampache:

First, install Just Player on your Android device. It is an Ampache client and uses XML APIs to stream content from Ampache. It is available from the Play Store.

Once installed, open the settings of Just Player and search for Ampache under cloud player.

We need to add our Ampache server details here. Enter the server URL as the domain name or IP address of your Ampache server and append /ampache at the end, for example:

http://myampacheserver.com/ampache

Next, enter the username and password in their respective fields. You can use the user account created in the last recipe.

Click Check to confirm the settings and then save.

Now you should be able to access your Ampache songs on your Android device or phone.

Creating Ubuntu user accounts in batch mode

In this recipe, you will see how to create multiple user accounts in batch mode without using any external tool.

Getting ready

You will need a user account with root or root privileges.

How to do it...

Follow these steps to create a user account in batch mode:

  1. Create a new text file users.txt with the following command:
    $ touch users.txt
  2. Change file permissions with the following command:
    $ chmod 600 users.txt
  3. Open users.txt with GNU nano and add user account details:
    $ nano users.txt
  4. Press Ctrl + O to save the changes.
  5. Press Ctrl + X to exit GNU nano.
  6. Enter $ sudo newusers users.txt to import all users listed in users.txt file.
  7. Check /etc/passwd to confirm that users are created:

How it works…

We created a database of user details listed in same format as the passwd file. The default format for each row is as follows:

username:passwd:uid:gid:full name:home_dir:shell

Where:

  • username: This is the login name of the user. If a user exists, information for user will be changed; otherwise, a new user will be created.
  • password: This is the password of the user.
  • uid: This is the uid of the user. If empty, a new uid will be assigned to this user.
  • gid: This is the gid for the default group of user. If empty, a new group will be created with the same name as the username.
  • full name: This information will be copied to the gecos field.
  • home_dir: This defines the home directory of the user. If empty, a new home directory will be created with ownership set to new or existing user.
  • shell: This is the default login shell for the user.

The new user command reads each row and updates the user information if the user already exists, or it creates a new user.

We made the users.txt file accessible to owner only. This is to protect this file, as it contains the user's login name and password in unencrypted format.

Managing LXD containers in Ubuntu

We have installed LXD and deployed our first container with it. In this recipe, we will learn various LXD commands that manage the container lifecycle.

Getting ready…

Make sure that you have followed the previous recipes and created your first container.

How to do it…

Follow these steps to manage LXD containers:

Before we start with container management, we will need a running container. If you have been following the previous recipes, you should already have a brand new container running on your system. If your container is not already running, you can start it with the lxc start command:

$ lxc start c1

To check the current state of a container, use lxc list, as follows:

$ lxc list c1

This command should list only containers that have c1 in their name.

You can also set the container to start automatically. Set the boot.autostart configuration option to true and your container will start automatically on system boot. Additionally, you can specify a delay before autostart and a priority in the autostart list:

$ lxc config set c1 boot.autostart true

Once your container is running, you can open a bash session inside a container using the lxc exec command:

$ lxc exec c1 -- bash

root@c1:~# hostname

c1

This should give you a root shell inside a container. Note that to use bash, your container image should have a bash shell installed in it. With alpine containers, you need to use sh as the shell as alpine does not contain the bash shell.

LXD provides the option to pause a container when it's not being actively used. A paused container will still hold memory and other resources assigned to it, but not receive any CPU cycles:

$ lxc pause c1

Containers that are paused can be started again with lxc start.

You can also restart a container with the lxc restart command, with the option to perform a stateful or stateless restart:

$ lxc restart --stateless c1

Once you are done working with the container, you can stop it with the lxc stop command. This will release all resources attached to that container:

$ lxc stop c1

At this point, if your container is an ephemeral container, it will be deleted automatically.

If the container is no longer required, you can explicitly delete it with the lxc delete command:

$ lxc delete c1

There's more…

For those who do not like to work with command line tools, you can use a web-based management console known as LXD GUI. This package is still in beta but can be used on your local LXD deployments. It is available on GitHub at https://github.com/dobin/lxd-webgui .

See also

Get more details about LXD at https://www.stgraber.org/2016/03/19/lxd-2-0-your-first-lxd-container-312/

LXC web panel: https://lxc-webpanel.github.io/install.html