<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lakshan Dissanayake</title>
    <description>The latest articles on DEV Community by Lakshan Dissanayake (@lakshanwd).</description>
    <link>https://dev.to/lakshanwd</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F499858%2Ff13280a0-95e0-43c1-a637-dc34fa5d7361.jpeg</url>
      <title>DEV Community: Lakshan Dissanayake</title>
      <link>https://dev.to/lakshanwd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lakshanwd"/>
    <language>en</language>
    <item>
      <title>OpenTelemetry</title>
      <dc:creator>Lakshan Dissanayake</dc:creator>
      <pubDate>Thu, 20 Jun 2024 19:06:40 +0000</pubDate>
      <link>https://dev.to/lakshanwd/opentelemetry-k4o</link>
      <guid>https://dev.to/lakshanwd/opentelemetry-k4o</guid>
      <description>&lt;h2&gt;
  
  
  What is OpenTelemetry?
&lt;/h2&gt;

&lt;p&gt;OpenTelemetry is an open-source project that provides a set of APIs, libraries, agents, and instrumentation to enable observability in software applications. Tracing is one of the core features of OpenTelemetry, which helps in tracking the execution of operations within and across services. &lt;/p&gt;

&lt;h2&gt;
  
  
  What is OpenTelemetry Tracing?
&lt;/h2&gt;

&lt;p&gt;OpenTelemetry tracing is a way to capture and visualise the flow of requests as they traverse through different components of a distributed system. It allows developers to understand how different parts of an application interact and identify performance bottlenecks, errors, and latency issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Concepts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;h4&gt;
  
  
  Trace
&lt;/h4&gt;

&lt;p&gt;A trace represents the entire journey of a request as it moves through a system. It consists of a series of spans that are linked together.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h4&gt;
  
  
  Span
&lt;/h4&gt;

&lt;p&gt;A span represents a single operation within a trace. It contains information such as the operation name, start and end timestamps, attributes (metadata), and references to other spans (parent/child relationships).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h4&gt;
  
  
  Context Propagation
&lt;/h4&gt;

&lt;p&gt;Context propagation allows trace context to be passed along with requests as they move through different services and components. This ensures that spans are correctly linked together to form a complete trace.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h4&gt;
  
  
  Sampling
&lt;/h4&gt;

&lt;p&gt;Sampling determines which traces are collected and reported. It helps control the volume of trace data, balancing the need for observability with resource constraints.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How OpenTelemetry Tracing Works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;h4&gt;
  
  
  Instrumentation
&lt;/h4&gt;

&lt;p&gt;OpenTelemetry provides instrumentation libraries for various programming languages and frameworks. These libraries automatically capture trace data for common operations like HTTP requests, database queries, and more.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h4&gt;
  
  
  Context Injection
&lt;/h4&gt;

&lt;p&gt;When a request enters a service, OpenTelemetry injects trace context into the request headers. This context is propagated through downstream services, ensuring that all operations related to the initial request are included in the same trace.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h4&gt;
  
  
  Span Creation
&lt;/h4&gt;

&lt;p&gt;Each operation within a service creates a new span. Developers can create custom spans to capture additional operations or specific code blocks.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h4&gt;
  
  
  Trace Exporting
&lt;/h4&gt;

&lt;p&gt;Collected trace data is exported to a backend for analysis. OpenTelemetry supports various backends, including Jaeger, Zipkin, Prometheus, and more. The exported data can be visualised to understand request flows and identify issues.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Benefits of OpenTelemetry Tracing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;h4&gt;
  
  
  End-to-End Visibility
&lt;/h4&gt;

&lt;p&gt;Provides a comprehensive view of how requests are processed across different services, helping to identify bottlenecks and improve performance.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h4&gt;
  
  
  Error Detection
&lt;/h4&gt;

&lt;p&gt;Helps in identifying and diagnosing errors by showing where they occur in the request flow.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h4&gt;
  
  
  Performance Optimisation
&lt;/h4&gt;

