List of 16 Linux Networking and Troubleshooting Commands for Beginners

Linux Networking and Troubleshooting Commands

Network configuration and troubleshooting are the essential part of Linux administration. Even for a developer who works with Linux Systems, knowledge about Linux networking commands is an added advantage.

Specifically, if you are in DevOps or SRE domain, it is essential to know all the Linux troubleshooting commands as they will be part of your day-to-day activities.

This post will cover the important networking and troubleshooting commands that are natively available in the Linux systems.

List of Linux Networking and Troubleshooting Commands

Following is the list of natively available troubleshooting commands.

Command Description
hostnameTo check and set the hostname of the server.
hostTo get host DNS details
pingChecks if the remote server is reachable using ICMP protocol. It also shows the round trip time of packets.
curlA cross-platform utility that is used to transfer data. It can be used for troubleshooting several network issues.
wget Utility to download files. Can be used for troubleshooting proxy connections and connectivity.
ipA replacement for ifconfig. Can be used to configure and retrieve information about systems network interfaces
arpUtility to view and manage arp cache.
ss/netstatPrimarily used to check the connections and PID on ports and Unix sockets.
tracerouteThis utility uses the ICMP protocol and finds the hops involved in reading the destination server. It also shows the time it takes between hops.
mtrmtr is a mix of ping and traceroute. It also provides additional information like intermediate hosts and responsiveness.
digHelps you get the DNS records associated with a domain name.
nslookupCommand similar to dig.
ncutility to debug TCP/UDP sockets.
telnetIt can be used to test remote connectivity on ports
routeHelps you get all the route table information
tcpdumpThis utility helps you to capture network packets and analyze them for network issues.

Let’s understand each command and see how we can use it to troubleshoot Linux.

Important Note: Every command/utility mentioned in this post has many options and flags. Every command has a man page and you can use it to identify the flags and options that are required for your use case. For example, for ip command, you can just type it man ip in the terminal to get all the details about that command.

1. hostname

Hostname command is used to view the hostname of the machine and to set the hostname.


You can use the hostname command to set a new hostname for the machine. For example,

sudo hostname

If you set the hostname using “hostname” command, when you restart the machine, the hostname will change to the name specified in the hostname file ( eg: /etc/hostname).

So if you want to change the hostname permanently, you can use the /etc/hosts file or relevant hostname file present on the server.

  1. For ubuntu machines, you can change it in the /etc/hostname file.
  2. For RHEL, CentOS and Fedora you can change it in the /etc/sysconfig/network file.

Also read: List of Linux Commands Every Developer Should Know

2. host

Host command is for the reverse lookup of IP or a DNS name.

For example, If you want to find a DNS attached with an IP you can use the host commands as follows.


You can also do the reverse to find the IP address associated with the domain name. For example,


3. ping

The ping networking utility is used to check if the remote server is reachable or not. It is primarily used for checking the connectivity and troubleshooting network.

It provides the following details.

  1. Bytes sent and received
  2. Packets sent, received, and lost
  3. Approximate round-trip time (in milliseconds)

Ping command has the following syntax.

ping <IP or DNS>

For example,


To ping IP address


If you want to limit the ping output without using ctrl+c, then you can use the “-c” flag with a number as shown below.

ping -c 1

4. curl

Curl utility is primarily used to transfer data from or to a server. However, you can use it for network troubleshooting.

For network troubleshooting, curl supports protocols such as DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S, RTMP, RTMPS, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET and TFTP

For example, curl can check connectivity on port 22 using telnet.

curl -v telnet://

You can check the FTP connectivity using curl.


You can troubleshoot web server connectivity as well.

curl -I

5. wget

The wget command is primarily used to fetch web pages.

You can use wget to troubleshoot network issues as well.

For example, you can troubleshoot proxy server connections using wget.

wget -e use_proxy=yes http_proxy=<proxy_host:port>

You can check if a website is up by fething the files.


6. ip (ifconfig)

ip command is used to display and manipulate routes and network interfaces. ip command is the newer version of ifconfig. ifconfig works in all the systems, but it is better to use ip command instead of ifconfig.

Let’s have a look at few examples of ip command.

Display network devices and configuration

ip addr

You can use this command with pipes and grep to get more granular output like the IP address of the eth0 interface. It is very useful when you work on automation tools that require IP to be fetched dynamically.

The following command gets the IP address of eth0 network interface.

ip a | grep eth0  | grep "inet" | awk -F" " '{print $2}'

Get details of a specific interface

ip a show eth0

You can list the routing tables.

ip route
ip route list

7. arp

ARP (Address Resolution Protocol) shows the cache table of local networks’ IP addresses and MAC addresses that the system interacted with.


Example output,

va[email protected]:~$ arp
Address                  HWtype  HWaddress           Flags Mask            Iface                 ether   52:54:00:12:35:03   C                     eth0             ether   0a:00:27:00:00:00   C                     eth1                 ether   52:54:00:12:35:02   C                     eth0

8. ss (netstat)

The ss command is a replacement for netstat. You can still use the netstat command on all systems.

Using ss command, you can get more information than netstat command. ss command is fast because it gets all the information from the kernel userspace.

Now let’s have a look at few usages of ss command.

Listing all connections

The “ss” command will list all the TCP, UDP, and Unix socket connections on your machine.

