Search icon CANCEL
Cart icon
Close icon
You have no products in your basket yet
Save more on your purchases!
Savings automatically calculated. No voucher code required
Arrow left icon
All Products
Best Sellers
New Releases
Learning Hub
Free Learning
Arrow right icon
Mastering Ubuntu Server - Fourth Edition
Mastering Ubuntu Server - Fourth Edition

Mastering Ubuntu Server: Explore the versatile, powerful Linux Server distribution Ubuntu 22.04 with this comprehensive guide, Fourth Edition

$43.99 $29.99
Free Trial
Renews at $15.99p/m

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon AI Assistant (beta) to help accelerate your learning
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
Table of content icon View table of contents Preview book icon Preview Book

Mastering Ubuntu Server - Fourth Edition

Managing Users and Permissions

In the previous chapter, we set up our very own Ubuntu Server installation, and we can now learn how to maintain it, starting with a look at managing who is able to use our server.

As administrators of Ubuntu servers, users can be your greatest asset and also your biggest headache. During your career, you’ll add countless new users, manage their passwords, remove their accounts when they leave the company, and grant or remove access to resources across the network. Even on servers on which you’re the only user, you’ll still find yourself managing user accounts, since even system processes run as users. To be successful at managing Linux servers, you’ll also need to know how to manage permissions, create password policies, and limit who can execute administrative commands on the machine. In this chapter, we’ll work through these concepts so that you have a clear idea of how to manage users and their resources.

In particular, we will cover:

  • Understanding the purpose of users and groups
  • Understanding when to use root
  • Creating and removing users
  • Understanding the /etc/passwd and /etc/shadow files
  • Distributing default configuration files with /etc/skel
  • Switching between users
  • Managing groups
  • Managing passwords and password policies
  • Configuring administrator access with sudo
  • Setting permissions on files and directories

In the first section, we will have a quick discussion about the nature of managing users.

Understanding the purpose of users and groups

When it comes to a server, users are very important—without users to serve, then there’s no real need for a server in the first place. The subject of user management itself within the world of IT is in and of itself quite vast. Entire books have been written on individual methods of authentication, and entire technologies (such as Lightweight Directory Access Protocol, or LDAP) exist around it. In this chapter, we’ll look at managing users that exist locally on our server, and the groups that help define what they are able to do.

Since Ubuntu Server is a distribution of Linux, it adopts the Unix style of managing user accounts, groups, and permissions. Although our focus is on Ubuntu, many of the same commands around user management that you’ll learn in this chapter will apply to other platforms as well. There are commands that allow you to add, remove, and change users, as well as commands that allow you to alter permissions.

Users in the context of a server refer to who (or what) is able to use the server. For example, you may have an accountant named Susan, or an IT administrator named Haneef, who both need to access the server. Perhaps Susan only needs access to a file share directory for accounting-related files, and Haneef might have more access to the server as a system administrator. The user accounts we create on our server will represent the actual people that will use it.

Groups allow us to segregate access to specific files and directories. As we’ll learn later, files and directories have user and group assignments. When combined with permissions, we’ll be able to manage what our users are able to do with our server.

Users aren’t always people, though. We also have system users on our server that applications and running processes might use for background or automated tasks. An example of this might be a backup job, and you may have a backup user that runs a task in the background to facilitate some sort of file copy task that copies important files to another place. You don’t have to worry about system-related users for now, just know that they exist. You’ll see more examples of this as we go through the book.

More advanced organizations may have a central login server, such as Active Directory (AD) or standard LDAP. There are others aside from those, as well. In this book, we won’t cover those technologies, but just keep in mind that central authentication servers are a possibility for your organization, should you choose to explore them.

The most powerful user of all, though, is root. This special user gives us the most control, but as you’ll see in the next section, that comes with risks.

Understanding when to use root

In the last chapter, we set up our very own Ubuntu Server installation. During the installation process, we were instructed to create a user account to act as a system administrator. So, at this point, we should have at least two users on our server. We have the aforementioned administrative user, as well as root. We can certainly create additional user accounts with varying levels of access (and we will do so in this chapter), but before we get to that, some discussion is in order regarding the administrator account you created, as well as the root user that was created for you.

The root user account exists on all Linux distributions and is the most powerful user account on the planet. The root user account can be used to do anything within your server, and I do mean anything. Want to create files and directories virtually anywhere on the filesystem? Want to install software? These processes are easily performed with root. The root account can even be used to destroy your entire installation with one typo or ill-conceived command: if you instruct root to delete all the files on your entire hard disk, it won’t hesitate to do so. It’s always assumed on a Linux system that if you are using root, you are doing so because you know what you are doing. So, there’s often not so much as a confirmation prompt while executing any command as root. It will simply do as instructed, for better or worse.

It’s for this reason that every Linux distribution I’ve ever used has stated, or at least highly recommended, that you create a standard user during the installation process. It’s generally recommended in the Linux community for an administrator to have their own account and then switch to root whenever a task comes up that requires root privileges to complete. This approach is less likely to destroy your server with an accidental typo or bad command. Some administrators will strictly use root at all times without any issue, but again, it’s recommended to use root only when you have to.

Most distributions ask you to create a root password during installation in order to protect that account. Even Debian (on which Ubuntu is based) has you set a root password during installation. Ubuntu just decides to do things a little bit differently. The reason for this is that, unlike many other distributions, Ubuntu defaults to locking out the root account altogether. There’s nothing stopping you from enabling root, or switching to the root user after you log in. Being disabled by default just means the root account isn’t as easily accessible as it normally would be. I’ll cover how to enable this account later in this chapter, should you feel the need to do so.

An exception to this rule is that some VPS providers, such as Linode, will enable the root account even on their Ubuntu servers. Sometimes, the root password will be randomly generated and emailed to you. However, you should still create a user for yourself with administrative access regardless.

Instead of using root outright, Ubuntu (as well as its server version) recommends the use of sudo. Specifically, sudo enables you to run individual commands with elevated privileges instead of being logged in as root all the time.

Using sudo to run privileged commands

I’ll go over how to manage sudo later on in this chapter, but for now, just keep in mind that the purpose of sudo is to enable you to use your user account to do things that normally only root would be able to do. For example, as a normal user, you cannot issue a command such as the following to install a software package (don’t worry about the apt command for now, as we’ll cover that in Chapter 3, Managing Software Packages):

apt install tmux

Instead, you’ll receive an error:

E: Could not open lock file /var/lib/dpkg/lock-frontend - open (13: Permission denied)
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), are you root?

But if you prefix the command with sudo (assuming your user account has access to it), the command will work just fine:

sudo apt install tmux

When you use sudo, you’ll be asked for your user’s password for confirmation, and then the command will execute. Subsequent commands prefixed with sudo may not prompt for your password, as it will cache your password for a short period of time until it times out or the terminal is closed. Understanding this should clarify the usefulness of the user account you created during installation. I referred to this user as an administrative account earlier, but it’s really just a user account that is able to utilize sudo. Ubuntu Server automatically gives the first user account you create during installation access to sudo.

The intent is that you’ll use that account to administer the system, rather than root. When you create additional user accounts, they will not have access to sudo by default, unless you explicitly grant it to them.

Creating and removing users

Creating users in Ubuntu can be done with one of two commands: adduser and useradd. This can be a little confusing at first, because both of these commands do the same thing (in different ways) and are named very similarly. I’ll go over the useradd command first and then I’ll explain how adduser differs. You may even prefer the latter, but we’ll get to that in a moment.

Using useradd

First, here’s an example of the useradd command in action:

sudo useradd -d /home/jdoe -m jdoe

With this command, I created a user named jdoe. With the -d option, I’m clarifying that I would like a home directory created for this user, and following that, I called out /home/jdoe as the user’s home directory. The -m flag tells the system that I would like the home directory to be created during the process; otherwise, I would’ve had to create the directory myself. Finally, I called out the username for my new user (in this case, jdoe).