&lt;p&gt;By measuring the latency of different operations, developers can pinpoint and optimise slow parts of the system.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h4&gt;
  
  
  Improved Debugging
&lt;/h4&gt;

&lt;p&gt;Detailed trace data makes it easier to debug complex issues that involve multiple services.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>golang unit testing</title>
      <dc:creator>Lakshan Dissanayake</dc:creator>
      <pubDate>Sat, 03 Sep 2022 17:14:51 +0000</pubDate>
      <link>https://dev.to/lakshanwd/golang-unit-testing-39ib</link>
      <guid>https://dev.to/lakshanwd/golang-unit-testing-39ib</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Test driven development also known as TDD is a good software development practice followed by all over the software industry. With unit tests we can test a small pieces of our software independently what makes it "unit".&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;Let's assume you're making some changes to a function which was developed by someone else previously. with the developer test you might think, it is safe to deploy. But what will happen if you missed a specific test scenario? probably it will lead to a software crash if exceptions are not properly handled. panics in go's context.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;If we have already developed unit tests, then we can run it to test whether we broke the code or not. It will execute a list of specific scenarios of the software and shows if some flows are broken. if there is not unit test, I &lt;strong&gt;highly recommend&lt;/strong&gt; you to implement it first, then do the changes to the function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Libraries we can use to write unit tests
&lt;/h2&gt;

&lt;p&gt;I use &lt;a href="https://github.com/golang/mock"&gt;gomock&lt;/a&gt; or &lt;a href="https://github.com/vektra/mockery"&gt;mockery&lt;/a&gt; for mocking the interfaces and &lt;a href="https://github.com/stretchr/testify"&gt;testify&lt;/a&gt; for evaluating tests&lt;/p&gt;

&lt;p&gt;Let'a have a look how its implemented&lt;/p&gt;

&lt;p&gt;Sms Provider&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Email Provider&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;And suppose notification service, which validates phone numbers and email and calls sms provider and email provider to send actual email and test messages&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The unit tests of the notification service can be written as the following&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


</description>
      <category>go</category>
      <category>unittest</category>
      <category>tdd</category>
    </item>
    <item>
      <title>golang multithreading</title>
      <dc:creator>Lakshan Dissanayake</dc:creator>
      <pubDate>Mon, 02 May 2022 20:07:57 +0000</pubDate>
      <link>https://dev.to/lakshanwd/golang-multi-threading-1iod</link>
      <guid>https://dev.to/lakshanwd/golang-multi-threading-1iod</guid>
      <description>&lt;p&gt;In my workplace, client had reported a performance bottle-neck and as a resolution, I was assigned to identify the bottleneck and make necessary changes to make it more efficient. After some time investing the logs, I had found the root cause and it was due to the repetitive occurrence of some time-consuming activity, which ultimately impacted on the response time.&lt;/p&gt;

&lt;p&gt;After some workaround, I decided to execute the time consuming operations asynchronously and wait for the execution of asynchronous work and aggregate the final results. Here I found 3 ways to do this.&lt;/p&gt;

&lt;p&gt;go-routines are light weight wrappers for threads, they will do the work using a pool of threads internally. &lt;/p&gt;

&lt;h3&gt;
  
  
  The Bad way
&lt;/h3&gt;

&lt;p&gt;TLDR: Execute jobs synchronously.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
This is a bad way of doing asynchronous work since it blocks main thread and execute jobs synchronously.  

&lt;h3&gt;
  
  
  The Normal way
&lt;/h3&gt;

&lt;p&gt;TLDR: Execute jobs asynchronously, but number of parallel jobs are uncontrolled&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
In here, &lt;code&gt;sync.WaitGroup&lt;/code&gt; is controlling the execution of background thread and it waits till the atomic counter of waitGroup is reduced to zero, which indicates all the routines have been executed. The problem with this approach is, if we get a large number of jobs in job array, there will be that number of go-routines which consumes resources.  

&lt;h3&gt;
  
  
  The Better Way