[email protected]:~$ ss
Netid  State      Recv-Q Send-Q   Local Address:Port       Peer Address:Port
u_str  ESTAB      0      0                    * 7594                  * 0
u_str  ESTAB      0      0      @/com/ubuntu/upstart 7605                  * 0  
u_str  ESTAB      0      0                    * 29701                 * 0
u_str  ESTAB      0      0      /var/run/dbus/system_bus_socket 29702                 * 0
tcp    ESTAB      0      400

The output of the ss command will be big so you can use ” ss | less ” command to make the output scrollable.

Filtering out TCP, UDP and Unix sockets

If you want to filter out TCP , UDP or UNIX socket details, use “-t” “-u” and “-x” flag with the “ss” command. It will show all the established connections to the specific ports. If you want to list both connected and listening ports using “a” with the specific flag as shown below.

ss -ta
ss -ua
ss -xa

List all listening ports

To list all the listening ports, use “-l” flag with ss command. To list specific TCP, UDP or UNIX socket, use “-t”, “-u” and “-x” flag with “-l” as shown below.

[email protected]:~$ ss -lt
State      Recv-Q Send-Q      Local Address:Port          Peer Address:Port
LISTEN     0      128                     *:ssh                      *:*
LISTEN     0      50                     :::http-alt                 :::*
LISTEN     0      50                     :::55857                   :::*
LISTEN     0      128                    :::ssh                     :::*
LISTEN     0      50                     :::53285                   :::*
[email protected]:~$

List all established

To list all the established ports, use the state established flag as shown below.

ss -t -r state established

To list all sockets in listening state,

ss -t -r state listening

9. traceroute

If you do not have a traceroute utility in your system or server, you can install it from the native repository.

traceroute is a network troubleshooting utility. Using traceroute you can find the number of hops required for a particular packet to reach the destination.

For example,


Here is the output.