As we go along in this book, there will be commands that require root privileges in order to execute. The preceding command was an example of this. For commands that require such permissions, I’ll prefix the commands with sudo. When you see these, it just means that root privileges are required to run the command. For these, you can also log in as root (if root is enabled) or switch to root to execute these commands as well. However, as I mentioned before, using sudo instead of using the root account is strongly encouraged.

Now, list the storage of /home using the following command:

ls -l /home

You should see a folder listed there for our new user:

Figure 2.1: Listing the contents of /home after our first user was created

What about creating our user’s password? We may have been asked for our current user’s password due to using sudo, but we weren’t asked for a password for the new user. To create a password for the user, we can use the passwd command. The passwd command defaults to allowing you to change the password for the user you’re currently logged in as, but it also allows you to set a password for any other user if you run it as root or with sudo. If you enter passwd by itself, the command will first ask you for your current password, then your new password, and then it will ask you to confirm your new password again. If you prefix the command with sudo and then specify a different user account, you can set the password for any user you wish. An example of the output of this process is as follows:

Figure 2.2: Changing the password of a user

As you can see in the previous screenshot, you won’t see any asterisks or any kind of output when you type a password using the passwd command. This is normal. Although you won’t see any visual indication of input, your input is being recognized.

Now we have a new user and we were able to set a password for that user. The jdoe user will now be able to access the system with the password we’ve chosen. This user won’t have access to sudo by default, but we’ll cover how to change this later on in the chapter.

Using adduser

Earlier, I mentioned the adduser command as another way of creating a user. The difference (and convenience) of this command should become apparent immediately once you’ve used it. Go ahead and give it a try; execute adduser along with a username for a user you wish to create. An example run of this process is as follows:

Figure 2.3: Creating a user with the adduser command

In the preceding process, I executed sudo adduser dscully (commands that modify users require sudo or root) and then I was asked a series of questions regarding how I wanted the user to be created. I was asked for the password (twice), Full Name, Room Number, Work Phone, and Home Phone. In the Other field, I entered the comment Trust no one, which is a great mindset to adopt while managing users. The latter prompts prior to the final confirmation were all optional: I didn’t have to enter Full Name, Room Number, and so on. I could’ve pressed Enter to skip those prompts if I wanted to. The only things that are really required are the username and the password.

From the output, we can see that the adduser command performed quite a bit of work for us. The command defaulted to using /home/dscully as the home directory for the user, the account was given the next available User ID (UID) and Group ID (GID) of 1002, and it also copied files from /etc/skel into our new user’s home directory. In fact, both the adduser and useradd commands copy files from /etc/skel, but adduser is more verbose regarding the actions it performs.

Don’t worry if you don’t understand what UID, GID, and /etc/skel are yet. We’ll work through those concepts soon.

In a nutshell, the adduser command is much more convenient in the sense that it prompts you for various options while it creates the user without requiring that you memorize command-line options. It also gives you detailed information about what it has done. At this point, you may be wondering why someone would want to use useradd at all, considering how much more convenient adduser seems to be. Unfortunately, adduser is not available on all distributions of Linux. It’s best to familiarize yourself with useradd in case you find yourself on a Linux system that’s not Ubuntu.

It may be interesting for you to see what exactly the adduser command is. It’s not even a binary program—it’s a shell script. A shell script is simply a text file that can be executed as a program. You don’t have to worry too much about scripting now, as we will cover it in Chapter 6, Boosting Your Command-line Efficiency. In the case of adduser, it’s a script written in Perl, which is a programming language that is sometimes used for administrative tasks. Since it’s not binary, you can even open it in a text editor in order to view all the code that it executes behind the scenes. However, make sure you don’t open the file in a text editor with root privileges, to ensure that you don’t accidentally save changes to the file and break the script. The following command will open adduser in a text editor on an Ubuntu Server system:

nano /usr/sbin/adduser

Use your up/down arrows as well as the Page Up and Page Down keys to scroll through the file. When you’re finished, press Ctrl + x on your keyboard to exit the text editor. If the editor prompts you to save changes, don’t do so. Anyway, those of you with keen eyes will likely notice that the adduser script is calling useradd to perform its actual work. So either way, you’re either directly or indirectly using useradd.

Now that we know how to create users, it will be useful to understand how to remove them as well.

Removing users

Removing or disabling an account is very important when a user no longer needs to access a system, as unmanaged accounts often become a security risk. To remove a user account, we’ll use the userdel command.

Before removing an account, though, there is one very important question you should ask yourself. Will you (or another person) need access to the user’s files? Most companies have retention policies in place that detail what should happen to a user’s data when they leave the organization. Sometimes, these files are copied into an archive for long-term storage. Often, a manager, coworker, or new hire will need access to the former user’s files, perhaps to continue working on a project where they left off. It’s important to understand this policy ahead of managing users. If you don’t have a policy in place that outlines retention requirements for files when users resign, you should probably work with your management team and create one.

By default, the userdel command does not remove the contents of the user’s home directory. Here, we use the following command to remove dscully from the system:

sudo userdel dscully

We can see that the files for the dscully user still exist by entering the following command:

ls -l /home

The preceding commands will result in the following outputs:

Figure 2.4: The home directory for the user dscully still exists, even though we removed the user

With the /home directory for dscully still existing, we’re able to move the contents of this directory anywhere we would like to. If we had a directory called /store/file_archive, for example, we could easily move the files there:

sudo mv /home/dscully /store/file_archive

Of course, it’s up to you to create the directory where your long-term storage will ultimately be, but you get the idea.

If you weren’t already aware, you can create a new directory with the mkdir command. You can create a directory within any other directory that your logged-in user has access to. The following command will create the file_archive directory I mentioned in the preceding example:

sudo mkdir -p /store/file_archive

The -p flag simply creates the parent directory if it didn’t already exist.

If you do actually want to remove a user’s home directory at the same time that you remove an account, just add the -r option. This will eliminate the user and their data in one shot:

sudo userdel -r dscully

To remove the /home directory for the user after the account was already removed (if you didn’t use the -r parameter the first time), use the rm -r command to get rid of it, as you would any other directory:

sudo rm -r /home/dscully

It probably goes without saying, but the rm command can be extremely dangerous. If you’re logged in as root or using sudo while using rm, you can easily destroy your entire installed system if you’re not careful. DO NOT run this command, but as a hypothetical example, the following command (while seemingly innocent at first glance) will likely completely destroy your entire filesystem:

sudo rm -r / home/dscully

Notice the typo: I accidentally typed a space after the first forward slash. I literally accidentally told my system to remove the contents of the entire filesystem. If that command were executed, the server probably wouldn’t even boot the next time we attempted to start it. All user and program data would be wiped out. If there was ever any single reason for us to be protective over the root account, the rm command is most certainly it!

At this point, we understand how to add and remove users. In the next section, we’ll look deeper into passwords.

Understanding the /etc/passwd and /etc/shadow files

Now that we know how to create (and delete) user accounts on our server, we are well on our way to being able to manage our users. But where exactly is this information stored? We know that users store their personal files in /home, but is there some kind of database somewhere that keeps track of which user accounts are on our system? Actually, user account information is stored in two special text files:

  • /etc/passwd
  • /etc/shadow

You can display the contents of each of those two files with the following commands. Note that any user can look at the contents of /etc/passwd, while only root has access to /etc/shadow:

cat /etc/passwd 
sudo cat /etc/shadow

Go ahead and take a look at these two files (just don’t make any changes), and I will help you understand them.

Understanding the /etc/passwd file

First, let’s go over the /etc/passwd file. What follows is some example output from this file on my test server. For brevity, I have limited the output to the last eight lines:

Figure 2.5: Example /etc/passwd file

Each line within this file corresponds to a user account on the system. Entries are split into columns, separated by a colon (:). The username is in the first column, so you can see that I’ve created users jay and jdoe. The next column on each is simply an x. I’ll go over what that means a bit later. For now, let’s skip to the third and fourth columns, which reference the UID and GID respectively.