&lt;/h3&gt;

&lt;p&gt;TLDR: Execute jobs asynchronously and number of parallel jobs are &lt;strong&gt;controlled&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;br&gt;
This approach will do the work in a controlled parallel manner. So at any given time, it will use &lt;code&gt;max&lt;/code&gt; number of go-routines to execute the jobs parallelly and will consumes less resources.

</description>
      <category>go</category>
      <category>concurrency</category>
      <category>parallelism</category>
    </item>
    <item>
      <title>implementing retry mechanism in rmq</title>
      <dc:creator>Lakshan Dissanayake</dc:creator>
      <pubDate>Fri, 29 Apr 2022 12:13:06 +0000</pubDate>
      <link>https://dev.to/lakshanwd/use-rmq-with-retry-mechanism-5c15</link>
      <guid>https://dev.to/lakshanwd/use-rmq-with-retry-mechanism-5c15</guid>
      <description>&lt;p&gt;Rabbit MQ is an opensource message broker. We can publish messages to exchanges and queues can be bound to exchange with routing keys. Consumers will consume the payloads from the queues and so the application will work as intended.&lt;/p&gt;

&lt;p&gt;Lets assume for some reason application couldn't process the payload and it rejects it, and we need to retry it with some delay? This is not rocket science, but lemme show you how I would have done it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q0inqWKd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aqf4smzov4nf168slr28.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q0inqWKd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aqf4smzov4nf168slr28.jpg" alt="Image description" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pre-Conditions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;q_work&lt;/code&gt; is bounded to &lt;code&gt;ex_main&lt;/code&gt; with &lt;code&gt;rk_work&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;DLX of &lt;code&gt;q_work&lt;/code&gt; is &lt;code&gt;ex_retry&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;DLX Routing Key of &lt;code&gt;q_work&lt;/code&gt; is &lt;code&gt;work&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;q_retry_work&lt;/code&gt; is bounded to &lt;code&gt;ex_retry&lt;/code&gt; with &lt;code&gt;rk_work&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;DLX of &lt;code&gt;q_retry_work&lt;/code&gt; is &lt;code&gt;ex_main&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;DLX Routing Key of &lt;code&gt;q_retry_work&lt;/code&gt; is &lt;code&gt;work&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;TTL of the &lt;code&gt;q_retry_work&lt;/code&gt; is &lt;code&gt;30s&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Producers publishes messages to &lt;code&gt;ex_main&lt;/code&gt;. &lt;br&gt;
Messages with &lt;code&gt;rk_work&lt;/code&gt; routing key is immediately pushed to &lt;code&gt;q_work&lt;/code&gt;. &lt;br&gt;
The application will consume or reject messages. &lt;br&gt;
Rejected messages are dropped to &lt;code&gt;ex_retry&lt;/code&gt; and messages with &lt;code&gt;rk_work&lt;/code&gt; will immediately pushed to &lt;code&gt;q_retry_work&lt;/code&gt;.&lt;br&gt;
Since no one is consuming from &lt;code&gt;q_retry_work&lt;/code&gt; and after 30s it will dropped the messages to its DLX, which is &lt;code&gt;ex_main&lt;/code&gt;. &lt;/p&gt;

</description>
      <category>rabbitmq</category>
      <category>dlx</category>
    </item>
    <item>
      <title>Pipenv and Django</title>
      <dc:creator>Lakshan Dissanayake</dc:creator>
      <pubDate>Tue, 26 Apr 2022 15:17:39 +0000</pubDate>
      <link>https://dev.to/lakshanwd/pipenv-and-django-4lkf</link>
      <guid>https://dev.to/lakshanwd/pipenv-and-django-4lkf</guid>
      <description>&lt;h2&gt;
  
  
  How to setup pipenv for django
&lt;/h2&gt;