traceroute to (, 30 hops max, 60 byte packets
 1 (  1.974 ms  1.895 ms  1.899 ms
 2 (  1.414 ms (  1.127 ms (  1.313 ms
 3 (  1.443 ms (  2.160 ms (  2.116 ms
10 (  6.313 ms  7.104 ms (  5.986 ms
11 (  6.157 ms  6.341 ms  6.574 m.
12 (  6.302 ms  6.517 ms  6.071 ms
[email protected]:~$

The above output shows the hop count (12) to reach from devopscube AWS ec2 server.

10. mtr

The mtr utility is a network diagnostic tool to troubleshoot the network bottlenecks. It combines the functionality of both ping and traceroute

For example, the following command shows the traceroute output in real-time.


Here is the output.

mtr network diagnostic tool

mtr report

You can generate a report using the –report flag. When you run the mtr report, it sends 10 packets to the destination and creates the report.

mtr -n --report
network troubleshooting with mtr report

11. dig

If you have any task related to DNS lookup, you can use “dig” command to query the DNS name servers.

Get all DNS records with dig

The following command returns all the DNS records and TTL information of a

dig ANY
all DNS records with dig

Use +short to get the output without verbose.

dig ANY +short

Get Specific DNS Record with dig

For example, If you want to get the A record for the particular domain name, you can use the dig command. +short will provide the information without verbose

dig A +short

Similarly, you can get the other record information separately using the following commands.

dig CNAME +short
dig MX +short
dig TXT +short
dig NS +short

12. nslookup

Nslookup (Name Server Lookup) utility is used to check the DNS entries. It is similar to dig command.

To check the DNS records of a domain, you can use the following command.


You can also do a reverse lookup with the IP address.


To get all the DNS records of a domain name, you can use the following.

nslookup -type=any

Similarly, you can query for records like mx, soa etc

13. nc (netcat)

The nc (netcat) command is known as the swiss army of networking commands.

Using nc, you can check the connectivity of a service running on a specific port.

For example, to check if ssh port if open, you can use the following command.

nc -v -n 22

netcat can also be used for data transfer over TCP/UDP and port scanning.

Port scanning is not recommended in cloud environments. You need to request the cloud provider to perform port scanning operations in your enviroment.

14. telnet

The telnet command is used to troubleshoot the TCP connections on a port.

To check port connectivity using telnet, use the following command.

telnet 22

15. route

The “route” command is used to get the details of the route table for your system and to manipulate it. Let us look at few examples for the route command.

Listing all routes

Execute the “route” command without any arguments to list all the existing routes in your system or server.

[email protected]:~$ route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         ip-172-31-16-1.         UG    0      0        0 eth0      *          U     0      0        0 docker0     *        U     0      0        0 eth0
[email protected]:~$

If you want to get the full output in numerical form without any hostname, you can use “-n” flag with the route  command.

[email protected]:~$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface         UG    0      0        0 eth0     U     0      0        0 docker0   U     0      0        0 eth0
[email protected]:~$

If you think we missed any important command,  let us know in the comments section.

16. tcpdump

The tcpdump command is primarily used for troubleshooting network traffic.

Note: To analyze the output of tcpdump command requires some learning, so explaining it is out of the scope of this article.

tcpdump command works with the network interfaces of the system. So you need to use administrative privileges to execute the command.

List all network interfaces

Use the following command to list all the interfaces.

sudo  tcpdump --list-interfaces

Capture Packets on Specific Interface

To get the dump of packets on a specific interface, you can use the following command.

Note: press ctrl + c to stop capturing the packets.

sudo tcpdump -i eth0

To limit the packet capturing, you can use the -c flag with the number.

For example,

sudo tcpdump -i eth0 -c 10

Capture Packets on All Interfaces

To capture packets on all the interfaces, use the any flag as shown below.

sudo tcpdump -i any

Third-Party Network Troubleshooting Utilities

There are more networking troubleshooting command-line utilities available from third-party solutions.

You need to install them separately and use them for your troubleshooting purposes. Not every company will allow you to do it. However, if you have to option to use third-party tools, you can explore them.


In this article, we have covered the important Linux command-line utilities for network troubleshooting and configuration.

If you are getting started with system administration, DevOps, or SRE roles, it is essential to learn about these utilities to support the projects you are working on.

Each utility has many functionalities, and you can explore further to meet your requirements.

Linux Networking and Troubleshooting Commands

How to set Git Upstream For a Respository and a Branch

git set upstream tutorial

In this blog, you will learn everything about setting up an upstream for a git repository, a branch and the --set-upstream-to command usage

You will also learn about different scenarios where git upstream is used and how to apply it in your git development workflow.

Have you wondered how to keep the forked repo in sync with the main repo? It’s done by adding the main repo as the upstream. It is explained in the below sections.

What is Upstream in Git?

Note: We are following the name “main” instead of “master” considering the removal of terms like “master” and “slave” in the IT community.

Like the literal meaning, upstream refers to something which points to where it originated from.

In the git world, upstream refers to the original repo or a branch. For example, when you clone from Github, the remote Github repo is upstream for the cloned local copy.

Let’s take a look at different types of git upstreams.

Git Repository Upstream

Whenever you clone a git repository, you get a local copy in your system. So, for your local copy, the actual repository is upstream.

git remote upstream

Git Forked repository Upstream

When you clone a Forked repository to your local, the forked repository is considered as the remote origin, and the repository you forked from is upstream.

This workflow is common in open-source development and even in normal project developments.

For example, If you wanted to contribute to an open-source project, this is what you do.

  1. You would fork the actual project repository.
  2. Then you clone from the forked repository.
  3. Meanwhile, to keep up with the main open-source repository, you pull the changes from it through your git upstream config.
  4. You push your changes to a branch in the forked repository.
  5. Then you would raise a PR to the actual project repository from your forked repository.
git forked upstream min

Tip: With Jenkins multibranch pipelines, you can easily set up the hooks for pull requests from a Forked branch.

Setup Git Upstream For a Repository

Let’s say you are working on a forked project and you want to sync changes from the main project repo.

You can add the actual repo as an upstream to your local copy. This way you can pull all the changes happening in the main project repo.

Add an Upstream Repo

Before adding upstream, you can take a look at your .git/config file and you will see something like below with a remote origin. Which is a clone of the forked repo.

git forked repo without upstream repo

Now lets the add the upstream to our repo with the main project repo URL using the add upstream command.

git remote add upstream

Now if you check the .git/config, you will see an upstream entry as shown below.

git repo with upstream repo

You can also check out the remote origin and upstream branches using the following command.

git branch --remotes

Here is a sample output.

[email protected]:~/vagrant-examples$ git branch --remotes
  origin/HEAD -> origin/main

Sync Changes From The Upstream repo

To sync an upstream repo, first, you need to fetch the upstream changes.

git fetch upstream

Then, merge the changes from the upstream branch to the local branch. In this example, its the main upstream branch.

git merge upstream/main

Setup Git Upstream For a Branch

But when we talk about an upstream branch, it refers to the specific upstream of a branch in the remote respository.

For example, let’s say you clone a git repository with two branches, main and dev.

When you clone the repository both the branches, main, and dev will have the respective upstream branches (remote branches) because these branches are present in both the local copy as well the remote or upstream repository. Also, the tracking is enabled by default.

Now let’s look at scenarios where you want to set up git upstream using --set-upstream-to command.

Important Note: In git version update, 1.8.0 the --set-upstream the command is changed to --set-upstream-to

Add Git Upstream Using –set-upstream-to

When you create a branch (named foo) in your local repository and want to add an upstream branch for tracking, you can use the following command.

git push -u origin foo

Important Note: Here -u is the shorthand for --set-upstream-to

When you push a local branch with the upstream command, it automatically creates the remote branch and adds tracking to your local branch.

Add Git Upstream To Existing Remote Branch

Sometimes, when you create a local branch, you might push the remote repository changes without adding the upstream tag. For example,

git push origin foo

It will create the remote branch without tracking. Meaning, when someone pushes any change to the branch foo in the remote branch, and when you try to pull the changes, it will throw the following error.

There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details

    git pull <remote> <branch>

If you wish to set tracking information for this branch you can do so with:

    git branch --set-upstream-to=origin/<branch> testing

To avoid this, you can set git upstream using the following command. It will enable tracking, and you will be able to pull the changes.

git branch --set-upstream-to origin/foo

Add Git Upstream Using Git HEAD

In git, HEAD refers to the currently active branch.

For example, if you have checked out foo branch, your HEAD now is foo.

So when you create a new local branch named foo, you can create the upstream using the HEAD as shown below.

git push -u origin HEAD

Git set-upstream FAQ’s

What is the need to set upstream in git?

By setting upstream in git, the local branches can track the remote branches. This makes pulling changes from the remote repository very easy.

How to keep the original and forked repo in sync?

By setting the original repo as upstream on your local copy, you can fetch the original repo changes and push them to the forked repo to keep it in sync.

What is an upstream branch in Git?

When you clone a git repository, the parent or remote repository branches are called the upstream branches for the local branches.

How to check the git upstream branches?

You can check all the upstream branches using the git branch -vv command. It will show all the upstream tracking mapped to the local branches.

git set upstream tutorial

Vagrant Tutorial For Beginners: Getting Started Guide

Vagrant Tutorial For Beginners

In this Vagrant tutorial, I will teach you to set up Vagrant on your workstation to create and manage Virtual machines for your development environment.

I have been a big fan of vagrant and using it for more than 7 years now. Whenever I want to test a utility or a tool related to DevOps, it makes it so easy to set up and environment.

What is Vagrant?

Vagrant is an open-source utility created by guys in Hashicorp.

It is a wrapper utility that works on top of Virtual machine solutions like Virtualbox, HyperV, VMware, and also Docker. It abstracts away all the complex activities involved in managing a VM through the VM solutions and can automate most of the tasks.

Vagrant Architecture

Vagrant Architecture min


Using Vagrant, you can easily create virtual development environments from exiting VM images and have all the VM configs in a configuration file called Vagrantfile. To put it simply, you define everything you need in a VM in the Vagrantfile, and Vagrant will take care of configuring those in the VM.

Here is an example Vagrantfile,

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config| = "ubuntu/trusty64" "private_network", ip: ""
    config.vm.provider "virtualbox" do |vb|
      vb.memory = "1024"

If someone has Vagrant installed on their system, you can share the Vagrantfile with them and they can build a similar VM you have created. A similar workflow like how Docker Works

Vagrant Boxes

In the sample Vagrantfile, you can see a parameter named ““.

The vagrant box is a prebaked Virtual machine image (Ubuntu, Centos, etc). This box format can be shared with anyone who uses Vagrant.

You can download readily available community boxes from Vagrantcloud

You can also add shell scripts or use chef cookbooks, puppet modules, or Ansible playbooks to the Vagrantfile to automate the VM configuration process. You can then package the box with all configurations and share it with other team members.

Vagrant Use Cases

Following are the real world use cases for Vagrant

  1. Development Environments: Let’s say you want identical development environments for all the developers in a team. In this case, you can create a common Vagrantfile with all the configs required to provision the VM with development environment dependencies (Softwares). And then share the Vagrantfile with all the developers. This way, there will not be any change in the underlying software or configs used. Some companies host Vagrant boxes in a common location for different approved software so that everyone in the organization can use it.
  2. Sandboxed environments: If you want a sandboxed environment for testing, you could use Vagrant to spin up and destroy VMs in minutes.


  1. You should have a virtual box installed. You can download the latest Virtualbox setup from here
  2. You should have root access to install the software on your workstation.
  3. Open internet access to download a few software and VM images.
  4. Your workstation should have more than 4 GB of RAM.

Installing Vagrant

Step 1: Download the vagrant installation file from

Step 2: Install Vagrant from the downloaded file based on your operating system. The vagrant executable will be automatically added to your system path and you can start using the vagrant command.

Step 3: To verify the installation for vagrant, execute the following vagrant command see if it output the version.

vagrant --version

Getting Started With Vagrant (Creating Development Environments With Vagrant)

In this section, I will walk you through the following 4 processes to get a basic understanding of how vagrant works and how you can use it for your development purposes.

  1. Create a Ubuntu-based VM using Vagrant. Let’s name is apache-vm
  2. SSH into the newly created Vagrant VM.
  3. Install an Apache web server on the VM
  4. Access the webserver page over the browser.

Let’s get started with the setup.

Create a Virtual Machine Using Vagrant

In this section, you will learn how to create a Virtual machine using vagrant.

Step 1: Choose a folder to keep all vagrant-related files and Create a VM project directory.

mkdir apache-vm

Step 2: Initialize a Vagrantfile with Ubuntu Image. This file will contain all the necessary configs for your reference. Here we are going to use the generic Ubuntu Trusty image available in the vagrant cloud.

Note: In Vagrant, we create VMs using prebaked Virtual Machine images. All these images can be found in the Vagrant cloud catalog. It is completely free.

Execute the following command to initialize the Vagrantfile

vagrant init ubuntu/trusty64

If you check now, you will see a Vagrantfile in your current folder. If you open the file, you will see most of the lines commented out. For now, let’s not worry about it. Let’s bring up the ubuntu VM.

Step 3: Start the Vagrant VM using the following command.

vagrant up

Note: If you don’t have a virtual box installed, you will get a “No usable default provider could be found for your system” error.

The above command will first download the ubuntu/trusty64 VM image from the vagrant cloud and then it will start the VM.

Also, it will generate an SSH key pair and adds the public key to the VM during this process. So that we can SSH into the machine once it is up and running.

Step 4: You can check the status of the VM using the following command.

vagrant status

It should show the output as running (virtualbox)

SSH into Vagrant Virtual Machine

Now lets look at how to SSH in to the VM started by Vagrant.

Make sure that you are executing the commands from the apache-vm folder.

You can SSH into the Vagrant using the following command.

vagrant ssh

When you run the ssh command, it vagrant fetches the private key from the apache-vm/.vagrant/machines/default/virtualbox folder and connects to the VM.

Install Apache Web Server

Now let’s install an apache server and see if we can access it through our web browser.

Step 1: Install apache using the following command.

sudo apt-get install apache2 -y

Step 2: Start the Apache server.

sudo service apache2 start

Step 3: check the status of the server. You will see the output as running.

sudo service apache2 status

Step 4: Let’s use curl and see if we are able to access the webpage. It should output the apache 2 HTML welcome page.

curl localhost

Step 5: Let’s get the IP address of the VM using the following command.

ip route get | awk '{print $7}'

The above command should output the IP address.

Step 5: Try curl with the IP address. You should see the same output as step 4. Replace the IP address with the one you see in the output.


Step 6: Now, try accessing the IP address from your systems web browser. You will not be able to access it. The reason is the current network of VM is not in a private network now. Meaning, there is a connection to the VM from the outside world.

Let’s make some changes to the Vagrant file to access the VM from your browser.

Step 7: Destroy the VM using the following command.

vagrant destroy

Step 8: Now, open the Vagrantfile and uncomment the following line. "private_network", ip: ""

It means, we are enabling the private network and setting the IP address of the VM to

If you want to enable access to the VM from a different computer on your wifi network, enable the following option. "public_network"

When you bring up the VM, it will ask for the interface to bridge as shown below.

Vagrant public network bridge details

You can also configure port forwarding from the host to Vagrant VM. For example, if you run an apache server on 80 on the VM, you can configure the host port 8080 to forward requests to VM port 80. "forwarded_port", guest: 80, host: 8080

This way, you can access the apache server from your host web browser on http://localhost:8080

Step 9: Bring up the VM again and ssh into it.

vagrant up
vagrant ssh

Step 10: Now install the apache server and start it using step 1 and 2

Step 11: Now if you try to access the apache welcome page using, you will be able to access it.

Vagrant Shared Folder

If you are wondering how to share a host folder with Vagrant VM, here is where the /vagrant folder comes into play

Vagrant Default Shared Folder

Every Vagrant VM will have a /vagrant folder. This folder is mounted to the host folder where you have the Vagrantfile. Meaning, the project folder you create to have the Vagrantfile will be mounted inside the VM on /vagrant location.

So form a vagrant VM if you access the /vagrant folder, you can see the Vagrantfile.

Here is the real use case for using the shared folder.

If you are working on your code on the host machine, you can set the vagrant project folder as the root folder for the code so that the webserver running in the VM can access your code and test it directly.

Vagrant Custom Shared Folder Location

If you wish to use a custom host folder to be shared with a Vagrant VM, you can do it by adding the config.vm.synced_folder parameter.

For example,

config.vm.synced_folder "code/", "/app/code"

In the above config, code/ is the folder present in the apache-vm project directory. If it any other location, you need to specify the full path.

Custom CPU & Memory

You can define custom CPU & memory for your vagrant VM.

Set the CPU & memory values based on the available resources in your system.

Here is the config syntax.

config.vm.provider "virtualbox" do |vb|
    vb.memory = 2048
    vb.cpus = 1

Vagrant Provisioner

The best thing about Vagrant is that you can add provisioning scripts to Vagrantfile.

Here is an example of having shell script as provisioner.

config.vm.provision "shell", inline: <<-SHELL
    apt-get update
    apt-get install -y apache2
    service apache2 start

You can also use Ansible, Chef, or puppet as provisioners.

Example Vagrantfiles

From a single Vagrantfile, you can create single or multiple VMs. Lets have a look at the examples of single and multiple VM configurations.

Single VM Vagrantfile

The following Vagrantfile has all the concepts I have explained above.

  1. Creates VM with ubuntu/trusty64 box
  2. Enables private network, public_network, and port forwarding on host port 8080
  3. Custom shared folder
  4. Custom CPU and memory
  5. Shell provisioner to install apache2
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config| = "ubuntu/trusty64" "private_network", ip: "" "public_network" "forwarded_port", guest: 80, host: 8080

  config.vm.synced_folder "code/", "/app/code"

  config.vm.provider "virtualbox" do |vb|
    vb.memory = 2048
    vb.cpus = 1

  config.vm.provision "shell", inline: <<-SHELL
    apt-get update
    apt-get install -y apache2
    service apache2 start

Multi VM Vagrantfile

The following Vagrantfile has configs to create two VMs named web and db with its own configurations.

Vagrant.configure("2") do |config|
  config.vm.provision "shell", inline: "echo Hello"

  config.vm.define "web" do |web| = "ubuntu/trusty64" "private_network", ip: ""
    web.vm.synced_folder "code/", "/app/code"
    web.vm.provider "virtualbox" do |vb|
        vb.memory = 1048
        vb.cpus = 1

  config.vm.define "db" do |db| = "ubuntu/trusty64" "private_network", ip: ""
    db.vm.synced_folder "data/", "/db/data"
    db.vm.provider "virtualbox" do |vb|
        vb.memory = 2048
        vb.cpus = 1

To ssh into the VMs, you need to use the names web and db

vagrant ssh web
vagrant ssh db

You can individually manage the VMs with its name.

Multi VM Vagrantfile With Loop

Let’s say you want to create 3 Vms of the same type.

In this case, you can use a loop to create multiple VMs with derived private IPs.

Here is an example.

Vagrant.configure("2") do |config|

  (2..4).each do |i|
    config.vm.define "vm-#{i}" do |web| = "ubuntu/trusty64" "private_network", ip: "192.168.33.#{i}", auto_config: false
      web.vm.provision "shell", inline: "echo hello #{i}"
      web.vm.synced_folder "code/", "/app/code"

Vagrant Vs Docker

Vagrant is just a wrapper utility that can provision VMs or containers using backend providers like Virtualbox or Docker. In comparison, Docker is a lightweight container solution with its own set of tooling to manage containers.

If you use Virtualbox or Vmware as the provider for Vagrant, it can launch a Virtual machine as per the configs in the Vagrantfile.

If you use Docker as the provider for Vagrant, then it will launch docker containers as per the configs in the Vagrantfile.


In this Vagrant Tutorial, you have learned how to set up a basic Vagrant Virtual machine for development environments.

It is a wonderful tool for setting up development environments for your workstations.

You can achieve these using tools like docker-compose but most of the time I prefer using Vagrant with plain VMs fr testing purposes.

Let me know in the comment section if you have any cool hacks that work with vagrant.

Vagrant Tutorial For Beginners

How To Create Kubernetes Jobs/Cron Jobs – Getting Started Guide

Kubernetes Jobs/Cron Jobs – Getting Started Guide

Kubernetes jobs are primarily meant for short-lived and batch workloads. It runs for completion instead of other objects like deployment, replicasets, replication controllers, and DaemonSets, which continuously runs.

This tutorial explains creating kubernetes jobs and cronjobs, along with a few tips and tricks.

Kubernetes Jobs run until the tasks specified in the job are completed. Meaning, if the pods give exit code 0, the job will exit. Whereas in normal Kubernetes deployments, irrespective of the exit codes, the deployment object will create new pods when it terminates or throws an error to keep the deployment’s desired state.

During a Job run, if the node hosting the pod fails, the job pod will get automatically rescheduled to another node.

Kubernetes Jobs Use Case

The best use case for Kubernetes jobs are,

  1. Batch processing: Let’s say you want to run a batch task once a day or during a specific schedule. It could be something like reading files from storage or a database and feed them to a service to process the files.
  2. Operations/ad-hoc tasks: Let’s say you want to run a script/code which runs a database cleanup activity or even backup a kubernetes cluster itself.

How to Create a Kubernetes Job

In this example, we will use an Ubuntu container that runs a shell script with for loop and echoes a message based on the argument you pass to the container. This argument is a number that decides how many times the shell script loop should run.

You Might Like: CKA, CKAD & CKS Exam Coupon Codes

For example, if you pass 100 as an argument, the shell script will echo the message 100 times and the container will exit.

You can view the Dockerfile and the shell script from here -> kube-job-example Docker configs

Let’s get started with a job with a simple setup.

Step 1: Create a job.yaml file with our custom Docker image with 100 as a command argument. The value 100 will be passed to the docker ENTRYPOINT script as an argument.

apiVersion: batch/v1 
kind: Job 
  name: kubernetes-job-example   
    jobgroup: jobexample 
      name: kubejob       
        jobgroup: jobexample     
      - name: c         
        image: devopscube/kubernetes-job-demo:latest         
        args: ["100"]       
      restartPolicy: OnFailure

Step 2: Let’s create a job using kubectl with the job.yaml file.

kubectl apply -f job.yaml

Step 3: Check the status of the job using kubectl.

kubectl get jobs

Step 4: You can get the list of pods using kubectl.

kubectl get po

Step 5: You can get the job pod logs using kubectl. Replace the pod name with the pod name you see in the output.

kubectl logs kubernetes-job-example-bc7s9 -f

You should see an output as shown below.

kube jobs 2

Multiple Job Pods and Parallelism

When a job is deployed you can make it run on multiple pods with parallelism.

For example, in a job if you want to run 6 pods and run 2 pods in parallel, you need to add the following two parameters to your job manifest.

completions: 6
parallelism: 2

Here is the manifest file with those parameters.

apiVersion: batch/v1
kind: Job
  name: kubernetes-parallel-job
    jobgroup: jobexample
  completions: 5
  parallelism: 2
      name: kubernetes-parallel-job
        jobgroup: jobexample
      - name: c
        image: devopscube/kubernetes-job-demo:latest
        args: ["100"]
      restartPolicy: OnFailure

Generate Random Name for Kubernetes Job

You cannot have a single job manifest file and create multiple jobs from it. Kubernetes will throw an error stating that a job with the same name exists.

To circumvent this problem, you can add the generateName name parameter to the metadata.

For example,

apiVersion: batch/v1
kind: Job
  generateName: kube-job-
    jobgroup: jobexample

In the above example, every time you run the manifest, a job will get created with kube-job- as a prefix followed by a random string.

How to Create a Kubernetes CronJob

What if you want to run a batch job on specific schedules, for example, every 2 hours. You can create a Kubernetes cronjob with a cron expression. The job will automatically kick in as per the schedule you mention in the job.

Here is how we specify a cron schedule. You can use the crontab generator to generate your own schedule.

schedule: "0,15,30,45 * * * *"

The following image shows the kubernetes cronjob scheduling syntax.

kubernetes cronjob scheduling syntax

If we were to run our previous job as a cronjob every 15 minutes, here is how the manifest looks. Create a file named cron-job.yaml and copy the following manifest.

apiVersion: batch/v1beta1
kind: CronJob
    name: kubernetes-cron-job
  schedule: "0,15,30,45 * * * *"
            app: cron-batch-job
          restartPolicy: OnFailure
          - name: kube-cron-job
            image: devopscube/kubernetes-job-demo:latest
            args: ["100"]

Let’s deploy the cronjob using kubectl.

kubectl create -f cron-job.yaml

List the cronjobs

kubectl get cronjobs

To check Cronjob logs, you can list down the cronjob pod and get the logs from the pods in running state or from the finished pods.

Run a Kubernetes CronJob Manually

There are situations where you might want to execute the cronjob in an ad-hoc manner. You can do this by creating a job from an existing cronjob.

For example, if you want a cronjob to be triggered manually, here is what we should do.

kubectl create job --from=cronjob/kubernetes-cron-job manual-cron-job

--from=cronjob/kubernetes-cron-job will copy the cronjob template and creates a job named manual-cron-job

Few Key Kubernetes Job Parameters

There are a few more key parameters you can use with kubernetes jobs/cronjobs based on your needs. Let’s have a look at each.

  1. failedJobHistoryLimit & successfulJobsHistoryLimit: Deletes the failed and successful job history based on the retention number you provide. This is super useful to trim down all failed entries when you try to list the jobs. For example,
    failedJobHistoryLimit: 5  successfulJobsHistoryLimit: 10
  2. backoffLimit: Total number of retries if your pod fails.
  3. activeDeadlineSeconds: You can use this parameter if you want to specify a hard limit on how the time the cronjob runs. For example, if you want to run your cronjob only for one minute, you can set this to 60.

Kubernetes Jobs/Cron Jobs – Getting Started Guide

How To Install and Configure GUI for Amazon EC2 RHEL 7 & RHEL 8 Instance

amazon ec2 rhel 7 gui

In this tutorial, I have explained the easy steps to configure GUI for the RedHat 7 & 8 EC2 instance and connect to it using RDP clients.

Note: For RHEL 6 follow this tutorial. Setting up GUI on RHEL6

GUI for Amazon EC2 RHEL 7 & RHEL 8

There are three sections involved in the whole setup. Follow all the three sections explained below to successfully configure the GUI.

Note: This tutorial is tested on both RHEL 7 and RHEL 8 ec2 instances.


  1. RHEL 7 or 8 ec2 instance with minimum instance type of t2.medium. The GUI won’t load on smaller instance types.
  2. ec2 instance security group should have an inbound connection to 3389 port.

Installing GUI Components

1. Update the server using the following command.

sudo yum -y update

2. Install the gnome GUI components using the following command.

sudo yum groupinstall -y "Server with GUI"

3. Issue the following commands to start the GUI during boot.

sudo systemctl set-default
sudo systemctl default

Now we have all the essential GUI components installed on the server. In the next section, we will install the xrdp components to enable remote desktop connections.

Recommended: Learn Linux in 5 Days and Level Up Your Career Udemy Course

Setting up XRDP

1. Add the xrdp repository to your instance using the following command.

sudo rpm -Uvh

2. Install xrdp and tiger VNC server.

sudo yum install -y xrdp tigervnc-server

3. Setup SELINUX security using the following commands.

chcon --type=bin_t /usr/sbin/xrdp
chcon --type=bin_t /usr/sbin/xrdp-sesman

4. Start and enable the xrdp service.

sudo systemctl start xrdp
sudo systemctl enable xrdp

5. Enable RDP port on the instance using the following firewall commands.

sudo firewall-cmd --permanent --add-port=3389/tcp
sudo firewall-cmd --reload

6. Set a password for ec2-user . This password will be used to connect to the RDP session.

sudo passwd ec2-user

7. Set password for root as you will be prompted for cloud user password for network proxy and color. Login as root and set the password.

sudo su

Now we have the xdrp components and all instance-level settings in the right place. Now let’s test out the RDP connection from an RDP client.

In this tutorial, I am using a windows RDP client.

If you are using MAC, you can use the Microsoft Remote Desktop app to connect.

Connecting the Instance Using RDP

Note: Make sure you have added the inbound RDP port (3389) in your instance security group.

1. Open RDP client and type in the public IP of your instance and click connect.

2. If you get a warning message about remote identity, just click yes.

3. Now you will get a xrdp authentication window, enter the credentials and click ok.

Note: The username is “ec2-user” and the password is the password you set for ec2-user in step 6.

4. You will be prompted to enter the password again. Provide the password and proceed to the steps to configure the initial desktop.

5. If it prompts for “cloud user password” provide the root user password you set in step 7.

6. That’s it, you will get a GUI session as shown below. If you face any errors do let me know in the comment session.

amazon ec2 rhel 7 gui
amazon ec2 rhel 7 gui

10 Key Considerations for Kubernetes Cluster Design & Setup

kubernetes design considerations

Design is a very important aspect when it comes to kubernetes cluster setup.

This blog will talk about the 10 high-level things that have to the taken into consideration when setting up a Kubernetes cluster.

1. Kubernetes Networking (Cloud, Hybrid, or On-Prem):

Kubernetes network has to be designed in such a way that it can accommodate future cluster and application requirements.

One common mistake organizations do is using CIDR ranges that are not part of the organization’s network. In the future when they want the clusters to be in a hybrid network, it ends up in migration.

It is better to discuss with the organization’s network team before finalizing the network design. This way, you can carve out and reserve an IP range even if you are not part of the hybrid network.

Each cloud provider gives multiple options for Node and Pod networking. For example, GKE offers multi-cluster services, VPC native clusters with routable pod IPs from the same VPC and the peered VPCs.

But if you don’t want to expose your pod IPs, you might need to use something like an IP masquerading agent in your cluster so that the outgoing traffic will always have the Node IP as the source identity.

Also, Ingress and egress traffic design are essential. There could be API gateways, on-prem systems, and third-party APIs that you need to connect from the cluster apps.

Your design should include all the access requirements so that you won’t face any access restrictions during implementation.

2. Kubernetes Security, Compliance & Benchmarks

Following are the generic security considerations.

  1. Understand the compliance requirements and security benchmarks as per your organization’s policy. If you are using managed services, make sure it complies with the organization’s compliance policies.
  2. Will there be any PCI/PII data apps?. If yes, then segregate these apps in terms of access and storage.
  3. Implement the standard pod security policies ( disabling container root access, privileged access, read-only file system, etc).
  4. Accessing the container registries securely.
  5. Network policies to control pod to pod traffic and isolate apps as per access requirements.
  6. A well-designed pipeline to make sure only approved container images are deployed in the cluster. Containers should be scanned for vulnerabilities and fail the CI process if the image scan fails to meet the security requirements,

3. Kubernetes Cluster Access

It is very important to design and document the way the kubernetes cluster is accessed.

Following are the key considerations.

  1. Restricting manual cluster-admin access. Instead, cluster-admin access should only be allowed through automation.
  2. Implement RBAC’s authorization.
  3. Allow kubernetes API access via service accounts with limited privileges.
  4. Implement Open Policy Agent for fine-grained access controls.
  5. Consider options for openID connect
  6. Have a good audit mechanism for checking the roles and removing unused users, roles, service accounts, etc.

Design the access levels so that you can hand off responsibilities to other teams using the cluster. It would save time for everyone, and you can focus more on the engineering par rather than working on repeated tasks.

4. Kubernetes High Availability & Scaling

High availability another key factor in the kubernetes cluster.

Here you need to consider the worker node availability across different availability zones.

Also, consider Pod Topology Spread Constraints to spread pods in different availability zones.

When we talk about scaling, it’s not just autoscaling of instances or pods.

It’s about how gracefully you can scale down and scale up the apps without any service interruptions.

Depending on the type of apps that needs to be hosted on kubernetes, you can design deployments to evict the pods gracefully during scale down and patching activities.

Also, consider chaos engineering experiments before production to check the cluster and app stability.

5. Kubernetes Ingress

Ingress is an essential component of Kubernetes clusters. There are many ways to set up a kubernetes ingress.

Also, there are different types of ingress controllers.

You can try out the best option that will be suitable for your organization’s compliance policies and scaling requirements.

Few considerations,

  1. Have separate ingress controllers for the platform-tools.
  2. SSL management for ingress endpoints.
  3. Do not try to route all the apps through the same ingress. If your apps grow day by day, they could end up in a big configuration file creating issues.

6. Kubernetes Backup & Restore Strategy

Whether it is a managed service or custom kubernetes implementation, it is essential to back up the cluster.

When we say backup, it is primarily backing up etcd.

You should have a very good design to automate the backup of the kubernetes cluster and its associated components.

Also, a design to restore the cluster if required.

There are also options to take the dump of existing objects in JSON format. You can use dump to restore the objects in the same or a different cluster.

7. Kubernetes Node & Container Image Patching & Lifecycle Management

Patching is a repeated process.

When it comes to kubernetes, there is node and container patching.

Make sure you implement DevSecOps principles in your CI/CD pipelines.

Here are some key considerations,

  1. An automated pipeline integrated with container scanning tools to patch container images on a monthly schedule.
  2. An automated pipeline to perform node patching without downtime.
  3. An automated pipeline to manage the lifecycle of container images. You don’t want to keep so many versions in your registry that are outdated.

8. Kubernetes Cluster Upgrades

Generally, you can perform a cluster updgrade in two ways

  1. Upgrading the existing cluster.
  2. Create a new cluster and migrate the apps to the new cluster.

You need a very good automated pipeline design to perform a cluster upgrade.

There could be Networking, DNS, and other component changes during an upgrade. It all depends on the design & organizational policies.

9. Kubernetes Cluster Capacity & Storage

Cluster capacity a very important topic of discussion.

You need to decide on the number of clusters you need to run.

Some organization prefers running multiple clusters to reduce the blast radius and easy maintenance. While others prefer a big cluster with a large number of worker nodes or less number of nodes with huge instance capacity.

You can decide on the cluster capacity based on your needs and the size of the team to manage the clusters.

Next comes the storage part.

Plan how you want to attach volumes to containers. Follow all the standard storage security practices on kubernetes.

When it comes to the cloud, there is out of the box support for provisioning storage,

If you are planning to run stateful sets, it is very important to design the storage to get high throughputs and maximum availability.

10. Kubernetes Logging & Monitoring

Most of the organizations will have a centralized logging and monitoring system and they prefer to integrate kubernetes with these systems.

Here are the key considertions.

  1. How much log data will be generated.
  2. Mechanisms to ingest Kubernetes logs into the logging systems considering huge data volume.
  3. Scaling logging and monitoring components deployed in the cluster.
  4. Data retention as per organizations policy.
  5. Define and document the KPIs for monitoring.


These are some of the key considerations which often get missed while setting up a kubernetes cluster.

Missing these aspects while implementing kubernetes could lead to issues in the overall cluster and might impose compromises for the business.

Ideally, the Solution/ Technical architect should keep all the mentioned Items (there could be many but worth considering) as a checklist while designing the cluster architecture to make sure they are implemented during the IaaC development.

kubernetes design considerations