Saturday 30 December 2017

Nginx04-Standard-Configuration

Standard NGINX Configuration

  • For NGINX the base and main configuration file is /etc/nginx/nginx.conf as it contains all the main and mandatory configs.
  • Let us add an include statement to pull our customized configs.
  • We can see the ngin.conf file has an include directive in the http section which will tell the main config to pull the configs from.
  • By default it will pull the configs from /etc/nginx/conf.d directory.
  • We'll add an additional include directive to pull our configs from /etc/nginx/vhost.conf in which we are going to have our custom configs. Here we'll remove the server directive and have that in our custom config file.
# cp -prv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.`date +"%Y%m%d"`
# vi /etc/nginx/nginx.conf

include /etc/nginx/vhost.d/*.conf;
  • If we are hosting multiple websites then we can have our SITE_NAME.d directory in place of vhost.d. This will help us in hosting multiple websites to avoid confusion.
  • Now let us create a directory named vhost.d and prepare our custom config.
# cd /etc/nginx
# mkdir vhost.d
# cp -prv conf.d/default.conf vhost.d/
  • If you are unable to find the default.conf file in conf.d directory then you can copy default.conf
  • Comment the include directive which points to load the default configs from the /etc/nginx/default.d
  • Change the document root to /var/www/html from /usr/share/nginx/html in the location section.
  • Create the document root and create and index file.
# mkdir /var/www/html
# echo -e "WELCOME TO LINUX-LIBRARY NGINX WEBSERVER\nThis site is under development" > /var/www/html/index.html
  • Once you are done with your customizations then restart the nginx service.

Thursday 21 December 2017

Nginx03-Configuration-Optimization

Optimizing the NGINX Configurations

  • Location of the nginx main config file is /etc/nginx/nginx.conf
  • Let us know about this configuration file and its options first
  • worker_processes
    • This is responsible for machine to know how many workers are available to spawned after getting bounded to an IP / Port.
  • worker_connections
    • By default this will be set to 1 but depending on the connections the host can accept we can change it.
    • Through ulimit -n we can know the max number of connections allowed to a host.
     worker_connections 1024;
    
  • Buffers This section should be placed in the html section and before the include statement of the nginx config file.
    • client_body_buffer_size
     client_body_buffer_size 10k;
    
    • client_header_buffer_size
     client_header_buffer_size 1k;
    
    • client_max_body_size
     client_max_body_size 8m;
    
    • large_client_header_buffers
     large_client_header_buffers 2 1k;
    
  • Timeouts This will tell the server to know the max time to wait after a request has been received from a client. There are 2 types of timeouts.
    • client_body_timeout This can be set to a max of 12 seconds.
     client_body_timeout 12;
    
    • client_header_timeout Maintaining the same as the timeout for the body
     client_header_timeout 12;
    
    • keep_alive_timeoutsend_timeout These will let the system know till when a request can be waited and when to send the error if not able to serve the request. If you already have these then you can modify those as per your choice.
     keep_alive_timeout 15;
     send_timeout 10;
    
  • Test your configurations This would always be a good practice to verify your config before restarting the application as you can get to know where you have misconfigured.
# nginx -t

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
  • Restart nginx
# systemctl restart nginx

Saturday 16 December 2017

Nginx02-Installation

Installation and Setup

  • Configure EPEL repository and install NGINX
# yum install nginx -y
  • Enable Nginx and start it
# systemctl enable nginx
# systemctl start nginx

Nginx01-Intro

NGINX

NGINX WebServer Administration

NGINX is a free, open-source, high-performance HTTP server and reverse proxy, as well as an IMAP/POP3 proxy server. NGINX is known for its high performance, stability, rich feature set, simple configuration, and low resource consumption.
NGINX is one of a handful of servers written to address the C10K problem. Unlike traditional servers, NGINX doesn’t rely on threads to handle requests. Instead it uses a much more scalable event-driven (asynchronous) architecture. This architecture uses small, but more importantly, predictable amounts of memory under load. Even if you don’t expect to handle thousands of simultaneous requests, you can still benefit from NGINX’s high-performance and small memory footprint. NGINX scales in all directions: from the smallest VPS all the way up to large clusters of servers.

Overview of nginx Architecture

nginx-arch
Traditional process- or thread-based models of handling concurrent connections involve handling each connection with a separate process or thread, and blocking on network or input/output operations. Depending on the application, it can be very inefficient in terms of memory and CPU consumption. Spawning a separate process or thread requires preparation of a new runtime environment, including allocation of heap and stack memory, and the creation of a new execution context. Additional CPU time is also spent creating these items, which can eventually lead to poor performance due to thread thrashing on excessive context switching. All of these complications manifest themselves in older web server architectures like Apache's. This is a tradeoff between offering a rich set of generally applicable features and optimized usage of server resources.
From the very beginning, nginx was meant to be a specialized tool to achieve more performance, density and economical use of server resources while enabling dynamic growth of a website, so it has followed a different model. It was actually inspired by the ongoing development of advanced event-based mechanisms in a variety of operating systems. What resulted is a modular, event-driven, asynchronous, single-threaded, non-blocking architecture which became the foundation of nginx code.
Nginx uses multiplexing and event notifications heavily, and dedicates specific tasks to separate processes. Connections are processed in a highly efficient run-loop in a limited number of single-threaded processes called workers. Within each worker nginx can handle many thousands of concurrent connections and requests per second.

Tomcat16-Multiple-Instances

Running Multiple Tomcat Instances on a Single Server Setup

  • Be sure you have installed JDK-8 and check the following variables
# env | grep JAVA
JAVA_HOME=/opt/jdk8

# env | grep JRE
JRE_HOME=/opt/jdk8/jre
  • Add tomcat user and group
# groupadd tomcat
# useradd -M -s /sbin/nologin -g tomcat -d /opt/tomcat tomcat
  • Have the tomcat base downloaded to your machine and extreact those to /opt/tomcat-src
  • In my case I already have tomcat downloaded. So I am going to extract those
# mkdir /opt/tomcat-src
# tar -xzvf ~/apache-tomcat-8.5.11.tar.gz -C tomcat-src/ --strip-components=1
  • Let us create 2 directories for our tomcat instances
# mkdir /opt/tomcat{1,2}
  • Copy the contents of tomcat-src to tomcat1 and tomcat2
# cp -prf /opt/tomcat-src/* /opt/tomcat1
# cp -prf /opt/tomcat-src/* /opt/tomcat2
  • Let us change the permissions of some directories in tomcat1 and tomcat2
# cd tomcat1/
# chgrp -R tomcat conf
# chmod g+rwx conf/
# chmod g+r conf/*
# chown -R tomcat work/ temp/ logs/
# cd tomcat2/
# chgrp -R tomcat conf
# chmod g+rwx conf/
# chmod g+r conf/*
# chown -R tomcat work/ temp/ logs/
  • Now we need to change the configs to change the ports as we know each instance should have some distinct ports to listen on.
[TOMCAT1]

Shutdown Port ->      7005
Web Port  ->      7080
Redirect Port ->      7443
AJP Conn. Port ->      7009
[TOMCAT2]

Shutdown Port   ->      8005
Web Port        ->      8080
Redirect Port   ->      8443
AJP Conn. Port  ->      8009
  • Please refer to Basic Clustering to know how to change the ports also to know how can these tomcat instances be run in a clustered environment to balance the load

Sunday 10 September 2017

Tomcat15-as-Service

Configuring Tomcat as Service

  • Till now we are starting or stopping the tomcat instance from the home through the catalina script.
  • We will not be able to start this through service or systemctl
  • In the previous sessions you might have seen that we have started this through service but it is a custom script written by me
  • Apart from that we can't directly use tomcat through service
  • Now let us see how to accomplish this.
  • For this we should have jvsc package installed on our CentOS/Redhat machine.
  • This package will help us to run the java services as daemons or services.
    • Install through YUM
     # yum install jsvc -y
    
    • If the packages are not available then we need to download and install from the source.
    NOTE: Please ensure that you have configured you JAVA_HOME before proceeding with the below.
     # wget http://www-eu.apache.org/dist//commons/daemon/source/commons-daemon-1.0.15-src.tar.gz
     # tar -xzvf commons-daemon-1.0.15-src.tar.gz
     # cd commons-daemon-1.0.15-src/src/native/unix
     # echo $JAVA_HOME
     # make
     # ./jsvc -help
    
  • Now we should have tomcat user and apache
# useradd tomcat
# groupadd apache
# usermod -G apache tomcat
  • Change the owner and group of the $CATALINA_HOME
Before doing this be sure tomcat is not running. Stop if it is running
# cd /opt
# chown -R tomcat:apache tomcat8
  • We need to create a file where our ENVIRONMENT variables can be setup for tomcat
# vi /etc/sysconfig/tomcat

CATALINA_HOME=/opt/tomcat8
JAVA_HOME=/opt/jdk8
JSVC=/usr/share/jsvc-src/commons-daemon-1.0.15-src/src/native/unix
  • Now we need to create a service file for tomcat
# vi /usr/lib/systemd/system/tomcat.service

[Unit]
Description=Tomcat WebServer
After=syslog.target network.target

[Service]
Type=forking
User=tomcat
EnvironmentFile=/etc/sysconfig/tomcat
ExecStart=/opt/tomcat8/bin/catalina.sh start
ExecStop=/opt/tomcat8/bin/catalina.sh stop

[Install]
WantedBy=multi-user.target
  • Enable the tomcat service
# systemctl enable tomcat.service
  • Start Tomcat
# systemctl start tomcat.service

Saturday 29 July 2017

Tomcat14-Troubleshooting-Logs

Troubleshooting Tomcat using log files

  • We have already seen how to troubleshoot tomcat instance based on the catalina.out log
  • By default tomcat writes some different logs as defined in the catalina script into the logs directory
  • Here we can see some other logs
    • localhost.YYYY-MM-DD.log
      • This log contains information about the server and the application on that server
      • We can see information like contextInitialized() and contextDestroyed()
      • Everytime we start or stop applications will be logged here as the context Initialized or Destroyed
    • localhost_access_log.YYYY-MM-DD.txt
      • This log contains information about the access from clients to our web application
      • Here we can see each and every action took place while navigating through the client. We can see the activities done through the client.
      • From this log we can log how many users accessing what information.
    • host-manager.YYYY-MM-DD.log
      • This log will say how and when the HostManager is accessed from the GUI
    • manager.YYYY-MM-DD.log
      • This log will say how and when the Manager App is accessed from the GUI

Sunday 23 July 2017

Tomcat13-Troubleshooting-Catalina-Logs

Troubleshooting Tomcat using Catalina log

  • We can get the catalina logs in $CATALINA_HOME/logs
  • Here we'll have a catalina.out
  • We can see some huge info in that log file. If we want to what exactly happens since the start of tomcat then we need to log that into a new file.
  • By default we have log rotation enabled on this logs.
  • For now let us stop tomcat and nullify the catalina.out file and then start tomcat to have some new info in the catalina.out
# service tomcat stop
# cd $CATALINA_HOME/logs
# :> catalina.out (or) cat /dev/null > catalina.out
# ll catalina.out
-rw-r----- 1 root root 0 Feb 18 16:19 catalina.out

# service tomcat start
# ll catalina.out
-rw-r----- 1 root root 17341 Feb 18 16:21 catalina.out
  • We can see the log being written after the start of tomcat.
  • Now we can notice the instance giving some information about the starting of tomcat, about the configuration for the startup, path of the servlet instance for which the log is responsible for, when the instance and the webapplications have started.
  • Also as we are not hosting any production applications on it we don't have any other information logged continuously to it as there is no running transaction on it.
  • And the last line in this log at this moment tells us how much time the tomcat instance has took to startup.
  • We can see how the issues can be logged in this log file.
  • As we previously configured another tomcat instance with some different port numbers let us change the config file of the first instance to use the connector port as 8010
  • Let us stop the tomcat instance, do the above change, start the second instance and then start the first instance.
     # cd $CATALINA_HOME
     # ./bin/catalina.sh stop
     # :> logs/catalina.out
     # vi conf/server.xml
    
    • Change port 8009 with 8010 and save the config file
     # cd $CATALINA_HOME2
     # ./bin/catalina.sh start
     # ps -ef | grep catalina | grep -v grep
     # cd $CATALINA_HOME
     # ./bin/catalina.sh start
     # ps -ef | grep catalina | grep -v grep
    
    • We can see 2 tomcat instances running, let us check the catalina.out log for the errors. We will see the following error in the log.
     18-Feb-2017 16:39:33.802 SEVERE [main] org.apache.catalina.core.StandardService.initInternal Failed to initialize connector [Connector
     [AJP/1.3-8010]]
     org.apache.catalina.LifecycleException: Failed to initialize component [Connector[AJP/1.3-8010]]
       at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:112)
       at org.apache.catalina.core.StandardService.initInternal(StandardService.java:549)
       at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:107)
       at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:875)
       at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:107)
       at org.apache.catalina.startup.Catalina.load(Catalina.java:606)
       at org.apache.catalina.startup.Catalina.load(Catalina.java:629)
       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
       at java.lang.reflect.Method.invoke(Method.java:498)
       at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:311)
       at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:494)
     Caused by: org.apache.catalina.LifecycleException: Protocol handler initialization failed
       at org.apache.catalina.connector.Connector.initInternal(Connector.java:970)
       at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:107)
       ... 12 more
     Caused by: java.net.BindException: Address already in use
       at sun.nio.ch.Net.bind0(Native Method)
       at sun.nio.ch.Net.bind(Net.java:433)
       at sun.nio.ch.Net.bind(Net.java:425)
       at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
       at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
       at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:210)
       at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:972)
       at org.apache.tomcat.util.net.AbstractJsseEndpoint.init(AbstractJsseEndpoint.java:237)
       at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:558)
       at org.apache.catalina.connector.Connector.initInternal(Connector.java:968)
       ... 13 more
    
    • Here we need to see the below lines
     org.apache.catalina.core.StandardService.initInternal Failed to initialize connector [Connector
         [AJP/1.3-8010]]
     Caused by: java.net.BindException: Address already in use
    
    • This tells us that the application is failed to initialize the AJP Connector Port on 8010 as it is addressed already in use
    • Now to fix this let us stop tomcat and change the port back to 8009 in the $CATALINA_HOME/conf/server.xml
    • After this start both the instances and can notice that we don't have any issues in either of the instance

Friday 21 July 2017

Tomcat12-Troubleshooting-Java-Exceptions

Troubleshooting Common Java Exceptions

  • Below is an example of NullPointer Exception
     Exception in thread "main" java.lang.NullPointerException
      at com.example.myproject.Object1.getValue(Object1.java:16)
      at com.example.myproject.Object2.getNumericValue(Object2.java:25)
      at com.example.myproject.Object3.main(Object3.java:14)
    
    • In this case we need to navigate to the file Object1 and review the method called getValue() to determine what happened
    • The remaining lines give the further information about how the exception was arrived at.
  • Most of the times we'll have something different to the above, but the above given can be taken as a basic example of how to find out the issue.
  • Let us look at the below log once
     Exception in thread "main" java.lang.NullPointerException
      at com.example.myproject.Object1.getValue(Object1.java:16)
      at com.example.myproject.Object2.getNumericValue(Object2.java:25)
      at com.example.myproject.Object3.main(Object3.java:14)
     Caused by: java.lang.IllegalReferenceException
      at com.example.myproject.Object1.getParentValue(Object1.java:22)
    
    • This means that we have a NullPointer exception in Object1 at the getValue() method occured as Object1 and getParentValue() method thrown a IllegalReferenceException and this is the initial cause of the problem.
    • If we have multiple Caused by sections then the lowest is the initial cause of the problem.

Thursday 20 July 2017

Tomcat11-Tuning-Tomcat-Ports

Tuning Tomcat Ports

  • To have the tomcat to be hosted in secured way we need to run it using the SSL certs.
  • By default we will have a section for this.
  • All we need to do is that we need to uncomment the Connector section with the SSL details.
  • In the same way we can change the port numbers to any other open port numbers.
  • We might need to change the port numbers to secure our tomcat application.

Wednesday 19 July 2017

Tomcat10-Basic-Clustering

Basic Clustering

  • Till now we have 1 tomcat instance running and now we'll learn how to loadbalance multiple tomcat instances.
  • For this let us have another tomcat instance configured first.
  • Go to the /opt directory and copy tomcat8 to tomcat8-n2
# cp -prv tomcat8 tomcat8-n2
  • Now we know that we are using some ports for tomcat say 8080, 8005, 8009
  • For our additional tomcat instance we need to change the ports. If we don't then we might need to experience port conflict
  • I am going to edit server.xml config file in the new node and increment the port numbers by 1
# cd /opt/tomcat8-n2/conf/
# vi server.xml

8005 -> 8006
8080 -> 8081
8443 -> 8444
8009 -> 8010
  • Now you need to add your new Catalina home, base and temp directories
  • First you need to change the catalina.sh script and redirect the above 3 variables to the new variables
  • Edit the catalina.sh script and add the following lines
# vi /opt/tomcat-n2/bin/catalina.sh

CATALINA_BASE=$CATALINA_BASE2
CATALINA_HOME=$CATALINA_HOME2
CATALINA_TMPDIR=$CATALINA_TMPDIR2
  • Now edit /etc/profile file and set our new directories
# vi /etc/profile

CATALINA_BASE2=/opt/tomcat8-n2
CATALINA_HOME2=/opt/tomcat8-n2
CATALINA_TMPDIR2=/opt/tomcat8-n2/temp
  • Now we need to edit /etc/nginx/vhost.d/default.conf file to add the upstream directive to loadbalance
  • Edit that file and add the following at the top of the file
upstream myTomcat {
 server localhost:8080;
 server localhost:8081;
}
  • Now we need to change the proxy_pass
proxy_pass http://myTomcat;

Saturday 15 July 2017

Tomcat09-Proxy-Connection

Proxy Connection for Tomcat

  • For proxy we are using Nginx, so let us install nginx
While installing nginx I got issue with "libunwind" package. So I've manually downloaded that package and installed it.
# wget ftp://195.220.108.108/linux/centos/7.3.1611/os/x86_64/Packages/libunwind-1.1-5.el7_2.2.x86_64.rpm && rpm -ivh libunwind-1.1-5.el7_2.2.x86_64.rpm

# yum install nginx -y
  • Now for our default configuration files let us have a directory
# cd /etc/nginx
# mkdir vhosts.d
  • Now we need to change the configuration as per our requirement
    • Find the include statement for the config files and add another for our new directory
    • After that remove the server definition under the include statement as we'll have it in our new config
# vi nginx.conf

 include /etc/nginx/vhost.d/*.conf;
  • Now lets go to the vhost.d directory and create a new config file
    • Copy the sample server definition after deleting the existing server definition in the main config file
    • Paste it in the new config file and modify as per your requirements
# cd vhost.d/
# vi default.conf

server {
 listen 80;

 root /opt/tomcat8/webapps/hello/;
 index index.php index.html index.htm;

 server_name localhost;

 location / {
  try_files $uri $uri/ /index.html;
 }

 location ~ \.php$ {
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $remote_addr;
  proxy_set_header Host $host;
  proxy_pass http://127.0.0.1:8080;
 }

 location ~ /\.ht {
  deny all;
 }
}
  • Start Nginx
  • Verify that you are able to hit the webapps/hello without any issue.
# elinks http://localhost

Friday 7 July 2017

Tomcat08-Deploying_WebApp

Deploying Web Application on Tomcat

  • For deploying a web application oon tomcat we should have .war file of the application
  • Once we have the .war file then we need to put it in webapps directory
  • After copying the .war file restart tomcat
  • Another way of deploying application on tomcat is through the Manager GUI
  • Go to the deploy section
  • Browse and select your application
  • Click on Deploy
  • Now to use your application you need to use your url like below
http://< IP / HOSTNAME of Tomcat >:<PORT>/<APPLICATION_NAME_WITHOUT_WAR EXTENSION>

Ex:

http://dev02.linux-library.com:8080/jenkins

Friday 28 April 2017

Tomcat07-Security-and-User-Accounts

Security and User Accounts

  • If we need to access the Tomcat WebApplications then we need to setup some user accounts.
  • For this we need to edit the conf/tomcat-users.xml
  • At the bottom of this file we can find some roles and user accounts
  • Let us add some new roles and users now
    • Adding tomcat,manager, manager-gui, admin-gui roles
     <role rolename="tomcat"/>
     <role rolename="manager"/>
     <role rolename="manager-gui"/>
     <role rolename="admin-gui"/>
    
    • Adding admintom user
     <user username="admintom" password="s3cret" roles="manager,manager-gui,admin-gui"/>
    
  • Now setting up your Hostname / IP to your server instead of localhost
    • Open conf/server.xml and edit the following lines to add your Hostname
     Find the line starts with Engine and change the value of defaultHost
     <Engine name="Catalina" defaultHost="dev02.linux-library.com">
     
     Find the line starts with Host change the value of name to your hostname same as above
     <Host name="dev02.linux-library.com"  appBase="webapps"
    
  • If you want to access the tomcat manager from other than your local machine then you need to allow those IP ranges
    • To allow IPs to access manager edit webapps/manager/META-INF/context.xml file
    NOTE: If you want to access the app from a host of Class-A IP then you should add 10.\d+.\d+.\d+ to the allow directive That should look like below. I have allowed Class-A as well as Class-C ranges
     allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1|10\.\d+\.\d+\.\d+|192\.168\.1\.\d+" />
    
    • In the same way you can allow access to you hostmanager too.
    • Open webapps/host-manager/META-INF/context.xml and edit same as above