&lt;p&gt;pipenv is a tool that allows you to create virtual environments and manage python dependencies effectively. If you need more information regarding pipenv, Read this&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Django&lt;/strong&gt; is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Built by experienced developers, it takes care of much of the hassle of Web development, so you can focus on writing your app without needing to reinvent the wheel. It’s free and open source. Ridiculously fast.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#setup&lt;/span&gt;
&lt;span class="c"&gt;# create solution directory&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;my-first-django-project 
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;my-first-django-project
&lt;span class="c"&gt;# install pipenv&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;pipenv
&lt;span class="c"&gt;# installs django framework&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;pipenv &lt;span class="nb"&gt;install &lt;/span&gt;django
&lt;span class="c"&gt;# create django project&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;pipenv run django-admin startproject project &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="c"&gt;# initialize django app&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;pipenv run django-admin startapp app
&lt;span class="c"&gt;# fire-up python web browser&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;pipenv run python manage.py runserver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>django</category>
      <category>pipenv</category>
      <category>python</category>
    </item>
    <item>
      <title>Server monitoring with Zabbix</title>
      <dc:creator>Lakshan Dissanayake</dc:creator>
      <pubDate>Tue, 26 Apr 2022 15:13:31 +0000</pubDate>
      <link>https://dev.to/lakshanwd/server-monitoring-with-zabbix-3f8j</link>
      <guid>https://dev.to/lakshanwd/server-monitoring-with-zabbix-3f8j</guid>
      <description>&lt;p&gt;We were developing a shopping cart application for a client using WordPress. During the development, we faced an occasional server not responding situation. So we wanted to monitor the availability of the Linux server.&lt;/p&gt;

&lt;p&gt;After several hours of searching and exploring, we found several server monitoring solutions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.nagios.com/"&gt;Nagios&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.zabbix.com/"&gt;Zabbix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.cacti.net/"&gt;Cacti&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.opennms.org/en"&gt;OpenNMS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.icinga.com/"&gt;Icinga&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://netdata/"&gt;Netdata&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Zabbix was the obvious choice for us as we were seeking for an open-source monitoring solution. It was quite easy and could able to get online pretty soon. Just go through the installation instructions of Zabbix and get your servers monitored.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cY2LQjdr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o7dhdsd1s8byb2uxv1fr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cY2LQjdr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o7dhdsd1s8byb2uxv1fr.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>servermonitoring</category>
      <category>zabbix</category>
      <category>systemadmin</category>
    </item>
    <item>
      <title>Golang Job Queue Implementation</title>
      <dc:creator>Lakshan Dissanayake</dc:creator>
      <pubDate>Tue, 26 Apr 2022 15:01:50 +0000</pubDate>
      <link>https://dev.to/lakshanwd/golang-job-queue-implementation-580p</link>
      <guid>https://dev.to/lakshanwd/golang-job-queue-implementation-580p</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;A friend of mine asked me to implement a job-queue. As I was new to Golang at that time I was curious and talked with the friend and also browsed the internet and read the purpose of a job queue.&lt;/p&gt;

&lt;h3&gt;
  
  
  Eliminate performance bottlenecks
&lt;/h3&gt;

&lt;p&gt;During the research time, I found using JSON is causing a huge impact on performance. The solution was to use gRPC with Protobuf. I used a channel with size with several thousand as the main queue. Since there is limited no of worker machines, I needed to utilize the processor with maximum efficiency to get the jobs done quickly. So each worker machine takes job parameters from the main queue and stores them in their own queue which allows making the room for new requests in the main queue.&lt;/p&gt;

&lt;p&gt;These worker machines are equipped with several Goroutines. Each Goroutine takes job parameters from its own worker machine and executes the job.&lt;br&gt;
Even though Goroutines are extremely light-weight thread like programs, using millions of Goroutines won’t result in the optimal utilisation of resources. Please read this article.&lt;/p&gt;

&lt;p&gt;My approach to the job-queue implementation&lt;br&gt;
The central server application listens to client requests and put them into the main queue. Several worker machines take job parameters from the main queue and store them on their own queue. Each worker machine is equipped with several small processes whose sole task is to execute the job parameters which are extracted from the queue in the worker machine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Artifacts
&lt;/h3&gt;