On a Linux system, user accounts and groups are actually referenced by their IDs. While it’s easier for you and I to manage users by their names, usernames and group names are nothing more than a label placed on the UID and GID in order to help us identify them more easily.

For example, it may be frustrating to try to remember that jdoe is UID 1001 on our server each time we want to manage this account. Managing it by referring to the account as jdoe is easier for humans, since we don’t remember numbers as well as we do names. But to Linux, each time we reference user jdoe, we’re actually just referencing UID 1001. When a user is created, the system (by default) automatically assigns the next available UID to the account. If you manage multiple Ubuntu servers, note that the UIDs will not match from one system to another, so keep in mind that UIDs don’t synchronize between installations.

In my case (as shown in Figure 2.5), the UID of each user is the same as their GID. This is just a coincidence on my system and it isn’t always that way in practice. While I’ll discuss creating groups later in this chapter, understand that creating groups works in a similar way to creating users, in the sense that the group is assigned the next available GID in much the same way as new user accounts are assigned the next available UID. When you create a user, the user’s primary group is the same as their username (unless you request otherwise). For example, when I created jdoe, the system also automatically created a jdoe group as well.

This is what you’re actually seeing here—the UID for the user, as well as the GID for the user’s primary group. Again, we’ll get to groups in more detail later.

You probably also noticed that the /etc/passwd file on your system contains entries for many more users than the ones we’ve created ourselves. This is perfectly normal, as Linux uses user accounts for various processes and services that run in the background. You’ll likely never interact with the default accounts at all, though you may someday create your own system user for a process to run as. For example, perhaps you’ll create a data processor account for an automated data-processing script to run under.

Anyway, back to our /etc/passwd file. The fifth column is designated for user info, most commonly the user’s first and last names. In my example, the fifth field is blank for jdoe, as I created jdoe with the useradd command, which didn’t prompt me for the first and last names. This field is also nicknamed the GECOS field, and you may see it referred to as such when you read the documentation.

In the sixth column, the home directory for each user is shown. In the case of jdoe, it’s set as /home/jdoe. Finally, we designate the user’s shell as /bin/bash. This field refers to the default shell the user will use, which defaults to /bin/bash when an account is created with the adduser command, and /bin/sh when created with the useradd command. (If you have no preference, /bin/bash is the best choice for most.) If we want the user to use a different shell, we can clarify that here (though shells other than /bin/bash aren’t covered in this book). If we wanted, we could change the user’s shell to something invalid to prevent them from logging in at all. This is useful for when a security issue requires us to disable an account quickly.

Understanding the /etc/shadow file

With that out of the way, let’s take a look at the /etc/shadow file. We can use cat to display the contents like any other text file, but unlike /etc/passwd, we need root privileges in order to view it. So, go ahead and display the contents of this file, and I’ll walk you through it:

sudo cat /etc/shadow

This will display the following output:

Figure 2.6: Example /etc/shadow file

The preceding screenshot, Figure 2.6, shows the last four lines of this file on my server. First, we have the username in the first column—no surprises there. Note that the output is not showing the UID for each user in this file. The system knows which username matches which UID based on the /etc/passwd file, so there’s no need to repeat that here. In the second column, we have what appears to be gobbledygook. Actually, that’s the most important part of this entire file. That’s the actual hash for the user’s password.

A password hash is a conversion of the actual password to a different string that represents the original password. This is a one-way conversion, so you cannot find the actual password by reverse-engineering the hash. In the /etc/passwd file, the hash of the password is stored rather than the actual password, for security purposes.

If you recall, in the /etc/passwd file, each user listing had an x for the second column, and I mentioned I would explain that later. What the x refers to is the fact that the user’s password is encrypted and simply not stored in /etc/passwd and is instead stored in /etc/shadow. After all, the /etc/passwd file is viewable by everyone, so it would compromise security quite a bit if anyone could just open up the file and see what everyone’s passwords were.

In the days of old, you could actually store a user’s password in /etc/passwd, but it’s never done that way anymore. Whenever you create a user account on a modern Linux system, the user’s password is encrypted (an x is placed in the second column of /etc/passwd for the user), and the actual password hash is stored in the second column of /etc/shadow to keep it away from prying eyes. Hopefully, now the relationship between these two files has become apparent.

Remember earlier I mentioned that the root user account is locked out by default? Well, let’s actually see that in action. Execute the following command to see the root user account entry in /etc/shadow:

sudo cat /etc/shadow | grep root

On my system, I get the following output:

Figure 2.7: Example /etc/shadow file

You should notice right away that the root user account doesn’t have a password hash at all. Instead, there’s an asterisk where the password hash would’ve been. In practice, placing an asterisk or exclamation point here is one way to lock an account. Even easier, you can use the passwd -l command against an account to lock it without having to edit a file. But either way, we can still switch to the root account anytime (which I’ll show you how to do later on in this chapter). Entering an asterisk or exclamation mark in the second field creates the restriction that we can’t directly log in as that user from the shell or over the network. We have to log in to the system as a normal user account first, and then we can still switch to that user if we want to.

With the discussion of password hashes out of the way, there are a few more fields within /etc/shadow entries that we should probably understand. Here’s a contrived example line:


Continuing on with the third column, we can see the number of days since the Unix epoch that the password was last changed. For those that don’t know, the Unix epoch is January 1, 1970. Therefore, we can read that column as the password having last been changed 16,809 days after the Unix epoch.

Personally, I like to use the following command to show more easily when the password was last changed:

sudo passwd -S <username>

This will result in an output that looks something like the following:

Figure 2.8: Checking the date of the last password change for a user

By executing this command, you can view information about any account on your system. The first column is obviously the username. The second has to do with the status of the password, which in this case is L, which refers to the fact that the user has a password that is locked. It would show P if the password was set and usable, or NP if the user didn’t have a password at all.

The third column of this command’s output gives you the actual date of the last password change for the user. The fourth column tells us how many days are required to pass before the user will be able to change their password again. In this example, jdoe can change the password any time because the minimum number of days is set to 0. We’ll talk about how to set the minimum number of days later on in this chapter, but I’ll give you a brief explanation of what this refers to. At first, it may seem silly to require a user to wait a certain number of days to be able to change their password. However, never underestimate the ability of your users to be oppositional. It’s quite common for a user, when required to change their password, to change their password to satisfy history requirements, only to then just change it back to what it was originally. By setting a minimum number of days, you’re forcing a waiting period in between password changes, making it less convenient for your users to cycle back through to their original password.

The fifth column, as you can probably guess, is the maximum number of days that can pass between password changes. If you require your users to change their passwords every certain number of days, you’ll see that in this column. By default, this is set to 99999 days. That number of days is way beyond the human lifespan, so it may as well be infinite.

Continuing with the sixth column, we have the number of days that will elapse before the expiration date on which the user is warned that they will soon be required to change their password. In the seventh column, we set how many days can pass after the password expires, in which case the account will be disabled. With our example user, this is not set. Finally, with the eighth column (which is not visible), we can see the number of days since the Unix epoch that will elapse before the account is disabled (in our case, there’s nothing here, so there is no disabled day set).

We’ll go over setting these fields later, but for now, hopefully you understand the contents of the /etc/shadow file better.

If at any time you’d like additional clarification, feel free to check out the Ubuntu man pages. A man page (short for manual page) can give you quite a bit more information about commands as well as files. For example, the following command shows you the man page for the ls command:

man ls

More specific to this section, you can retrieve man pages for the /etc/shadow files as well:

man passwd
man shadow

Press q on your keyboard to exit out of a man page. Feel free to check out the man pages for any command in this book to learn more as you go along.

Now that we fully understand how to manage our users, we can also look at how to provide them with default files in their home directory.

Distributing default configuration files with /etc/skel

In a typical organization, there are usually some defaults that are recommended for users in terms of files and configuration.

For example, in a company that performs software development, there are likely recommended settings for text editors and version control systems. Files that are contained within /etc/skel are copied into the home directory for all new users when you create them (assuming you’ve chosen to create a home directory while setting up the user).