&lt;p&gt;Let the no of worker machines to be m and the no of Goroutines each worker machine runs to be n, on maximum resource utilisation, the applications execute m x n concurrent jobs at any given time.&lt;/p&gt;

&lt;h4&gt;
  
  
  Source Code
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://gitlab.com/lakshanwd/go-job-queue"&gt;https://gitlab.com/lakshanwd/go-job-queue&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>grpc</category>
      <category>jobqueue</category>
    </item>
    <item>
      <title>Configure CentOS to host WordPress with Nginx</title>
      <dc:creator>Lakshan Dissanayake</dc:creator>
      <pubDate>Wed, 04 Nov 2020 10:13:08 +0000</pubDate>
      <link>https://dev.to/lakshanwd/configure-centos-to-host-wordpress-with-nginx-2ld2</link>
      <guid>https://dev.to/lakshanwd/configure-centos-to-host-wordpress-with-nginx-2ld2</guid>
      <description>&lt;p&gt;I’ve been told to set up a WordPress installation on a CentOS server. While most of CentOS based WordPress hosting providers offer cPanel, I had thoughts of writing a tutorial regarding configuring a server from zero.&lt;/p&gt;

&lt;p&gt;A WordPress site consists of 3 main parts&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PHP Interpreter&lt;/li&gt;
&lt;li&gt;Database&lt;/li&gt;
&lt;li&gt;Web Server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s walk through the tutorial and find out what each of these does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup MariaDB
&lt;/h2&gt;

&lt;p&gt;Even though WordPress is written in PHP, it needs a MySQL/MariaDB database for its functionality. So we’ll choose MariaDB as our SQL database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install MariaDB
&lt;/h3&gt;

&lt;p&gt;CentOS is packed with an old version of MariaDB which impacts on overall performance. So let’s update the MariaDB source repository configurations and install it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# install mariadb-server&lt;/span&gt;
wget https://downloads.mariadb.com/MariaDB/mariadb_repo_setup
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x mariadb_repo_setup 
&lt;span class="nb"&gt;sudo&lt;/span&gt; ./mariadb_repo_setup
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install &lt;/span&gt;mariadb-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure MariaDB
&lt;/h3&gt;

&lt;p&gt;You need a database and properly configured MySQL user for the access of the database. let’s create a database and user.&lt;/p&gt;

&lt;p&gt;Even though you can use MySQL root for WordPress, I strongly discourage you to do so. Because if somehow your password gets compromised, You’ll compromise other databases on your host as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# configure mariadb to start automatically upon system boot&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;mariadb.service
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart mariadb.service
&lt;span class="c"&gt;# enhance security by setting up root password and other enhancements&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;mysql_secure_installation
&lt;span class="c"&gt;# login to mysql&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;mysql &lt;span class="nt"&gt;-u&lt;/span&gt; root
&lt;span class="c"&gt;# create database&lt;/span&gt;
mysql &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c"&gt;# create user&lt;/span&gt;
mysql &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; grant all privileges on wordpress.&lt;span class="k"&gt;*&lt;/span&gt; to &lt;span class="s1"&gt;'wp_user'&lt;/span&gt;@&lt;span class="s1"&gt;'localhost'&lt;/span&gt; identified by &lt;span class="s1"&gt;'secure-password'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
mysql &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; flush privileges&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Setup PHP and Nginx
&lt;/h2&gt;

&lt;p&gt;We need a PHP interpreter to render raw HTML from PHP scripts and we also need a webserver to serve those. Since we’re seeking for an open-source server solution with robust speed there are several server solutions. For the purpose of this demonstration, we will Nginx as the webserver.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Nginx and PHP
&lt;/h3&gt;

&lt;p&gt;By default, Nginx is not listed in CentOS software repository and also the PHP version it bears is an old one. So let’s update the software repositories and install Nginx and PHP with other dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# setup required repositories for Nginx/PHP&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; epel-release
&lt;span class="c"&gt;# setup required repositories for php74-php-fpm&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;https://rpms.remirepo.net/enterprise/remi-release-7.rpm
&lt;span class="c"&gt;# install Nginx&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; nginx
&lt;span class="c"&gt;# install PHP&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; php74-php-fpm php74-php-mysqlnd php74-php-mbstring php74-php-zip php74-php-gd php74-php-imagick php74-php-xml
&lt;span class="c"&gt;# enable and restart nginx php74-php-fpm services&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;nginx php74-php-fpm
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart nginx php74-php-fpm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PHP and Nginx are been installed successfully at this point. But we need to change some configurations of PHP and Nginx as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure PHP
&lt;/h3&gt;

&lt;p&gt;Edit the /etc/opt/remi/php74/php.ini and make the following changes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# uncomment cgi.fix_pathinfo and change the value to 0
&lt;/span&gt;&lt;span class="py"&gt;cgi.fix_pathinfo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;0&lt;/span&gt;
&lt;span class="c"&gt;# change the value of post_max_size
&lt;/span&gt;&lt;span class="py"&gt;post_max_size&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;64M&lt;/span&gt;
&lt;span class="c"&gt;# change the value of upload_max_filesize
&lt;/span&gt;&lt;span class="py"&gt;upload_max_filesize&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;32M&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit the /etc/opt/remi/php74/php-fpm.d/&lt;a href="http://www.conf"&gt;www.conf&lt;/a&gt; as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# change  the user to nginx
&lt;/span&gt;&lt;span class="py"&gt;user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
&lt;span class="c"&gt;# change  the group to nginx
&lt;/span&gt;&lt;span class="py"&gt;group&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
&lt;span class="c"&gt;# uncomment and change  the listen.owner to nginx
&lt;/span&gt;&lt;span class="py"&gt;listen.owner&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
&lt;span class="c"&gt;# uncomment and change  the listen.group to nginx
&lt;/span&gt;&lt;span class="py"&gt;listen.group&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
&lt;span class="c"&gt;# change listen as follows
&lt;/span&gt;&lt;span class="py"&gt;listen&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/run/php74-fpm.sock&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Download WordPress
&lt;/h3&gt;

&lt;p&gt;Let’s take a fresh build of WordPress from the WordPress site and extract it where you want your site to be located.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# download latest WordPress build&lt;/span&gt;
wget https://wordpress.org/latest.tar.gz
&lt;span class="nb"&gt;sudo tar&lt;/span&gt; &lt;span class="nt"&gt;-xzf&lt;/span&gt; latest.tar.gz &lt;span class="nt"&gt;-C&lt;/span&gt; /path/to/web-site
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change the ownership of extracted WordPress files&lt;br&gt;
Changing the ownership of the WordPress files to the PHP user is an absolute requirement. Otherwise, PHP interpreter won’t be able to access those files and you face issues with rendering PHP.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# change the owner of the website to nginx&lt;/span&gt;
&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; nginx:nginx /path/to/web-site
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set SELinux permissions
&lt;/h3&gt;

&lt;p&gt;Since SELinux bundled with CentOS, We’ll have to let SELinux knows that the extracted files will be read and written. Execute the following to do so.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;setenforce 1
&lt;span class="c"&gt;# enable content readable by php-fpm&lt;/span&gt;
&lt;span class="nb"&gt;sudo chcon&lt;/span&gt; &lt;span class="nt"&gt;-Rt&lt;/span&gt; httpd_sys_content_t /path/to/web-site
&lt;span class="c"&gt;#enable content writable by php-fpm&lt;/span&gt;
&lt;span class="nb"&gt;sudo chcon&lt;/span&gt; &lt;span class="nt"&gt;-Rt&lt;/span&gt; httpd_sys_rw_content_t /path/to/web-site/wrirable-dir
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure Nginx
&lt;/h2&gt;