In fact, you can see this for yourself right now. Execute the following command:

ls -la /etc/skel

Now, you should be able to view the contents of the /etc/skel directory:

Figure 2.9: Default /etc/skel files

You probably already know how to list files within a directory, but I added the -a option because I wanted to view hidden files as well. The files included in /etc/skel by default are hidden (their filenames begin with a period). I threw in the -l parameter solely because it shows a long list, which I think is easier to read.

Each time you create a new user and request a home directory to be created as well, these three files, shown in Figure 2.9, will be copied into their home directory, along with any other files you create here. You can verify this by listing the storage of the home directories for the users you’ve created so far. The .bashrc file in one user’s home directory should be the same as any other, unless they’ve made changes to it.

Armed with this knowledge, it should be extremely easy to create default files for new users that you create. For example, you could create a file named welcome with your favorite text editor and place it in /etc/skel. Perhaps you may create this file to contain helpful phone numbers and information for new hires in your company. The file would then be automatically copied to the new user’s home directory when you create the account. The user, after logging in, would see this file in their home directory and see the information. More practically, if your company has specific editor settings that are favored for writing code, you can include those files in /etc/skel as well to help ensure your users are compliant. In fact, you can include default configuration files for any application your company uses.

Go ahead and give it a try. Feel free to create some random text files and then create a new user afterward, and you’ll see that these files will propagate into the home directories of the new user accounts that you add to your system.

Now that we have multiple users and have also seen how to manage their default files, we can take a look at how to switch from one user to another.

Switching users

Now that we have several users on our system, we need to know how to switch between them. Of course, you can always just log in to the server as one of the users, but you can actually switch to any user account at any time, provided you either know that user’s password or have sudo access.

The command you will use to switch from one user to another is the su command. If you enter su with no options, it will assume that you want to switch to root and will ask you for the root password. As I mentioned earlier, Ubuntu locks the root account by default, so at this point you may not have a root password.

Even though Ubuntu doesn’t create a password for root by default, some Virtual Private Server (VPS) providers unlock the root password and actually have you log in as the root user. Having an unlocked root account is not a standard Ubuntu practice, and is a customization specific to some cloud providers.

Unlocking the root account is actually really simple; all you have to do is create a root password. To do that, you can execute the following command as any user with sudo access:

sudo passwd

The command will ask you to create and confirm your root password. From this point on, you will be able to use the root account as any other account. You can log in as root or switch to root—it’s fully available now. However, you really don’t have to unlock the root account in order to use it. You certainly can, but there are ways to switch to root without unlocking it, and it’s typically better to leave the root account locked unless you have a very specific reason to unlock it. The following command will allow you to switch to root from a user account that has sudo access:

sudo su - 

Now you’ll be logged in as root and will be able to execute any command you want with no restrictions whatsoever. To return to your previously logged-in account, simply type exit. You can tell which user you’re logged in as by the value at the beginning of your bash prompt.

What if you want to switch to an account other than root? Of course, you can simply log out and then log in as that user. But you really don’t have to do that. The following command will do the job, providing you know the password for the account:

su - <username>

The shell will ask for that user’s password and then you’ll be logged in as that user. Again, type exit when you’re done using the account, which will return you to the one you were using before you switched.

That command is all well and good if you know the user’s password, but you often won’t. Typically, in an enterprise, you’ll create an account, force the user to change their password at first login, and then you will no longer know that user’s password.

Since you have root and sudo access, you could always change their password and then log in as them. But they’ll know something is amiss if their password suddenly stops working—you’re not eavesdropping, are you? Armed with sudo access, you can use sudo to change to any user you want to, even if you don’t know their password. Just prefix our previous command with sudo and you’ll only need to enter the password for your user account, instead of theirs:

sudo su - <username>

Switching to another user account is often very helpful for support (especially while troubleshooting permissions). As an example, say that a user comes to you complaining that they cannot access the contents of a specific directory, or they are unable to run a command. In that case, you can log in to the server, switch to their user account, and try to reproduce their problem. That way, you can not only see their problem yourself, but you can also test out whether or not your fix has solved their issue before you report back to them.

Now we have a full understanding of user accounts, and even how to switch between them. In the next section, we’ll look into groups, which allow us to categorize our users.

Managing groups

Now that we understand how to create, manage, and switch between user accounts, we’ll need to understand how to manage groups as well. The concept of groups in Linux is not very different from other platforms and pretty much serves the exact same purpose. With groups, you can more efficiently control a user’s access to resources on your server. By assigning a group to a resource (a file, a directory, and so on), you can allow and disallow access to users by simply adding them or removing them from the group.

The way this works in Linux is that every file or directory has both a user and a group that takes ownership of it. This is contrary to platforms such as Windows, which can have multiple groups assigned to a single resource. With Linux, it’s just one-to-one ownership: just one user and just one group assigned to each file or directory. If you list the contents of a directory on a Linux system, you can see this for yourself:

ls -l 

The following is a sample line of output from a directory on one of my servers:

-rw-r--r-- 1 root bind  490 2022-04-15 22:05 named.conf 

In this case, we can see that root owns the file and that the group bind is also assigned to it. Ignore the other fields for now; I’ll explain them later when we get to the section of this chapter dedicated to permissions. For now, just keep in mind that one user and one group are assigned to each file or directory.

While each file or directory can only have one group assignment, any user account can be a member of any number of groups. Entering the groups command by itself with no options will tell you what groups your logged-in user is currently a member of. If you add a username to the groups command, you’ll see which groups that user is a member of. Go ahead and give the groups command a try with and without providing a username to get the idea.

On the Ubuntu Server platform, you’ll likely see that each of your user accounts is a member of a group that’s named the same as your username. As I mentioned earlier, when you create a user account, you’re also creating a group with the same name as the user. On some Linux distributions, though, a user’s primary group will default to a group called users instead. If you were to execute the groups command as a user on the Ubuntu desktop platform, you would likely see additional groups. This is due to the fact that distributions of Linux that cater to being a server platform are often more stripped down and users on desktop platforms need access to more objects such as printers, audio cards, and so on. Some packages that can be installed also add additional system users to the server.

If you were curious as to which groups exist on your server, all you would need to do is cat the contents of the /etc/group file. Similar to the /etc/passwd file we covered earlier, the /etc/group file contains information regarding the groups that have been created on your system. Go ahead and take a look at this file on your system:

cat /etc/group 

The following is sample output from this file on one of my servers:

Figure 2.10: Sample output from the /etc/group file

Like before, the columns in this file are separated by colons, though each line is only four columns long. In the first column, we have the name of the group. No surprise there. In the second, we are able to store a password for the group, but this is not used often as it’s actually a security risk to do so. In the third column, we have the GID, which is similar in concept to the UID from when we were discussing users. Finally, in the last column, we (would) see a comma-separated list of each user that is a member of each of the groups.

Several entries don’t show any group memberships at all. Each user is indeed a member of their own group, so this is implied even though it doesn’t explicitly call that out in this file. If you take a look at the /etc/passwd entries for your users, you will see that their primary group (shown as the third column in the form of a GID) references a group contained in the /etc/group file.

Creating new groups on your system is easy to do and is a great idea for categorizing your users and what they are able to do. Perhaps you create an accounting group for your accountants, an admins group for those in your IT department, and a sales group for your salespeople. The groupadd command allows you to create new groups.

If you wanted to, you could just edit the /etc/group file and add a new line with your group information manually, although, in my opinion, using groupadd saves you some work and ensures that group entries are created properly. Editing group and user files directly is typically frowned upon (and a typo can cause serious problems). Anyway, what follows is an example of creating a new group with the groupadd command:

sudo groupadd admins

If you take a look at the /etc/group file again after adding a new group, you’ll see that a new line was created in the file and a GID was chosen for you (the first one that hadn’t been used yet). Removing a group is just as easy. Just issue the groupdel command followed by the name of the group you wish to remove:

sudo groupdel admins

Next, we’ll take a look at the usermod command, which will allow you to actually associate users with groups. The usermod command is more or less a Swiss Army knife; there are several things you can do with that command (adding a user to a group is just one of its abilities). If we wanted to add a user to our admins group, we would issue the following command:

sudo usermod -aG admins myuser

In that example, we’re supplying the -a option, which means append, and immediately following that, we’re using -G, which means we would like to modify secondary group membership. I put the two options together with a single dash (-aG), but you could also issue them separately (-a -G). The example I gave only adds the user to additional groups; it doesn’t replace their primary group.

Be careful not to miss the -a option here, as by doing so, you will instead replace all current group memberships with the new one, which is usually not what you want. The -a option means append, or to add the existing list of group memberships for that user.

If you wanted to change a user’s primary group, you would use the -g option instead (lowercase g instead of an uppercase G as we used earlier):

sudo usermod -g <group-name> <username>

Feel free to check out the man pages for the usermod command, to see all the nifty things it allows you to manage relating to your users. You can peruse the man page for the usermod command with the following command:

man usermod

One additional example is changing a user’s /home directory. Suppose that one of your users has undergone a name change, so you’d like to change their username, as well as moving their previous home directory (and their files) to a new one. The following commands will take care of that:

sudo usermod -d /home/jsmith jdoe -m 
sudo usermod -l jsmith jdoe 

In that example, we’re moving the home directory for jdoe to /home/jsmith, and then in the second example, we’re changing the username from jdoe to jsmith.

If you wish to remove a user from a group, you can use the gpasswd command to do so. gpasswd -d will do the trick:

sudo gpasswd -d <username> <grouptoremove> 

In fact, gpasswd can also be used in place of usermod to add a user to a group:

sudo gpasswd -a <username> <group> 

So, now you know how to manage groups. With the efficient management of groups, you’ll be able to manage the resources on your server better. Of course, groups are relatively useless without some explanation of how to manage permissions (otherwise, nothing would actually allow a member of a group access to a resource). Later on in this chapter, we’ll cover permissions so that you have a complete understanding of how to manage user access.

Managing passwords and password policies

In this chapter, we’ve already covered a bit of password management, since I’ve given you a few examples of the passwd command. If you recall, the passwd command allows us to change the password of the currently logged-in user. In addition, using passwd as root (and supplying a username) allows us to change the password for any user account on our system. But that’s not all this command can do.

Locking and unlocking user accounts

One thing I’ve neglected to mention regarding the passwd command is the fact that you can use it to lock and unlock a user’s account. There are many reasons why you may want to do this. For instance, if a user is going on vacation or extended leave, perhaps you’d want to lock their account so that it cannot be used while they are away. After all, the fewer active accounts, the smaller your attack surface. To lock an account, use the -l option:

sudo passwd -l <username>

And to unlock it, use the -u option:

sudo passwd -u <username>

However, locking an account will not prevent the user from logging in if they have access to the server via SSH while utilizing public key authentication. In that case, you’d want to remove their ability to use SSH as well. One common way of doing this is to limit SSH access to users who are members of a specific group. When you lock an account, simply remove them from the group. Don’t worry so much about the SSH portion of this discussion if this is new to you. We will discuss securing your SSH server in Chapter 21, Securing Your Server. For now, just keep in mind that you can use passwd to lock or unlock accounts, and if you utilize SSH, you’ll want to lock your users out of that to prevent them from logging in.

However, there’s more to password management than the passwd command, as we can also implement our own policies, such as viewing or adjusting password expiration details.

Setting password expiration information

Earlier, I mentioned that you can set an expiration date on a user’s password (during our discussion on the /etc/shadow file). In this section, we’ll go through how to actually do that. Specifically, the chage command gives us this ability. We can use chage to alter the expiration period of a user’s password, but it’s also a more convenient way of viewing current expiration information than viewing the /etc/shadow file. With the -l option of chage, along with providing a username, we can see the relevant info:

sudo chage -l <username>

Using sudo or root is not required to run chage. You’re able to view expiration information for your own username without needing to escalate permissions. However, if you want to view information via chage for any user account other than your own, you will need to use sudo.

In the example that follows, we can see the output of this command from a sample user account:

Figure 2.11: Output from the chage command

In the output, we can see values for the date of expiration, the maximum number of days between password changes, and so on. Basically, it’s the same information stored in /etc/shadow but it’s much easier to read.

If you would like to change this information, chage will again be the tool of choice. The first example I’ll provide is a very common one. When creating user accounts, you’ll certainly want them to change their password when they first log in.

Unfortunately, not everyone will be keen on doing so. The chage command allows you to force a password change for a user when they first log in. Basically, you can set their number of days to expiry to 0 as follows:

sudo chage -d 0 <username>

You can see the results of this command immediately if you run chage -l again against the user account you just modified:

sudo chage -l <username>

The output will display information regarding the password change:

Figure 2.12: The chage command listing a user that has a required password change period set

To set a user account to require a password change after a certain period of days, the following will do the trick:

sudo chage -M 90 <username> 

In that example, I’m setting the user account to expire and require a password change in 90 days. When the impending date reaches 7 days before the password is to be changed, the user will see a warning message when they log in.

As I mentioned earlier, users will often do whatever they can to cheat password requirements and may try to change their password back to what it was originally after satisfying the initially required password change. You can set the minimum number of days with the -m flag, as you can see in the next example where we set it to 5 days:

sudo chage -m 5 dscully

The trick with setting a minimum password age is to set it so that it will be inconvenient for the user to change their password to the original one, but you still want a user to be able to change their password when they feel the need to (so don’t set it too long, either). If a user wants to change their password before the minimum number of days elapses (for example, if your user feels that their account may have been compromised), they can always have you change it for them. However, if you make your password requirements too much of an inconvenience for your users, it can also work against you.

Setting a password policy

Next, we should discuss setting a password policy. After all, forcing your users to change their passwords does little good if they change it to something simple, such as abc123. A password policy allows you to force requirements on your users for things such as length, complexity, and so on.

To facilitate this, we have Pluggable Authentication Module (PAM) at our disposal. PAM gives us additional functionality and control over the process of authentication, and also provides additional plugins we can use to extend authentication and add additional features. Although a full walkthrough of PAM isn’t covered in this book, I recommend keeping it fresh in your mind in case you want to add additional features later.

Specific to the subject of setting up a password policy, we can install a PAM module to enable this, which involves installing a new package:

sudo apt install libpam-cracklib

Next, let’s take a look at the following file, which is provided with Ubuntu. Feel free to open it with a text editor, such as nano, as we’ll need to edit it:

sudo nano /etc/pam.d/common-password

An extremely important tip while modifying configuration files related to authentication (such as password requirements, sudo access, SSH, and so on) is to always keep a root shell open at all times while you make changes, and in another shell, test those changes. Do not log out of your initial root window until you are 100% certain that your changes have been thoroughly tested. While testing a policy, make sure that not only can your users log in, but your admins too. Otherwise, you may remove your ability to log in to a server and make changes.

To enable a history requirement for your passwords (meaning the system remembers the last several passwords a user has used, preventing them from reusing them), we can add the following line to the file:

password   required remember=99 use_authok

In the example config line, I’m using remember=99, which (as you can probably guess) will cause our system to remember the last 99 passwords for each user and prevent them from using those passwords again. If you’ve configured a minimum password age earlier, for example, 5 days, it would take the user 495 days to cycle back to their original password if you take into account that the user changes their password once every 5 days, 99 times. That pretty much makes it impossible for the user to utilize their old passwords.

Another field worth mentioning within the /etc/pam.d/common-password file is the section that reads difok=3. This configuration mandates that at least three characters have to be different before the password is considered acceptable. Otherwise, the password would be deemed too similar to the old one and refused. You can change this value to whatever you like; the default is normally 5 but Ubuntu defaults it to 3 in their implementation of this config file. In addition, you’ll also see obscure mentioned in the file as well, which prevents simple passwords from being used (such as common dictionary words and so on).