&lt;p&gt;Create the following directories&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# holds all (active / inactive) site configurations&lt;/span&gt;
&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /etc/nginx/sites-available
&lt;span class="c"&gt;# holds Nginx active site configurations&lt;/span&gt;
&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /etc/nginx/sites-enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit /etc/nginx/nginx.conf and put the following content at the end of http block&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# enable gzip compression
&lt;/span&gt;&lt;span class="err"&gt;gzip&lt;/span&gt;              &lt;span class="err"&gt;on&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;&lt;span class="err"&gt;gzip_buffers&lt;/span&gt;      &lt;span class="err"&gt;16&lt;/span&gt; &lt;span class="err"&gt;8k&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;&lt;span class="err"&gt;gzip_comp_level&lt;/span&gt;   &lt;span class="err"&gt;5&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;&lt;span class="err"&gt;gzip_http_version&lt;/span&gt; &lt;span class="err"&gt;1.0&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;&lt;span class="err"&gt;gzip_min_length&lt;/span&gt;   &lt;span class="err"&gt;10240&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;&lt;span class="err"&gt;gzip_types&lt;/span&gt;        &lt;span class="err"&gt;text/plain&lt;/span&gt; &lt;span class="err"&gt;text/css&lt;/span&gt; &lt;span class="err"&gt;application/x-javascript&lt;/span&gt; &lt;span class="err"&gt;text/xml&lt;/span&gt; &lt;span class="err"&gt;application/xml&lt;/span&gt; &lt;span class="err"&gt;application/xml+rss&lt;/span&gt; &lt;span class="err"&gt;text/javascript&lt;/span&gt; &lt;span class="err"&gt;image/x-icon&lt;/span&gt; &lt;span class="err"&gt;image/bmp&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;&lt;span class="err"&gt;gzip_vary&lt;/span&gt;         &lt;span class="err"&gt;on&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;&lt;span class="err"&gt;gzip_proxied&lt;/span&gt; &lt;span class="err"&gt;expired&lt;/span&gt; &lt;span class="err"&gt;no-cache&lt;/span&gt; &lt;span class="err"&gt;no-store&lt;/span&gt; &lt;span class="err"&gt;private&lt;/span&gt; &lt;span class="err"&gt;auth&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;&lt;span class="err"&gt;gzip_disable&lt;/span&gt; &lt;span class="err"&gt;"MSIE&lt;/span&gt; &lt;span class="nn"&gt;[1-6]&lt;/span&gt;&lt;span class="err"&gt;\."&lt;/span&gt;&lt;span class="c"&gt;;
# per site configurations
&lt;/span&gt;&lt;span class="err"&gt;include&lt;/span&gt; &lt;span class="err"&gt;/etc/nginx/sites-enabled/*&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create an empty file in /etc/nginx/sites-available/my.domain.tld and put the following content&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="err"&gt;server&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;server_name&lt;/span&gt; &lt;span class="err"&gt;my.domain.tld&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;root&lt;/span&gt; &lt;span class="err"&gt;/path/to/web-site&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;index&lt;/span&gt; &lt;span class="err"&gt;index.php&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;error_log&lt;/span&gt; &lt;span class="err"&gt;/var/log/nginx/my.domain.tld/error.log&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;access_log&lt;/span&gt; &lt;span class="err"&gt;/var/log/nginx/my.domain.tld/access.log&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="py"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/favicon.ico {&lt;/span&gt;
        &lt;span class="err"&gt;log_not_found&lt;/span&gt; &lt;span class="err"&gt;off&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;        &lt;span class="err"&gt;access_log&lt;/span&gt; &lt;span class="err"&gt;off&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;}&lt;/span&gt;
    &lt;span class="py"&gt;location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/robots.txt {&lt;/span&gt;
        &lt;span class="err"&gt;allow&lt;/span&gt; &lt;span class="err"&gt;all&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;        &lt;span class="err"&gt;log_not_found&lt;/span&gt; &lt;span class="err"&gt;off&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;        &lt;span class="err"&gt;access_log&lt;/span&gt; &lt;span class="err"&gt;off&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;location&lt;/span&gt; &lt;span class="err"&gt;/&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
        &lt;span class="err"&gt;try_files&lt;/span&gt; &lt;span class="err"&gt;$uri&lt;/span&gt; &lt;span class="err"&gt;$uri/&lt;/span&gt; &lt;span class="err"&gt;/index.php?$args&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;location&lt;/span&gt; &lt;span class="err"&gt;~&lt;/span&gt; &lt;span class="err"&gt;\.php$&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
        &lt;span class="err"&gt;include&lt;/span&gt; &lt;span class="err"&gt;fastcgi.conf&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;        &lt;span class="err"&gt;fastcgi_intercept_errors&lt;/span&gt; &lt;span class="err"&gt;on&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;        &lt;span class="err"&gt;fastcgi_pass&lt;/span&gt; &lt;span class="err"&gt;unix:/run/php74-fpm.sock&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;location&lt;/span&gt; &lt;span class="err"&gt;~*&lt;/span&gt; &lt;span class="err"&gt;\.(js|css|png|jpg|jpeg|gif|ico)$&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
        &lt;span class="err"&gt;expires&lt;/span&gt; &lt;span class="err"&gt;max&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;        &lt;span class="err"&gt;log_not_found&lt;/span&gt; &lt;span class="err"&gt;off&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;client_max_body_size&lt;/span&gt; &lt;span class="err"&gt;64M&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;listen&lt;/span&gt; &lt;span class="err"&gt;443&lt;/span&gt; &lt;span class="err"&gt;ssl&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;listen&lt;/span&gt; &lt;span class="nn"&gt;[::]&lt;/span&gt;&lt;span class="err"&gt;:443&lt;/span&gt; &lt;span class="err"&gt;ssl&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;ssl_certificate&lt;/span&gt; &lt;span class="err"&gt;/etc/ssl/my.domain.tld-certs/certificate.pem&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="err"&gt;/etc/ssl/my.domain.tld-certs/privatekey.pem&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;server&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;if&lt;/span&gt; &lt;span class="err"&gt;($&lt;/span&gt;&lt;span class="py"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;my.domain.tld) {&lt;/span&gt;
        &lt;span class="err"&gt;return&lt;/span&gt; &lt;span class="err"&gt;301&lt;/span&gt; &lt;span class="err"&gt;https://$host$request_uri&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt;server_name&lt;/span&gt; &lt;span class="err"&gt;my.domain.tld&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;listen&lt;/span&gt; &lt;span class="err"&gt;80&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;listen&lt;/span&gt; &lt;span class="nn"&gt;[::]&lt;/span&gt;&lt;span class="err"&gt;:80&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;    &lt;span class="err"&gt;return&lt;/span&gt; &lt;span class="err"&gt;404&lt;/span&gt;&lt;span class="c"&gt;;
&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Link the configuration to Nginx&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# activate the site&lt;/span&gt;
&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /etc/nginx/sites-available/my.domain.tld /etc/nginx/sites-enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reload Nginx and PHP
&lt;/h2&gt;

&lt;p&gt;Let’s restart the Nginx and PHP services.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# restart nginx and php-fpm&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart php74-php-fpm nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Congratulations
&lt;/h3&gt;

&lt;p&gt;Yay!!! You have successfully configured a CentOS server with PHP and Nginx. There are a lot more configurations that we didn’t even talk about in this tutorial. Just browse and look at the official documentation of Nginx, PHP and SELinux.&lt;/p&gt;

&lt;p&gt;Don’t forget to strength up your server by implementing a Firewall. So if you have done everything correctly, with a proper DNS direction, your site should be online by now.&lt;/p&gt;

</description>
      <category>php</category>
      <category>nginx</category>
      <category>centos</category>
      <category>wordpress</category>
    </item>
  </channel>
</rss>