Setting a password policy is a great practice to increase the security of your server. However, it’s also important to not get carried away. In order to strike a balance between security and user frustration, the challenge is always to create enough restrictions to increase your security, while trying to minimize the frustration of your users. Of course, the mere mention of the word “password” to a typical user is enough to frustrate them, so you can’t please everyone. But in terms of overall system security, I’m sure your users will appreciate the fact that they can be reasonably sure that you as an administrator have taken the necessary precautions to keep their (and your company’s) data safe. When it comes down to it, use your best judgment.

Since we’re on the subject of security, we should also take a look at configuring sudo itself, which we’ll take care of in the next section.

Configuring administrator access with sudo

By now, we’ve already used sudo quite a few times in this book. At this point, you should already be aware of the fact that sudo allows you to execute commands as if you were logged in as another user, with root being the default. However, we haven’t had any formal discussion about it yet, nor have we discussed how to actually modify which of your user accounts are able to utilize sudo.

On all Linux systems, you should protect your root account with a strong password and limit it to being used by as few people as possible. On Ubuntu, the root account is locked anyway, so unless you unlocked it by setting a password (or you’re using a version of Ubuntu supplied by a VPS provider), it cannot be used to log in to the system. Using sudo is an alternative to logging in as root to execute commands directly, so you can give your administrators access to perform tasks that require root privileges with sudo without actually giving them your root password or unlocking the root account. In fact, sudo allows you to be a bit more granular. Using root directly is basically all or nothing—if someone knows the root password and the root account is enabled, that person is not limited and can do whatever they want. With sudo, that can also be true, but you can actually restrict some users to use only particular commands and therefore limit the scope of what they are able to do on the system. For example, you could give an admin access to install software updates but not allow them to reboot the server.

By default, members of the sudo group are able to use sudo without any restrictions. Basically, members of this group can do anything root can do (which is everything). During installation, the user account you created was made a member of sudo. To give additional users access to sudo, all you would need to do is add them to the sudo group:

sudo usermod -aG sudo <username>

Not all distributions utilize the sudo group by default, or even automatically install sudo. Other distributions require you to install sudo manually and may use another group (such as wheel) to govern access to sudo.

But again, that gives those users access to everything, and that may or may not be what you want. To actually configure sudo, we use the visudo command. This command assists you with editing /etc/sudoers, which is the configuration file that governs sudo access. Although you can edit /etc/sudoers yourself with a text editor, configuring sudo in that way is strongly discouraged. The visudo command checks to make sure your changes follow the correct syntax and helps prevent you from accidentally destroying the file. This is a very good approach, because if you did make any errors in the /etc/sudoers file, you may wind up in a situation where no one is able to gain administrative control over the server. And while there are ways to recover from such a mistake, it’s certainly not a very pleasant situation to find yourself in! So, the takeaway here is never to edit the /etc/sudoers file directly; always use visudo to do so.

Here’s an example of the type of warning the visudo command shows when you make a mistake:

Figure 2.13: The visudo command showing an error

If you do see this error, press e to return to edit the file, and then correct the mistake.

The way this works is when you run visudo from your shell, you are brought into a text editor with the /etc/sudoers file opened up. You can then make changes to the file and save it like you would any other text file. By default, Ubuntu opens up the nano text editor when you use visudo. With nano, you can save changes using Ctrl + w, and you can exit the text editor with Ctrl + x.

So visudo allows you to make changes to who is able to access sudo. But how do you actually make these changes? Go ahead and scroll through the /etc/sudoers file that visudo opens and you should see a line similar to the following:

%sudo   ALL=(ALL:ALL) ALL 

This is the line of configuration that enables sudo access to anyone who is a member of the sudo group. You can change the group name to any that you’d like, for example, perhaps you’d like to create a group called admins instead. If you do change this, make sure that you actually create that group and add yourself and your staff to be members of it before you edit the /etc/sudoers file or log off; it would be rather embarrassing if you found yourself locked out of administrator access to the server.

Of course, you don’t have to enable access by group. You can actually call out a username instead. With the /etc/sudoers file, groups are preceded by %, while users are not. As an example of this, we also have the following line in the file:

root    ALL=(ALL:ALL) ALL 

Here, we’re calling out a username (in this case, root), but the rest of the line is the same as the one I pointed out before. While you can certainly copy this line and paste it one or more times (substituting root for a different username) to grant access to others, using the group approach is really the best way. It’s easier to add and remove users from a group (such as the sudo group) than it is to use visudo each time.

So, at this point, you’re probably wondering what the options on /etc/sudoers configuration lines actually mean. So far, both examples used ALL=(ALL:ALL) All. In order to fully understand sudo, understanding the other fields is extremely important, so let’s go through them (using the root line again as an example).

The first ALL means that root is able to use sudo from any terminal. The second ALL means that root can use sudo to impersonate any other user. The third ALL means that root can impersonate any other group. Finally, the last ALL refers to what commands this user is able to use; in this case, any command they wish.

To help drive this home, I’ll give some additional examples. Here’s a hypothetical example:

charlie    ALL=(ALL:ALL) /sbin/reboot,/sbin/shutdown 

Here, we’re allowing user charlie to execute the reboot and shutdown commands. If user charlie tries to do something else (such as install a package), they will receive an error message:

Sorry, user charlie is not allowed to execute '/usr/bin/apt install tmux' as root on ubuntu. 

However, if charlie wants to use the reboot or shutdown commands on the server, they will be able to do so because we explicitly called out those commands while setting up this user’s sudo access. We can limit this further by changing the first ALL to a machine name, in this case, ubuntu, to reference the host name of the server I’m using for my examples. I’ve also changed the command that charlie is allowed to run:

charlie    ubuntu=(ALL:ALL) /usr/bin/apt 

It’s always a good idea to use full paths to commands when editing sudo permissions, rather than the shortened versions. For example, we used /usr/bin/apt here, instead of just apt. This is important, as the user could create a script named apt to do mischievous things that we normally wouldn’t allow them to do. By using the full path, we’re limiting the user to the binary stored at that path.

Now, charlie is only able to use apt. They can use apt update, apt dist-upgrade, and any other sub-command of apt. But if they try to reboot the server, remove protected files, add users, or anything else we haven’t explicitly set, they will be prevented from doing so.

We have another problem, though. We’re allowing charlie to impersonate other users. This may not be completely terrible given the context of installing packages (impersonating another user would be useless unless that user also has access to install packages), but it’s bad form to allow this unless we really need to. In this case, we could just remove the (ALL:ALL) from the line altogether to prevent charlie from using the -u option of sudo to run commands as other users:

charlie    ubuntu= /usr/bin/apt

On the other hand, if we actually do want charlie to be able to impersonate other users (but only specific users), we can call out the username and group that charlie is allowed to act on behalf of by setting those values:

charlie    ubuntu=(dscully:admins) ALL

In that example, charlie is able to run commands on behalf of the user dscully and the group admins.

Of course, there is much more to sudo than what I’ve mentioned in this section. Entire books could be written about sudo (and have been), but 99% of what you will need for your daily management of this tool involves how to add access to users while being specific about what each user is able to do. As a best practice, use groups when you can (for example, you could have an apt group, a reboot group, and so on) and be as specific as you can regarding who is able to do what. This way, you’re not only able to keep the root account private (or even better, disabled), but you also have more accountability on your servers.

Now that we’ve explored granting access to sudo, we will next take a look at permissions, which give us even more control over what our users are able to access.

Setting permissions on files and directories

In this section, all the user management we’ve done in this chapter so far all comes together. We’ve learned how to add accounts, manage accounts, and secure them, but we haven’t actually done any work regarding managing the resources as far as who is able to access them. In this section, I’ll give you a brief overview of how permissions work in Ubuntu Server and then I’ll provide some examples for customizing them.

Viewing permissions

I’m sure by now that you understand how to list the contents of a directory with the ls command. When it comes to viewing permissions, the -l flag is especially handy, as the output that the long listing provides allows us to view the permissions of an object:

ls -l

The following are some example, hypothetical file listings:

-rw-rw-rw- 1 doctor   5        Jan 11   12:52 welcome 
-rw-r--r-- 1 root     root   665      Feb 19   profile 
-rwxr-xr-x 1 dalek   dalek   35125    Nov  7   exterminate 

In each line, we see several fields of information. The first column is our permission string for the object (for example, -rw-r—r--), which we’ll cover in more detail shortly. We also see the link count for the object (second column). Links are beyond the scope of this chapter but will be discussed in Chapter 5, Managing Files and Directories. Continuing on, the user that owns the file is displayed in the third column, the group that owns the file is in the fourth column, the size in bytes is in the fifth, the last date the file was modified is in the sixth, and finally there is the name of the file.

Keep in mind that depending on how your shell is configured, your output may look different and the fields may be in different places. For the sake of our discussion on permissions, what we’re really concerned with is the permissions string, as well as the owning user and group. In this case, we can see that the first file (named welcome) is owned by a user named doctor. The second file is named profile and is owned by root. Finally, we have a file named exterminate owned by a user named dalek.

With these files, we have the permission strings of -rw-rw-rw-, -rw-r--r--, and -rwxr-xr-x respectively. If you haven’t worked with permissions before, these may seem strange, but it’s actually quite easy when you break them down. Each permission string can be broken down into four groups, as I’ll show you in the following table:

Object type
















I’ve broken down each of the three example permission strings into four groups. Basically, I split them each at the first character and then again every third. The first section of a permission string is just one character. In each of these examples, it’s just a single hyphen. This refers to what type the object is. Is it a directory? A file? A link? In our case, each of these permission strings is a file, because the first positions of the permission strings are all hyphens. If the object were a directory, the first character would’ve been a d instead of a -. If the object were a link, this field would’ve been l (lowercase L) instead.

In the next section, in the second column of each object, we have three characters, rw-, rw-, and rwx respectively. This refers to the permissions that apply to the user that owns the file. For example, here is the first permission string again:

-rw-rw-rw- 1 doctor doctor    5 Jan 11 12:52 welcome

The third section of the preceding code output shows us that doctor is the user that owns the file. Therefore, referring back to the table, the second column of the permission string (rw-) applies specifically to the user doctor. Moving on, the third column of permissions is also three characters; in this case, rw- again. This section of the permissions string refers to the group that owns the file. In this case, the group is also named doctor, as you can see in column four of the preceding code output. Finally, the last section of the permission string, visualized in the table (rw- yet again, in this case), refers to world, also known as other. This basically refers to anyone else other than the owning user and owning group. Therefore, literally everyone else gets at least rw- permissions on the object.

Individually, r stands for read and w stands for write. Therefore, we can read the second column (rw-), indicating that the user (doctor) has access to read and write to this file. The third column (rw- again) tells us the doctor group also has read and write access to this file. The fourth column of the permission string is the same, so anyone else would also have read and write permissions to the file as well.

The third permission string I gave as an example looks a bit different. Here it is again:

-rwxr-xr-x 1 dalek dalek      35125 Nov  7  exterminate

Here, we see the x attribute set. The x attribute refers to the ability to execute the file as a script. So, with that in mind, we know that this file is likely a script and is executable by users, groups, and others. Given the filename of exterminate, this is rather suspicious, and if it were a real file, we’d probably want to look into it.

If a permission is not set, it will simply be a single hyphen where there would normally be r, w, or x. This is the same as indicating that a permission is disabled. Here are some examples:

  • rwx: Object has read, write, and execute permissions set for this field
  • r-x: Object has read enabled, write disabled, and execute enabled for this field
  • r--: Object has read enabled, write disabled, and execute disabled for this field
  • ---: Object has no permissions enabled for this field

Bringing this discussion all the way home, here are a few more permission strings:

-rw-r--r-- 1   sue   accounting      35125  Nov  7  budget.txt 
drwxr-x--- 1   bob   sales           35125  Nov  7  annual_projects 

For the first of these examples, we see that sue is the owning user of budget.txt and that this file is assigned an accounting group. This object is readable and writable by sue and readable by everyone else (group and world). This is probably bad, considering this is a budget file and is probably confidential. We’ll change it later.

The annual_projects object is a directory, which we can tell from the d in the first column. This directory is owned by the bob user and the sales group. However, since this is a directory, each of the permission bits has different meanings. In the following two tables, I’ll outline the meanings of these bits for files and again for directories:

  • Files:




The file can be read


The file can be written to


The file can be executed as a program

  • Directories:




The contents of the directory can be viewed


The contents of the directory can be altered


The user or group can use cd to go inside the directory

As you can see, permissions are read differently depending on their context: whether they apply to a file or a directory. In the example of the annual_projects directory, bob has rwx permissions to the directory. This means that the user bob can do everything (view the contents, add or remove contents, and use cd to move the current directory of his shell into the directory). Regarding a group, members of the sales group are able to view the contents of this directory and cd into it. However, no one in the sales group can add or remove items to or from the directory. On this object, other has no permissions set at all. This means that no one else can do anything at all with this object, not even view its contents.

Changing permissions

So, now we understand how to read permissions on files and directories. That’s great, but how do we alter them? As I mentioned earlier, the budget.txt file is readable by everyone (other). This is not good because the file is confidential. To change permissions on an object, we will use the chmod command. This command allows us to alter the permissions of files and directories in a few different ways.

First, we can simply remove read access from the sue user’s budget file by removing the read bit from the other field. We can do that with the following example:

chmod o-r budget.txt

If we are currently not in the directory where the file resides, we need to give a full path:

chmod o-r /home/sue/budget.txt

If you’re using the chmod command against files other than those you own yourself, you’ll need to use sudo.

But either way, you probably get the idea. With this example, we’re removing the r bit from other (o-r). If we wanted to add this bit instead, we would simply use + instead of -. Here are some additional examples of chmod in action:

  • chmod u+rw <filename>: The object gets rw added to the user column
  • chmod g+r <filename>: The owning group is given read access
  • chmod o-rw <filename>: Other is stripped of the rw bits

In addition, you can also use octal point values to manage and modify permissions. This is actually the most common method of altering permissions. I like to think of this as a scoring system. That’s not what it is, but it makes it a lot easier to understand to think of each type of access as having its own value. Basically, each of the permission bits (r, w, and x) has its own octal equivalent, as follows:

  • Read: 4
  • Write: 2
  • Execute: 1

With this style, there are only a few possibilities for numbers you can achieve when combining these octal values (each can only be used once). Therefore, we can get 0, 1, 2, 3, 4, 5, 6, and 7 by adding (or not adding) these numbers in different combinations. Some of them you’ll almost never see, such as an object having write access but not read. For the most part, you’ll see 0, 4, 5, 6, and 7 used with chmod most often. For example, if we add Read and Write, we get 6. If we add Read and Execute, we get 5. If we add all three, we get 7. If we add no permissions, we get 0. We repeat this for each column (User, Group, and Other) to come up with a string of three numbers. Here are some examples:

  • 600: User has read and write (4+2). No other permissions are set.

    This is the same as -rw-------.

  • 740: User has read, write, and execute. Group has read. Other has nothing.

    This is the same as -rwxr-----.

  • 770: Both User and Group have full access (read, write, and execute). Other has nothing.

    This is the same as -rwxrwx---.

  • 777: Everyone has everything.

    This is the same as -rwxrwxrwx.

Going back to chmod, we can use this numbering system in practice:

  • chmod 600 filename.txt
  • chmod 740 filename.txt
  • chmod 770 filename.txt

Hopefully you get the idea. If you wanted to change the permissions of a directory, the -R option may be helpful to you. This makes the changes recursive, meaning that you’ll not only make the changes to the directory but also to all files and directories underneath it in one shot:

chmod 770 -R mydir

While using -R with chmod can save you some time, it can also cause trouble if you have a mix of directories and files underneath the directory you’re changing permissions on. The previous example gives permissions 770 to mydir and all of its contents. If there are files inside, they are now given executable permissions to the user and group, since 7 includes the execute bit (value of 1). This may not be what you want. We can use the find command to differentiate these. While find is out of the scope of this chapter, it should be relatively simple to see what the following commands are doing and how they may be useful:

find /path/to/dir/ -type f -exec chmod 644 {} \; 
find /path/to/dir/ -type d -exec chmod 755 {} \; 

Basically, in the first example, the find command is locating all files (-type f) in /path/to/dir/ and everything it finds, it executes chmod 644 against. The second example is locating all directories in this same path and changing them all to permission 755. The find command isn’t covered in detail here because it easily deserves a chapter of its own, but I’m including it here because hopefully these examples are useful and will be handy for you to include in your own list of useful commands.

Changing the ownership of objects

Finally, we’ll need to know how to change the ownership of files and directories. It’s often the case that a particular user needs to gain access to an object, or perhaps we need to change the owning group as well. We can change user and group ownership of a file or directory with the chown command. As an example, if we wanted to change the owner of a file to sue, we could do the following:

sudo chown sue myfile.txt

In the case of a directory, we can also use the -R flag to change the ownership of the directory itself, as well as all the files and directories it may contain:

sudo chown -R sue mydir 

If we would like to change the group assignment to the object, we would follow the following syntax:

sudo chown sue:sales myfile.txt 

Notice the colon separating the user and the group. With that command, we established that we would like the sue user and the sales group to own this resource. Again, we could use -R if the object were a directory and we wanted to make the changes recursive.

Another command worth knowing is the chgrp command, which allows you to directly change the group ownership of a file. To use it, you can execute the chgrp command along with the group you’d like to own the file, followed by the filename. For example, our previous chown command can be simplified to the following, since we were only modifying the group assignment of that file:

sudo chgrp sales myfile.txt

Just like the chown command, we can use the -R option with chgrp to make our changes recursively, in the case of a directory.

Well, there you have it. You should now be able to manage permissions of the files and directories on your server. If you haven’t worked through permissions on a Linux system before, it may take a few tries before you get the hang of it. The best thing for you to do is to practice. Create some files and directories (as well as users) and manage their permissions. Try to remove a user’s access to a resource and then try to access that resource as that user anyway and see what errors you get. Fix those errors and work through more examples. With practice, you should be able to get a handle on this very quickly.


In Linux administration and related fields, managing users and permissions is something you’ll find yourself doing quite a bit. New users will join your organization, while others will leave, so this is something that will become ingrained in your mental toolset. Even if you’re the only person using your servers, you’ll find yourself managing permissions for applications as well, given the fact that processes cannot function if they don’t have access to their required resources.

In this chapter, we took a lengthy dive into managing users, groups, and permissions. We worked through creating and removing users, assigning permissions, and managing administrative access with sudo. Practice these concepts on your server. When you get the hang of it, I’ll see you in our next chapter, where we’ll discuss all things related to package management. It’s going to be epic.

Relevant videos

Further reading

Join our community on Discord

Join our community’s Discord space for discussions with the author and other readers:

Left arrow icon Right arrow icon
Download code icon Download Code

Key benefits

  • Get well-versed with newly added features in Ubuntu 22.04
  • Master the art of installing, managing, and troubleshooting Ubuntu Server
  • Leverage the improved performance and security-related aspects of Ubuntu Server 22.04


Ubuntu Server is taking the server world by storm - and for a good reason! The server-focused spin of Ubuntu is a stable, flexible, and powerful enterprise-class distribution of Linux with a focus on running servers both small and large. Mastering Ubuntu Server is a book that will teach you everything you need to know in order to manage real Ubuntu-based servers in actual production deployments. This book will take you from initial installation to deploying production-ready solutions to empower your small office network, or even a full data center. You'll see examples of running an Ubuntu Server in the cloud, be walked through set up popular applications (such as Nextcloud), host your own websites, and deploy network resources such as DHCP, DNS, and others. You’ll also see how to containerize applications via LXD to maximize efficiency and learn how to build Kubernetes clusters. This new fourth edition updates the popular book to cover Ubuntu 22.04 LTS, which takes advantage of the latest in Linux-based technologies. By the end of this Ubuntu book, you will have gained all the knowledge you need in order to work on real-life Ubuntu Server deployments and become an expert Ubuntu Server administrator who is well versed in its feature set.

What you will learn

Install Ubuntu Server on physical servers and on the Raspberry Pi Deploy Ubuntu Server in the cloud and host websites on your own server Deploy your applications to their own containers and scale your infrastructure Set up popular applications such as Nextcloud Automate deployments and configuration with Ansible to save time Containerize applications via LXD to maximize efficiency Discover best practices and troubleshooting techniques

Product Details

Country selected

Publication date : Sep 22, 2022
Length 584 pages
Edition : 4th Edition
Language : English
ISBN-13 : 9781803234243
Concepts :

What do you get with eBook?

Product feature icon Instant access to your Digital eBook purchase
Product feature icon Download this book in EPUB and PDF formats
Product feature icon AI Assistant (beta) to help accelerate your learning
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want

Product Details

Publication date : Sep 22, 2022
Length 584 pages
Edition : 4th Edition
Language : English
ISBN-13 : 9781803234243
Concepts :

Table of Contents

26 Chapters
Preface Chevron down icon Chevron up icon
1. Deploying Ubuntu Server Chevron down icon Chevron up icon
2. Managing Users and Permissions Chevron down icon Chevron up icon
3. Managing Software Packages Chevron down icon Chevron up icon
4. Navigating and Essential Commands Chevron down icon Chevron up icon
5. Managing Files and Directories Chevron down icon Chevron up icon
6. Boosting Your Command-line Efficiency Chevron down icon Chevron up icon
7. Controlling and Managing Processes Chevron down icon Chevron up icon
8. Monitoring System Resources Chevron down icon Chevron up icon
9. Managing Storage Volumes Chevron down icon Chevron up icon
10. Connecting to Networks Chevron down icon Chevron up icon
11. Setting Up Network Services Chevron down icon Chevron up icon
12. Sharing and Transferring Files Chevron down icon Chevron up icon
13. Managing Databases Chevron down icon Chevron up icon
14. Serving Web Content Chevron down icon Chevron up icon
15. Automating Server Configuration with Ansible Chevron down icon Chevron up icon
16. Virtualization Chevron down icon Chevron up icon
17. Running Containers Chevron down icon Chevron up icon
18. Container Orchestration Chevron down icon Chevron up icon
19. Deploying Ubuntu in the Cloud Chevron down icon Chevron up icon
20. Automating Cloud Deployments with Terraform Chevron down icon Chevron up icon
21. Securing Your Server Chevron down icon Chevron up icon
22. Troubleshooting Ubuntu Servers Chevron down icon Chevron up icon
23. Preventing Disasters Chevron down icon Chevron up icon
24. Other Books You May Enjoy Chevron down icon Chevron up icon
25. Index Chevron down icon Chevron up icon

Customer reviews

Top Reviews
Rating distribution
Full star icon Full star icon Full star icon Full star icon Half star icon 4.7
(7 Ratings)
5 star 71.4%
4 star 28.6%
3 star 0%
2 star 0%
1 star 0%
Filter icon Filter
Top Reviews

Filter reviews by

N/A Jan 23, 2024
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Author very knowledgeable and presents the material in a way that is easy to understand.
Feefo Verified review Feefo image
N/A Feb 5, 2024
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Because of the simple and clear narrative!
Feefo Verified review Feefo image
wil blake Jan 22, 2024
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Feefo Verified review Feefo image
N/A Apr 2, 2024
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Feefo Verified review Feefo image
Vladimir Vinarsky Apr 18, 2024
Full star icon Full star icon Full star icon Full star icon Empty star icon 4
Good book, but could go a bit more in the detail
Feefo Verified review Feefo image