YouTube2Text

How to Deploy, Secure, and Automate Full-Stack Web Apps – Course for Beginners — Transcript

by freeCodeCamp.org · 100,405 words · 13,243 segments · language en · Watch on YouTube

Full transcript

  1. 0:00Taking a web application from local
  2. 0:01development to a live secure production
  3. 0:04environment can be daunting if you've
  4. 0:06never looked under the hood. In this
  5. 0:09comprehensive step-by-step course, you
  6. 0:12will learn to manually configure an
  7. 0:15Ubuntu server, set up essential runtimes
  8. 0:18and search services, and establish
  9. 0:21automated CI/CD pipelines. By doing
  10. 0:24everything hands-on before introducing
  11. 0:27automation, you will gain a deep
  12. 0:29foundational understanding of full stack
  13. 0:32deployment and how to reliably host
  14. 0:35complex systems. Immad Sadi developed
  15. 0:38this course. Hi everyone, I hope you are
  16. 0:41all doing great. In this course, we are
  17. 0:44going to talk about full stack
  18. 0:46deployment. This is a long course but
  19. 0:49trust me if you stick around and follow
  20. 0:52each chapter slowly you will learn a lot
  21. 0:55of things because I try to do things
  22. 0:57manually and to go step by step even if
  23. 1:00you haven't tried anything and the
  24. 1:03problem that here that I'm trying to
  25. 1:05solve and that I will try to teach you
  26. 1:07is how to take a web application that
  27. 1:09you have developed locally and deploy
  28. 1:12it. I have done this exercise three
  29. 1:14times for websites that I developed for
  30. 1:17myself and that I deployed for users to
  31. 1:20use and I will try to teach you all the
  32. 1:22things that I have learned across
  33. 1:24different domains. So let's look at the
  34. 1:27slides and let's see what we will learn.
  35. 1:30Let's define the problem in detail.
  36. 1:32First you have your web application.
  37. 1:35That's the prerequisite for watching
  38. 1:37this course. You can develop it using
  39. 1:40Python, Vue.js JS or other web
  40. 1:42frameworks and you want this application
  41. 1:45to be used. Here we have users so they
  42. 1:49they need to access the web application
  43. 1:51but they can't because you are running
  44. 1:54it locally on your laptop so they can't
  45. 1:57access it. What do you need to do? You
  46. 1:59need to take your source code and deploy
  47. 2:02it somewhere. So this is what we call
  48. 2:04the production environment. Here you
  49. 2:07rent a server where you can launch your
  50. 2:10application code. You can use platforms
  51. 2:13like Digital Ocean, Cloudflare,
  52. 2:16Lenode or others. There are plenty of
  53. 2:18platforms that we can use. And now your
  54. 2:22users can access the application that
  55. 2:24you have deployed and they are going to
  56. 2:26be happy. This is the problem. How do we
  57. 2:29do this? We have the web application. So
  58. 2:31we need a few steps to follow in order
  59. 2:34to deploy the web application and this
  60. 2:37is exactly the problem that we are going
  61. 2:38to solve in this course. What is the
  62. 2:41solution? In our case, we are going to
  63. 2:44rent as I said a server from let's say
  64. 2:48digital ocean, but you can do the same
  65. 2:51thing with other platforms. And this
  66. 2:54server can be either virtual or
  67. 2:56physical. We are going to explain this
  68. 2:57later. And some of these managed
  69. 2:59platforms simplify the process for us.
  70. 3:02So for example, you can have your code
  71. 3:04on GitHub and you just connect it to
  72. 3:07this to one of these platforms and they
  73. 3:09will deploy the code for you. You have
  74. 3:11platforms like Netlifi, Cloudflare,
  75. 3:15Lenode as I said and others. But the
  76. 3:18problem if you are a beginner and go
  77. 3:20directly to one of these managed
  78. 3:22platforms is that you won't understand
  79. 3:25exactly what is happening under the hood
  80. 3:28because they have a layer of abstraction
  81. 3:30that removes all the burden and all of
  82. 3:34the things that you need to configure
  83. 3:35manually. And this is great for people
  84. 3:38that have the experience with Linux and
  85. 3:41have deployed things manually across the
  86. 3:44years. But if you are be a beginner, I
  87. 3:47will highly suggest to not start with
  88. 3:49these platforms and try to do things
  89. 3:51manually to understand what is happening
  90. 3:54because transitioning from a manual
  91. 3:56process to using one of these platforms
  92. 3:59is very easy. So we are going to look
  93. 4:02behind the scenes here. As as you can
  94. 4:04see from the slide, I am banning these
  95. 4:06platforms because we are going to rent a
  96. 4:09server, a brand new server. We are going
  97. 4:12to install the operating system on it.
  98. 4:15In this case, we are going to use Abuntu
  99. 4:17and I will show you how to install the
  100. 4:20required software. So, we can install
  101. 4:22Python, NodeJS and other software that
  102. 4:26we need to run the application. And we
  103. 4:28will focus also on making sure that the
  104. 4:31web server is secure and that no one can
  105. 4:34access it. And we will see other things
  106. 4:36as well in this course. And here I want
  107. 4:38to mention or I want to emphasize this
  108. 4:41core philosophy that we will follow
  109. 4:43during the course is that before we
  110. 4:46automate anything we have to do the
  111. 4:49process manually because that will teach
  112. 4:51us why we need automation because if you
  113. 4:53don't do that you won't see the benefit
  114. 4:55of automating processes and also I have
  115. 4:58developed a book that goes uh with this
  116. 5:01course is uh not something the
  117. 5:04theoretical as I said I have applied
  118. 5:06this three times s on three websites
  119. 5:09that I have deployed and I am trying to
  120. 5:12give you all that knowledge in a
  121. 5:14distilled format. So I used a lot of
  122. 5:16resources like Google, I read books, I
  123. 5:20also found some code snippets and I
  124. 5:22filtered all of that into one simp one
  125. 5:26course that you can follow with all the
  126. 5:28things that I have learned and also the
  127. 5:30book if you want to read it. And as I
  128. 5:33have said, I have worked on this course
  129. 5:36for more than 8 months now to try to
  130. 5:39give you something that you might find
  131. 5:41helpful and to go in to see everything
  132. 5:44manually and to learn about everything
  133. 5:46that happens behind the scenes. And in
  134. 5:49this course, I will focus on deploying a
  135. 5:53specific web application that I have
  136. 5:55used and that you can find the source
  137. 5:56code online on GitHub that uses fast API
  138. 6:00in the back end and Vue.js JS in the
  139. 6:02front end and as an extra layer we added
  140. 6:05a search engine using M search but this
  141. 6:08is just an example to show you that you
  142. 6:10can deploy a complex system but if you
  143. 6:13are using Ruby or other programming
  144. 6:15languages the process will be the same
  145. 6:17you just need to change the software
  146. 6:19that you need to install and the
  147. 6:21commands to run it. This course is
  148. 6:24divided into six modules. In the first
  149. 6:27one which I call the foundation we are
  150. 6:30going to as I said in this case we are
  151. 6:32going to use digital ocean but you can
  152. 6:34do the same thing with the other
  153. 6:35platforms. We are going to rent a
  154. 6:37server. I will teach you what is an SSH
  155. 6:40key. This is something that we are going
  156. 6:42to use in order to authenticate to uh
  157. 6:44the machine that we are going to rent.
  158. 6:47And here something very important. This
  159. 6:49is for security reasons. We are going to
  160. 6:51remove the ability to connect using a
  161. 6:54password. Instead, we will only allow
  162. 6:56using an SSH key. And we will also block
  163. 7:00users from connecting as the root user
  164. 7:04because if someone is able to use that,
  165. 7:08they might do something nefarious in
  166. 7:10your server and we don't want to allow
  167. 7:12that. Instead, we are going to create a
  168. 7:14new user that you can use in order to
  169. 7:16connect to the virtual machine. And on
  170. 7:18top of that, we are going to configure
  171. 7:20firewall to block anyone who is trying
  172. 7:24to access your your web server. Why is
  173. 7:26that? Because once you once you create a
  174. 7:30web server, it is going to be available
  175. 7:31online and anyone can see it. So we need
  176. 7:35to set up the firewall and block people
  177. 7:37that are trying to access your web
  178. 7:40server. In this second module which is
  179. 7:42called the application runtime, here we
  180. 7:45are going to work with our code. So we
  181. 7:47are going to take it from let's say
  182. 7:49GitHub or from our laptop and we are
  183. 7:52going to deploy it to the server. So we
  184. 7:55are going to copy it and paste it there.
  185. 7:58Because we are using Python, we need to
  186. 8:00install we need to install it and
  187. 8:02configure the virtual environment. And
  188. 8:04something very important here. We are
  189. 8:06going to start with a small server. It's
  190. 8:09not it is not going to have a lot of
  191. 8:11RAM. So we will end up having some
  192. 8:14problems with memory. So we will
  193. 8:16eventually when we try to install
  194. 8:18software that needs compilation that
  195. 8:20will that will make the uh Linux run out
  196. 8:23of memory. So in that case we are going
  197. 8:26to learn something new which is swap
  198. 8:27memory which will allow us to take some
  199. 8:31some space from the SSD and help to in
  200. 8:35order to help us to install some some
  201. 8:37software that requires a lot of RAM. And
  202. 8:39in order to manage the back end we are
  203. 8:41going to use a mix of these software. We
  204. 8:44are going to use supervisor, J unicorn
  205. 8:46and UV core. Don't worry about that. We
  206. 8:49are going to learn why do we need them
  207. 8:52in module 2. So I'm just showing you
  208. 8:54what the things that we are going to
  209. 8:56learn. And after that we are going to
  210. 8:58use engineext as a reverse proxy and we
  211. 9:01are going to connect it to the back end
  212. 9:04using Unix sockets. In the third module,
  213. 9:07we are going to focus on media search
  214. 9:09because this is the data that we that
  215. 9:12the web application needs. I will show
  216. 9:14you how to export and dump the data that
  217. 9:17we have locally so that you can take it
  218. 9:19from your local machine and put it on
  219. 9:21the server. We are going to self-host
  220. 9:23mail search. We are not going to use a
  221. 9:26cloud offering that will give us the
  222. 9:28ability to get me search. No, we are
  223. 9:31going to install it and we are going to
  224. 9:32manage it on the same server. And here
  225. 9:35we are going to create another user that
  226. 9:37will manage me search for us. And we are
  227. 9:39going to use systemd to create a
  228. 9:42background service that will launch me
  229. 9:45search for us and that we can use in
  230. 9:47order to manage me search. After that we
  231. 9:49are going to use or we are going to
  232. 9:51create a batch script that will
  233. 9:53automatically create backups for us so
  234. 9:55that if something bad happens we can
  235. 9:58just read the backup and load it in
  236. 10:00order to continue. And finally, we are
  237. 10:03going to I will show you a nice
  238. 10:05dashboard that you can use in order to
  239. 10:07manage the data you have on me search.
  240. 10:10And we are going to use something very
  241. 10:12awesome which is called SSH tunneling
  242. 10:15that will allow us to connect this
  243. 10:17dashboard to your server without having
  244. 10:21to open a port or something like that.
  245. 10:25In module four, we are going to talk
  246. 10:27about global delivery and app security.
  247. 10:31And here we are going to start by
  248. 10:33registering a domain and configuring
  249. 10:36DNS. After that we are going we need a
  250. 10:39certificate so that we can get HTTPS
  251. 10:42that will make uh the connection between
  252. 10:46your users and your web server secure
  253. 10:48because if you don't do that you they
  254. 10:50will only see HTTP and their browser
  255. 10:53will flag that connection as insecure.
  256. 10:56And with let's encrypt the certificates
  257. 10:59are only valid for 3 months. So here I
  258. 11:02will show you how to create a script
  259. 11:03that will automatically renew the
  260. 11:05certificate for you without having to
  261. 11:07run any commands. After that we are
  262. 11:10going to use cloud player to serve our
  263. 11:13front- end assets because it is static
  264. 11:16and that will help us reduce the latency
  265. 11:19across uh the world because when when
  266. 11:23you pick a server you pick a location in
  267. 11:25in my example I picked Germany. So that
  268. 11:28means people from China or other
  269. 11:31countries that are very far away they
  270. 11:33are going to see high latency. In order
  271. 11:36to fix this problem, we use CDNs and in
  272. 11:39this case we are going to use cloud
  273. 11:41player. In module 5, we will focus a lot
  274. 11:43on automation. Here we are going to
  275. 11:46connect to GitHub because up to now we
  276. 11:50have cloned the project using a command.
  277. 11:55So we copied the code and we pasted it
  278. 11:57on the virtual machine and we ran the
  279. 12:00commands to start the back end and front
  280. 12:01end servers etc. We did everything
  281. 12:03manually. But in this module, we are
  282. 12:06going to automate that. So we will push
  283. 12:09the code to GitHub and we will just hit
  284. 12:11a button to deploy the web application
  285. 12:13without having to go to the server. So
  286. 12:15this is what we are going to learn here.
  287. 12:18But first we need to learn how to
  288. 12:19protect a branch. So if you are working
  289. 12:22on a codebase, you have let's say your
  290. 12:25main or master branch, you should never
  291. 12:27push the code directly to it. You need
  292. 12:29to create a new branch and then merge
  293. 12:31the code. So I will show you how to
  294. 12:33protect that main branch so that you
  295. 12:35cannot so that you don't push code that
  296. 12:38is broken accidentally. After that we
  297. 12:40are going to use a project called
  298. 12:41pre-commit that will allow us to create
  299. 12:45some rules that we can run when we
  300. 12:47commit code. For example, one of the
  301. 12:50rules that we can add is checking
  302. 12:51linting and formatting so that if your
  303. 12:53code is not formatted well, you will not
  304. 12:55be able to commit. After that, we are
  305. 12:58going to create a pipeline using GitHub
  306. 13:00actions. And that will allow us to run
  307. 13:03the same um tests like linting,
  308. 13:06formatting, running unit tests, etc.,
  309. 13:10but on GitHub. And that will allow us to
  310. 13:13block a merge request or a pull request
  311. 13:16if it doesn't satisfy all these tests.
  312. 13:20And that's how we can detect if our code
  313. 13:22is broken or not. If it isn't, if
  314. 13:24everything is green, then we can merge
  315. 13:26to master and from that we can deploy
  316. 13:28and we will do other things. Uh we will
  317. 13:30add integration tests, end to end tests,
  318. 13:33etc. So don't worry about that. We will
  319. 13:35focus a lot. Uh this this model is going
  320. 13:37to be very long, but it is going to be
  321. 13:40very very useful. And finally in the
  322. 13:43last module, we will focus on
  323. 13:45optimization and maintenance. Here I
  324. 13:47will show you how to read the enginex
  325. 13:49logs and display that data nicely using
  326. 13:51a project called go access. After that I
  327. 13:54will show you how to monitor the memory
  328. 13:56usage using btop++. This is an amazing
  329. 14:00project. I really like it and you will
  330. 14:02see once we once you reach module 6 you
  331. 14:04will see how btop can help us understand
  332. 14:08what is happening on our web server and
  333. 14:11I will show you how to ban IP addresses
  334. 14:14that are hammering your website. So
  335. 14:16sometimes when you analyze the logs
  336. 14:19using go access you will see some IP
  337. 14:21addresses that are trying to reach your
  338. 14:24server thousand um more than a thousand
  339. 14:27times a day or a minute and that's that
  340. 14:29is not human. So a human will not will
  341. 14:32not go to your website and try to
  342. 14:34refresh the page a thousand times.
  343. 14:35That's impossible. So these are
  344. 14:37automated bots that are trying to steal
  345. 14:39credentials or to see if there are
  346. 14:41weaknesses in your web server. So we are
  347. 14:43going to block them in order to first
  348. 14:46not waste time serving them things that
  349. 14:48they they are not going to read and to
  350. 14:51yeah reduce the the burden on our
  351. 14:54server. And we will also use an amazing
  352. 14:56tool called locust. This is a Python
  353. 14:59library that allows us to simulate users
  354. 15:02trying to access our website because
  355. 15:04this will allow us to estimate how many
  356. 15:07requests per second or per minute we the
  357. 15:10server can sustain before crashing or
  358. 15:13not being able to serve as many users as
  359. 15:16possible. So this is going to allow us
  360. 15:18to understand the weaknesses of our
  361. 15:21server and we will do other things. is
  362. 15:23we will analyze the disk usage um
  363. 15:26perform some log retention policy
  364. 15:28changes etc. So as you can see this
  365. 15:30course is packed with information. So it
  366. 15:34is going to be more than 10 hours long.
  367. 15:36So go through it step by step and don't
  368. 15:38try to rush. I I have tried to make it
  369. 15:41accessible to anyone. So even if you are
  370. 15:44a beginner don't worry about that
  371. 15:46because this is why I have made the
  372. 15:48course in order to teach you how to
  373. 15:50deploy things. And at the end you will
  374. 15:52see that you can also go automate uh
  375. 15:56more stuff but I just try to pick your
  376. 15:59interest and show you what you can do.
  377. 16:01And after that as I said if you don't
  378. 16:03want to do this process manually at
  379. 16:05least you did it once. So now you
  380. 16:07understand after that you can use
  381. 16:08platforms like Netifi get GitHub pages
  382. 16:11to deploy your applications without
  383. 16:13having to worry about renting a server
  384. 16:16or something like that. And in terms of
  385. 16:18resources don't worry about that.
  386. 16:20Everything is open source. I will make
  387. 16:23sure to put the links in the video
  388. 16:24description. You have two GitHub
  389. 16:26repositories. The first one, which is
  390. 16:28what I'm showing you right now, contains
  391. 16:31the code that we will deploy and the
  392. 16:34second GitHub repository contains the
  393. 16:36content of the book. So if you want to
  394. 16:40just read and you don't prefer watching
  395. 16:42videos, you can go to that repository,
  396. 16:46click on the book folder and you'll find
  397. 16:48all the chapters right there with the
  398. 16:50code. Everything everything is there in
  399. 16:52a nice format. And if you need some help
  400. 16:55or if you just want to say something
  401. 16:58after watching the course, feel free to
  402. 17:00connect with me. You can find my
  403. 17:02LinkedIn on the video description or you
  404. 17:05can send me a an email if you want to.
  405. 17:08You will find all my information in the
  406. 17:11video description. I hope that I have
  407. 17:13motivated you enough to watch the
  408. 17:15course. I hope that you enjoy it and
  409. 17:17that you learn a lot from it. Now, let's
  410. 17:19start with the first module.
  411. 17:22Welcome to module one where we will set
  412. 17:25up the foundation of the cloud
  413. 17:27environment. This is where your code
  414. 17:30will live. In this sub chapter, we will
  415. 17:33focus on cloud setup and access. Let's
  416. 17:36get started. Before we deploy any code,
  417. 17:40we need a secure environment. In this
  418. 17:44course, I will be using digital ocean.
  419. 17:47But these concepts apply everywhere.
  420. 17:50Whether you are using AWS, Lenode, or
  421. 17:54even a Raspberry Pi at home, the Linux
  422. 17:57commands remain the same. By the end of
  423. 18:00this video, you will have a server
  424. 18:03running Ubuntu 2404 LTS. We will
  425. 18:07generate secure SSH keys, connect to the
  426. 18:12server, and most importantly, we will
  427. 18:15completely disable password
  428. 18:18authentication.
  429. 18:19This ensures that your server is locked
  430. 18:22down from the very first moment. Now
  431. 18:25let's go to digital ocean in order to
  432. 18:28create our first droplet.
  433. 18:31Before creating the droplets, I want you
  434. 18:34to know that we have a GitHub repository
  435. 18:37where you will find everything I'm
  436. 18:40sharing with you in this course. So for
  437. 18:42example here inside the book folder we
  438. 18:45have the first subchapter and you have
  439. 18:49all the steps here. So if you prefer
  440. 18:52reading articles you will find those
  441. 18:55inside the book folder and the slides
  442. 18:58and everything else are available in the
  443. 19:01repository as well. You will find the
  444. 19:03link in the video description. If you
  445. 19:06have never used Digital Ocean before, if
  446. 19:09you click on the link in the video
  447. 19:10description, you will be able to get
  448. 19:13$200 for free just to test their
  449. 19:16platform. And that amount is available
  450. 19:18for 60 days. Click on get started. That
  451. 19:22will take you to a login page where you
  452. 19:26can create your account. In my case, it
  453. 19:29it logs me directly because I already
  454. 19:31have an account. And here we need to
  455. 19:34click on projects. As you can see, I
  456. 19:36already have two projects. I have my
  457. 19:39personal website is hosted here. And in
  458. 19:43your case, this list will be empty.
  459. 19:46First, click on new project.
  460. 19:50In this form, give the project a name.
  461. 19:53Select the environment type and the
  462. 19:55purpose of this project. I will call the
  463. 19:58project test. The environment type,
  464. 20:02let's say development. Here in the
  465. 20:05purpose drop-down menu, I'll select it
  466. 20:08web application and the description is
  467. 20:10optional. So click on create a project.
  468. 20:14Let me zoom in a little bit. Here they
  469. 20:16say move resources into test. So here we
  470. 20:20don't have any resources. So we will
  471. 20:22skip this for now. And as you can see
  472. 20:25the project has been created. And now we
  473. 20:28can create resources. And the resource
  474. 20:32that we are going to create is a
  475. 20:34droplet. Droplets are machines that that
  476. 20:37can run our code in the cloud. This
  477. 20:40means that we will take our
  478. 20:43application's source code put it on this
  479. 20:46droplet that is hosted by digital ocean
  480. 20:49and the code will be running inside
  481. 20:52inside of that machine. So now you can
  482. 20:55click on create droplets or you can do
  483. 20:58it from here. Create droplets. It's the
  484. 21:02same thing.
  485. 21:05Now we are in the create droplets page.
  486. 21:08The first thing that we need is to
  487. 21:11choose a region. For example, in my
  488. 21:14case, I live in Morocco. So I will
  489. 21:16choose Frankfurt because Germany is
  490. 21:20close to Morocco. That's why I chose it.
  491. 21:23you can do the same thing. So for
  492. 21:24example, if you live in Europe, you can
  493. 21:26select either London or Frankfurt or
  494. 21:29also Amsterdam. Those three will work
  495. 21:31perfectly. But if you are trying to
  496. 21:35deploy this application next to users in
  497. 21:38another country, then try to choose the
  498. 21:40the region based on where your users are
  499. 21:44going to be uh located. And here for
  500. 21:47example in Frankfurt, we have just one
  501. 21:49data center. So there there are there
  502. 21:51aren't other options. Next, choose the
  503. 21:55operating system. Here we have a lot of
  504. 21:58options, but I will select Ubuntu. And
  505. 22:02here we have plenty of versions. I will
  506. 22:04choose the LTS version, and I will
  507. 22:07select the latest one. Now you need to
  508. 22:10choose the size of your virtual machine.
  509. 22:14You can pick between shared CPU and
  510. 22:18dedicated CPU. Inside each option, you
  511. 22:22must decide the type of of storage, how
  512. 22:26much memory you want, uh how many CPU
  513. 22:30cores you want to have in this machine,
  514. 22:32etc. And here if you select dedicated
  515. 22:35GPU CPU, uh you will see that the price
  516. 22:39increases drastically because inside
  517. 22:43this option, the resources are reserved
  518. 22:46only for you. But shared CPU, you will
  519. 22:49be sharing resources with other people.
  520. 22:52That's why it's not as expensive as
  521. 22:55dedicated CPU. Just for testing
  522. 22:58purposes, select choose shared CPU,
  523. 23:02regular, and then select the lowest
  524. 23:06tier, $4 a month. And if you have just a
  525. 23:09simple web application that you want to
  526. 23:11host, then this option is fine. uh for
  527. 23:16example I have de deployed many websites
  528. 23:18using just this plan and it works
  529. 23:21wonderfully if you see that the
  530. 23:24application can't handle this the high
  531. 23:26traffic that you are seeing after that
  532. 23:28it's possible to to to get more
  533. 23:31resources so this doesn't if you select
  534. 23:33this now it doesn't mean that you are
  535. 23:35stuck in this offer and you'll have to
  536. 23:37recreate everything from the beginning
  537. 23:40no you you can still uh upsize the the
  538. 23:43droplet and add more resources If you
  539. 23:46need next, so here we have additional
  540. 23:48storage. You can see that here we get 10
  541. 23:50GB of storage. If you think that this is
  542. 23:53not enough, you can click on add volume
  543. 23:56and select the amount that you want to
  544. 23:58add. But this is not free. So you will
  545. 24:00be paying $1 per month per 10 GB. In my
  546. 24:04case, I don't need this, so I'll just
  547. 24:06remove it. 10 GB is enough. Uh if you
  548. 24:10want to have backups, you can click on
  549. 24:12this. And again, this is not free. So uh
  550. 24:16if you need this enable it and choose
  551. 24:19the right options but in any I don't
  552. 24:22think this is needed for testing
  553. 24:24purposes. So uncheck it. And now we
  554. 24:28arrive at the authentication section. So
  555. 24:31here we have two options. We can use SSH
  556. 24:35keys which is as you can see the default
  557. 24:37option selected by Digital Ocean or if
  558. 24:40you want you can use passwords. But as
  559. 24:43you can see here, we have a warning that
  560. 24:45says please store your password securely
  561. 24:48because if because passwords can be cast
  562. 24:51if they are not strong, but SSH keys are
  563. 24:54much stronger. So let's use SSH keys and
  564. 24:58I'll show you how to create one uh next.
  565. 25:01So now we need to create an SSH key. So
  566. 25:04I already have one here, but I will
  567. 25:06create one by clicking on this new SSH
  568. 25:09key button. You can see that they give
  569. 25:12us here the steps that we need to
  570. 25:15follow. I will show you how to do that.
  571. 25:17Now one once we generate the SSH key, we
  572. 25:21will put it here. Give it a name and add
  573. 25:24it. But before I create this, I want to
  574. 25:26go back to the slides in order to
  575. 25:28explain how uh authentication with SSH
  576. 25:32keys work. Let's look at what actually
  577. 25:36happens when you try to connect to your
  578. 25:39droplet. As I said, we will be using SSH
  579. 25:42keys instead of passwords because they
  580. 25:44are much harder to steal. The process
  581. 25:48starts with two files that we call
  582. 25:50private key and public key. And as you
  583. 25:54can see, we have two containers. This
  584. 25:56one represents your machine, your laptop
  585. 26:00that you have next to you. And here we
  586. 26:02have the server that we are creating on
  587. 26:05Digital Ocean or you can create on AWS
  588. 26:09or other cloud providers. The private
  589. 26:11key lives on your laptop but the public
  590. 26:14key will be inside the server. So the
  591. 26:18private key here think of it as your
  592. 26:20physical house key. You never share this
  593. 26:23with anyone. So this needs to be kept
  594. 26:26secret. Then you give the server a
  595. 26:31public key. Think of this as the lock on
  596. 26:34the door. Anyone can see the lock, but
  597. 26:37because they don't have the key, they
  598. 26:39cannot open it. When you run the SSH
  599. 26:42command, your laptop contacts the server
  600. 26:46and says, "Hello, I would like to
  601. 26:49connect using this specific ID." When
  602. 26:52the server receives this request, it
  603. 26:55replies with a challenge because the
  604. 26:58server is suspicious. It it doesn't know
  605. 27:00if you are the real person or if this is
  606. 27:02a hacker that wants to hack the the
  607. 27:04server and extract valuable information
  608. 27:07from it. So the server sends a challenge
  609. 27:11basically a random string of characters
  610. 27:13that we call a nons and basically says
  611. 27:17prove you own that private key. sign
  612. 27:20this random string for me. So if the the
  613. 27:24requesttor is legitimate, that means
  614. 27:28that it has the private key, it will be
  615. 27:31able to basically sign this string and
  616. 27:35send it back to the server. So here the
  617. 27:40the laptop will say or the real person
  618. 27:42will say I signed this using my private
  619. 27:44key. Here is the signature. Now the
  620. 27:47server will receive this and will try to
  621. 27:50do the math to verify if this is uh if
  622. 27:53the private key is correct. If that's
  623. 27:56the case, the server will grant access
  624. 27:59because it verified that the signature
  625. 28:01is correct. Otherwise, it's going to
  626. 28:04block this request and the anyone except
  627. 28:08you will not be able to log to your
  628. 28:11machine. So this is how SSH SSH
  629. 28:14authentication works. And now I'll show
  630. 28:17you how to create the these two pairs of
  631. 28:20keys uh the private and public keys.
  632. 28:23Paste this command. As I told you if you
  633. 28:26go to the to GitHub you will find this
  634. 28:31markdown file and here you will have
  635. 28:33everything. Um, so if I scroll down a
  636. 28:35little bit, you can see that I'm here we
  637. 28:37we have the same steps that we followed
  638. 28:40and here you can see that we had the
  639. 28:42commands. So don't worry about them. You
  640. 28:44will find the everything in here so that
  641. 28:46we can just copy copy them easily
  642. 28:48without typing them manually. So the SSH
  643. 28:52key gen command is used to generate SSH
  644. 28:56keys and we have plenty of algorithms
  645. 28:59that we can use to generate these pairs
  646. 29:01of keys and one of those is called
  647. 29:04ED25519.
  648. 29:06So this is the one that we are going to
  649. 29:07use. It's faster and more secure than
  650. 29:11RSA but you can also use RSA if you
  651. 29:14want. And here - F is basically the file
  652. 29:18name. All SSH keys are stored in the SSH
  653. 29:22directory. And if you don't give it a
  654. 29:24name, you might risk overriding your
  655. 29:27keys. So here I will call it test SSH
  656. 29:32key. And here we can add a comment. This
  657. 29:36is helpful if you want to identify the
  658. 29:38keys. And now I can hit enter. And as
  659. 29:42you can see it says generating public
  660. 29:44key with this algorithm. And here I need
  661. 29:47to enter a passphrase for this specific
  662. 29:51key. And here they tell me if I don't
  663. 29:53want to add a passphrase, I can just hit
  664. 29:55enter to move to the next uh step. When
  665. 29:59should you add a passphrase and when
  666. 30:02should you ignore this? I strongly
  667. 30:04recommend adding a passphrase for your
  668. 30:07personal key. So if you want to log to
  669. 30:10the machine, type some commands etc. do
  670. 30:14do some maintenance in that case you
  671. 30:16will be logged in manually. So in that
  672. 30:19case it's great to have a passphrase
  673. 30:21because even if someone was able to get
  674. 30:25your key they won't be able to login
  675. 30:27because the server will ask for a
  676. 30:29passphrase. Basically it's another layer
  677. 30:31of security that will prevent anyone
  678. 30:34from using your ser or accessing your
  679. 30:37server. But if you want to have a a
  680. 30:42machine or a script that will
  681. 30:44automatically deploy your application,
  682. 30:47in that case you don't want to have a
  683. 30:48passphrase because the script will be
  684. 30:51blocked. I will show you how to create
  685. 30:54two keys. So this one that we are
  686. 30:57creating is going to be used manually
  687. 31:00but we'll have another one that will
  688. 31:02call it let's say GitHub or something
  689. 31:05that we will use in GitHub to deploy our
  690. 31:08application automatically and in that
  691. 31:11case we don't need a passphrase. So for
  692. 31:13now I will add the passphrase and I will
  693. 31:15show you that we will be asked to enter
  694. 31:18it when we want to log the droplets. I
  695. 31:23have entered the passphrase and here
  696. 31:26they tell me to enter it again. Great.
  697. 31:29So as you can see the key random image
  698. 31:32is so that means that the the keys were
  699. 31:35generated. As you can see I have listed
  700. 31:38all the keys inside the SSH directory
  701. 31:41and I search just for this and you can
  702. 31:44see that we have two files. This one pub
  703. 31:48means public key and this one is the
  704. 31:50private key. This one should stay on
  705. 31:52your laptop but this one we will copy it
  706. 31:55and put it inside the droplet. Great. So
  707. 31:59now copy this and we will use the catch
  708. 32:03command to see the content of this
  709. 32:06public key. So here make run this and
  710. 32:09copy everything and after that I will
  711. 32:13show you where to put that uh on digital
  712. 32:15ocean. I have copied the key and now I
  713. 32:18will put it here and I will give it a
  714. 32:21name. So I will start by entering the
  715. 32:24name. So test SSH key manual. So here
  716. 32:30you paste your SSH key and after that
  717. 32:32click on add SSH key. I have done that
  718. 32:35and as you can see I have another SSH
  719. 32:37key here. And now if I want to add
  720. 32:40another key, I can click on new SSH key
  721. 32:42and repeat the same steps in the
  722. 32:45terminal to generate another one. But
  723. 32:47make sure to have another name and to
  724. 32:51not enter a passphrase because that one
  725. 32:54we will use later to deploy the
  726. 32:57application automatically. Or if you
  727. 32:59don't want to do this here, I will show
  728. 33:01you how to do it within the droplet.
  729. 33:04Here we can select this first option add
  730. 33:07improved metric monitoring. It's free so
  731. 33:10why not? And here finally we have this
  732. 33:14section. So here we can create multiple
  733. 33:16droplets if you want to but in our case
  734. 33:20uh one is enough. You can change the
  735. 33:23host name. So this is the name that will
  736. 33:26appear inside the droplet. We can we can
  737. 33:30change that. Let's call it uh let's keep
  738. 33:33it as Ubuntu test project. If you have
  739. 33:37multiple droplets, using tags will help
  740. 33:40you filter them quickly. And after that,
  741. 33:43we should assign this to the test
  742. 33:45project that we created. So everything
  743. 33:48is okay. Now click on create droplet.
  744. 33:53Open your list of projects and click the
  745. 33:56project that you have created. As you
  746. 33:58can see here is the droplet and here
  747. 34:01this is the running indicator. So this
  748. 34:04means that this droplet is in the
  749. 34:08creation phase but once this turns green
  750. 34:12it means that it's running. You can
  751. 34:14click on the name and as you can see now
  752. 34:17it's running. We have no data because we
  753. 34:20have just created this. You have your IP
  754. 34:23address. You have everything here. And
  755. 34:26as you can see, if you want to upsize
  756. 34:29this later, you can click on the upsize
  757. 34:31droplets button. And here you can in add
  758. 34:34more memory, more storage or in uh
  759. 34:38increase the the number of CPU cores if
  760. 34:41you want to. So I have refreshed the
  761. 34:43page and as you can see now it says
  762. 34:45active instead of uh new. Great. Now I
  763. 34:49want you to copy this IP address. Just
  764. 34:52click on the copy button. And you might
  765. 34:55be wondering why am I blurring the IP
  766. 34:58address. Even though this is just a test
  767. 35:01droplets that I will delete later, it's
  768. 35:04a good habit to keep your server IPs
  769. 35:06private to prevent unwanted traffic or
  770. 35:10attacks. So, copy the IP address and
  771. 35:13open your terminal. We are going to use
  772. 35:16the SSH command to SSH to the droplet.
  773. 35:21So first we type SSH
  774. 35:24I and here we need to specify the
  775. 35:28private key and the keys are stored in
  776. 35:32the SSH directory and here I have called
  777. 35:35mine test SSH key and after that we
  778. 35:38specify the user that we want to log in.
  779. 35:43So in the machine we have uh by default
  780. 35:45we'll have just the root the root user
  781. 35:47but after that we'll I will show you how
  782. 35:49to create other users and here we type
  783. 35:53at and we paste the IP address. Now hit
  784. 35:58enter and you should be able to login.
  785. 36:02So because this is the first time we are
  786. 36:05trying to login, we get this warning.
  787. 36:08And here you can just type yes. And as
  788. 36:11you can see, I'm not able to log in uh
  789. 36:14because I have added a passphrase. I
  790. 36:17need to specify it before logging in. So
  791. 36:21now I will add my passphrase. And here
  792. 36:24on Ubuntu there, they we have this
  793. 36:27option that will automatically unlock
  794. 36:28the key. Um so if you want to login
  795. 36:31quickly, that's fine. and just click on
  796. 36:33unlock and as you can see I am in uh
  797. 36:36let's verify so this is the memory usage
  798. 36:39it's has 40% we don't have any swap
  799. 36:42memory this we are using 22% of the disk
  800. 36:46space and yeah it seems to be working
  801. 36:50you can see that we have some updates
  802. 36:52that we can perform and that's great so
  803. 36:56as you can see we are logged in as the
  804. 36:58root user and this is the name that we
  805. 37:01have specif ified when we created the
  806. 37:03droplet. So everything seems to be
  807. 37:06working. Okay. So since we are logged in
  808. 37:09as user, we can type in sudo app update.
  809. 37:14So this is a an abuntu.
  810. 37:17So this is a machine running Ubuntu and
  811. 37:19this is how we update it. Okay, good. So
  812. 37:22now we will type sudo upgrade.
  813. 37:26Okay, the type yes and hit enter to
  814. 37:29start installing the packages. If you
  815. 37:32see a configuration screen during the
  816. 37:35update, select keep the local version
  817. 37:39currently installed. Don't don't select
  818. 37:42any other option because we want to
  819. 37:44preserve the working SSH configuration
  820. 37:47that Digital Ocean set up for you. In
  821. 37:50the Digital Ocean page, we added a SSH
  822. 37:55key manually. So that updates the SSH
  823. 37:58configuration and we want to keep that
  824. 38:00but also add the new modifications that
  825. 38:02this update process is trying to
  826. 38:05perform. Keep the differences and yeah
  827. 38:08let the the updates continue. Great. So
  828. 38:12the update has finished. Now we need to
  829. 38:16reboot the machine. So just type the
  830. 38:18reboot command. This will complete the
  831. 38:22upgrade process and start using the new
  832. 38:24kernel and packages. So you can see that
  833. 38:28the connection is closed. So I was uh
  834. 38:31ejected from the server because it needs
  835. 38:33to reboot. But don't worry, I can run
  836. 38:36the SSH command again to login back to
  837. 38:40the machine. So let's wait a little bit
  838. 38:43or let's go back to Digital Ocean just
  839. 38:45to check uh if it is ready. So I'll
  840. 38:49refresh the page. Okay, it says it says
  841. 38:51active. Let's hit enter. And voila, I am
  842. 38:56back. And as you can see, it says zero
  843. 38:59updates can be applied immediately. This
  844. 39:02confirms that the update process works
  845. 39:06perfectly. Now we are going to create a
  846. 39:09nonroot user and configure SSH access.
  847. 39:14Why do we create new users instead of
  848. 39:17using the root user? Running everything
  849. 39:20as root is dangerous because sometimes
  850. 39:23you can make mistakes or if you don't
  851. 39:27know Linux a lot and you might be using
  852. 39:30LMS without knowing the commands that
  853. 39:32they give you, you might do something
  854. 39:34that will maybe corrupt your file system
  855. 39:37or do something irreversible and that's
  856. 39:40not good. And if a hacker was able to
  857. 39:44log into your machine, he can do every
  858. 39:46anything. We want to limit the things
  859. 39:49that we can do inside the VM by creating
  860. 39:53a nonroot user. And if you want to
  861. 39:56perform something that requires pseudo
  862. 40:00privileges, we can give the user that
  863. 40:03ability momentarily. So the command to
  864. 40:06create a user is add user. I will call
  865. 40:11that user Emad. So that's my name. Uh
  866. 40:15make sure to change that. And as you can
  867. 40:17see now we need to provide a password.
  868. 40:20This means that if I try to to run the
  869. 40:24same command sudo opt update the Linux
  870. 40:28machine will ask me to enter my
  871. 40:29password. So this is really great
  872. 40:32because let's say that someone wants to
  873. 40:35login with this specific user that I
  874. 40:37created, they will not be able to do
  875. 40:40commands that require sudo privileges
  876. 40:42because they don't know the password. So
  877. 40:45create the password uh retype it again.
  878. 40:49And here you can add additional
  879. 40:50information like the full name. So let
  880. 40:53me just add that uh room number. I don't
  881. 40:56need that. For the things that you don't
  882. 40:59want to add anything, uh, just hit
  883. 41:03enter. And finally, let's type yes to
  884. 41:06create the user. So, as I said, we want
  885. 41:09this user to be able to run pseudo
  886. 41:11commands. So, we will use the user mod
  887. 41:14command. And here we will type the the
  888. 41:18user. And now we can see that we are
  889. 41:21still logged in as the root user, but we
  890. 41:23want to log in as this user. As you can
  891. 41:26see that I'm inside the the droplet. In
  892. 41:30order to exit, I can type exit and hit
  893. 41:32enter or I can just hit control and D.
  894. 41:37Good. So the connection to this server
  895. 41:40is closed. Now I can go back and instead
  896. 41:44of uh login logging in as root I will
  897. 41:48use my new user. Hit enter. And as you
  898. 41:52can see we were we weren't able to
  899. 41:54connect. Why is that? And here it says
  900. 41:56too many authentication failures. In
  901. 41:59your case, you might see just permission
  902. 42:01denied public key. In my case, I see
  903. 42:04this because I have a lot of public
  904. 42:05keys. So the the server was or my laptop
  905. 42:09was trying to log in with multiple keys
  906. 42:13and it wasn't able to do that. So why
  907. 42:16aren't we able to connect as this new
  908. 42:20user? This happens because the SSH key
  909. 42:24that we added in digital ocean lives in
  910. 42:27the root user. This means that we need
  911. 42:30to take that SSH configuration and also
  912. 42:34give it to my new user. So let's log
  913. 42:38back as the root user and we can verify
  914. 42:41this. We can go inside the root user and
  915. 42:44we have again the SSH folder and here we
  916. 42:48have authorized keys and authorized keys
  917. 42:51is a file. It's not a directory and we
  918. 42:55can verify this by typing ls-la
  919. 42:59and you can see that here we have a dash
  920. 43:01that means it's a file. If it says d
  921. 43:04that's a directory. So authorized keys
  922. 43:06contains all the public keys that we
  923. 43:08want to use on this droplet. In our
  924. 43:11case, it contains just one because uh
  925. 43:14when we created the droplets, we added
  926. 43:16one key. But we can add more if we
  927. 43:18wanted to. But my new user doesn't have
  928. 43:22this directory. So if I go to home and
  929. 43:25this user new user, you can see that
  930. 43:28there isn't an SSH directory. This means
  931. 43:32that we we won't be able to login as
  932. 43:34this new user. But luckily, we can solve
  933. 43:39this issue by just copying this SSH
  934. 43:43directory from the root user to this new
  935. 43:46user. And the command to do that is cp
  936. 43:50preserve mode. And here we want to copy
  937. 43:54this directory to this new user. And
  938. 43:58preserve mode is an option that we can
  939. 44:00add in order to preserve the file
  940. 44:03permissions. So you can see that here.
  941. 44:06Uh so let me just run this command. And
  942. 44:08instead of running ch mode 600 700 etc
  943. 44:13on this new directory. Preserve mode
  944. 44:16will do that for us. So in just one
  945. 44:18command we preserve the the file
  946. 44:20permissions. Who can access this file?
  947. 44:23Who can read it? Who can execute it etc.
  948. 44:25And if now I can look at this. So let's
  949. 44:30use ls and let's see what we have inside
  950. 44:34the sh folder. You can see that we have
  951. 44:38the authorized keys. That's good. But
  952. 44:40the problem is that if I look at who
  953. 44:43owns that file, you will see that the
  954. 44:46root user is owning this file. So we
  955. 44:49want to change the ownership and give
  956. 44:51that to this new user that you have
  957. 44:53created. And in order to do that, we use
  958. 44:56the ch own. And here I will also add
  959. 45:01capital R. And I want this new user to
  960. 45:06own that file. And here I'll go to home
  961. 45:09and SSH folder. And now if I go back to
  962. 45:13ls-la, you can see that we have that
  963. 45:17this user is owning this file. Now we
  964. 45:21can exit. Uh again hit Ctrl D go back to
  965. 45:26the previous command and here type in
  966. 45:29the new user not root and now hit enter
  967. 45:33and as you can see we are logged in and
  968. 45:36the prompt shows my user and not root
  969. 45:41and if I want to let's look at root dosh
  970. 45:47I'm not I'm not able to do that because
  971. 45:49that's not my directory but Because I
  972. 45:53have the pseudo privilege, I can type in
  973. 45:55pseudo and enter my password. And as you
  974. 45:57can see, I'm still able to look at
  975. 46:00things that I'm that I'm not supposed to
  976. 46:02look at or per do maintenance uh stuff
  977. 46:06like that. But if someone hacks your
  978. 46:08machine and is logged in as this user,
  979. 46:12new user, they won't be able to do this
  980. 46:14because they need to know the password.
  981. 46:17Awesome. Uh just one note, if this
  982. 46:20didn't work for you, if uh for example,
  983. 46:23you weren't able to uh look inside the
  984. 46:26SSH directory, that means that you did
  985. 46:29something wrong. Just rewind and make
  986. 46:32sure that this step works because in the
  987. 46:34next step, we are going to disable root
  988. 46:37login. We will not allow even us, we
  989. 46:40won't be able to login as root. We will
  990. 46:42only login as this new user. This will
  991. 46:46uh help increase security a lot because
  992. 46:49no one will be able to login as roots
  993. 46:51because as you saw root doesn't require
  994. 46:53providing a password and that's a big
  995. 46:56security problem. If someone is able to
  996. 47:01login as that super user let me show you
  997. 47:05how to stop this from happening. We will
  998. 47:08use pseudo again. I'm going to use nano
  999. 47:11as matx editor and I'm going to go
  1000. 47:14inside the shd config.
  1001. 47:18We want to change uh the following I
  1002. 47:21will say parameter and in nano in order
  1003. 47:24to search you can click on or press ctrl
  1004. 47:28w paste the thing that you are looking
  1005. 47:31for and hit enter. You can see that by
  1006. 47:33default this value is set to yes which
  1007. 47:36means that we can login as root but we
  1008. 47:39want to change that to no. We also want
  1009. 47:42to disable password authentication even
  1010. 47:45though we have specified in the creation
  1011. 47:49of the droplets that we want to use an
  1012. 47:50SSH key but it's it's also a great idea
  1013. 47:54to set it here and not rely on the cloud
  1014. 47:58provider to do that for you. So these
  1015. 48:00are the two things that you need to
  1016. 48:02change. You need to change permit root
  1017. 48:04login to no and password authentication
  1018. 48:07to no. Now in order to save this you can
  1019. 48:11click on Ctrl S or if you are on an
  1020. 48:14older machine you can hit Ctrl O just
  1021. 48:18hit enter and after that Ctrl X. You can
  1022. 48:22verify that again if this works. Just
  1023. 48:24enter. And you can see that the the
  1024. 48:27values are now set to no.
  1025. 48:30So now we need to restart the SSH
  1026. 48:34service. And now let's test this. So I
  1027. 48:37will type exit. And now I will try to
  1028. 48:40login as root. Okay. Let's see what will
  1029. 48:43happen. Uh so as you can see um my
  1030. 48:45request was rejected because we have
  1031. 48:48blocked root access to or we blocked
  1032. 48:52logging in as root. But if I go back and
  1033. 48:56try to login as my new user I am able to
  1034. 49:00do that. So that's awesome. So now we
  1035. 49:03have lots of layers of security. We have
  1036. 49:06disabled password login. We are using
  1037. 49:09SSH keys. And even if we use an SSH key,
  1038. 49:13we need to provide a passphrase. And
  1039. 49:15within the machine, we created a new
  1040. 49:18user in order to prevent us from doing
  1041. 49:21things that are unreoverable.
  1042. 49:24And if we want to do things that require
  1043. 49:26sudo privileges, we need to provide a
  1044. 49:29password. So this means that if someone
  1045. 49:32was able to breach a layer, they won't
  1046. 49:36be able to uh do something harmful
  1047. 49:39because if even if they have the SSH
  1048. 49:42key, they need to provide a passphrase
  1049. 49:44or even if they logged in, they need to
  1050. 49:46provide uh the password. I want to
  1051. 49:49explain to you how the SSH configuration
  1052. 49:53works. We have this main configuration
  1053. 49:57file that we have changed. Remember we
  1054. 50:01have disabled root login by setting
  1055. 50:05permit root login to no and we also
  1056. 50:08changed password authentication to no.
  1057. 50:12So this is the main configuration file.
  1058. 50:15But if I go up you will see that we have
  1059. 50:18this line include and here we include
  1060. 50:22all these configuration files that are
  1061. 50:25inside this directory. We call this drop
  1062. 50:29in configuration files. Now let's try to
  1063. 50:32look at this folder to understand what
  1064. 50:35we have there. As you can see I am using
  1065. 50:38tmox. This is why I have two window
  1066. 50:40panes so that you can see everything uh
  1067. 50:43in one place. Here I have copied that
  1068. 50:46path and let me enter my password. And
  1069. 50:49here I need to list all the
  1070. 50:52configuration files. You can see that I
  1071. 50:54have two of them. And if I use this
  1072. 50:58command, as you can see, let me zoom in
  1073. 51:01a little bit. So here I am searching for
  1074. 51:03this property that we have changed to
  1075. 51:07no. And you can see that it we already
  1076. 51:09have it in these two files. What does
  1077. 51:12this mean? When we created our droplet,
  1078. 51:16we selected SSH authentication
  1079. 51:20and digital ocean created this file for
  1080. 51:23us because on Linux we treat these
  1081. 51:28drop-in configuration files before the
  1082. 51:31main configuration. Let me explain. You
  1083. 51:34can see that here we include all these
  1084. 51:37files before changing all these fields
  1085. 51:40manually. This means that even if I come
  1086. 51:43here and set let me see so if I set this
  1087. 51:47to yes this will not take effect because
  1088. 51:51if I go for example inside this file so
  1089. 51:55let's look at it here we have this
  1090. 51:58command and here I will just try to
  1091. 52:01print what we have inside that file and
  1092. 52:04here I need to type 50 yes so as you can
  1093. 52:07see this file contains just this
  1094. 52:10configur this property and it is set to
  1095. 52:13no. So this means that this will
  1096. 52:16override any value that we have in the
  1097. 52:19main configuration file and you can see
  1098. 52:21that we have also another file which is
  1099. 52:24called 60 cloud image and here we also
  1100. 52:28have this property set to no. So as you
  1101. 52:31can see we have two files that set this
  1102. 52:34property to no. Which one should we
  1103. 52:37take? Because this is the SSH service,
  1104. 52:40we are going to order the files
  1105. 52:43alphabetically.
  1106. 52:44So here in this example, 50 cloud in it
  1107. 52:47will come before 60 cloud image. We are
  1108. 52:51going to read the properties inside this
  1109. 52:54file and we are not going to look at the
  1110. 52:57other ones. So here if we find that
  1111. 52:59password authentication is set to no, we
  1112. 53:02are going to take it and we will drop
  1113. 53:04the other files and the main
  1114. 53:06configuration file. This is why I said
  1115. 53:08that the values that we have in these
  1116. 53:11drop in file configuration are going to
  1117. 53:14override what we have in the main SSH
  1118. 53:18configuration file. So you might be
  1119. 53:21asking why did we edit the main file if
  1120. 53:25Digital Ocean has already created this
  1121. 53:28for us. That's a good question. We edit
  1122. 53:32the main configuration file as a safety
  1123. 53:34net. If you ever want to do this in the
  1124. 53:37future without using a cloud provider,
  1125. 53:40in that case you will not have these
  1126. 53:42files configured for you. So you will
  1127. 53:45need to either create one uh manually
  1128. 53:48and put it inside this directory or you
  1129. 53:52come inside the configuration
  1130. 53:55file the the main one and you change the
  1131. 53:57values manually. This way you guarantee
  1132. 54:00that your server is secure regardless of
  1133. 54:02the hosting provider. So now I want to
  1134. 54:06simplify the way we access the machine.
  1135. 54:09So if I hit again Ctrl V, I need to
  1136. 54:12always specify the SSH key and then the
  1137. 54:16user and uh the IP address. That's a lot
  1138. 54:20and there is a way to simplify this and
  1139. 54:23I'll show you how to do that. On your
  1140. 54:25local machine, you can see that I'm no
  1141. 54:27longer connected to the VM. I have
  1142. 54:30closed the connection. I want you to
  1143. 54:32type this command nano uh SSH config.
  1144. 54:36You can see that here I already have
  1145. 54:38some entries but I want you to go to the
  1146. 54:41end of the file and I want you to copy
  1147. 54:45and paste the following. So here we have
  1148. 54:48placeholders that we need to change
  1149. 54:50here. Uh the host. So this is just a
  1150. 54:53name. Uh this is a shortcut that we will
  1151. 54:56be using in the SSH command. So here
  1152. 54:58I'll call this test website. Here I need
  1153. 55:02to provide the droplet ID. Uh sorry the
  1154. 55:06droplet IP address. I'll copy it from
  1155. 55:10digital ocean. Uh okay. I will replace
  1156. 55:13this placeholder with that IP address.
  1157. 55:15And here I will replace this with my new
  1158. 55:18user. Here the identity file is going to
  1159. 55:22be the private key. I think I've named
  1160. 55:24it test ssh key. Uh but I'm not certain
  1161. 55:29but I I can check this. So save the file
  1162. 55:32again. You can do it by hitting Ctrl S
  1163. 55:36or Ctrl O and then enter. And after that
  1164. 55:39hit Ctrl X. So let me check. Yeah, it's
  1165. 55:43test SSH key. Okay. And let's go back to
  1166. 55:46the configuration. And yeah, it's uh
  1167. 55:49it's correct. Awesome. So you can see
  1168. 55:51that now after adding this to the config
  1169. 55:55file we will be able to log to the
  1170. 55:57website just by typing SSH and the
  1171. 56:01shortcut name that we have created. So
  1172. 56:04now I can just type this and as you can
  1173. 56:07see I am in and this is easier to
  1174. 56:09remember instead of uh remembering which
  1175. 56:13key you use and what is the IP address
  1176. 56:16of that droplet. And now I can just type
  1177. 56:19this and I'm in. You have successfully
  1178. 56:22configured a clean Ubuntu server and
  1179. 56:26secured it with SSH keys. However, your
  1180. 56:30server is still exposed to the open
  1181. 56:33internet. In the next subchapter, I will
  1182. 56:37show you how to work with the firewall
  1183. 56:41to lock down the network. You will learn
  1184. 56:44how to configure UFW to block unwanted
  1185. 56:49traffic, set up fail toban to stop brute
  1186. 56:53force attacks, and use the recovery
  1187. 56:57console if you ever get logged out.
  1188. 57:01Welcome back. In the previous video, we
  1189. 57:04launched our server and set up secure
  1190. 57:07SSH access. However, right now our
  1191. 57:12server is like a house with the front
  1192. 57:14door locked, but every window is wide
  1193. 57:19open. The server is sitting on the
  1194. 57:22public internet and by default it will
  1195. 57:26accept connections on any port. In this
  1196. 57:29sub chapter, the firewall strategy, you
  1197. 57:34are going to close those windows and
  1198. 57:37lock the parameter. Here's our plan for
  1199. 57:40this session. First, you will address
  1200. 57:43the problem. A fresh Linux server is too
  1201. 57:47open. It accepts traffic from anywhere.
  1202. 57:52To fix this, you will configure UFW,
  1203. 57:56which means the uncomplicated firewall.
  1204. 57:59You will set it to block all incoming
  1205. 58:02traffic by default and only open these
  1206. 58:06specific ports you trust. Next, you will
  1207. 58:10install fail to ban. This tool adds a
  1208. 58:14layer of intelligence to your firewall.
  1209. 58:17It automatically bans bots that try to
  1210. 58:21brute force your SSH keys. Finally, I
  1211. 58:25will show you the digital ocean recovery
  1212. 58:28console. This is your safety net. If you
  1213. 58:31ever accidentally configure the firewall
  1214. 58:34wrong and block yourself out, this tool
  1215. 58:38will save you. Now, setting up a
  1216. 58:41firewall is great, but it doesn't stop
  1217. 58:44people from trying to get in. If you
  1218. 58:47look at your server logs, you will see
  1219. 58:50bots trying to guess your password.
  1220. 58:53thousands of times a day. We need a way
  1221. 58:56to stop them automatically. This is
  1222. 58:58where fail to ban comes in. I will try
  1223. 59:02to explain this using this diagram that
  1224. 59:05I created. We have our server and we
  1225. 59:09have an attacker. So this is a user who
  1226. 59:14wants to get access to our server. You
  1227. 59:17can see inside the server we have the
  1228. 59:19uncomplicated firewall. We have fail to
  1229. 59:22ban. We have the SSH service that runs
  1230. 59:26on this port. And we have this log file.
  1231. 59:30So the first thing that that this
  1232. 59:32attacker will try to do is to connect to
  1233. 59:35this server using the SSH service. This
  1234. 59:39is going to fail because they don't know
  1235. 59:42the our SSH key and maybe they don't
  1236. 59:46know the user. In the previous video, we
  1237. 59:49have blocked access to this server using
  1238. 59:53the root user. So if they try to SSH as
  1239. 59:56the root user, they will be blocked. So
  1240. 59:59if that happens, the service will write
  1241. 1:00:02to the log something like this invalid
  1242. 1:00:06user Ubuntu from this IP address using
  1243. 1:00:10this port. So yubuntu is the user that
  1244. 1:00:13the attacker tried to use in order to
  1245. 1:00:16connect to this machine and this is uh
  1246. 1:00:20his IP. So if we see this we know that
  1247. 1:00:23there are some bad actors who are trying
  1248. 1:00:26to log to our server. So fail to ban is
  1249. 1:00:30a service that we need to install. I
  1250. 1:00:34will show you how to do that. And it's
  1251. 1:00:37it's going to monitor this log file. And
  1252. 1:00:41if this attacker is making multiple
  1253. 1:00:44requests, we can detect that. And if
  1254. 1:00:47fail to ban sees that uh we have too
  1255. 1:00:50many errors coming from this attacker,
  1256. 1:00:53it's going to tell the firewall to block
  1257. 1:00:55this IP. And now if this attacker tries
  1258. 1:00:59to login again, we are going to block
  1259. 1:01:02that connection. It's not going to enter
  1260. 1:01:04the server. And this way we limit
  1261. 1:01:08attacks like these just by reading
  1262. 1:01:11what's happening inside the log file.
  1263. 1:01:14That's it for the theory. Now let's open
  1264. 1:01:17the terminal connect to the machine and
  1265. 1:01:19let me show you how to set up UFW fail
  1266. 1:01:23to ban and other things. Before I start
  1267. 1:01:26the practice session, I would like to
  1268. 1:01:28mention that I updated the first chapter
  1269. 1:01:32and now it contains the second
  1270. 1:01:35subchapter and it's called the firewall
  1271. 1:01:37strategy and you have all the steps
  1272. 1:01:41written here and we are going to follow
  1273. 1:01:43them in this session and this GitHub
  1274. 1:01:47repository is going to be shared and the
  1275. 1:01:50link is going to be in the video
  1276. 1:01:52description. Now let's open the
  1277. 1:01:54terminal. Last time we configured the
  1278. 1:01:58SSH configuration to allow us to login
  1279. 1:02:01directly without specifying the user and
  1280. 1:02:04without specifying the IP address. So
  1281. 1:02:07now I can run this command and I am in.
  1282. 1:02:11Let's start by looking at the authentic
  1283. 1:02:14the.log file. To do that I will use
  1284. 1:02:18sudo. I will use the cat command to
  1285. 1:02:21print the content of that file. I need
  1286. 1:02:25to go to var log and art.log.
  1287. 1:02:30It's going to ask me for my password. I
  1288. 1:02:32will provide it. And as you can see, we
  1289. 1:02:35have a lots of stuff. And we see that
  1290. 1:02:39invalid message. Let me try to filter
  1291. 1:02:44the output to get only uh the rows that
  1292. 1:02:48mention this word invalid user. And as
  1293. 1:02:51you can see, we have a lot. Remember
  1294. 1:02:54that's my user is IMAD. It's not Oracle,
  1295. 1:02:58it's not Solana or other stuff. And as
  1296. 1:03:02you can see, we have plenty of IP
  1297. 1:03:05addresses that are repeating. Let's take
  1298. 1:03:07this one as an example. You can see that
  1299. 1:03:10this attacker is trying to connect as a
  1300. 1:03:14test user after that. Yeah, it's it's
  1301. 1:03:17trying to connect uh again. And if you
  1302. 1:03:21look at the time, so yeah, they are
  1303. 1:03:23making hundreds or maybe even thousands
  1304. 1:03:27of requests a minute or a day. And
  1305. 1:03:30that's not good because they are here
  1306. 1:03:33the the log file is going to be to get
  1307. 1:03:35bigger and it's going to consume uh
  1308. 1:03:38storage and we don't want that. It's
  1309. 1:03:40going to be great if we can block these
  1310. 1:03:43to not fill this log file. So you can
  1311. 1:03:47see that I have just created this uh
  1312. 1:03:50specific droplet for this course and as
  1313. 1:03:53you can see I'm getting bombarded by uh
  1314. 1:03:57attackers who are trying to log the
  1315. 1:04:00machine but luckily we have services
  1316. 1:04:04that will automatically ban them. So
  1317. 1:04:07let's get started. First, I would like
  1318. 1:04:10you to look at the status of the UFW or
  1319. 1:04:15the uncomplicated firewall. To do that,
  1320. 1:04:18we can use pseudo UFW
  1321. 1:04:22status. And as you can see, it's
  1322. 1:04:24inactive. This is the problem that we
  1323. 1:04:27have. The firewall is is not active. We
  1324. 1:04:30need to activate it in order to block
  1325. 1:04:34the open ports and allow only the ones
  1326. 1:04:37that we care about because the web
  1327. 1:04:40application that we are going to deploy
  1328. 1:04:42is going to be running on one one or two
  1329. 1:04:46ports. We don't need to open every
  1330. 1:04:49single port to the public internet. But
  1331. 1:04:52before activating the firewall, we need
  1332. 1:04:56to allow SSH connections. If you don't
  1333. 1:05:00do this step, you will lock yourself out
  1334. 1:05:02of the server immediately. So run this
  1335. 1:05:05command sudo ufw allow open ssh. And
  1336. 1:05:10this is going to allow port 22 to be
  1337. 1:05:15accessible. Otherwise, if we enable the
  1338. 1:05:19firewall without allowing SSH, we will
  1339. 1:05:22not be able to run SSH uh the SSH
  1340. 1:05:26command to connect to the server. and
  1341. 1:05:28that's not going to be uh good. In that
  1342. 1:05:31case, we need to go to digital ocean,
  1343. 1:05:33open the recovery console and fix this
  1344. 1:05:36problem. But if you do this, then
  1345. 1:05:40everything is going to be fine. Now I
  1346. 1:05:43can go back and run enable to start the
  1347. 1:05:49uh firewall. So as you can see, we get
  1348. 1:05:52this message. It says command may
  1349. 1:05:54disrupt existing SSH connections. You
  1350. 1:05:56can uh let's say yes. Okay. So it says
  1351. 1:05:59firewall is active and enabled on system
  1352. 1:06:03startup. Let's validate this. We have a
  1353. 1:06:07command that we can run. It's called
  1354. 1:06:08verbose. And this is the output that we
  1355. 1:06:12are getting. We have default deny
  1356. 1:06:15incoming, allow outgoing and disable
  1357. 1:06:18disabled routed. And the status is
  1358. 1:06:21active. That's what we want to see. And
  1359. 1:06:23we have uh we have this table. So by
  1360. 1:06:27default you can see that we deny
  1361. 1:06:30everything. This is the most important
  1362. 1:06:33rule. It means that every single port on
  1363. 1:06:37your server is blocked unless you
  1364. 1:06:40explicitly allow it. The the exception
  1365. 1:06:42list is allow in. So here we allow open
  1366. 1:06:47we allow SSH on port 22. This is the
  1367. 1:06:50exception. But the other ports are all
  1368. 1:06:53closed. We cannot use them. This means
  1369. 1:06:56that port 80 for HTTP and port 443 for
  1370. 1:07:01HTTPS are blocked. But in a future
  1371. 1:07:04episode, we are going to open them. But
  1372. 1:07:06for now, we only care about SSH. Great.
  1373. 1:07:10So now we have the firewall. We can test
  1374. 1:07:13it. I will exit the machine like this.
  1375. 1:07:17And now I will try to SSH again by using
  1376. 1:07:21the SSH command. And as you can see I am
  1377. 1:07:24in. I hope that you followed the steps
  1378. 1:07:26in order. And if somehow you are unable
  1379. 1:07:30to reach the server, don't worry. I will
  1380. 1:07:33show you how to use the digital ocean
  1381. 1:07:35recovery console to fix the issue. But
  1382. 1:07:38for now uh we are going to install fail
  1383. 1:07:41to ban to deal with this problem of
  1384. 1:07:44attackers trying to log to the machine
  1385. 1:07:48and b yeah yeah filling in the disk
  1386. 1:07:51space because the SSH service is writing
  1387. 1:07:55a lot of stuff uh into the log file
  1388. 1:07:59because here we are using
  1389. 1:08:02luckily fail toban is available in its
  1390. 1:08:05default repository and can be installed
  1391. 1:08:08told by using the following command sudo
  1392. 1:08:12up install fail to ban dashy means yes
  1393. 1:08:15confirm everything. Let me enter my
  1394. 1:08:18password. Awesome. So we can see that
  1395. 1:08:22the installation
  1396. 1:08:24was successful and now we can verify if
  1397. 1:08:28fail to ban is running or not. As you
  1398. 1:08:31can see, I run this command pseudo
  1399. 1:08:34service and the service that we in that
  1400. 1:08:36we want to inspect is fail toban. And
  1401. 1:08:38they want to look at the status. And as
  1402. 1:08:41you can see here in the active row, it
  1403. 1:08:44says running. Awesome. That's what we
  1404. 1:08:46want to see. Now, hit Q. By default,
  1405. 1:08:51fail to ban only bans attackers for 10
  1406. 1:08:55minutes. This is too short. and bots
  1407. 1:08:58that are hitting the web automatically
  1408. 1:09:01are going to come back later. So let's
  1409. 1:09:04increase this default value value to one
  1410. 1:09:07day. Let's create a local configuration
  1411. 1:09:11and edit this default value. So if we
  1412. 1:09:15try to run sudo nano etc fail to ban, we
  1413. 1:09:21can look at the jail.coniguration
  1414. 1:09:25file. Awesome. And as you can see uh we
  1415. 1:09:28have some default values and here they
  1416. 1:09:30are telling telling us how to override
  1417. 1:09:33this. So we can see that they say
  1418. 1:09:34provide customizations in a jail. file.
  1419. 1:09:39So this means that we should not updates
  1420. 1:09:40the jail.config because if the system
  1421. 1:09:43updates the values are going to be uh
  1422. 1:09:46overridden and we don't want that to
  1423. 1:09:48happen but the local file is uh not
  1424. 1:09:51going to be changed. And if we scroll a
  1425. 1:09:54little bit, yeah, we can see that we
  1426. 1:09:56have plenty of values that we can change
  1427. 1:09:58and the band time is set to 10 minutes.
  1428. 1:10:01Uh I will explain the other values, but
  1429. 1:10:04let's start by creating the local file.
  1430. 1:10:07Here is the command and I want you to
  1431. 1:10:09copy and paste the following text. Let
  1432. 1:10:13me explain to you these parameters. So
  1433. 1:10:15enabled means that we want to turn on
  1434. 1:10:18protection for SSH band time. As I said,
  1435. 1:10:22it's going to ban attackers for a
  1436. 1:10:25specific duration. Here it is set to one
  1437. 1:10:28day. Max retry allows a user to fail
  1438. 1:10:32five times before being banned. This is
  1439. 1:10:35important. Don't set this to one or a
  1440. 1:10:38low value because you are you can also
  1441. 1:10:42get banned. Let's say that I forgot to
  1442. 1:10:45pass the SSH key and I did that let's
  1443. 1:10:49say three times. If max retry was set to
  1444. 1:10:52three, I will be banned from the server.
  1445. 1:10:54I will not be able to log in. Keep it at
  1446. 1:10:57around three or five. Don't set it to
  1447. 1:11:00one. If you do once one mistake will be
  1448. 1:11:03logged out. And if that happens, you
  1449. 1:11:05need to go to recovery console, open the
  1450. 1:11:08terminal, and unban yourself. But we
  1451. 1:11:11don't want to do that. That's a lot of
  1452. 1:11:13work. Find time is set to 10 minutes.
  1453. 1:11:16And this is the window of time in which
  1454. 1:11:18those five failures must occur to
  1455. 1:11:21trigger a pan. So let's say that t is
  1456. 1:11:24equal to zero. Time is equal to zero. Uh
  1457. 1:11:27so the interval is 10 minutes. If we get
  1458. 1:11:30an attacker who failed to authenticate
  1459. 1:11:33five times during that duration, we are
  1460. 1:11:35going to block it. But if that attacker
  1461. 1:11:38failed only four times, we are not we
  1462. 1:11:40are not going to block it because uh the
  1463. 1:11:42minimum value is set to five. uh if we
  1464. 1:11:46get five failures during that 10
  1465. 1:11:48minutes, we can ban them otherwise we
  1466. 1:11:50will wait for the next interval and
  1467. 1:11:53start the count from zero again. Now
  1468. 1:11:56save the file and exit. I also want you
  1469. 1:12:00to enable the failtobend service to
  1470. 1:12:04start automatically when the server
  1471. 1:12:06reboots. So do this and start it using
  1472. 1:12:11the systemctl start command. Now we can
  1473. 1:12:15verify that the ban time is equal to 1
  1474. 1:12:18day by running this command failtoban
  1475. 1:12:22client get shd ban time and it gives us
  1476. 1:12:27600.
  1477. 1:12:28600 is basically 60 seconds time stamp
  1478. 1:12:32which is 10 minutes. Let me retry
  1479. 1:12:34running the enable and start commands
  1480. 1:12:37again. Let's go back to get SHD band
  1481. 1:12:40time and it still gives us 600 seconds.
  1482. 1:12:44The problem here is that I forgot to
  1483. 1:12:48restart the service and in order to do
  1484. 1:12:51that we need to run the restart command.
  1485. 1:12:54So this will allow fail to ban to read
  1486. 1:12:57the new configuration that we created.
  1487. 1:13:00Now if I go back and as you can see we
  1488. 1:13:02get 86,400
  1489. 1:13:05seconds which is 1 day in seconds. Now
  1490. 1:13:09let's see if fail to ban is working. We
  1491. 1:13:12have this command status SHD. As you can
  1492. 1:13:16see we get this output. We have the
  1493. 1:13:18status for the jail SHD. Great.
  1494. 1:13:21Currently failed total failed. We have
  1495. 1:13:24the and currently banned. So we can see
  1496. 1:13:26that fail to ban has banned these two
  1497. 1:13:29IPs and here we have total banned
  1498. 1:13:32currently banned. Now these two
  1499. 1:13:35attackers are not going to be able to
  1500. 1:13:38reach the SSS SSH service because the
  1501. 1:13:41firewall is going to block their
  1502. 1:13:44requests. Awesome. So this means fade
  1503. 1:13:47toban is working as we expected. Now
  1504. 1:13:50I'll keep this running. I'll now
  1505. 1:13:53transition to showing you how to access
  1506. 1:13:56the digital ocean recovery console and
  1507. 1:13:59I'll come back and see if we catched
  1508. 1:14:02some bad actors. You might be wondering
  1509. 1:14:06why do we need to use the recovery
  1510. 1:14:09console. I'll give you an example. If
  1511. 1:14:11you accidentally run UFW enable before
  1512. 1:14:17allowing open SSH or if you configure
  1513. 1:14:20SSH keys incorrectly and lose access to
  1514. 1:14:24your private key. In that case, you not
  1515. 1:14:27be able to log in to the machine and the
  1516. 1:14:30recovery console is provided to us by
  1517. 1:14:33digital ocean to give us direct access
  1518. 1:14:36to the machine through the browser and
  1519. 1:14:40this bypasses SSH entirely. To access
  1520. 1:14:44the recovery console, click on the
  1521. 1:14:47droplets, click on the access tab,
  1522. 1:14:50scroll down, and here you have the
  1523. 1:14:53recovery console. Let's launch it. Okay.
  1524. 1:14:56So, here it tells us that we need to log
  1525. 1:14:59in. First, I want you to start typing
  1526. 1:15:02randomly just to verify that the keys
  1527. 1:15:07that are pressed matches what you are
  1528. 1:15:10seeing because sometimes if you have a
  1529. 1:15:13different keyboard layout, yeah, this
  1530. 1:15:15might not work well. So in that case you
  1531. 1:15:18need to basically start typing your
  1532. 1:15:22login username and password and after
  1533. 1:15:26that delete everything and start typing
  1534. 1:15:29your user. So here I want to login as a
  1535. 1:15:33and the password is going to be this
  1536. 1:15:36one. As you can see I am logged in and
  1537. 1:15:40now I can type in the same command that
  1538. 1:15:44I've showed you earlier. sudo ufw allow
  1539. 1:15:47open SSH it's already allowed so nothing
  1540. 1:15:51will happen um because I am using pseudo
  1541. 1:15:53I need to provide this and as you can
  1542. 1:15:56see it says skipping adding existing
  1543. 1:15:58rule but in your case it's not going to
  1544. 1:16:00say this it's going to add it it's going
  1545. 1:16:03to add this rule for SSH now we are fine
  1546. 1:16:07we can exit and let's close this tab and
  1547. 1:16:12now you can run the SSH command and you
  1548. 1:16:15can login without any problem. Let's go
  1549. 1:16:18back to Digital Ocean again. If for some
  1550. 1:16:21reason you want to reset the p the root
  1551. 1:16:24password, you can do that. But we don't
  1552. 1:16:27have that, so there is no need to. And
  1553. 1:16:30you can open the droplet console by
  1554. 1:16:34specifying the user and you can launch
  1555. 1:16:37it. So if you don't want to use your
  1556. 1:16:39terminal, you can use everything through
  1557. 1:16:42the web page. And as you can see I am
  1558. 1:16:44connected as this user. Let's try to
  1559. 1:16:48connect as root. Awesome. So it failed
  1560. 1:16:52because in the previous session we
  1561. 1:16:54blocked accessing this machine as root.
  1562. 1:16:58Awesome. So everything is working as
  1563. 1:17:01expected. What is next? You might be
  1564. 1:17:04wondering. That's a good question. So
  1565. 1:17:06far you have a solid foundation. You
  1566. 1:17:10have a secure server that blocks
  1567. 1:17:12unauthorized traffic and automatically
  1568. 1:17:16bans attackers. As you can see, I have I
  1569. 1:17:20rerun the status shd command. As as you
  1570. 1:17:23can see, now we blocked four people.
  1571. 1:17:26This is the new IP address that we
  1572. 1:17:29blocked. So, this means that fail to ban
  1573. 1:17:31is working. And as you can see, it's
  1574. 1:17:33automatic. We don't need to do anything
  1575. 1:17:35manually. And that's awesome. And you
  1576. 1:17:37might be wondering why this IP was not
  1577. 1:17:41added to the previous two. So these two
  1578. 1:17:44got unbanned because the band duration
  1579. 1:17:47is set to 10 minutes before I changed it
  1580. 1:17:51to 1 day. And we can verify this by
  1581. 1:17:54running this. As you can see it says
  1582. 1:17:57unban. So [clears throat] if I look at
  1583. 1:17:59the fail toban logs I can filter by this
  1584. 1:18:02word unban. And as you can see these all
  1585. 1:18:06these IPs were uh were unbanned. And you
  1586. 1:18:09can also look at this specific new ID.
  1587. 1:18:12And as you can see it was banned. So
  1588. 1:18:15that's that's confirms it. And here I
  1589. 1:18:18just want to explain this. If you will
  1590. 1:18:21see that these two got unbanned because
  1591. 1:18:23before changing the configuration to set
  1592. 1:18:27the band time to one day, these two were
  1593. 1:18:29already banned. That's why they they
  1594. 1:18:31were unbanned in 10 minutes. But this
  1595. 1:18:33one will stay here and will be unbanned
  1596. 1:18:36the next day. Let's just verify that it
  1597. 1:18:39is still there. Yeah, it is still here.
  1598. 1:18:42And four, this basically keeps a total
  1599. 1:18:45count of how many IPs were banned. It
  1600. 1:18:48doesn't mean that we have four IPs that
  1601. 1:18:50are currently banned. The currently
  1602. 1:18:53banned is what you need to look at and
  1603. 1:18:55it shows us that we have just one IP
  1604. 1:18:57that that is banned from accessing or
  1605. 1:19:00from trying to communicate with the
  1606. 1:19:01server. In the next module, we will
  1607. 1:19:04shift focus from security to software.
  1608. 1:19:07You will learn how to prepare the
  1609. 1:19:09environment by installing Python and
  1610. 1:19:11NodeJS. Setting up swap memory to handle
  1611. 1:19:15builds on a low RAM server like ours and
  1612. 1:19:20configuring J unicorn and supervisor to
  1613. 1:19:23keep your application running reliably
  1614. 1:19:26in the background. Hi everyone. In this
  1615. 1:19:30video, you are going to put your server
  1616. 1:19:32to work by turning it into a web server.
  1617. 1:19:37You will learn a lot from this video.
  1618. 1:19:39I'll show you how to move files from
  1619. 1:19:42your local machine to the virtual
  1620. 1:19:44machine, use SSH tunneling, find and
  1621. 1:19:48kill zombie processes, and more. In this
  1622. 1:19:52video, you will be deploying a full
  1623. 1:19:54stack application that uses Vue.js JS in
  1624. 1:19:58the front end and pass API for the back
  1625. 1:20:01end. The source code is available on
  1626. 1:20:04GitHub and I will make sure to put the
  1627. 1:20:06link in the video description. I am
  1628. 1:20:09using my personal website in order to
  1629. 1:20:12show you the exact same steps I took to
  1630. 1:20:16deploy it. The goal here is not to
  1631. 1:20:18deploy my specific website on your
  1632. 1:20:21server, but use this project as a
  1633. 1:20:24reference. Especially if you don't have
  1634. 1:20:26your own project. If you have your own
  1635. 1:20:29app, but you don't use Vue.js and pass
  1636. 1:20:32API, it's fine. You can adjust a few
  1637. 1:20:36commands in this tutorial to make it
  1638. 1:20:38work with your specific setup. Now,
  1639. 1:20:40let's go back to the slides because I
  1640. 1:20:41want to show you the road map for this
  1641. 1:20:44session. We will transfer the project to
  1642. 1:20:48the server using the SCP command and I
  1643. 1:20:52will show you how to organize the file
  1644. 1:20:55permissions securely. Next, you will
  1645. 1:20:58install the necessary runtimes. We will
  1646. 1:21:01need Python for the back end and NodeJS
  1647. 1:21:04for the front end. I will show you how
  1648. 1:21:07to set up swap memory. This is an
  1649. 1:21:10important step for smaller servers in
  1650. 1:21:13order to prevent out of memory crashes
  1651. 1:21:16during the build process. We will use
  1652. 1:21:19SSH tunneling to securely preview the
  1653. 1:21:22application on your local browser before
  1654. 1:21:25opening it to the public. And finally,
  1655. 1:21:29we will configure J Unicorn and
  1656. 1:21:31Supervisor to make the backend robust
  1657. 1:21:34and production ready. Now let's go to
  1658. 1:21:37GitHub because we need to copy the
  1659. 1:21:39source code. Click on the code button
  1660. 1:21:42and copy this link. Now open your
  1661. 1:21:45terminal. Since this is just a test, uh
  1662. 1:21:48for me, I will put this in the download
  1663. 1:21:51folder, but feel free to clone this
  1664. 1:21:53repository in any directory. Run the get
  1665. 1:21:57cloned command and here paste that link
  1666. 1:22:00that we copied and hit enter. As you can
  1667. 1:22:04see, we are cloning the repository and
  1668. 1:22:06the command finished. Great. Now we need
  1669. 1:22:09to move inside this folder. So I will
  1670. 1:22:12use the cd command and I will type in my
  1671. 1:22:16this name. And now I am inside that
  1672. 1:22:20repository. And as you can see we are on
  1673. 1:22:22the master branch. Now let me type ls. I
  1674. 1:22:26want to see what we have inside. As you
  1675. 1:22:28can see we have the backend folder and
  1676. 1:22:30front end folder. These are the two
  1677. 1:22:32folders that are that contain the s the
  1678. 1:22:36code for the the website. The other
  1679. 1:22:39stuff are not that important for now.
  1680. 1:22:41These folders are inside my laptop. I
  1681. 1:22:45need to move them to the server that we
  1682. 1:22:48created on digital ocean. We could move
  1683. 1:22:51them one by one, but that is slow and
  1684. 1:22:55repetitive. Instead, we are going to
  1685. 1:22:57compress these files and folders into
  1686. 1:23:01one compressed file. In order to do
  1687. 1:23:04that, we will use the tar command. So
  1688. 1:23:07here I am going to call this compressed
  1689. 1:23:10file source code and we need to exclude
  1690. 1:23:14some folders that are not important and
  1691. 1:23:17that will take a lot of space. For
  1692. 1:23:18example, the node modules contains the
  1693. 1:23:21dependencies that the front end needs.
  1694. 1:23:23So we don't need this. we can generate
  1695. 1:23:25it directly on the server. Same for
  1696. 1:23:28Python, we have the virtual environment.
  1697. 1:23:31We need to exclude that. We also have pi
  1698. 1:23:34cache and the getit directory. So we
  1699. 1:23:37don't need this these folders. That's
  1700. 1:23:39why we exclude them. And here we have a
  1701. 1:23:43dot and this means that we want to
  1702. 1:23:46compress everything inside this
  1703. 1:23:49directory. So if you wanted to compress
  1704. 1:23:52just the back end folder, we you need to
  1705. 1:23:55change this dot and put back end or if
  1706. 1:23:58or something else. But here we want to
  1707. 1:24:00take everything and put put it on the
  1708. 1:24:02server. Now hit enter. And as you can
  1709. 1:24:06see, we were able to compress everything
  1710. 1:24:08inside this compressed file. Now we need
  1711. 1:24:11to copy this from our laptop to the
  1712. 1:24:15server. In order to do that, we are
  1713. 1:24:17going to use the SCP command, which
  1714. 1:24:20stands for secure copy. And here,
  1715. 1:24:23because we configured SSH alias in the
  1716. 1:24:27previous chapter, we don't need to type
  1717. 1:24:29the IP address of the server, we can
  1718. 1:24:32just type in the name. So here I will
  1719. 1:24:35take the source code. So I'm going to
  1720. 1:24:38copy this and I'll put it on the
  1721. 1:24:42website. And here we don't need to type
  1722. 1:24:45root uh the user at and then the IP
  1723. 1:24:48address. We can just uh use the alias
  1724. 1:24:51the alias that we created before. And
  1725. 1:24:54here I will put it inside the temp
  1726. 1:24:57directory. Now hit enter. And as you can
  1727. 1:25:00see we have a progress bar that shows us
  1728. 1:25:02that we are uploading this to the
  1729. 1:25:04server. And we it's finished. So now I
  1730. 1:25:08can go SSH to that website or to that
  1731. 1:25:13server using this command. As you can
  1732. 1:25:15see I am in let's verify that we have
  1733. 1:25:18that zipped file and as you can see we
  1734. 1:25:21have it inside the temp directory. Now
  1735. 1:25:24let's organize the project files. We
  1736. 1:25:27should move this compressed file
  1737. 1:25:29somewhere. But where exactly? The best
  1738. 1:25:32practice for web applications is to use
  1739. 1:25:35a neutral location like /var/www
  1740. 1:25:40or a dedicated folder like web app. This
  1741. 1:25:44approach keeps your application logic
  1742. 1:25:47separate from your personal user files
  1743. 1:25:50like SSH or bash history and prevents
  1744. 1:25:55permission issues. So let's create this
  1745. 1:25:58folder with the make directory command.
  1746. 1:26:02So I will use a make directory command
  1747. 1:26:05and I'll put everything inside web app.
  1748. 1:26:08Now we need to move the compressed file
  1749. 1:26:10into this new folder. For that we are
  1750. 1:26:13going to use the move command. I will
  1751. 1:26:16take the path to that compressed file
  1752. 1:26:19and I will move it to web app. Great.
  1753. 1:26:22Now we can um yeah yeah yeah let's
  1754. 1:26:25change directory let's move to web app
  1755. 1:26:28uh let's type ls and as you can see we
  1756. 1:26:30have that compressed file now we need to
  1757. 1:26:33decompress it using the tar command
  1758. 1:26:35again and here is how we do that hit
  1759. 1:26:38enter and let's see yes we have
  1760. 1:26:42everything now we can delete this
  1761. 1:26:44compressed file because we no longer
  1762. 1:26:46need it let's type its okay great so we
  1763. 1:26:48have everything here that's great now
  1764. 1:26:51Before uh we continue, let's type ls-la
  1765. 1:26:55and hit enter. Here you need to see that
  1766. 1:26:58your user is owning these files. As you
  1767. 1:27:00and as you can see, my user is owning
  1768. 1:27:02them. If you see root is owning these
  1769. 1:27:05files and folders, make sure to run this
  1770. 1:27:08command sudo chown. So change ownership
  1771. 1:27:12dash r. We want to do this recursively.
  1772. 1:27:14And here you put in you put the user and
  1773. 1:27:17the group. in in in my case it's going
  1774. 1:27:20to be a MAD and here you specify the
  1775. 1:27:24folder but since we are inside web app
  1776. 1:27:27um we need to yeah change directory but
  1777. 1:27:30or we can just use dos okay and
  1778. 1:27:34hopefully when you when you run ls-la
  1779. 1:27:37you you'll be able to uh see that the
  1780. 1:27:40ownership has changed and your user is
  1781. 1:27:42owning these files. This is very
  1782. 1:27:44important so make sure to do that.
  1783. 1:27:47Awesome. We are now ready to install
  1784. 1:27:49dependencies. Let's start with the back
  1785. 1:27:52end. First we need to install Python
  1786. 1:27:54tools because those are required for the
  1787. 1:27:57back end. Here we are working with the
  1788. 1:27:59with an Ubuntu machine. So this is how
  1789. 1:28:01we can install them. So we are going to
  1790. 1:28:03install pip the virtual environment and
  1791. 1:28:06dev. And here dashy will just accept
  1792. 1:28:09everything and we don't need to yeah
  1793. 1:28:11confirm this operation. Awesome. We
  1794. 1:28:14installed the those tools. Now I'll
  1795. 1:28:17clear the screen. Let's go inside the
  1796. 1:28:20backend folder. And now let's create an
  1797. 1:28:24virtual environment. So we will use
  1798. 1:28:26Python tree dash M. We will use the VNV
  1799. 1:28:30module and we will create a virtual
  1800. 1:28:32environment called VNV. Hit enter. Okay,
  1801. 1:28:36great. Let's activate the environment.
  1802. 1:28:39So we will use source bend/bin/activate.
  1803. 1:28:45If you see the name of the virtual
  1804. 1:28:47environment here before your name is the
  1805. 1:28:50user's name that means that you
  1806. 1:28:52activated the virtual environment
  1807. 1:28:54successfully. Now if I let's type ls
  1808. 1:28:58because I want to see yeah we have the
  1809. 1:29:00requirements.txt file. Those are all the
  1810. 1:29:03the dependencies that we need to launch
  1811. 1:29:06the backend server. In order to install
  1812. 1:29:08them, we will use pip install-r
  1813. 1:29:13and we will provide the requirements.txt
  1814. 1:29:16file. Let's wait for this to finish. And
  1815. 1:29:19here make sure that before you install
  1816. 1:29:21the dependencies that your virtual
  1817. 1:29:24environment is activated cuz we want
  1818. 1:29:26everything to be contained inside this
  1819. 1:29:28project. Awesome. We were able to
  1820. 1:29:31install everything. That's great. Let me
  1821. 1:29:34uh clear the screen. And now we can
  1822. 1:29:37start the back end to yeah make sure
  1823. 1:29:40that everything runs without any issue.
  1824. 1:29:42And here we are working with an with a
  1825. 1:29:44fast API application which means that we
  1826. 1:29:47need to use uh u core. Uh this is this
  1827. 1:29:51command or this library is installed
  1828. 1:29:53will be installed after running pip
  1829. 1:29:55install-r
  1830. 1:29:56requirements.txt.
  1831. 1:29:58And here we have uh so the entry is the
  1832. 1:30:03entry point is inside this file and the
  1833. 1:30:06yeah the app is called app. We are going
  1834. 1:30:09to provide 0000 to the host because we
  1835. 1:30:12want we want to make this the server
  1836. 1:30:16accessible outside the virtual machine.
  1837. 1:30:19And finally we want port and let's use
  1838. 1:30:248,000 because this is what the front end
  1839. 1:30:27expects. So now hit enter
  1840. 1:30:30and yeah it seems to be working. If you
  1841. 1:30:33see application startup complete then
  1842. 1:30:35that means that you are in a in a good
  1843. 1:30:37shape and you can see that u is running
  1844. 1:30:39on this IP 0000
  1845. 1:30:43and yeah if you try to click on this
  1846. 1:30:46link nothing will happen because uh
  1847. 1:30:48let's see let me show you as you can see
  1848. 1:30:51nothing happens because this server is
  1849. 1:30:53running inside the virtual machine it's
  1850. 1:30:55not running locally on our computer uh
  1851. 1:30:59close the page go back to the VM but if
  1852. 1:31:02We can't access this the server outside
  1853. 1:31:05of the VM. How can we test it? Well, in
  1854. 1:31:09order to test it, we need to to open
  1855. 1:31:11another terminal. I will use again the
  1856. 1:31:14sh command and I will go inside the VM.
  1857. 1:31:19But before I test it, I want you to run
  1858. 1:31:22the uh UFW
  1859. 1:31:25status command. uh provide your password
  1860. 1:31:29and I want you to make sure that the
  1861. 1:31:33firewall is active and that you have
  1862. 1:31:36just SSH. So these are the ports that
  1863. 1:31:39are allowed. But we don't have port
  1864. 1:31:418,000 or other ports. That's why we were
  1865. 1:31:44not able to access this server outside
  1866. 1:31:48of the the VM. But we can at least test
  1867. 1:31:51using the curl command. So we are going
  1868. 1:31:53to send a request to this to the server
  1869. 1:31:57and here 127.001
  1870. 1:32:00means local host basically inside the VM
  1871. 1:32:03inside the server and 8,000 is the port
  1872. 1:32:07and this is going to make a get request
  1873. 1:32:10to the server running on this port. So
  1874. 1:32:13yeah, let's see what we'll get. So it
  1875. 1:32:15says detail not found. Uh maybe because
  1876. 1:32:20we need to do health. Uh let me go
  1877. 1:32:22inside the web application back end and
  1878. 1:32:27let's look at the main file. Let's use
  1879. 1:32:31uh or let's use maybe nano main.py.
  1880. 1:32:36Let me make the screen smaller. I want
  1881. 1:32:39to see the end points that we have here.
  1882. 1:32:42So yeah, we need to use / API/hel
  1883. 1:32:46in order to get status is okay. Okay,
  1884. 1:32:49let's zoom in again and here we need to
  1885. 1:32:54before help we need to add API and as
  1886. 1:32:58you can see we get we are we get status
  1887. 1:33:00is okay which means that the backend
  1888. 1:33:02server is responding and if you look at
  1889. 1:33:04the logs you see that we were making get
  1890. 1:33:07requests this we we were getting 404
  1891. 1:33:10because the endpoints didn't didn't
  1892. 1:33:13exist so the root endpoints or the /hel
  1893. 1:33:17endpoints don't don't exist That's what
  1894. 1:33:19we got 404. But when we try to talk to
  1895. 1:33:24this endpoint API/halth, we got 200.
  1896. 1:33:27Okay, because it exists in the source
  1897. 1:33:30code. Great. So this confirms that the
  1898. 1:33:33backend server is running and that's the
  1899. 1:33:35we installed all the dependencies that
  1900. 1:33:38we need. Hit Ctrl C because we want to
  1901. 1:33:40stop the server. We no longer need it.
  1902. 1:33:42Now we will move to the front end. We we
  1903. 1:33:45are going to install the dependencies
  1904. 1:33:47there and do the same thing. We need to
  1905. 1:33:49verify that it works and after that we
  1906. 1:33:51will combine them together. Uh you can
  1907. 1:33:54see that we are inside the backend
  1908. 1:33:55folder. Let's move uh one layer up.
  1909. 1:34:00We have the virtual environment is still
  1910. 1:34:03active. We can leave it like that or if
  1911. 1:34:06you want you can um write type
  1912. 1:34:08deactivate like so. And now we need to
  1913. 1:34:12go inside the front end folder. I am
  1914. 1:34:15using Vue.js in the front end. This
  1915. 1:34:17means that we need to install NodeJS.
  1916. 1:34:21And the best way to install NodeJS is
  1917. 1:34:24with NVM. Uh if you don't know, NVM is a
  1918. 1:34:28Node package manager. So just type nvm
  1919. 1:34:31GitHub. There it is. And the
  1920. 1:34:34installation the installation is easy.
  1921. 1:34:36You just have you just run this curl
  1922. 1:34:39command. So copy it, go back to the
  1923. 1:34:42server and paste it here. So this is the
  1924. 1:34:45latest version of NVM. Now in order to
  1925. 1:34:48install it, as I said, we just hit enter
  1926. 1:34:51and voila, it's done. Now the the
  1927. 1:34:54problem is that when you install NVM,
  1928. 1:34:56you need to create a new terminal to
  1929. 1:34:59basically get the command. Because now
  1930. 1:35:01if I run NVM, you can see that it's not
  1931. 1:35:04recognized. But we have a solution. we
  1932. 1:35:06can uh use source uh and here I am using
  1933. 1:35:11bash so I will target bash rc
  1934. 1:35:16and this so if when you run this it's
  1935. 1:35:18going to basically load in nvm so now if
  1936. 1:35:22I type nvm you can see that uh it works
  1937. 1:35:24and let's verify that the version is
  1938. 1:35:27correct yes it's 040.4 4. Awesome. Now
  1939. 1:35:30we can we need to install the late the
  1940. 1:35:34latest long-term support version of
  1941. 1:35:37node. And in order to do that, we run
  1942. 1:35:40nvm install and we we uh yeah we provide
  1943. 1:35:44LCS because we that's what we want to
  1944. 1:35:46install. And this is the latest LTS
  1945. 1:35:50version from node. And if you want to
  1946. 1:35:53yeah verify if that's correct, you can
  1947. 1:35:56go to nodejs.org. or uh click on get
  1948. 1:36:00NodeJS and as you can see so the latest
  1949. 1:36:02LTS version is 2413.1
  1950. 1:36:07let's verify that and yeah that's
  1951. 1:36:09correct so 2413.1
  1952. 1:36:11we also need to install PNPM this is the
  1953. 1:36:15command that I use to install the
  1954. 1:36:16front-end dependencies I don't use npm
  1955. 1:36:20and this is how you install that make
  1956. 1:36:22sure to install the latest version of
  1957. 1:36:25PNPM version 10 and not prior prior
  1958. 1:36:28ones. Hit enter. And here we want to
  1959. 1:36:31install it globally. Okay. So, it's it's
  1960. 1:36:35working. Uh it says that there is a new
  1961. 1:36:38minor version of npm available. That's
  1962. 1:36:40not important. So, let's click that. And
  1963. 1:36:43now let's verify we are inside the front
  1964. 1:36:46end directory. Type pnpm install and hit
  1965. 1:36:50enter. And as you can see, yeah, PNPM is
  1966. 1:36:53very fast and it's uh I really like to
  1967. 1:36:56work with it. And voila, we have
  1968. 1:36:58everything installed. And now in the
  1969. 1:37:01front um so when working with Vue.js or
  1970. 1:37:04any front end framework, uh you need to
  1971. 1:37:07run the the build command to ensure that
  1972. 1:37:10everything builds. So let's do that. And
  1973. 1:37:12here we are going to hit a out of memory
  1974. 1:37:15problem. So this is why we need to
  1975. 1:37:17create a swap memory. But let's verify
  1976. 1:37:19if that's what will happen or not. Okay.
  1977. 1:37:22So as you can see the terminal is stuck.
  1978. 1:37:25Uh but let's wait a minute. If you want
  1979. 1:37:28you can also go back to the other
  1980. 1:37:30terminal and maybe run hub. But as you
  1981. 1:37:34can see the yeah the the VM is
  1982. 1:37:37struggling. So the I can't run things
  1983. 1:37:40smoothly and that means that I'm running
  1984. 1:37:42out of memory. And yeah, this this this
  1985. 1:37:46command will fail at any second. So
  1986. 1:37:49let's just wait. Yeah, so this one is
  1987. 1:37:52stuck. Let's go back to here.
  1988. 1:37:55And let's wait. Uh I am back to the
  1989. 1:37:58other terminal. And as you can see, the
  1990. 1:38:00memory is full. Uh and this is not
  1991. 1:38:03updating because it's uh struggling. And
  1992. 1:38:06as I told you, the command failed. And
  1993. 1:38:09that's because we don't have enough
  1994. 1:38:11memory to build uh the front end. Is
  1995. 1:38:14that the end? Uh we have a solution. So
  1996. 1:38:17when uh on Linux we have something
  1997. 1:38:19called swap memory. Basically we take
  1998. 1:38:23some portion from the SSD and we use
  1999. 1:38:26that as additional RAM. It's going to be
  2000. 1:38:30slower but it's going to help us uh deal
  2001. 1:38:33with these situations where we run out
  2002. 1:38:35of memory. Let's run the df command.
  2003. 1:38:39Going to show you uh so all available
  2004. 1:38:43and yeah let's type it h to make it
  2005. 1:38:46human readable. As you can see here we
  2006. 1:38:49have 8 GB of disk storage and we have 5
  2007. 1:38:54GB available. I'm going to take two GB
  2008. 1:38:57from this partition and I'm going to
  2009. 1:39:00create a swap file because we don't need
  2010. 1:39:03all this storage uh to run the front end
  2011. 1:39:06and back end. And this is how we create
  2012. 1:39:08a swap file. So we use the f allocate
  2013. 1:39:12command. We specify the size and this is
  2014. 1:39:17the the file that we are going to
  2015. 1:39:18create. And here so let's just run the
  2016. 1:39:21command first and let me provide my
  2017. 1:39:23password. It worked and we didn't get
  2018. 1:39:25any error. That's great. And I want to
  2019. 1:39:28explain something this. So when you see
  2020. 1:39:31/ swap file, this doesn't mean that we
  2021. 1:39:34this is a folder. No, it's a single file
  2022. 1:39:38acting as a virtual RAM. So this means
  2023. 1:39:42that you can just you can't do this. You
  2024. 1:39:45can do this. Um just type in in / LA.
  2025. 1:39:49And as you can see, it's a file. If it's
  2026. 1:39:51that D that means that it's a directory
  2027. 1:39:54but yeah it is a file and it's owned by
  2028. 1:39:57root. Why did we create a file instead
  2029. 1:40:00of a dedicated disk partition? Because
  2030. 1:40:04we can easily resize or delete this file
  2031. 1:40:08if we wanted to if we don't need it
  2032. 1:40:10anymore. This is the flexibility of
  2033. 1:40:12working with files. But we need to set
  2034. 1:40:15up uh some permissions. Uh again let me
  2035. 1:40:17type in ls-la. You can see that these
  2036. 1:40:20are the permissions. We need to change
  2037. 1:40:22them and uh to do that we are going to
  2038. 1:40:25use sudo ch mode 600 and swap file. I
  2039. 1:40:30will explain what the 600 means. Now if
  2040. 1:40:33I type ls-la you can see that some of
  2041. 1:40:36these characters have changed. So w
  2042. 1:40:39means write, r means read and x means
  2043. 1:40:43execute. But here we don't have x. And
  2044. 1:40:46the first three let's say letters are
  2045. 1:40:50related relative to your to the root
  2046. 1:40:53user. The second three are relative to
  2047. 1:40:57uh where is the yeah the second tree are
  2048. 1:40:59here are uh for your user. So in my case
  2049. 1:41:02it's emad and the last ones are for
  2050. 1:41:05other users. So here uh so we did 600 we
  2051. 1:41:10which means that root will be able to
  2052. 1:41:13read and uh to read from swap file and
  2053. 1:41:16write to it but the other users are not
  2054. 1:41:20able to touch this at all. So we created
  2055. 1:41:23the swap file. Now we need to make this
  2056. 1:41:26file as a swap space and to do that we
  2057. 1:41:29are going to use the make swap command
  2058. 1:41:32and we are going to provide that file.
  2059. 1:41:35Hit enter. As you can see, it says
  2060. 1:41:37setting up swap space and here is the
  2061. 1:41:39size and it gives us an ID uh which is
  2062. 1:41:43not important. Now let's enable it. So
  2063. 1:41:46we created the swap space. Now we will
  2064. 1:41:48use swap on and um swap file. Hit enter.
  2065. 1:41:53How do we how do we verify this? We are
  2066. 1:41:56going to use the swap on command. And
  2067. 1:41:58let's type show. And yeah, we have it
  2068. 1:42:02here. So this is the file name and this
  2069. 1:42:05is the size. It says that the file the
  2070. 1:42:07type is file. That's good. And here we
  2071. 1:42:10have priority. The priority level is set
  2072. 1:42:13to minus2. In our case it doesn't matter
  2073. 1:42:16because this this is um used only when
  2074. 1:42:20we have multiple swap files. So if um we
  2075. 1:42:24had another swap file that had a lower
  2076. 1:42:27priority level, then Linux will
  2077. 1:42:29prioritize this one. And when it's
  2078. 1:42:31filled, it's going to move to the other
  2079. 1:42:32one. But in our case, it's not relevant
  2080. 1:42:35because we have just one swap file. By
  2081. 1:42:38default, this swap configuration will be
  2082. 1:42:41lost when the server reboots. To ensure
  2083. 1:42:44that the swap file loads automatically
  2084. 1:42:47every time the system starts, you must
  2085. 1:42:49add it to the FS tab file. Uh let me
  2086. 1:42:53show you the FS tab file that I'm
  2087. 1:42:55talking about. It's this one. Now let's
  2088. 1:42:58try to uh let's see the content. Okay,
  2089. 1:43:00so this is what we have. Uh and we are
  2090. 1:43:03going to yeah put uh this string inside
  2091. 1:43:08there and we are going to use one
  2092. 1:43:09command to do that to make things
  2093. 1:43:11quicker. Here we have echo. It's going
  2094. 1:43:13to spit this string. We use the pipe
  2095. 1:43:16command to take the output from this
  2096. 1:43:18command and give it as input to the t
  2097. 1:43:21command. Let me let's hit enter. Okay,
  2098. 1:43:24great. So it worked. Let's go back and
  2099. 1:43:27as you can see we appended this string
  2100. 1:43:29to the end of the fsst tab command. Now
  2101. 1:43:32that we have added extra memory let's
  2102. 1:43:35try to build the project again. So let's
  2103. 1:43:37run pmppm run build. Uh I will also yeah
  2104. 1:43:42let's uh open another terminal and let's
  2105. 1:43:44go ssh to the server and here I want to
  2106. 1:43:49run htop. Okay. And as you can see htop
  2107. 1:43:52also detects the swap memory. So
  2108. 1:43:54currently it is empty but look what will
  2109. 1:43:57happen when we start the build process.
  2110. 1:44:00Let's see what will happen. As you can
  2111. 1:44:02see we are already filling the swap
  2112. 1:44:04space and look how the the physical RAM
  2113. 1:44:08is quickly filling up. Nothing is
  2114. 1:44:11freezing. That means that it we it
  2115. 1:44:13works. So if you look at the total uh
  2116. 1:44:17space consumed it's yeah greater than
  2117. 1:44:19the total memory that we have inside
  2118. 1:44:23this uh machine and it seems that it
  2119. 1:44:26worked. Yeah it built. So yeah that's
  2120. 1:44:28that's awesome. Before making this
  2121. 1:44:31tutorial sometimes node was not using a
  2122. 1:44:35lot of memory so the build failed due to
  2123. 1:44:39an error called heap limit error. If
  2124. 1:44:42that somehow happens to you, then before
  2125. 1:44:46uh running pmpp run build, we need to
  2126. 1:44:49pass this variable. So here we are going
  2127. 1:44:52to set max all space size to 2 GB. Uh we
  2128. 1:44:56do that before uh starting pmppm. Um in
  2129. 1:45:00my case it worked but if for some reason
  2130. 1:45:03again uh you get that heap limit error,
  2131. 1:45:06you can solve that by using this
  2132. 1:45:08command. Awesome. So we built the
  2133. 1:45:11project and as you can see we have the
  2134. 1:45:13dis folder. It contains everything we
  2135. 1:45:15have in the front end. Uh let's move
  2136. 1:45:18inside that directory cd dist. Uh let's
  2137. 1:45:22see we should have yeah we have our
  2138. 1:45:24assets there. We have the index html
  2139. 1:45:28some images sitemap uh and stuff like
  2140. 1:45:31that. Now we can create a temporary
  2141. 1:45:33Python web server on port 8000. Uh let
  2142. 1:45:37me use Python and we want to use this
  2143. 1:45:40module https
  2144. 1:45:43server and the port is going to be at80.
  2145. 1:45:46Uh I need to use python tree. Okay
  2146. 1:45:50great. So we are serving the built files
  2147. 1:45:54uh on this port. Again we cannot access
  2148. 1:45:57this. So if you try to open this on your
  2149. 1:46:00local machine, it's not going to work
  2150. 1:46:02because the firewall is active and we
  2151. 1:46:05are not uh letting traffic through this
  2152. 1:46:09port. But is are we done? Um maybe yeah,
  2153. 1:46:13we can use the cur command if we want.
  2154. 1:46:15So we can do something like this. But
  2155. 1:46:19yeah, we are we have port 8080 this
  2156. 1:46:22time. And as you can see, we got uh some
  2157. 1:46:24HTML back. Uh so that's that means that
  2158. 1:46:27it's it's working right but we want to
  2159. 1:46:30see this we want to see the UI because
  2160. 1:46:33the back end uh it's it's fine if we run
  2161. 1:46:35cur commands on the back end but when it
  2162. 1:46:38comes to the front end we need to see it
  2163. 1:46:39with our eyes to validates that it is
  2164. 1:46:42working but you might say well we cannot
  2165. 1:46:45do that because the firewall is active
  2166. 1:46:48but I have a solution for you and it's
  2167. 1:46:50called SSH tunneling. Let's go back to
  2168. 1:46:53the slides because I want you to learn
  2169. 1:46:56about this amazing feature. Okay, here
  2170. 1:46:59we are and let's look at SSH tunneling.
  2171. 1:47:02I have this diagram that I made in order
  2172. 1:47:05to explain this concept for you. We have
  2173. 1:47:08our laptop is sitting here. It can be
  2174. 1:47:12running maybe Linux, Mac or Windows. It
  2175. 1:47:15doesn't matter. We have the SSH key
  2176. 1:47:18pairs that we created. Uh here we have
  2177. 1:47:21the private key and we will be uh
  2178. 1:47:24accessing the the website through a
  2179. 1:47:28browser and here on the other side we
  2180. 1:47:30have the server. It's can be running on
  2181. 1:47:32digital ocean, Azure, GCP, AWS doesn't
  2182. 1:47:36matter. We also we will have our front
  2183. 1:47:39end running here. Uh in our case it's
  2184. 1:47:42Vue.js JS but it can also be react or
  2185. 1:47:45any other framework or just pure HTML
  2186. 1:47:48CSS and JavaScript and we have our
  2187. 1:47:50public key in the middle we have a
  2188. 1:47:53tunnel that we call SSH tunnel how do we
  2189. 1:47:56see the app without opening uh let's say
  2190. 1:48:00port 8080 the we use SSH tunneling for
  2191. 1:48:03that think of this as a secure private
  2192. 1:48:06subway line that runs inside your
  2193. 1:48:09existing SSH connection we don't need to
  2194. 1:48:12change the firewall because we are
  2195. 1:48:14already allowed to access the server via
  2196. 1:48:16SSH to create a tunnel. We use the -l
  2197. 1:48:21flag. And this syntax tells SSH to bind
  2198. 1:48:26port 8080 on your laptop. It's this one
  2199. 1:48:30colored in pink to port 8080 on the
  2200. 1:48:34server. After running this command, a
  2201. 1:48:37tunnel will be created. Now if I open my
  2202. 1:48:40browser and type localhost and specify
  2203. 1:48:44port 8080 in my browser the request is
  2204. 1:48:48not going to stay on my computer. It's
  2205. 1:48:51going to travel through the tunnel. It's
  2206. 1:48:54going to reach the server the this uh
  2207. 1:48:57and here it's going to reach the server
  2208. 1:48:59on this port 8080 because this is what
  2209. 1:49:01we specified here. It's going to see
  2210. 1:49:03that we have a server running. This is
  2211. 1:49:06why we have uh yeah we run that Python
  2212. 1:49:09command to create a temporary server.
  2213. 1:49:11Okay. So it's going to forward that to
  2214. 1:49:14the front end. The front end will
  2215. 1:49:16respond with that HTML. It's going to go
  2216. 1:49:18back through the tunnel. It's going to
  2217. 1:49:20hit the browser and the browser uh sees
  2218. 1:49:24HTML. It's going to load it. So this is
  2219. 1:49:26the concept uh of SSH tunneling and it's
  2220. 1:49:29really great. And as you can see, we
  2221. 1:49:31didn't update the firewall configuration
  2222. 1:49:34to allow port at it enabled directly
  2223. 1:49:38because we are already using SSH. But if
  2224. 1:49:41we stop this command, the tunnel will go
  2225. 1:49:44yeah will go away and these ports are
  2226. 1:49:47going to be are not going to be
  2227. 1:49:48connected. Awesome. So yeah, let's do
  2228. 1:49:51this. Uh uh let's create. So here I'm
  2229. 1:49:54already inside the machine. I need to
  2230. 1:49:57exit by using Ctrl D or exit. And now
  2231. 1:50:00yeah, let's run let's write that
  2232. 1:50:03command. So it's SSH-L.
  2233. 1:50:06Uh let's type the local port on my
  2234. 1:50:09machine. Here we need to specify
  2235. 1:50:11localhost AT80 and let's use my alias my
  2236. 1:50:16website. As you can see, we are inside
  2237. 1:50:19and now we have a tunnel. Let's go back.
  2238. 1:50:23You can see that we have the server
  2239. 1:50:24running. Now let's go. Yeah, let's open
  2240. 1:50:28Firefox. And now we can go to localhost
  2241. 1:50:32at80. And voila. As you can see, it
  2242. 1:50:35works. You saw that we we got some
  2243. 1:50:37errors because we are making uh requests
  2244. 1:50:40to the back end, but we don't have a
  2245. 1:50:42back end running. Uh yeah, so you can
  2246. 1:50:45see that if I go to the blogs page,
  2247. 1:50:47yeah, nothing will show up because we
  2248. 1:50:49don't have the back end running yet. But
  2249. 1:50:51that's not a problem. What we want to
  2250. 1:50:53see is uh basically the UI. Does it look
  2251. 1:50:57right? Um did we load the images? Um is
  2252. 1:51:01the font loaded? Do we have animations
  2253. 1:51:04running? Stuff like that. This is what
  2254. 1:51:06we wanted to verify. But connecting the
  2255. 1:51:08front end to the back end or to other
  2256. 1:51:11services uh should be uh easily done
  2257. 1:51:15when we connect it to the back end.
  2258. 1:51:18Awesome. And yeah, let's go back. Uh now
  2259. 1:51:20what will happen if I do this? So let's
  2260. 1:51:23close this. Now we have no SSH tunnel.
  2261. 1:51:27Let's go back and let's refresh. Can see
  2262. 1:51:29that it doesn't work because now the the
  2263. 1:51:32two machines are not connected. Great.
  2264. 1:51:35So everything is working perfectly.
  2265. 1:51:38Nice. We installed the Python the back
  2266. 1:51:41end and front end dependencies. We made
  2267. 1:51:43sure that both servers run correctly. Uh
  2268. 1:51:47everything worked really well.
  2269. 1:51:50Now we need to move to installing J
  2270. 1:51:54unicorn and supervisor. But why do we
  2271. 1:51:57need them? Let's go back to the slides
  2272. 1:51:59again to explain this. Here is the
  2273. 1:52:02diagram that I created for this slide in
  2274. 1:52:05order to explain this. Uh as you can
  2275. 1:52:07see, we have three components. We have
  2276. 1:52:09supervisor, junior and uvicorn. We have
  2277. 1:52:14used the uvicorn command to run the
  2278. 1:52:17python server. After that, we used curl
  2279. 1:52:20to ensure that the the back end responds
  2280. 1:52:24correctly. So that's done. But we did
  2281. 1:52:26this manually. What will happen if the
  2282. 1:52:28server crashes? We need to again SSH to
  2283. 1:52:32the server and run the UV command again.
  2284. 1:52:35Is this scalable? No. What will happen
  2285. 1:52:38if your server crashes at 4:00 a.m. or
  2286. 1:52:41something? Are you going to uh wait
  2287. 1:52:44until 8:00 a.m. when you wake up and
  2288. 1:52:47launch it? No. We want the system, we
  2289. 1:52:49want the server to do this for us
  2290. 1:52:51automatically. And this is why we need
  2291. 1:52:53these three components or this
  2292. 1:52:55architecture. At the bottom, we have our
  2293. 1:52:58workers. The worker he's is is Uicorn.
  2294. 1:53:02The the worker is going to run your fast
  2295. 1:53:05API code. So if someone visits the
  2296. 1:53:08website and wants to get blogs, the
  2297. 1:53:11worker will get that request. It's going
  2298. 1:53:13to talk to me search and it's going to
  2299. 1:53:16get the response and send it back to the
  2300. 1:53:19user. Or let's say that someone wanted
  2301. 1:53:22to maybe do a search query or maybe uh
  2302. 1:53:26like a blog. U yeah that that worker
  2303. 1:53:30will also do that. And let's say that we
  2304. 1:53:32had a huge traffic um let's say that we
  2305. 1:53:36we have maybe 100 people trying to
  2306. 1:53:39access the server at the same time. Then
  2307. 1:53:41the load is going to be balanced through
  2308. 1:53:44these workers here. Let's say that we
  2309. 1:53:46have three workers. So this one is going
  2310. 1:53:48to get maybe 33 requests. The other one
  2311. 1:53:50is going to get 40 and the other one
  2312. 1:53:52gets 30. So yeah and J Unicorn will do
  2313. 1:53:56that. It's going to balance the load
  2314. 1:53:57through all these workers. Now we know
  2315. 1:54:00the role of Uicorn but why do we need J
  2316. 1:54:03Unicorn? J Unicorn acts as the manager.
  2317. 1:54:07It spawns multiple Uicorn workers and
  2318. 1:54:11this is can be configured. So if you
  2319. 1:54:12want to you have just one URON instance
  2320. 1:54:15or worker you can do that. If you want
  2321. 1:54:17to have three or 10 or whatever yeah you
  2322. 1:54:21can do that. Um you can just change the
  2323. 1:54:23configuration. We will see this after
  2324. 1:54:26explaining this slide. Let's say that
  2325. 1:54:28this worker crashed for some reason.
  2326. 1:54:31Jorn will detect that. It's going to
  2327. 1:54:34delete it and replace it with a new with
  2328. 1:54:37a new uh worker. And this is going to be
  2329. 1:54:41done automatically for you. You don't
  2330. 1:54:43need to enter to SSH to the server and
  2331. 1:54:46start the worker manually. That's not
  2332. 1:54:49scalable. But this this is above that we
  2333. 1:54:53have the supervisor or we can also call
  2334. 1:54:56it watchdog. Uh in engineering this term
  2335. 1:54:59means a hardware component that
  2336. 1:55:02basically will hit the reset button if
  2337. 1:55:05the system freezes for some reason.
  2338. 1:55:07Let's say that something bad is
  2339. 1:55:09happening. The unicorn is not doing
  2340. 1:55:12good. The unicorn curs are also
  2341. 1:55:16crashing. Supervisor will detect that
  2342. 1:55:18and uh hit the resize button which means
  2343. 1:55:21that uh we are going to recreate
  2344. 1:55:22everything from uh scratch just to
  2345. 1:55:25ensure that yeah the the our application
  2346. 1:55:28is healthy again and is ready to receive
  2347. 1:55:31requests from users. So yeah, this is
  2348. 1:55:34the this is why we need J unicorn and
  2349. 1:55:37unicorn and also supervisor and you saw
  2350. 1:55:41we tested manually. Always do that. Try
  2351. 1:55:44to test uh your application manually by
  2352. 1:55:47running the commands like what we did.
  2353. 1:55:50So we run uh uicorn to start the backend
  2354. 1:55:54server. After that we moved to the front
  2355. 1:55:57end server. After validating that we can
  2356. 1:56:01automate this process. Let's go back to
  2357. 1:56:03the server and let's do this. Okay. Uh
  2358. 1:56:07now let's stop the front the temporary
  2359. 1:56:10front end server because we don't need
  2360. 1:56:12it. Uh let's also go back to back end.
  2361. 1:56:18Activate the environment and let's
  2362. 1:56:21install J Unicorn. I'm not sure if I
  2363. 1:56:24already have it in the requirements
  2364. 1:56:26file. Let's just double check. And yes,
  2365. 1:56:28we have it. So yeah, that's great. So we
  2366. 1:56:30don't need to install it separately. Uh
  2367. 1:56:33let's make sure that it is there. Yeah,
  2368. 1:56:35it is there. So we it just didn't
  2369. 1:56:38receive any application. So that's fine.
  2370. 1:56:40So we have J Unicorn and we also have UV
  2371. 1:56:43core. Now let's try Yeah, we need to
  2372. 1:56:45create a J Unicorn start script that
  2373. 1:56:49will tell J Unicorn how to run uh your
  2374. 1:56:52application. Let's call it J Unicorn
  2375. 1:56:55start. And let's use nano. I will paste
  2376. 1:56:59all this directly here. But don't worry,
  2377. 1:57:03you you should be able to find this on
  2378. 1:57:06my blog. Yeah, I will make sure to
  2379. 1:57:09deploy it uh in the future. So if you go
  2380. 1:57:11to blogs, you will be able to see the
  2381. 1:57:14individual articles here. So if you want
  2382. 1:57:17to copy paste them uh quickly, you can
  2383. 1:57:20do that. Don't worry about it. Or you
  2384. 1:57:22can go to GitHub. I have this repository
  2385. 1:57:25where I yeah basically documents these
  2386. 1:57:28uh videos in a in text format. So we
  2387. 1:57:32have foundation. So now we are in
  2388. 1:57:35chapter 2. So you can click here and
  2389. 1:57:37you'll should yeah will find everything
  2390. 1:57:39here. So can just copy the commands and
  2391. 1:57:42uh paste them uh in your VM. So okay
  2392. 1:57:46let's continue. We forgot to add the
  2393. 1:57:49shebang. So let's add it. Uh we are
  2394. 1:57:53going to use bash. We have some
  2395. 1:57:55placeholders that we need to change.
  2396. 1:57:57Let's start with the user. So my user is
  2397. 1:58:01IMAD and the group is also IMAD. So
  2398. 1:58:05let's provide that. We have the number
  2399. 1:58:08of workers. Let's set it to one because
  2400. 1:58:10we don't have a lot of traffic and we
  2401. 1:58:13are just testing. So as you can see I
  2402. 1:58:16have this comment. increase this if you
  2403. 1:58:17have more traffic or or a more complex
  2404. 1:58:20application. But when you increase the
  2405. 1:58:22number of workers, you will consume more
  2406. 1:58:24RAM. So keep that in mind. The
  2407. 1:58:26application directory is web app back
  2408. 1:58:28end. That's correct. And we have this
  2409. 1:58:31stocket file. We'll come back to this
  2410. 1:58:33later. And here we need to give the
  2411. 1:58:35project a name. Let's call this my
  2412. 1:58:38website or something or a mad website.
  2413. 1:58:41And here the worker is going to be
  2414. 1:58:43Uicorn. That's fine. here forward allow
  2415. 1:58:47ips. Yeah. So here here we just want to
  2416. 1:58:50pass the IP of the user directly uh
  2417. 1:58:53because yeah we will talk about
  2418. 1:58:54engineext and unique sockets later so
  2419. 1:58:57don't worry about this. Here we are just
  2420. 1:58:59showing that we are starting this
  2421. 1:59:01website. We move to the directory. We
  2422. 1:59:05activate the environment. Here we create
  2423. 1:59:07the socket file. Uh let's go back to
  2424. 1:59:10sock file. We need to create this. Uh so
  2425. 1:59:12this is important because it's going to
  2426. 1:59:14communicate with engineext but we will
  2427. 1:59:17talk about this later don't worry about
  2428. 1:59:18it and here start junicorn so here we
  2429. 1:59:22have the execute command j unicorn is
  2430. 1:59:25inside the virtual environment we could
  2431. 1:59:27have just uh yeah since we activated the
  2432. 1:59:29environment we could just type j unicorn
  2433. 1:59:32that's fine the application is inside
  2434. 1:59:34the main file and we pass these
  2435. 1:59:37arguments so the name of the project the
  2436. 1:59:40number of workers
  2437. 1:59:42the worker class which is uicorn. Here
  2438. 1:59:45it is. Uh time out the user and the
  2439. 1:59:48group. We bind this to the socket file.
  2440. 1:59:52Uh we forward the IPs and we have some
  2441. 1:59:55login. Great. So now save this. Uh I'll
  2442. 1:59:59hit Ctrl S and then Ctrl X. And now we
  2443. 2:00:02need to make this executable. So let's
  2444. 2:00:05do sud ch mode plus x or before that I
  2445. 2:00:09want I want you to understand the ch
  2446. 2:00:12mode command. So before that let's run
  2447. 2:00:14ls-la j unicorn start. You can see it's
  2448. 2:00:18not executable. But if I run ch mode
  2449. 2:00:22plus x j uh unicorn start and run the
  2450. 2:00:28ls-la you can see now we have x and x is
  2451. 2:00:32is available in the three users. So ruse
  2452. 2:00:35can execute this file my user ID can
  2453. 2:00:39execute this file and other users can do
  2454. 2:00:42the same. Great and you can see that I
  2455. 2:00:45am the owner of this file. So we
  2456. 2:00:47configured the unicorn. Now we need to
  2457. 2:00:50configure supervisor. We could again we
  2458. 2:00:54could run this uh script manually but if
  2459. 2:00:58it if for some reason J unicorn crashes
  2460. 2:01:01we need to come back and uh rerun it
  2461. 2:01:04again. We want we don't want to do that.
  2462. 2:01:06We want supervisor to do this for us.
  2463. 2:01:09Supervisor is not installed by default.
  2464. 2:01:13Yeah, it's not recognized but we can
  2465. 2:01:16install it using the op command. So
  2466. 2:01:18let's do that. Supervisor.
  2467. 2:01:21Let me provide my password. And it is
  2468. 2:01:24installing. Great. Let's wait a little
  2469. 2:01:26bit. Uh let's also create the logs
  2470. 2:01:29folder because we we want supervisor to
  2471. 2:01:32save logs um there so that we can uh if
  2472. 2:01:37something hap bad happens we can uh see
  2473. 2:01:40what happened there. So that's important
  2474. 2:01:42and again verify that you are owning
  2475. 2:01:45that uh directory. So run this and yeah
  2476. 2:01:49we are running that since we don't use
  2477. 2:01:52the sudo command we will be uh owning
  2478. 2:01:54everything but just in case uh it's a
  2479. 2:01:56good practice to keep checking the
  2480. 2:01:58ownership. In order to configure
  2481. 2:02:00supervisor we need to create this
  2482. 2:02:03configuration file. So supervisor lives
  2483. 2:02:06inside the etc folder and here we want
  2484. 2:02:09to create our own configuration and let
  2485. 2:02:13me paste this. Uh okay so we have so as
  2486. 2:02:17you can see we want supervisor to run
  2487. 2:02:19the J unicorn start start command. Uh so
  2488. 2:02:23the only thing we need to change here is
  2489. 2:02:25the user. It's going to be emad and here
  2490. 2:02:29we need to change this placeholder and
  2491. 2:02:32let's call it a mad website. Okay. And
  2492. 2:02:36the log file we are going to store to
  2493. 2:02:38yeah to store logs inside this. This is
  2494. 2:02:40why we created this directory. And yeah
  2495. 2:02:43um save this. Hit ctrl x. Great. Now we
  2496. 2:02:47can start this service. Let's use pseudo
  2497. 2:02:51supervisor
  2498. 2:02:53ctl. And here we are going to reread the
  2499. 2:02:56new configuration. It says available. It
  2500. 2:02:59detected this uh new config that we
  2501. 2:03:02created. And now we need to let's run
  2502. 2:03:05this. Great. So we added this to the
  2503. 2:03:08process group. And now let's check the
  2504. 2:03:11status. It should be running. So if I
  2505. 2:03:13type status uh and here you need to type
  2506. 2:03:16that project name. Great. It says run
  2507. 2:03:19in. It didn't crash. That's great. Let's
  2508. 2:03:23see. So, we have logs. So, let's look at
  2509. 2:03:26logs. Supervisor log. The file exists.
  2510. 2:03:29Awesome. Let's do cat or maybe tail.
  2511. 2:03:33Awesome. So, it's working. You can see
  2512. 2:03:34that. Uh, let me let me look at the full
  2513. 2:03:38output. So, these are just this is just
  2514. 2:03:40configuration. Um, yeah, great. And here
  2515. 2:03:45the application started. So we are
  2516. 2:03:47starting J unicorn. Uh it's listening at
  2517. 2:03:50this socket and here we have just one
  2518. 2:03:52worker and the application startup
  2519. 2:03:55complete. So this means that it's
  2520. 2:03:56working. We can try and uh yeah let's do
  2521. 2:04:00some curl commands. Oops, we don't have
  2522. 2:04:02it here. Uh that's fine. Okay. Uh this
  2523. 2:04:06is the curl command that we used
  2524. 2:04:08earlier. Uh let's try to run it. And it
  2525. 2:04:11fail. It says fail to connect to local
  2526. 2:04:14host. Why this command failed? We have
  2527. 2:04:17tested this before and it worked fine.
  2528. 2:04:20Let me show you why this failed.
  2529. 2:04:23Remember we have uh yeah let's look at
  2530. 2:04:26the G unicorns tart uh file. You can see
  2531. 2:04:29that we are using this socket file. So
  2532. 2:04:34in order to communicate with the server,
  2533. 2:04:36we need to use the socket file that was
  2534. 2:04:39created here in back end. And let's
  2535. 2:04:41verify that it is there. Yeah, as you
  2536. 2:04:44can see, we have JU Unicorn stock and if
  2537. 2:04:47I look at it, yeah, it's it's it's a
  2538. 2:04:50different type of files in Linux. You
  2539. 2:04:53can see that it says S, which means
  2540. 2:04:55socket and this is used um it's like a
  2541. 2:04:58pipe. It's used to uh by different
  2542. 2:05:00applications to communicate with each
  2543. 2:05:02other. In our case, we want uh the
  2544. 2:05:04backend server to communicate with
  2545. 2:05:06EngineX. Uh but we don't have EngineX
  2546. 2:05:10yet. We are just preparing for that
  2547. 2:05:12step. uh but uh to fix that we can do
  2548. 2:05:15this. So with curl we can specify the
  2549. 2:05:19Unix socket file and here here is the
  2550. 2:05:22the socket file that we want to use and
  2551. 2:05:25same here we are going to use this
  2552. 2:05:27endpoint and curl will use this socket
  2553. 2:05:30as a way to talk to the backend server
  2554. 2:05:34and the backend server will send the
  2555. 2:05:36response through the socket to curl and
  2556. 2:05:39curl would display that. As you can see,
  2557. 2:05:41I I run that and I got status. Okay,
  2558. 2:05:45awesome. Now we can uh run tail again
  2559. 2:05:49just to verify and yeah, we got this. So
  2560. 2:05:51we uh so this is the get requests. We
  2561. 2:05:55got 200. Okay. And yeah, it took less
  2562. 2:05:58than 2 milliseconds. Awesome. So yeah,
  2563. 2:06:01everything is working. Now if we run
  2564. 2:06:04htop or I want you to install this. So
  2565. 2:06:08we have a replacement um we have many uh
  2566. 2:06:12applications like htop with good UI. One
  2567. 2:06:16of them is called Btop and I really like
  2568. 2:06:19Btop. Uh it looks like yeah this is a
  2569. 2:06:22Btop and it's available on a lot of
  2570. 2:06:25Linux distros. It's also available in
  2571. 2:06:27Auntu. So that's great. And to install
  2572. 2:06:30it we can as you can see it looks really
  2573. 2:06:33really nice. So we are going to use this
  2574. 2:06:34in order to monitor the processes,
  2575. 2:06:36memory usage, etc. And to install it, we
  2576. 2:06:40can run the APC command uh sudo up to
  2577. 2:06:43install btop. Awesome. Now run btop and
  2578. 2:06:46as you can see uh it looks really nice.
  2579. 2:06:48So here you have the CPU usage, you have
  2580. 2:06:51memory usage. Uh let me decrease the
  2581. 2:06:54yeah the the font size. Okay. So we have
  2582. 2:06:57uh so we have 8 GB of storage. We are
  2583. 2:07:00using 65%.
  2584. 2:07:03This is the swap um space that we
  2585. 2:07:05created. It's not used. So we are just
  2586. 2:07:08using 6%. This is the available memory.
  2587. 2:07:11It's uh yeah almost 500 megabytes. We
  2588. 2:07:14are using 35% of the memory. Uh and yeah
  2589. 2:07:18we have also the network. Uh so we have
  2590. 2:07:20the download and upload speeds. Um and
  2591. 2:07:24here we have the processes. This is what
  2592. 2:07:26we care about. And here you have filter.
  2593. 2:07:29With the arrow keys, you can uh let's go
  2594. 2:07:32to memory because that's what we want.
  2595. 2:07:34And this is going to sort everything by
  2596. 2:07:36memory. If you want, you can hit R to
  2597. 2:07:39reverse this. But we want to yeah, we
  2598. 2:07:41want this sorted in a descending order.
  2599. 2:07:44And here type filter and run uh and type
  2600. 2:07:48J unicorn. Why? We want to see the
  2601. 2:07:51processes that are running. Here we have
  2602. 2:07:53just one worker but you you can see that
  2603. 2:07:56we have two processes. Why is that? So
  2604. 2:08:01one J unicorn creates two services. So
  2605. 2:08:05one will manage the workers. So one of
  2606. 2:08:08them is the worker and the other one is
  2607. 2:08:12uh the one controlling those workers and
  2608. 2:08:15as you can see they are using uh roughly
  2609. 2:08:1824 megabytes. That's not a lot because
  2610. 2:08:20the application is not doing anything
  2611. 2:08:22right now. But this is why I mentioned
  2612. 2:08:26that if you increase the number of
  2613. 2:08:27workers,
  2614. 2:08:29you are going to consume more memory.
  2615. 2:08:32Why I why I installed bet? Because I
  2616. 2:08:34want you to I want you to learn about
  2617. 2:08:38zombie processes. Um yeah, this is
  2618. 2:08:41something very important because
  2619. 2:08:42sometimes uh this happened to me. I
  2620. 2:08:46didn't pay attention and I my memory
  2621. 2:08:48usage was rising up quickly because I
  2622. 2:08:51was I was not restarting J Unicorn
  2623. 2:08:54correctly uh because sometimes when I do
  2624. 2:08:57when I work on a new feature uh I push
  2625. 2:09:00that to the server and uh restart the
  2626. 2:09:03back end that created zombie processes.
  2627. 2:09:06Basically some uh G unicorn processes
  2628. 2:09:09were left here. they weren't doing work
  2629. 2:09:11but they were consuming memory because
  2630. 2:09:13they were from the old deployments. So
  2631. 2:09:15let's see uh we don't have this problem
  2632. 2:09:17right now. Uh we we have just created
  2633. 2:09:20this uh but I will try to do uh to
  2634. 2:09:23basically create zombie processes just
  2635. 2:09:26to show you how this looks like and how
  2636. 2:09:28to deal with this problem. Uh but first
  2637. 2:09:30we need to go and SSH through the
  2638. 2:09:32website. Great. So if you don't want to
  2639. 2:09:36look at this, we can run um this command
  2640. 2:09:39ps and we are going to grab and we are
  2641. 2:09:43going to use I think aad websites. We
  2642. 2:09:47have two of them. So yeah, this one and
  2643. 2:09:50the other one. Uh this looks ugly
  2644. 2:09:53because we have a lot of text but no
  2645. 2:09:55problem. It confirms that we have two
  2646. 2:09:57processes running. Now let me manually
  2647. 2:10:00let's first go to web app back end and I
  2648. 2:10:04want to run this manually just to create
  2649. 2:10:07more processes. Uh let's do this. So J
  2650. 2:10:10unicorn now hit enter. This is going to
  2651. 2:10:12create uh yeah this is going to run
  2652. 2:10:15again the the back end and it's going to
  2653. 2:10:17create more processes. Uh let's wait a
  2654. 2:10:20little bit. You can see that the memory
  2655. 2:10:21usage is getting higher and higher every
  2656. 2:10:24single time. Okay, good. And now if we
  2657. 2:10:27want to we can also go inside uh that
  2658. 2:10:30file
  2659. 2:10:32G unicorn start. And um yeah let's
  2660. 2:10:36change this from 1 2 3 save exit. And
  2661. 2:10:40now we need to restart. We will run this
  2662. 2:10:42command because we changed the
  2663. 2:10:44configuration. We need to read that and
  2664. 2:10:47restart again. Let's do this. So restart
  2665. 2:10:50and let's uh use my project name. Uh I
  2666. 2:10:53need to pass my password. Okay, it says
  2667. 2:10:56stopped. Let's look at this. Okay, so uh
  2668. 2:10:59the old processes were gone and now we
  2669. 2:11:01have three new ones. Uh we should have
  2670. 2:11:04just the manager is going to be
  2671. 2:11:06controlling the the workers and we
  2672. 2:11:09should have three workers because this
  2673. 2:11:10is the new configuration that we
  2674. 2:11:12created. But we also have how many? So
  2675. 2:11:15one we have 1, two, three, four. But we
  2676. 2:11:17have three orphaned processes or we can
  2677. 2:11:21also call them zombie processes that are
  2678. 2:11:23look consuming memory but not doing any
  2679. 2:11:26useful work. And if you get this somehow
  2680. 2:11:31uh this is how you solve this issue. You
  2681. 2:11:33can't just come here and hit okay to
  2682. 2:11:36kill the process because it's not clear
  2683. 2:11:40which one is uh doing work. I mean you
  2684. 2:11:44can sort of uh get that information by
  2685. 2:11:47looking at the memory because the the
  2686. 2:11:50workers that are busy are going to be
  2687. 2:11:52using more memory but yeah the you need
  2688. 2:11:55to confirm this and I'll show you how to
  2689. 2:11:57do that. Uh let's run uh ps.
  2690. 2:12:01As you can see we have uh yeah we have
  2691. 2:12:04plenty of processes. Great. Now I have
  2692. 2:12:08this uh command that we can run. uh it
  2693. 2:12:11it's basically giving us the same info
  2694. 2:12:13that we have here in Btop. I'm just
  2695. 2:12:15showing you that running commands like
  2696. 2:12:17these, it's not that fun, but looking at
  2697. 2:12:20this uh in a terminal app, it's really
  2698. 2:12:23uh useful and it's fast. But you can do
  2699. 2:12:26the same thing with just Linux commands.
  2700. 2:12:29And here are the processes and how much
  2701. 2:12:31memory they are using. We can also try
  2702. 2:12:33to uh sum the memory. So we are using
  2703. 2:12:37almost 300 mgabytes. But yeah, we have
  2704. 2:12:40some processes that we need to remove to
  2705. 2:12:42free some memory. So the quick fix is to
  2706. 2:12:45kill all J unicorn uh processes. And to
  2707. 2:12:49do that you can either do you can do it
  2708. 2:12:52here uh by hitting K and and you say yes
  2709. 2:12:56I want to kill this but uh if you want
  2710. 2:12:59to kill everything you can use uh
  2711. 2:13:01process kill and this is the name of the
  2712. 2:13:04process. uh but this will cause
  2713. 2:13:07downtime. Your your application your
  2714. 2:13:09users won't be able to access your
  2715. 2:13:12application. Uh the front end will try
  2716. 2:13:14to make requests to the back end but
  2717. 2:13:15it's it's not going to respond. So they
  2718. 2:13:17will get errors. So this is the easiest
  2719. 2:13:21uh you do this and then supervisor will
  2720. 2:13:24start everything up because it sees that
  2721. 2:13:26something bad happened. Where are the J
  2722. 2:13:28unicorn services? It's going to panic
  2723. 2:13:30but it's going to uh yeah run them.
  2724. 2:13:34Let's actually do it. So let's look at
  2725. 2:13:36this. So we have uh all these J unicorn
  2726. 2:13:39services. Let's kill them. Now let's go
  2727. 2:13:41back here. You can see they are gone but
  2728. 2:13:44supervisor create them created them
  2729. 2:13:46quickly. You can see that we have four.
  2730. 2:13:48That's the correct amount. We have the
  2731. 2:13:50manager. Uh one of them is the manager
  2732. 2:13:53and the other ones are workers. And you
  2733. 2:13:56can see this is why we used supervisor
  2734. 2:13:58in order to uh solve this issue for us.
  2735. 2:14:01Great. Yeah. This is the the easiest uh
  2736. 2:14:06solution and the quickest but if you it
  2737. 2:14:08will cause some downtime but yeah it
  2738. 2:14:11depends on your application. If you
  2739. 2:14:12don't have a lot of users just do this
  2740. 2:14:14one it's fine. Uh but if you have more
  2741. 2:14:17users then yeah we shouldn't do it. Let
  2742. 2:14:20me show you the other option. So I will
  2743. 2:14:23again run the J unicorn start command.
  2744. 2:14:28Uh okay, we created more or more
  2745. 2:14:32processes.
  2746. 2:14:33Let's restart. Okay, so you can see that
  2747. 2:14:36the restart command is the one that's
  2748. 2:14:38causing the issue. It's yeah, it re it
  2749. 2:14:41reads the new configuration,
  2750. 2:14:43but it doesn't delete the old processes.
  2751. 2:14:47It just creates new ones. So this is the
  2752. 2:14:50the big issue that we need to solve. And
  2753. 2:14:52this is what I was doing uh in my
  2754. 2:14:55websites running currently on
  2755. 2:14:56production. I was just pushing new
  2756. 2:14:59changes and I run restart before
  2757. 2:15:03removing the old ones and this created a
  2758. 2:15:06lot of orphaned uh processes. So we can
  2759. 2:15:09see that now we need to remove uh three
  2760. 2:15:11more processes. Okay, I show you uh I
  2761. 2:15:14have showed you the easy method. Now
  2762. 2:15:17let's try to solve this uh surgically
  2763. 2:15:21without causing any uh downtime. First
  2764. 2:15:25we need to ask supervisor for the
  2765. 2:15:29process ID of the J unicorn process
  2766. 2:15:32which which we can also call master
  2767. 2:15:34because it is controlling the other
  2768. 2:15:36workers and to do that we use sudo
  2769. 2:15:40supervisor ctl P ID and here uh you type
  2770. 2:15:43your project name so this is the P ID of
  2771. 2:15:47the master process this is very
  2772. 2:15:50important in in your case it's not going
  2773. 2:15:52to be the same it's going to be a number
  2774. 2:15:54But just uh remember it. Now let's look
  2775. 2:15:57at the process hierarchy. We can use
  2776. 2:16:00this command. Okay. So yeah, we have a
  2777. 2:16:03lot of text. We can also do the same
  2778. 2:16:05thing here uh in Btop. You can see that
  2779. 2:16:07you have this tree column. Just uh hit E
  2780. 2:16:12and as you can see it groups everything.
  2781. 2:16:14So this is the master process. You can
  2782. 2:16:17see that it's uh it is controlling these
  2783. 2:16:19three processes and these ones they
  2784. 2:16:22don't have a parent. So they are just
  2785. 2:16:24here they are orphaned processes that
  2786. 2:16:27are consuming a lot of memory uh but uh
  2787. 2:16:31doing no work. So we need to kill them.
  2788. 2:16:33So now this makes it easy. So I can just
  2789. 2:16:36hit K and kill them one by one. But we
  2790. 2:16:39can also see this in the ps-f
  2791. 2:16:42command. Uh yeah I know this is this is
  2792. 2:16:45a lot of text. So let me just copy this
  2793. 2:16:48and let me open a text editor. So I'll
  2794. 2:16:52open them in VS code. Uh so yeah this
  2795. 2:16:56this stuff is not needed. So you can see
  2796. 2:16:58that these are all the commands that we
  2797. 2:17:01uh are used in order to run the s the
  2798. 2:17:04yeah the junior core service. We don't
  2799. 2:17:07want them. So let's just delete this
  2800. 2:17:08stuff. Uh we don't need this two
  2801. 2:17:12uh and this. Okay great. Let's zoom in a
  2802. 2:17:15little bit on this part. Okay great. So
  2803. 2:17:19let me also go back to the terminal. Let
  2804. 2:17:22me also copy the master ID. So this is
  2805. 2:17:26the master process ID. It's this one.
  2806. 2:17:30You can see that how many we have three
  2807. 2:17:33of uh we have 1 2 3 4 5 6 7 and eight.
  2808. 2:17:38Where is the the process the manager?
  2809. 2:17:40Here is the manager. So uh and here I
  2810. 2:17:43forgot to add the column names. Uh I
  2811. 2:17:47think uh let let me go back. I just want
  2812. 2:17:49to confirm something. Let's go here.
  2813. 2:17:52This is the process ID. This is the
  2814. 2:17:55parent process ID. RSS. Yeah, we don't
  2815. 2:17:58need this one. So let's remove it. We
  2816. 2:18:00just want these two. Let's see. We have
  2817. 2:18:04uh yeah, these are the three UVON
  2818. 2:18:07workers and they are attached to this
  2819. 2:18:11master process ID. And if we look at
  2820. 2:18:14this, it's going to point out to this
  2821. 2:18:16one. And this is that fourth J unicorn
  2822. 2:18:20service. It's this this is the same as
  2823. 2:18:23this. We have these. So let me double
  2824. 2:18:26click on this one. As you can see, here
  2825. 2:18:28is the process ID. It's 531 402 531 402.
  2826. 2:18:33And it is attached to the parent. Uh
  2827. 2:18:36let's look at the parent. Yes, it's this
  2828. 2:18:38one. 531399.
  2829. 2:18:41This this is your group. It's exactly
  2830. 2:18:44it's exactly this. You have one process
  2831. 2:18:47ID and one master process and their
  2832. 2:18:51children. But we have these three
  2833. 2:18:54strugglers, these three orphaned
  2834. 2:18:56processes. They are these ones. So 274,
  2835. 2:19:00272 and 273. Here they are. And the PP
  2836. 2:19:04ID is equal to one. Hm. What does this
  2837. 2:19:07mean in Linux? P1
  2838. 2:19:11is the system in it process. This means
  2839. 2:19:15these processes lost their parent but at
  2840. 2:19:19least they were adopted by the init
  2841. 2:19:22process because they they need to be
  2842. 2:19:24attached to something. This is how you
  2843. 2:19:27detect orphaned processes. If they are
  2844. 2:19:30not attached to a process ID uh if they
  2845. 2:19:34lost their parents they will be attached
  2846. 2:19:36to in it. And now we can safely delete
  2847. 2:19:38these. And we have the process ids. So
  2848. 2:19:41we can do it uh here with the help of
  2849. 2:19:44the top. Let's do it once for this one.
  2850. 2:19:47So we hit okay. And yes.
  2851. 2:19:51And it should Yeah, it's gone. Bye. We
  2852. 2:19:54no longer have that zombie process, but
  2853. 2:19:56we have the other two. Uh if you want to
  2854. 2:19:58do this with the terminal, you can just
  2855. 2:20:00uh use pseudo kill. And here you provide
  2856. 2:20:03the IP addresses or the process ID
  2857. 2:20:06sorry. Uh you pass them like this one
  2858. 2:20:09after the other. Now hit enter. Go to
  2859. 2:20:12Btop and they are gone and we freed
  2860. 2:20:15memory. You can see that uh we we had to
  2861. 2:20:17do a lot of stuff in order to detect the
  2862. 2:20:19processes that uh are not used by uh our
  2863. 2:20:23back end. But this this is useful if you
  2864. 2:20:27don't want to cause any downtime at all.
  2865. 2:20:29Your application code is on the server.
  2866. 2:20:32We built it. We run it and we everything
  2867. 2:20:37went smooth. The back end is managed by
  2868. 2:20:39supervisor and listening on a private
  2869. 2:20:43socket file. However, no one from the
  2870. 2:20:46outside world can access your
  2871. 2:20:48application yet. This is a problem that
  2872. 2:20:50we will fix in the next sub chapter. We
  2873. 2:20:53are going to talk about engine X
  2874. 2:20:56security headers and stuff like that.
  2875. 2:20:59See you in the next episode. Hi
  2876. 2:21:01everyone. In the previous section, you
  2877. 2:21:04successfully started your backend and
  2878. 2:21:07set up a process manager. Your API is
  2879. 2:21:10alive and listening on a Unix socket
  2880. 2:21:14file. However, your users cannot access
  2881. 2:21:17your website. Your front end is also
  2882. 2:21:20just a folder of static files sitting on
  2883. 2:21:23the server waiting to be served. In this
  2884. 2:21:27sub chapter, we are going to talk about
  2885. 2:21:30reverse proxy and security headers.
  2886. 2:21:33First, we need to sync the front end and
  2887. 2:21:36backend URLs. After that, we will
  2888. 2:21:39install EngineX to act as a reverse
  2889. 2:21:42proxy. I will explain this once we
  2890. 2:21:45install Engine X. I'm going to explain
  2891. 2:21:48to you what does 502 bad gateway means.
  2892. 2:21:53So this is an error that we might get if
  2893. 2:21:56we don't set up enginex correctly. And
  2894. 2:21:59finally we will move to the security
  2895. 2:22:01part. In this sub chapter we are going
  2896. 2:22:04to focus only on the HTTP security
  2897. 2:22:07headers mainly CSP and there are other
  2898. 2:22:10ones but CSP is the one that that
  2899. 2:22:13requires a lot of work and we will focus
  2900. 2:22:15on it at the end of this video. Now
  2901. 2:22:18let's SSH to the machine because we need
  2902. 2:22:21to start by syncing the front end and
  2903. 2:22:23back end and I will come back to the
  2904. 2:22:25slides in if I want to explain some
  2905. 2:22:28diagrams. As you can see I am logged in
  2906. 2:22:31to the machine and before we configure
  2907. 2:22:34engine X you need to prepare your code.
  2908. 2:22:36You want your front end and back end to
  2909. 2:22:39act as if they live on the exact same
  2910. 2:22:42server both in local development and in
  2911. 2:22:45production. This avoids complex cross
  2912. 2:22:48origin issues. Let me show you what I am
  2913. 2:22:51talking about. As you can see, I need to
  2914. 2:22:53go to the web app directory because last
  2915. 2:22:57time we moved the source code here. I
  2916. 2:22:59will change ls to cd. Now I am inside
  2917. 2:23:03that directory. Let's start with the
  2918. 2:23:05front end. Let's go to front end. And
  2919. 2:23:09here we need to go to source. And we
  2920. 2:23:12have main.js. So we need to open that
  2921. 2:23:17file. Let's use nano and let's see. As
  2922. 2:23:21you can see here we are using an
  2923. 2:23:23environment variable v a base url. Let
  2924. 2:23:27me show you the content of that
  2925. 2:23:29variable. Let's do ls. And here I need
  2926. 2:23:33to go back to front end because here we
  2927. 2:23:37have the environment file as you can. So
  2928. 2:23:40let's do ls-la.
  2929. 2:23:42Yeah, you can see that we have env.ample
  2930. 2:23:46and we also from that we create the env
  2931. 2:23:49file. But let's look at env.ample
  2932. 2:23:52by using cat. So let's provide the file
  2933. 2:23:57and as you can see this is what we have
  2934. 2:24:00here. The back end runs on this port.
  2935. 2:24:04When you are developing this locally the
  2936. 2:24:07back end will be running on a different
  2937. 2:24:08server. And in the front end we use
  2938. 2:24:10Axios to make HTTP requests and it needs
  2939. 2:24:15a it needs to know where the the API
  2940. 2:24:17lives and here it lives in port 8000.
  2941. 2:24:22This is good but it introduces cross
  2942. 2:24:26origin issues. If we try to send a
  2943. 2:24:29request to this port, the browser will
  2944. 2:24:31block it because it sees that you are
  2945. 2:24:33trying to communicate with a different
  2946. 2:24:35origin and even though we are running on
  2947. 2:24:37local host, it it's not going to be
  2948. 2:24:40allowed because the front end runs on
  2949. 2:24:42port 8080
  2950. 2:24:44but your back end runs on port 8,000. So
  2951. 2:24:48that's how I started developing this but
  2952. 2:24:50I will show you a simple way to avoid
  2953. 2:24:52this problem. We are going to use vit
  2954. 2:24:55and with vit we have something called
  2955. 2:24:57proxy and it will make this very simple.
  2956. 2:25:00So this example we no longer need it.
  2957. 2:25:04That's why I wanted I wanted you to open
  2958. 2:25:07the main file and change it. So let's do
  2959. 2:25:10that quickly. Now you can see that here
  2960. 2:25:12I am using axios and the base URL is we
  2961. 2:25:16set it here. I I will remove all of
  2962. 2:25:18this. I don't need it. And here instead
  2963. 2:25:21I will just put slash. By doing this the
  2964. 2:25:25browser will automatically send requests
  2965. 2:25:27to the current host. So if I am running
  2966. 2:25:29on local host this will will tell the
  2967. 2:25:32browser to send it to local host. If I
  2968. 2:25:34am running on my domain it's going to be
  2969. 2:25:38that domain. That's the first change
  2970. 2:25:40that we need to make. Now save the file.
  2971. 2:25:43Exit uh with Ctrl X Y and enter. Great.
  2972. 2:25:48Now we need to configure vit. So let's
  2973. 2:25:50look at vit. It's not here. Uh it's it
  2974. 2:25:53must be here. Yes. So we have vit
  2975. 2:25:55config. Let's open it with nano vit
  2976. 2:25:58config. Now I want you to scroll down
  2977. 2:26:01here. You can see that we have server.
  2978. 2:26:03And this is uh where we set the port. By
  2979. 2:26:06default vit starts on on a different
  2980. 2:26:10port. I think 4,000 something. But we uh
  2981. 2:26:13I usually change it to 8,080.
  2982. 2:26:17And here we can add another field to the
  2983. 2:26:20server block and we we call it proxy.
  2984. 2:26:23Here is the the field that we need to
  2985. 2:26:25add to server. You can see that it's
  2986. 2:26:27called proxy. And here the backend API
  2987. 2:26:31is yeah it has this prefix / API and we
  2988. 2:26:36tell V to send that request to this URL
  2989. 2:26:40or or to this target. This means that if
  2990. 2:26:43the front end tries to send a request to
  2991. 2:26:48the API, vit will intercept that and
  2992. 2:26:52target this URL. This way we can change
  2993. 2:26:56origin without having to worry about
  2994. 2:26:59cross origin issues. Let me explain this
  2995. 2:27:02with another diagram that I created. You
  2996. 2:27:05can see that here we are on a local
  2997. 2:27:07machine. we are developing the the web
  2998. 2:27:09application and here I I am using let's
  2999. 2:27:13say Chrome and I want to make a an HTTP
  3000. 2:27:17request. So I I am in the browser. If I
  3001. 2:27:20want to load static files basically the
  3002. 2:27:23web page I will call I will be here. So
  3003. 2:27:27the path will not be API. I will just
  3004. 2:27:29talk to the front end. The front end
  3005. 2:27:32will send back the HTML, CSS and
  3006. 2:27:35JavaScript files. Vit will take that and
  3007. 2:27:38send it back to the browser and the
  3008. 2:27:40browser will display the web the website
  3009. 2:27:43for me. Good. But let's say that I am
  3010. 2:27:45that I want to search for an article or
  3011. 2:27:47something that that request will need to
  3012. 2:27:50talk to the back end. So vit will see
  3013. 2:27:53the the request that I'm trying to make
  3014. 2:27:56or the browser is trying to make. If it
  3015. 2:27:58sees that it has this prefix / ai, it's
  3016. 2:28:02it's going to send it to the back end.
  3017. 2:28:04So, VIT sits between the browser and
  3018. 2:28:08your front end and backend servers and
  3019. 2:28:11this implementation
  3020. 2:28:13solves the cross origin issues. Awesome.
  3021. 2:28:17Now, we need to go to the to the back
  3022. 2:28:18end. Let's do that quickly. So, we are
  3023. 2:28:22in the backend folder. Let's see what we
  3024. 2:28:24have. So, we need to look at main.py.
  3025. 2:28:26Let's open it with nano. And here we
  3026. 2:28:29need to remove some things. You can see
  3027. 2:28:31that here we have a coarse middleware.
  3028. 2:28:34This is what we needed before using the
  3029. 2:28:37proxy feature that vit uh gives us. So
  3030. 2:28:41we need to remove this class. And now
  3031. 2:28:44let's go down a little bit because here
  3032. 2:28:47as you can see we used that middleware
  3033. 2:28:49here because we we allowed the following
  3034. 2:28:53origins. So this block need we need to
  3035. 2:28:56remove it. And in order to do that, hit
  3036. 2:29:00alt a go down and hit ctrl k. That will
  3037. 2:29:04remove the those multiple those lines.
  3038. 2:29:08Now we need to yeah save this and go
  3039. 2:29:12back. Okay. So now the we don't have
  3040. 2:29:16course issues. everything will the front
  3041. 2:29:18end will be able to communicate with the
  3042. 2:29:20back end because as as you as you saw we
  3043. 2:29:23used uh the proxy feature that v comes
  3044. 2:29:27with. So after making this change the
  3045. 2:29:29back end we don't need to to do anything
  3046. 2:29:31in the back end but the front end must
  3047. 2:29:33be uh built again. So we need to build
  3048. 2:29:36the front end. So go back to the front
  3049. 2:29:38end folder and run pnpm build. Why we
  3050. 2:29:42need to do that? because the build
  3051. 2:29:44process would regenerate the the HTML,
  3052. 2:29:47CSS and JavaScript files and it will
  3053. 2:29:49bake in the changes in those generated
  3054. 2:29:52files. But the back end doesn't need
  3055. 2:29:53that because it doesn't have a uh build
  3056. 2:29:57step. So just run pmppm build and let's
  3057. 2:30:00wait for the build process to finish.
  3058. 2:30:03Awesome. The build finished. Now the
  3059. 2:30:06first step in this video uh is done. We
  3060. 2:30:10synced the back end and front end URLs.
  3061. 2:30:13And now we can move to using EngineX.
  3062. 2:30:16But why do we need enginex? EngineX, you
  3063. 2:30:21can think of it as a front door for your
  3064. 2:30:24server. When a user types your domain
  3065. 2:30:27name into their browser, the request
  3066. 2:30:29will hit X first before loading HTML
  3067. 2:30:33files or before talking to the back end.
  3068. 2:30:36So engine X is going to intercept that
  3069. 2:30:38request and it's going to act as a
  3070. 2:30:41reverse proxy meaning it will decide
  3071. 2:30:45what to do with that request. Let me
  3072. 2:30:47show you another diagram that I created
  3073. 2:30:49to explain this in detail. I am back and
  3074. 2:30:53let's let's go to the next slide. Here
  3075. 2:30:55is the diagram that I created in order
  3076. 2:30:58to explain why we need engine X. As you
  3077. 2:31:02can see, it's similar to the diagram
  3078. 2:31:04that I showed you that explains vit
  3079. 2:31:07proxy. Here we start with the user with
  3080. 2:31:10a browser. We send a request before
  3081. 2:31:14talking to the front end or back end. We
  3082. 2:31:18in EngineX will intercept that request.
  3083. 2:31:21If it sees that the path is slappi
  3084. 2:31:26something, engineext will talk to the
  3085. 2:31:29Unix socket and that Unix socket will
  3086. 2:31:32send the request to J Unicorn and J
  3087. 2:31:35Unicorn will send it to the UVORN worker
  3088. 2:31:39which runs our back end. You can see
  3089. 2:31:41that this is the part that we talked
  3090. 2:31:43about in the previous sub chapter. Let's
  3091. 2:31:46go back here. When we talked about SSH
  3092. 2:31:50tunneling, we mentioned that the front
  3093. 2:31:52end is running here and the back end is
  3094. 2:31:54running on the server and we explained
  3095. 2:31:57how that works. We have the supervisor,
  3096. 2:32:01we have J unicorn and our workers and
  3097. 2:32:04here we mentioned that we created a Unix
  3098. 2:32:07socket file and I told you that I will
  3099. 2:32:10explain to you where that will be used
  3100. 2:32:13and in this video we are using that to
  3101. 2:32:15communicate with EngineX. Let's go back.
  3102. 2:32:18You can see that we have the unicorn.
  3103. 2:32:19Here I simplified the diagram. I am
  3104. 2:32:22showing just one worker, but you get the
  3105. 2:32:24idea. You have your Unix socket. It is
  3106. 2:32:27used in order to allow EngineX and J
  3107. 2:32:31Unicorn to communicate between each
  3108. 2:32:32other. You can see that here in the
  3109. 2:32:34description I I said it's a two-way pipe
  3110. 2:32:38connecting EngineX and J Unicorn. Uh so
  3111. 2:32:41let's say that the user is searching for
  3112. 2:32:44an article. Let's say that the endpoint
  3113. 2:32:46is / API/ articles. That request will be
  3114. 2:32:50intercepted by EngineX. It sees that it
  3115. 2:32:53has the / API prefix. It's going to send
  3116. 2:32:56that to Unicorn, but it's going to do it
  3117. 2:32:59through the Unix socket file because
  3118. 2:33:02here we are inside the VM. And in order
  3119. 2:33:04for two programs to communicate with
  3120. 2:33:06each other, we used Unix sockets files.
  3121. 2:33:09So now the J J unicorn receives a
  3122. 2:33:13request to the / API/ articles endpoint.
  3123. 2:33:17It's going to give that to the fast API
  3124. 2:33:19endpoint. If we have an endpoint, great.
  3125. 2:33:23The code will run. We'll we'll try to
  3126. 2:33:26fetch articles. Now we will send that
  3127. 2:33:28response to engine X. So we will move uh
  3128. 2:33:32the response will go to G unicorn. We'll
  3129. 2:33:35will go through the socket and back to
  3130. 2:33:37EngineX. engineext sees the response.
  3131. 2:33:40It's going to send it to the browser and
  3132. 2:33:42yeah, you will see articles. So that's
  3133. 2:33:44why here we use unique Unix sockets and
  3134. 2:33:48you can see on the other side we have
  3135. 2:33:50just the static files and if we if if we
  3136. 2:33:53have a request to an end points that
  3137. 2:33:55doesn't start with / API we will go here
  3138. 2:33:58we will fetch the static files which are
  3139. 2:34:00HTML, CSS and JavaScript and the browser
  3140. 2:34:03can display that. So that's why we need
  3141. 2:34:05enginex and as you can see it works like
  3142. 2:34:08uh vit but this runs on production. You
  3143. 2:34:11use vit locally when you develop your
  3144. 2:34:14application but on the virtual machine
  3145. 2:34:17or on the digital ocean droplet we use
  3146. 2:34:20engine x. It's the same concept but one
  3147. 2:34:23runs on your laptop and the other one
  3148. 2:34:25runs on the virtual machine. I hope that
  3149. 2:34:28my explanation was clear. Now let's
  3150. 2:34:31install enginex. We will do it this way.
  3151. 2:34:34We are we are on Ubuntu. So we can
  3152. 2:34:36install this directly from the
  3153. 2:34:38repository. I will provide my password.
  3154. 2:34:41And let's wait for a few seconds.
  3155. 2:34:44Awesome. We installed EngineX. You need
  3156. 2:34:47to understand that EngineX uses
  3157. 2:34:49configuration files to know how to route
  3158. 2:34:52traffic. Let's create a new
  3159. 2:34:54configuration file for your website in
  3160. 2:34:58the sites available directory. Now let's
  3161. 2:35:01do this. pseudo nano etc engine x and we
  3162. 2:35:06have a directory called sites available
  3163. 2:35:09and here you put your project name let's
  3164. 2:35:12call it my website maybe.com uh com we
  3165. 2:35:18are going to build this configuration
  3166. 2:35:21block by block so that you can
  3167. 2:35:22understand everything let's start with
  3168. 2:35:24the upstream block as you can see I just
  3169. 2:35:27copy copied this from GitHub and you
  3170. 2:35:31just I we just need to change this
  3171. 2:35:34placeholder. I will use the same name
  3172. 2:35:37that I used for the configuration file.
  3173. 2:35:40And if you are wondering where to get
  3174. 2:35:43the code or yeah the the things that I
  3175. 2:35:46copy paste, you will find them on this
  3176. 2:35:48GitHub repository. Here it is. So if you
  3177. 2:35:51go to full stack deployment handbook,
  3178. 2:35:54you will see that here I am documenting
  3179. 2:35:56everything. Click on the book folder you
  3180. 2:36:00have and here you have the chapters. So
  3181. 2:36:02far we completed chapter one. Now we are
  3182. 2:36:04in chapter number two. So if you click
  3183. 2:36:08on the uh the second markdown file let's
  3184. 2:36:11search for upstream.
  3185. 2:36:13You can see that here is the upstream
  3186. 2:36:15block. I you can copy it from here and
  3187. 2:36:18paste it in nano and uh go from there.
  3188. 2:36:22So so that you can uh go quickly. So
  3189. 2:36:24don't worry about the code. Everything
  3190. 2:36:25will be shared in the video description.
  3191. 2:36:28First, as I said, start by changing that
  3192. 2:36:30placeholder here. I use my website com,
  3193. 2:36:33but you can use any other name. So, this
  3194. 2:36:37acts as a variable that we can reuse in
  3195. 2:36:40other blocks. Instead of typing every
  3196. 2:36:42single time Unix, web app etc., we will
  3197. 2:36:46just use this variable to make the code
  3198. 2:36:49clean. Here you can see that we are so
  3199. 2:36:52here this is a variable. Here we have
  3200. 2:36:54fail timeout is equal to zero. This is
  3201. 2:36:58an important setting because it tells
  3202. 2:37:00engineext to never mark the back end as
  3203. 2:37:03down even if it fails to respond. So uh
  3204. 2:37:06if you have a lot of traffic and your
  3205. 2:37:09back end is starting to respond slowly.
  3206. 2:37:11Sometimes the engineext will drop the
  3207. 2:37:14request if it if it doesn't respond
  3208. 2:37:16quickly. But here we tell engineext
  3209. 2:37:19don't worry uh even if the back end is
  3210. 2:37:21down don't fail. Okay, now let's add a
  3211. 2:37:25different block. It's called the server
  3212. 2:37:28block. This tells EngineX to listen for
  3213. 2:37:32incoming web traffic on port 80, which
  3214. 2:37:35is standard HTTP, and to respond when
  3215. 2:37:38someone asks for your specific domain.
  3216. 2:37:41Right now, we haven't created a domain
  3217. 2:37:44name, but that's not a problem. We will
  3218. 2:37:48use the droplet IP here in the server
  3219. 2:37:51name. But later this will be changed
  3220. 2:37:54from the droplet IP to the domain name.
  3221. 2:37:58So let's do this. If you don't know how
  3222. 2:38:00to get your droplet IP, we have
  3223. 2:38:02different ways of getting this but you
  3224. 2:38:04can go to digital ocean. Make sure to
  3225. 2:38:07log in here in the projects. Make sure
  3226. 2:38:10to select the project where you created
  3227. 2:38:11the droplet. And here as you can see we
  3228. 2:38:14have the IP address. So copy it and
  3229. 2:38:17let's go back to nano and let's paste it
  3230. 2:38:20here. I will remove this and replace it
  3231. 2:38:24with the droplets IP. You can see that
  3232. 2:38:26we also have some log files. And here we
  3233. 2:38:29need to change this. Uh these are also
  3234. 2:38:32placeholders.
  3235. 2:38:34And here I will use again let me copy
  3236. 2:38:36this my website com and let's place it
  3237. 2:38:40here. Let's also do it here. This is
  3238. 2:38:43helpful because if something breaks, we
  3239. 2:38:45can check the error logs to understand
  3240. 2:38:48why that happened. Here I have a comment
  3241. 2:38:52that says we will add the location block
  3242. 2:38:54some other blocks here next. But as as
  3243. 2:38:57you can see we are doing this step by
  3244. 2:38:59step to understand every every line that
  3245. 2:39:02we are writing. Okay. Now I will remove
  3246. 2:39:04this comment again. I will use Ctrl K to
  3247. 2:39:07do that. And let me place the location
  3248. 2:39:10block. Remember here we have slash which
  3249. 2:39:14means that we want to serve the front
  3250. 2:39:16end. If I open the browser and go to
  3251. 2:39:18this IP address and I add a slash at the
  3252. 2:39:21end, engineext will catch that and will
  3253. 2:39:25serve my front end to the user. Now
  3254. 2:39:30let's try to understand what we have
  3255. 2:39:31inside here. We have root. This tells
  3256. 2:39:35engineext where to look for files. In
  3257. 2:39:37this case, it points to the dist
  3258. 2:39:40directory because when you run pmppm
  3259. 2:39:43build, the files that are generated are
  3260. 2:39:46going to be inside the disc folder. Try
  3261. 2:39:49files is important because here we have
  3262. 2:39:52a single page application. It tells
  3263. 2:39:55engineext to find the exact file the
  3264. 2:39:59user asked for and that file is going to
  3265. 2:40:02be here dollar uri. If it is not there,
  3266. 2:40:05it's going to look for a directory. So
  3267. 2:40:08if it this is a directory, it's going to
  3268. 2:40:11look inside it to find the file. If it
  3269. 2:40:13can't find the file, it's going to use
  3270. 2:40:16index.html
  3271. 2:40:17as a fallback. Let me explain this. So
  3272. 2:40:20here I have my personal website. I can
  3273. 2:40:23open it. You can see that here we have
  3274. 2:40:25slash at the end which means that we are
  3275. 2:40:27serving the front end files. If I want
  3276. 2:40:30to open something else like maybe my
  3277. 2:40:34resume, I can do it. So I can do /resume
  3278. 2:40:38and you can see we get it. But how does
  3279. 2:40:41this work? If I go back to the machine
  3280. 2:40:44or to the VM, let's save this file.
  3281. 2:40:47Let's hit Ctrl X. Let's look at the this
  3282. 2:40:51folder. What do we have here? We can see
  3283. 2:40:53that I have a lot of files. So we have
  3284. 2:40:57some images. We have robot txt. Let's
  3285. 2:41:00let's also try to get robots txt. robots
  3286. 2:41:02txt. You can see that I am able to see
  3287. 2:41:05this file. Why? Because engine x knows
  3288. 2:41:08where to find those because of this. Uh
  3289. 2:41:12let's go back to nano because of this
  3290. 2:41:15location block. So try files will uh URI
  3291. 2:41:19will be robots txt
  3292. 2:41:22and uh we know that we should look
  3293. 2:41:24inside the disc folder. If we find it
  3294. 2:41:26good, we will show it. But if we can't
  3295. 2:41:28find it, we will show index.html.
  3296. 2:41:31Okay. And uh yeah, index html is also
  3297. 2:41:35should be here. Uh you can see here here
  3298. 2:41:38it is. So that's that's how that's uh
  3299. 2:41:41the reason why we added this location
  3300. 2:41:43block. And this will serve the your
  3301. 2:41:45front end. We will do another one for
  3302. 2:41:48the back end. And it's going to look for
  3303. 2:41:50/ API instead. I will copy it and I'll
  3304. 2:41:53paste it here. You can see that it is
  3305. 2:41:56similar. we will use the location block
  3306. 2:41:58and instead we will look for /
  3307. 2:42:02okay now we have um a lot of directives
  3308. 2:42:05the these are called directives so proxy
  3309. 2:42:08pass is a directive and here we have we
  3310. 2:42:11need to change this placeholder from
  3311. 2:42:13your project name to this string so
  3312. 2:42:17proxy pass will the request over to your
  3313. 2:42:22J unicorn socket that's what I explained
  3314. 2:42:25in the slides we are here. So we use the
  3315. 2:42:28unique socket to allow EngineX to
  3316. 2:42:32forward the request to J unicorn and
  3317. 2:42:35this is what we are doing here in this
  3318. 2:42:37directive. The proxy set header we have
  3319. 2:42:41two of them are crucial here because
  3320. 2:42:43they take information about the real
  3321. 2:42:46user who is trying to access your
  3322. 2:42:48website because if we don't do this we
  3323. 2:42:51will all we will send the IP address of
  3324. 2:42:54your virtual machine and we don't want
  3325. 2:42:56to do that and finally we have proxy
  3326. 2:42:59redirect of tells engineext to trust the
  3327. 2:43:02redirect URLs exactly as uh your backend
  3328. 2:43:07sends them. So if your back end tells
  3329. 2:43:09EngineX to redirect, EngineX will trust
  3330. 2:43:11it. It's not going to do uh something
  3331. 2:43:13else. Okay, great. So now we have the we
  3332. 2:43:16we have two two locations, one for the
  3333. 2:43:18front end and one for the back end. So
  3334. 2:43:21we can save the file and let's exit. We
  3335. 2:43:25have two options to test this
  3336. 2:43:26configuration. We can do it live here on
  3337. 2:43:29the server. But if you aren't unsure or
  3338. 2:43:32if you already have a working website
  3339. 2:43:34and you want to introduce changes to
  3340. 2:43:36your configuration, if you do if you
  3341. 2:43:38have a mistake or if the configuration
  3342. 2:43:41is false, that will cause downtime and
  3343. 2:43:44we don't want that. There is another
  3344. 2:43:45option which is to use an a website
  3345. 2:43:50called EngineX Playground. EngineX
  3346. 2:43:52playground is a website that allows you
  3347. 2:43:55to simulate your routing rules safely in
  3348. 2:43:58your browser without uh having to do
  3349. 2:44:00this on your production server. You can
  3350. 2:44:03see that here we have we put the
  3351. 2:44:04engineext configuration. Uh here we have
  3352. 2:44:07events HTTP. We as you saw we didn't
  3353. 2:44:10write these. I'll explain to you why.
  3354. 2:44:12But we need to have we need to add them
  3355. 2:44:15for the configuration to work. the the
  3356. 2:44:17the blocks that we created are these. We
  3357. 2:44:20created server location. We created two
  3358. 2:44:23of them. Here we are listening on 80
  3359. 2:44:25because we we used uh HTTP. Here we are
  3360. 2:44:29serving the front end and here we are
  3361. 2:44:30serving the back end. This playground
  3362. 2:44:33has a built-in testing back end running
  3363. 2:44:36on port 7777
  3364. 2:44:38and we can use this as our back end.
  3365. 2:44:40Here you write your curl commands to
  3366. 2:44:44yeah send HTTP requests. We'll start
  3367. 2:44:47with local host. Make sure to use local
  3368. 2:44:49host. You can't use your own domain
  3369. 2:44:51because this is a playground and we are
  3370. 2:44:54testing things internally. To test the
  3371. 2:44:57cur command you hit run. And as you can
  3372. 2:44:59see the output says serving view.js JS
  3373. 2:45:03files which is correct because here we
  3374. 2:45:05have slash and the this location block
  3375. 2:45:08will catch that and it will in this case
  3376. 2:45:11return this string. Uh but let's add uh
  3377. 2:45:14maybe something else. So let's add API
  3378. 2:45:18v2. Will this work? Let's see. Let's hit
  3379. 2:45:22run. And that works because here we have
  3380. 2:45:25/ API and that catches this. And here
  3381. 2:45:28you can see that we have u yeah this is
  3382. 2:45:31a response from the back end. Uh let's
  3383. 2:45:33do something else maybe let's do API
  3384. 2:45:39v1 or slash articles. Uh let's remove
  3385. 2:45:42this. Let's send the request and it
  3386. 2:45:45works. So this block will catch this.
  3387. 2:45:47But maybe let's do something else like
  3388. 2:45:50maybe resume or something. Yeah that
  3389. 2:45:53will be catched by this block. So
  3390. 2:45:55everything is working. And if you add
  3391. 2:45:58complex um I don't know if you work on
  3392. 2:46:00complex configurations this playground
  3393. 2:46:03will be very useful. So we know that our
  3394. 2:46:06configuration works. Now we can close
  3395. 2:46:08this go back to the VM and I want to
  3396. 2:46:13tell you why in our configuration we
  3397. 2:46:16don't have the events block and HTTP.
  3398. 2:46:20Okay, let's close the file. And here on
  3399. 2:46:23Ubuntu, we use a modeler system for
  3400. 2:46:26EngineX. There is a master configuration
  3401. 2:46:29file located here. Uh let's look at it.
  3402. 2:46:32Let's do cat etc. EngineX enginex
  3403. 2:46:38doconfig. Hit enter. So this is uh this
  3404. 2:46:42is the master configuration file. Let's
  3405. 2:46:44scroll to the top. You can see that we
  3406. 2:46:46have events.
  3407. 2:46:48We it's already here and we have the
  3408. 2:46:50HTTP block and if we scroll down uh we
  3409. 2:46:54include some things and what do we
  3410. 2:46:55include? If you look at this path it's
  3411. 2:46:57etc engineext sites enabled here we have
  3412. 2:47:00an asterisk to load every configuration
  3413. 2:47:03inside that directory and if you
  3414. 2:47:06remember the configuration that we
  3415. 2:47:08created is inside this folder. So that
  3416. 2:47:11means that this master file will load
  3417. 2:47:14our configuration. That's why we didn't
  3418. 2:47:17we don't need to add events or HTTP. It
  3419. 2:47:20is it's already there. And one thing
  3420. 2:47:22that you need to understand is that the
  3421. 2:47:24engineext will run as this user. It's
  3422. 2:47:27not going to run as my user or the user
  3423. 2:47:30you created. No, it's going it has its
  3424. 2:47:32own user. It's going to use it. So, it's
  3425. 2:47:34ww
  3426. 2:47:36data. Now, we need to enable this site.
  3427. 2:47:40Um, let's see. So, we have pseudo nano.
  3428. 2:47:43Okay, good. But I want to use uh ls
  3429. 2:47:47instead of nano. So let's see what we
  3430. 2:47:50have inside the engine x. You can see
  3431. 2:47:52that we have two folders. We have sites
  3432. 2:47:55available and sites enabled. So sites
  3433. 2:47:58available uh we define the
  3434. 2:48:00configuration. So just so that engineext
  3435. 2:48:03knows that there is a maybe a
  3436. 2:48:05configuration that's that that it needs
  3437. 2:48:07to take into consideration. But for it
  3438. 2:48:11to work we need to put it in enabled.
  3439. 2:48:13And here we are not going to copy paste
  3440. 2:48:15it because that's that's not
  3441. 2:48:18[clears throat] a good bracket because
  3442. 2:48:19you would need to maintain both. Instead
  3443. 2:48:21we are going to use a symbolic link. Uh
  3444. 2:48:24this is uh just a shortcut that will put
  3445. 2:48:27that file here and if we want we can
  3446. 2:48:30just change the configuration inside
  3447. 2:48:33sites available and that change will uh
  3448. 2:48:35take effect in the other directory. So
  3449. 2:48:38we we'll have it in two places but we
  3450. 2:48:40can change it once and it will take
  3451. 2:48:42effect in uh other places. Here is how
  3452. 2:48:45we create a symbolic link. We use ln
  3453. 2:48:49dash s here we need to change this. Uh
  3454. 2:48:54let's see I need to put my configuration
  3455. 2:48:56my name the name here. Uh let's go here
  3456. 2:49:00and let's do it in size available
  3457. 2:49:02because I can copy it easily. Let's copy
  3458. 2:49:06this and let's paste it inside sites
  3459. 2:49:09enabled. So we are creating a symbolic
  3460. 2:49:12link from here to this directory. Now
  3461. 2:49:16hit enter. Great. Let's look at let me
  3462. 2:49:20copy this uh or let's copy the other
  3463. 2:49:22one. Let's do etc. And here I will add
  3464. 2:49:26ls-la.
  3465. 2:49:28And as you can see here it says l which
  3466. 2:49:30confirms that is a symbolic link. As you
  3467. 2:49:32can see we have this it is pointing at
  3468. 2:49:35this file which means that if this file
  3469. 2:49:37change changes this uh file will also
  3470. 2:49:40change because it is a basically a
  3471. 2:49:43shortcut. We are almost ready. So now we
  3472. 2:49:45need to make sure that the configuration
  3473. 2:49:47is correct. So run this command and what
  3474. 2:49:50you should see is this. It should say it
  3475. 2:49:53should say that the syntax is okay and
  3476. 2:49:56the the test was successful. If you see
  3477. 2:49:59an error or something, please fix it
  3478. 2:50:01because if you use a configuration that
  3479. 2:50:04is not correct, it's the your websites
  3480. 2:50:09will not work or people will not be able
  3481. 2:50:11to access your website. Awesome. So now
  3482. 2:50:14let's reload X so that it it can read
  3483. 2:50:17the configuration. And now we cannot
  3484. 2:50:20access the website. So I can take my IP
  3485. 2:50:24address. Let's copy it. Uh let's go here
  3486. 2:50:27and let's paste it. You can see that
  3487. 2:50:29it's not going to work because we have
  3488. 2:50:32the firewall. We need to allow traffic
  3489. 2:50:34through port 80. And in order to do
  3490. 2:50:37that, we have we can do this. We can
  3491. 2:50:40allow EngineX. You we use sudo here. We
  3492. 2:50:43use the uncomplicated firewall and we
  3493. 2:50:46tell it to allow EngineX. Let's do that.
  3494. 2:50:49Okay. And now let's verify the status.
  3495. 2:50:51Sudo UFW
  3496. 2:50:54status. Uh before as you saw as you can
  3497. 2:50:57see we we had just open SSH so that we
  3498. 2:51:00can SSH to the machine but now we also
  3499. 2:51:03have enginex which means that we can
  3500. 2:51:05talk to port 80. Now if I go back if I
  3501. 2:51:08go to the website as you can see it's
  3502. 2:51:10already worked. Before it it it wasn't
  3503. 2:51:13uh working. It couldn't find the the
  3504. 2:51:16machine or the the firewall was blocking
  3505. 2:51:18it. But now as you can see I can refresh
  3506. 2:51:21the page and I uh I see the front end.
  3507. 2:51:24You can see that the website is not
  3508. 2:51:25secure because we are on HTTP. We will
  3509. 2:51:28solve this in the upcoming chapters and
  3510. 2:51:32you as you can see we have some errors
  3511. 2:51:34because we don't have articles yet in
  3512. 2:51:37the brows in the application but the
  3513. 2:51:39front end is running and the back end is
  3514. 2:51:41also running. So if I click on blogs or
  3515. 2:51:45courses you can see we cannot we cannot
  3516. 2:51:47get them because they are not here. And
  3517. 2:51:50in my web application I am using mill
  3518. 2:51:53search and we will talk about that in
  3519. 2:51:55the next chapter. But we also have a
  3520. 2:51:58problem here. So uh let's see. So if I
  3521. 2:52:02open the console, let's zoom in a little
  3522. 2:52:05bit. You can see that I am not able to
  3523. 2:52:09make a request to the API endpoint.
  3524. 2:52:13Interesting. So let's go to the VM and
  3525. 2:52:17let's understand why is this happening.
  3526. 2:52:20Remember we added log folders. So here
  3527. 2:52:25let's do this. You can see that here we
  3528. 2:52:27have error logs for our website. Let's
  3529. 2:52:30take this and let's put it here and
  3530. 2:52:33let's look at what we have here. We
  3531. 2:52:35don't have anything. Okay, that's
  3532. 2:52:37interesting. And let's look at access.
  3533. 2:52:39So here access log that's me trying to
  3534. 2:52:42access the website. So you can see that
  3535. 2:52:43I made a post request to these
  3536. 2:52:45endpoints. So here we have tracking and
  3537. 2:52:48here we have search and yeah and I was
  3538. 2:52:51using uh Mozilla I'm using Firefox. So
  3539. 2:52:55yeah that's uh what you see in the
  3540. 2:52:58access logs but we don't see any errors.
  3541. 2:53:02Let's look at the supervisor logs. For
  3542. 2:53:04that we need to go to back end. Let's
  3543. 2:53:08see. Yes, we have logs. Let's go inside.
  3544. 2:53:11What do we have here? We have
  3545. 2:53:12supervisor.log.
  3546. 2:53:14So let's let's do tail supervisor.log.
  3547. 2:53:19And as you can see we see the problem.
  3548. 2:53:21So here it says that uh failed to
  3549. 2:53:24establish a new connection to me search.
  3550. 2:53:28So here it is me search communication
  3551. 2:53:30error. That's what that's why uh what I
  3552. 2:53:32said but we will fix this in the
  3553. 2:53:34upcoming chapter. Let's make sure that
  3554. 2:53:38we can also reach the back end. So here
  3555. 2:53:41the back end starts at API slash and let
  3556. 2:53:45me do health because we have an endpoint
  3557. 2:53:47that tells us if the back end is alive
  3558. 2:53:49or not. So as you can see we are
  3559. 2:53:51receiving okay which means that this is
  3560. 2:53:53working. Uh we can confirm this in uh
  3561. 2:53:57the main file we have this endpoint
  3562. 2:54:00API/halth
  3563. 2:54:01and yeah it means it is working. If you
  3564. 2:54:05followed the previous sub chapters, you
  3565. 2:54:09shouldn't get a bad gateway error. But
  3566. 2:54:11if you do, that might happen because of
  3567. 2:54:13the engineext user doesn't have the full
  3568. 2:54:16permissions to to access the Unix socket
  3569. 2:54:19file. Uh remember the Unix socket is
  3570. 2:54:22here. You can see that it is called
  3571. 2:54:24junicorn.sock.
  3572. 2:54:27And if we try to let's look at the
  3573. 2:54:29permission. So if we do ls-la
  3574. 2:54:32juniors
  3575. 2:54:34sock, here is what we have. Uh I want to
  3576. 2:54:37correct a mistake that I made in the
  3577. 2:54:39previous video. So here the first three
  3578. 2:54:43characters are for the current user. So
  3579. 2:54:46the current user is IMAD. If you are
  3580. 2:54:49connected as root then it's going to
  3581. 2:54:51apply to root. The second tree are for
  3582. 2:54:54the group and the final three are for
  3583. 2:54:57other users. So the mod here is 777.
  3584. 2:55:02Why? Because here uh we have three of
  3585. 2:55:05them. So every person or every user can
  3586. 2:55:08read, write or execute this file. This
  3587. 2:55:12is not good. We need to make sure to
  3588. 2:55:16restrict this. This is why the we didn't
  3589. 2:55:19get bad gateway because everything is
  3590. 2:55:22open. Everyone can uh access read this
  3591. 2:55:24file. But we need to change this or
  3592. 2:55:28maybe if you have a different mode then
  3593. 2:55:31you might get a bad a bad gateway. Let's
  3594. 2:55:33try to do this. So uh I'll change this
  3595. 2:55:37intentionally just to show you how to
  3596. 2:55:39debug this problem. Let's use ch own and
  3597. 2:55:43let's change the ownership to 700
  3598. 2:55:48and let's point it to let's do it for j
  3599. 2:55:50unicorn.stock. What does 700 mean? So
  3600. 2:55:54this is in binary and let's take these
  3601. 2:55:58three. The first character is one, the
  3602. 2:56:00second character is two and the third
  3603. 2:56:03character is four. If you sum those
  3604. 2:56:05three numbers, it's going to give you
  3605. 2:56:06seven. So if all of them are on, if you
  3606. 2:56:10want to allow read, write and execute,
  3607. 2:56:12you put seven. If you don't want to
  3608. 2:56:14allow anything, you put zero. So here it
  3609. 2:56:17means that for the current user, it can
  3610. 2:56:20do everything anything with this file.
  3611. 2:56:23But for the the group they can't and for
  3612. 2:56:26other users they cannot uh do anything
  3613. 2:56:29with it. If you want to allow people in
  3614. 2:56:32in the group to just read the file maybe
  3615. 2:56:36read and execute in that case we will
  3616. 2:56:38put five because four + 1 is five. Let's
  3617. 2:56:42do this. So ch okay so it said uh
  3618. 2:56:46operation is not permitted. Let's use
  3619. 2:56:48pseudo. Okay that works this time. Let's
  3620. 2:56:51go back to ls-la.
  3621. 2:56:53Sorry, I did ch own. I I should have um
  3622. 2:56:57changed this to ch mod because these are
  3623. 2:57:00called mods. Uh so yeah, this time it
  3624. 2:57:02worked. Uh let's do ls- array. And as
  3625. 2:57:05you can see it changed. Let's verify
  3626. 2:57:07that. So the three characters here for
  3627. 2:57:10other users are not available which
  3628. 2:57:12means they are set to zero. The second
  3629. 2:57:15three are read and execute. That's
  3630. 2:57:17that's uh five. And uh the last three
  3631. 2:57:21for my user is seven. So I can do
  3632. 2:57:23whatever I want with this file, but
  3633. 2:57:25other users cannot. So this is very
  3634. 2:57:27important. And remember you engine x is
  3635. 2:57:32not inside this group. It's not my user.
  3636. 2:57:35It's ww- data. Okay. Now let's try to do
  3637. 2:57:40this. Uh, as you can see, we get the 502
  3638. 2:57:44bad gateway error because EngineX is
  3639. 2:57:47trying its best to send this request
  3640. 2:57:50that I am trying to make to API/halth
  3641. 2:57:54to J Unicorn. Let's go back to the
  3642. 2:57:56slides. It received / API/halth. It
  3643. 2:58:00tries to send it to J Unicorn, but the
  3644. 2:58:02Unix sockets, we changed the mode now to
  3645. 2:58:06not allow EngineX to do anything with
  3646. 2:58:09it. So that's why it was blocked and uh
  3647. 2:58:12if it is blocked then it's going to
  3648. 2:58:14display this bad gateway error to the
  3649. 2:58:16user. Now how do we solve this? So we
  3650. 2:58:19can add engine X to my group that will
  3651. 2:58:22solve the issue. If you want you can set
  3652. 2:58:24it to 777 but that's uh yeah that's not
  3653. 2:58:28secure. Any user can do whatever they
  3654. 2:58:31want with the file. Let's add uh ww data
  3655. 2:58:34to my uh group. And let's let's also uh
  3656. 2:58:38let's look at the error logs. Uh I want
  3657. 2:58:41to see what we have there. Uh as you can
  3658. 2:58:44see we also get uh something in the
  3659. 2:58:46error logs. Great. So this confirms as
  3660. 2:58:49as you can see it says critical
  3661. 2:58:51permission denied. So it it tried to
  3662. 2:58:53connect to the socket but it failed
  3663. 2:58:55because it doesn't have the full
  3664. 2:58:57permissions. Awesome. So this make uh
  3665. 2:58:59this confirms that changing the mod will
  3666. 2:59:02either allow engine X to be able to
  3667. 2:59:06connect to the socket or not. So let's
  3668. 2:59:09fix this. We have different ways but I
  3669. 2:59:11will do it in this way. So I will just
  3670. 2:59:14use this command sudo user mod- a g and
  3671. 2:59:20here I have this you put here put your
  3672. 2:59:23user my user is emad I will put it here
  3673. 2:59:25and I will add ww- data to my user now
  3674. 2:59:30we have another command called get end
  3675. 2:59:33group and here put your user and as you
  3676. 2:59:36can see you should be able to see ww-
  3677. 2:59:39data awesome so this confirms that it
  3678. 2:59:41works Now let's run uh let's do that ls-
  3679. 2:59:46array and ww data is part of my group so
  3680. 2:59:50it is a uh let's see so we have this
  3681. 2:59:53tree so it's able to read and execute
  3682. 2:59:57okay let's go back to the browser let's
  3683. 2:59:59refresh uh it is still not working maybe
  3684. 3:00:03let's try to reload engine x so here hit
  3685. 3:00:06ctrr and start typing reload it's going
  3686. 3:00:08to find it in the history
  3687. 3:00:12Let's reload. Okay, we still we are not
  3688. 3:00:15able to connect to the socket. I want to
  3689. 3:00:17go back to uh ls-la
  3690. 3:00:21and let's do it on J unicorn. And here
  3691. 3:00:23we have a problem because before I ran
  3692. 3:00:27ch mode and that changed the yeah the
  3693. 3:00:30user to 750 and that's not correct. So
  3694. 3:00:33we need to fix this. So let's do uh ch
  3695. 3:00:38own. I want to own this file, not 750.
  3696. 3:00:41750 is not correct. So that was a
  3697. 3:00:43mistake that I did because instead of
  3698. 3:00:45typing chod, I typed ch own. And here,
  3699. 3:00:49let's do it on genicorn.
  3700. 3:00:52Let's run ls-la. Okay, now that's fixed.
  3701. 3:00:55Okay, let's go back again to the
  3702. 3:00:57website. Okay, it's still doesn't work.
  3703. 3:01:00And maybe because we also need write
  3704. 3:01:03permissions. So that's how you debug
  3705. 3:01:04this. Um, let's do it. So let's go back
  3706. 3:01:08to here and let's change this to 770.
  3707. 3:01:13Let's look at ls-la. Let's go back to
  3708. 3:01:15the web application. Okay, now it
  3709. 3:01:18worked. We need also write permission
  3710. 3:01:21because we need to write to the Unix
  3711. 3:01:22socket file. That makes sense. We write
  3712. 3:01:25data to this file so that G unicorn can
  3713. 3:01:27read it. And again, G Unicorn will write
  3714. 3:01:30data to Unix file so that engineext can
  3715. 3:01:32read it. Okay, great. So that works. And
  3716. 3:01:35as you can see, the other users will not
  3717. 3:01:37be able to reach this file. If you
  3718. 3:01:40followed uh the same steps as I did, you
  3719. 3:01:43should be uh able to get this to work.
  3720. 3:01:45Awesome. So, we have finished with the
  3721. 3:01:49first part of this video. Now, we will
  3722. 3:01:52talk about security headers. We saw that
  3723. 3:01:56we were all already secure because we
  3724. 3:01:58have the firewall. it was blocking port
  3725. 3:02:0280, but now we allowed port 80 so that
  3726. 3:02:05we can access the website. But security
  3727. 3:02:07doesn't stop at the firewall. Browsers
  3728. 3:02:10have built-in security features, but
  3729. 3:02:13they only activate them if your server
  3730. 3:02:15tells them to. And if you want to read
  3731. 3:02:17more about this, you can go to HTTP
  3732. 3:02:20security headers, and you will find this
  3733. 3:02:23documented here on the developer Mozilla
  3734. 3:02:27website. And as you can see, they have a
  3735. 3:02:29lot of headers. They will explain them
  3736. 3:02:31to you in detail, but I will show you
  3737. 3:02:34because we have a lot of uh headers.
  3738. 3:02:36I'll just show you the main ones that we
  3739. 3:02:38need to have. And there are also
  3740. 3:02:40websites like security headers.com and
  3741. 3:02:45the http observatory from Mozilla that
  3742. 3:02:49will test the security headers to see if
  3743. 3:02:52they are uh on your website or not. If
  3744. 3:02:55they aren't, you will get a low score.
  3745. 3:02:58But if they they find them, then they
  3746. 3:03:00will tell you that your website is
  3747. 3:03:01secure. Same thing with security
  3748. 3:03:04headers. You just need to paste here
  3749. 3:03:06your domain name or uh in our case, we
  3750. 3:03:09don't have a domain name. So we could
  3751. 3:03:10try to put uh just the IP address. Uh
  3752. 3:03:15let's try this. Let's try it here. I'll
  3753. 3:03:18try it on HTTP Observatory. Ah, so it
  3754. 3:03:20says that it cannot scan IP addresses.
  3755. 3:03:23Okay. So that means that we need to do
  3756. 3:03:25it with a domain name. Okay. But here
  3757. 3:03:29let me actually take the full the full
  3758. 3:03:31link. Yeah, it doesn't work. So with
  3759. 3:03:33HTTP Observer 3, we need the full
  3760. 3:03:36domain. But I can uh use my own website.
  3761. 3:03:39Let's try to scan it. And as you can
  3762. 3:03:42see, I get A+, which is great. It's even
  3763. 3:03:45higher than the 100. So uh the security
  3764. 3:03:48here is great. But let's go back to
  3765. 3:03:51security headers. This is the websites
  3766. 3:03:53that you are that we are working with.
  3767. 3:03:55We have created the new configuration,
  3768. 3:03:57but you can see that it lacks a lot of
  3769. 3:03:58headers here. The great thing is that
  3770. 3:04:00they show you the main ones. They have
  3771. 3:04:02the list of missing headers. They tell
  3772. 3:04:04you why you need them. And here F. So F
  3773. 3:04:08is the lowest score that you can get,
  3774. 3:04:11but you can climb uh from F to A+. And
  3775. 3:04:16here what I like about HTTP observatory
  3776. 3:04:18is that if you click on scan history
  3777. 3:04:21they show you the progression. So in the
  3778. 3:04:23beginning I got I got the because I
  3779. 3:04:26wasn't aware of these headers or I
  3780. 3:04:28didn't add them in the beginning but
  3781. 3:04:30after that I started to add them
  3782. 3:04:32gradually to make uh my website secure
  3783. 3:04:36and now I have the highest score which
  3784. 3:04:38uh yeah which which gives me the A+
  3785. 3:04:40grade. We will do the same thing for
  3786. 3:04:43this website that we created now. Yeah,
  3787. 3:04:45let's start working with these simple
  3788. 3:04:46ones because the the complex one is CSP
  3789. 3:04:50content security policy. That one we
  3790. 3:04:52will leave it at the end because it
  3791. 3:04:53requires a lot of iterations to get it
  3792. 3:04:55right. Now let's go back again. Hit
  3793. 3:04:58CtrlR. Let's do pseudo nano. Okay, we
  3794. 3:05:01find this is the configuration. We will
  3795. 3:05:04start with strict transport security.
  3796. 3:05:07This one forces the browser to always
  3797. 3:05:10use HTTPS when talking to your website.
  3798. 3:05:14And here it will uh force that for the
  3799. 3:05:17next two years. So this value uh is 2
  3800. 3:05:21years. You might be asking we don't have
  3801. 3:05:23HTTPS yet. We are just on HTTP. That's
  3802. 3:05:26not that's not a problem because this
  3803. 3:05:28header is ignored by browsers if they
  3804. 3:05:31see that you are uh accessing the
  3805. 3:05:34website over regular HTTP. That's fine.
  3806. 3:05:37But this will be active or it's going to
  3807. 3:05:39be used by browsers when we switch to
  3808. 3:05:42HTTPS. So keep it like that. And here we
  3809. 3:05:45want to also include subdomains. Uh we
  3810. 3:05:48don't have that but if you plan to add
  3811. 3:05:50subdomains then uh we also want to
  3812. 3:05:53include them. Okay. So this is the first
  3813. 3:05:55one. Now we can yeah let's let's save
  3814. 3:05:58the file. Uh hit Ctrl X. Remember we
  3815. 3:06:01need to do sudo engineext-t.
  3816. 3:06:04Okay. It says successful. Now we can
  3817. 3:06:07reload. Reload EngineX. Now let's go
  3818. 3:06:10back to the browser. Let's scan the
  3819. 3:06:15website again. Okay. So yeah, it didn't
  3820. 3:06:18change because that header wasn't in
  3821. 3:06:20this list. That's fine because now we
  3822. 3:06:23will add X frame options, X content type
  3823. 3:06:27options, and another one called cross
  3824. 3:06:30origin cross origin resource policy.
  3825. 3:06:33I'll copy all of them. I'll go back to
  3826. 3:06:36nano. Let's go back to nano and I will
  3827. 3:06:39add them here. So here I have some
  3828. 3:06:41comments if you want them. Uh I will
  3829. 3:06:43just remove them from here but they are
  3830. 3:06:44in the markdown file. Let's start with
  3831. 3:06:47corp. This one allows sharing. So if you
  3832. 3:06:50want to allow other browsers to share
  3833. 3:06:52your resources then you can leave it
  3834. 3:06:55this way. Otherwise you uh you you might
  3835. 3:06:59need to block it. And to do that you
  3836. 3:07:01just need to copy this header. Go back
  3837. 3:07:04to the browser, search for it. You will
  3838. 3:07:07find the Mozilla uh the documentation
  3839. 3:07:09there. And here as you can see you have
  3840. 3:07:12uh you have an explanation and you also
  3841. 3:07:14have the directives that you can that
  3842. 3:07:16you can set. So you have same site, same
  3843. 3:07:18origin or cross origin. In our case, we
  3844. 3:07:21are using cross origin because we want
  3845. 3:07:23to allow other websites to maybe link
  3846. 3:07:25our articles, images or something like
  3847. 3:07:27that. But if you want to block them, you
  3848. 3:07:29put same sites which means that you you
  3849. 3:07:32allow only yourself to yeah reuse uh
  3850. 3:07:35some of your resources. Okay, let's see
  3851. 3:07:38what we have in nano. And as you can
  3852. 3:07:40see, we allow other origins and origin
  3853. 3:07:42means other uh domains. Uh I will remove
  3854. 3:07:45the comment because I don't need it. We
  3855. 3:07:47have here anti- clickjing. Uh we use
  3856. 3:07:51Xframe options for that. If you want to
  3857. 3:07:53read more about clickjing, you can find
  3858. 3:07:56this Wikipedia page which explains it.
  3859. 3:07:59Basically, this is uh how the attack
  3860. 3:08:02works. So, the user is presented with a
  3861. 3:08:05false interface where their input is
  3862. 3:08:07applied to something they cannot see.
  3863. 3:08:10You might visit a website, they will
  3864. 3:08:12show you this page where you see they
  3865. 3:08:15are telling you claim your prize. But
  3866. 3:08:17this page is layered on top of another
  3867. 3:08:20page. So when you click on claim your
  3868. 3:08:23prize, you are not clicking on this
  3869. 3:08:25button. You are clicking on another one
  3870. 3:08:27which is invisible to you. And here they
  3871. 3:08:30say confirm bank payment. So they can do
  3872. 3:08:33uh shady things. They can take your data
  3873. 3:08:36or something like that. So that's a
  3874. 3:08:38problem and we don't want to do that. We
  3875. 3:08:39we want to to prevent this. To do that
  3876. 3:08:42we add xframe options and we tell same
  3877. 3:08:46origin. As you can see we are not using
  3878. 3:08:48cross origin uh or other directive. Uh
  3879. 3:08:51let's look at the other directories
  3880. 3:08:53quickly. Let's search for it here. Um
  3881. 3:08:55Mozilla.
  3882. 3:08:57Okay. So here this is what we have. So
  3883. 3:08:59we have either deny sim origin or allow
  3884. 3:09:02from origin. Awesome. So we have that.
  3885. 3:09:04We also have MIM sniffing. This one
  3886. 3:09:08forces the browser to strictly trust the
  3887. 3:09:10file type declared by the server.
  3888. 3:09:12Sometimes attackers might upload
  3889. 3:09:16malicious files maybe like a script but
  3890. 3:09:19they might tell the browser this is not
  3891. 3:09:21a script this is an image and this is
  3892. 3:09:23called MIM sniffing. MIM means uh the
  3893. 3:09:27the format types. So let's search for
  3894. 3:09:29MIM. If you are not familiar with MIM
  3895. 3:09:32let's search for MIM type and yeah it's
  3896. 3:09:35uh media types. So this uh uh yeah it
  3897. 3:09:39can mean pawns, images, text, scripts
  3898. 3:09:43etc. So attackers will trick your
  3899. 3:09:46browser to think that that script is an
  3900. 3:09:48image and in that script they might load
  3901. 3:09:51some uh malicious code or something like
  3902. 3:09:53that. So we want to deny this. We don't
  3903. 3:09:55want them to sniff the file types. We
  3904. 3:09:58added three extra headers. Now save the
  3905. 3:10:01configuration. Let's do engineext-t.
  3906. 3:10:04Everything is good. Let's reload. Nice.
  3907. 3:10:07So, let's go to the browser. Let's close
  3908. 3:10:10these tabs. We don't need them. Let's
  3909. 3:10:11scan. Great. Now, we have D. So, you can
  3910. 3:10:14see that we have two green check marks,
  3911. 3:10:15but we need to add another ones. Uh,
  3912. 3:10:18these two are simple. So, let's add
  3913. 3:10:19them. And let's leave CSP at the end.
  3914. 3:10:23Okay. And let's add the headers just
  3915. 3:10:26below them. So, here we have this one is
  3916. 3:10:29for privacy. When a user clicks a link
  3917. 3:10:32on your website, uh for example, if I
  3918. 3:10:35link a maybe a Wikipedia article on my
  3919. 3:10:39website, if a user clicks it, the
  3920. 3:10:42browser will send a referral header to
  3921. 3:10:45the new site. So if you want to protect
  3922. 3:10:47user privacy by only sending your your
  3923. 3:10:50root domain name, not the full URL path,
  3924. 3:10:54you can do this. So this uh then wiki
  3925. 3:10:57here if they click on that Wikipedia
  3926. 3:10:59link they will Wikipedia will only see
  3927. 3:11:02my domain name they will not be able to
  3928. 3:11:03see the full link. So yeah we can add
  3929. 3:11:06this and here this one is simple. So if
  3930. 3:11:09your website doesn't require using
  3931. 3:11:11camera microphone dual location payment
  3932. 3:11:15you can disable them because these are
  3933. 3:11:16things that I don't want and that's
  3934. 3:11:18great. So if someone tries to maybe hack
  3935. 3:11:21your website and enable the user's
  3936. 3:11:24camera that's that will not happen
  3937. 3:11:26because we are blocking blocking that
  3938. 3:11:29with the help of the permissions policy
  3939. 3:11:31header. Now save exit the file verify
  3940. 3:11:35that the configuration is correct. Now
  3941. 3:11:37reload let's go to the website and let's
  3942. 3:11:40refresh. Awesome. So it says C and in
  3943. 3:11:44order to jump from C to A+ we need to
  3944. 3:11:47work on CSP which is the final boss.
  3945. 3:11:50This one is complex but I'll show you
  3946. 3:11:52how to do it uh step by step. Okay,
  3947. 3:11:55let's go back to our website. So this is
  3948. 3:11:58the front end. Everything looks good. Uh
  3949. 3:12:02let me open another tab. I want you to
  3950. 3:12:04search for this. So we find it here and
  3951. 3:12:07we also uh you can also see it here. So
  3952. 3:12:10yeah, uh if you want to read more about
  3953. 3:12:12cross sites, that's not what I wanted to
  3954. 3:12:14search for. I wanted to search for
  3955. 3:12:16content security policy CSP. Uh yes,
  3956. 3:12:21here it is. You can see that this
  3957. 3:12:23article is very long because in order in
  3958. 3:12:26order to build it, there isn't a one
  3959. 3:12:30there isn't one CSP that everyone can
  3960. 3:12:32uses. This depends on what you are using
  3961. 3:12:35in your website. That's why you need to
  3962. 3:12:37build it progressively.
  3963. 3:12:39open your uh website. So I will delete
  3964. 3:12:43uh the tab that we don't need. Okay, we
  3965. 3:12:46just want these two. Now we are in
  3966. 3:12:48Chrome because here we have the ability
  3967. 3:12:52to change this CSP very quickly. I'll
  3968. 3:12:56show you how to do this. Now I want you
  3969. 3:12:59to look at the very top of the network
  3970. 3:13:02request list. Here we don't have a
  3971. 3:13:04domain. That's why we have just uh the
  3972. 3:13:07IP address. Right click, show all
  3973. 3:13:10overrides. Uh here I will start fresh.
  3974. 3:13:13Now select let's click on select folder
  3975. 3:13:15for override. So I will create one here
  3976. 3:13:20and select it and let's yeah allow this.
  3977. 3:13:24Now go back to network. Here I want to
  3978. 3:13:27click on override headers. Yes, that
  3979. 3:13:30worked. And here let's add content
  3980. 3:13:34security
  3981. 3:13:36policy because this is the one that we
  3982. 3:13:38want to work with. And here in the
  3983. 3:13:40header value let's start with default
  3984. 3:13:44source and let's do none. And let's not
  3985. 3:13:46forget the semicolon. Now hit enter. Now
  3986. 3:13:50I want you to click on the dot headers
  3987. 3:13:53pile here. It should say star because we
  3988. 3:13:57want to apply it to everything. And
  3989. 3:13:59let's refresh the page. Okay, you can
  3990. 3:14:02see that we cannot view the website. H
  3991. 3:14:05and we have a lot of errors. So we can
  3992. 3:14:07see that here it says refused to load
  3993. 3:14:09the image, refused to load the
  3994. 3:14:12stylesheets, refused to load the script.
  3995. 3:14:14So now that's what we need to do the and
  3996. 3:14:17also make sure if you want you can open
  3997. 3:14:19this uh headers file in a text editor so
  3998. 3:14:22that you can change it here easily. I'm
  3999. 3:14:25opening it in sublime and yeah I see the
  4000. 3:14:28same thing. So I'm applying it to
  4001. 3:14:29everything and I am just playing with
  4002. 3:14:32this header and default source none will
  4003. 3:14:35block everything. So this is the
  4004. 3:14:37strictest CSP and as you can see it
  4005. 3:14:39doesn't work but we start from here and
  4006. 3:14:41we start relaxing it in steps. So you
  4007. 3:14:44can see that there are many things that
  4008. 3:14:45are blocked. There are images that are
  4009. 3:14:47blocked some styles. You can see that
  4010. 3:14:49this image comes from our origin. So
  4011. 3:14:52this one is fine. Uh let's see we here
  4012. 3:14:55we are blocking this side sheets because
  4013. 3:14:57we are it comes from cloud flare so this
  4014. 3:15:00is not our website it's coming from
  4015. 3:15:02another place but we know that we need
  4016. 3:15:04this font it's awesome so we can keep it
  4017. 3:15:06that's not a problem but this will show
  4018. 3:15:08you the things you will decide do you
  4019. 3:15:11want to keep it or block it uh same
  4020. 3:15:14thing for scripts these are all coming
  4021. 3:15:16from our assets folder so yeah these are
  4022. 3:15:18these things can can be kept but uh if
  4023. 3:15:21you if we see that there are other
  4024. 3:15:23strange change things we need to decide
  4025. 3:15:25if we should keep them or not. So let's
  4026. 3:15:27start with the uh with the images. So I
  4027. 3:15:30will come here. You can see that here
  4028. 3:15:32default source I will change it from
  4029. 3:15:34none to self. I saved the file. Now I'll
  4030. 3:15:38go to the browser. Let's refresh. So
  4031. 3:15:40that's solved a lot of problems. Why?
  4032. 3:15:43Because you see that we don't have
  4033. 3:15:46assets. The image was loaded because
  4034. 3:15:48those things were in our disc folder. So
  4035. 3:15:52when we built the website we already had
  4036. 3:15:54those images uh those stylesheets
  4037. 3:15:56everything was there. So when you use
  4038. 3:15:59self it means our origin everything in
  4039. 3:16:02our origin uh should be allowed to load.
  4040. 3:16:07Now we aren't we have uh different
  4041. 3:16:10errors. So for forget about these ones
  4042. 3:16:13uh because as we saw before we don't
  4043. 3:16:15have media search that's why they are
  4044. 3:16:16failing. But focus on these. Now we
  4045. 3:16:19cannot load this font. So this is the
  4046. 3:16:21fonts that we are using in our website.
  4047. 3:16:23Yeah, let's fix this one. Go back here
  4048. 3:16:26and we have another directive. We need
  4049. 3:16:29to come here. Let's add a space and
  4050. 3:16:32let's put style source. This one will
  4051. 3:16:34allow us to load styles. Again, we can
  4052. 3:16:37start with self. And if we want, we can
  4053. 3:16:40add more things here. But let's save
  4054. 3:16:42this. Let's go back to the website. Uh
  4055. 3:16:44or instead, let's let me put it here.
  4056. 3:16:46And let me load Chrome like this. Yeah,
  4057. 3:16:49that's better. And I will move this docs
  4058. 3:16:53this panel uh to the bottom. Now I've
  4059. 3:16:56saved this. I will refresh the page. Uh
  4060. 3:16:59we still have some problems with uh
  4061. 3:17:02Google. So we will copy this link and
  4062. 3:17:05paste it here. We we we need just the
  4063. 3:17:08the origin. We don't need the full URL.
  4064. 3:17:10So we can see that the origin is
  4065. 3:17:12fonts.googleapis.com.
  4066. 3:17:14That's what we need. Now save. Refresh
  4067. 3:17:17the page. And as you can see now we are
  4068. 3:17:20able to load the font. We don't have any
  4069. 3:17:22any error. Now we have another
  4070. 3:17:24stylesheet issue but this time we will
  4071. 3:17:27just take this domain. Take it copy and
  4072. 3:17:30let's add it after Google. Sorry let's
  4073. 3:17:34add it here before the semicolon. Save.
  4074. 3:17:37Refresh the page. Awesome. So now we are
  4075. 3:17:40we are able to load font awesome icons.
  4076. 3:17:43We are able to load the font. And as you
  4077. 3:17:46can see, we don't have those errors, but
  4078. 3:17:47we have different errors. So here we are
  4079. 3:17:50not able to load the font URL because it
  4080. 3:17:53violates the following default source
  4081. 3:17:56self. Okay. So you can see that here we
  4082. 3:17:58don't have uh let me decrease the font
  4083. 3:18:00size. We have default source. We have
  4084. 3:18:02style source but we haven't yet added
  4085. 3:18:05font source. So let's do that. I will
  4086. 3:18:08come after the semicolon. I will add
  4087. 3:18:10this and I will add another semicolon.
  4088. 3:18:13Save this. refresh the page. Okay. So,
  4089. 3:18:16let's open this and let's see what's
  4090. 3:18:18happening. So, again, we have the same
  4091. 3:18:21do origin. Let's copy it. Let's paste it
  4092. 3:18:24after self. Save. Reload. Okay. So, we
  4093. 3:18:27have a different domain that's coming
  4094. 3:18:29from Jstatic. That one is fine. Again,
  4095. 3:18:33if you see that there is a domain or an
  4096. 3:18:35origin that is suspicious, then you feel
  4097. 3:18:38free to block it. But if you think that
  4098. 3:18:40this is something that you are using and
  4099. 3:18:44it comes from a reputable website, it's
  4100. 3:18:46not something suspicious, then add it to
  4101. 3:18:48the list. So now we solved the problem
  4102. 3:18:50with fonts. Now let's look at images.
  4103. 3:18:54Okay. So here we have some X SVG files
  4104. 3:18:58and in order to keep those we can just
  4105. 3:19:00add data. I will come where is it? Do I
  4106. 3:19:04have image source? No, we don't. And
  4107. 3:19:06here they are telling us. So note that
  4108. 3:19:08image source was not explicitly set. So
  4109. 3:19:11again let's do the same thing. Uh I will
  4110. 3:19:13copy font source. I'll come here and
  4111. 3:19:16here I'll need to change it to image
  4112. 3:19:18source. Save. Reload. Okay. That still
  4113. 3:19:22doesn't work because we need to add this
  4114. 3:19:25here. We don't have a website but uh we
  4115. 3:19:28can add where is image. Uh let me make
  4116. 3:19:31this smaller. Yeah, it's here. I can
  4117. 3:19:33come after this and add data. Let's
  4118. 3:19:35refresh the page. And voila. As you can
  4119. 3:19:38see, we were able to fix uh all every
  4120. 3:19:42error. And now these are just coming
  4121. 3:19:44from the back end. But we are not done
  4122. 3:19:45yet. What we what you need to do is to
  4123. 3:19:48test your whole website. Make sure to
  4124. 3:19:50click on every single page. See if the
  4125. 3:19:53errors are uh if you don't see the goal
  4126. 3:19:57is that we we should not see errors
  4127. 3:19:59coming from here. Okay. So as you can
  4128. 3:20:02see, we have other problems. Okay. So we
  4129. 3:20:04have inline style issues. Let's go back
  4130. 3:20:08to sublime text. I want you to find
  4131. 3:20:12style source. Do we have Yes, we have
  4132. 3:20:15style source. So we have self font.
  4133. 3:20:18Google and here. So I will add a space
  4134. 3:20:20at the end because here they say that we
  4135. 3:20:23are using so yeah we are using inline
  4136. 3:20:26styles but that this is blocked by
  4137. 3:20:28default. So we need to add unsafe
  4138. 3:20:30inline.
  4139. 3:20:33Let's save it first and let's reload the
  4140. 3:20:35page. Okay, we have zero errors. Great.
  4141. 3:20:38But this is unsafe. Here's the thing.
  4142. 3:20:40Even though this is unsafe, it's fine
  4143. 3:20:43here in our case because in our Vue.js
  4144. 3:20:46application or maybe you uh you might be
  4145. 3:20:49using React or other frameworks. You you
  4146. 3:20:52are using inline styles or inline
  4147. 3:20:54scripts and those are fine because if
  4148. 3:20:56you don't do those, your application
  4149. 3:20:58won't work. But yeah, by default they
  4150. 3:21:00are blocked but we can add them. Let's
  4151. 3:21:02continue testing the application. Let's
  4152. 3:21:04go here. Okay, that's fine. So, the
  4153. 3:21:07other pages are not working because they
  4154. 3:21:09need to communicate with me search. But
  4155. 3:21:11at least uh every other page is working
  4156. 3:21:14uh correctly. Good. Now, after doing
  4157. 3:21:17this, we can let's let's copy the value.
  4158. 3:21:21I'll hit Ctrl X. I no longer need this.
  4159. 3:21:24So, I'll clear this. Uh I'll just keep
  4160. 3:21:26this. Now, I'll go back to engine X. I
  4161. 3:21:30need to update the configuration. So
  4162. 3:21:33let's do that. I will come down and here
  4163. 3:21:38I'll type add header. It's going to be
  4164. 3:21:41content security policy. I'll add quotes
  4165. 3:21:47and I'll add the other ones. As you can
  4166. 3:21:49see, I have added the CSP. I'll save the
  4167. 3:21:53file. I'll exit. Let's verify that the
  4168. 3:21:56syntax is okay. And it isn't. So this is
  4169. 3:21:59why we need to do this. Let's go back. I
  4170. 3:22:02forgot to add something at the end.
  4171. 3:22:04Yeah, I forgot to add always. And why do
  4172. 3:22:08we do this? Because we want to send this
  4173. 3:22:09header in all the response codes. So if
  4174. 3:22:13we get 200, 2010,
  4175. 3:22:16all of them. So uh this header will be
  4176. 3:22:19there. And we can also add something
  4177. 3:22:21here at the end. I will add another
  4178. 3:22:24semicolon. I will add upgrade insecure
  4179. 3:22:27requests. This one again forces the
  4180. 3:22:29browser to change from HTTP to HTTPS.
  4181. 3:22:33Now we have HTTP. So this doesn't matter
  4182. 3:22:36but later uh after adding SSL
  4183. 3:22:39certificates stuff like that we will be
  4184. 3:22:42able to have HTTPS. Now we are just
  4185. 3:22:45preparing save the file exit. Verify
  4186. 3:22:49okay the syntax is okay this time and
  4187. 3:22:52let's reload X. Okay so this is the
  4188. 3:22:54moment of truth. I will take this. Let's
  4189. 3:22:58put it here. We need to make sure that
  4190. 3:22:59the the website loads correctly. And it
  4191. 3:23:02is it is loading. Let me move this to
  4192. 3:23:05the left. Uh I will clear the logs. I
  4193. 3:23:08also go to the other pages. Yeah,
  4194. 3:23:09everything seems to be working
  4195. 3:23:11perfectly. Okay. So now let's scan
  4196. 3:23:14again. And yes, we got uh a um maybe uh
  4197. 3:23:19on Firefox might have gotten a plus, but
  4198. 3:23:22this is the highest score that we can
  4199. 3:23:23get. And as you can see, everything is
  4200. 3:23:24green. And the yeah these are the this
  4201. 3:23:28is the response that uh we received. So
  4202. 3:23:30as you can see this is what we have
  4203. 3:23:31added here is upgrading secure requests
  4204. 3:23:34and yeah they're also telling you if you
  4205. 3:23:36want to add other requests but this is
  4206. 3:23:37the bare minimum you need to have these
  4207. 3:23:40and as you can see most of them are easy
  4208. 3:23:42but content security policy is the one
  4209. 3:23:44that takes time because it is unique to
  4210. 3:23:47each website. Your application is now
  4211. 3:23:50live. Engine X is serving your view
  4212. 3:23:52front end and routing API calls to your
  4213. 3:23:55fast API back end. However, we haven't
  4214. 3:23:59yet configured search. This is a search
  4215. 3:24:02engine that I am using to s to allow
  4216. 3:24:05users to search for articles. It's
  4217. 3:24:08similar to elastic search uh yeah to
  4218. 3:24:10elastic search but it doesn't consume a
  4219. 3:24:12lot of memory. So we are going to
  4220. 3:24:14configure that in the next chapter. But
  4221. 3:24:16if you don't care about mail search, you
  4222. 3:24:19can skip to the to the other chapter,
  4223. 3:24:22chapter number four where we are going
  4224. 3:24:24to create our domain name, add SSL
  4225. 3:24:27certificates and make our websites
  4226. 3:24:29secure by accessing by making um making
  4227. 3:24:33users access accesses through HTTPS
  4228. 3:24:36instead of HTTP. See you in the next
  4229. 3:24:38chapter. Welcome to module 3. At this
  4230. 3:24:42point, we have a secure server and we
  4231. 3:24:45have deployed the front end and back end
  4232. 3:24:49successfully. There is one missing piece
  4233. 3:24:52if you are using my project which is to
  4234. 3:24:55include a search engine. In my case, I
  4235. 3:24:58am self-hosting M search because it is
  4236. 3:25:02lightweight, doesn't consume a lot of
  4237. 3:25:04memory and it is fast. A quick note on
  4238. 3:25:07this module. If your specific project
  4239. 3:25:10doesn't need a search feature, you can
  4240. 3:25:13technically skip this chapter. However,
  4241. 3:25:16I highly recommend following along
  4242. 3:25:18anyway because the skills you are about
  4243. 3:25:21to learn like creating a system user and
  4244. 3:25:24deploying background services that are
  4245. 3:25:27completely hidden from the internet are
  4246. 3:25:30essential server skills you will use
  4247. 3:25:32anytime you need to host your own
  4248. 3:25:35database or yeah something else. Here is
  4249. 3:25:38our road map. First the search engine
  4250. 3:25:42that we are going to download is me
  4251. 3:25:44search. There are other options like
  4252. 3:25:46elastic search but those consume a lot
  4253. 3:25:49of memory and here we are playing with a
  4254. 3:25:51small virtual machine and we can't just
  4255. 3:25:54host elastic search. So we are using me
  4256. 3:25:57search because it's lightweight it's
  4257. 3:26:00fast and most importantly it doesn't
  4258. 3:26:02consume a lot of memory. Next we are
  4259. 3:26:05going to log this database by creating a
  4260. 3:26:09dedicated system user. I'll explain the
  4261. 3:26:13difference between a regular user and a
  4262. 3:26:16system user in the upcoming slides. Then
  4263. 3:26:19you will configure systemd to run me
  4264. 3:26:23search as a background service. This
  4265. 3:26:26will allow us to perform daily backups.
  4266. 3:26:30Make sure that me search is running even
  4267. 3:26:32if it if the service fails and other
  4268. 3:26:35things. As I said, we are going to
  4269. 3:26:37schedule automatic snapshots. I'll show
  4270. 3:26:39you how to do it. You can specify the
  4271. 3:26:41duration. Do you want to do it daily,
  4272. 3:26:43weekly? It depends on how much your data
  4273. 3:26:46changes. Finally, we are going to use
  4274. 3:26:49SSH tunneling again to access the daily
  4275. 3:26:53search database uh using a dashboard.
  4276. 3:26:57Now let's go back to GitHub. I want to
  4277. 3:27:00show you what we are trying to do. We
  4278. 3:27:03are now in module 3 data and search. You
  4279. 3:27:07will you'll find the commands here. So
  4280. 3:27:10even if you get lost or if you find long
  4281. 3:27:12commands, don't worry about them. Uh you
  4282. 3:27:14will find everything inside this
  4283. 3:27:16markdown document. As I said, if you
  4284. 3:27:19don't have a project and you rely on my
  4285. 3:27:22own inside the backend folder, I have
  4286. 3:27:25everything for you. So even if you don't
  4287. 3:27:27have data that you want to put in me
  4288. 3:27:30search, you can just come here in the
  4289. 3:27:32seed folder and I have created this
  4290. 3:27:36documents list. As you can see, we have
  4291. 3:27:39some documents that we can index uh in
  4292. 3:27:42mill to me search. Okay, so don't worry
  4293. 3:27:44about this. Everything is inside these
  4294. 3:27:47two repositories. Great. Now, open your
  4295. 3:27:50terminal and let's SSH to the machine. I
  4296. 3:27:54will use
  4297. 3:27:56my alias. Uh the alias that I'm using is
  4298. 3:27:59my website. I have successfully logged
  4299. 3:28:02into the machine. Uh let's run ls. Yeah.
  4300. 3:28:06Uh let's go to web app. Okay, so we have
  4301. 3:28:08everything. Great. Let's start by
  4302. 3:28:11installing me search. If you click on
  4303. 3:28:15the curl option, I mean you have a lot
  4304. 3:28:17of options, but we'll go with this one.
  4305. 3:28:19Copy this command. Paste it here inside
  4306. 3:28:23the machine. It shouldn't take a lot of
  4307. 3:28:26time. Yeah. So it worked. Let's see. So
  4308. 3:28:28we have me search. Uh let's see if it is
  4309. 3:28:32executable.
  4310. 3:28:33Yes. If we are the current yeah for my
  4311. 3:28:36current user it is executable. Now we
  4312. 3:28:38need to move this binary into user local
  4313. 3:28:43/bin. Let's do this. So we have mainly
  4314. 3:28:46search here. Let's move it to user local
  4315. 3:28:51bin. I need to provide my password.
  4316. 3:28:54Awesome. Why we do this? Because it
  4317. 3:28:56allows us to run search from any place.
  4318. 3:28:59So I can now just type med search d-
  4319. 3:29:02version and it works. I don't need to go
  4320. 3:29:05to uh say say I downloaded the binary in
  4321. 3:29:09the downloads folder. If I don't move it
  4322. 3:29:12to user local bin, I have to always go
  4323. 3:29:14to downloads in order to interact with
  4324. 3:29:16the binary. But now when you put it in
  4325. 3:29:20uh user local bin, it allows you to run
  4326. 3:29:23it from any place like we did. Now if I
  4327. 3:29:26type ls as you can see we don't have the
  4328. 3:29:28mely search binary but I was able to run
  4329. 3:29:32the me search uh version command without
  4330. 3:29:35any error. So now we have me search.
  4331. 3:29:38Let's create a system user. Before we do
  4332. 3:29:42that I would like to come to go back to
  4333. 3:29:43the slides to explain the difference
  4334. 3:29:45between a regular and a system user. I
  4335. 3:29:49have created this table to explain to
  4336. 3:29:52you the difference between these two
  4337. 3:29:54types of users. Here are the features
  4338. 3:29:56and here are the types of users. So what
  4339. 3:29:58is the purpose of a standard user when
  4340. 3:30:01we started this course? We created a
  4341. 3:30:04user. We are not using the root user but
  4342. 3:30:07we created another user that we can use
  4343. 3:30:09to do maintenance, install software.
  4344. 3:30:12Yeah, stuff like that. We are using a
  4345. 3:30:14standard user to administer to do
  4346. 3:30:17maintenance. So this is the purpose of
  4347. 3:30:19this user. But a system user is used to
  4348. 3:30:24run background services only. So if I
  4349. 3:30:27want to run M search uh in a background
  4350. 3:30:30service, I need to run to use a system
  4351. 3:30:32user for that. Can we use the shell in a
  4352. 3:30:36standard user? Yes. As you saw, I was
  4353. 3:30:38able to SSH to the machine and uh type
  4354. 3:30:41commands. But if I try to do the same
  4355. 3:30:43with a system user, I won't be able to
  4356. 3:30:45because we deactivate that. This means I
  4357. 3:30:48can't login as a system user and start
  4358. 3:30:51typing commands. So this is the same
  4359. 3:30:53thing that I that I mentioned here. So
  4360. 3:30:55login is possible with a standard user
  4361. 3:30:57but it isn't allowed with a system user
  4362. 3:31:00and generally the standard users have
  4363. 3:31:03their uh home folder inside/home
  4364. 3:31:07but system users are yeah put somewhere
  4365. 3:31:10else. So this is the difference between
  4366. 3:31:12them and because M search is a software
  4367. 3:31:15that we want to run as a background
  4368. 3:31:18service we want this specific system
  4369. 3:31:21user to be responsible of handling that.
  4370. 3:31:25Okay. So let's create uh a system user
  4371. 3:31:28and we can call it med search because it
  4372. 3:31:30uh its job is to uh uh run this software
  4373. 3:31:35for us. And in order to do that, we will
  4374. 3:31:37use the user add command. Here I will uh
  4375. 3:31:42specify the directory where we want to
  4376. 3:31:45put this user. As I said, we are not
  4377. 3:31:48going to put it in home. We will put it
  4378. 3:31:50here. var lib mail search. We will
  4379. 3:31:53disable login. So we won't give it shell
  4380. 3:31:56access. And finally, we will call it
  4381. 3:32:00search. Mele search. I hope I didn't
  4382. 3:32:02make a mistake. Me search. Me search.
  4383. 3:32:05Yes. So now let's hit enter and it
  4384. 3:32:09worked. Now let's try to look at this
  4385. 3:32:13directory. As you can see the I don't
  4386. 3:32:15have the permissions. Why? Because I am
  4387. 3:32:17using my standard user aad and this
  4388. 3:32:21folder or yeah this directory is owned
  4389. 3:32:25by me search the system user we created
  4390. 3:32:28and we can verify this. And if we do
  4391. 3:32:30sudo as you can see this user mini
  4392. 3:32:33search owns this this folder. So we
  4393. 3:32:37cannot go inside it. But yeah with with
  4394. 3:32:40root we can do that and we can also
  4395. 3:32:42verify it here. As you can see the
  4396. 3:32:45permissions are they are they are
  4397. 3:32:47constrained. They are they are allowing
  4398. 3:32:49just this user to write to this
  4399. 3:32:52directory. Great. So this confirms that
  4400. 3:32:54everything is working. Now we need to
  4401. 3:32:56create a folder inside
  4402. 3:33:00uh that will hold data. We need to
  4403. 3:33:03create the data folder because me search
  4404. 3:33:06needs somewhere to save data. So let's
  4405. 3:33:08do it. Uh let's verify the ownership.
  4406. 3:33:12This is very important. ls-la
  4407. 3:33:15as you can see. Uh let me go back. Okay.
  4408. 3:33:18So data is owned by root and we want it
  4409. 3:33:22to be owned by med search. So let's do
  4410. 3:33:24it. We we have used this each own
  4411. 3:33:28command before. Here we are uh changing
  4412. 3:33:31the user and group from root to M search
  4413. 3:33:35and we want this user to own everything
  4414. 3:33:37inside this directory. That's why we are
  4415. 3:33:40using dash r. So now if I rerun this
  4416. 3:33:43command as you can see now the data
  4417. 3:33:46folder is owned by mini search. Awesome.
  4418. 3:33:49So now we installed the mini search
  4419. 3:33:51binary. We created a system user. Now we
  4420. 3:33:55need to put some data inside. So if you
  4421. 3:33:59already have your own instance, you you
  4422. 3:34:02don't need to use let let me go back to
  4423. 3:34:05GitHub. You don't need to use this JSON
  4424. 3:34:08file. You can just uh export the data
  4425. 3:34:12from your local main search instance and
  4426. 3:34:14use that. If you if you don't have data,
  4427. 3:34:18then you can use this. I'll show both
  4428. 3:34:20options. so that uh everyone can uh
  4429. 3:34:24follow along. Let's start by exporting
  4430. 3:34:27data from a local me search instance.
  4431. 3:34:30For that I will create another terminal
  4432. 3:34:32window. Now I am uh on my local machine.
  4433. 3:34:36I will start the mearch service and I
  4434. 3:34:39will show you how to export data from
  4435. 3:34:42it. I will use T-Max to create two panes
  4436. 3:34:46here. Okay, I moved where I installed me
  4437. 3:34:50search and this is how I am using it.
  4438. 3:34:52Um, okay. So, as you can see it started.
  4439. 3:34:55Let me show everything and here. Yeah,
  4440. 3:34:57it is listening on this port. Maybe
  4441. 3:35:00search by default uses port 7,700.
  4442. 3:35:03Uh, in this other terminal we can talk
  4443. 3:35:07to this server. We can use the terminal
  4444. 3:35:10or if you want you can also use their
  4445. 3:35:13SDKs. They have one for Python,
  4446. 3:35:15JavaScript and other programming
  4447. 3:35:17languages. But for now, to keep things
  4448. 3:35:19simple, we will just use the yeah the
  4449. 3:35:23terminal and we'll just run a curl
  4450. 3:35:25command. And as you can see here, we
  4451. 3:35:27have something that we call dumps. And
  4452. 3:35:30here I need to provide my master key.
  4453. 3:35:32And since we are on a local machine,
  4454. 3:35:35yeah, I am just using their default
  4455. 3:35:38master key. Plus in a production
  4456. 3:35:41environment we will change this into a
  4457. 3:35:43secure key. But for now it's fine. Uh
  4458. 3:35:46when what you are working with this
  4459. 3:35:48locally no one will steal data from you.
  4460. 3:35:50So it's fine. Keep it like this as the
  4461. 3:35:52default. Yeah. So now I can't talk to
  4462. 3:35:55this. But before running the command I
  4463. 3:35:57just want to explain the difference
  4464. 3:35:58between dumps and snapshots. If you
  4465. 3:36:02search for me search dumps snapshots,
  4466. 3:36:05you will find this page where they
  4467. 3:36:07explain the difference between these two
  4468. 3:36:10concepts. A snapshot is an exact copy of
  4469. 3:36:14your database. You use a snapshot to
  4470. 3:36:17create backups. So this is what we are
  4471. 3:36:19going to schedule later. We are going to
  4472. 3:36:22uh allow me search to save a backup of
  4473. 3:36:24the database daily. So that's let's say
  4474. 3:36:27some if uh for some reason something bad
  4475. 3:36:30happened to me search and you lost data
  4476. 3:36:34you can recover by using these
  4477. 3:36:36snapshots. A dump on the other hand is
  4478. 3:36:40just a set of instructions that are used
  4479. 3:36:43to recreate the database from scratch.
  4480. 3:36:45So this is the difference between the
  4481. 3:36:47two and dumps are the safest way to
  4482. 3:36:50migrate data across different machines
  4483. 3:36:53or versions. This is why in uh my local
  4484. 3:36:57terminal I am using the dumps. I'm going
  4485. 3:37:00to create a dump with this curl command.
  4486. 3:37:03So now let's run it. As you can see we
  4487. 3:37:05get a task uid. Uh in m search tasks are
  4488. 3:37:09asynchronous which means that they take
  4489. 3:37:12time to finish but search at least gives
  4490. 3:37:15us a task u so that we can track the
  4491. 3:37:18task and the task that we are performing
  4492. 3:37:21is creating a dump. And if you want to
  4493. 3:37:24follow a task, what you need to do is to
  4494. 3:37:27change here dumps to tasks and you
  4495. 3:37:32provide the U ID and in in our case it's
  4496. 3:37:354,94
  4497. 3:37:38and you yeah keep keep the authorization
  4498. 3:37:41key and hit enter. And here I forgot to
  4499. 3:37:44change post to get. So let's try to do
  4500. 3:37:47that. And as you can see the status is
  4501. 3:37:50succeeded which means that we were able
  4502. 3:37:52to create a dump. That's great. And we
  4503. 3:37:55can also if you want you can also verify
  4504. 3:37:57this in the mini search server. Uh so
  4505. 3:38:01here we started with 20 workers. And
  4506. 3:38:04here as you can see we the server
  4507. 3:38:06received the the task and here it says a
  4508. 3:38:09batch of task was successfully completed
  4509. 3:38:12with one successful task which means
  4510. 3:38:14that everything worked great. Now we
  4511. 3:38:16just need to find this dump. As you can
  4512. 3:38:19see, I have my mini search binary inside
  4513. 3:38:22this folder. If I hit if I try to run
  4514. 3:38:25ls, you can see that we have a dumps
  4515. 3:38:28folder. Let's go there and let's see
  4516. 3:38:31what we have. Let me also remove the
  4517. 3:38:33first pane. We don't need it. As you can
  4518. 3:38:34see, I have created a lot of dumps.
  4519. 3:38:37Let's look at this one. So, we uh as you
  4520. 3:38:40can see, they label them by date. So we
  4521. 3:38:42are in 2026 which means this is the one
  4522. 3:38:44that we created. Today is March 20 which
  4523. 3:38:47is correct. So this is the one that we
  4524. 3:38:49created. Great. Now we need to take this
  4525. 3:38:52dump and move it to the virtual machine.
  4526. 3:38:56As I mentioned you can if you don't want
  4527. 3:38:58to use curl you can use one of their
  4528. 3:39:00SDKs. If if you go to this page I just
  4529. 3:39:04searched for create dump and I got I got
  4530. 3:39:07here. If you click on curl, you can get
  4531. 3:39:10as you can see they have a lot of
  4532. 3:39:11programming languages. Let's select
  4533. 3:39:14Python. And as you can see when you
  4534. 3:39:16create the client, you can just call the
  4535. 3:39:18create them. Uh the response will be a
  4536. 3:39:20task u uh same same as what we got in
  4537. 3:39:25the terminal just by using the curl
  4538. 3:39:26command and after that you can just wait
  4539. 3:39:28for it to finish. In the beginning it's
  4540. 3:39:31going to be incued but after uh a
  4541. 3:39:33successful execution it's going to
  4542. 3:39:35return succeeded. Uh so they talk about
  4543. 3:39:37authorization. So yeah, everything you
  4544. 3:39:39need to know about uh how this works.
  4545. 3:39:42Now let's go back to the terminal. We
  4546. 3:39:44need to move this to the machine. Uh so
  4547. 3:39:48let's use the SCP command. Let's paste
  4548. 3:39:51the name of that dump. I will use my
  4549. 3:39:54alias, my website, and I will put this
  4550. 3:39:59uh temporarily in the temp directory.
  4551. 3:40:02Okay. Okay. Great. So that worked. Uh
  4552. 3:40:05let me copy the name again. I'll go back
  4553. 3:40:08to the virtual machine and let's find
  4554. 3:40:11that if if the dump is uh inside the
  4555. 3:40:13temp deck directory or not. So let's use
  4556. 3:40:16ls temp and let's paste the name of that
  4557. 3:40:20file. And as you can see we have it
  4558. 3:40:23great. Now we need to move this dump. So
  4559. 3:40:26let's uh go up. I will remove ls and
  4560. 3:40:30replace it with mv to move this file
  4561. 3:40:34into var lib mail search. As you can
  4562. 3:40:38see, I cannot do this because I don't
  4563. 3:40:42own that directory. So, let's use sudo.
  4564. 3:40:45Okay, it's it's there. And again, don't
  4565. 3:40:48forget to use ch own. Uh let's search
  4566. 3:40:51for it. Hit ctrlr.
  4567. 3:40:54Start typing ch. We found it. Now hit
  4568. 3:40:58enter. Let's verify that the permissions
  4569. 3:41:01are correct. If we copy this, let's use
  4570. 3:41:06ludo ls-la
  4571. 3:41:08and paste that directory. Let's see.
  4572. 3:41:11Yes. So this dump is owned by mail
  4573. 3:41:14search. We could have created a dumps
  4574. 3:41:16folder, but for now this is temporary
  4575. 3:41:19because we just want to transfer the
  4576. 3:41:20data once and remove this file. We don't
  4577. 3:41:23we don't need it later. That's why we we
  4578. 3:41:25didn't create the dumps folder inside
  4579. 3:41:28the virtual machine. Now let me show you
  4580. 3:41:31how to run me search as a service
  4581. 3:41:33because right now if uh it's not it's
  4582. 3:41:37not running we need to manually do it
  4583. 3:41:40and if a problem happened that cause
  4584. 3:41:43many search to stop we need to SSH back
  4585. 3:41:46to the machine and rerun the command
  4586. 3:41:48again and this is not good. We want the
  4587. 3:41:52system to do this for us like when we
  4588. 3:41:55used supervisor J unicorn to manage the
  4589. 3:41:59back end uh the fast API back end for us
  4590. 3:42:02without doing any work. So this is what
  4591. 3:42:05we are going to do now. We will use the
  4592. 3:42:08mini search system user to run search as
  4593. 3:42:12a service. Here we are going to use
  4594. 3:42:15systemd to create the service. We are
  4595. 3:42:17not we are not going to use supervisor
  4596. 3:42:20like we did with J unicorn because uh
  4597. 3:42:25systemd sits at a lower level. Let me
  4598. 3:42:29explain this. Uh I have a slide that
  4599. 3:42:31explains this. So here we are talking
  4600. 3:42:32about systemd versus supervisor. As you
  4601. 3:42:36can see we have many layers and here I'm
  4602. 3:42:38just showing the operating system level
  4603. 3:42:41and the application level. So operating
  4604. 3:42:44the operating system level is lower and
  4605. 3:42:47here we have the services that are
  4606. 3:42:49running and system D manages these
  4607. 3:42:52services. We are going to create a
  4608. 3:42:54service that we will call mini search
  4609. 3:42:56and the goal here is that we want system
  4610. 3:42:58D to start this service whenever we
  4611. 3:43:02reboot whenever a mini search crashes.
  4612. 3:43:05Uh so yeah systemd will be the manager
  4613. 3:43:08and we use systemd in uh when we work
  4614. 3:43:12with things that are low level at the
  4615. 3:43:15application level for example with our
  4616. 3:43:18backend API we use supervisor for that.
  4617. 3:43:21So yeah this is the difference between
  4618. 3:43:23the systemd and supervisor. Okay now
  4619. 3:43:26let's go back to the terminal and let's
  4620. 3:43:29create this service. If you want to
  4621. 3:43:32learn more about systemd, you can just
  4622. 3:43:34type systemd and they have here their
  4623. 3:43:37website where you can learn more about
  4624. 3:43:39it. It's really awesome and uh it's also
  4625. 3:43:42easy to use. Let's go back to the
  4626. 3:43:44terminal. Now we need to create a secure
  4627. 3:43:47key. Uh if you remember here when
  4628. 3:43:51locally I am just using this dummy
  4629. 3:43:54master key that uh yeah the med search
  4630. 3:43:57team uh shows you uh in their
  4631. 3:44:00documentation but only do this if you
  4632. 3:44:03are working locally because no one will
  4633. 3:44:05steal your data because everything is
  4634. 3:44:07local in production. We need to create a
  4635. 3:44:11secure master key and that this is what
  4636. 3:44:14we are going to do in uh at this stage.
  4637. 3:44:17Okay, let's go back to the BM. Uh, in
  4638. 3:44:20etc., we need to create millarch because
  4639. 3:44:23we don't want to put the master key in
  4640. 3:44:26the service file. We want to secure this
  4641. 3:44:29so that we can just call a variable that
  4642. 3:44:32will contain the master key. And we are
  4643. 3:44:35going to do that here in this search
  4644. 3:44:37directory. And inside we will put uh an
  4645. 3:44:41env file where we are going to create uh
  4646. 3:44:45two environment variables. I'll put them
  4647. 3:44:48here but we will change the values. And
  4648. 3:44:50by default me search will search for any
  4649. 3:44:54environment variable that that uses this
  4650. 3:44:56prefix melee.
  4651. 3:44:59So here the environment is production.
  4652. 3:45:01This is important. And now we need to
  4653. 3:45:03change this placeholder to a secure key.
  4654. 3:45:07You have many options to generate a a
  4655. 3:45:10secure uh key. Uh one of the options is
  4656. 3:45:14to use OpenSSL. So when you run it, it
  4657. 3:45:17gives you this random number that you
  4658. 3:45:19can use. So yeah, just do this. Copy it
  4659. 3:45:22and put it there. I will do this and I
  4660. 3:45:24will come back. Okay, I have created the
  4661. 3:45:27key using the open SSL command. I have
  4662. 3:45:33opened the env file and I have pasted
  4663. 3:45:36that key there. I'm not I am not going
  4664. 3:45:38to show you the key and you should also
  4665. 3:45:41do the same. Keep your keys secret. No
  4666. 3:45:44one should see them. Now we need to make
  4667. 3:45:46sure that the me search user is owning
  4668. 3:45:49again these files because we are going
  4669. 3:45:51to use that user in the service. We know
  4670. 3:45:54how to do this. We are going to use the
  4671. 3:45:56chall command and yeah we want to own
  4672. 3:45:59this file. We also we are also going to
  4673. 3:46:02change the permissions. Uh I think by
  4674. 3:46:05now you know what this what 600 means.
  4675. 3:46:07It means that for the search user we
  4676. 3:46:10wanted to be able to read and write from
  4677. 3:46:12this file but we want to block access to
  4678. 3:46:16any other user. Let's just do ls-la to
  4679. 3:46:20confirm this ls-la.
  4680. 3:46:23As you can see everything is prohibited.
  4681. 3:46:25So we just uh the mail first user will
  4682. 3:46:27be able to read and write. won't be able
  4683. 3:46:29to execute. But uh and also for the the
  4684. 3:46:33group and the other users, they are
  4685. 3:46:35blocked. They they don't have the
  4686. 3:46:37permission to even see read this file.
  4687. 3:46:40This is very important because we want
  4688. 3:46:42to keep things isolated. We don't want
  4689. 3:46:45anyone to touch the NV file or to read
  4690. 3:46:48the secrets from there. Now we are ready
  4691. 3:46:50to create the service file. And as I
  4692. 3:46:53said with systemd it's it's really easy
  4693. 3:46:56and this is how we do this. We are going
  4694. 3:46:58to create a service file. You can name
  4695. 3:47:01it whatever you want but at the end you
  4696. 3:47:03need to add dots service and you put it
  4697. 3:47:05inside the systemd folder. I will paste
  4698. 3:47:08this text and I will explain what it
  4699. 3:47:10does. And again uh we have two options.
  4700. 3:47:14The first one deals with users who have
  4701. 3:47:18data and they extracted it from their
  4702. 3:47:20local uh med search instance like what
  4703. 3:47:23we are doing now. And the other option
  4704. 3:47:25is for users who don't have uh data and
  4705. 3:47:29they just want to use the the JSON file
  4706. 3:47:32that I provided. I'll come back to that
  4707. 3:47:35to that second option. But for now, this
  4708. 3:47:37is what we have in a systemd service. We
  4709. 3:47:40need to provide a description. So here
  4710. 3:47:43um provide something that is that
  4711. 3:47:46explains what this file is doing. So
  4712. 3:47:49here we are going to run the mail search
  4713. 3:47:52engine and here what does after mean?
  4714. 3:47:56This line tells Linux do not attempt to
  4715. 3:48:00start this service until the server's
  4716. 3:48:03networking stack is fully active. This
  4717. 3:48:05sometimes is important for things that
  4718. 3:48:07need internet access. But if you if you
  4719. 3:48:11are running something that doesn't
  4720. 3:48:12require it, you can remove this. This is
  4721. 3:48:14what it means. So if you want your
  4722. 3:48:16service to start maybe after some other
  4723. 3:48:18services you you do that uh here. Now we
  4724. 3:48:22have the service. So the type here is
  4725. 3:48:24set to simple and here is where we put
  4726. 3:48:28the user. As you can see we are allowing
  4727. 3:48:31only me search to run this service for
  4728. 3:48:34us. This is why we were creating all
  4729. 3:48:36these env files. Uh this is why we
  4730. 3:48:39created this working directory and we
  4731. 3:48:41made sure that me search is the own is
  4732. 3:48:45the is the owner of uh these files and
  4733. 3:48:48folders that we created. Uh let's say
  4734. 3:48:50that someone hacks your server. They
  4735. 3:48:52won't be able to look inside for for
  4736. 3:48:55instance the env file. This allows us to
  4737. 3:48:58isolate media search as much as as as
  4738. 3:49:01possible. Okay. Uh so I have this
  4739. 3:49:03comment here. uh we will load those
  4740. 3:49:07environment variables. The working
  4741. 3:49:09directory is here and here we have the
  4742. 3:49:11execute start. This is the command that
  4743. 3:49:13will be executed. As you can see we are
  4744. 3:49:15pointing to the M search binary. We can
  4745. 3:49:18uh so here I'm putting the the full path
  4746. 3:49:21but you saw that we can just use M
  4747. 3:49:23search and it's going to be recognized
  4748. 3:49:25the database path. So here M search will
  4749. 3:49:28store all its data in the data uh
  4750. 3:49:31folder. Here we have dump directory is
  4751. 3:49:34dumps like uh what I have here locally
  4752. 3:49:38and these two lines are what we want or
  4753. 3:49:42this is yeah this is uh what we what you
  4754. 3:49:45will use if you want to import the data
  4755. 3:49:48that you exported locally. So here the
  4756. 3:49:51argument is import dump and here you
  4757. 3:49:53need to specify the the path to that
  4758. 3:49:56dump file and this ignore dump if
  4759. 3:49:59database exists is very important. So if
  4760. 3:50:02you have data in me search that will
  4761. 3:50:05raise an exception because this might
  4762. 3:50:07cause me search to override your data.
  4763. 3:50:10So just for safety it's going to block
  4764. 3:50:12it here. What you say is ignore this. So
  4765. 3:50:14if you have data in me search please
  4766. 3:50:16don't import this. We don't need it. And
  4767. 3:50:20finally uh we have this is very
  4768. 3:50:22important restart on failure. As I said
  4769. 3:50:25if me search failed for some reason no
  4770. 3:50:29problem. We don't need to go to the
  4771. 3:50:31machine and restart it. System D will do
  4772. 3:50:34it for us thanks to this line. As you
  4773. 3:50:37can see the the service is easy. I just
  4774. 3:50:40need to change this placeholder. I need
  4775. 3:50:42to find the name of the dump and put it
  4776. 3:50:45here. So here is the name. I'll copy it
  4777. 3:50:48from here. Let's go back and let's paste
  4778. 3:50:51it. Let's remove this placeholder. Let's
  4779. 3:50:54paste this. Save. Exit. Let's run damon
  4780. 3:50:59reload and enable. So after creating a
  4781. 3:51:03service, we need to enable it. Uh so it
  4782. 3:51:06created a system a sim link. That's
  4783. 3:51:09good. And now we can start it. Okay. Now
  4784. 3:51:13let's go back and let's do status cuz
  4785. 3:51:15status will show us if something bad
  4786. 3:51:17happened. And as you can see, yes,
  4787. 3:51:19something bad happened. So here it says
  4788. 3:51:22failed. This is not a problem. This is
  4789. 3:51:24part of the process. Uh don't worry
  4790. 3:51:26about it. Okay, let me show you how to
  4791. 3:51:28debug this. We can use journal CLL the
  4792. 3:51:32name we put the name of the service and
  4793. 3:51:34here 10 minutes ago. So yeah, it should
  4794. 3:51:36be fine. Uh let me remove this. Okay, so
  4795. 3:51:40it tells me that I am not able to see uh
  4796. 3:51:44any message. Let's add sudo. Okay, now
  4797. 3:51:47that works. So this is what we have
  4798. 3:51:49here. As you can see it tell let's see
  4799. 3:51:52it says failed to execute
  4800. 3:51:54user/loc/bin/aily
  4801. 3:51:57search. Okay so that means it wasn't
  4802. 3:52:00able to run the binary. Okay let's see
  4803. 3:52:04why. Let's type- la user local bin and
  4804. 3:52:10me search. Ah okay. So here the problem
  4805. 3:52:13is that uh we don't have the uh execute
  4806. 3:52:17permission. So execute is given just to
  4807. 3:52:19my user but maybe search is is going to
  4808. 3:52:23be in the others section. It's not going
  4809. 3:52:26to be in my group but it's going to be
  4810. 3:52:28here. And as you can see we don't have
  4811. 3:52:29X. So we need to provide that. Okay. So
  4812. 3:52:32this is the issue. Now let's change this
  4813. 3:52:35and let's use sudo ch mode plus X. Now
  4814. 3:52:40let's go back. Okay. Now now now it
  4815. 3:52:43should be working. Now it should work.
  4816. 3:52:44Uh in order to restart the service we
  4817. 3:52:47use systemctl restart. Let's look at the
  4818. 3:52:50status and voila it is running. So it
  4819. 3:52:54says active running. Awesome. So now
  4820. 3:52:57let's see what we have here. So here it
  4821. 3:52:59gives us some info. It says the instance
  4822. 3:53:01UID. Here it says that a master key has
  4823. 3:53:04been set but it shouldn't show it. Yeah
  4824. 3:53:07it's not showing it. So request search
  4825. 3:53:10won't be authorized unless you provide
  4826. 3:53:12an authentication key. This is the ex
  4827. 3:53:14this is exactly what we have done here
  4828. 3:53:16locally when we when you try to make a
  4829. 3:53:18post request or something you need to
  4830. 3:53:21provide uh a key to be able to
  4831. 3:53:24communicate with the server. So this
  4832. 3:53:26confirms it uh and yeah they have some
  4833. 3:53:29other info uh like documentation some
  4834. 3:53:32stuff like that but what's important is
  4835. 3:53:34what we have here. So here we have
  4836. 3:53:35starting one workers uh locally uh it
  4837. 3:53:39said starting 20 workers. Uh let's
  4838. 3:53:41verify that. Yeah, it says starting 20
  4839. 3:53:44workers because I have a lot of cores.
  4840. 3:53:47If you we look at the memory, let me
  4841. 3:53:50show you and resources. As you can see,
  4842. 3:53:51I have 20 cores. So that's why locally
  4843. 3:53:54it it's going to use all of them. But we
  4844. 3:53:57are using a poor VM. It doesn't have a
  4845. 3:54:00lot of CPU cores. That's why it's going
  4846. 3:54:03to work with what we have, which is one
  4847. 3:54:06core, and that equals one worker. Uh
  4848. 3:54:10yeah, it's it's working and it is
  4849. 3:54:11listening. If we go here, it's listening
  4850. 3:54:14on port 7,700.
  4851. 3:54:16Awesome. So that means it's working. So
  4852. 3:54:19now just hit Q to exit and let's
  4853. 3:54:23continue. We have talked about option
  4854. 3:54:25one. But now let's deal with the with
  4855. 3:54:28other users who don't have their local M
  4856. 3:54:31search instance. This section is is made
  4857. 3:54:34just for those people. So for the other
  4858. 3:54:36ones who have their own local instance,
  4859. 3:54:38they can skip this section if they want
  4860. 3:54:40or they can stick they you will learn um
  4861. 3:54:43you will learn a lot. First let's verify
  4862. 3:54:46if I have the JSON here. Uh let's look
  4863. 3:54:49at web app. We need to go to back end
  4864. 3:54:52and yeah I have the seed folder. Uh
  4865. 3:54:55let's look at it. And we have
  4866. 3:54:57documents.json.
  4867. 3:54:59Awesome. You can read the readme if you
  4868. 3:55:02want. Let's let me show you the readme.
  4869. 3:55:04And here let's look at and it's it's
  4870. 3:55:07going to tell you what you need to run.
  4871. 3:55:09And here you you are not going to index
  4872. 3:55:12them manually but I have a uh I have
  4873. 3:55:15created a script for that. I called it
  4874. 3:55:17see the mainly search and it is here. It
  4875. 3:55:20is located inside the scripts folder and
  4876. 3:55:23this will uh yeah will index the
  4877. 3:55:26documents for you. Let's go inside back
  4878. 3:55:29end or yeah what's what was command?
  4879. 3:55:32Yeah, let's just take it like this. I
  4880. 3:55:34just need to go inside
  4881. 3:55:37web app. And now I can run this. Okay,
  4882. 3:55:41it didn't work because I need to
  4883. 3:55:43activate the virtual environment. This
  4884. 3:55:45is the command source van bin activate.
  4885. 3:55:48No such file or directory because I need
  4886. 3:55:51to go inside the back end. Uh let's do
  4887. 3:55:54it now. Okay, as you can see, we have
  4888. 3:55:56van which means that we were able to
  4889. 3:55:59activate the environment. Okay, now
  4890. 3:56:02let's go back to this command and let's
  4891. 3:56:04remove back end because we are inside
  4892. 3:56:06that directory and let's run this. Okay,
  4893. 3:56:09let's see. So here this is just a text
  4894. 3:56:11see the mainly search with real data.
  4895. 3:56:14Okay, here is the art the indexes we are
  4896. 3:56:16going to create. Okay, so here we are
  4897. 3:56:18trying to connect to mainly search. Uh
  4898. 3:56:20so here it says index articles already
  4899. 3:56:23exists because I have imported the dump
  4900. 3:56:27successfully connected. Uh but here we
  4901. 3:56:30have an error but it says that we have
  4902. 3:56:33an invalid API key. That's
  4903. 3:56:35understandable because I have created a
  4904. 3:56:38new master key. So let's see what we
  4905. 3:56:41have inside this file. Let's use nano.
  4906. 3:56:45Oh sorry uh I need to keep the full
  4907. 3:56:48path. Let's use nano. Okay. So here we
  4908. 3:56:52are using I have a settings. I have a
  4909. 3:56:56configuration and from that
  4910. 3:56:58configuration I load the API key. So as
  4911. 3:57:02you can see here we have API key is set
  4912. 3:57:05to settings dot mainly search master
  4913. 3:57:08key. This is why. So here I assume that
  4914. 3:57:11we are loading a default master key. Uh
  4915. 3:57:15okay that's why it didn't work. Let's
  4916. 3:57:17see. So let's go inside settings just to
  4917. 3:57:19show you what what we have there. Let's
  4918. 3:57:21go inside core. Let's look at config.
  4919. 3:57:25Yeah, as I told you, we are using the
  4920. 3:57:27default master key. That's why it didn't
  4921. 3:57:30work because because we are using a
  4922. 3:57:32strong master key. And here, let's see.
  4923. 3:57:36So, we have an environment variable. We
  4924. 3:57:38have an environment variable that we can
  4925. 3:57:41open. And there we can put the new
  4926. 3:57:44master key. Or if you want, you can do
  4927. 3:57:46it temporarily. You can just change this
  4928. 3:57:49and the script will work. Let me change
  4929. 3:57:51it inside the env file. And the env file
  4930. 3:57:55should be here. Let's go back to back
  4931. 3:57:57end. Let's use ls-l
  4932. 3:58:00and let's see do we have env. Okay. So
  4933. 3:58:03we just have env.example and from that
  4934. 3:58:06we need to create env. Let's use cp
  4935. 3:58:11env.ample and we will create av file.
  4936. 3:58:15Let's open that file. And as you can see
  4937. 3:58:18this is what we have. The environment is
  4938. 3:58:20set to development. We can change that
  4939. 3:58:22to production. Mainly search URL is
  4940. 3:58:25correct. The index is correct. But I'll
  4941. 3:58:28create um uh another one. Let's call it
  4942. 3:58:31articles too because as you saw from the
  4943. 3:58:33logs, we already have articles. And here
  4944. 3:58:36I need to change this. And remember use
  4945. 3:58:38the same key that we have put inside the
  4946. 3:58:43env uh inside the env file. Uh let me
  4947. 3:58:46show you. So we have this file where
  4948. 3:58:50hopefully you have created a strong key
  4949. 3:58:52and you put it here. I'm not going to
  4950. 3:58:54show you my key but I will just open the
  4951. 3:58:56file again. Copy it and paste it inside
  4952. 3:58:59this env file that we created in the
  4953. 3:59:03backend folder. I am back and I have
  4954. 3:59:07changed the master key inside thisv
  4955. 3:59:11file. Now we can try to run the Python
  4956. 3:59:15script again. Let's do it. So, Python
  4957. 3:59:18scripts seed med search. And as you can
  4958. 3:59:21see this time, we didn't get any error.
  4959. 3:59:24It says this is the index that we are
  4960. 3:59:26going to create. It created it. It
  4961. 3:59:29successfully connected to my search. And
  4962. 3:59:31here, as you can see, documents were
  4963. 3:59:33added successfully. Awesome. And I will
  4964. 3:59:36show you later how to verify this with a
  4965. 3:59:39dashboard. We can do it with the with
  4966. 3:59:41the curl commands or the SDKs, but it's
  4967. 3:59:45going to be very easy with a dashboard.
  4968. 3:59:48Now, I want to do something. Uh let's go
  4969. 3:59:51back to the service file here. We have
  4970. 3:59:56we imported the dump successfully. Now,
  4971. 3:59:59we don't need it. We can just get rid of
  4972. 4:00:01these two lines because I as I said, we
  4973. 4:00:03import the dump only once. We don't
  4974. 4:00:05import it every single time. We made we
  4975. 4:00:08made sure that we have the index the
  4976. 4:00:11documents were there and yeah after uh
  4977. 4:00:14verifying that you can safely clean this
  4978. 4:00:16service by removing those two lines. Now
  4979. 4:00:19save the file exit. We need to tell the
  4980. 4:00:23dam that we need to reload the damon
  4981. 4:00:25because we have we changed the service
  4982. 4:00:28configuration and we also we need to
  4983. 4:00:30restart the service itself. Awesome.
  4984. 4:00:33Remember that we can access the web
  4985. 4:00:37application using our IP. If you don't
  4986. 4:00:40remember the IP address, you can always
  4987. 4:00:43come back to Digital Ocean and find it
  4988. 4:00:47here. I'll copy it. I'll paste it here.
  4989. 4:00:50Let's go to the front end. So it's going
  4990. 4:00:53to be
  4991. 4:00:55sorry I'm not sure why I did that but
  4992. 4:00:57let's just put the uh the IP address
  4993. 4:01:00because we are using engineext and
  4994. 4:01:02engineext will take care of uh routing
  4995. 4:01:05the traffic but what why I want you to
  4996. 4:01:08come back here because last time if you
  4997. 4:01:10remember we weren't able to yeah we
  4998. 4:01:14weren't able to talk to the to get
  4999. 4:01:16articles from the back end because me
  5000. 4:01:19search was not set up Now we have M
  5001. 4:01:23search but we need to connect it to the
  5002. 4:01:25back end in order to get articles cuz
  5003. 4:01:28right now as you can see we we don't
  5004. 4:01:30have anything. Now we just need to
  5005. 4:01:32restart supervisor because it doesn't
  5006. 4:01:35have the new environment variable. This
  5007. 4:01:37is why it's not it's not able to connect
  5008. 4:01:39to the me search server. And to do that
  5009. 4:01:43we are going to use supervisor DTL. If
  5010. 4:01:47you don't remember the project name that
  5011. 4:01:49you used, you can always type status and
  5012. 4:01:52that will give you the pro the yeah the
  5013. 4:01:54name of that project and currently it is
  5014. 4:01:57running and it was running for 10 days
  5015. 4:01:59without any problem. Now we need to
  5016. 4:02:02restart that. So let's use restart and
  5017. 4:02:05let's put the name. You can use restart
  5018. 4:02:07all but if you have many websites on the
  5019. 4:02:10same server
  5020. 4:02:11uh it's not a good idea. So it's always
  5021. 4:02:13great to yeah just restart what you
  5022. 4:02:16want. Okay. So it said stopped now it
  5023. 4:02:19says it is saying started. Let's also
  5024. 4:02:22follow the mini search service logs.
  5025. 4:02:25This is what we have. It is saying
  5026. 4:02:27invade the API key because that's when
  5027. 4:02:30we run supervisor we use an old keys in
  5028. 4:02:33the NV file. But hopefully now it should
  5029. 4:02:36it should work. Uh let's verify this. So
  5030. 4:02:39I am here. I'll refresh the page and
  5031. 4:02:42voila, as you can see, I am able to get
  5032. 4:02:44my articles and if we look at the logs,
  5033. 4:02:48yeah, this is the latest request that we
  5034. 4:02:51got. It's a post request. It's coming
  5035. 4:02:54from Python because I am using the
  5036. 4:02:55Python SDK and the status status code is
  5037. 4:02:58200 and as you can see media search is
  5038. 4:03:00fast. Uh so it was able to do this in
  5039. 4:03:04less than 100 milliseconds and also the
  5040. 4:03:07benefits of self-hosting misarch is that
  5041. 4:03:09the communication is local because my
  5042. 4:03:11back end is in local host and misarch is
  5043. 4:03:14also uh in local host. If I hosted
  5044. 4:03:16misarch on another server maybe uh that
  5045. 4:03:19will add some latency but here
  5046. 4:03:21everything is inside one box. Awesome.
  5047. 4:03:24Let's also verify other stuff. Let's go
  5048. 4:03:26to the homepage because we should see
  5049. 4:03:28some blogs here. Yeah, that's correct.
  5050. 4:03:30Let's all let's click on maybe this one.
  5051. 4:03:34Yeah, let's click on this one. We have
  5052. 4:03:36the content. We can also add some claps
  5053. 4:03:41just to verify that it the data is
  5054. 4:03:43saved. We also get recommendations which
  5055. 4:03:46is great to see. The number of claps
  5056. 4:03:48should have changed from 0 to five.
  5057. 4:03:51Awesome. It is working. This is really
  5058. 4:03:53great to see. We also have some filters.
  5059. 4:03:55We can sort by popularity. So this sorts
  5060. 4:03:59by the number of views. We can change
  5061. 4:04:01that to ascending. So we have seven 7 11
  5062. 4:04:0529. Uh we can change that to um number
  5063. 4:04:09of claps. So these ones these these
  5064. 4:04:12articles don't have any claps in them.
  5065. 4:04:15But this one has the most number of
  5066. 4:04:17claps. It has 15. This one has six five
  5067. 4:04:20etc. We also can filter by year. And we
  5068. 4:04:24have yeah we can filter by tags. And
  5069. 4:04:26here we are using faceted distribution.
  5070. 4:04:30Now we can let's go back to the machine
  5071. 4:04:32and let's stop this because we don't
  5072. 4:04:34need it. And as you can see the the
  5073. 4:04:36request that we were performing were all
  5074. 4:04:38successful. They all returned 200.
  5075. 4:04:41That's all I wanted to share with you in
  5076. 4:04:42this first subchapter in module 3. You
  5077. 4:04:47now have a working uh mini search server
  5078. 4:04:51hosted on your virtual machine. We
  5079. 4:04:54connected it to the back end. We created
  5080. 4:04:58a server, a service that will handle
  5081. 4:05:01managing the mele search service for us.
  5082. 4:05:05And we tested it in the front end and it
  5083. 4:05:07worked wonderfully. In the next sub
  5084. 4:05:10chapter, you will learn how to maintain
  5085. 4:05:13this database. I mentioned that we can
  5086. 4:05:16use the Python SDK or just plain curl
  5087. 4:05:20commands, but it's not enjoyable. I'll
  5088. 4:05:23show you a better way to maintain your
  5089. 4:05:26server by uh connecting it to a uh
  5090. 4:05:30goodlooking dashboard. We are also going
  5091. 4:05:34to set we are also going to set up M
  5092. 4:05:37search to automatically create daily
  5093. 4:05:40backups for us in order to protect the
  5094. 4:05:43data and we are going to use SSH
  5095. 4:05:47tunneling again so that we prevent
  5096. 4:05:50opening firewall ports and this is
  5097. 4:05:53important because we want we don't want
  5098. 4:05:55to host the dashboard. You can host the
  5099. 4:05:57dashboard on your virtual machine but we
  5100. 4:06:00in our case we don't want to do that. We
  5101. 4:06:02just want to connect to it. See you in
  5102. 4:06:04the next sub chapter. Welcome back and
  5103. 4:06:08today we are going to manage your med
  5104. 4:06:12search database securely. We are going
  5105. 4:06:15to use this amazing open-source web
  5106. 4:06:18dashboard. You can click on this link.
  5107. 4:06:20It will take you directly to GitHub.
  5108. 4:06:23Here it is. Uh you can give them a star.
  5109. 4:06:26uh clone the code, run it locally if you
  5110. 4:06:29want to, but the project is really
  5111. 4:06:31awesome and I use it to maintain my
  5112. 4:06:35database that I am using on my
  5113. 4:06:36production server. There are other
  5114. 4:06:38dashboards, but for me, this is the one
  5115. 4:06:40that I liked. And this is how it looks.
  5116. 4:06:42In your homepage, you can give your
  5117. 4:06:45instance a name. It shows you the
  5118. 4:06:48database size, status, and the version
  5119. 4:06:51of the mill search binary. You can also
  5120. 4:06:55create a dump, see the tasks, create
  5121. 4:06:58keys and view your indices. It's really
  5122. 4:07:01awesome. These are some some of the
  5123. 4:07:03features that are present there. You can
  5124. 4:07:04search documents, upload ones, edit the
  5125. 4:07:08fields. Uh and all of this is done
  5126. 4:07:11visually. You don't need to run any
  5127. 4:07:12command. And again, in order to connect
  5128. 4:07:15to it, we are going to use the same
  5129. 4:07:17trick. We are going to use this amazing
  5130. 4:07:19SSH channel feature so that we don't
  5131. 4:07:23open open any ports. And this time as
  5132. 4:07:26you can see we will have we have mill
  5133. 4:07:28search running on the server. It runs on
  5134. 4:07:31this port and we want to be able to
  5135. 4:07:33access or to manage this using this
  5136. 4:07:36dashboard. The dashboard is going to be
  5137. 4:07:38running on a browser on our local
  5138. 4:07:41laptop. And with SSH Simon, we will
  5139. 4:07:44connect the ports 7,700 from our machine
  5140. 4:07:48to uh 7,700
  5141. 4:07:50on the server and they can communicate
  5142. 4:07:52freely. But if when we stop the SSH
  5143. 4:07:56connection, not we can't manage the med
  5144. 4:08:00search instance. We already worked with
  5145. 4:08:02SSH tunneling. So it should be uh very
  5146. 4:08:05easy for you to reuse again uh in this
  5147. 4:08:08sub chapter. Okay. Okay, now let's go
  5148. 4:08:10back to the virtual machine. I want to
  5149. 4:08:13start with automatic backups. So, let's
  5150. 4:08:16open the server or the service. I want
  5151. 4:08:20you to add two lines here. SK schedule
  5152. 4:08:24snapshot and snapshot directory. Here
  5153. 4:08:28the value in schedule snapshot is in
  5154. 4:08:30seconds. I set it to 86,400
  5155. 4:08:34and this is exactly 24 hours. uh if you
  5156. 4:08:37want to save every hour or yeah if you
  5157. 4:08:40want to change the duration feel free to
  5158. 4:08:42do that just change this value and we
  5159. 4:08:45want to save data to the snapshots
  5160. 4:08:48directory but currently we don't have it
  5161. 4:08:51so we need to create it and also I
  5162. 4:08:53believe we should also create the dumped
  5163. 4:08:55directory uh if you want for to to
  5164. 4:08:58create some dumps yeah let's do this
  5165. 4:09:00let's save the file we uh we can create
  5166. 4:09:04the snapshots directory like this And
  5167. 4:09:07let's also create dumps if we don't have
  5168. 4:09:10it. Okay, great. And now let's change
  5169. 4:09:12the ownership. I will change everything
  5170. 4:09:16inside my search, not just snapshots
  5171. 4:09:19because I have also created dumps and I
  5172. 4:09:21made a typos. Uh let me show you how we
  5173. 4:09:23can do this. We can use move. Let's use
  5174. 4:09:26sudo move. Let's take this path and
  5175. 4:09:30let's rename it. Instead of dumps, it's
  5176. 4:09:32going to be dumps. Uh let's just verify
  5177. 4:09:34that it it's worked and let's look at me
  5178. 4:09:38search and yes we have dumps we have
  5179. 4:09:41snapshots and data and we can delete
  5180. 4:09:44this dumps file because we no longer
  5181. 4:09:46need it. We used this we imported the
  5182. 4:09:49data now it's it's not useful anymore.
  5183. 4:09:52So let's use sudo remove and let's put
  5184. 4:09:55the file there. Sorry. Okay. So let's go
  5185. 4:09:59back. Ah I wasn't able to delete it.
  5186. 4:10:01Why? Ah, I did sudo ls. I need to do
  5187. 4:10:05sudo remove. Now let's go back. Awesome.
  5188. 4:10:08So everything is there. Let's just
  5189. 4:10:10verify the ownership. Who owns those
  5190. 4:10:14folders? M search. Awesome. Now we can
  5191. 4:10:17continue. Whenever you update the
  5192. 4:10:20service file, make sure to run damon
  5193. 4:10:23reload and reload the service itself.
  5194. 4:10:27Now, Med Search will quietly save a safe
  5195. 4:10:31copy of your database every single day.
  5196. 4:10:35And I want to mention that we will keep
  5197. 4:10:37just the most recent snapshots. We won't
  5198. 4:10:40have a lot of snapshots because that
  5199. 4:10:43will uh fill up your hard drive over
  5200. 4:10:46time. You we just need one and that's uh
  5201. 4:10:48that's sufficient.
  5202. 4:10:50Let me exit and let's use this command.
  5203. 4:10:53SSH-L7,700
  5204. 4:10:58to 7,700. This will will create a
  5205. 4:11:01tunnel.
  5206. 4:11:02Ah, so it says address already in use
  5207. 4:11:04because I am running Milly Search
  5208. 4:11:06locally. So I need to stop that server
  5209. 4:11:09and re retry again. So let's retry.
  5210. 4:11:13Okay, now it worked. It didn't uh it
  5211. 4:11:16didn't tell me that the port is
  5212. 4:11:17occupied. Now let's go back to GitHub
  5213. 4:11:20because as I mentioned you don't need to
  5214. 4:11:23host the dashboard locally because this
  5215. 4:11:27the creators of this project are already
  5216. 4:11:30hosting it uh on Versel for free and as
  5217. 4:11:33I said I am using it uh both locally and
  5218. 4:11:36on my production server and in order to
  5219. 4:11:40add your own instance you can just click
  5220. 4:11:43on the plus button give it a name I will
  5221. 4:11:47call
  5222. 4:11:48test instance. The host is correct. It
  5223. 4:11:52should be 7,700.
  5224. 4:11:54This one is pointing at your local port.
  5225. 4:11:56And here I need to provide the API key.
  5226. 4:11:59For that I need to go back here and um
  5227. 4:12:03copy the code the API key. Again I have
  5228. 4:12:06copied the key. I have pasted it. Now I
  5229. 4:12:09click on confirm. Okay. I can save that
  5230. 4:12:12but doesn't it's not needed. Now just
  5231. 4:12:15click on your instance. One thing the me
  5232. 4:12:18search server should be running. So you
  5233. 4:12:20can always run status if it is if it
  5234. 4:12:24says running you are good to go. And as
  5235. 4:12:27you can see I uh here are my indices. So
  5236. 4:12:29I have articles articles number two and
  5237. 4:12:33articles test. This was also on my dump.
  5238. 4:12:36And I have everything. Now I can click
  5239. 4:12:38on let's say articles. It shows me the
  5240. 4:12:41distribution. Uh we can click on
  5241. 4:12:43documents. And here it shows you the
  5242. 4:12:45fields. You can click on updates. Let's
  5243. 4:12:48say that I want to update the view count
  5244. 4:12:50from 14 to something else. I can do it
  5245. 4:12:53without any problem. So maybe let's just
  5246. 4:12:56do 999 or something. Submit. It's going
  5247. 4:12:59to create a task. We can look at that
  5248. 4:13:02here. So it's it says a few seconds ago
  5249. 4:13:05and it succeeded. Uh let's go back to
  5250. 4:13:08here. Let's go up. Let's go to blogs.
  5251. 4:13:12Let me see. Do we have what was that
  5252. 4:13:14blog? Let's go back. So, it says elastic
  5253. 4:13:17search change heap size. Elastic search
  5254. 4:13:21change heap size. Do I need to refresh?
  5255. 4:13:24Oh, no. Maybe I used the wrong index.
  5256. 4:13:27So, let's go back. Okay. Let's click on
  5257. 4:13:29articles. Yeah, I think I am using
  5258. 4:13:31articles too instead. Uh, let's look at
  5259. 4:13:34documents. Okay. Yeah, let's change this
  5260. 4:13:37one. So, update from 7 to 999.
  5261. 4:13:41submit. Go back to the website. Refresh.
  5262. 4:13:45And as you can see, we have 9999. With
  5263. 4:13:47this dashboard, you can easily manage uh
  5264. 4:13:50your documents. And here, if you want,
  5265. 4:13:52you can upload once. You can upload your
  5266. 4:13:54documents here. Just paste the JSON and
  5267. 4:13:57hit submit. And that will uh add a new
  5268. 4:14:01article or product, whatever. Uh for in
  5269. 4:14:04my case, I am using it to add articles.
  5270. 4:14:07Uh so that's my content. But if you use
  5271. 4:14:10it for other purposes, it doesn't
  5272. 4:14:13matter. You can just just put your JSON
  5273. 4:14:14here and hit submit or you can drag and
  5274. 4:14:17drop the file directly. Uh let's let's
  5275. 4:14:19look at settings here. Uh these are
  5276. 4:14:21these are the the settings. And this is
  5277. 4:14:24very important. When you create a dump,
  5278. 4:14:26the settings needs to be the same. And
  5279. 4:14:29just like that, we finished module
  5280. 4:14:31number three. As you can see, using me
  5281. 4:14:34search is very easy. It's just one
  5282. 4:14:36binary. It is really fast.
  5283. 4:14:39uh it's uh we have really awesome
  5284. 4:14:42dashboards that we can use to maintain
  5285. 4:14:45this database. We tried to create a
  5286. 4:14:49system user to isolate the database as
  5287. 4:14:52much as possible so that we don't leak
  5288. 4:14:54data, we don't leak keys, stuff like
  5289. 4:14:57that. And even if someone hacks to your
  5290. 4:15:00server, they won't be able to extract
  5291. 4:15:04anything from it. And we used SSH
  5292. 4:15:06tunneling to access this dashboard.
  5293. 4:15:09Which means that if I stop the server as
  5294. 4:15:13you can see I stopped it which means
  5295. 4:15:15that yeah port forwarding is no uh sorry
  5296. 4:15:19SSH tunneling is no longer a thing. That
  5297. 4:15:22means that yes I won't be able to
  5298. 4:15:24connect to this instance. So if I click
  5299. 4:15:26on it it says connection failed because
  5300. 4:15:29we don't we create a temporary tunnel
  5301. 4:15:32that allows us to manage this. Once we
  5302. 4:15:34are done, we close it and no one will be
  5303. 4:15:36able to talk to me research. So even
  5304. 4:15:39though it is inside the machine, it is
  5305. 4:15:41isolated. It cannot talk to the outer
  5306. 4:15:45world. It just talks to the back end
  5307. 4:15:47locally. In the next module, module
  5308. 4:15:50number four, we are going to talk about
  5309. 4:15:53global delivery and app security. This
  5310. 4:15:57is important because as you can see
  5311. 4:15:59right now if uh let's say that you
  5312. 4:16:01deployed this to production your users
  5313. 4:16:04will have to type your IP address to
  5314. 4:16:08access your website. This is not good.
  5315. 4:16:10We need to change this to be something
  5316. 4:16:13like this. So so that they can just type
  5317. 4:16:16a name and
  5318. 4:16:18in behind the scenes this name will be
  5319. 4:16:20converted to the uh to your IP address.
  5320. 4:16:24So this is what we are going to fix in
  5321. 4:16:26the next sub chapter and we are going to
  5322. 4:16:28talk about DNS records creating custom
  5323. 4:16:31domains uh adding certificates to uh
  5324. 4:16:35finally uh have a secure connection
  5325. 4:16:37because right now it is not secure it is
  5326. 4:16:40we are just working with HTTP uh in the
  5327. 4:16:43next module we will finally upgrade to
  5328. 4:16:46HTTPS and that will add another layer of
  5329. 4:16:48security to your website.
  5330. 4:16:52Welcome to module four.
  5331. 4:16:54Up until now, our application has been
  5332. 4:16:58running perfectly. But to access it, we
  5333. 4:17:02need to type the IP address in the
  5334. 4:17:05browser. This is not user friendly. In
  5335. 4:17:08this video, we are going to buy our own
  5336. 4:17:13domain name. I'm going to show you how
  5337. 4:17:16to transition from HTTP to HTTPS. We are
  5338. 4:17:20going to use Let's Encrypt for that. We
  5339. 4:17:24are going to modify the engineext
  5340. 4:17:26configuration and at the end I'm going
  5341. 4:17:29to show you how to autorenew your SSL
  5342. 4:17:32certificate.
  5343. 4:17:34This is the agenda that we are going to
  5344. 4:17:36follow. As you can see, we are going to
  5345. 4:17:38start with purchasing a custom domain.
  5346. 4:17:42We are going to configure DNS records.
  5347. 4:17:44We are going to add an A address and a
  5348. 4:17:47CNAME record. I'm going to explain
  5349. 4:17:49these. We are going to install three SSL
  5350. 4:17:52certificates via list encrypt. And
  5351. 4:17:56finally, we are going to automate the
  5352. 4:17:58renewal process because by default, the
  5353. 4:18:03certificates are going to expire after
  5354. 4:18:0590 days and we don't want to do the
  5355. 4:18:08renewing manually. We want the machine
  5356. 4:18:11to do it for us. We are going to use a
  5357. 4:18:14chrome job for that. Before we start
  5358. 4:18:17practicing, I would like you to go to
  5359. 4:18:19GitHub. You'll find the links for this
  5360. 4:18:22repository in the video description.
  5361. 4:18:25Click on the book folder and come here
  5362. 4:18:27to the fourth file. As you can see, I
  5363. 4:18:30have committed the changes. Everything
  5364. 4:18:33is here. You will find the steps and the
  5365. 4:18:36commands that you need to run.
  5366. 4:18:38Everything is described in this
  5367. 4:18:40document. So, don't worry. Just follow
  5368. 4:18:43with me and uh the resources are on this
  5369. 4:18:46repository. Let's register a domain. In
  5370. 4:18:50my case, I'm going to use pork bun but
  5371. 4:18:53if you want you can use namecheep or god
  5372. 4:18:56daddy or other registars. There are many
  5373. 4:19:00but in my case I will use pork bun
  5374. 4:19:03because this is the one I use and their
  5375. 4:19:06pricing is transparent. They they show
  5376. 4:19:10you the real price. Sometimes the other
  5377. 4:19:12ones they show you a very low price but
  5378. 4:19:15the problem is that when you try to
  5379. 4:19:18renew in the next upcoming years they
  5380. 4:19:22the price becomes higher. So that's not
  5381. 4:19:24good. And here in pork bun as you can
  5382. 4:19:27see you can type the domain that the
  5383. 4:19:29name that you want to register and if it
  5384. 4:19:31is available you can uh you can take it.
  5385. 4:19:35I will I will sign in because I already
  5386. 4:19:37have an account and I will create a I
  5387. 4:19:39will try to register a new domain name.
  5388. 4:19:42I am back. As you can see, I have logged
  5389. 4:19:45in with my account. I already have two
  5390. 4:19:48domain names. This is the one that I
  5391. 4:19:51showed you in the beginning of this
  5392. 4:19:53course. If I go there, it takes me to my
  5393. 4:19:57personal website. And as you can see
  5394. 4:20:00here, uh, if you look at at the bottom
  5395. 4:20:03left corner, the link is HTTP. It's
  5396. 4:20:07insecure. But when I click on it, it's
  5397. 4:20:10going to use HTTPS because we
  5398. 4:20:13reconfigured EngineX so that it takes
  5399. 4:20:17HTTP requests and redirects them to
  5400. 4:20:19HTTPS. And as you can see, if you click
  5401. 4:20:22here, it shows you that the connection
  5402. 4:20:24is secure. And this is what we are going
  5403. 4:20:26to do with the new domains that I will
  5404. 4:20:29create now. Okay, I will close this.
  5405. 4:20:32This is the domain name that I would
  5406. 4:20:35like to register and I want a com one.
  5407. 4:20:41Let's search and let's see if it is
  5408. 4:20:42available. Okay, let me zoom in so that
  5409. 4:20:46we can see clearly. As you can see, I
  5410. 4:20:48have typed the name here and look what
  5411. 4:20:51we found. As you can see, I can I can
  5412. 4:20:54get the domain for $11 per year. And
  5413. 4:20:59this is what I was talking about the
  5414. 4:21:01renew process. As you can see, the renew
  5415. 4:21:03is the same as the price that I will pay
  5416. 4:21:06in the first year. But if you if you
  5417. 4:21:08look at this one, I am going to pay just
  5418. 4:21:11under $2. But after this year, I will be
  5419. 4:21:15paying almost $30. And this is why I
  5420. 4:21:19mentioned in the beginning that the
  5421. 4:21:20pricing here in pork one is transparent.
  5422. 4:21:23You can see everything. In my case, I
  5423. 4:21:25will take the com one because yeah, this
  5424. 4:21:28is what I want. And I want to also get
  5425. 4:21:32ma but sadly yeah this one is uh country
  5426. 4:21:36specific because I live in Morocco. I
  5427. 4:21:37would like to also take that one. But
  5428. 4:21:40yeah, you can try your luck. Uh maybe if
  5429. 4:21:43you live in another country, you can try
  5430. 4:21:45it. Maybe you will find uh yours here or
  5431. 4:21:47maybe use a different uh register. Uh I
  5432. 4:21:51know that I will not find that one. So
  5433. 4:21:53I'll just skip
  5434. 4:21:55and in my case yeah I think this one is
  5435. 4:21:58is fine. So now what we will do we will
  5436. 4:22:01click on the plus button that will add
  5437. 4:22:03it to the cart. Now click there and here
  5438. 4:22:08again pay attention to what they are
  5439. 4:22:09showing you here. So the registration
  5440. 4:22:12here is for one year. I want to pay just
  5441. 4:22:14one year. Uh after that they will notify
  5442. 4:22:17me to pay for the the second and the
  5443. 4:22:20upcoming years if I want to stick with
  5444. 4:22:22them. So the renewal is the same price.
  5445. 4:22:25That's correct. And here they are giving
  5446. 4:22:28you other things. They always do this so
  5447. 4:22:30that you that you pay more. But don't
  5448. 4:22:33don't add anything. These are the things
  5449. 4:22:36that they show you here are not are not
  5450. 4:22:37important. Okay. So this is uh this
  5451. 4:22:41looks good. Now all we need to do is to
  5452. 4:22:44scroll a little bit and here click on
  5453. 4:22:47continue to billing and finish the
  5454. 4:22:49payment and you can also ver verify the
  5455. 4:22:52price before doing this. I will click on
  5456. 4:22:56continue to billing. Here you have many
  5457. 4:22:58options. You can use PayPal if you have
  5458. 4:23:00it, crypto or your Visa card. I will
  5459. 4:23:04select PayPal and I'll I'll finish the
  5460. 4:23:06process and I'll come back. I am back.
  5461. 4:23:09As you can see, this is the message that
  5462. 4:23:11you should see after completing the
  5463. 4:23:13purchase. They will tell you great
  5464. 4:23:15success. Congratulations on your brand
  5465. 4:23:17new domain. That's uh that's good. Now,
  5466. 4:23:20we can go back. We can click on account
  5467. 4:23:22domain management. And as you can see, I
  5468. 4:23:26got my new domain. Uh they say that it
  5469. 4:23:29will take some time. That's fine. We'll
  5470. 4:23:30come back to it. Now, we need to
  5471. 4:23:32configure DNS domain name system. But
  5472. 4:23:37before I do that, let's go back to the
  5473. 4:23:39slides because I want to explain DNS how
  5474. 4:23:42DNS works. I created this diagram to
  5475. 4:23:45explain this. Let's say that I am this
  5476. 4:23:48user. I want to check this website. I
  5477. 4:23:53will type it on this browser that I have
  5478. 4:23:56here. I will hit enter. What happens
  5479. 4:23:59after I do that? The browser will talk
  5480. 4:24:02to the DNS server. In our case, it might
  5481. 4:24:06be pork bun. It might be cloud player.
  5482. 4:24:09It depends on what you want to do. For
  5483. 4:24:12right now, we have created we have just
  5484. 4:24:15bought a domain and pork bun. They have
  5485. 4:24:18their own DNS server. Behind the scenes,
  5486. 4:24:21what will happen is that we need to to
  5487. 4:24:23give Porkbun a an IP address. And this
  5488. 4:24:27IP address is the one that we that we
  5489. 4:24:31can take from Digital Ocean. It's the
  5490. 4:24:33machine that we created in the first
  5491. 4:24:35module in this course. And this will
  5492. 4:24:39will allow pork bun or other DNS servers
  5493. 4:24:43to create this mapping. They will map
  5494. 4:24:46the name the domain that you have
  5495. 4:24:49purchased to that IP address. After
  5496. 4:24:52typing this domain name, the browser
  5497. 4:24:56will tell the DNS server where is this
  5498. 4:25:00address. The DNS server will look in in
  5499. 4:25:03its databases. It will if it finds it,
  5500. 4:25:06if it finds that address, it will reply
  5501. 4:25:09with the IP address and the browser will
  5502. 4:25:12type that IP address automatically. It's
  5503. 4:25:15the same. Before we were typing the IP
  5504. 4:25:18address directly, but now the DNS server
  5505. 4:25:21will give that information to the
  5506. 4:25:22browser. Now the browser has the IP
  5507. 4:25:25address. It will communicate with your
  5508. 4:25:28Linux server. So it's going to tell it
  5509. 4:25:30please give me the content and the the
  5510. 4:25:33server will reply with the content and
  5511. 4:25:36you will be able to see the the front
  5512. 4:25:38end that you built. This is how DNS
  5513. 4:25:41works and this is what we are going to
  5514. 4:25:43do to create this mapping. We need to
  5515. 4:25:46configure the domain that we bought in
  5516. 4:25:48porkbun. We call this mapping the a
  5517. 4:25:51record. Let's go back to porkbun and
  5518. 4:25:55let's see if we can change this. I'll
  5519. 4:25:57refresh the page. Okay, everything is is
  5520. 4:26:01all right. As you can see, we have DNS
  5521. 4:26:03here. If you click on it, it allows you
  5522. 4:26:07to modify it. As you can see, we have uh
  5523. 4:26:11a few default ones. Yeah, and I think
  5524. 4:26:14this is a newer one. I will I'll go back
  5525. 4:26:16to the classic view because this is
  5526. 4:26:18Yeah, this is the view that I used here
  5527. 4:26:21uh on GitHub. Let's uh let's see. Yeah,
  5528. 4:26:24as you can see, before it was like this.
  5529. 4:26:26And yeah, we get a model. So I I'll
  5530. 4:26:29stick to the old one. You can see that
  5531. 4:26:32we have a few records. These are default
  5532. 4:26:34records that Porkman created for us. We
  5533. 4:26:37need to remove some of them. I will
  5534. 4:26:39start by removing the alias and CNAME by
  5535. 4:26:43clicking on this trash icon. We will
  5536. 4:26:46also remove the last two, these text
  5537. 4:26:48ones. That's what we want to do. Now
  5538. 4:26:51scroll up and here let's add the first
  5539. 4:26:54one is the address record. Here host
  5540. 4:26:57leave it blank but here in the answer
  5541. 4:27:01value we need to put the IP address.
  5542. 4:27:04Let's go to digital ocean because I
  5543. 4:27:06forgot the IP address. Okay, here is the
  5544. 4:27:09the droplet. Here is the IP address. I
  5545. 4:27:12copied it. I will paste it here. Here we
  5546. 4:27:15have time to live. Leave it at 600
  5547. 4:27:18seconds. Um, you can add notes if you
  5548. 4:27:21want. And now click on add. Okay, let's
  5549. 4:27:25scroll down. As you can see, we have the
  5550. 4:27:27new record here. That's great. Now,
  5551. 4:27:29let's add another one, which is going to
  5552. 4:27:32be CNAME. This record maps one domain
  5553. 4:27:35name to another domain name. You use
  5554. 4:27:38this one to ensure that if someone types
  5555. 4:27:42www
  5556. 4:27:44in front of your domain, they can still
  5557. 4:27:46reach your website. So this is going to
  5558. 4:27:48map www to uh your domain name. I can
  5559. 4:27:52show you this with my own website. If I
  5560. 4:27:54type my domain name, I can go there.
  5561. 4:27:57That's fine. But I can also do let's
  5562. 4:28:00remove this part and type ww dot.
  5563. 4:28:05And as you can see that redirects me to
  5564. 4:28:08my yeah to my website. And it's it's
  5565. 4:28:10working. To accomplish that we add we
  5566. 4:28:13add the CNAME record. Here in host we
  5567. 4:28:16add www.
  5568. 4:28:19And here in answer you need to type the
  5569. 4:28:21domain name and we can just copy it from
  5570. 4:28:23here and paste it and hit time to live.
  5571. 4:28:27We shouldn't change that. Now just add
  5572. 4:28:31this record. Let's scroll down. As you
  5573. 4:28:34can see we have it here. This is the
  5574. 4:28:36mapping that I was talking about. If I
  5575. 4:28:38type this domain name porkbang will
  5576. 4:28:41return this IP address to the browser.
  5577. 4:28:44So that so that it can communicate with
  5578. 4:28:46my droplets and that's it. We configured
  5579. 4:28:49DNS as I said I used pork bun but what
  5580. 4:28:52we have learned here applies to the
  5581. 4:28:55other domain registars the only thing
  5582. 4:28:57that will change is their user interface
  5583. 4:28:59but other than that everything I think
  5584. 4:29:02should be should be the same. We need to
  5585. 4:29:06SSH into the server. Let's do this. I
  5586. 4:29:10will use this command to SSH directly.
  5587. 4:29:14Great. I am now inside the machine. We
  5588. 4:29:16need to configure SSL certificates. How
  5589. 4:29:20do we do that? First, we need to install
  5590. 4:29:22the searchbot client. To do that, we can
  5591. 4:29:26type this command. As you can see, it
  5592. 4:29:28installs searchbot and this Python 3
  5593. 4:29:32searchb engineext. Uh this is a plug-in
  5594. 4:29:36that allows searchbots to modify the
  5595. 4:29:39enginex configuration for us. We will
  5596. 4:29:41see that in action but for now let's
  5597. 4:29:43just install this. Provide the password
  5598. 4:29:46and let's wait for a few seconds. Okay.
  5599. 4:29:49Now let's request certificates for this
  5600. 4:29:53domain and subdomain. As you can see I
  5601. 4:29:55have placeholders. I need to replace
  5602. 4:29:58them with this domain name. I will take
  5603. 4:30:01it and paste it here. And uh here I will
  5604. 4:30:04keep the www do and I'll paste the
  5605. 4:30:08domain name. Here I made a mistake. I
  5606. 4:30:10need to remove the.com from here and
  5607. 4:30:13from here. Let's hit enter. The first
  5608. 4:30:16thing they are asking for your email
  5609. 4:30:19address. This information is used
  5610. 4:30:22strictly for urgent security notices and
  5611. 4:30:26renewal warnings if uh maybe the
  5612. 4:30:29automation fails. After that, they will
  5613. 4:30:31ask you if you agree with their terms of
  5614. 4:30:34service. Type yes. And for this
  5615. 4:30:37question, they are telling you, do you
  5616. 4:30:39want to share your email address? Just
  5617. 4:30:41type no. The account is registered. And
  5618. 4:30:44now they are requesting a certificate
  5619. 4:30:46for my domain name. Let's wait for a few
  5620. 4:30:49seconds. And okay, this is the message
  5621. 4:30:52that we want to see. Successfully
  5622. 4:30:54received certificate. And as I mentioned
  5623. 4:30:58the certificate will expire after 90
  5624. 4:31:00days. Today is April 4th and 90 days
  5625. 4:31:05will be yeah it's 3 months. So yeah 4 +
  5626. 4:31:093 is 7. That's correct. But don't worry
  5627. 4:31:12we are going to automate the process of
  5628. 4:31:14renewing the certificates. Let's open
  5629. 4:31:17the engineext configuration and let's
  5630. 4:31:20see if searchbot changed the changed it
  5631. 4:31:24or not. Hit enter and let's scroll down.
  5632. 4:31:28It seems to me that it's it's the same.
  5633. 4:31:32Source B did not change it. That's not a
  5634. 4:31:35problem. I wanted to show this issue
  5635. 4:31:38because as you can see in the previous
  5636. 4:31:41chapters, we didn't have a domain.
  5637. 4:31:43That's why we created just a dummy name
  5638. 4:31:47here. But the new domain that we created
  5639. 4:31:50is called this. and searchbot didn't
  5640. 4:31:54find something uh there. That's why it's
  5641. 4:31:57it uh yeah it couldn't change it. We can
  5642. 4:32:00see that search bot because it couldn't
  5643. 4:32:03find the domain name inside the the
  5644. 4:32:07configuration. It created the default
  5645. 4:32:10configuration. Let's remove that because
  5646. 4:32:12we don't need it. Now open the
  5647. 4:32:15configuration that we created before.
  5648. 4:32:17And here we need to update server name.
  5649. 4:32:20As you can see before because before we
  5650. 4:32:22didn't have a domain name, we used the
  5651. 4:32:24IP address. But now we need to change
  5652. 4:32:27that. Let me show you how we do it. I
  5653. 4:32:30will come here. Let's hit Ctrl K to
  5654. 4:32:33remove that line. I will replace it with
  5655. 4:32:35this one. Server name stays the same,
  5656. 4:32:38but here we replaced the IP address with
  5657. 4:32:42the domain name and the subdomain name.
  5658. 4:32:45Save the file. Exit. Let's ver let's
  5659. 4:32:49verify that the syntax is correct.
  5660. 4:32:51Always do that before reloading engine
  5661. 4:32:53X. And now I will search for reload
  5662. 4:32:57engine X. And to search you just type
  5663. 4:33:00something, hit CtrlR and that will show
  5664. 4:33:03you the previous commands in the
  5665. 4:33:05history. Hit enter. This is going to
  5666. 4:33:07reload EngineX because whenever you
  5667. 4:33:10change the configuration, always check
  5668. 4:33:12the syntax and after that reload. Now
  5669. 4:33:14let's run searchbot again with the same
  5670. 4:33:17command and this time it will find the
  5671. 4:33:19configuration because we ran this
  5672. 4:33:22before. Searchbot is asking us if we
  5673. 4:33:25want to reinstall. If we want if we
  5674. 4:33:27choose one that will attempt to
  5675. 4:33:29reinstall and two will just renew. We
  5676. 4:33:32want to reinstall. So let's type one and
  5677. 4:33:34hit enter. As you can see this message
  5678. 4:33:37shows us that third boss was able to
  5679. 4:33:39find to find the our custom
  5680. 4:33:42configuration. And now if we open that
  5681. 4:33:44file, we should be able to see the new
  5682. 4:33:49stuff that SB added. Let's scroll down.
  5683. 4:33:52Great. As you can see, it worked. We
  5684. 4:33:54have some new lines. Let's remove them.
  5685. 4:33:57Let's go up. Yeah, everything here
  5686. 4:33:59stayed the same. We have the server
  5687. 4:34:01name. We We have log files. These are
  5688. 4:34:04the HTTP headers that we added before.
  5689. 4:34:08Here we are serving the front end. We
  5690. 4:34:10serve the API. That stuff didn't change.
  5691. 4:34:13But here, here is the new stuff that
  5692. 4:34:16search bots added. And as you can see,
  5693. 4:34:18this comment proves that we have listen
  5694. 4:34:21443 SSL. We have some SSL certificate
  5695. 4:34:25stuff. Let me explain what we have here.
  5696. 4:34:28Before in the server block, we were
  5697. 4:34:30listening for port 80. Searchbot
  5698. 4:34:33migrated that to port 443.
  5699. 4:34:36And for this port is the standard port
  5700. 4:34:40for HTTPS. You can search that on the
  5701. 4:34:42web to verify that information. But port
  5702. 4:34:4580 is for regular HTTP and it is
  5703. 4:34:49unencrypted. That's why it is it is not
  5704. 4:34:52secure. Great. So that's nice. And here
  5705. 4:34:56um these these new lines just point to
  5706. 4:34:58the to the keys that search B created
  5707. 4:35:02for us. We are including this
  5708. 4:35:05configuration. Yeah, this stuff it's not
  5709. 4:35:07that important because it is managed by
  5710. 4:35:09search. The most important thing here is
  5711. 4:35:12443. It will make our website secure.
  5712. 4:35:15Now if we scroll down, we have another
  5713. 4:35:16server block and this one is used for
  5714. 4:35:19redirecting. Here we have two if blocks.
  5715. 4:35:22If the host is this subdomain, we are
  5716. 4:35:25going to redirect to HTTPS
  5717. 4:35:28and 30. Let's search for it. 301 means
  5718. 4:35:33moved permanently and it is used for
  5719. 4:35:36redirection. And this is what we want to
  5720. 4:35:38do here. If someone visits www do we
  5721. 4:35:42want to redirect them to https and here
  5722. 4:35:45we put the domain name and again this is
  5723. 4:35:48managed by searchbot and here if we type
  5724. 4:35:51just the domain name we will catch that
  5725. 4:35:54and we will redirect to this link and as
  5726. 4:35:57you can see here for this server block
  5727. 4:35:59we are listening on port uh port 80
  5728. 4:36:02which is the regular HTTP which is not
  5729. 4:36:05secure. Yeah, when we catch that
  5730. 4:36:07traffic, we will redirect it to HTTPS.
  5731. 4:36:10Awesome. Now save the file and exit. Now
  5732. 4:36:14let's automate the certificate renewal.
  5733. 4:36:17Let me clear the screen. We have this
  5734. 4:36:19command that we can run to test the
  5735. 4:36:23renewal system. We want to do this to
  5736. 4:36:25ensure that it works. And we are adding
  5737. 4:36:28dry run because this is just a test.
  5738. 4:36:30It's not going to change anything. Let's
  5739. 4:36:32verify that this is going to work. They
  5740. 4:36:34found that the account is registered.
  5741. 4:36:37That's good. And as you can see here,
  5742. 4:36:39they are saying simulating renewal. So
  5743. 4:36:41this is just a simulation. And they are
  5744. 4:36:43saying congratulations all simulation.
  5745. 4:36:46All simulated renewals succeeded. This
  5746. 4:36:48is what we want to see before
  5747. 4:36:50proceeding. Now let's create a new
  5748. 4:36:53chrome job. We are going to type sudo
  5749. 4:36:56chrome tab-e.
  5750. 4:36:58We want to do this in for the root user.
  5751. 4:37:02This is the first time we are doing
  5752. 4:37:03this. So the this command is showing us
  5753. 4:37:06what text editor to use. I like to use
  5754. 4:37:09nano. I will type one and hit enter. Now
  5755. 4:37:12let's go down and let's add this line.
  5756. 4:37:15If you don't understand the chrome tab
  5757. 4:37:18syntax, you can use this website called
  5758. 4:37:22chronab.guru.
  5759. 4:37:24And here you can paste the chrome tab
  5760. 4:37:27notation. And this is the one that I
  5761. 4:37:30added in the chrome tab. Why I like this
  5762. 4:37:33website is because they show you they
  5763. 4:37:35try to convert this into a sentence that
  5764. 4:37:37you can understand. And this expression
  5765. 4:37:41means at exactly midnight every Sunday.
  5766. 4:37:46And this is the command that we want to
  5767. 4:37:48run every sun. Every Sunday we want to
  5768. 4:37:52run the renew command. And we are adding
  5769. 4:37:55quiet because we don't want to generate
  5770. 4:37:58a lot of system logs. We want to do this
  5771. 4:38:00quietly. Now save the file. Exit. Good.
  5772. 4:38:04Now Linux will run this job every
  5773. 4:38:08Sunday. And again, as I said, you don't
  5774. 4:38:10need to do this manually. The system
  5775. 4:38:12will take care of the renew process. But
  5776. 4:38:16we have a small problem. Let's say that
  5777. 4:38:19before the expiration of the
  5778. 4:38:22certificates, we were able to
  5779. 4:38:24automatically renew it. Engine X will
  5780. 4:38:26not be able to see it because we need to
  5781. 4:38:29reload it in order to load the new
  5782. 4:38:32certificates. In order to solve this, we
  5783. 4:38:34will create a post renewal hook. I will
  5784. 4:38:38explain what that means. Let's create
  5785. 4:38:40this file. Look where we are creating
  5786. 4:38:43it. We have etc. Let's encrypt. This is
  5787. 4:38:46what we are using for the certificates.
  5788. 4:38:49And here they have a renewal hooks
  5789. 4:38:51folder. And we want to do this in the
  5790. 4:38:54post. So after renewing this is what
  5791. 4:38:56post means after an operation. After
  5792. 4:38:59that we are going to reload engineext.
  5793. 4:39:01This is a simple script that will run
  5794. 4:39:04this command for us whenever the
  5795. 4:39:06certificates are updated. Save the file
  5796. 4:39:09and exit. But don't forget to make it
  5797. 4:39:12executable so that searchbot can execute
  5798. 4:39:15this. And you can always verify if that
  5799. 4:39:18works by using ls-la.
  5800. 4:39:23And what you want to see is X in yeah
  5801. 4:39:26three positions and okay you are now set
  5802. 4:39:29up. You can just kick back and enjoy
  5803. 4:39:31your sleep. I think we have finished the
  5804. 4:39:35full setup. Now we can test if this
  5805. 4:39:38works or not. Let's go back. You
  5806. 4:39:40remember that before we used to go to
  5807. 4:39:43Digital Ocean, copy the IP address,
  5808. 4:39:46paste it here in order to uh see the the
  5809. 4:39:50website. Now this does not work because
  5810. 4:39:53we have uh updated the engineext
  5811. 4:39:56configuration to look for the domain
  5812. 4:39:59name. Let's do that. I will or I can do
  5813. 4:40:02it from here. I can click on this and
  5814. 4:40:04let's hope that it works. Yes, it did.
  5815. 4:40:06As you can see, I have typed the domain
  5816. 4:40:09name. This is my website. Uh as you can
  5817. 4:40:13see, it is working. Uh the front end and
  5818. 4:40:15back end are both connected. Let's load
  5819. 4:40:18an article. Let's scroll down a little
  5820. 4:40:21bit. This is a long article here. I can
  5821. 4:40:24add some claps. Let's go up. Let's
  5822. 4:40:27ensure that this works. Yes, it says 11.
  5823. 4:40:29That's the new claps. Yeah, everything
  5824. 4:40:32is working. And we can also try to force
  5825. 4:40:36this to go to HTTP. Uh let's use that.
  5826. 4:40:41And here I will type the domain name.
  5827. 4:40:43What will happen? This will go this will
  5828. 4:40:46redirect to HTTPS automatically. Boom.
  5829. 4:40:48That worked. As you can see, the
  5830. 4:40:50connection is secure. Awesome. This is
  5831. 4:40:53great. Uh, that works. And we can also
  5832. 4:40:56verify www do. Let me remove this part.
  5833. 4:41:01And let's hit enter. And that also
  5834. 4:41:04redirects without any problem. Amazing.
  5835. 4:41:08Now we have uh successfully created
  5836. 4:41:12purchased a domain. We changed the DNS
  5837. 4:41:17configuration. We added the A and C name
  5838. 4:41:20records. We used let's encrypt to make
  5839. 4:41:24the connection encrypted. But we are not
  5840. 4:41:28done yet. In the next subchapter, we are
  5841. 4:41:31going to talk about CDN layer. Why do we
  5842. 4:41:35need to talk about that? Because the
  5843. 4:41:37problem is that for me, this droplet
  5844. 4:41:41that I created is hosted in Germany. I
  5845. 4:41:44live in Morocco. So if I want to access
  5846. 4:41:47this website, it's going to load fast.
  5847. 4:41:49But if let's say that someone is from
  5848. 4:41:52China or Australia, if they want to to
  5849. 4:41:55go to my website, the load time is going
  5850. 4:41:57to be very slow. They need to wait for
  5851. 4:42:00seconds instead of milliseconds to yeah
  5852. 4:42:03to load the the content of the website.
  5853. 4:42:06That's a problem. We are going to fix it
  5854. 4:42:08in the next sub chapter with the help of
  5855. 4:42:11Cloudflare. We are going to use it to
  5856. 4:42:14cache the static files on their servers
  5857. 4:42:17because they have servers all over the
  5858. 4:42:20world and that will mitigate this
  5859. 4:42:22problem. So that person in Australia
  5860. 4:42:24that before was used to wait in seven or
  5861. 4:42:288 seconds for the website to load, we
  5862. 4:42:30now only wait for maybe a second or
  5863. 4:42:33less. And that's what we are going to
  5864. 4:42:35focus on in the next uh video. Welcome
  5865. 4:42:39back. In this video, we are going to
  5866. 4:42:42talk about the CDN layer and caching.
  5867. 4:42:47Here is what we are going to work on. In
  5868. 4:42:50this video, I'm going to show you how to
  5869. 4:42:53route traffic through a content delivery
  5870. 4:42:56network. There are many, but we are
  5871. 4:42:59going to use Cloudflare for this
  5872. 4:43:01tutorial. We are going to configure
  5873. 4:43:04strict end toend SSL encryption. I will
  5874. 4:43:08show you how to unmask the visitor IP
  5875. 4:43:11address in engine X because now
  5876. 4:43:13Cloudflare will sit between the user and
  5877. 4:43:17engine X. This is an important step that
  5878. 4:43:20we should not forget. And finally, I
  5879. 4:43:24will show you how to implement caching
  5880. 4:43:26strategies for single page applications.
  5881. 4:43:30Let me show you why we need to rely on
  5882. 4:43:34CDNs, especially for applications that
  5883. 4:43:38don't require a backend. Last time I
  5884. 4:43:41bought this domain to demonstrate how to
  5885. 4:43:45link your domain to your VM. And as you
  5886. 4:43:50can see, the application loads and uh
  5887. 4:43:52here is my website. You can use this
  5888. 4:43:55free utility that allows you to check
  5889. 4:43:59the load times. Here you can test. Let's
  5890. 4:44:03test this website. Keep from all
  5891. 4:44:05checkpoints and click on start test.
  5892. 4:44:10Here is the results that we got. As you
  5893. 4:44:13can see, this shows us the result. Shows
  5894. 4:44:17us a lot of information. But as you can
  5895. 4:44:19see, it tests the load time of our
  5896. 4:44:21website in different locations. You can
  5897. 4:44:23see that here Frankfurt is in Germany
  5898. 4:44:26because I am hosting this server on a
  5899. 4:44:30virtual machine in Germany. That's why
  5900. 4:44:32the load time is basically zero. But if
  5901. 4:44:36we go um let's see. So here the the
  5902. 4:44:40worst load response time is almost 5
  5903. 4:44:44seconds which is in China. It makes
  5904. 4:44:47sense because the distance between
  5905. 4:44:48Germany and China is very big. We we
  5906. 4:44:52will also see here u yeah as you can see
  5907. 4:44:55we have Japan we have yeah other
  5908. 4:44:58countries that are very far but the the
  5909. 4:45:01countries that are countries that are
  5910. 4:45:03close to Germany uh especially in Europe
  5911. 4:45:07Africa those will uh see very uh very
  5912. 4:45:10low uh load times. This is a good tool
  5913. 4:45:14that you can use to test how fast your
  5914. 4:45:17your website loads for users. I wanted
  5915. 4:45:21to start with this because it shows the
  5916. 4:45:23problem that we currently have. And if
  5917. 4:45:27you want to solve this, one option is to
  5918. 4:45:29host your website on many servers. For
  5919. 4:45:32example, you can host one maybe
  5920. 4:45:34somewhere in Europe. That will give
  5921. 4:45:37people in Europe
  5922. 4:45:39very high load times. Maybe you put
  5923. 4:45:42another one in um USA, you put another
  5924. 4:45:45one in Africa, another one in Asia. But
  5925. 4:45:48that will drive the cost up very
  5926. 4:45:51quickly. CDNs solve this issue for us.
  5927. 4:45:54They allow us to serve static files to
  5928. 4:45:58users all over the world. And here cloud
  5929. 4:46:01player, this is what we are going to
  5930. 4:46:04use. They have plenty of servers uh
  5931. 4:46:07scattered around the world. And let me
  5932. 4:46:09show you this diagram that I made that
  5933. 4:46:12explains how this works. We have two
  5934. 4:46:15situations. The first one is before
  5935. 4:46:18applying CDN and the other one is after.
  5936. 4:46:21Let's now look at the first diagram.
  5937. 4:46:24Let's consider that the server here is
  5938. 4:46:26hosted maybe here in somewhere in
  5939. 4:46:28Morocco. And let's say someone here in
  5940. 4:46:31Asia wants to check my website. The load
  5941. 4:46:34time will be let's say almost 4 seconds.
  5942. 4:46:38And this user will see a smaller load
  5943. 4:46:41time but still it's not it's not very
  5944. 4:46:43responsive. 1.2 seconds is bad. But if
  5945. 4:46:46someone is here in Morocco or Algeria,
  5946. 4:46:49the the website will load instantly for
  5947. 4:46:52them. This is the problem that we have
  5948. 4:46:55distance that we need to travel and that
  5949. 4:46:58takes time. With CDN, we'll solve this
  5950. 4:47:01by including edge servers. These servers
  5951. 4:47:05are located close to the end user. This
  5952. 4:47:10person who lives in Asia will connect to
  5953. 4:47:14a server
  5954. 4:47:16the closest server to them. We call them
  5955. 4:47:19edge. And that edge server will
  5956. 4:47:21communicate with the main server. And
  5957. 4:47:24these edge servers are provided or are
  5958. 4:47:28given to us by Cloudflare. And here they
  5959. 4:47:31will cache your static files just the
  5960. 4:47:34front end so that users can load them
  5961. 4:47:36instantly. And as you can see, with the
  5962. 4:47:39help of these edge servers, we were able
  5963. 4:47:42to bring down this 3.9 seconds to almost
  5964. 4:47:46zero. This is the benefit. And I will
  5965. 4:47:49show you how to do this in this video.
  5966. 4:47:52And the great thing about this is that
  5967. 4:47:54we have the before situation. After
  5968. 4:47:56applying the test, we will come back
  5969. 4:47:58here. We will uh start the test again.
  5970. 4:48:01And hopefully we will see that for
  5971. 4:48:03example for Beijing it will go from 5
  5972. 4:48:05seconds to maybe uh 1 second or less
  5973. 4:48:09hopefully and uh we will see that at the
  5974. 4:48:11end of this video. Now go to
  5975. 4:48:13cloudplayer.com.
  5976. 4:48:15Let me zoom out a little bit so that you
  5977. 4:48:17can see. And here make sure to create an
  5978. 4:48:22account. If you don't have it you can
  5979. 4:48:23loging in for free. They have a free
  5980. 4:48:25tier which we we are going to use in
  5981. 4:48:27this video. I will log in and I'll come
  5982. 4:48:29back. After you log in, you will see a
  5983. 4:48:33add button. Click on it and choose
  5984. 4:48:36connect a domain. Here I will type my
  5985. 4:48:40domain name. I will choose this one.
  5986. 4:48:44Keep import DNS records automatically
  5987. 4:48:48checked. This will allow Cloudflare to
  5988. 4:48:51automatically fetch the A and C name
  5989. 4:48:55records that we created uh in pork bun
  5990. 4:48:59or in your preferred domain registar.
  5991. 4:49:03Here we have a section uh about AI
  5992. 4:49:06crawlers. If you don't want AI companies
  5993. 4:49:10to scrape your websites, select block on
  5994. 4:49:14all pages or you can select the other
  5995. 4:49:17options. I don't want them to scrape my
  5996. 4:49:20content. So, I will select this. And
  5997. 4:49:23here we have this option that will
  5998. 4:49:25instruct AI bot traffic with robots txt.
  5999. 4:49:28You can read more about this. Uh it's an
  6000. 4:49:31it's a setting that Cloudfare will add
  6001. 4:49:34to robots txt to block AI companies from
  6002. 4:49:39scraping your website. As you can see,
  6003. 4:49:41they have a few few options. So, they
  6004. 4:49:43have AI input, AI train. If you want,
  6005. 4:49:45you can read read it here in the
  6006. 4:49:47documentation. I'll keep that enabled
  6007. 4:49:50and I'll hit continue. As I mentioned,
  6008. 4:49:52they have a free plan that you can use.
  6009. 4:49:56They also have other plans. If you want
  6010. 4:49:58to scale your website, you need to move
  6011. 4:50:00to maybe the pro plan. But for this
  6012. 4:50:04tutorial, the free plan will be enough.
  6013. 4:50:07And here they are showing you the how
  6014. 4:50:09much you will pay monthly or yearly. We
  6015. 4:50:11don't care about that because yeah we
  6016. 4:50:13will be on the free pan anyway. This
  6017. 4:50:16step is very important. Cloudflare here
  6018. 4:50:19is listing the DNS records. It's found
  6019. 4:50:22on pork bun. Here we need to verify the
  6020. 4:50:26status. Here you can see that we they
  6021. 4:50:28show you two icons. Uh so if the icon is
  6022. 4:50:32orange like we see here, it means it's
  6023. 4:50:34proxied which means traffic will go
  6024. 4:50:37through the cloudflare network network.
  6025. 4:50:39And this is what we want. Here we have
  6026. 4:50:41the A and C name records. They are
  6027. 4:50:44pointing to the correct values. And here
  6028. 4:50:47the proxy status is proxied. This is
  6029. 4:50:49correct. This is what we want to see.
  6030. 4:50:51Email traffic uh for the MX and TX
  6031. 4:50:56records. Here you want them to be DNS
  6032. 4:50:59only. We don't want we don't want
  6033. 4:51:01Cloudflare to proxy them because
  6034. 4:51:04Cloudflare does not proxy email traffic.
  6035. 4:51:08If you do this, your email will stop
  6036. 4:51:10working. So, please keep it as DNS only.
  6037. 4:51:14And if you have any NS records, in my
  6038. 4:51:18case, I don't have them. You need to
  6039. 4:51:19delete them. You will have this delete
  6040. 4:51:21button. Just click on it and delete
  6041. 4:51:23those records. Uh I can show you how
  6042. 4:51:25this looks in the documentation. Click
  6043. 4:51:28on the book folder. Come here to uh the
  6044. 4:51:32fourth module. Search for NS. And yeah,
  6045. 4:51:37here is the page. You can see that here
  6046. 4:51:39if you see these NS records, just click
  6047. 4:51:42on the delete button to remove them.
  6048. 4:51:45Okay, now we can go back. I'll click on
  6049. 4:51:47continue to activation. And if you are
  6050. 4:51:50wondering, there is here a warning that
  6051. 4:51:53tells you this host name is not covered
  6052. 4:51:55by a certificate. This is not a problem.
  6053. 4:51:57We created a certificate in the previous
  6054. 4:52:00tutorial. We used Let's Encrypt for
  6055. 4:52:03that. So yeah the and as you can see the
  6056. 4:52:06website is secure we have um as you can
  6057. 4:52:08see it's verified by let's encrypt just
  6058. 4:52:11click on continue to activation and at
  6059. 4:52:14this step we need to connect to porkban
  6060. 4:52:18because we need to uh update some stuff
  6061. 4:52:20I'll I'll log into pork and I will come
  6062. 4:52:23back I am in the domain management page
  6063. 4:52:27here as you can see we have uh the my
  6064. 4:52:30new domain I'll click on ns by default
  6065. 4:52:33We have a few name servers. We need to
  6066. 4:52:36replace these by the the ones that
  6067. 4:52:39Cloudflare has given us. Just click on
  6068. 4:52:42this link. It's going to copy the name
  6069. 4:52:46servers. Remove these depot ones and
  6070. 4:52:50start pasting the name servers that uh
  6071. 4:52:54Cloudflare has given you. And you can
  6072. 4:52:56follow the steps. You can read here. So
  6073. 4:52:58they tell you to log into the DNS
  6074. 4:53:00provider. In my case, it's Porkban. And
  6075. 4:53:02after that they tell you to find the
  6076. 4:53:04name servers section. Here it is. And
  6077. 4:53:08after that add these and delete the
  6078. 4:53:09other uh name servers. I have done that.
  6079. 4:53:12Now I just need to click on save name
  6080. 4:53:14servers and hit okay. Now return to
  6081. 4:53:18Cloudflare and click on I updated my
  6082. 4:53:22name servers. In this page click on
  6083. 4:53:25check name servers now to see if the
  6084. 4:53:28name servers have been propagated. Uh if
  6085. 4:53:31you read the text, they tell you that
  6086. 4:53:32this uh takes around maybe an hour or
  6087. 4:53:35two or sometimes even a day. But if you
  6088. 4:53:38want, you can click on check name
  6089. 4:53:40servers now. And uh as you can see,
  6090. 4:53:44Cloudflare is saying that they are
  6091. 4:53:45checking the name servers for my domain.
  6092. 4:53:48So they are telling me to wait a few
  6093. 4:53:50hours. But that's not a problem. We can
  6094. 4:53:52continue the configuration. We will come
  6095. 4:53:54back and uh verify that everything is
  6096. 4:53:57proxied through Cloudflare. Now on this
  6097. 4:54:01left panel we can click on SSL uh /TLS
  6098. 4:54:06click on overview and here make sure
  6099. 4:54:08that your domain is selected here I have
  6100. 4:54:12two uh I will select the the new one
  6101. 4:54:14that we added and here we need to set
  6102. 4:54:16this to full strict uh hit confirm. Why
  6103. 4:54:21do we need to select this instead of
  6104. 4:54:24full? Because as I said in the previous
  6105. 4:54:26tutorial, we used let's encrypt to
  6106. 4:54:30secure uh our website and uh we saw that
  6107. 4:54:34when we were add when we were verifying
  6108. 4:54:36the DNS uh Cloudflare was giving us that
  6109. 4:54:39warning because they don't know if we
  6110. 4:54:42have a a certificate and uh by choosing
  6111. 4:54:45full strict cloud player will know that
  6112. 4:54:47we have our own certificates and will
  6113. 4:54:50accept it. Now I want to show you a
  6114. 4:54:53utility called dig. Uh you can search
  6115. 4:54:57for it. It's it's called as I said dig
  6116. 4:55:00and you can read about it uh here on
  6117. 4:55:03Wikipedia.
  6118. 4:55:04It's a utility that we can use to verify
  6119. 4:55:08if the internet is seeing the new name
  6120. 4:55:12servers that we got from Cloudflare.
  6121. 4:55:14First make sure that it is installed by
  6122. 4:55:17typing dig-v. It's going to give you the
  6123. 4:55:20version. If you don't have the utility,
  6124. 4:55:23you can install it like this on Ubuntu
  6125. 4:55:26by installing DNS utils and that will
  6126. 4:55:29give you access to this utility. To use
  6127. 4:55:32it, you type big plus short. We want to
  6128. 4:55:36verify the name servers. And here uh I
  6129. 4:55:39will put my domain name. As you can see,
  6130. 4:55:41it is showing me the these four that are
  6131. 4:55:44coming from Porkbun, which means that
  6132. 4:55:47the new name servers haven't propagated
  6133. 4:55:50yet. So, we will have to wait for a few
  6134. 4:55:53hopefully for a few hours and not a full
  6135. 4:55:55day. You can also go back to Cloudflare,
  6136. 4:55:59go to overview. Here you should see that
  6137. 4:56:03this message that tells you that your
  6138. 4:56:05domain is now protected by Cloudflare.
  6139. 4:56:08That this is what we want to see.
  6140. 4:56:10And if you made any mistake, you can
  6141. 4:56:13always go back here. For example, if you
  6142. 4:56:15want to update the DNS records, just
  6143. 4:56:19click there or you can find it here on
  6144. 4:56:21the left panel. And here are the
  6145. 4:56:23records. You can see we have all the
  6146. 4:56:25records and also the name servers. You
  6147. 4:56:28can also use another website called
  6148. 4:56:30what's mydns.net.
  6149. 4:56:33We can do the same thing here. I can put
  6150. 4:56:36my name uh I can put my domain name
  6151. 4:56:39here. Here I will select NS because this
  6152. 4:56:41is what I want to verify. And if you hit
  6153. 4:56:44enter, as you can see, it is starting to
  6154. 4:56:47propagate. There are some locations
  6155. 4:56:50where the Cloudflare name servers
  6156. 4:56:53haven't propagated yet. But yeah, the it
  6157. 4:56:56it will take a few hours for uh every
  6158. 4:57:00location to see the new name servers.
  6159. 4:57:02Let's go back to dig to see what we get.
  6160. 4:57:05We are still getting uh yeah we are
  6161. 4:57:08still getting the old name servers but
  6162. 4:57:10yeah it's going to uh it's going to show
  6163. 4:57:12up uh in a few hours with this website.
  6164. 4:57:16We were we are able to confirm that uh
  6165. 4:57:19the new cloud player name servers are
  6166. 4:57:21starting to propagate. Let's go back to
  6167. 4:57:25this website. I will take a screenshot
  6168. 4:57:29for this previous test and uh I will
  6169. 4:57:33rerun it again and let's see if uh
  6170. 4:57:36things have changed or not. Okay. Uh we
  6171. 4:57:40see some improvements. Uh obviously uh
  6172. 4:57:42yeah uh the DN the name servers haven't
  6173. 4:57:45propagated fully but we should be able
  6174. 4:57:48to see some uh differences. I'll take
  6175. 4:57:51another screenshot and I'll put the two
  6176. 4:57:54images next to each other. On the right
  6177. 4:57:56side we have the before
  6178. 4:57:59and here this is after. As you can see
  6179. 4:58:02let's start with Beijing. Before it was
  6180. 4:58:045 seconds now it is 3.4 seconds and this
  6181. 4:58:07will keep improving. Um maybe the first
  6182. 4:58:11time you try to load the website that
  6183. 4:58:13will take maybe uh let's say 3 seconds
  6184. 4:58:16but after that the files are going to be
  6185. 4:58:18cached which means that they are going
  6186. 4:58:19to load very fast and uh since uh the
  6187. 4:58:22name servers are still propagating
  6188. 4:58:25I will maybe I'll try to rerun this uh
  6189. 4:58:28afterwards uh and just before ending
  6190. 4:58:31this tutorial and we'll see if things
  6191. 4:58:33will improve or not. But you can see
  6192. 4:58:34that there are some locations that
  6193. 4:58:36improved uh drastically. Uh especially
  6194. 4:58:39Beijing. Uh let's look at maybe Hong
  6195. 4:58:43Kong. So Hong Kong is now it takes just
  6196. 4:58:461 second. Soul takes 0.9 seconds. Okay,
  6197. 4:58:50good. We see some improvements which is
  6198. 4:58:52a great thing to see. Well, I will come
  6199. 4:58:54back to this website later. I will leave
  6200. 4:58:56it here. And now let's go back to the
  6201. 4:58:59slides. This is uh what I observed on my
  6202. 4:59:03personal website. You can see that uh I
  6203. 4:59:06used the same tool and here I I see big
  6204. 4:59:10changes because I let the name servers
  6205. 4:59:13propagate for maybe a day before running
  6206. 4:59:16the test again. For Tokyo, as you can
  6207. 4:59:19see, we were able to reduce the time
  6208. 4:59:22from 1.3 seconds to 0.3.
  6209. 4:59:25So again, same situation. Jakarta, same.
  6210. 4:59:29and Beijing it went from 4 seconds to
  6211. 4:59:311.5 seconds. This is the benefit of
  6212. 4:59:34using a CDN especially if your website
  6213. 4:59:37is
  6214. 4:59:38doesn't even if it has a back back end
  6215. 4:59:41uh attached to it there is no problem
  6216. 4:59:44your front end will load quickly but
  6217. 4:59:47because we introduced cloud player we
  6218. 4:59:50now have a problem I have created this
  6219. 4:59:54illustration to explain you the issue
  6220. 4:59:57let's say that we have a user this is
  6221. 5:00:00their IP address now if let's say that
  6222. 5:00:03they want to check my homepage, the
  6223. 5:00:06request will go through Cloudflare with
  6224. 5:00:09the IP of that user. That's not a
  6225. 5:00:12problem. But when Cloudflare will try to
  6226. 5:00:16send that request to my application,
  6227. 5:00:19it's going to send it to EngineX. But
  6228. 5:00:21the problem is that we are not sending
  6229. 5:00:23the user's IP. Instead, we send
  6230. 5:00:26Cloudflare's IP address and this will be
  6231. 5:00:30sent to the back end. And uh that's
  6232. 5:00:32problematic if you want to do I don't
  6233. 5:00:35know if you want to track uh IP
  6234. 5:00:38addresses. This is bad because let's say
  6235. 5:00:40that you you received 100 requests from
  6236. 5:00:44let's say 50 users your backend will see
  6237. 5:00:47the same IP address and this is the
  6238. 5:00:50problem that we will try to fix. And
  6239. 5:00:52luckily, if you read the Cloudflare
  6240. 5:00:54documentation, they tell you that you
  6241. 5:00:57need to add CF connecting IP to your
  6242. 5:01:00EngineX configuration. And that will
  6243. 5:01:03allow you to unwrap the IP to get uh
  6244. 5:01:07yeah to get the user's original IP
  6245. 5:01:10address. And now your backend receive
  6246. 5:01:12the correct IP and you can store that in
  6247. 5:01:15your in a database or uh yeah uh use it
  6248. 5:01:18in your analytics or something like
  6249. 5:01:20that. Let me show you how we do that. I
  6250. 5:01:23have connected to the machine. Let's
  6251. 5:01:26open this file. Let me type my password.
  6252. 5:01:30And here I want you to copy this from
  6253. 5:01:33the GitHub repository and put it here.
  6254. 5:01:36Let me show you where you can get that.
  6255. 5:01:39Here is where to get this code block. It
  6256. 5:01:42is available in uh my GitHub repository.
  6257. 5:01:45Let me go back here. If I scroll down,
  6258. 5:01:48you can see that we have this line which
  6259. 5:01:51uses this header to get the real user
  6260. 5:01:54IP. And don't worry about this. If you
  6261. 5:01:56want, you can find the link to the
  6262. 5:01:59documentation. Just click on this that
  6263. 5:02:02will take you to this page and you can
  6264. 5:02:04read about this header in detail. Here
  6265. 5:02:08we have the Cloudflare IP addresses. And
  6266. 5:02:12here I added a note that shows you these
  6267. 5:02:16IP addresses and they you can also see
  6268. 5:02:19the dates that maybe if they change them
  6269. 5:02:21or if they added more you can just come
  6270. 5:02:23to this page, copy them and put them in
  6271. 5:02:27this configuration file. Good. Now we
  6272. 5:02:30can save the file. Exit. This file will
  6273. 5:02:33be loaded automatically. So there is no
  6274. 5:02:36need to go to our website configuration
  6275. 5:02:39and uh include this. Now we need to
  6276. 5:02:41verify the syntax to ensure that
  6277. 5:02:43everything is correct. Good. And now we
  6278. 5:02:47need to reload uh engine X. But before I
  6279. 5:02:50do that, I just want to go to the
  6280. 5:02:52website because now we are using uh
  6281. 5:02:55Cloudflare. I want to show you the
  6282. 5:02:57situation before and after. We already
  6283. 5:03:00we have the logs. So we can check them
  6284. 5:03:02to see the IP address that we are
  6285. 5:03:04getting. Let's check the access logs. I
  6286. 5:03:08want I will do tail instead of cat and
  6287. 5:03:12let's see what we are getting. This is
  6288. 5:03:15the the IP that I was talking about. We
  6289. 5:03:17can see them here. Uh let me go to the
  6290. 5:03:21website again just to make sure that we
  6291. 5:03:23are receiving Cloudflare's IP addresses.
  6292. 5:03:27Okay, I have visited the web page. I am
  6293. 5:03:29using tail-fs
  6294. 5:03:33and let's start refreshing the page. You
  6295. 5:03:34can see that here we get we are using uh
  6296. 5:03:37some I uh we are receiving some IP
  6297. 5:03:40addresses. We confirmed that we are
  6298. 5:03:42receiving one IP address which is coming
  6299. 5:03:45from Cloudflare. We might receive
  6300. 5:03:47different ones but all of them are
  6301. 5:03:48coming from Cloudflare because here we
  6302. 5:03:50have uh plenty of uh IP ranges. Now
  6303. 5:03:55let's stop this and let's reload X.
  6304. 5:03:58Okay, I've reloaded. Now uh let's let's
  6305. 5:04:01watch and let's see what we get after uh
  6306. 5:04:05refreshing the page. Aha. As you can
  6307. 5:04:07see, I am getting my own IP address now
  6308. 5:04:10instead of the server's IP. And I can
  6309. 5:04:14refresh. And uh yeah, as you can see, I
  6310. 5:04:17am getting my IP address. And I'm I'm
  6311. 5:04:19also receiving other IP addresses. These
  6312. 5:04:22are coming from either bots, probably
  6313. 5:04:25bots because no one knows my website and
  6314. 5:04:28not real humans. Uh these are just
  6315. 5:04:30automatic bots that are uh targeting
  6316. 5:04:33your website because they are trying to
  6317. 5:04:35see if they can get some credentials
  6318. 5:04:39from your website. I can show you this
  6319. 5:04:40if we scroll uh let me use maybe cat or
  6320. 5:04:44something to see the full uh log. I can
  6321. 5:04:48also take this to grab and search for
  6322. 5:04:51env. As you can see, this person or
  6323. 5:04:55yeah, this boss is trying to see if they
  6324. 5:04:58can find some env files on my uh web
  6325. 5:05:02server. Um I mean even if they they try
  6326. 5:05:05they won't be able to get anything
  6327. 5:05:06because we are not serving those files
  6328. 5:05:08when we created our engineext
  6329. 5:05:10configuration. But you need to be aware
  6330. 5:05:12that if your server is public, it's
  6331. 5:05:15going to be hammered by bots. Awesome.
  6332. 5:05:18Now the thing that we need to do is um
  6333. 5:05:21to start working on caching. When you
  6334. 5:05:25develop a front- end application, there
  6335. 5:05:28are some pages that are not going to
  6336. 5:05:31change. Those can be cached. But the
  6337. 5:05:34pages uh that are dynamic, we should not
  6338. 5:05:38change them. For example, if I change my
  6339. 5:05:41index.html,
  6340. 5:05:43this is a single page application. If I
  6341. 5:05:45add another feature, let's say to one of
  6342. 5:05:47my blogs, I want to I want users to be
  6343. 5:05:51able to see it. If I cache index.html,
  6344. 5:05:55they won't be showing they won't be
  6345. 5:05:57receiving the new updates because
  6346. 5:06:00browsers they are the they are designed
  6347. 5:06:02to cache resources so that they load
  6348. 5:06:05fast for users. But sometimes if this is
  6349. 5:06:08not implemented correctly uh they might
  6350. 5:06:11not receive uh new updates from you and
  6351. 5:06:15this is what we are going to focus on.
  6352. 5:06:17Uh now let's open my engineext
  6353. 5:06:20configuration and here we need to start
  6354. 5:06:23adding some caching. We have a single
  6355. 5:06:28page application. I'm going to divide
  6356. 5:06:30the caching strategy into two parts. The
  6357. 5:06:34first one we will uh we will never cache
  6358. 5:06:37index.html
  6359. 5:06:39because the whole application is
  6360. 5:06:41injected there and if uh something new
  6361. 5:06:45was added to the front end it's not
  6362. 5:06:48going to show up if we cache index.html
  6363. 5:06:51but assets like images logos those can
  6364. 5:06:54be cached forever. So let's start uh
  6365. 5:06:57applying this. Let me show you how we do
  6366. 5:07:00this. I will come here and I will add
  6367. 5:07:04another location block. This block will
  6368. 5:07:08tell the browser to always communicate
  6369. 5:07:11with the server to see if there is a new
  6370. 5:07:15version of index.html.
  6371. 5:07:18If if we have one then the browser will
  6372. 5:07:22try to load it. And here in the caching
  6373. 5:07:25strategy we are using no cache. uh so
  6374. 5:07:29that we tell the browser to not store it
  6375. 5:07:32and instead try to communicate with the
  6376. 5:07:36server every time uh this file is
  6377. 5:07:39requested. And as you can see here we
  6378. 5:07:41are using equal because we want to focus
  6379. 5:07:44just on this specific file. We can also
  6380. 5:07:48add this location block to cache assets
  6381. 5:07:52forever. Here we are the the assets are
  6382. 5:07:55located in the b folder. Here the
  6383. 5:07:59caching strategy is now we are setting
  6384. 5:08:02it to public. Max age is set to this
  6385. 5:08:06very big value. Uh it is in seconds. If
  6386. 5:08:10you convert it to years it's going to
  6387. 5:08:12give you exactly one year. And here we
  6388. 5:08:15are using immutable. This is an
  6389. 5:08:18instruction that tells the browser that
  6390. 5:08:20this file will never change. Let's save
  6391. 5:08:24the file. Let's exit. Uh now we need to
  6392. 5:08:29verify that the syntax is okay. Good.
  6393. 5:08:32And we can reload. Let's go to the
  6394. 5:08:36browser. Let's refresh the page. Just
  6395. 5:08:38ensure that everything is uh working
  6396. 5:08:41without any issue. Okay, great. Now what
  6397. 5:08:44I want you to do is to open the network
  6398. 5:08:48tab. I will zoom in a little bit here.
  6399. 5:08:50Select all or you can select the static
  6400. 5:08:53files. Refresh the page and let's see
  6401. 5:08:56what we have here. I'll select HTML, CSS
  6402. 5:08:59and JavaScript. If you look at this
  6403. 5:09:02column transferred, you see that the
  6404. 5:09:04browser is telling you that most of
  6405. 5:09:07these static files were cached. That
  6406. 5:09:10makes sense because we have added the
  6407. 5:09:12the caching strategy but the root file
  6408. 5:09:16which is uh the index.html HTML we
  6409. 5:09:20always uh we are always communicating
  6410. 5:09:23with the server to get the latest
  6411. 5:09:26version. And as you can see here in the
  6412. 5:09:28cache control we uh it is set to no
  6413. 5:09:31cache which means that the configuration
  6414. 5:09:34that we added to engineext uh has been
  6415. 5:09:36loaded uh successfully and in the
  6416. 5:09:39response we get uh index.thml the HTML
  6417. 5:09:42and as I mentioned in Vue or other
  6418. 5:09:45frameworks we inject uh the application
  6419. 5:09:48inside this div with the id app that's
  6420. 5:09:52why we need uh it's very important to
  6421. 5:09:54not cache this file amazing this worked
  6422. 5:09:57now I want uh I want to mention the pros
  6423. 5:10:01and cons of using a CDN like Cloudflare
  6424. 5:10:06or yeah other CDN's uh the benefit here
  6425. 5:10:10is speed. We saw that before we weren't
  6426. 5:10:15able I mean for users in China they
  6427. 5:10:18needed to wait 5 seconds to load the
  6428. 5:10:22website and my website is not heavy.
  6429. 5:10:25Imagine if the website was uh very huge
  6430. 5:10:28or not optimized that 5 seconds uh would
  6431. 5:10:33have turned to maybe 7 seconds or or
  6432. 5:10:36more. Um but now thankfully with the
  6433. 5:10:39help of Cloudflare we were able to bring
  6434. 5:10:42that down from 5 seconds to 1.5 seconds
  6435. 5:10:46which is amazing. And as you can see the
  6436. 5:10:48the numbers have changed because
  6437. 5:10:50probably the name servers uh have
  6438. 5:10:54propagated that's why we see this
  6439. 5:10:56dramatic shift. Uh yeah, as you can see
  6440. 5:11:00even here uh when trying to run the dick
  6441. 5:11:03command I no longer see the pork bun
  6442. 5:11:05name servers instead I am seeing the
  6443. 5:11:08cloud player name servers amazing this
  6444. 5:11:11didn't take even an hour and we can see
  6445. 5:11:14a huge boost in uh performance that this
  6446. 5:11:17is very amazing another benefit is
  6447. 5:11:20security even uh even though we are
  6448. 5:11:23using the free plan we are able to uh
  6449. 5:11:28get some security. Um, CloudFlare will
  6450. 5:11:31protect your website from DDoS attacks
  6451. 5:11:34and other types of attacks. It's going
  6452. 5:11:36to block AI crawlers from scraping your
  6453. 5:11:40website uh which is amazing. But the
  6454. 5:11:42problem is uh this adds complexity. We
  6455. 5:11:46have introduced another step before
  6456. 5:11:49reaching uh our application. And if uh
  6457. 5:11:53let's say that someday a uh a problem
  6458. 5:11:56happened and your application is not
  6459. 5:11:58accessible you have to verify everything
  6460. 5:12:01and um yeah because you don't know if
  6461. 5:12:03the problem is in cloudflare or is uh in
  6462. 5:12:07your application and sometimes if cloud
  6463. 5:12:10if there is an outage in cloudflare your
  6464. 5:12:12application will not be accessible and
  6465. 5:12:14this happened many times uh in the
  6466. 5:12:17recent months uh many people who relied
  6467. 5:12:21on Cloudflare suddenly couldn't uh or
  6468. 5:12:25users couldn't re reach their
  6469. 5:12:27applications. So these are the pros and
  6470. 5:12:30cons of using this. But I mean I would
  6471. 5:12:34say the main benefit is that you won't
  6472. 5:12:36pay a lot of money to host your
  6473. 5:12:38application in uh many web uh on many
  6474. 5:12:42web servers scattered around the world.
  6475. 5:12:45Your website is now globally
  6476. 5:12:47distributed,
  6477. 5:12:49passed, and protected by Cloudflare's
  6478. 5:12:52network. You have successfully finished
  6479. 5:12:55the performance setup. However, before
  6480. 5:12:58we move on to automating your
  6481. 5:13:01deployments, we need to ensure that your
  6482. 5:13:05server is completely locked down against
  6483. 5:13:07hackers and automated scanners. As you
  6484. 5:13:10saw in the engineext logs, we saw that
  6485. 5:13:12there are many bots who are trying to
  6486. 5:13:15fetch secure files. So we need to ensure
  6487. 5:13:19that everything is secure so that we can
  6488. 5:13:21rest easy and don't worry about
  6489. 5:13:24something being stolen from your web
  6490. 5:13:26server. In the next chapter, we are
  6491. 5:13:28going to talk about vulnerability
  6492. 5:13:31scanning. I will show you how to test
  6493. 5:13:34your own defenses. I'm going to show you
  6494. 5:13:37how to update the engineext
  6495. 5:13:39configuration to block access to files
  6496. 5:13:43like envit
  6497. 5:13:46something like that so that bots
  6498. 5:13:48automated bots cannot reach them. I will
  6499. 5:13:51show you how to scan uh your web server
  6500. 5:13:55for open ports using a tool called end
  6501. 5:13:57mapap. This will uh with this we can uh
  6502. 5:14:00verify that only the minimum amount of
  6503. 5:14:04ports are open. Uh we want ports for
  6504. 5:14:08HTTP, HTTPS and SSH. These are the only
  6505. 5:14:11ports that we want to open to the entire
  6506. 5:14:14internet. But the other ports like uh
  6507. 5:14:18your applications back end or me search
  6508. 5:14:21or other services services those needs
  6509. 5:14:23to be uh closed and if we want to use
  6510. 5:14:26them we need to use SSH tunneling like
  6511. 5:14:29we did with the previous tutorials. This
  6512. 5:14:31is what we are going to focus on uh in
  6513. 5:14:34the next tutorial. See you next time.
  6514. 5:14:37Welcome back. In this tutorial we are
  6515. 5:14:40going to focus on vulnerability
  6516. 5:14:43scanning. You are going to learn about a
  6517. 5:14:46concept called soft 404. We are going to
  6518. 5:14:50fix it because this is present in our
  6519. 5:14:52application. You are going to configure
  6520. 5:14:54engine X to block malicious bots that
  6521. 5:14:57are scanning your website 24/7.
  6522. 5:15:01And finally, you will use a tool called
  6523. 5:15:03N MAPAP to scan your firewall from the
  6524. 5:15:07outside. Let's talk about this trap that
  6525. 5:15:10we call soft 404s. I have this diagram
  6526. 5:15:14that explains it. Here we don't have a I
  6527. 5:15:17mean we could have a regular user but
  6528. 5:15:19mostly these are bots. They will try to
  6529. 5:15:22get files that contains um valuable
  6530. 5:15:26information like your env files. So this
  6531. 5:15:31request will go through cloudflare and
  6532. 5:15:33will reach your application. Now,
  6533. 5:15:36engineext doesn't know about these files
  6534. 5:15:38because the location blocks that we
  6535. 5:15:40added are serving just our back end and
  6536. 5:15:44the built files uh for view. So, env is
  6537. 5:15:48not known. So, engineext will just fall
  6538. 5:15:51back to serving index.html
  6539. 5:15:54and this query or this request will
  6540. 5:15:57succeed. But this is a false success
  6541. 5:16:00because the intent of the bot is to get
  6542. 5:16:04not index.html.
  6543. 5:16:06Why this is a false success? Because the
  6544. 5:16:08bot will and will think that it was able
  6545. 5:16:12to get thev file. So it's going to
  6546. 5:16:15always come to your web server and it
  6547. 5:16:18will hammer it day and night. It's going
  6548. 5:16:20to keep asking it for the same file. But
  6549. 5:16:22if it gets A44 not found, it's going to
  6550. 5:16:27skip this. And this is useful for
  6551. 5:16:30malicious bots and also crawlers like
  6552. 5:16:33Google's crawlers, for example. If they
  6553. 5:16:35see that this path doesn't exist on your
  6554. 5:16:37website, it's going to stop uh accessing
  6555. 5:16:40it. And this this is b this is good for
  6556. 5:16:43you and for them because you will uh you
  6557. 5:16:46will not start wasting bandwidth on
  6558. 5:16:49requests that are uh going to give 404
  6559. 5:16:53and uh in this case bot will not will
  6560. 5:16:57see a signal that will tell them you are
  6561. 5:16:59not going to get this file anyway. So
  6562. 5:17:00they are going to back up. This is the
  6563. 5:17:03trap that we are uh that we have right
  6564. 5:17:06now in our application and we can test
  6565. 5:17:08it here. Uh this is uh the new domain. I
  6566. 5:17:12can come here. So we can see that we
  6567. 5:17:14have just slash that will go to
  6568. 5:17:16index.html but I can add dot /.Nv. As
  6569. 5:17:20you can see uh the request was
  6570. 5:17:22successful. I was a I am still on the
  6571. 5:17:25website. I don't see any error and my
  6572. 5:17:28application uh I configured my
  6573. 5:17:30application to load a 404 page because
  6574. 5:17:34yeah this is not known. there is no
  6575. 5:17:35route that will there is no page that
  6576. 5:17:37will uh be loaded after accessing this
  6577. 5:17:40URL. So I have a custom page but this
  6578. 5:17:44gives 200 as a uh HTTP status code. Uh
  6579. 5:17:49but we don't want to do this. Now if I
  6580. 5:17:51go to my production server and type the
  6581. 5:17:56same query I am I will get 404 not found
  6582. 5:17:59because I am blocking these uh most of
  6583. 5:18:02these files that uh automated boss try
  6584. 5:18:05to check and now the response is 404
  6585. 5:18:08it's not 200. If I go here and click on
  6586. 5:18:13this request we get 404. If we go back
  6587. 5:18:17to this website where we have the soft
  6588. 5:18:19404 problem, you can see that here we
  6589. 5:18:22are receiving 200. Okay, let's see how
  6590. 5:18:26to solve this problem. Again, you can go
  6591. 5:18:29back to my GitHub repository. You have
  6592. 5:18:32everything in this file. If you scroll
  6593. 5:18:34down a little bit, you have the
  6594. 5:18:36vulnerability scanning section. And
  6595. 5:18:40here, this is what we need to add. You
  6596. 5:18:43can see that here we are blocking a lot
  6597. 5:18:45of files um so that we are blocking
  6598. 5:18:48mainly anything that starts with dot we
  6599. 5:18:51have SQL all yeah there are plenty of
  6600. 5:18:54things that that we don't want to uh
  6601. 5:18:57serve. I will copy this and I will paste
  6602. 5:18:59it uh in uh my engineext configuration.
  6603. 5:19:03Now let's go to my server. I am still
  6604. 5:19:06logged in. I will use nano and let's add
  6605. 5:19:10this uh you can add it u here or below
  6606. 5:19:14it doesn't matter let me explain to you
  6607. 5:19:17the second location block here we are
  6608. 5:19:20blocking uh a lot of stuff even though
  6609. 5:19:22we are not using PHP in this application
  6610. 5:19:26you if you inspect the logs you will see
  6611. 5:19:28that they are trying to access some
  6612. 5:19:30admin panels PHP files stuff like that
  6613. 5:19:34so I am just I just have this
  6614. 5:19:36application block that will check all
  6615. 5:19:38these um file extensions and uh will
  6616. 5:19:41block them. Here I as you can see I am
  6617. 5:19:44returning 404 so that I can display that
  6618. 5:19:47page and access log and log not found
  6619. 5:19:51are set to off because I don't want to
  6620. 5:19:53store um yeah these failed requests uh
  6621. 5:19:57so that I don't consume a lot of disk
  6622. 5:19:59space because as I mentioned you will be
  6623. 5:20:02receiving thousands of requests per day
  6624. 5:20:05just um from bots that are trying to
  6625. 5:20:08access these files and here we have
  6626. 5:20:10something called well-known phone. Uh
  6627. 5:20:12you can go to this page on Wikipedia and
  6628. 5:20:16read more about them. Uh this is
  6629. 5:20:18important. We don't need to block this.
  6630. 5:20:22If you do, search bot will not be able
  6631. 5:20:25to verify your domain and your SSL
  6632. 5:20:28certificates. And if that happens, um
  6633. 5:20:32yeah, uh s will not be able to renew
  6634. 5:20:35your certificates and that will break
  6635. 5:20:38after 90 days. we are so here again we
  6636. 5:20:42are using uh an expression that will
  6637. 5:20:44capture most files like envit stuff like
  6638. 5:20:49that but uh we have one exception which
  6639. 5:20:52is the the wellknown uh directory we
  6640. 5:20:56don't want uh we don't want to block
  6641. 5:20:59that we want to keep it for all files we
  6642. 5:21:02are going to deny that request and again
  6643. 5:21:04we are going to return 404 and we don't
  6644. 5:21:06want to add anything or yeah we don't
  6645. 5:21:09want to add noise to the log files.
  6646. 5:21:11Okay, now let's save the file. Let's
  6647. 5:21:14verify that the configuration is
  6648. 5:21:16correct. Yes, it is. And let's reload.
  6649. 5:21:20Now, let's go back to the browser.
  6650. 5:21:23Let's see what we have here. Okay, so
  6651. 5:21:26remember this is my new domain. This is
  6652. 5:21:28the response that I re that I got before
  6653. 5:21:31this update to the configuration. Now,
  6654. 5:21:35let's refresh the page. And voila, we
  6655. 5:21:39get 404. Now I cannot get um
  6656. 5:21:44or what were the other stuff. Uh yeah,
  6657. 5:21:47let's uh check the logs. So they were
  6658. 5:21:50getting some PHP stuff. I'm not sure
  6659. 5:21:53what about uh what they were trying to
  6660. 5:21:55get. Yeah, you can see that they are
  6661. 5:21:57trying to go to some admin thing. Uh
  6662. 5:21:59yeah, I'm not familiar with PHP, but we
  6663. 5:22:02can uh take this and see if that will
  6664. 5:22:05get blocked or not.
  6665. 5:22:07put it here and yeah that worked because
  6666. 5:22:10we have PHP at the end and um yeah we
  6667. 5:22:14can also I think we are also capturing
  6668. 5:22:16some Python stuff let's see mainph
  6669. 5:22:20that also gets blocked but let's try
  6670. 5:22:23with Python yeah that works amazing so
  6671. 5:22:26yeah the list can be can be big uh I
  6672. 5:22:29just try to you can analyze the the logs
  6673. 5:22:33to see uh the files that the bots are
  6674. 5:22:37trying to access or you could search
  6675. 5:22:39online. There are many blacklists that
  6676. 5:22:42you can find to add to your engineext
  6677. 5:22:44configuration. If you want, you can uh
  6678. 5:22:47use one of these GitHub repositories to
  6679. 5:22:51uh block uh bad bots. And here uh so
  6680. 5:22:55yeah, this is a repository. They give
  6681. 5:22:58you some text files that you can just
  6682. 5:23:00put on your engineext configuration. Uh
  6683. 5:23:03so yeah they had a few stuff here that
  6684. 5:23:06uh that you can just include in your
  6685. 5:23:08configuration. You can read more about
  6686. 5:23:10this and you can also uh come here on
  6687. 5:23:13this other repository and use it. They
  6688. 5:23:16have plenty of uh files here that you
  6689. 5:23:18can check. But this is something that
  6690. 5:23:21you can also configure yourself just uh
  6691. 5:23:24by reading the yeah by reading the logs.
  6692. 5:23:27You can also use LLMs. they will be very
  6693. 5:23:30helpful in this uh step. You can explain
  6694. 5:23:33to them your stack so that they don't so
  6695. 5:23:37that they can help you uh block
  6696. 5:23:39everything but u yeah don't touch some
  6697. 5:23:43some things that will make your
  6698. 5:23:45application not load or break. Now we
  6699. 5:23:48have one more thing that I want you to
  6700. 5:23:50learn and that will involve this tool N
  6701. 5:23:55map the network mapper. It's a free
  6702. 5:23:58utility that we can install uh on Ubuntu
  6703. 5:24:02and other Linux dros. You just run um
  6704. 5:24:07sudo app install end mapap and you will
  6705. 5:24:10get it. Uh I already have it so there is
  6706. 5:24:12no need to download it. And uh let's
  6707. 5:24:15verify the version. We have 7.95.
  6708. 5:24:19That's good. And to use it, we are going
  6709. 5:24:22to run this command here. I will I'll
  6710. 5:24:26type my domain name. And let's see what
  6711. 5:24:29we have. Now end mapap is going to
  6712. 5:24:32start. The f flag will run a fast scan.
  6713. 5:24:36And this is going to check just 100
  6714. 5:24:39ports. And uh one one thing that I want
  6715. 5:24:43to mention is that end mapap you should
  6716. 5:24:45run this command on your local computer
  6717. 5:24:48uh not uh on the on the virtual machine.
  6718. 5:24:52Uh you can see that I have opened
  6719. 5:24:54another terminal tab and let's see what
  6720. 5:24:56we have here. So we have 97 and here we
  6721. 5:25:00have another three ports. The the sum
  6722. 5:25:02gives us 100 which confirms the theory
  6723. 5:25:05um or what I explained about this F
  6724. 5:25:08flag. Now let's analyze the the output.
  6725. 5:25:10You can see that here uh we have not
  6726. 5:25:13shown 97. These are other ports that are
  6727. 5:25:17not available or that are not accessible
  6728. 5:25:19from the out from the basically the
  6729. 5:25:22public internet. So that's that's a good
  6730. 5:25:25sign. And after that we have three ports
  6731. 5:25:28which are this is what I explained uh in
  6732. 5:25:30the beginning. We want to allow just
  6733. 5:25:33HTTP, HTTPS and SSH. We don't want to
  6734. 5:25:37open port 8080 or 7,700. These are ports
  6735. 5:25:41that we are using uh in that I am using
  6736. 5:25:44in my applications uh to basically
  6737. 5:25:47access M search fast API and also uh
  6738. 5:25:52view but those are running uh but they
  6739. 5:25:55are p uh they are they're not accessible
  6740. 5:25:58from uh the outside and uh as I showed
  6741. 5:26:01you in the previous tutorials if you
  6742. 5:26:04want to access those you don't open a
  6743. 5:26:07new hole in the firewall instead Use SSH
  6744. 5:26:11tunneling to open a temporary tunnel
  6745. 5:26:14between your local setup and the virtual
  6746. 5:26:17machine. Do your work and then close
  6747. 5:26:20that uh tunnel. At this point, you were
  6748. 5:26:24able to deploy your application
  6749. 5:26:27manually. You have u learned to how to
  6750. 5:26:31deal with uh bad actors that are trying
  6751. 5:26:34to access your website. you learn how to
  6752. 5:26:36optimize the load time and plenty of
  6753. 5:26:39other skills that are going to be very
  6754. 5:26:42um beneficial.
  6755. 5:26:44We saw you saw that we are using digital
  6756. 5:26:47ocean but you can take the concept that
  6757. 5:26:49you have learned here and use those with
  6758. 5:26:52other cloud providers. But this is the
  6759. 5:26:55first step. Now we are going to enter
  6760. 5:26:58another phase where we are going to
  6761. 5:27:00automate a lot of stuff. We are going to
  6762. 5:27:04create an automation pipeline that will
  6763. 5:27:07allow you to make changes to your
  6764. 5:27:10application locally. Maybe develop a new
  6765. 5:27:13feature uh fix a security problem and
  6766. 5:27:17instead of uh taking the source code,
  6767. 5:27:21copying it from your local computer to
  6768. 5:27:24the virtual machine, do the build
  6769. 5:27:26process and um install the dependencies
  6770. 5:27:30and then serve your application. We you
  6771. 5:27:33are going to automate this process. You
  6772. 5:27:35are going to learn about CICD which
  6773. 5:27:39stands for continuous integration and
  6774. 5:27:42delivery which will allow you to click
  6775. 5:27:44on a few buttons and those buttons will
  6776. 5:27:48run jobs uh on your behalf. Those jobs
  6777. 5:27:52will check for security problems. They
  6778. 5:27:55will check if uh dep the dependencies
  6779. 5:27:58that you are relying on are secure. They
  6780. 5:28:00will build your front end. They will
  6781. 5:28:03shut your backend application, reload
  6782. 5:28:06the new changes if there are any and um
  6783. 5:28:10other other kinds of job and you will
  6784. 5:28:12just sit there and watch uh your new
  6785. 5:28:15changes uh live become live on your
  6786. 5:28:18website and that will take you a few
  6787. 5:28:21minutes to do instead of hours of manual
  6788. 5:28:24labor. In the in that next module, we
  6789. 5:28:27are going to start slow. In the first
  6790. 5:28:30sub chapter, I will show you how to put
  6791. 5:28:33this code on GitHub. I assume that you
  6792. 5:28:36already have one or you can also use
  6793. 5:28:38other websites like GitLab or uh
  6794. 5:28:42Codeberg or yeah any any g compatible
  6795. 5:28:45client. Uh we'll show you how to protect
  6796. 5:28:49your main branch so that you don't push
  6797. 5:28:52code accidentally to it. We need to run
  6798. 5:28:55that pipeline to ensure that everything
  6799. 5:28:56is secure, everything is correct before
  6800. 5:28:59merging it to main. And after merging, I
  6801. 5:29:01will show you how to do the deployment.
  6802. 5:29:04But that will come uh in the next sub
  6803. 5:29:06chapters. So here we just want to focus
  6804. 5:29:08on the code quality. I'll show you how
  6805. 5:29:10to use the rough library because here we
  6806. 5:29:13are using Python to uh standardize to
  6807. 5:29:17run linting and formatting in order to
  6808. 5:29:19standardize the code that we write. And
  6809. 5:29:23on the front end side you will use
  6810. 5:29:25eslint which is the the default one.
  6811. 5:29:28Okay we will uh focus on formatting the
  6812. 5:29:31code and catching linting errors in the
  6813. 5:29:33next uh tutorial. See you next time.
  6814. 5:29:37Welcome to module five titled the
  6815. 5:29:40automation pipeline. In the previous
  6816. 5:29:43modules you were able to deploy the web
  6817. 5:29:47application manually. We have started by
  6818. 5:29:50copying the source code from your local
  6819. 5:29:54machine to the VM. You have been able to
  6820. 5:29:58install the dependencies, build the
  6821. 5:30:00front end and other stuff. This is
  6822. 5:30:02great. It's important to do things
  6823. 5:30:05manually, but you should not continue
  6824. 5:30:07like this because if you add features to
  6825. 5:30:10your application, you want to do the
  6826. 5:30:12deployment automatically. you you want
  6827. 5:30:15to focus on writing the code and let the
  6828. 5:30:18this automation that we are going to
  6829. 5:30:20build in this module do the work for
  6830. 5:30:22you. Here is what we are going to talk
  6831. 5:30:25about in this sub chapter. First I will
  6832. 5:30:28show you how to protect the main branch
  6833. 5:30:31using GitHub rule sets. In this tutorial
  6834. 5:30:35I am using GitHub but you can do the
  6835. 5:30:37same thing if you are using GitLab or
  6836. 5:30:40other uh websites. I will show you how
  6837. 5:30:43to automate local checks using
  6838. 5:30:46pre-commit. And for Python, we are going
  6839. 5:30:49to use the rough project to do linting
  6840. 5:30:52and formatting. And for JavaScript, we
  6841. 5:30:55will be using ESLint with prettier. If
  6842. 5:30:58you use other other programming
  6843. 5:31:00languages, look for the projects that
  6844. 5:31:03are there and use them. The concepts are
  6845. 5:31:05the same, but we are using different
  6846. 5:31:07technologies.
  6847. 5:31:08This is the repository that I was
  6848. 5:31:11talking about a lot during the previous
  6849. 5:31:13modules. Here you can find everything
  6850. 5:31:15related to the to the book that I am
  6851. 5:31:17writing and these the slides everything
  6852. 5:31:20is inside this repository and I want to
  6853. 5:31:23show you this is my this is my other
  6854. 5:31:26GitHub repository where I host my where
  6855. 5:31:29the source code of my personal website
  6856. 5:31:31and I want to show you what will what we
  6857. 5:31:34will achieve by the end of this module.
  6858. 5:31:36You can see that here is the automation
  6859. 5:31:39that I was talking about. You have
  6860. 5:31:41certain jobs that you run here on
  6861. 5:31:44GitHub. They run whenever you push code
  6862. 5:31:48and they do a lot of things for you. For
  6863. 5:31:50example, here this job will check my
  6864. 5:31:53dependencies. It will look at the Python
  6865. 5:31:55libraries. If it sees that there is some
  6866. 5:31:59security vulnerabilities, it's going to
  6867. 5:32:01stop the code that I pushed and it's not
  6868. 5:32:03going to be merged to the main branch.
  6869. 5:32:06This will protect you from deploying
  6870. 5:32:09code that is not secure. Uh here we are
  6871. 5:32:12performing linting and formatting. In
  6872. 5:32:15this video we are going to do this
  6873. 5:32:16locally but we can also do it here on
  6874. 5:32:19GitHub actions. You can run tests. We
  6875. 5:32:23have different kind of tests here. Here
  6876. 5:32:25you can see that we have unit tests,
  6877. 5:32:27integration tests and end to end test.
  6878. 5:32:30Finally, if everything goes well, we
  6879. 5:32:33will build the front end and the
  6880. 5:32:35pipeline succeeds. And we we can add
  6881. 5:32:37other actions that will allow us to
  6882. 5:32:40build the front end and deploy it. For
  6883. 5:32:43example, if I look at this one here, as
  6884. 5:32:46you can see, I have uh plenty of jobs or
  6885. 5:32:50workflows. And here I have this one,
  6886. 5:32:52manual deploy. after merging a pull
  6887. 5:32:55request to the to the main branch. I
  6888. 5:32:58come here and run the manual deploy
  6889. 5:33:01because here as you can see we just
  6890. 5:33:03built the front end because we are 100%
  6891. 5:33:06sure that there is no problem with the
  6892. 5:33:07code because it uh it passed all those
  6893. 5:33:10checks. Now I come here I run the job
  6894. 5:33:13and here it notifies me sends an email
  6895. 5:33:15telling me hey do you want to deploy? I
  6896. 5:33:18just click on a button to approve that.
  6897. 5:33:21And as you can see it says deploy and I
  6898. 5:33:23can check the website. This is what we
  6899. 5:33:26want to do. And we don't need to SSH to
  6900. 5:33:29the machine, run commands manually.
  6901. 5:33:31Everything is going to be done for us uh
  6902. 5:33:34in this interface. And what we do is we
  6903. 5:33:38just create a pull request. We check the
  6904. 5:33:40code. And here you have the checks. So
  6905. 5:33:43for example, here it says all 17 checks
  6906. 5:33:46have passed. If that's the case, we
  6907. 5:33:48merge. But if a check fails, it's not
  6908. 5:33:51going to be it's not going to to let me
  6909. 5:33:53merge until I fix it. But for now, let's
  6910. 5:33:56just focus on this branch. It's brand
  6911. 5:33:58new. I haven't set up anything. We are
  6912. 5:34:01going to do this uh together. The first
  6913. 5:34:04thing we want to do is to secure the
  6914. 5:34:06main branch. I also have my code editor.
  6915. 5:34:09Here it is. And as you can see, if I
  6916. 5:34:12click on this icon, it shows me the
  6917. 5:34:15changes that I have here. You can see I
  6918. 5:34:17I can come here uh add this and push.
  6919. 5:34:21Nothing is go no one is going to stop
  6920. 5:34:23me. But what what if I what if I don't
  6921. 5:34:26want that? Let's say that you are
  6922. 5:34:27working with a team of people and you
  6923. 5:34:30want to do a pull request before
  6924. 5:34:32merging. In that case, we want to
  6925. 5:34:34protect this so that you don't push
  6926. 5:34:36domain accidentally. But to fix this, we
  6927. 5:34:39come here, we click on settings. Let me
  6928. 5:34:42zoom in a little bit. Here we click on
  6929. 5:34:45branches and we add a branch rule set.
  6930. 5:34:49Here we need to give the rule set a
  6931. 5:34:51name. Let's call it main branch
  6932. 5:34:54protection. Here it currently it's
  6933. 5:34:57disabled. We want to enable it. Let's
  6934. 5:35:00choose active. Let's scroll to the
  6935. 5:35:03target branches section. Click on add
  6936. 5:35:06target. Let's select include default
  6937. 5:35:10branch. Let's go back to the repository.
  6938. 5:35:13As you can see, my default branch is
  6939. 5:35:15main, but in some cases it could be
  6940. 5:35:17master. That's why here it shows default
  6941. 5:35:20instead of uh main or master. And here
  6942. 5:35:24we have some rules that we can apply.
  6943. 5:35:26You can read through them. And here for
  6944. 5:35:29example, let's scroll down to restrict
  6945. 5:35:33deletions. This will prevent anyone from
  6946. 5:35:36deleting the main branch. That's why we
  6947. 5:35:39want to restrict it. Here we have
  6948. 5:35:41another rule that we need to keep. It
  6949. 5:35:43says block force pushes. This will
  6950. 5:35:46prevent you from writing from using git
  6951. 5:35:49push-force
  6952. 5:35:51because when you use force you rewrite
  6953. 5:35:53history and that can lead to problems
  6954. 5:35:56here. These two are uh checks by
  6955. 5:35:58default. We want to add this third one.
  6956. 5:36:01Require a pull request before merging.
  6957. 5:36:05If you are working with a team, required
  6958. 5:36:08approval should be either one or two. It
  6959. 5:36:10depends on the size of the team. But if
  6960. 5:36:12you are working as a solo developer,
  6961. 5:36:15select keep this at zero. I am I am
  6962. 5:36:18doing it on my other project. Why?
  6963. 5:36:21Because it builds the habit of uh
  6964. 5:36:23creating a branch for each feature you
  6965. 5:36:25work on. And if you here you have to do
  6966. 5:36:28zero because you are the only one who is
  6967. 5:36:30working on this project. And it is very
  6968. 5:36:32helpful. is going to make you think of
  6969. 5:36:36always working with making small
  6970. 5:36:38changes, creating a pull request and
  6971. 5:36:41merge it to main like I do with my other
  6972. 5:36:44projects. We will come back to this uh
  6973. 5:36:47in the upcoming sub chapters because we
  6974. 5:36:50don't want to do everything in this in
  6975. 5:36:51this first video, but we just want to
  6976. 5:36:53get up and running. Now, let's click on
  6977. 5:36:56create. Here it's going to tell you you
  6978. 5:36:58need to sign in. I will do this and I'll
  6979. 5:37:00come back. I am back. You can see it
  6980. 5:37:03says rule set created and here it is and
  6981. 5:37:06it it says applies to one target which
  6982. 5:37:09is the main branch. This is what we want
  6983. 5:37:12to see. Now if I go back to the
  6984. 5:37:15repository you can see that this is our
  6985. 5:37:18main branch. If we click on view all
  6986. 5:37:20branches and here you can see that we
  6987. 5:37:23have we can also view the rules from
  6988. 5:37:25this button. And yeah we have three
  6989. 5:37:28branch rules. That's correct. But let's
  6990. 5:37:30go back to VS Code and let's see if we
  6991. 5:37:32can push something to this codebase from
  6992. 5:37:36main. Here is the repository. Let's make
  6993. 5:37:39some change to this file. I will come
  6994. 5:37:41here and let's just add an empty line.
  6995. 5:37:45You can see that we we have modified the
  6996. 5:37:48file. I will stage it and let's create a
  6997. 5:37:51commit. Get commit- m let's call it
  6998. 5:37:56test. Hit enter. Okay, that worked. But
  6999. 5:37:59now let's try to push this get push. As
  7000. 5:38:03you can see I was not able to do that.
  7001. 5:38:06Let's see what is the error. You can see
  7002. 5:38:08that here it says repository rule
  7003. 5:38:10violations found on the main branch.
  7004. 5:38:14Here it says changes must be made
  7005. 5:38:16through a pull request. This is what we
  7006. 5:38:18want to see. So remote rejected our push
  7007. 5:38:22operation. Amazing. And to undo this
  7008. 5:38:25commit because it was just test, you can
  7009. 5:38:27run git reset add. And here we just want
  7010. 5:38:31to reset the latest commit. Let's do it.
  7011. 5:38:34And as you can see, uh, it was removed.
  7012. 5:38:37And it shows me that this is the last
  7013. 5:38:38modification I made to this file. Great,
  7014. 5:38:41it's working. So, let me just undo this
  7015. 5:38:43because I don't want to make that
  7016. 5:38:45change.
  7017. 5:38:46You have successfully protected the main
  7018. 5:38:49branch. But we still need to check the
  7019. 5:38:52commits that we are pushing. What do I
  7020. 5:38:55mean when I say we need to check
  7021. 5:38:56commits? Sometimes you might be working
  7022. 5:38:59on your project and you might
  7023. 5:39:01accidentally commit let's say a secret
  7024. 5:39:03key. That's that's a problem because
  7025. 5:39:06that will that will sit on the git
  7026. 5:39:08history and everyone can see it unless
  7027. 5:39:11you rotate the key. With something
  7028. 5:39:14called pre-commit, we are able to catch
  7029. 5:39:16this problem before pushing the commit
  7030. 5:39:18to the remote repository. We can do
  7031. 5:39:22other checks. We can check if the
  7032. 5:39:24linting is correct, if the code is
  7033. 5:39:26formatted correctly and other stuff.
  7034. 5:39:29This concept is called get hooks and we
  7035. 5:39:32are going to target pre-commit hook
  7036. 5:39:35specifically. So when you type get
  7037. 5:39:38commit, this hook will intercept uh your
  7038. 5:39:42request. Basically, it's going to see
  7039. 5:39:44what you are what you are committing and
  7040. 5:39:46it's going to run a series of checks and
  7041. 5:39:49you can add uh as many checks as you
  7042. 5:39:52want. If everything passes, great. The
  7043. 5:39:55request will go through and your commit
  7044. 5:39:57will be deployed to the cloud or yeah to
  7045. 5:40:01the cloud repository. But if something
  7046. 5:40:04if a check fails the the hook will going
  7047. 5:40:08to block you unless you fix the problem.
  7048. 5:40:11Okay. So this is what we what we are
  7049. 5:40:12going to do uh now and we are going to
  7050. 5:40:15use this amazing project called
  7051. 5:40:17recommit. Let's go back to VS Code to
  7052. 5:40:20show you how to use this. Here you can
  7053. 5:40:23see that I have some changes made to
  7054. 5:40:26this get ignore. I'll try to stash that
  7055. 5:40:29because I don't need it. Now I need to
  7056. 5:40:33add this specific file
  7057. 5:40:35pre-commit-config.yml.
  7058. 5:40:39Here we are going to add the checks that
  7059. 5:40:41we want to perform. Let's now start with
  7060. 5:40:44the back end. You can see that here we
  7061. 5:40:46don't have any Python code but we will
  7062. 5:40:48add one to test this. Let's just add
  7063. 5:40:51main.py and let's create a a function
  7064. 5:40:56that will print hello world. We can run
  7065. 5:40:59this and it should work. So if we do
  7066. 5:41:03main.py,
  7067. 5:41:05as you can see, we get hello world. We
  7068. 5:41:07are doing this just to test this hook.
  7069. 5:41:10We have two kinds of texts that we can
  7070. 5:41:13use. You have remote repositories and
  7071. 5:41:16you have local custom hooks that you can
  7072. 5:41:19create on your own. For example, here if
  7073. 5:41:22I click on this link, it takes me to
  7074. 5:41:25GitHub. You can see that people who are
  7075. 5:41:28working on rough have created this
  7076. 5:41:31pre-commit that I can just install by
  7077. 5:41:35just putting the link of the repository
  7078. 5:41:38here. So this means when I run install,
  7079. 5:41:41it's going to go to this repository.
  7080. 5:41:44It's going to bring this version. How do
  7081. 5:41:47I know if this is the latest version?
  7082. 5:41:49It's simple. Just go back to the
  7083. 5:41:52repository. Scroll down and here click
  7084. 5:41:55on releases and that will show you the
  7085. 5:41:57latest release. Currently we uh in here
  7086. 5:42:01in rough the latest version is 0.15.12
  7087. 5:42:05and this is exactly what I have
  7088. 5:42:07specified here in this field and here
  7089. 5:42:10you put your hooks what you want to run
  7090. 5:42:13here I have two kind of checks I have a
  7091. 5:42:17linting step and a formatting step.
  7092. 5:42:20Let's focus on the first hook. You can
  7093. 5:42:23see that the ID is rough and I give it a
  7094. 5:42:26name and I specify that I want to
  7095. 5:42:27perform LinkedIn. And here I have I am
  7096. 5:42:30passing additional arguments. And here I
  7097. 5:42:32pass d-fix because sometimes there are
  7098. 5:42:35some some things that we can fix in the
  7099. 5:42:38code. And here I am targeting everything
  7100. 5:42:40inside the backend folder. So let's do
  7101. 5:42:44that. Let's let's create a backend
  7102. 5:42:46folder. And let's drag this file and put
  7103. 5:42:49it there. Otherwise, this hook will not
  7104. 5:42:52find anything. It's going it's going to
  7105. 5:42:53succeed. But we want to target only u
  7106. 5:42:58Python files that are inside the backend
  7107. 5:43:00folder. In the second hook, we are just
  7108. 5:43:02performing formatting. Uh it's simple.
  7109. 5:43:05This file is is good. There is no
  7110. 5:43:07problem in it. Now, if I try to use this
  7111. 5:43:11hook, it's not going to fail. Let's see
  7112. 5:43:13how to install this. You have different
  7113. 5:43:15options of installing it. You can use
  7114. 5:43:17Anaconda, you can use poetry, uv or any
  7115. 5:43:21package manager in Python or you can
  7116. 5:43:24simply use the ven module. Uh let's try
  7117. 5:43:28let's try that. Then ven as you can see
  7118. 5:43:31we have our virtual environment and
  7119. 5:43:34let's activate it. Source van bin
  7120. 5:43:38/activate.
  7121. 5:43:40As you can see here I have van and I am
  7122. 5:43:42using python 3.12 here we need to add
  7123. 5:43:46dot getit ignore so that we don't push
  7124. 5:43:48what we have here and let's put van here
  7125. 5:43:52okay good now we have just three
  7126. 5:43:53modifications now let's install precomit
  7127. 5:43:56to do that make sure that the
  7128. 5:43:58environment is activated and run pip
  7129. 5:44:01install precomit
  7130. 5:44:04great that worked and now we need to run
  7131. 5:44:06precomit install you can see that it
  7132. 5:44:09says pre-commit installed at this
  7133. 5:44:11location. Let's controlclick on this
  7134. 5:44:13file just to see what we have here. You
  7135. 5:44:16can see that this file was autogenerated
  7136. 5:44:18by pre-comit and here we have this
  7137. 5:44:20variable install python that points to
  7138. 5:44:23the virtual environment. The problem
  7139. 5:44:25with this approach is that you can see
  7140. 5:44:27that we have installed precomit on this
  7141. 5:44:31project. So if I move if I delete this
  7142. 5:44:33virtual environment, the pre-commit hook
  7143. 5:44:36will fail. It's not going to find this
  7144. 5:44:38path and it's not going to work. But if
  7145. 5:44:41you stay here, it's going to work
  7146. 5:44:43without any issue. But we have other
  7147. 5:44:45options that we can try to fix this
  7148. 5:44:48problem because ideally we want to
  7149. 5:44:50install pre-commit globally so that we
  7150. 5:44:52can use it in any Python pro in any
  7151. 5:44:55projects not just Python and that way we
  7152. 5:44:58will fix these issues. So using a
  7153. 5:45:01virtual environment is perfectly fine.
  7154. 5:45:03The only issue that you will face is
  7155. 5:45:06when you decide to delete the virtual
  7156. 5:45:08environment. But if you don't then you
  7157. 5:45:11can keep using this or we have another
  7158. 5:45:14option which is to install pre-commit
  7159. 5:45:16globally with pep x. This is another
  7160. 5:45:20python library that we can use and we
  7161. 5:45:22have plenty of options to download it.
  7162. 5:45:25Here I am using because I am on iuntu I
  7163. 5:45:27am using apt to install this from the
  7164. 5:45:30repository. Uh I have already installed
  7165. 5:45:33it. So, it's not going to add anything,
  7166. 5:45:35but I just want you to go to GitHub, you
  7167. 5:45:38will find the pipex there. As you can
  7168. 5:45:40see from the about section, it says
  7169. 5:45:43install and run Python applications in
  7170. 5:45:47isolated environments. And this is what
  7171. 5:45:49we want to do. I am not using the
  7172. 5:45:52regular pip because I don't want to
  7173. 5:45:54install this globally because it's not
  7174. 5:45:57it's a bad idea. That's why we use
  7175. 5:45:59virtual environments. But PEX solved
  7176. 5:46:03this issue for us. And if you scroll
  7177. 5:46:05down a little bit, you can see here in
  7178. 5:46:08the image, it shows you that you can
  7179. 5:46:10install libraries and run them in
  7180. 5:46:13isolation. And you have plenty of
  7181. 5:46:15options to install this here on Linux.
  7182. 5:46:18You can use pip if you want. And uh I
  7183. 5:46:21decided to use apt. But I just want you
  7184. 5:46:24to go here to in to look at your current
  7185. 5:46:27OS to uh get the perfect command for
  7186. 5:46:31your system. After installing pipex, you
  7187. 5:46:34need to run pipex insure path. And
  7188. 5:46:37that's that's the second command here.
  7189. 5:46:40Let's do it. As you can see, it says
  7190. 5:46:42that it already found the path. So
  7191. 5:46:45that's fine. And if you see this
  7192. 5:46:47warning, no problem. uh the the message
  7193. 5:46:50that let tells us that if it is working
  7194. 5:46:52is this otherwise pipex is ready to go.
  7195. 5:46:55If you see this, you are good to go.
  7196. 5:46:57Let's clear the page. And now we run pip
  7197. 5:47:00x install pcomit. As you can see, I have
  7198. 5:47:04already installed it before. That's why
  7199. 5:47:06it didn't work. So it tells me that it
  7200. 5:47:08seems that this library is already
  7201. 5:47:11installed. So that's fine. And as you
  7202. 5:47:13can see here is the location of that
  7203. 5:47:17specific library. Now all we need to do
  7204. 5:47:20is to go back to VS Code. You can see
  7205. 5:47:24that here I have activated this virtual
  7206. 5:47:26environment. Now I need to deactivate.
  7207. 5:47:29Let's type deactivate. Good. The virtual
  7208. 5:47:33environment is is no longer there. And
  7209. 5:47:35we can also delete it because we uh I
  7210. 5:47:38want to show you that this is going to
  7211. 5:47:39work without a virtual environment. You
  7212. 5:47:43can see we have removed that folder. And
  7213. 5:47:46I can also remove the changes from git
  7214. 5:47:49ignore. We need to do the same command
  7215. 5:47:52pre-commit install. I'll hit enter. As
  7216. 5:47:55you can see, this worked. And in this
  7217. 5:47:57file, you can see that the path has
  7218. 5:47:59changed. Now the path is pointing to the
  7219. 5:48:03pipex environments. This is what we
  7220. 5:48:05want. Now, as you can see, I don't have
  7221. 5:48:07a virtual environment. That's fine
  7222. 5:48:09because this is installed globally. Now,
  7223. 5:48:12I can open another project, run
  7224. 5:48:14pre-commit install, and it's going to
  7225. 5:48:17use the same virtual environment. That's
  7226. 5:48:19great. And this solves the issue with
  7227. 5:48:22local virtual environments. Great. Now
  7228. 5:48:24we can continue. First, we need to
  7229. 5:48:27commit this file. This is the first
  7230. 5:48:29operation that we need to do. So, let me
  7231. 5:48:32commit this. I'll click on the commit
  7232. 5:48:34button. Great. It works. The code uh I
  7233. 5:48:38have I have been able to create the
  7234. 5:48:39commit. Nothing has stopped me. Now,
  7235. 5:48:41because we have this specific hook that
  7236. 5:48:44targets Python files, if I try to commit
  7237. 5:48:48this, it this these hooks are going to
  7238. 5:48:51check the file. And I'm going to do this
  7239. 5:48:53in the in the terminal because it's
  7240. 5:48:55going to show us what is happening.
  7241. 5:48:57Okay, let's do get commit dash m and
  7242. 5:49:01let's say test python hooks and let's
  7243. 5:49:06hit enter. As you can see the first
  7244. 5:49:10check passed. So linting was good but
  7245. 5:49:13formatting was not good. So here it says
  7246. 5:49:17failed and we as you can see it says one
  7247. 5:49:20file reformatted and the commit is not
  7248. 5:49:23going to go. The file has been changed
  7249. 5:49:26and as you can see here is the change
  7250. 5:49:27that was made and we are using this to
  7251. 5:49:30make sure that formatting is consistent.
  7252. 5:49:33If you work with a team, you want the
  7253. 5:49:35formatting to stay consistent because
  7254. 5:49:38otherwise it's going to be very hard to
  7255. 5:49:40review put requests because they are
  7256. 5:49:42going to make changes with different
  7257. 5:49:44formatting and and that's not a pleasant
  7258. 5:49:47uh situation to be in. This is why we
  7259. 5:49:49use pre-commit hooks. And as you can
  7260. 5:49:51see, we were not able to push this. And
  7261. 5:49:53if everyone is using the same set of
  7262. 5:49:56rules, it ensures that the code uses the
  7263. 5:50:00same formatting rules and everything
  7264. 5:50:02stays the same. The only thing I need to
  7265. 5:50:04do is to add this again to add the
  7266. 5:50:08modifications. Let's try to commit. And
  7267. 5:50:11voila, it worked. You can see that uh
  7268. 5:50:14both checks have passed and I was able
  7269. 5:50:17to create the commit without any
  7270. 5:50:20problem. As you can see, I can click on
  7271. 5:50:21the button to push these two commits.
  7272. 5:50:24But this is not going to work because I
  7273. 5:50:26am on the main branch. We can test it
  7274. 5:50:29again. It's fun to test stuff like this.
  7275. 5:50:32So, let's do get push. And it was
  7276. 5:50:35rejected. Great. So, this confirms that
  7277. 5:50:37it it's working. Awesome. So, this was
  7278. 5:50:40just an example. But now let's go back
  7279. 5:50:42to my other repository in order to show
  7280. 5:50:45you the pre-commit hook, the pre-commit
  7281. 5:50:48configuration that I have there. It's
  7282. 5:50:51totally different from this one because
  7283. 5:50:53we have JavaScript and Python. Here is
  7284. 5:50:57my other project. And if you remember,
  7285. 5:50:59this is exactly the code that I told you
  7286. 5:51:02to download if you didn't have your own
  7287. 5:51:05projects to work with. And here here is
  7288. 5:51:08my configuration. We have plenty of
  7289. 5:51:10things but you can see that the first
  7290. 5:51:12part is similar to what I have showed
  7291. 5:51:15you in the other project. We are using
  7292. 5:51:18rough and we are we have two hooks one
  7293. 5:51:22for linting and the other one for
  7294. 5:51:24formatting. Let me collapse this because
  7295. 5:51:26we have seen it here. I have another
  7296. 5:51:29repository and this is used for
  7297. 5:51:32JavaScript. Here we are using eslint
  7298. 5:51:35because we want to do linting. We want
  7299. 5:51:37to verify that the syntax in our
  7300. 5:51:40JavaScript code is correct and that
  7301. 5:51:42there are no problems. As you can see
  7302. 5:51:45here, we have just one hook and uh I've
  7303. 5:51:48called it yes link front end. Here I
  7304. 5:51:51have files. It's going to target
  7305. 5:51:53everything inside the front end folder.
  7306. 5:51:57This is a regular expression that will
  7307. 5:52:00target only view and JS files inside the
  7308. 5:52:04front end directory. If I open source
  7309. 5:52:07you can see that here view files end
  7310. 5:52:10with dot view that's why I have it here
  7311. 5:52:13and I also have js here I am not using
  7312. 5:52:16typescript if I was using it I will
  7313. 5:52:18change js to ts so the types that uh I'm
  7314. 5:52:22looking for files and here I also add
  7315. 5:52:25arguments so that I can fix problems if
  7316. 5:52:28I find them and I also point the conf to
  7317. 5:52:31the configuration file because yes lint
  7318. 5:52:33can be configured and here is a
  7319. 5:52:35configuration file. So here if you want
  7320. 5:52:38to disable some rules, you can uh come
  7321. 5:52:40here and modify the rules that uh you
  7322. 5:52:44want your hook to check for uh or to
  7323. 5:52:48skip in this case. And here I have
  7324. 5:52:50additional dependencies. These are these
  7325. 5:52:53will change. It depends on the project
  7326. 5:52:55that you are working on. If you aren't
  7327. 5:52:57working with Vue, you won't you won't
  7328. 5:52:59add this. So yeah, these are just
  7329. 5:53:01additional dependencies that will be
  7330. 5:53:02installed in order to run this hook. So
  7331. 5:53:05this is the front end part and we also
  7332. 5:53:08have some local repositories or local
  7333. 5:53:11hooks that we create on ourselves. This
  7334. 5:53:14is what why I mentioned before that you
  7335. 5:53:17can use either hooks created by the
  7336. 5:53:20community or use your own. For example,
  7337. 5:53:23here I have two local ones and here I
  7338. 5:53:26will you can see that I I call this one
  7339. 5:53:28prettier because with prettier I can
  7340. 5:53:30check many files. I can check JS view,
  7341. 5:53:34CSS and other file extensions and uh
  7342. 5:53:37same if I detect that some format
  7343. 5:53:40something is not formatted well I I add
  7344. 5:53:43the dash dash write to change the file
  7345. 5:53:46and uh after that I can just come here
  7346. 5:53:48and add click on the plus button to
  7347. 5:53:51accept the change and finally I have
  7348. 5:53:53this other hook that will automatically
  7349. 5:53:56generate the site map for my website and
  7350. 5:53:59this will run whenever I commit and here
  7351. 5:54:01you can see that I just have a simple
  7352. 5:54:03bash script. I go inside the front end,
  7353. 5:54:06run the sitemap. So this is a script
  7354. 5:54:09that I have and it's going to generate
  7355. 5:54:11this XML file that I will stage. Using
  7356. 5:54:15pre-commit is really easy and it helps
  7357. 5:54:18you catch a lot of problems locally in
  7358. 5:54:22before deploying or publishing the the
  7359. 5:54:25code changes. And we can also do a
  7360. 5:54:28simple test here. Let's let's open app
  7361. 5:54:31doview view and let me add some spaces
  7362. 5:54:34some new lines here that will trigger
  7363. 5:54:37prettier and it's going to block this
  7364. 5:54:38operation. Let me open my terminal and
  7365. 5:54:41let's check the status just to confirm
  7366. 5:54:44that everything is all right. Let's add
  7367. 5:54:47this. Okay, now we can write the commit
  7368. 5:54:50message. Let's say uh let's hit enter.
  7369. 5:54:56As you can see that works here. rough is
  7370. 5:54:59not failing. It is skipped because we
  7371. 5:55:01haven't changed anything uh in the back
  7372. 5:55:03end but uh we have changed something in
  7373. 5:55:07the front end directory. Yes, lint
  7374. 5:55:09worked. That's not a problem. But
  7375. 5:55:11prettier didn't like the changes that we
  7376. 5:55:13have made. And because we have set
  7377. 5:55:16rights, you can see that it changed the
  7378. 5:55:17file. So, it removed those new lines for
  7379. 5:55:20us. That's great because I can just come
  7380. 5:55:22here verify the new changes and click on
  7381. 5:55:25add. And yeah, I can come let me also
  7382. 5:55:30you can see that sitemap was generated
  7383. 5:55:32for us automatically. That's good. I can
  7384. 5:55:36come back and uh run it. And as you can
  7385. 5:55:38see this time it worked because we fixed
  7386. 5:55:41all the issues. And that's it for this
  7387. 5:55:44video. Your local environment is now
  7388. 5:55:46fully secure. You have protected the
  7389. 5:55:49main branch and you have created
  7390. 5:55:52pre-commit hooks to check commits before
  7391. 5:55:56pushing them. In the next sub chapter,
  7392. 5:55:59we are going to talk about continuous
  7393. 5:56:02integration. We are going to perform
  7394. 5:56:04automation using GitHub actions that
  7395. 5:56:07will allow us to write workflows that we
  7396. 5:56:10can that we can run after let's say
  7397. 5:56:14creating a pull request that will allow
  7398. 5:56:16you to do something similar to what I
  7399. 5:56:18have here. You can define your jobs and
  7400. 5:56:23uh put them in a pipeline that will run
  7401. 5:56:26uh automatically and if everything
  7402. 5:56:27succeeds you can merge your pull
  7403. 5:56:29request. This is going to take us a lot
  7404. 5:56:32of time to develop. But I'll try to go
  7405. 5:56:34uh step by step. I'll try to go slowly
  7406. 5:56:37so that you can understand everything.
  7407. 5:56:39Uh once you understand this, once you
  7408. 5:56:41make one or two jobs, then the rest is
  7409. 5:56:43going to be repetitive. You will uh then
  7410. 5:56:46you will know how to add uh anything.
  7411. 5:56:48And you might be asking, do I need to
  7412. 5:56:51follow a specific rule? You can. No, you
  7413. 5:56:54can design this however you like. Just
  7414. 5:56:57make sure that you catch the things that
  7415. 5:56:59you want to focus on. For example, if
  7416. 5:57:01you want to do security, you need to add
  7417. 5:57:03some jobs that will test if your app is
  7418. 5:57:06secure. If you want to check LinkedIn
  7419. 5:57:08and formatting, you need to add jobs
  7420. 5:57:09that will check that. So each job is
  7421. 5:57:12going to check one thing for you. And by
  7422. 5:57:14building uh the these sets of jobs, you
  7423. 5:57:17will ensure that uh the code that you
  7424. 5:57:20push to production is secure. Uh there
  7425. 5:57:23are and there are no bugs no bugs in it.
  7426. 5:57:26See you in the next video. Welcome back.
  7427. 5:57:29In this video we are going to talk about
  7428. 5:57:32continuous integration. In the previous
  7429. 5:57:35video you have seen how to perform
  7430. 5:57:38checks locally to stop bugs or
  7431. 5:57:42unformatted code from being synced with
  7432. 5:57:46the remote repository. Today we are
  7433. 5:57:49going to do the same thing but on GitHub
  7434. 5:57:52or you can do the same thing on GitLab
  7435. 5:57:54or other platforms. The same concept
  7436. 5:57:57applies but there are some uh things
  7437. 5:57:59that might change from platform to
  7438. 5:58:01platform. Here is what we are going to
  7439. 5:58:03talk about in this video. We are going
  7440. 5:58:06to learn about continuous integration.
  7441. 5:58:08You are going to build modular and
  7442. 5:58:11reusable workflows to automate linting
  7443. 5:58:15formatting and to perform unit tests.
  7444. 5:58:19And of course, we want to block bad code
  7445. 5:58:21from being merged to the main branch by
  7446. 5:58:25using GitHub status checks. In this
  7447. 5:58:28session, we are going to build a small
  7448. 5:58:30pipeline that will do the following. You
  7449. 5:58:34can see that here. This is specific to
  7450. 5:58:36GitHub but you can find the same concept
  7451. 5:58:39on GitLab also or other platforms. Here
  7452. 5:58:42we have five jobs. You can see that we
  7453. 5:58:45have two jobs that we run to test the
  7454. 5:58:49back end and we have the same that but
  7455. 5:58:52for the front end. The first step is to
  7456. 5:58:55perform linting and formatting and after
  7457. 5:58:58that we perform unit tests. And you can
  7458. 5:59:01see by default GitHub will run jobs in
  7459. 5:59:05parallel but some jobs can depend on
  7460. 5:59:08each other. For example, before I run
  7461. 5:59:11the unit tests in the back end, I need
  7462. 5:59:14to make sure that there is no syntax
  7463. 5:59:16error and the code is formatted
  7464. 5:59:18correctly. If this is not the case, this
  7465. 5:59:21job will be skipped. It's not going to
  7466. 5:59:23run. The same the same goes for the
  7467. 5:59:25front end. Finally, we have this
  7468. 5:59:27pipeline success which is going to be
  7469. 5:59:30used to allow us to merge the pull
  7470. 5:59:35request or to uh block it. You can see
  7471. 5:59:38that in this case everything passed that
  7472. 5:59:40mean that's why I get a green check mark
  7473. 5:59:43which means that I can merge this pull
  7474. 5:59:46request. If let's say the lint failed
  7475. 5:59:48this is going to turn red and it's going
  7476. 5:59:50to block the mer the pull request. We
  7477. 5:59:52will keep adding more jobs to this
  7478. 5:59:54pipeline in the upcoming videos. But for
  7479. 5:59:57now, let's just start with these two.
  7480. 5:59:59This is what we have performed locally
  7481. 6:00:01in the previous video. But on top of
  7482. 6:00:03that, we are going to add unit tests. I
  7483. 6:00:06am now on GitHub and I I switched to my
  7484. 6:00:10secondary account. Here I have forked
  7485. 6:00:13the source code that we used to deploy
  7486. 6:00:17the website on digital ocean because I
  7487. 6:00:20wanted to experiment here uh without any
  7488. 6:00:23problem. So I have forked this and now I
  7489. 6:00:25will create I've already created a pull
  7490. 6:00:28request but we will start from scratch
  7491. 6:00:30and I will show you how this works and
  7492. 6:00:33how to build a GitHub action. First
  7493. 6:00:37let's start by creating a branch. Here
  7494. 6:00:40we are using VS code. I will just click
  7495. 6:00:43on this button that will allow me to
  7496. 6:00:47create a new branch from a specific
  7497. 6:00:50branch. And here I am creating it from
  7498. 6:00:52master. I will call this test number
  7499. 6:00:55two. I will hit enter and I will select
  7500. 6:00:58head. I will switch to that branch
  7501. 6:01:01because remember the master branch is
  7502. 6:01:04protected. I cannot push directly to
  7503. 6:01:08that branch. If you are using GitHub,
  7504. 6:01:10you start by creating agitub
  7505. 6:01:14folder. You can see I already have it
  7506. 6:01:16here and we have plenty of things. But
  7507. 6:01:19to create a pipeline, we put our
  7508. 6:01:21workflows inside the workflows folder.
  7509. 6:01:25Let's open it. You can see that I have a
  7510. 6:01:28lot of things. Don't worry about these.
  7511. 6:01:30Don't worry about this. Uh what you are
  7512. 6:01:32seeing here is the final product. Uh we
  7513. 6:01:35are going to build these step by step.
  7514. 6:01:38I'll go through these and remove them
  7515. 6:01:40and I will keep just the ones that we
  7516. 6:01:41need for this video. I am back. As you
  7517. 6:01:44can see, I have removed a lot of files
  7518. 6:01:47and let's start by working on linting
  7519. 6:01:49and formatting in the back end. If you
  7520. 6:01:51want to learn more about this, you can
  7521. 6:01:54search GitHub actions. As you can see,
  7522. 6:01:57you can search GitHub actions and you'll
  7523. 6:01:59find you will find them here. Their
  7524. 6:02:02documentation is great. So if you want
  7525. 6:02:05to dive deeper, you can use this or you
  7526. 6:02:08can just take the documentation and uh
  7527. 6:02:12use that with your preferred large
  7528. 6:02:14language model and they will help you uh
  7529. 6:02:16understand the concept. But I'll try to
  7530. 6:02:18also do my best to explain to you how
  7531. 6:02:20this works. Our goal is to build a
  7532. 6:02:24modular and robust pipeline. Which means
  7533. 6:02:27that we want each job to be contained in
  7534. 6:02:30its own file. And we call these reusable
  7535. 6:02:34workflows. For example, here I am
  7536. 6:02:37hovering over the backend lint and
  7537. 6:02:39format. This is going to be one file
  7538. 6:02:42which is this one. The code that we will
  7539. 6:02:45put here will run at this step. And
  7540. 6:02:48after that this file ci will be the
  7541. 6:02:52orchestrator. It's going to call these
  7542. 6:02:54uh workflows independently one after the
  7543. 6:02:57other. And we don't want to put
  7544. 6:02:58everything inside one giant file because
  7545. 6:03:02if you get an error, it's going to be
  7546. 6:03:04very hard to debug. But by putting
  7547. 6:03:07everything inside a its own file, it's
  7548. 6:03:11going to make life easier and you will
  7549. 6:03:13see how the the orchestrator is going to
  7550. 6:03:16be very minimal. It's going to be very
  7551. 6:03:18easy to read and debugging is also going
  7552. 6:03:20to be fun. To create a workflow, you
  7553. 6:03:23start by giving it a name. Here you can
  7554. 6:03:26put anything and it's going to be easier
  7555. 6:03:28for you to locate. For example, if we
  7556. 6:03:32let me go back to GitHub, you can see
  7557. 6:03:35that here we have this actions tab. If I
  7558. 6:03:38click on it, uh you can see that we have
  7559. 6:03:40plenty of workflows and you can see that
  7560. 6:03:42they're named uh they are named. Let's
  7561. 6:03:44look at this one. You can see that it's
  7562. 6:03:46called backend lint and format. Let's go
  7563. 6:03:50back to GitHub and we we find it here.
  7564. 6:03:53back end lint and format. You can click
  7565. 6:03:56on it, you will see the how many times
  7566. 6:03:58it we run it, etc. Uh, okay. And
  7567. 6:04:02sometimes you can even run them manually
  7568. 6:04:04if you want to. Let's look at the
  7569. 6:04:05workflow or the orchestrator. You can
  7570. 6:04:08see that I can come here and run it
  7571. 6:04:10manually if I want to. We will I will
  7572. 6:04:12show you how to implement that. But this
  7573. 6:04:14is why we give them names so that it
  7574. 6:04:16becomes easier for us to uh find them
  7575. 6:04:19here in the actions tab. After that we
  7576. 6:04:22add the onb block and here we specify
  7577. 6:04:26workflow call. This tells GitHub that
  7578. 6:04:30this file is a reusable template not a
  7579. 6:04:34standalone script which means we cannot
  7580. 6:04:35run it on its own. We need to call it
  7581. 6:04:38from the orchestrator. After that we
  7582. 6:04:41create a series of jobs that we want to
  7583. 6:04:43run inside this specific workflow. And
  7584. 6:04:47here we want to perform just lint and
  7585. 6:04:49formatting. That's why we you can see
  7586. 6:04:52that here we have jobs and here you can
  7587. 6:04:54specify your jobs and here we are going
  7588. 6:04:56to run one one specific job. We are not
  7589. 6:04:59going to run more than that. Inside the
  7590. 6:05:02lint and format job we can also give it
  7591. 6:05:06a name and runs on is very important.
  7592. 6:05:09Here you can choose different operating
  7593. 6:05:11systems. Here I am using iuntu and
  7594. 6:05:14latest will take the la the the recent
  7595. 6:05:18version of Ubuntu. Why are we doing
  7596. 6:05:20this? Because remember we are going to
  7597. 6:05:22run this on the cloud. It's not going
  7598. 6:05:25the these checks are going to be
  7599. 6:05:27executed on GitHub's own machines.
  7600. 6:05:31That's why we need to specify a an
  7601. 6:05:34operating system. After that we add
  7602. 6:05:37defaults run and we specify the working
  7603. 6:05:40directory. We are doing this to make our
  7604. 6:05:42life easier because if we don't add this
  7605. 6:05:45we have to always type cd back end
  7606. 6:05:49whenever if we want to perform if you
  7607. 6:05:51want to perform something inside the
  7608. 6:05:53backend folder we need to always do that
  7609. 6:05:56but by putting this GitHub will
  7610. 6:05:58automatically move us to the backend
  7611. 6:06:01folder and we can run the commands
  7612. 6:06:03without always repeating cd space back
  7613. 6:06:07end and finally we put the steps A job
  7614. 6:06:11is a series of steps and here you can
  7615. 6:06:14you see the the template is the same.
  7616. 6:06:16Everything has a name. You can see that
  7617. 6:06:18here we have name checkout repository.
  7618. 6:06:22This is going to be very helpful. If you
  7619. 6:06:25go to your pipeline if you click on this
  7620. 6:06:29backend lint and format you see here are
  7621. 6:06:31the steps and let me split the screen
  7622. 6:06:34and let's look at let's look at this.
  7623. 6:06:36You can see that here we have checkout
  7624. 6:06:39repository. This is exactly the name
  7625. 6:06:41that I have here. Here we have setup
  7626. 6:06:43Python. We also find this here. And why
  7627. 6:06:46is this important? Because let's say
  7628. 6:06:47that this step has failed. You can
  7629. 6:06:50quickly go back to your YAML file and
  7630. 6:06:54find that specific step. It's going to
  7631. 6:06:56make your it's going to make debugging
  7632. 6:06:59very easy. And as you can see, each step
  7633. 6:07:01is going to run. And here they're going
  7634. 6:07:03to run sequentially one after the other.
  7635. 6:07:05And if a step failed, the other ones are
  7636. 6:07:08going to be skipped. So let's look at
  7637. 6:07:10what we have here in this specific job.
  7638. 6:07:13First we need to check out the
  7639. 6:07:14repository. Because we are running on a
  7640. 6:07:17virtual machine, we need to download the
  7641. 6:07:21source code. And here we have something
  7642. 6:07:24that we call actions. You can see that
  7643. 6:07:26here we have two different keywords that
  7644. 6:07:29we are using. Here we have users and
  7645. 6:07:31down below we have run. Basically this
  7646. 6:07:34keyword is going to use scripts that the
  7647. 6:07:38community has made. Let me show you what
  7648. 6:07:41I am talking about. If I copy this name
  7649. 6:07:44and search for it, let's see what we are
  7650. 6:07:47going to get. You will find that there
  7651. 6:07:49is a repository that contains the code
  7652. 6:07:52for that specific action that we want to
  7653. 6:07:54run. And uh you can see that here here
  7654. 6:07:56is here it is actions/checkout.
  7655. 6:08:00If I go back, it's the same name. and
  7656. 6:08:03let's verify the version. How do we do
  7657. 6:08:05that? It's simple. You click on the
  7658. 6:08:07releases page and here you find the
  7659. 6:08:10versions. So the latest version is 6.0.2
  7660. 6:08:14but I am using version 6. And this is
  7661. 6:08:17important because sometimes these
  7662. 6:08:19actions change and uh if they introduce
  7663. 6:08:22breaking changes you can read more about
  7664. 6:08:25them here on GitHub. But if you use run
  7665. 6:08:28this means you will provide uh commands
  7666. 6:08:32that the uh that Ubuntu will run. This
  7667. 6:08:36is the difference between users and run.
  7668. 6:08:38Okay. So when I do this, let's look at
  7669. 6:08:41here on uh this job. Let's open this.
  7670. 6:08:45You can see that we this action has been
  7671. 6:08:48executed and now it is syncing the
  7672. 6:08:50repository. And yeah, you can open this
  7673. 6:08:53and read more about this. You can see
  7674. 6:08:55that they are initializing the
  7675. 6:08:56repository and fetching the repository.
  7676. 6:08:59This is what we want to see. After this
  7677. 6:09:02step, the source code is on this Ubuntu
  7678. 6:09:04machine. And now we can run commands in
  7679. 6:09:06it. Setup python is going to download
  7680. 6:09:09Python for us. And uh let's uh let's see
  7681. 6:09:13here. We install rough. You can see that
  7682. 6:09:15we use pip to install that library. And
  7683. 6:09:18it worked. After that, we run the
  7684. 6:09:21llinter and formatter. We can see that
  7685. 6:09:24everything is great. Every there is no
  7686. 6:09:26problem. And here these are jobs that
  7687. 6:09:30GitHub will run. We can see that we
  7688. 6:09:32don't have these uh post setup Python.
  7689. 6:09:34It's not here. But the this these are
  7690. 6:09:36just steps that are uh run to clean the
  7691. 6:09:40machine because we are done with it and
  7692. 6:09:42uh there is no need to keep this there.
  7693. 6:09:45And you might be wondering how many
  7694. 6:09:47steps do I need to put here. You can put
  7695. 6:09:50as many steps as you want. Uh you feel
  7696. 6:09:52free to customize your jobs however you
  7697. 6:09:56like and um yeah there is no constraint
  7698. 6:09:59know the difference between users and
  7699. 6:10:01run and sometimes it's going it's easier
  7700. 6:10:03to just use pre-made scripts. Uh so for
  7701. 6:10:08example here if we wanted to install if
  7702. 6:10:10we wanted to use rough you can we can
  7703. 6:10:14search for it and uh use it maybe
  7704. 6:10:16instead of doing all these steps. Uh
  7705. 6:10:19let's do this just uh to show you how
  7706. 6:10:22how to search this. So you type rough
  7707. 6:10:25GitHub action and you search for it. As
  7708. 6:10:28you can see there is one. So instead of
  7709. 6:10:30repeating instead of doing these these
  7710. 6:10:33steps manually we can reuse this rough
  7711. 6:10:36action and that will make our life
  7712. 6:10:38easier. It depends sometimes you might
  7713. 6:10:41you don't find actions for the specific
  7714. 6:10:44uh library that you are using. In that
  7715. 6:10:46case you you use uh this approach and
  7716. 6:10:50here I wanted to show you both so that
  7717. 6:10:52you so that you don't get stuck if you
  7718. 6:10:54don't find a a an action for a specific
  7719. 6:10:58library that you are using. We have
  7720. 6:11:00spent a lot of time in this specific
  7721. 6:11:04file. So now let's go through the other
  7722. 6:11:06steps quickly and let's see the
  7723. 6:11:09difference between the back end and
  7724. 6:11:11front end. Okay. Now let me go back to
  7725. 6:11:14the CI pipeline. uh let's click on it
  7726. 6:11:16again and let this time let's focus on
  7727. 6:11:19uh linting and formatting the front end
  7728. 6:11:22and here I will also open that file here
  7729. 6:11:24it is front end lint and format okay
  7730. 6:11:27let's see what we have here uh we start
  7731. 6:11:30same as before we define the name and uh
  7732. 6:11:33here we use workflow call to let GitHub
  7733. 6:11:36know that this is a reusable template
  7734. 6:11:39and here we have again just one job here
  7735. 6:11:42let's see this time the working
  7736. 6:11:44directory is front end. We are using
  7737. 6:11:47checkout. And here we use, as you can
  7738. 6:11:50see, this time we didn't install PMP
  7739. 6:11:53manually, but we used an an action that
  7740. 6:11:57we can find on GitHub. And we specify
  7741. 6:12:00that we want to install PNPM version 10.
  7742. 6:12:03But same thing with node, we are using
  7743. 6:12:07an action to install node and we target
  7744. 6:12:10this specific version. And here I forgot
  7745. 6:12:13to talk about caching. We are doing that
  7746. 6:12:16here. And on pi the the python side you
  7747. 6:12:21can see that here we also cache pip. Why
  7748. 6:12:23are we using caching? Basically if your
  7749. 6:12:26dependencies don't change you don't need
  7750. 6:12:29to download them every single time. So
  7751. 6:12:31caching will make sure to save uh the
  7752. 6:12:35dependencies so that uh the next job
  7753. 6:12:38will just read them instead of
  7754. 6:12:39downloading them each time. This is
  7755. 6:12:41going to make your pipeline faster and
  7756. 6:12:44it's uh yeah it's great uh it's a great
  7757. 6:12:46thing to add. After that we install the
  7758. 6:12:49dependencies. We run eslint to lint the
  7759. 6:12:53frontend files and we use prettier for
  7760. 6:12:56formatting and uh as you can see we have
  7761. 6:12:59the these steps are are shown here on
  7762. 6:13:02GitHub. Here we have check out
  7763. 6:13:04repository, set up pmppm and nodejs, you
  7764. 6:13:09install the dependencies and you run the
  7765. 6:13:12linting and formatting steps. Great. Uh
  7766. 6:13:15these are the two things that we have
  7767. 6:13:17done in the previous video. We did them
  7768. 6:13:20locally um before accepting the commit
  7769. 6:13:24and now we replicated them here on
  7770. 6:13:27GitHub using GitHub actions. Now we are
  7771. 6:13:30going to add one more job. uh we are
  7772. 6:13:33going to perform unit testing and let me
  7773. 6:13:36show you how that looks like. Let's open
  7774. 6:13:38backend unit tests. It's going to be uh
  7775. 6:13:41similar but uh we will change some steps
  7776. 6:13:44and I want to emphasize that in this
  7777. 6:13:47course I am not going to show you how to
  7778. 6:13:49write unit tests because this is outside
  7779. 6:13:52our scope. If you want to do this that
  7780. 6:13:54will that will take a lot of time and it
  7781. 6:13:57depends on what programming language we
  7782. 6:13:59are using. So we are going to consider
  7783. 6:14:02that as a blackbox. And if you are using
  7784. 6:14:05let's say go or another backend language
  7785. 6:14:09you can swap the commands that I have
  7786. 6:14:11here with the ones that are appropriate
  7787. 6:14:14for the specific stack that you are
  7788. 6:14:16using. Okay. So let's get started. Here
  7789. 6:14:20the name is backend unit tests. And here
  7790. 6:14:24we have again one job which I called
  7791. 6:14:27tests. Let's go inside. First, we
  7792. 6:14:30download the source code. We set up
  7793. 6:14:32Python. We install the dependencies. And
  7794. 6:14:35here we run the unit tests. Okay. And
  7795. 6:14:39let's look. You can see that here we are
  7796. 6:14:41using piest. This is the library that
  7797. 6:14:45that we are using to test our backend
  7798. 6:14:47code. And after that, this is not
  7799. 6:14:49important. Basically, here we are using
  7800. 6:14:51code coverage. Why? So that we can see
  7801. 6:14:54the code coverage. You can see that here
  7802. 6:14:57in the readme I showed that okay uh the
  7803. 6:15:00tests cover 95% of the back end and 85%
  7804. 6:15:04of the front end and uh yeah you if you
  7805. 6:15:07want you can add that and for that we
  7806. 6:15:09use the code coverage package or yeah
  7807. 6:15:13you can search for it code cover this is
  7808. 6:15:16the the service that we are using they
  7809. 6:15:18have a free plan that uh that you can
  7810. 6:15:21benefit from okay and so this step is
  7811. 6:15:24not important but what we have here is
  7812. 6:15:27is what we need. Yeah, it's it's the
  7813. 6:15:29same. So, if I open this and look at run
  7814. 6:15:32unit tests, you can see that here are
  7815. 6:15:35the tests that we have. The everything
  7816. 6:15:38went well. So, uh so we have 9 59 tests
  7817. 6:15:42and they all pass without any problem.
  7818. 6:15:45But if let's if one of them failed, this
  7819. 6:15:47step is going to fail which means that
  7820. 6:15:50this pipeline will not succeed. And we
  7821. 6:15:52are doing the same thing uh in the front
  7822. 6:15:55end. Let's open that front end unit
  7823. 6:15:58tests. Let's go down. So here after
  7824. 6:16:00installing the dependencies we have this
  7825. 6:16:04test script and on in the front end we
  7826. 6:16:08put those in the in your package.json
  7827. 6:16:11file. So here in this scripts object you
  7828. 6:16:16let's find test. Here it is. We are
  7829. 6:16:18using v test for that and we have other
  7830. 6:16:21commands. So if you want to run end to
  7831. 6:16:23end tests, we are going to look at this
  7832. 6:16:25in the upcoming tutorials. But for now,
  7833. 6:16:28we just run unit tests. And again, we
  7834. 6:16:31use code coverage to get the code
  7835. 6:16:34coverage for the front end. Great. So
  7836. 6:16:36now we created these four individual
  7837. 6:16:39components. Now let's see how to put
  7838. 6:16:41them in CI.YAML
  7839. 6:16:44so that they run so that it orchestrates
  7840. 6:16:47all of them. Here is CI.YML. I have
  7841. 6:16:50removed uh some stuff so that um yeah so
  7842. 6:16:53that you don't get overwhelmed. First
  7843. 6:16:55the name is CI pipeline and here we have
  7844. 6:16:59something different. So here we put on
  7845. 6:17:02push on pull request and on workflow
  7846. 6:17:05dispatch. Let's start with this one. So
  7847. 6:17:08on push will run this pipeline whenever
  7848. 6:17:11we push something to the master branch.
  7849. 6:17:13We will also run it if we create a pull
  7850. 6:17:16request that targets the master branch.
  7851. 6:17:19This is what I have here. If I click on
  7852. 6:17:22pull requests. Let's look at this one.
  7853. 6:17:24It is targeting the master branch which
  7854. 6:17:27means it's going to trigger this
  7855. 6:17:29workflow to run. If I scroll down, uh
  7856. 6:17:32you can see that I have the workflow
  7857. 6:17:34here. Here I have my four steps and you
  7858. 6:17:38can see I cannot merge because we have
  7859. 6:17:41some failures. Some jobs have failed.
  7860. 6:17:43And finally we have workflow dispatch.
  7861. 6:17:46and workflow dispatch allows us to look
  7862. 6:17:50at the workflows. Let's look at CI
  7863. 6:17:52pipeline. And I can come here and run it
  7864. 6:17:55from this page. This is useful
  7865. 6:17:59especially if you want to uh if
  7866. 6:18:01something failed and you want to rerun
  7867. 6:18:04the job manually, you can do it from
  7868. 6:18:07this uh page. Let's start with the front
  7869. 6:18:10end link format check. First we give it
  7870. 6:18:13a name and here users. This time we
  7871. 6:18:16already have a workflow. We are going to
  7872. 6:18:19reuse it here. And as you can see now it
  7873. 6:18:21looks clean. Imagine taking all all
  7874. 6:18:24everything inside this file and putting
  7875. 6:18:26it here. And then do the same thing for
  7876. 6:18:29these three. This file will be very
  7877. 6:18:31long. Debugging. If you get a problem
  7878. 6:18:34here uh in your workflow, it's going to
  7879. 6:18:37be challenging to read the whole file,
  7880. 6:18:41find the bug, and solve it. But now it
  7881. 6:18:44looks clean. I just use this keyword to
  7882. 6:18:47let GitHub know that the implementation
  7883. 6:18:49is inside this specific file. And I do
  7884. 6:18:54the same thing for backend lind, front
  7885. 6:18:56end unit tests, and backend unit tests.
  7886. 6:18:59The only thing that that we changed here
  7887. 6:19:02is that we added the needs keyword. Why
  7888. 6:19:05did we do that? Let's go back again to
  7889. 6:19:08the pipeline. Let's collapse these two
  7890. 6:19:11and let's look at just uh let's look at
  7891. 6:19:14just these two jobs. By default, GitHub
  7892. 6:19:18will run your jobs in parallel. Here we
  7893. 6:19:21are performing linting and formatting in
  7894. 6:19:23the front end and back end. And because
  7895. 6:19:25these jobs are independent, we allow
  7896. 6:19:28GitHub to run them in parallel. But if I
  7897. 6:19:31want to run unit tests, I need to ensure
  7898. 6:19:33that the code is clean. There is no
  7899. 6:19:35syntax error. There is no problem in the
  7900. 6:19:37code. If that's the case, I can run
  7901. 6:19:39this. So if you have a dependency, you
  7902. 6:19:42add the needs keyword. So this job needs
  7903. 6:19:46front end lint format check to succeed.
  7904. 6:19:50And this creates this dependency which
  7905. 6:19:52will force GitHub to run them in
  7906. 6:19:54sequence. We do the same thing for
  7907. 6:19:56backend. It's going to wait for backend
  7908. 6:19:59lint format check. If backend lint
  7909. 6:20:02format fails, this job will not run.
  7910. 6:20:05GitHub will skip it. And finally, we
  7911. 6:20:07have pipeline success. For the pipeline
  7912. 6:20:10to succeed, we want every job to
  7913. 6:20:13succeed. Okay, that's why we put
  7914. 6:20:15everything here. again runs on Abuntu
  7915. 6:20:18latest and if always is important
  7916. 6:20:21because if something failed we want to
  7917. 6:20:24run this anyways we don't want to skip
  7918. 6:20:26it because this is what's going to give
  7919. 6:20:28us that status at the end the status is
  7920. 6:20:32going to be either uh success or failure
  7921. 6:20:35let's look at steps because this is
  7922. 6:20:37where we have that logic let me expand
  7923. 6:20:40this page so that we can see this better
  7924. 6:20:43and let me also decrease the font size
  7925. 6:20:45First here we have two steps. The
  7926. 6:20:48pipeline can either succeed or fail. How
  7927. 6:20:52do we know if that's the case? We use
  7928. 6:20:55this function contains and here needs so
  7929. 6:21:00this variable result is going to give us
  7930. 6:21:02the results for all these jobs. This
  7931. 6:21:06condition will check if we don't have
  7932. 6:21:08any failures and if no job has been
  7933. 6:21:11cancelled we will show check all checks
  7934. 6:21:14passed successfully. But if we find a
  7935. 6:21:18failure or something has been cancelled
  7936. 6:21:21we will show some checks failed or were
  7937. 6:21:24cancelled and we exit with number one.
  7938. 6:21:28When we exit with one, we tell the
  7939. 6:21:30runner that there was an issue and
  7940. 6:21:33GitHub will display a uh let me show
  7941. 6:21:36you. It's going to tell you that yeah
  7942. 6:21:38that the test has failed. We can compare
  7943. 6:21:41both of these tests to uh understand
  7944. 6:21:44what's happening here. So the first test
  7945. 6:21:47you can see it shows us it is showing us
  7946. 6:21:50a failure. Why? because that specific uh
  7947. 6:21:55condition this one contains failure is
  7948. 6:21:59true. Why? Because we have one failure
  7949. 6:22:01here. It is and this one was skipped
  7950. 6:22:03that this will make pipeline success
  7951. 6:22:06exit with one and the pipeline has
  7952. 6:22:10failed. So it's which means that I won't
  7953. 6:22:12be able to merge. But in this other
  7954. 6:22:15case, you can see that it succeeded
  7955. 6:22:17because um there is no failure and
  7956. 6:22:20nothing has been skipped. Great. And now
  7957. 6:22:22if I save this, you can see that we have
  7958. 6:22:25we are in this branch and uh push the
  7959. 6:22:28code, we will we will see that this will
  7960. 6:22:31run. Okay. Now let me remove the
  7961. 6:22:34splitting to give us some room to play
  7962. 6:22:36with. Let's push all of this. Uh let's
  7963. 6:22:39just type test because we are we are not
  7964. 6:22:42doing something serious now. And but
  7965. 6:22:44remember to type uh good com commit
  7966. 6:22:47messages. I'll commit and push. Let's go
  7967. 6:22:51back to GitHub. You can see that we have
  7968. 6:22:53this new branch. And uh let's click on
  7969. 6:22:56new pull requests. And here I don't want
  7970. 6:22:59to merge with the upstream repository. I
  7971. 6:23:02want to merge with my fork. And uh let's
  7972. 6:23:06see. So I want to merge with the master.
  7973. 6:23:08But here I need to select test number
  7974. 6:23:11two. Okay. Okay, it shows me these are
  7975. 6:23:13the changes that I have made. Click on
  7976. 6:23:15create pull request. Let's keep
  7977. 6:23:17everything like that and hit create pull
  7978. 6:23:20request. Okay, let's scroll down and as
  7979. 6:23:23you can see here are the checks. But
  7980. 6:23:25notice that we have a problem. I can
  7981. 6:23:27this button uh it's it's not grayed out
  7982. 6:23:30like it is still active that which means
  7983. 6:23:33I can still click on it. That's a
  7984. 6:23:36problem and I am going to show you why.
  7985. 6:23:39Because we are here we are not waiting
  7986. 6:23:42for the final stage to finish which is
  7987. 6:23:46pipeline success. But the solution is
  7988. 6:23:50easy. Let's go to settings and we need
  7989. 6:23:53to update the rule sets. This is the
  7990. 6:23:56rule that we created before. Open it.
  7991. 6:23:59Scroll down and here uh make sure to
  7992. 6:24:02activate require status checks to pass.
  7993. 6:24:06here. Let's click on add checks and
  7994. 6:24:08start typing pipeline success and it
  7995. 6:24:11should appear. Yeah, here it is. Select
  7996. 6:24:14it and just like that save the changes.
  7997. 6:24:18Now let's go back to that pull request
  7998. 6:24:21and let's see what will happen. Uh as
  7999. 6:24:23you can see I cannot now click on it.
  8000. 6:24:25And if I hover the message says merging
  8001. 6:24:28is blocked due to pending merge
  8002. 6:24:31requests. And here is the pending uh
  8003. 6:24:34job. It's pipeline success. And this one
  8004. 6:24:37is going to wait for the other ones to
  8005. 6:24:39finish before running. And let's see.
  8006. 6:24:42It's going to run. Let's click on it
  8007. 6:24:45just to see what's happening. So,
  8008. 6:24:46pipeline succeeded. This is the message
  8009. 6:24:49that we have uh that we wrote here. Echo
  8010. 6:24:53all checks passed successfully. This is
  8011. 6:24:55what we see here. Great. So, that
  8012. 6:24:57worked. And now I can merge because
  8013. 6:25:00there is no failure and nothing has been
  8014. 6:25:03skipped. Amazing. But let's uh let's try
  8015. 6:25:07to break this just to show you that we
  8016. 6:25:10won't be able to merge broken code.
  8017. 6:25:13Okay, let's open let's uh let's say
  8018. 6:25:16main.js.
  8019. 6:25:19Yeah, let's let's remove import and
  8020. 6:25:21let's just put Axios from Axios. This is
  8021. 6:25:24not correct. And here you can see that
  8022. 6:25:26I'm not running this locally. I am
  8023. 6:25:28running it here on yeah on GitHub just
  8024. 6:25:32to make modifications quickly which
  8025. 6:25:33means this is not going to be catched by
  8026. 6:25:36the pre-commit hooks that we defined
  8027. 6:25:37earlier. Normally this will will catch
  8028. 6:25:41that but this is the limitation that I
  8029. 6:25:43mentioned in the beginning of this video
  8030. 6:25:45is that yes it's good to have those
  8031. 6:25:47pre-commit hooks locally to stop the uh
  8032. 6:25:52some bugs like these but people can also
  8033. 6:25:56skip them. Uh this is why we create this
  8034. 6:25:58pipeline to be the gatekeeper. It's not
  8035. 6:26:00going to allow anything in unless it's
  8036. 6:26:03good and yeah let's verify that. So
  8037. 6:26:06let's just have another test commit
  8038. 6:26:08commit and push. Go back to here. Okay
  8039. 6:26:12is blocked. And now um the the linking
  8040. 6:26:17and formatting step in the front end is
  8041. 6:26:19going to fail. Let's click on it and
  8042. 6:26:22let's see what's happening. So now we
  8043. 6:26:24are set up in NodeJS.
  8044. 6:26:26Good. And let's read the message. You
  8045. 6:26:29can see that here it says cache restored
  8046. 6:26:31successfully, which means it it skipped
  8047. 6:26:34installing NodeJS and it just took it
  8048. 6:26:38took it restored it from the cache which
  8049. 6:26:41is great. It confirmed that the caching
  8050. 6:26:43is working. But let's scroll down a
  8051. 6:26:46little bit. Ah, you can see that ESLint
  8052. 6:26:48is not happy with this. It's saying that
  8053. 6:26:50error parsing uh this token. So it it
  8054. 6:26:53couldn't find the import and it uh
  8055. 6:26:56exited with code one. Now let's go back.
  8056. 6:26:59You can see that because this job has
  8057. 6:27:03failed uh we we weren't able to run the
  8058. 6:27:07unit the tests because this depends on
  8059. 6:27:11the first job and pipeline success
  8060. 6:27:16failed two because we have one failed
  8061. 6:27:19job and one cancelled job and now I
  8062. 6:27:22cannot merge this. So I have to fix uh
  8063. 6:27:25the problem and they cannot also push to
  8064. 6:27:28master because it is protected. You see
  8065. 6:27:30the beauty of having this kind of
  8066. 6:27:32pipeline in your repository, it's going
  8067. 6:27:34to be very helpful to catch problems and
  8068. 6:27:38whenever you merge something to master,
  8069. 6:27:40it's it is guaranteed that there are no
  8070. 6:27:42bugs in it and you can merge without any
  8071. 6:27:46problem and even deploy to your
  8072. 6:27:49production server. We have reached the
  8073. 6:27:52end of this tutorial. I hope that you
  8074. 6:27:54found it interesting and uh you can find
  8075. 6:27:57the documentation here on this GitHub
  8076. 6:27:59repository. You will find the link in
  8077. 6:28:02the video description. And what is next?
  8078. 6:28:06So we still have two more sub chapters
  8079. 6:28:09in module 5 and in this one we are going
  8080. 6:28:12to talk about automated security
  8081. 6:28:15scanning. We are going to scan
  8082. 6:28:17vulnerabilities in the libraries that
  8083. 6:28:20you use in your stack. This is very
  8084. 6:28:22important. We don't want to push
  8085. 6:28:24vulnerable code to a production system
  8086. 6:28:27because you could lose data. There are
  8087. 6:28:30many problems that can happen if that if
  8088. 6:28:33you push vulnerable uh libraries and we
  8089. 6:28:36will perform also this specific test to
  8090. 6:28:40yeah ensure that uh there are plenty of
  8091. 6:28:44tests that we can run and I'm going to
  8092. 6:28:47show you some of them in the upcoming uh
  8093. 6:28:50tutorial.
  8094. 6:28:52Welcome back. So far you have built a
  8095. 6:28:55pipeline that guarantees your code is
  8096. 6:28:59formatted correctly and your logic works
  8097. 6:29:02as expected.
  8098. 6:29:04Today we will focus on automating
  8099. 6:29:08security scanning.
  8100. 6:29:10Here is what we are going to talk about
  8101. 6:29:12in this sub chapter. I will try to
  8102. 6:29:14explain to you the shift left security
  8103. 6:29:18model. You are going to run software
  8104. 6:29:21composition analysis. We will also add
  8105. 6:29:25static application security testing
  8106. 6:29:28and finally we will implement a fail
  8107. 6:29:31fast strategy. CSA and SAS are the two
  8108. 6:29:35types of tests that we are going to add
  8109. 6:29:38because that they look for specific
  8110. 6:29:41security issues in different areas. And
  8111. 6:29:46the fail fast strategy basically means
  8112. 6:29:48if the security scan fails, we stop the
  8113. 6:29:52pipeline. We don't need to run the
  8114. 6:29:55subsequent jobs because it's just going
  8115. 6:29:57to be a waste of time because we know
  8116. 6:29:59that we have a problem in the
  8117. 6:30:01application. We should never deploy it.
  8118. 6:30:03And in terms of the shifting security
  8119. 6:30:06left concept, here it is. I have made
  8120. 6:30:09this diagram to explain this to you. We
  8121. 6:30:11have two ways of deploying an
  8122. 6:30:14application or working and uh we have to
  8123. 6:30:18work on security. This is very
  8124. 6:30:20important. But before or traditionally
  8125. 6:30:22we used to do it this way. First you can
  8126. 6:30:25see that this is the development cycle.
  8127. 6:30:28We plan, we design the application, we
  8128. 6:30:31start coding, we build to make sure that
  8129. 6:30:33everything is is correct. we have some
  8130. 6:30:36tests that should pass and right after
  8131. 6:30:39that we move to security. The problem
  8132. 6:30:42with this approach is that if you work
  8133. 6:30:44on a giant application and at the end
  8134. 6:30:47you realize that you have a lot of
  8135. 6:30:50problems that will make this development
  8136. 6:30:54cycle take a lot of time and you will
  8137. 6:30:58you will be fighting a lot of problems
  8138. 6:31:00and that will push the release cycle
  8139. 6:31:03further. uh this is very problematic
  8140. 6:31:06especially with bigger applications but
  8141. 6:31:09the shifting left security model fixes
  8142. 6:31:13this issue by integrating the security
  8143. 6:31:16checks during this inear cycle let's say
  8144. 6:31:19so after designing the application now
  8145. 6:31:23you start coding but while you are
  8146. 6:31:25coding you are making sure that you are
  8147. 6:31:28doing the best practices and so you keep
  8148. 6:31:30thinking about security if you have for
  8149. 6:31:33example input fields you think about uh
  8150. 6:31:36sanitizing the inputs. Try to test the
  8151. 6:31:39application. Can people do SQL injection
  8152. 6:31:41or other types of attacks while in this
  8153. 6:31:45tight loop? And you do it before you
  8154. 6:31:48build you make sure that the feature
  8155. 6:31:50that you are working on is secure. And
  8156. 6:31:53if you do this, you ensure that even if
  8157. 6:31:56you work on large applications,
  8158. 6:31:57integrating security is going to be an
  8159. 6:32:00easy task. It's like translation or
  8160. 6:32:03adding themes in your application. If
  8161. 6:32:06you do this at the end, it becomes hard.
  8162. 6:32:09But if you do it in the beginning of the
  8163. 6:32:11project, it's going to be very easy to
  8164. 6:32:14uh to integrate. And finally, once uh
  8165. 6:32:17once you are done with a specific
  8166. 6:32:19feature, you release and the cycle
  8167. 6:32:22repeats. Uh this is my GitHub profile
  8168. 6:32:25and last time you can see that I showed
  8169. 6:32:28you how to block merging if some of the
  8170. 6:32:32tests fails. That's good. Now what I'll
  8171. 6:32:36try to do I will fix these problems and
  8172. 6:32:38I will come back because we want to
  8173. 6:32:41ensure that these steps are fine but uh
  8174. 6:32:44we want uh to add on top of this the
  8175. 6:32:47security jobs. I am back and as you can
  8176. 6:32:50see every job has run successfully
  8177. 6:32:53without any issue. Now let's start
  8178. 6:32:56auditing both the front end and back
  8179. 6:32:59end. This is the software composition
  8180. 6:33:02analysis step and we use it to basically
  8181. 6:33:06audit the third party libraries that we
  8182. 6:33:09are including in our projects. For
  8183. 6:33:11example, in the front end folder we have
  8184. 6:33:15package.json.
  8185. 6:33:16It contains all the dependencies that I
  8186. 6:33:19am using for this project. You can see
  8187. 6:33:21that we have axios view router and many
  8188. 6:33:26more. The problem that might happen is
  8189. 6:33:29that let's say axio might be attacked.
  8190. 6:33:33Attackers might find a vulnerability in
  8191. 6:33:36this package which they can exploit.
  8192. 6:33:39Your application will run without any
  8193. 6:33:41problem. because that vulnerability is
  8194. 6:33:44invisible to the checks that we have
  8195. 6:33:47here. So by adding another job that goes
  8196. 6:33:51through all your dependencies, checks if
  8197. 6:33:54there is a vulnerability. When we do
  8198. 6:33:56this, we can uh successfully block the
  8199. 6:34:00pipeline. We will not allow deploying a
  8200. 6:34:04vulnerability a vulnerable package to a
  8201. 6:34:08to the production environment. we will
  8202. 6:34:10wait for the maintainers of that
  8203. 6:34:13specific project to fix the problem
  8204. 6:34:16before updating to the newest version.
  8205. 6:34:19And the same story for the back end. If
  8206. 6:34:21I go back, if I go to the backend
  8207. 6:34:23folder, you can see that here I am still
  8208. 6:34:26using the requirements.txt.
  8209. 6:34:28People nowadays use uv or other package
  8210. 6:34:31managers. Uh there is nothing wrong with
  8211. 6:34:34requirements.
  8212. 6:34:35We define the dependencies that we are
  8213. 6:34:38relying on and we need a tool that will
  8214. 6:34:41go through all of them, check the the
  8215. 6:34:43database, see if there are
  8216. 6:34:45vulnerabilities and block the pipeline
  8217. 6:34:48if it finds any. Okay, let's now go back
  8218. 6:34:51to VS code. You can see that I am still
  8219. 6:34:54using the web version because these are
  8220. 6:34:57changes that are simple. Now let's go to
  8221. 6:35:02the GitHub folder. open workflows and
  8222. 6:35:06here I need to add two more jobs one for
  8223. 6:35:09double check the dependencies in the
  8224. 6:35:11front end and the other one will do the
  8225. 6:35:13same but for the back end let's start
  8226. 6:35:16with the front end I will zoom a little
  8227. 6:35:18bit you can see that I have added this
  8228. 6:35:20job front end vulnerability check this
  8229. 6:35:23is the name that I've used here this is
  8230. 6:35:26a reusable workflow we have explained
  8231. 6:35:29this in the previous sub chapter and
  8232. 6:35:32here what are we doing so We are
  8233. 6:35:34checking the repository here. We are
  8234. 6:35:37using PMPM version 11. I have changed
  8235. 6:35:41this from the previous sub chapter. Why?
  8236. 6:35:44Because if if you want to learn more
  8237. 6:35:46about this specific version of PMP, make
  8238. 6:35:49sure to go to Google and search for
  8239. 6:35:52PMP1.
  8240. 6:35:54You will land on this page. You can read
  8241. 6:35:57more about it here. But basically uh by
  8242. 6:36:00default PNPM is more secure than npm.
  8243. 6:36:05Recently there were there were a lot of
  8244. 6:36:07attacks on very popular npm packages and
  8245. 6:36:11people sometimes they just download the
  8246. 6:36:14latest version and that uh gets them
  8247. 6:36:16hacked. PNPM solved these problems by
  8248. 6:36:20blocking recent updates. So if an update
  8249. 6:36:23is less than 7 days, it's not going to
  8250. 6:36:25be installed automatically. you will you
  8251. 6:36:27will get a warning or an error and you
  8252. 6:36:30had to decide if you want to download it
  8253. 6:36:32or not and it comes with other security
  8254. 6:36:35features by default. This is why I've
  8255. 6:36:38moved to version 11 to also help us in
  8256. 6:36:42um blocking the download of malicious uh
  8257. 6:36:46code in specific packages. And since we
  8258. 6:36:50moved to PMPM version 11, that requires
  8259. 6:36:54node version 22 and up. You cannot, as
  8260. 6:36:57you can see, this is a requirement. You
  8261. 6:37:00cannot use node 18, 19, 20 or any
  8262. 6:37:03version below 22. And after that, we
  8263. 6:37:06install the dependencies and again we
  8264. 6:37:08are using pmppm to audit the third party
  8265. 6:37:12packages. If everything is good, this
  8266. 6:37:15will not fail. But if we if PMPM finds a
  8267. 6:37:19vulnerability in a specific package uh
  8268. 6:37:22then this step will fail. Now let's do
  8269. 6:37:25the same thing for the back end. Uh the
  8270. 6:37:28job is called backend vulnerability
  8271. 6:37:31check. We are doing the same steps
  8272. 6:37:33checking the repository. We installed
  8273. 6:37:36Python version 3.13.
  8274. 6:37:39And here we are using a specific GitHub
  8275. 6:37:41action that uses the pip audit library.
  8276. 6:37:46And here as input we give it
  8277. 6:37:49requirements.txt because here we define
  8278. 6:37:52the dependencies. If you were using uv
  8279. 6:37:56or other py uh other package managers
  8280. 6:37:59those they they generate a file called
  8281. 6:38:03hi project.toml.
  8282. 6:38:05If this is the case, you just change the
  8283. 6:38:09input from requirements.txt
  8284. 6:38:12to pip projects.totml.
  8285. 6:38:14And you can read more. You can find more
  8286. 6:38:16examples in their GitHub repository.
  8287. 6:38:19Always this is what how how you should
  8288. 6:38:22reuse these uh specific GitHub actions.
  8289. 6:38:25Just look for their GitHub repository
  8290. 6:38:29and read their readme. From the readme,
  8291. 6:38:32they state that this action uses pip
  8292. 6:38:35audit which is the default library that
  8293. 6:38:38we use in Python to audit the
  8294. 6:38:40dependencies. And uh if you want to
  8295. 6:38:43learn more about the usage, just go to
  8296. 6:38:45the usage section. And as you can see
  8297. 6:38:48here uh for example, here they are
  8298. 6:38:51pointing to the environment folder. Uh
  8299. 6:38:53here is where how you can point to
  8300. 6:38:56requirements.txt.
  8301. 6:38:58And here you can point to more than one
  8302. 6:39:00file. For example, if you have if you
  8303. 6:39:02split the dependencies that are used by
  8304. 6:39:06your application and those that are used
  8305. 6:39:08just for development, you can provide
  8306. 6:39:11both files. And let me show you where is
  8307. 6:39:14the TOML one. Here it is. So if you read
  8308. 6:39:17this, they say that to audit a project
  8309. 6:39:19that uses pi project.toml,
  8310. 6:39:22you use this specific uh notation. You
  8311. 6:39:25just point to the directory where this
  8312. 6:39:28file lives. Now let's go back to VS code
  8313. 6:39:33and voila. You can see that it's very
  8314. 6:39:36easy. Now we just need to go back to the
  8315. 6:39:39orchestrator and add these jobs here. I
  8316. 6:39:43have changed the jobs list. Now I start
  8317. 6:39:46with the vulnerability checks. we what
  8318. 6:39:49we have the front end and back end and
  8319. 6:39:52we point to those two files that we have
  8320. 6:39:55created in this session and after that I
  8321. 6:39:59update the front end LinkedIn and
  8322. 6:40:02backend LinkedIn jobs to depend on these
  8323. 6:40:06vulnerability checks. You can see that
  8324. 6:40:08here we added needs and this front end
  8325. 6:40:12link job needs the vulnerability check
  8326. 6:40:15to succeed before running. At the end in
  8327. 6:40:19the pipeline success job I've also
  8328. 6:40:21updated the needs list by adding the two
  8329. 6:40:25security jobs. Now we can commit this.
  8330. 6:40:29Let's say CI add security jobs and let's
  8331. 6:40:34commit and push. Now we can go back here
  8332. 6:40:38and uh you can see the pipeline will run
  8333. 6:40:40again and this time we can go we can
  8334. 6:40:44click on view details click on summary
  8335. 6:40:48and here is our graph. Let me zoom in.
  8336. 6:40:51You can see that we have the backend
  8337. 6:40:54audit dependencies job and the front end
  8338. 6:40:58vulnerability job. Both of them run in
  8339. 6:41:01parallel and as you can see the backend
  8340. 6:41:04lint and front end lint depend on these
  8341. 6:41:09two jobs to succeed. If they fail the
  8342. 6:41:11pipeline will stop. And as you can see
  8343. 6:41:15the front end has failed. We will see
  8344. 6:41:19why in a minute. And the back end also
  8345. 6:41:22has failed which means that the pipeline
  8346. 6:41:26success job will fail too. Good. And now
  8347. 6:41:31if we go back to the food request tab,
  8348. 6:41:35you can see that I cannot merge. This is
  8349. 6:41:38blocked. And uh yeah, I need to solve
  8350. 6:41:41these problems. Now let me let's verify
  8351. 6:41:44what is happening. I will open this in a
  8352. 6:41:46new tab and I'll open the backend job
  8353. 6:41:50here. This is the result that we get
  8354. 6:41:52from pip audit. And here we have a
  8355. 6:41:55table. So name is basically the name of
  8356. 6:41:58the package. Here we have flask cores
  8357. 6:42:01and pi jwt.
  8358. 6:42:04We have the current version the ID of
  8359. 6:42:07the security problems. If you want you
  8360. 6:42:10can take this ID open a new tab and
  8361. 6:42:13search for it. You should be able to
  8362. 6:42:15find the details about that
  8363. 6:42:17vulnerability. And the severity is a I
  8364. 6:42:21think it ranges from 0 to 10 if I
  8365. 6:42:24remember correctly. And if it is closer
  8366. 6:42:27to 10, that's very problematic. And as
  8367. 6:42:29you can see, for this one, it's very
  8368. 6:42:31critical. When you see this, it means
  8369. 6:42:33that the you should update that package
  8370. 6:42:36as soon as possible. But sometimes it's
  8371. 6:42:38just medium or low. That's fine. Uh it's
  8372. 6:42:41not very problematic. Okay. Now, let's
  8373. 6:42:45look at the front end job. Ah, okay. So
  8374. 6:42:49here because we are using PMPM version
  8375. 6:42:5111, we need to yeah migrate from uh the
  8376. 6:42:56previous version. So we need to first in
  8377. 6:42:58uh try to update the the pmppm lock
  8378. 6:43:02file. Let's take this command. Let's go
  8379. 6:43:05back to VS code. I've opened the
  8380. 6:43:07terminal. Let me let me go through the
  8381. 6:43:10front end folder and let's run that
  8382. 6:43:12command. Okay. So we have we have the
  8383. 6:43:15dependencies but here I think yeah we
  8384. 6:43:17are using pmppm version 10. So we need
  8385. 6:43:20to update it. So to update they give us
  8386. 6:43:24this command to run. Let's run it. Okay.
  8387. 6:43:28So let's run pmppm setup to fix that
  8388. 6:43:32issue. Let's run this command. Okay.
  8389. 6:43:36Good. Now let's try to update it again.
  8390. 6:43:40Okay. So we need to use pmppm self
  8391. 6:43:42update. That's the new uh method. And
  8392. 6:43:45now we can run pmpm-
  8393. 6:43:48version. Still says 10.32.1.
  8394. 6:43:52Maybe I need to close and open a new
  8395. 6:43:54terminal window. So pmppm- version.
  8396. 6:43:58Okay. Yeah, that now that worked. So we
  8397. 6:44:00have version 11.1.3.
  8398. 6:44:03Let's go back to front end. Let's copy
  8399. 6:44:07this command again. Let's past space
  8400. 6:44:10here and hit enter. Let's say yes. And
  8401. 6:44:14now you can see that PMP is verifying
  8402. 6:44:16the log file for any supply chain
  8403. 6:44:19problems. Everything went well. But here
  8404. 6:44:22we have a problem. By default, PMPM is
  8405. 6:44:26going to ignore ES build. So if we want
  8406. 6:44:29to fix this, we need to run PMP approve
  8407. 6:44:32builds or so. We can either do this or
  8408. 6:44:35come back here because this is going to
  8409. 6:44:37work locally. But if we move to CI, it's
  8410. 6:44:40still going to fail and we cannot uh run
  8411. 6:44:43this in the CI interactively. Now with
  8412. 6:44:46PMP version 11, we have a new file
  8413. 6:44:50called PMP workspace that we can use to
  8414. 6:44:54modify or to update the settings. Here
  8415. 6:44:56it is. You can read more about it. And
  8416. 6:44:58if you want to search for uh specific
  8417. 6:45:02values within it, you you will find you
  8418. 6:45:05go to this [clears throat] link pm io/
  8419. 6:45:08settings and you can see they are
  8420. 6:45:11talking about this specific file and
  8421. 6:45:14what we need to do let's go back to this
  8422. 6:45:17tab. So here they are talking about
  8423. 6:45:19approved builds. We can search for it.
  8424. 6:45:24Okay, now it's approved builds. Yeah,
  8425. 6:45:27it's this one. And as you can see, we
  8426. 6:45:29need to add this to PMPM workspace and
  8427. 6:45:33we need to set AS build to true. Let's
  8428. 6:45:36do that. I will go back to this tab. We
  8429. 6:45:40are in the front end folder. Let's add
  8430. 6:45:44PNPM
  8431. 6:45:46workspacey.
  8432. 6:45:49Ah, we already have it. Yeah, we already
  8433. 6:45:51have it. Good. Ah, okay. Okay. So when
  8434. 6:45:54you run the command, PMP PM will try to
  8435. 6:45:56help you. Basically, as you can see,
  8436. 6:45:58it's created the file for us and it's
  8437. 6:46:01telling us set this to true or false.
  8438. 6:46:04Let's set it to true. Let's open the
  8439. 6:46:07terminal again. Yeah, let's try
  8440. 6:46:10installing this. Copy the command. Paste
  8441. 6:46:13it. Hit enter. Okay, it worked. Okay,
  8442. 6:46:17let's commit these two. Let's commit
  8443. 6:46:20this. Let's go back.
  8444. 6:46:23to the pipeline. Ah, I need to sync the
  8445. 6:46:26changes. Let's focus specifically on the
  8446. 6:46:28front end job because the back end will
  8447. 6:46:31fail. We haven't fixed that yet. Here we
  8448. 6:46:34are setting PNPM.
  8449. 6:46:36That's good. Can see that here it
  8450. 6:46:39switched to version 11. That's what we
  8451. 6:46:41want to see. We installed node and here
  8452. 6:46:44we are installing the dependencies.
  8453. 6:46:46Okay. So, that failed because we have 17
  8454. 6:46:50vulnerabilities.
  8455. 6:46:52Okay. And now let's go back to PMPM
  8456. 6:46:55workspace again. We need to let's look
  8457. 6:46:59at npmrc
  8458. 6:47:00or sorry package.json.
  8459. 6:47:03You can see that here before I used to
  8460. 6:47:07to resolve those problems and to do that
  8461. 6:47:10I added the overrides object because
  8462. 6:47:13these are transitive dependencies. I
  8463. 6:47:15don't depend on these libraries
  8464. 6:47:18directly. But some of my primary
  8465. 6:47:21thirdparty libraries are using them.
  8466. 6:47:24That's why we added overrides. But now
  8467. 6:47:27with pmpm11, we need to move these to
  8468. 6:47:31this pmpm workspace. And uh we can
  8469. 6:47:35search for that here. Let's see. Okay.
  8470. 6:47:38So we click on overrides. And as you can
  8471. 6:47:41see here is how we do it. We can copy
  8472. 6:47:43this format. We can let's put it here.
  8473. 6:47:47And yeah, I just need to copy all of
  8474. 6:47:51this and put it here. Okay, let's see.
  8475. 6:47:54We don't need these commas. We can
  8476. 6:47:57remove them. Yeah, I think this is the
  8477. 6:48:00format. Now, let's remove all of that.
  8478. 6:48:02Let's remove this from package.json. We
  8479. 6:48:06no longer need that. And let's save. And
  8480. 6:48:08if you are wondering how do I know all
  8481. 6:48:10of this, you can read the migrate v uh
  8482. 6:48:14v12 to v11 empm guide. So they have a
  8483. 6:48:19guide that will help you migrate to this
  8484. 6:48:22new version. Okay. Now let's save this.
  8485. 6:48:25Let's type fix move overrides to pmppm
  8486. 6:48:32work space commit
  8487. 6:48:35and sync the changes. Let's open the
  8488. 6:48:38front end job again. Remember before we
  8489. 6:48:40got 17 vulnerabilities.
  8490. 6:48:43Let's see how many we will get or if
  8491. 6:48:46this change will solve will resolve all
  8492. 6:48:49of them. Okay, we have the same problem.
  8493. 6:48:52I think because we have moved those from
  8494. 6:48:54package.json, we need to uh again update
  8495. 6:48:58the log file. Let me do it again. pmppm
  8496. 6:49:02install. Okay, so that changed the log
  8497. 6:49:05file. Good. So this is how how we work
  8498. 6:49:08with uh GitHub actions. You start in
  8499. 6:49:13with something, you test it doesn't
  8500. 6:49:15work, it gives you the error code, you
  8501. 6:49:18fix it, and you keep iterating until you
  8502. 6:49:21get something that works. And in the
  8503. 6:49:23future, let's say that we we have fixed
  8504. 6:49:26this. In the future, this job might
  8505. 6:49:28fail. So you open it, you look at some
  8506. 6:49:32the the step that failed, you read the
  8507. 6:49:34error and you go fix it. And this is
  8508. 6:49:38going this is super useful to ensure
  8509. 6:49:42that the code that you are deploying is
  8510. 6:49:45secure and that there are no problems in
  8511. 6:49:47it. Okay. Uh we are the job has failed
  8512. 6:49:51once more and now we have 14
  8513. 6:49:55vulnerabilities
  8514. 6:49:56and most of them are coming from Axios.
  8515. 6:49:59You can see that all of them are coming
  8516. 6:50:01from Axios. Uh let's see. Yeah, all of
  8517. 6:50:04them are coming from Axios and you can
  8518. 6:50:06see that here the vulnerabilities they
  8519. 6:50:08show you the range where that was found
  8520. 6:50:10and the patched version. You can also
  8521. 6:50:14go to the GitHub repository of that
  8522. 6:50:17specific project, open their releases
  8523. 6:50:21uh page and here you can read about the
  8524. 6:50:24release. Sometimes they might have a
  8525. 6:50:26security section in the release where
  8526. 6:50:30they talk about the specific
  8527. 6:50:32vulnerability that was found. So now we
  8528. 6:50:35can install version 16.1.
  8529. 6:50:38Uh it's the latest version. uh it was
  8530. 6:50:41released for more than a week. So that's
  8531. 6:50:44fine. PMPM will be able to install it.
  8532. 6:50:47Okay, let's take this version. Let's go
  8533. 6:50:50back to VS Code. We no longer need this,
  8534. 6:50:53but we need to search for Axios here.
  8535. 6:50:56Let's change the version to 16.1.
  8536. 6:50:59Let's also again run pmppm install.
  8537. 6:51:04Okay, good. So the the log file has
  8538. 6:51:06changed. Let's commit and let's push the
  8539. 6:51:09changes and hopefully this time this job
  8540. 6:51:12will succeed. Let's go back to the pull
  8541. 6:51:14request. Open the job in a new tab and
  8542. 6:51:18uh let's wait. Awesome. We were we were
  8543. 6:51:21too close. Uh but now we have one. So
  8544. 6:51:24this this library we are not depending
  8545. 6:51:27on it. But there is uh some third party
  8546. 6:51:30library that uses that uses it under the
  8547. 6:51:33hood. But you can see we went from 17
  8548. 6:51:35vulnerabilities to only one. And um
  8549. 6:51:40yeah, we can add this to the transitive.
  8550. 6:51:43Let's see. So, copy this. Go back to
  8551. 6:51:46PNPM workspace where it is here. Here we
  8552. 6:51:50have that version. And now we can add
  8553. 6:51:53what was the package name? I think it
  8554. 6:51:55was WS. Here we put this and and I think
  8555. 6:52:01the the last version is 8.20.1.
  8556. 6:52:05So we can fix it to that specific
  8557. 6:52:08version. You can always verify. You can
  8558. 6:52:10either type the package name and then
  8559. 6:52:13add npm or you can add GitHub to the
  8560. 6:52:16end. As you can see the last version is
  8561. 6:52:19820.1 and it was published 9 days ago.
  8562. 6:52:23That's good. If it was updated just a
  8563. 6:52:25day ago, the MPM will not allow you to
  8564. 6:52:27download it because by default it's I
  8565. 6:52:30think you can change the value. If you
  8566. 6:52:33go to settings, you can override that.
  8567. 6:52:36Uh you can set it to one day, a week or
  8568. 6:52:40more. It depends on the severity. If a
  8569. 6:52:43package is very popular, uh it's it's
  8570. 6:52:46good to wait for a while before
  8571. 6:52:47downloading the last version. Okay,
  8572. 6:52:50let's now again run pmppm install and
  8573. 6:52:53let's see if the log file will change.
  8574. 6:52:55And yes, it did. Commit. Save the
  8575. 6:52:58changes and let's push. This time it
  8576. 6:53:02should pass. We are installing the
  8577. 6:53:05dependencies and yes it worked. It took
  8578. 6:53:09it took a while but we have solved the
  8579. 6:53:11problem. Now you know how to iterate uh
  8580. 6:53:15over this. Now we are using PMP version
  8581. 6:53:1711 which is strict. It uh as you saw it
  8582. 6:53:22blocks a lot of things and we needed to
  8583. 6:53:24do uh some migration but it's worth it
  8584. 6:53:27once you do this. You do this once it
  8585. 6:53:29takes some time but later it's uh you
  8586. 6:53:32don't think about it. Awesome. Now we
  8587. 6:53:34can uh focus on the backend job. Let's
  8588. 6:53:39go back to the audit section and let's
  8589. 6:53:42see what we have here. Okay. So we have
  8590. 6:53:44two packages. We have flask cords and pi
  8591. 6:53:48JWT. The first package is problematic
  8592. 6:53:51because they don't have a new version.
  8593. 6:53:53So this is the last version that they
  8594. 6:53:55have. And pi JWT I'm not sure about that
  8595. 6:53:59one. So let's search for it. Uh let's
  8596. 6:54:02click here. Let's look at releases. Is
  8597. 6:54:05it an active project? Yes, it is still
  8598. 6:54:07active. And the last version is 2121
  8599. 6:54:11which is again we have the same problem
  8600. 6:54:13with PI JWT. We don't have a new version
  8601. 6:54:16that addresses this um vulnerability.
  8602. 6:54:20How do you handle this case? Well, it
  8603. 6:54:24depends. For example, in my project, I
  8604. 6:54:27am not using Flask. I am using fast API.
  8605. 6:54:31And I'm not sure why this is here. But
  8606. 6:54:33if you dig deeper, you will find that a
  8607. 6:54:36dependency that I'm using just for
  8608. 6:54:37development is relying on this package.
  8609. 6:54:41So I can move that specific package to a
  8610. 6:54:45to requirements dev and I can scan only
  8611. 6:54:48requirements. That's that's problematic
  8612. 6:54:52too. Yeah, you solve the problem with
  8613. 6:54:54production. So the code that you will
  8614. 6:54:55put in production is going to be safe
  8615. 6:54:57because we will not use this library.
  8616. 6:54:59But if uh you you have if you run this
  8617. 6:55:02[clears throat] locally, you might also
  8618. 6:55:04get infected.
  8619. 6:55:06There is another solution which is to
  8620. 6:55:08basically remove that package if you
  8621. 6:55:10don't need it. For example, if you used
  8622. 6:55:12it only once. Yeah, you can remove it
  8623. 6:55:15then. It's not it's not necessary. And
  8624. 6:55:18as we saw in this package, the
  8625. 6:55:20vulnerability is critical. Maybe if it
  8626. 6:55:22was low or medium, we could skip it. uh
  8627. 6:55:26or you could read it. Uh if it requires
  8628. 6:55:29user input or something like that. Uh if
  8629. 6:55:32you run it locally, you are safe. There
  8630. 6:55:34is no going to be any issue. But yeah,
  8631. 6:55:37this one has a critical problem. And uh
  8632. 6:55:40so it allows SQL injection. Can see that
  8633. 6:55:43here they say this vulnerability can
  8634. 6:55:45lead to unauthorized data manipulation,
  8635. 6:55:47data exfiltration, DOSs and yeah a lot
  8636. 6:55:51of problems. But most of them so SQL
  8637. 6:55:54injection requires an application that
  8638. 6:55:56users interact with. So that's the
  8639. 6:55:58problem. And here we we are not we are
  8640. 6:56:01not we are not using this. We are using
  8641. 6:56:03fast API for the front end. But it's
  8642. 6:56:06it's very tricky. Sometimes you have to
  8643. 6:56:08wait for a specific package to release a
  8644. 6:56:10fix uh for the that specific problem.
  8645. 6:56:15What I propose to do is to divide the
  8646. 6:56:18requirements file to two files. one for
  8647. 6:56:22production and the other one for local
  8648. 6:56:24development. Let's go back to GitHub.
  8649. 6:56:27Let's remove or let me keep that
  8650. 6:56:30specific workflow because we need to
  8651. 6:56:32update it. Backend vulnerability check.
  8652. 6:56:35I'll keep that one here. I'll go to back
  8653. 6:56:37end here. This is what we currently
  8654. 6:56:40have. I'll copy this file. Paste it.
  8655. 6:56:43Okay. So, it's not allowing me to copy
  8656. 6:56:45the file. Okay, that's not an issue. We
  8657. 6:56:48will create another one.
  8658. 6:56:49requirements-dev.txt.
  8659. 6:56:53Let's copy all of this. I already uh
  8660. 6:56:57have them here. So, let's put them in
  8661. 6:57:00this place. How do how do we split the
  8662. 6:57:03the file into dev and one the other one
  8663. 6:57:06for production. Basically, these
  8664. 6:57:08libraries are used for development. For
  8665. 6:57:10example, for pi test, we use that to run
  8666. 6:57:12tests. We're not going we don't need
  8667. 6:57:15this in production. So, that we can
  8668. 6:57:17drop. We can also drop the other with
  8669. 6:57:20the other packages by this facing kio
  8670. 6:57:22and the coverage pre-commit that's
  8671. 6:57:25another local one we have explained this
  8672. 6:57:27in the previous sub chapters locust this
  8673. 6:57:30is we this is new we haven't talked
  8674. 6:57:33about this uh but we will see it in the
  8675. 6:57:36upcoming chapter so I will not explain
  8676. 6:57:39this now but we will see it later uh the
  8677. 6:57:42other packages are re are uh important
  8678. 6:57:46python TNV is used to load environment
  8679. 6:57:49variables. Fast API as our back end. We
  8680. 6:57:53use Pantic to validate input. UVON is
  8681. 6:57:57important. Yeah. So everything else is
  8682. 6:58:00is required by our application. So this
  8683. 6:58:03is the first thing we will do. Uh now we
  8684. 6:58:07have two separate requirements files. So
  8685. 6:58:10let's do this here. Let's commit this.
  8686. 6:58:13Now let's go back here. Here you can see
  8687. 6:58:16that we are still pointing to
  8688. 6:58:18requirements.txt.
  8689. 6:58:20That's good. Uh let's just sync the
  8690. 6:58:23changes. Let's see what will happen on
  8691. 6:58:25GitHub. Uh let's click on backend
  8692. 6:58:28vulnerability. It should fail but I at
  8693. 6:58:32least we will have only one
  8694. 6:58:34vulnerability. Yeah, we have just one
  8695. 6:58:37which is PI JWT. This one is problematic
  8696. 6:58:41because if I did uh more research and I
  8697. 6:58:45found that docker are also flagging this
  8698. 6:58:49library and here the score is seven.
  8699. 6:58:51It's not uh like the other site that we
  8700. 6:58:54saw before. Let me explain to you how do
  8701. 6:58:58we get these CVE. Basically security
  8702. 6:59:02researchers they go through packages and
  8703. 6:59:04they look at the code to see if there is
  8704. 6:59:06some something that is that should be
  8705. 6:59:08fixed and in pjwt they say that it has
  8706. 6:59:13weak encryption but the people that were
  8707. 6:59:16that work on this project claim that no
  8708. 6:59:18the the project is fine there is no
  8709. 6:59:21issue and the problem that those
  8710. 6:59:23researchers have pointed is that the
  8711. 6:59:25length of the key uh is not very large
  8712. 6:59:29so it can be small. So in this case
  8713. 6:59:32where the maintainers don't want to
  8714. 6:59:35address the CVE, we can tell this is why
  8715. 6:59:39I kept this here. We can tell pip audit
  8716. 6:59:41to ignore that specific CVE because it's
  8717. 6:59:45just noise and the maintainers they are
  8718. 6:59:47the ones who understand their project
  8719. 6:59:50and they have the freedom to either
  8720. 6:59:52accept the claim the CVE or reject it.
  8721. 6:59:57because they have rejected it. We will
  8722. 6:59:59add ignore vulnerabilities and we
  8723. 7:00:02specify the name of that vulnerability
  8724. 7:00:05and uh you can find that here uh it's in
  8725. 7:00:09this in the ID column. Just copy this
  8726. 7:00:12and paste it in this YAML file. Let's
  8727. 7:00:16commit this. Let's think and hopefully
  8728. 7:00:20this time this job should should not
  8729. 7:00:23fail. Let's click on it again. Okay, we
  8730. 7:00:26are checking the repository. We install
  8731. 7:00:28Python. It should be cached. And
  8732. 7:00:32let's wait for a moment. And as you can
  8733. 7:00:35see, it says no known vulnerabilities
  8734. 7:00:38found. And it also tells us that we
  8735. 7:00:41ignored one vulnerability. And now if we
  8736. 7:00:45go to summary, everything will run. So
  8737. 7:00:48now because these security jobs has s
  8738. 7:00:53succeeded, we now can run LinkedIn.
  8739. 7:00:54adapt that we run unit tests. But if one
  8740. 7:00:58step fails, the other one will not run.
  8741. 7:01:01And here we have a problem with
  8742. 7:01:03LinkedIn. Why? And we have a problem
  8743. 7:01:06with unit tests. Interesting. Here we
  8744. 7:01:09are installing pip install-r
  8745. 7:01:11requirements.txt.
  8746. 7:01:13But now we need to also we need to
  8747. 7:01:15install from both of them. We keep
  8748. 7:01:17requirements txt and we add requirements
  8749. 7:01:19there. There is another option where you
  8750. 7:01:22put - r requirements txt within
  8751. 7:01:26uh requirementsdev.txt
  8752. 7:01:28but we will keep it simple like yeah
  8753. 7:01:30it's explicit it's uh it's not going to
  8754. 7:01:32hide that uh specific part of the
  8755. 7:01:34command commit and let's sync the
  8756. 7:01:37changes. We also have a problem with
  8757. 7:01:39linting that's uh that's weird. So let's
  8758. 7:01:42see what is happening there. Well, we
  8759. 7:01:45can just come let's come here and let's
  8760. 7:01:47uh run pmppm lint and pmppm format.
  8761. 7:01:52Okay, so we needed to format workspace.
  8762. 7:01:54That's the issue. Okay. Uh let's type
  8763. 7:01:57style apply formatting. I think now
  8764. 7:02:00everything should pass hopefully. Let's
  8765. 7:02:03close this tab and this one. Let's go
  8766. 7:02:06back here. Let's click on view details
  8767. 7:02:10summary and let's wait. Stage one
  8768. 7:02:13completed successfully. Let's move to
  8769. 7:02:16stage two. We have no problem with stage
  8770. 7:02:19two. Now we can move to stage three. And
  8771. 7:02:22the unit test has without any problem.
  8772. 7:02:26Amazing. And the pipeline succeeded.
  8773. 7:02:29Great. Now we can go back to the pull
  8774. 7:02:30request and if we are happy we can merge
  8775. 7:02:33the change the features that we are
  8776. 7:02:35developing or the bug fix that we that
  8777. 7:02:38we resolved. Amazing. You can see that
  8778. 7:02:40uh it took us a while. Uh we had a lot
  8779. 7:02:43of problems. We fixed an issue here. It
  8780. 7:02:45generated other problems there. But I
  8781. 7:02:48wanted to show you the full um the yeah
  8782. 7:02:52the row experience. That's how you
  8783. 7:02:54develop this. And uh it's it's it's
  8784. 7:02:57easy. Yes. But you get a lot of errors
  8785. 7:03:00along the way. And uh now I I think you
  8786. 7:03:03you have a better idea of how to work
  8787. 7:03:05with GitHub actions and how to resolve
  8788. 7:03:08any problem that you might face. But we
  8789. 7:03:11are not done yet. We have uh this is
  8790. 7:03:13this was the CSA software composition
  8791. 7:03:17analysis. Now we need to do static
  8792. 7:03:20application security testing. What is
  8793. 7:03:23the difference? Basically SCA doesn't
  8794. 7:03:26look at your source code. It checks the
  8795. 7:03:29third-party dependencies but static
  8796. 7:03:32application security testing which is
  8797. 7:03:34which we call SAS for short will go read
  8798. 7:03:38your Python code and see if there are
  8799. 7:03:40problems there. If you have password
  8800. 7:03:43within the source code if you are using
  8801. 7:03:46weak uh deprecated methods for example
  8802. 7:03:50if you are using the execute function
  8803. 7:03:53within your code that's a risky one. So
  8804. 7:03:56this is going to check for these
  8805. 7:03:57patterns and it's going to let you know
  8806. 7:03:59if it found something. Let's go to VS
  8807. 7:04:03code and let's add another job here. We
  8808. 7:04:07will call this one backend stat check
  8809. 7:04:11and we will put this code inside. Let's
  8810. 7:04:14scroll down. What we have here is this
  8811. 7:04:17is uh similar to what we have done
  8812. 7:04:19before. The only thing that changed is
  8813. 7:04:22bandit. Here we are using a library
  8814. 7:04:25called Bandit. You can search for it on
  8815. 7:04:28GitHub. And as you can see, it is a tool
  8816. 7:04:31designed to find common security issues
  8817. 7:04:34in Python code. That's the difference
  8818. 7:04:37between this and uh the other two jobs
  8819. 7:04:40that we worked on earlier. It is going
  8820. 7:04:43to read your code. And here we are
  8821. 7:04:45bandit with these specific arguments. Uh
  8822. 7:04:48basically dash r means recursive. Here
  8823. 7:04:51we are. So the working directory is
  8824. 7:04:54backend. It's going to go in the inside
  8825. 7:04:56the backend folder and go through all
  8826. 7:04:58the Python files. Dash LL means so here
  8827. 7:05:03we have two L's. This means that this is
  8828. 7:05:05going to flag only medium or high
  8829. 7:05:09issues. It is going to skip low
  8830. 7:05:13problems. We will see this in the logs.
  8831. 7:05:16If you if you don't do this, you will
  8832. 7:05:18have a lot of issues and they are just
  8833. 7:05:20false positives like uh what we have
  8834. 7:05:23done with PI JWT that CVE was blocking
  8835. 7:05:27us. But if you analyze it well, you see
  8836. 7:05:30that in the end it's not an issue.
  8837. 7:05:32That's why we are skipping low problems.
  8838. 7:05:34We want to focus just on medium or high
  8839. 7:05:38issues. And if you want to find uh if
  8840. 7:05:41you want to learn more about this
  8841. 7:05:43library, you can always go to the source
  8842. 7:05:45repository and read their documentation.
  8843. 7:05:48There you will find everything. Okay.
  8844. 7:05:51Now we need to go back to CI and we need
  8845. 7:05:54to add that after the backend
  8846. 7:05:56vulnerability check and I want let me
  8847. 7:06:00take this. I want backend linting and
  8848. 7:06:02formatting to run after both of these
  8849. 7:06:06tests. Okay. And uh I will add that here
  8850. 7:06:10also. I think that's all we need to do.
  8851. 7:06:12Now we can we commit this and let's
  8852. 7:06:16think the changes. Let's go back to
  8853. 7:06:18GitHub. I think it should pass because
  8854. 7:06:21uh I am not using any unsecure code in
  8855. 7:06:24my back end. But let's verify or refresh
  8856. 7:06:27the page. Sometimes it gets stuck. Uh I
  8857. 7:06:30have been refreshing the page uh for a
  8858. 7:06:32few minutes but it is still stuck. And
  8859. 7:06:36when that happens, sadly, GitHub, they
  8860. 7:06:38don't show you that there is a syntax
  8861. 7:06:40error. But here you can see that I have
  8862. 7:06:43missed a comma. That's the problem. And
  8863. 7:06:45that's why the pipeline didn't start
  8864. 7:06:47right away. Okay. And now it's working.
  8865. 7:06:51Yeah, that they should they should fix
  8866. 7:06:53this uh somehow because if you don't
  8867. 7:06:56know that, they should tell you that it
  8868. 7:06:59failed because of a syntax error. But
  8869. 7:07:01anyways, now we know if something gets
  8870. 7:07:03stuck uh that means that you have a
  8871. 7:07:06syntax error somewhere. And here we are
  8872. 7:07:09running those jobs in parallel. You can
  8873. 7:07:11see that backend Linton is uh requires
  8874. 7:07:16both of these jobs to succeed before
  8875. 7:07:19running. And as I told you, Bandit will
  8876. 7:07:21not fail. But let's look at the logs
  8877. 7:07:23because I want to show you that we have
  8878. 7:07:26so Banditis found 1,900 lines of code.
  8879. 7:07:29Here are the metrics. So you can see
  8880. 7:07:30that we have 159 low issues. If we
  8881. 7:07:34didn't skip low issues, you can see that
  8882. 7:07:38it will be a nightmare to look at all of
  8883. 7:07:40these problems. And most of them are
  8884. 7:07:43going to be false positive. These aren't
  8885. 7:07:45real problems in your code. But if we
  8886. 7:07:48had something in medium or high, now we
  8887. 7:07:50should look at those seriously. And here
  8888. 7:07:52you might be conf So don't confuse
  8889. 7:07:55issues and confidence. So here they have
  8890. 7:07:58total issues by severity. So these are
  8891. 7:08:00basically if we have an issue is it
  8892. 7:08:02severe or not in our case no they are
  8893. 7:08:05low and confidence is that here it is
  8894. 7:08:09set to high. This doesn't mean that all
  8895. 7:08:10of these problems are of a high
  8896. 7:08:13severity. No it's just the confidence
  8897. 7:08:15level. So here this means that bandit is
  8898. 7:08:18confident that all of these are low
  8899. 7:08:20problems that we that we should skip and
  8900. 7:08:23don't care about. It seems that this is
  8901. 7:08:25working. The pipeline has succeeded.
  8902. 7:08:28Everything has passed and now we can
  8903. 7:08:29merge without any problem. But before we
  8904. 7:08:32end this tutorial, I would like to show
  8905. 7:08:33you how banditis fails. That's
  8906. 7:08:36important. Um let's open let me open
  8907. 7:08:38main.py. I have added this because it
  8908. 7:08:41uses an outdated cryptography module. Um
  8909. 7:08:45I've just added something just to
  8910. 7:08:47trigger banditis. So let's see. Sure
  8911. 7:08:51trigger banditis, but I'm going to
  8912. 7:08:53remove it right away. I just want to
  8913. 7:08:55show you what happens when Bandit fails.
  8914. 7:08:58This will Yeah. Okay. So, let's wait for
  8915. 7:09:01this. Okay. So, it is it is running. Uh
  8916. 7:09:05let's let's click on Bandit. That's the
  8917. 7:09:07one we care about. Did it fail? Yes, it
  8918. 7:09:10did. So, the exit code is one. And now
  8919. 7:09:13we have one high problem. And if you
  8920. 7:09:16look closely, okay, so it is running
  8921. 7:09:19here. It says issue. Uh so it it found
  8922. 7:09:22that we used the MDA hash and it's uh
  8923. 7:09:26yeah it's not uh secure. This is an
  8924. 7:09:29outdated module that we should not use.
  8925. 7:09:32So here they show you the where where it
  8926. 7:09:35found the problem. Here is the location.
  8927. 7:09:37It's online 18. And you can see that now
  8928. 7:09:40we have one in the high severity
  8929. 7:09:43category. That confirms that bandit is
  8930. 7:09:45working and uh it it is reading the
  8931. 7:09:48code.
  8932. 7:09:49Uh it's not like the other the other
  8933. 7:09:51ones. So now we can remove this safely.
  8934. 7:09:54Uh we've confirmed that Bandis is
  8935. 7:09:56reading the code and uh let's wait for
  8936. 7:10:00this job to finish one more time. I want
  8937. 7:10:03to ensure that every every job passes
  8938. 7:10:06and that I can merge without any issue.
  8939. 7:10:08I am back. The pipeline took a minute
  8940. 7:10:12and 37 seconds. It succeeded which is a
  8941. 7:10:16great sign. And uh and yeah, we have
  8942. 7:10:19reached the end of this tutorial. You
  8943. 7:10:22know, I've really enjoyed making this
  8944. 7:10:24video. Uh it was challenging. Uh we have
  8945. 7:10:27hit a lot of problems and we fixed them
  8946. 7:10:30uh interactively. I hope that you
  8947. 7:10:33enjoyed it too and that you have learned
  8948. 7:10:35how to deal with securing your
  8949. 7:10:38application. You can see that the
  8950. 7:10:39pipeline is starting to get bigger and
  8951. 7:10:41bigger. We are adding we are making sure
  8952. 7:10:44that we develop a robust pipeline and by
  8953. 7:10:48the end of the of this module you will
  8954. 7:10:52get something that uh that is really
  8955. 7:10:54great and that will help you uh find
  8956. 7:10:57bugs easily and uh ensure that when you
  8957. 7:11:00hit deploy that your application will
  8958. 7:11:02run without any issue. In the next sub
  8959. 7:11:05chapter which is titled advanced testing
  8960. 7:11:09and dust. Dust is you can see that here
  8961. 7:11:12we have sust and dust is dynamic. So we
  8962. 7:11:15will add that one too. Uh we will still
  8963. 7:11:17continue working on testing and
  8964. 7:11:20security. So far we have just unit tests
  8965. 7:11:23but we will add integration tests and
  8966. 7:11:26end to end tests. Uh we will we will see
  8967. 7:11:29we will see that in details but I just
  8968. 7:11:31wanted you to know what is the next step
  8969. 7:11:34in our course. Thank you again for
  8970. 7:11:36watching. See you in the next sub
  8971. 7:11:39chapter. In this sub chapter we are
  8972. 7:11:42going to talk about advanced testing.
  8973. 7:11:46Here we are going to add both
  8974. 7:11:48integration and end to end tests and I'm
  8975. 7:11:51going to show you something called dust.
  8976. 7:11:54Here is the agenda that we will follow.
  8977. 7:11:56As I said, we will start by writing
  8978. 7:11:58integration tests. And here we are going
  8979. 7:12:02to test a live me search instance
  8980. 7:12:06because this is the search engine that I
  8981. 7:12:08am using on my personal project. We are
  8982. 7:12:11going to perform end to end tests using
  8983. 7:12:14the the playright tool in order to
  8984. 7:12:17simulate real users. And finally, we are
  8985. 7:12:21going to look at dynamic application
  8986. 7:12:23security testing. And we're going to do
  8987. 7:12:26that with this tool OASP zap. If you
  8988. 7:12:30want to follow with me, every command
  8989. 7:12:33will be here. Just go to this GitHub
  8990. 7:12:35repository, open the book folder and
  8991. 7:12:38here we are in chapter number five. Just
  8992. 7:12:42search DOS and you will find the this
  8993. 7:12:45new sub chapter advanced testing and
  8994. 7:12:47dust. And here you have all the commands
  8995. 7:12:50that I will run here. And this is
  8996. 7:12:53explained uh in detail. I will now close
  8997. 7:12:56this tab because we no longer need it.
  8998. 7:12:58And here you can see that I haven't
  8999. 7:13:00merged this pull request yet. We will
  9000. 7:13:03keep using it for uh the upcoming
  9001. 7:13:05videos. And as you can see at the end uh
  9002. 7:13:09if I click on this icon, you can see
  9003. 7:13:12that we have all these tests. We can
  9004. 7:13:14click on details here. Let's click on
  9005. 7:13:16summary. And currently this is what we
  9006. 7:13:19have in this video. We are going to add
  9007. 7:13:21integration tests and end to end tests
  9008. 7:13:25before the final pipeline success step.
  9009. 7:13:29Let's start doing this. Open the GitHub
  9010. 7:13:33folder. Open workflows. And here let's
  9011. 7:13:36you can see that we have backend
  9012. 7:13:38integration tests. This is what we want.
  9013. 7:13:41But before we do that, let's change the
  9014. 7:13:45branch to what did I call it? Test
  9015. 7:13:48number two. Okay, let's do it here. Test
  9016. 7:13:51number two. Okay, now we don't have that
  9017. 7:13:54file. So, we need to create it. Click on
  9018. 7:13:56this icon and add this file backend
  9019. 7:14:00integration tests. I will copy and paste
  9020. 7:14:03the code. And here, let me explain to
  9021. 7:14:05you what we have. There are some things
  9022. 7:14:07that we have seen before like checking
  9023. 7:14:10out the repository. I will collapse
  9024. 7:14:13that. Installing Python, installing the
  9025. 7:14:16dependencies. All of these steps are
  9026. 7:14:19known and uh we will skip them in this
  9027. 7:14:23uh sub chapter. We won't we don't want
  9028. 7:14:25to waste time here. The new stuff is the
  9029. 7:14:28main search environment variables and
  9030. 7:14:30the steps to launch that service. And
  9031. 7:14:34let me explain to you why do we need
  9032. 7:14:36integration tests. If I go back to
  9033. 7:14:39GitHub and open the pipeline, as you can
  9034. 7:14:43see, we have some tests already. We call
  9035. 7:14:46them unit tests. These are important
  9036. 7:14:49tests and they test few things in the
  9037. 7:14:52application in isolation. For example,
  9038. 7:14:55if I have a button or a function in the
  9039. 7:14:58back end that converts time into a
  9040. 7:15:00specific format, I can test that
  9041. 7:15:02function in isolation. And let's say if
  9042. 7:15:05I have if I am making requests to m
  9043. 7:15:08search, I am going to mock that. I am
  9044. 7:15:11going to uh not talk to M searcharch in
  9045. 7:15:15unit tests because here we are just
  9046. 7:15:18testing the individual functions or
  9047. 7:15:21functionalities. Integration tests are a
  9048. 7:15:24bit different. They test integrating
  9049. 7:15:28external services like me search or if
  9050. 7:15:31you have let's say a postgress SQL
  9051. 7:15:34database or other services you test them
  9052. 7:15:37in integration tests. And here when if I
  9053. 7:15:40want to make a let's say a search query
  9054. 7:15:43to me search I am going I need an
  9055. 7:15:46instance of me search running to be able
  9056. 7:15:48to do that that's why here in this uh
  9057. 7:15:52workflow we are going to set up m search
  9058. 7:15:56so that it runs in this job and so that
  9059. 7:16:00we can make requests to it. Here we have
  9060. 7:16:02a few environment variables. Uh these
  9061. 7:16:05are specific to me search. So if you are
  9062. 7:16:07using other services you need to change
  9063. 7:16:09this part but we have a master key a URL
  9064. 7:16:13and a name index name. Here we will
  9065. 7:16:15store documents. I will explain these
  9066. 7:16:18two environment variables down below
  9067. 7:16:20because they are important. Okay let's
  9068. 7:16:22start. Here we have the download me
  9069. 7:16:25search binary step. So after installing
  9070. 7:16:27the dependencies, Python and checking
  9071. 7:16:30out the repository, we need to install
  9072. 7:16:32me search and it is a binary file. So we
  9073. 7:16:35can download it easily using this curl
  9074. 7:16:38command. And uh this this also needs to
  9075. 7:16:42change if you use other services. And
  9076. 7:16:45here we have these two variables max
  9077. 7:16:48retries and retry delay. Sometimes in
  9078. 7:16:52the GitHub actions this step will fail
  9079. 7:16:55and you won't be able to download M
  9080. 7:16:58search and uh you might say oops the the
  9081. 7:17:02integration tests have failed but
  9082. 7:17:04actually the problem was just network
  9083. 7:17:07and uh we just need to retry this step
  9084. 7:17:10multiple times until we download mainly
  9085. 7:17:12search. So we are here uh redefining the
  9086. 7:17:16variables max retries and retry delay.
  9087. 7:17:18And here we are using a for loop to uh
  9088. 7:17:21try downloading me search max retries
  9089. 7:17:25times and in this case it is set to
  9090. 7:17:27three but you can change the value to
  9091. 7:17:30something higher. If this keeps failing
  9092. 7:17:32and if this step succeeds we will show
  9093. 7:17:36my search was downloaded and we will
  9094. 7:17:39break out of the loop. Otherwise we will
  9095. 7:17:42exit with one and uh tell GitHub that
  9096. 7:17:45this step has failed. Okay. So here we
  9097. 7:17:48download me search. After that we need
  9098. 7:17:51to start it. And in order to start it we
  9099. 7:17:53just run the binary and we pass the
  9100. 7:17:56master key. And here notice what I have
  9101. 7:17:58what I have added at the end. I have
  9102. 7:18:00this amperand. And this is very
  9103. 7:18:03important. If you don't add this, this
  9104. 7:18:06call will block this job or this step
  9105. 7:18:09and we won't be able to run the next
  9106. 7:18:11steps. But this by adding an amperand,
  9107. 7:18:14it will run this as a back as a
  9108. 7:18:17background job and it will allow the
  9109. 7:18:19next steps to run without being blocked.
  9110. 7:18:22And here when we run medarch, we need to
  9111. 7:18:24ensure that the server has started. And
  9112. 7:18:27the way we do that is we call the health
  9113. 7:18:30endpoint. If this endpoint replies it
  9114. 7:18:34means that M search is ready to accept
  9115. 7:18:36requests. That's this is what we are
  9116. 7:18:39doing here. And again we are using a for
  9117. 7:18:41loop so that we keep pinging this
  9118. 7:18:44endpoint. If we detect available great
  9119. 7:18:47we are going to show this in the logs
  9120. 7:18:50and we will break out. Otherwise we will
  9121. 7:18:53sleep a little bit to uh retry. We don't
  9122. 7:18:55want to do this quickly. And here uh at
  9123. 7:18:58the end we just if this uh doesn't uh
  9124. 7:19:01work we will show that the me search
  9125. 7:19:04fails to start after the number of
  9126. 7:19:06attempts that we have here. If this
  9127. 7:19:08succeeds we will run the integration
  9128. 7:19:11tests and uh again we will use piest and
  9129. 7:19:15in my case I I am storing you can see
  9130. 7:19:18that I try to group tests by their
  9131. 7:19:21nature. Here I have all of my unit
  9132. 7:19:23tests. Here I have integration tests and
  9133. 7:19:26I also have load testing. We might see
  9134. 7:19:28this in upcoming uh subchapters. And as
  9135. 7:19:32you can see here I am using tbhore so
  9136. 7:19:33that the exceptions are not very verbose
  9137. 7:19:37and I passed the environment variables
  9138. 7:19:39because we need them inside the tests.
  9139. 7:19:42So the only thing that I want you to
  9140. 7:19:44take from this workflow is that in
  9141. 7:19:47integration tests you need to start your
  9142. 7:19:50services. Uh if you have me search this
  9143. 7:19:52is how you do it. If you have Postgress
  9144. 7:19:54SQL, you need to do it differently. If
  9145. 7:19:58you are having services in Docker, you
  9146. 7:20:00need to run the containers, stuff like
  9147. 7:20:03that. And after running all of your
  9148. 7:20:05services, you can run your tests. And
  9149. 7:20:08the beauty is that here if something
  9150. 7:20:10broke, it's going to uh be uh very
  9151. 7:20:13informative because you are testing the
  9152. 7:20:16live services. Awesome. Now, we can go
  9153. 7:20:20back to CI.YAML YAML and add this
  9154. 7:20:24integration test there commit and we can
  9155. 7:20:27see if that will fail or not. Let's open
  9156. 7:20:30CI.YAML
  9157. 7:20:32and here let's add that job. We have
  9158. 7:20:35backend integration tests. I want to run
  9159. 7:20:38it after unit tests. And uh here is the
  9160. 7:20:42file. I need to copy this and also add
  9161. 7:20:45it here below backend unit tests. And I
  9162. 7:20:49guess that's it. Let's commit this. I
  9163. 7:20:52have pushed the code. Now let's go back
  9164. 7:20:54to GitHub. Let's refresh the page and
  9165. 7:20:57let's see if this is going to uh fail or
  9166. 7:21:01not. Let's open the details page and
  9167. 7:21:04let's see what we have. I want to go
  9168. 7:21:07back to summary. I want to see how this
  9169. 7:21:09looks like. And yeah, everything is
  9170. 7:21:11good. So we have unit tests and after
  9171. 7:21:13that we will run the integration tests.
  9172. 7:21:16I will wait for all these steps to
  9173. 7:21:17finish and I will come back. And as you
  9174. 7:21:19can see here, we have a problem with
  9175. 7:21:21audits. Probably something in the front
  9176. 7:21:23end changed. But this is not a problem.
  9177. 7:21:25We now know how to solve this. Uh I will
  9178. 7:21:27just focus on uh the integration tests
  9179. 7:21:30and then maybe we will we can come back
  9180. 7:21:32here and solve the problems that we
  9181. 7:21:34have. Now we are in the unit tests
  9182. 7:21:37phase. [snorts] Let's wait for it. Okay.
  9183. 7:21:39Uh let's click on backend integration
  9184. 7:21:42tests because I want to see the logs.
  9185. 7:21:44Okay. So far so good. These are the
  9186. 7:21:47steps that we that we have in every job.
  9187. 7:21:50Okay, great. Now we are downloading
  9188. 7:21:51Millie search and as you can see this
  9189. 7:21:54time it worked. Here we we are showing
  9190. 7:21:57attempt one of three and yeah we are
  9191. 7:22:00still trying to download it and that
  9192. 7:22:02that worked great and you can see that
  9193. 7:22:05they show us how to run it. Now here in
  9194. 7:22:08this step we are running it and as you
  9195. 7:22:11can see uh these are the logs and
  9196. 7:22:14awesome that worked. So far so good. Uh
  9197. 7:22:17let's collapse all of these steps. Okay,
  9198. 7:22:20but I think yeah, we have a problem
  9199. 7:22:22here. Import error while loading conf
  9200. 7:22:25test. Okay, so it couldn't import
  9201. 7:22:27something because it doesn't understand
  9202. 7:22:30fast API. Interesting. So I guess we
  9203. 7:22:32need to fix something when we in when we
  9204. 7:22:36are installing the dependencies. Okay,
  9205. 7:22:39let's go back here. So we are installing
  9206. 7:22:42requirements dev and uh what happens
  9207. 7:22:46what what's the problem? So if we go
  9208. 7:22:48back to back end we have divided the
  9209. 7:22:50requirements into two files. Ah I see so
  9210. 7:22:54I forgot to add - r. Yeah the difference
  9211. 7:22:57here is that we need to also do this. So
  9212. 7:23:01we need to do - r requirements
  9213. 7:23:04txt or we can do it here. So we do r
  9214. 7:23:09requirements.txt. txt space-ash r
  9215. 7:23:12requirementsdev.txt
  9216. 7:23:14txt and u yeah this time I will do it
  9217. 7:23:17this way pip will go inside requirements
  9218. 7:23:21dev it's going to find this it's going
  9219. 7:23:24to open requirements txt and it's going
  9220. 7:23:26to install fast API okay let's commit
  9221. 7:23:29this and let's push let's go back to
  9222. 7:23:33GitHub the pipeline has started let's
  9223. 7:23:37let's see the details let's open the
  9224. 7:23:40integration tests and I think this time
  9225. 7:23:44it should work. Let's collapse all of
  9226. 7:23:46these steps. We've installed M
  9227. 7:23:49searcharch successfully. We have started
  9228. 7:23:52it. Okay. And now we are running
  9229. 7:23:55integration tests and as you can see we
  9230. 7:23:57didn't have we didn't get the same error
  9231. 7:23:59and they succeeded. Great. So that
  9232. 7:24:02worked. Let's go back here to summary.
  9233. 7:24:05As you can see, both tests
  9234. 7:24:09uh run successfully, but the pipeline
  9235. 7:24:11didn't succeed because we have a problem
  9236. 7:24:14in the audit dependencies job. And as
  9237. 7:24:18you can see here, we have a problem with
  9238. 7:24:20JS cookie vest. So these are the two
  9239. 7:24:24libraries that we need to fix. Let's do
  9240. 7:24:26that. While we are here, remember that
  9241. 7:24:29we have PNPM workspace and here we can
  9242. 7:24:32add the libraries. uh we need to
  9243. 7:24:35override them because in my case I am
  9244. 7:24:37not using JS cookie that's why I need to
  9245. 7:24:41put it here in the overrides object and
  9246. 7:24:44what was the the version 306 okay so
  9247. 7:24:48let's go back here and let's put 306
  9248. 7:24:52that's the first one and what what else
  9249. 7:24:55we have test so for test I am using it
  9250. 7:24:59so if we open package JSON You can see
  9251. 7:25:04that I have a V test. Here it is. And
  9252. 7:25:07the here the version is 4014.
  9253. 7:25:11Okay, that's why. Yeah, that's why it
  9254. 7:25:13will it is complaining. So, we need to
  9255. 7:25:15upgrade that to for the 1.0.
  9256. 7:25:19Let's go inside the front end folder.
  9257. 7:25:21And here, let's try to install the
  9258. 7:25:25newest version. Here is the full
  9259. 7:25:28command. Let me open package.json JSON
  9260. 7:25:31again just to verify that we have V
  9261. 7:25:34test. Yes, it is in the dev
  9262. 7:25:36dependencies. This is why we are adding
  9263. 7:25:38dash D and yeah let's install the newest
  9264. 7:25:43version. Okay, it is installing and we
  9265. 7:25:46are using PMP
  9266. 7:25:49version 10 because this is a a fresh
  9267. 7:25:52virtual machine. So that's fine. You can
  9268. 7:25:54see that vest uh we were able to update
  9269. 7:25:57it upgrade it to 4.1 and uh yeah let's
  9270. 7:26:01see what we have here package.json yeah
  9271. 7:26:04that worked. I have updated pmppm to
  9272. 7:26:07version 11 because uh I don't want to
  9273. 7:26:09see any error in uh this PCI pipeline.
  9274. 7:26:14Let's run pmp install just to ensure
  9275. 7:26:17that nothing uh oh sorry I need to go to
  9276. 7:26:20front end and let's run pmppm install.
  9277. 7:26:24Uh let's say yes. Okay, we are good to
  9278. 7:26:28go. Let me close the terminal and let's
  9279. 7:26:32say sure update dependencies. Let's sync
  9280. 7:26:36the changes and hopefully this time the
  9281. 7:26:38pipeline will succeed. We will let that
  9282. 7:26:41one running and I will come back to it.
  9283. 7:26:43But now we need to add let's see we need
  9284. 7:26:46to add end to end tests. Let's open
  9285. 7:26:48workflows again and let's create this
  9286. 7:26:51file end to end tests. I will copy the
  9287. 7:26:55code and I will paste it here. Uh let me
  9288. 7:26:59collapse this and let's look at this
  9289. 7:27:01environment variables. This is identical
  9290. 7:27:04to what we have there. And in end to end
  9291. 7:27:06test we need to have everything running.
  9292. 7:27:08We need to have the front end, back end,
  9293. 7:27:10and all services. So here we have all of
  9294. 7:27:14these environment variables for me
  9295. 7:27:15search because we need to start the mele
  9296. 7:27:17search service. And let's see what we
  9297. 7:27:20have here. Here we added timeout minutes
  9298. 7:27:2230 minutes. Uh we don't want so if end
  9299. 7:27:25to end test for some reason take more
  9300. 7:27:27than 30 minutes, we want to time out.
  9301. 7:27:29This depends on how many tests you have
  9302. 7:27:31and how and the complexity, but for me
  9303. 7:27:3430 minutes is more than enough. Here we
  9304. 7:27:36are checking the repository. We install
  9305. 7:27:38Python here. Let's see. So we want to
  9306. 7:27:42install
  9307. 7:27:44R requirements and here let me add
  9308. 7:27:46dev.txt
  9309. 7:27:48because we want to run uh maybe this is
  9310. 7:27:51not important here. Yeah, it's not
  9311. 7:27:53important because we won't run it. We
  9312. 7:27:56will be right we will be using the
  9313. 7:27:58playright tool and that one runs in the
  9314. 7:28:00front end. That's why we just need the
  9315. 7:28:03production dependencies to run the fast
  9316. 7:28:05API service or server. Here we download
  9317. 7:28:09me search. This is identical to what we
  9318. 7:28:11have in the integration tests. We start
  9319. 7:28:14search and here we start the backend
  9320. 7:28:16server. We are using uicorn and again we
  9321. 7:28:20have the same for loop. We ping the
  9322. 7:28:23health endpoint and if it returns okay
  9323. 7:28:25that's great. We know that the backend
  9324. 7:28:27has started otherwise we exit. And here
  9325. 7:28:31we have a step that I called see the end
  9326. 7:28:34to end test data. When we create when we
  9327. 7:28:37download search and start it, it's going
  9328. 7:28:40to be empty. We won't have any data to
  9329. 7:28:42play with. In end to end tests, we need
  9330. 7:28:45to have data in the browser so that we
  9331. 7:28:47can interact with uh articles or
  9332. 7:28:50products or any it depends on the on the
  9333. 7:28:53project that you are working on. And in
  9334. 7:28:55my case, I want to put data in my
  9335. 7:28:58research. So I have created a a specific
  9336. 7:29:01file that I called test data that will
  9337. 7:29:04insert documents to many search. You can
  9338. 7:29:07see that here is the index that I am
  9339. 7:29:09using for tests. It's called articles in
  9340. 7:29:13test here and here here are all the
  9341. 7:29:16documents that I will inject just for
  9342. 7:29:19end to end tests. If you have Postgress
  9343. 7:29:22or other databases, you can do the same
  9344. 7:29:24something similar where you seed your uh
  9345. 7:29:27where you seed the test data and after
  9346. 7:29:30that we install here we have we use PNPM
  9347. 7:29:33version 11 we install node we install
  9348. 7:29:36the frontend dependencies and now we
  9349. 7:29:39arrived at the playright tool. Okay. So
  9350. 7:29:42we install it we check the version the
  9351. 7:29:45version is coming from again
  9352. 7:29:47package.json.
  9353. 7:29:48Uh if we look at playright test here it
  9354. 7:29:51is we take this specific version and
  9355. 7:29:55display it in the logs. Okay. After that
  9356. 7:29:57we cache play right because here we in
  9357. 7:30:00we need to download browsers and uh this
  9358. 7:30:03depends on your configuration. If you
  9359. 7:30:06some if you want to run the test only on
  9360. 7:30:09chrome this step will download Chrome.
  9361. 7:30:11If you want to also add Firefox it's
  9362. 7:30:13going to download Firefox as well. If
  9363. 7:30:15you want to to do it on Safari, you will
  9364. 7:30:17install Safari. So, and if the browsers
  9365. 7:30:20are the same, we need to cache them so
  9366. 7:30:22that next time when we run end to end
  9367. 7:30:24tests, they are going to be there and we
  9368. 7:30:26are just going to use them. And for
  9369. 7:30:27that, we are using uh an action called
  9370. 7:30:30cache, which is a very handy uh GitHub
  9371. 7:30:34action that allows us to cache stuff and
  9372. 7:30:37uh as you can see the continuation is
  9373. 7:30:39here. So here we basically define the
  9374. 7:30:41keys where we want to store um the cache
  9375. 7:30:44for playright and here we just check. So
  9376. 7:30:48here if there is no cache we will
  9377. 7:30:50execute this function that will install
  9378. 7:30:53here I want to run the tests on Chrome
  9379. 7:30:56and Firefox I don't want to use Safari
  9380. 7:30:59otherwise if we if we have downloaded
  9381. 7:31:02the the browsers previously we will just
  9382. 7:31:05uh go here and as you can see we have an
  9383. 7:31:06if block so if we have the cache so we
  9384. 7:31:10are checking if it is true that means we
  9385. 7:31:12can just reuse that and we don't need so
  9386. 7:31:15if we look at the difference between the
  9387. 7:31:17You can see that here we have with
  9388. 7:31:19dependencies
  9389. 7:31:20and this takes more time. Uh but if we
  9390. 7:31:23have things in the cache that will make
  9391. 7:31:25things faster. So after all of these
  9392. 7:31:28steps you can see that this is why I
  9393. 7:31:30said that end to end tests uh this
  9394. 7:31:32workflow is going to involve a lot of uh
  9395. 7:31:35work but we are just reusing what we
  9396. 7:31:37already have in the other workflows. So
  9397. 7:31:40after setting up all of these s servers
  9398. 7:31:44we can run the end to end tests and uh
  9399. 7:31:47in package.json JSON I have this script
  9400. 7:31:50that will run end to end tests and here
  9401. 7:31:53I pass environment CI to true to
  9402. 7:31:56differentiate between because you can
  9403. 7:31:58run end to end tests locally on your
  9404. 7:32:00laptop and or in this case we run it on
  9405. 7:32:04G using a GitHub runner and finally
  9406. 7:32:07after the the end of uh the tests we
  9407. 7:32:11will upload the report we will use the
  9408. 7:32:13upload artifact action and that will
  9409. 7:32:17allow us to download the report and
  9410. 7:32:19reports are amazing. Locally when the
  9411. 7:32:23tests finish uh playright will open a
  9412. 7:32:26new tab and show you the report. But
  9413. 7:32:28here since we are running this on GitHub
  9414. 7:32:31we can't open a new tab. So we need to
  9415. 7:32:33download a file that will that contains
  9416. 7:32:36the report. We can check it later. We
  9417. 7:32:38can see screenshots. Yeah, it's uh it's
  9418. 7:32:41really handy. Okay. So this is the end
  9419. 7:32:43to end tests and this will run as I said
  9420. 7:32:47on the cloud using GitHub actions. But
  9421. 7:32:50what if you want to run this locally?
  9422. 7:32:52For that I mean here on the repository
  9423. 7:32:54everything is set up already. Uh you can
  9424. 7:32:57see that we have this playright
  9425. 7:32:59configuration file that will come when
  9426. 7:33:01you install playright. And the way you
  9427. 7:33:03do it is simple. You just you just run
  9428. 7:33:07pnpm create playrite and this will
  9429. 7:33:10install playright for you. When you do
  9430. 7:33:12this the playright configuration JSON
  9431. 7:33:15will be created with some default
  9432. 7:33:16values. Maybe there um this command will
  9433. 7:33:20also create a uh some tests so that you
  9434. 7:33:23can just uh make sure that playright is
  9435. 7:33:26running but you can delete all of that.
  9436. 7:33:29Let's run the command together and let's
  9437. 7:33:30see what happens. You can see that here
  9438. 7:33:32it says do you want to use typescript or
  9439. 7:33:35javascript. In my case this project was
  9440. 7:33:37using javascript that's why I kept
  9441. 7:33:39javascript but if you rely on typescript
  9442. 7:33:43uh change that to typescript and here
  9443. 7:33:45they tell you where to put your end
  9444. 7:33:47toend tests. Uh in my case if I look at
  9445. 7:33:49the front end I always try to group my
  9446. 7:33:51tests so they are inside the end to end
  9447. 7:33:54tests. So here the default value is end
  9448. 7:33:56to end. Okay let's just keep it as end
  9449. 7:33:59to end test. uh add a GitHub actions
  9450. 7:34:01workflow. I mean no because we have we
  9451. 7:34:04did it ourselves. And here this step
  9452. 7:34:08tells you do you want to install
  9453. 7:34:10playright browsers? This can be done
  9454. 7:34:12manually via pmppm execute playright
  9455. 7:34:15install. And this is the exact command
  9456. 7:34:19that we have here. As you can see pmppm
  9457. 7:34:21exe execute playright. Let's install
  9458. 7:34:24them because in this machine we don't
  9459. 7:34:26have them. install play operating system
  9460. 7:34:28dependencies. Why not? And you do this
  9461. 7:34:32once and later you don't need to uh
  9462. 7:34:35install the browsers every single time.
  9463. 7:34:37Okay, so this finished. There was
  9464. 7:34:40something that was added to uh the logs
  9465. 7:34:43to the log files, but I I won't change
  9466. 7:34:46this. It's not important. So I'll just
  9467. 7:34:48undo this. I just wanted to show you the
  9468. 7:34:50steps that you need to run. And uh okay,
  9469. 7:34:53let's see what we have here. Okay. So,
  9470. 7:34:56we didn't override the file because it
  9471. 7:34:58found it. But uh in your case, if you
  9472. 7:35:01don't have this file, this is going to
  9473. 7:35:02be created for you. So, let's go through
  9474. 7:35:04it together in order to understand what
  9475. 7:35:06we have here. First of all, we tell
  9476. 7:35:09playright that our end to end tests are
  9477. 7:35:12located inside this folder. We want to
  9478. 7:35:15run things in parallel so that tests uh
  9479. 7:35:19finish quickly. Here we set the number
  9480. 7:35:22of retries. So if we are on CI sometimes
  9481. 7:35:25tests fail randomly so we want to retry
  9482. 7:35:28them but if you are locally we won't
  9483. 7:35:30retry anything here forbid only is
  9484. 7:35:34sometimes when you run end to end tests
  9485. 7:35:37you can tell player to run just one but
  9486. 7:35:40in our CI job we want to run everything
  9487. 7:35:43so this will fail if you tell player to
  9488. 7:35:45run one one test only because it's going
  9489. 7:35:48to skip the other ones and we don't want
  9490. 7:35:50to allow that. Here we have reporter.
  9491. 7:35:53This is also important because when you
  9492. 7:35:55run uh tests locally as I said you can
  9493. 7:35:58get an HTML page that will show you what
  9494. 7:36:02failed, what succeeded. Uh but if we are
  9495. 7:36:05in CI we are running this on GitHub. So
  9496. 7:36:07we need to to tell play that please show
  9497. 7:36:09us nice logs on GitHub. Here we define
  9498. 7:36:12the projects. You can see that I I am
  9499. 7:36:14using Chromium and Firefox. If you want
  9500. 7:36:17you can also add Safari down below. Uh
  9501. 7:36:19you can change this however you like.
  9502. 7:36:21And finally we have something very
  9503. 7:36:23interesting which is web server. This is
  9504. 7:36:26this will allow playright to run the
  9505. 7:36:28server the front end for you. So if you
  9506. 7:36:30forget to add a step to run the front
  9507. 7:36:33end playright will use this command to
  9508. 7:36:36start it for you and you tell it the URL
  9509. 7:36:39or and here the use existing server is
  9510. 7:36:42uh is interesting. So if uh we started
  9511. 7:36:46the server manually play will see that
  9512. 7:36:49oh the user has started the server so I
  9513. 7:36:52don't need to run this command. This is
  9514. 7:36:54why we use uh reuse existing server and
  9515. 7:36:56again we have timeout. Awesome. So now
  9516. 7:37:00we can close this. Let's open uh ci.yml
  9517. 7:37:04and let's add end to end tests there.
  9518. 7:37:08Okay we have integration tests. Let's
  9519. 7:37:11add end to end test underneath it. Copy
  9520. 7:37:14this and let's paste it here and let's
  9521. 7:37:18see what did I do in the needs um list.
  9522. 7:37:23So I am waiting for the integration
  9523. 7:37:26tests and also unit tests uh in the
  9524. 7:37:29front from the front end. Okay, let's
  9525. 7:37:31now commit this add end to end tests
  9526. 7:37:34commit and push. Okay, uh the tests are
  9527. 7:37:40running. Let's look at the details page.
  9528. 7:37:43Let's go back to summary and let's
  9529. 7:37:45ensure that the end to end test is
  9530. 7:37:48correctly placed. Yes, it is. You can
  9531. 7:37:50see that it is waiting for the front end
  9532. 7:37:53unit tests and the backend integration
  9533. 7:37:56tests. I will wait for these jobs to
  9534. 7:37:59finish and I will come back once the end
  9535. 7:38:01to end tests uh start. I am back and as
  9536. 7:38:04you can see so far everything is green.
  9537. 7:38:08Uh and wait yes the end to end tests
  9538. 7:38:10started because uh front the unit tests
  9539. 7:38:14in front end and integration tests in
  9540. 7:38:16back end didn't fail. Let's click here
  9541. 7:38:18and let's see what is happening. We are
  9542. 7:38:20now installing the backend dependencies.
  9543. 7:38:23We are downloading millarch. Good. That
  9544. 7:38:26worked. Now we are starting the mill
  9545. 7:38:28search server. That worked also. Let's
  9546. 7:38:32now start the backend server using
  9547. 7:38:34uicorn. And as you can see, we were able
  9548. 7:38:36to ping the health endpoint. We seeded
  9549. 7:38:40the M search with 15 documents. We've
  9550. 7:38:44installed PNPM node. And now we are
  9551. 7:38:48installing the playright browsers. And
  9552. 7:38:49as you can see, this takes time because
  9553. 7:38:52now as you can see, we are in the if no
  9554. 7:38:54cache state in the upcoming commits. Uh
  9555. 7:38:57this will not run and it's instead it's
  9556. 7:39:00going to to download to take the
  9557. 7:39:02browsers from the cache. Okay. Yeah, as
  9558. 7:39:05I said, this takes some time. Where are
  9559. 7:39:08we at? Okay, so it took 30 seconds.
  9560. 7:39:11Okay, and now we are you can see that
  9561. 7:39:13this the other the the other step was
  9562. 7:39:15skipped because we don't have any cache
  9563. 7:39:18and now we are running the end to end
  9564. 7:39:20tests and as you can see we have 178
  9565. 7:39:22tests and here we are using two workers.
  9566. 7:39:25So they are going to run the tests in
  9567. 7:39:27parallel. You can see that the tests are
  9568. 7:39:30uh so here we are running the first one,
  9569. 7:39:32second one, third one but now they start
  9570. 7:39:34randomly because we are running them uh
  9571. 7:39:36not in a sequential order but in
  9572. 7:39:38parallel. Okay, end to end tests usually
  9573. 7:39:42take minutes to finish and it depends on
  9574. 7:39:44how you uh design them. Mine uh mine
  9575. 7:39:48will take around 3 minutes to finish. So
  9576. 7:39:51I will stop the video here and I will
  9577. 7:39:54come back. We are almost done. Uh we
  9578. 7:39:57have 178 tests. Let's see. So they that
  9579. 7:40:01should finish now. And uh all of them
  9580. 7:40:03succeeded. You can see it took 3
  9581. 7:40:05minutes. And here, okay, we are trying
  9582. 7:40:08to upload the report. And awesome.
  9583. 7:40:12Everything works. Let's go back to
  9584. 7:40:14summary. Amazing. You can see that the
  9585. 7:40:17pi the whole pipeline took almost 7
  9586. 7:40:20minutes. Okay, let's wait for the last
  9587. 7:40:23or let's go back. Let's go back here. Uh
  9588. 7:40:26yeah, everything passed. Amazing. Now
  9589. 7:40:29what I would like to do is I want to
  9590. 7:40:31make a small change just to show you
  9591. 7:40:33that the cache is working. Let's see
  9592. 7:40:36what should I do here. I will just
  9593. 7:40:39remove this comma from this file cuz
  9594. 7:40:43it's not needed. So sure, remove extra
  9595. 7:40:48comma and let's push this. Let's go back
  9596. 7:40:51to GitHub. Okay, everything is uh okay.
  9597. 7:40:57Let's click on summary and let's wait
  9598. 7:41:00for end to end tests to start and
  9599. 7:41:02hopefully this time we should see that
  9600. 7:41:04we will be uh we will uh run the if
  9601. 7:41:08cache uh step. The end to end tests job
  9602. 7:41:12has started. Let's wait for Okay, so we
  9603. 7:41:16are now in the front end area. Okay, we
  9604. 7:41:19are installing the dependencies.
  9605. 7:41:22Let's see what we have here. So we are
  9606. 7:41:24looking at the cache and as you can see
  9607. 7:41:26that worked. Uh let me collapse this.
  9608. 7:41:29Before we ran this step if no cache but
  9609. 7:41:33now we run we are running this other
  9610. 7:41:36step if cash hit. Before this step took
  9611. 7:41:4030 seconds but now this one took almost
  9612. 7:41:43half of that. It's just 15 seconds but
  9613. 7:41:46it's it's working. It's better than
  9614. 7:41:48nothing. And yeah, the end to end test
  9615. 7:41:51will succeed and uh uh yeah, everything
  9616. 7:41:53will work. Let's create a new workflow
  9617. 7:41:57called dast scan. I will copy the code
  9618. 7:42:01and paste it here and let's see what it
  9619. 7:42:04does. First of all, you can see that we
  9620. 7:42:07are we also need my search because here
  9621. 7:42:10we are going to scan the API. First of
  9622. 7:42:12all, we are checking the repository. We
  9623. 7:42:15set up Python. We install the
  9624. 7:42:17dependencies. We download me search. We
  9625. 7:42:21run it. Here we see the data because we
  9626. 7:42:23want to have something in me search. We
  9627. 7:42:26start the back end. And uh finally this
  9628. 7:42:29is the new step uh that will use the zap
  9629. 7:42:34project. And if you are not familiar
  9630. 7:42:37with zap here it is. You can check their
  9631. 7:42:40website. Uh it's an amazing project.
  9632. 7:42:42It's free and open source. And uh we you
  9633. 7:42:45can use it to scan your applications.
  9634. 7:42:48And they have good documentation as
  9635. 7:42:50well. We will use this in this video
  9636. 7:42:52because by default this scan is going to
  9637. 7:42:57flag a lot of things that are uh that
  9638. 7:43:01are not problematic because we are not
  9639. 7:43:03in production. Well, I will show you I
  9640. 7:43:06will show you that. So let's look at
  9641. 7:43:08this step. You can see that we are using
  9642. 7:43:10a GitHub action provided by the Zap
  9643. 7:43:13team. And here the target is the open
  9644. 7:43:16API endpoint. Because we are using fast
  9645. 7:43:20API by default it gives us all the
  9646. 7:43:23endpoints in our back end. And this is
  9647. 7:43:26useful because Zap will use this in
  9648. 7:43:29order to know which endpoints to target.
  9649. 7:43:32The format is open API. And here you can
  9650. 7:43:36see that I'm referring to a file uh
  9651. 7:43:40called zap rules. Right now I will just
  9652. 7:43:42delete this one because we don't have it
  9653. 7:43:44and I will I want to do this so that you
  9654. 7:43:47understand the reason why we add this
  9655. 7:43:49specific file. I have deleted that line.
  9656. 7:43:53Now open ci.l because we need to add
  9657. 7:43:55this scan here in the main pipeline. I
  9658. 7:43:59will scroll up. Let's look at backend
  9659. 7:44:02length and format. I want to put it uh
  9660. 7:44:06or I want to run it after LinkedIn. So,
  9661. 7:44:09let me let's go down below. Let's paste
  9662. 7:44:12it here. And as you can see uh it's
  9663. 7:44:16going to run after the l after the lint
  9664. 7:44:18job. Now, copy it and paste it here.
  9665. 7:44:23Now, let's commit this. Add dust and
  9666. 7:44:26let's push it to the repository. Let's
  9667. 7:44:30go back. Let's click on the the pull
  9668. 7:44:32request. Scroll down and let's see. We
  9669. 7:44:36should see the pipeline running. Okay,
  9670. 7:44:39that's good. Let's try to see to look at
  9671. 7:44:42the details. Click on summary and let's
  9672. 7:44:45wait for dust to run. As you can see, it
  9673. 7:44:49should be right after. Yeah, it is after
  9674. 7:44:53uh backend link and format. You can see
  9675. 7:44:55that right now we have two kinds of
  9676. 7:44:57tests. We have sust and dust. The
  9677. 7:45:01difference is that SAS checks your row
  9678. 7:45:04source code for security flows. But some
  9679. 7:45:07security problems only appear while
  9680. 7:45:10interacting with with your application.
  9681. 7:45:12This is where Dusk comes in and this is
  9682. 7:45:15why we started mini search and the back
  9683. 7:45:17end and we gave it as the target the
  9684. 7:45:20open API spec so that when it looks at
  9685. 7:45:23that at those endpoints it's going to
  9686. 7:45:25attack them like any uh attacker would
  9687. 7:45:28do uh in order to find vulnerabilities
  9688. 7:45:31in your application. And as you can see
  9689. 7:45:34right now it failed. Okay. So why did it
  9690. 7:45:36fail? It failed because it couldn't
  9691. 7:45:39download me search. You can see that
  9692. 7:45:41even though we did three attempts, so
  9693. 7:45:44the first one failed, the second one
  9694. 7:45:47failed and the third one also failed. Uh
  9695. 7:45:49if this happens for you, no problem. You
  9696. 7:45:52can just go back and rerun the job.
  9697. 7:45:55Okay, so I can run rerun failed jobs. Uh
  9698. 7:45:59it gives me all of these. So I'll hit
  9699. 7:46:01rerun. Okay, let's wait for now. Let's
  9700. 7:46:05click again on this job. Hopefully this
  9701. 7:46:08time we will be able to download Mary
  9702. 7:46:10search. Sadly it failed again for some
  9703. 7:46:13reason. I'm not sure why. I guess we
  9704. 7:46:15just need to wait a little bit and
  9705. 7:46:17retry. They tell us to download this
  9706. 7:46:20manually from GitHub. But yeah, we
  9707. 7:46:23cannot do that here in the pipeline. We
  9708. 7:46:26we will need to change that specific
  9709. 7:46:28step. Okay, I will just I'll try to
  9710. 7:46:31rerun it one more time. If it fails
  9711. 7:46:33again, I will wait for a few minutes and
  9712. 7:46:36come back. I did some research and I
  9713. 7:46:38think the problem that we have here is
  9714. 7:46:40that if we look at their latest version,
  9715. 7:46:43you can see that it was released 14
  9716. 7:46:46minutes ago. But creating the assets
  9717. 7:46:49take time. You can see that for example
  9718. 7:46:51this one was just created a minute ago
  9719. 7:46:53even though the release was pushed 15
  9720. 7:46:56minutes ago. So that's why we are
  9721. 7:46:59getting 404s because um the installer
  9722. 7:47:03script is trying to download something
  9723. 7:47:06from GitHub that doesn't exist yet. This
  9724. 7:47:09is why we are getting uh 404 not found.
  9725. 7:47:13So we have two options here. We need to
  9726. 7:47:17wait a little bit to get the new file
  9727. 7:47:21and then we can run the script again or
  9728. 7:47:24in the future we need to update this to
  9729. 7:47:28download a specific version because here
  9730. 7:47:31when we run the installer script we try
  9731. 7:47:34to download the latest version or the
  9732. 7:47:37latest tag from GitHub and in this case
  9733. 7:47:40it is
  9734. 7:47:42146.1
  9735. 7:47:43right now I will keep the script like
  9736. 7:47:45this. But uh right after uh explaining
  9737. 7:47:49the dust scan, I will go back and I will
  9738. 7:47:51show you how to update only this
  9739. 7:47:54specific step to uh download a specific
  9740. 7:47:58version. And uh yeah, we will remove
  9741. 7:48:00this line because it downloads all it
  9742. 7:48:03tries to download the latest version
  9743. 7:48:05always. Okay, I rerun the script and uh
  9744. 7:48:09as you can see it worked because now we
  9745. 7:48:11we have uh the assets were created and
  9746. 7:48:15uh the installer script was able to get
  9747. 7:48:18it from GitHub. Awesome. So now let's
  9748. 7:48:20see as you can see the zap scan step is
  9749. 7:48:23running and uh okay so here let's see
  9750. 7:48:27what we have. We see a deprecation
  9751. 7:48:30warning that's fine. We can uh avoid
  9752. 7:48:33that. You can see that here it found 15
  9753. 7:48:35URLs and it was able to find them
  9754. 7:48:38because we provided the open API spec
  9755. 7:48:41and uh here I want to mention that the
  9756. 7:48:44dust scan that we are using is
  9757. 7:48:46lightweight because it is targeting just
  9758. 7:48:48the back end but we can also have a
  9759. 7:48:52serious one that will check the front
  9760. 7:48:53end as well. That one takes a lot of
  9761. 7:48:56time. This is why I didn't include it in
  9762. 7:48:58the main pipeline. Instead, we will
  9763. 7:49:01create another file that will uh have
  9764. 7:49:04the full dust scan and we will run it
  9765. 7:49:07daily um outside of the the pipeline
  9766. 7:49:10because we don't want to block
  9767. 7:49:12everything just to perform that heavy
  9768. 7:49:15scan and as as you can see this thing
  9769. 7:49:18has failed and uh I was expecting that.
  9770. 7:49:21Uh let's see what we have here. You can
  9771. 7:49:23see that it checks a lot of things and
  9772. 7:49:26most of them passed. As you can see,
  9773. 7:49:28everything passed except some problems.
  9774. 7:49:32And as you can see here, it says X
  9775. 7:49:34content type options header is missing.
  9776. 7:49:36Uh let's see what we have. We also have
  9777. 7:49:38cross origin resource policy missing.
  9778. 7:49:42And as I told you, we will have these
  9779. 7:49:44problems because we are running this in
  9780. 7:49:46a CI environment. It's not running in
  9781. 7:49:50production. And if you remember in the
  9782. 7:49:52past we have we have resolved these
  9783. 7:49:56problems and in our application that we
  9784. 7:49:58deployed we are using engineext we added
  9785. 7:50:01the HTTP security headers so everything
  9786. 7:50:04is set up already and zap is telling us
  9787. 7:50:07that these are missings that's that's
  9788. 7:50:09correct because we are running on a CI
  9789. 7:50:11environment this is why we add that
  9790. 7:50:15specific file that I was talking about
  9791. 7:50:18because it allows us to tell zap to skip
  9792. 7:50:22those specific tests. Here I will just
  9793. 7:50:25add rules file name and we need to
  9794. 7:50:28create this one in the GitHub folder. Uh
  9795. 7:50:32let's create it here. Uh it's already
  9796. 7:50:34there. Okay. So let's look at it. Here
  9797. 7:50:37is the zap rules file and this is
  9798. 7:50:40specific to my codebase. So if you add
  9799. 7:50:44dust to your codebase, you might have
  9800. 7:50:47different warnings. So in that case you
  9801. 7:50:50need to change this list. So how do we
  9802. 7:50:52do this? If I open let let me show you.
  9803. 7:50:55So here we have ids and the format is
  9804. 7:50:59simple. You have the ID of the rule.
  9805. 7:51:01It's the first column. You have the
  9806. 7:51:03action and you have a comment. So here
  9807. 7:51:07we tell zap to ignore all of these rules
  9808. 7:51:12because here the action is ignore. And
  9809. 7:51:14this comment is for us so that we can
  9810. 7:51:16understand what is happening here. How
  9811. 7:51:18do we get these rule ids? You can get
  9812. 7:51:21them from their documentation. You can
  9813. 7:51:24see that here. For example, if we open
  9814. 7:51:26this active scan rules, you have the ids
  9815. 7:51:30here. So they they show you the rule,
  9816. 7:51:33they explain it and they also give you
  9817. 7:51:35the ID. There is also this website that
  9818. 7:51:38I will make sure to drop in the video
  9819. 7:51:41description where you can find uh every
  9820. 7:51:45every rule. And here if we search for
  9821. 7:51:47cross origin which is basically this
  9822. 7:51:50error that we got here. Now you can see
  9823. 7:51:53the ID is 90,000 and4. Here it is. You
  9824. 7:51:57can see that we have uh uh a lot of them
  9825. 7:52:00here. And yeah you can use this website
  9826. 7:52:03to uh learn more about uh these specific
  9827. 7:52:07rules. And if you want to read it you
  9828. 7:52:10can click on it and you will find here a
  9829. 7:52:12summary solution etc. Okay. And uh we
  9830. 7:52:15can you can also find the ids here
  9831. 7:52:17directly from the logs. Uh so for
  9832. 7:52:19example here I can take this id and uh
  9833. 7:52:23paste it here in the rules. Uh here it
  9834. 7:52:26is. You can see 10,21
  9835. 7:52:29uh and I have added it here. Once you do
  9836. 7:52:31this the errors are going to go away.
  9837. 7:52:34But make sure to not skip everything.
  9838. 7:52:37Skip only the things that are related to
  9839. 7:52:39a production environment. And as you can
  9840. 7:52:41see here, many things are handled by
  9841. 7:52:44EngineX. That's why I've added them
  9842. 7:52:46here. And for example, this one is
  9843. 7:52:48failing because we are running this as
  9844. 7:52:51HTTP. We are not using HTTPS. And again,
  9845. 7:52:54because we are not in production. This
  9846. 7:52:56is fine. There is no problem with that.
  9847. 7:52:59Here we have a problem with timestamps
  9848. 7:53:01because M search uses Unix timestamps.
  9849. 7:53:04It doesn't use other formats. And here
  9850. 7:53:07uh Zap is thinking that this is a
  9851. 7:53:09problem. But in fact that's how med
  9852. 7:53:12search works. Okay. Now what I will try
  9853. 7:53:15to update this uh so let's say CI add
  9854. 7:53:21zap rules commit this. Let's sync the
  9855. 7:53:24changes and let's see what will happen
  9856. 7:53:27this time. I'll go back to the pull
  9857. 7:53:30requests. Let's look at the pipeline in
  9858. 7:53:33detail. Go to summary. Let's click on
  9859. 7:53:37OASP zap API scan. Uh we need to wait
  9860. 7:53:40for it first to start. Okay, let's see
  9861. 7:53:44the now we are auditing the backend
  9862. 7:53:46dependencies. This should pass without
  9863. 7:53:49any problem. Great, that worked. Now
  9864. 7:53:52let's go to LinkedIn and formatting. And
  9865. 7:53:55now let's look at the dust scan. The
  9866. 7:53:59scan has started again. It found 15
  9867. 7:54:03URLs. And as you can see, it is using
  9868. 7:54:06our zap rules file. Okay, let's see now
  9869. 7:54:09what will happen. Hopefully, it's uh
  9870. 7:54:12it's not going to fail. And yes, it
  9871. 7:54:14didn't. Let's see what we have here.
  9872. 7:54:17Okay, you can see that they tested 197
  9873. 7:54:22uh rules or URLs.
  9874. 7:54:24Um so all of them passed and again we
  9875. 7:54:27have those problems with timestamp,
  9876. 7:54:29cross origin, etc. because we have added
  9877. 7:54:32them to zap rules the zap project or the
  9878. 7:54:37zap tool is not failing it is skipping
  9879. 7:54:40them and u that's why uh the pipeline
  9880. 7:54:44has passed something to note is that
  9881. 7:54:47over time this file will stabilize I'm
  9882. 7:54:50talking about zap rules because
  9883. 7:54:52especially if you keep adding more
  9884. 7:54:54endpoints if you keep expanding your
  9885. 7:54:56backend application yeah zap is going to
  9886. 7:54:59find some uh small issues that you can
  9887. 7:55:02skip. After you do that job once, when
  9888. 7:55:06you get an error in your CI pipeline, it
  9889. 7:55:09means that you have a real security
  9890. 7:55:12issue that needs your immediate
  9891. 7:55:14attention. Right now, uh you can see
  9892. 7:55:16that we got a few errors because uh we
  9893. 7:55:19are just setting up D for the first time
  9894. 7:55:22and that's normal because uh by default
  9895. 7:55:25these tools are trying to find anything.
  9896. 7:55:28So that's why you get false alarms. But
  9897. 7:55:31once you handle those, you you are good
  9898. 7:55:34to go. And uh when you get an error,
  9899. 7:55:37that's a good that's a good signal that
  9900. 7:55:39something bad is happening. Great. And
  9901. 7:55:41as you can see, the other steps are are
  9902. 7:55:43also running without any problem. So we
  9903. 7:55:46were able to run integration tests. End
  9904. 7:55:48to end test should also pass. And
  9905. 7:55:50finally, we will uh the pipeline will
  9906. 7:55:52succeed. Awesome. We have done
  9907. 7:55:54everything uh in this sub chapter. But
  9908. 7:55:58uh let's let me also show you how to
  9909. 7:56:01update the download step so that you can
  9910. 7:56:03install a specific version. I'm not
  9911. 7:56:06going to apply that to the to all files
  9912. 7:56:08because I like to download the last
  9913. 7:56:10version and I don't want to go update
  9914. 7:56:13the the file and then commit to be able
  9915. 7:56:16to download the last version. But if you
  9916. 7:56:18are curious about how we can accomplish
  9917. 7:56:20this, here is how to do this. I will uh
  9918. 7:56:23remove all of this and I will paste
  9919. 7:56:26this. Okay. And now what do we need to
  9920. 7:56:28do? We need to go to GitHub. Click on
  9921. 7:56:31releases. And here the last one is
  9922. 7:56:34146.1.
  9923. 7:56:36I will take this. I will take this one.
  9924. 7:56:39So here we need to change this variable
  9925. 7:56:42to uh target this specific tag. Here we
  9926. 7:56:46are just echoing this message. And uh
  9927. 7:56:50here in the curl command we have uh this
  9928. 7:56:53handy arguments that we can use. Before
  9929. 7:56:57we uh we had to add these environment
  9930. 7:56:59variables. Yeah. Because we had an
  9931. 7:57:02external loop. But here we can do that.
  9932. 7:57:04We can do it directly with curl. So if
  9933. 7:57:08uh the command fails we retry three
  9934. 7:57:11times and between each retry we wait for
  9935. 7:57:135 seconds. And we are we go to the
  9936. 7:57:16releases page download version and we
  9937. 7:57:19download this specific binary. After we
  9938. 7:57:22do that we uh make it executable so that
  9939. 7:57:25we can start it. And uh you can see it
  9940. 7:57:28is smaller than the previous solution.
  9941. 7:57:31But this one requires you to always open
  9942. 7:57:33the file, update this commit, push and
  9943. 7:57:37wait for the pipeline to finish. That's
  9944. 7:57:39the the difference between the two. But
  9945. 7:57:41if you prefer this, you can keep it. Uh
  9946. 7:57:44in my case, as I said, I will not keep
  9947. 7:57:46that one. I I like to always download
  9948. 7:57:48the last version. We have arrived at the
  9949. 7:57:51end of this sub chapter. I really hope
  9950. 7:57:52that you enjoyed it. In my case, I I
  9951. 7:57:55did. And uh it's always great to
  9952. 7:57:58struggle to build a pipeline because
  9953. 7:58:00once you do, uh you you see this uh
  9954. 7:58:03amazing view where everything is green.
  9955. 7:58:06And um yeah, it's super super useful.
  9956. 7:58:10And now we finished the continuation the
  9957. 7:58:12continuous integration pipeline. In the
  9958. 7:58:15next uh subchapter we will work on
  9959. 7:58:18continuous delivery which is also
  9960. 7:58:20amazing. Uh we will connect this
  9961. 7:58:23pipeline to our virtual machine on
  9962. 7:58:26digital ocean. to that if uh this step
  9963. 7:58:29which I'm I'm referring to continuous
  9964. 7:58:31integration passes we will click on a
  9965. 7:58:34button to deploy the built application
  9966. 7:58:38directly without having to SSH to the VM
  9967. 7:58:42copy the code run some some commands we
  9968. 7:58:46will create a a workflow that will do
  9969. 7:58:48this for us and we will just hit the
  9970. 7:58:51button wait for a minute or two and see
  9971. 7:58:54the new version live on the website. We
  9972. 7:58:57will also update this pipeline because
  9973. 7:59:00you can see that pipeline success
  9974. 7:59:01depends on every job before it. So the
  9975. 7:59:06so the graph looks a little bit ugly.
  9976. 7:59:08But we just need to look at the last
  9977. 7:59:12job. We we need to wait for end to end
  9978. 7:59:14tests because if we wait for this job,
  9979. 7:59:17we are waiting for this one. This one we
  9980. 7:59:20are waiting for every previous job. So
  9981. 7:59:22we don't need to uh make this uh let's
  9982. 7:59:27go back to CI we can simplify this needs
  9983. 7:59:30to just uh the end to end tests we know
  9984. 7:59:33we don't need to have all of them
  9985. 7:59:36because implicit they are implicitly uh
  9986. 7:59:39within the end to end tests if we are
  9987. 7:59:41waiting for that specific job. So we
  9988. 7:59:43will do some optimizations to make the
  9989. 7:59:45pipeline uh cleaner and uh yeah that sub
  9990. 7:59:49chapter will be the the last one in
  9991. 7:59:51module 5. After that we will move to
  9992. 7:59:54module six which is the last module in
  9993. 7:59:56our course. See you in the next sub
  9994. 7:59:59chapter. We have arrived at continuous
  9995. 8:00:02delivery. This is the last subchapter in
  9996. 8:00:06module 5 and here are the things that we
  9997. 8:00:09are going to talk about. I will show you
  9998. 8:00:11how to compile and upload the static
  9999. 8:00:14view front end. You will trigger
  10000. 8:00:16automated database and search engine
  10001. 8:00:19backups. Before deploying, we are going
  10002. 8:00:22to require a human review using GitHub
  10003. 8:00:26environments. And finally, we will
  10004. 8:00:28execute an atomic virtual environment
  10005. 8:00:31roll back strategy. So if something bad
  10006. 8:00:34happened, we can go back to the previous
  10007. 8:00:37working version. In the [clears throat]
  10008. 8:00:38last sub chapter, we have built this
  10009. 8:00:42pipeline and the last step is end to end
  10010. 8:00:47tests. What are we going to do before
  10011. 8:00:49moving to continuous delivery is to also
  10012. 8:00:51add front end build. So we will try to
  10013. 8:00:54build the front end to make sure that
  10014. 8:00:55there is no syntax error that there is
  10015. 8:00:57no problem in the dependencies that we
  10016. 8:01:00are using before finishing the
  10017. 8:01:02continuous integration pipeline. I have
  10018. 8:01:05I forgot to add this in the previous sub
  10019. 8:01:07chapter but we are going to add it now.
  10020. 8:01:09Open the GitHub folder. Open workflows
  10021. 8:01:13and add this new file content build.yml.
  10022. 8:01:18But before I do that I need to change to
  10023. 8:01:21test number two because this is the
  10024. 8:01:23branch that we were using. Okay, let's
  10025. 8:01:25now try to create the file. Okay, now we
  10026. 8:01:28are able to create it. I will copy and
  10027. 8:01:31paste the code here. It is similar to
  10028. 8:01:34what we have done before. The name here
  10029. 8:01:36is build front end. First we check the
  10030. 8:01:38repository. We use pmppm version 11. We
  10031. 8:01:43install the dependencies and after that
  10032. 8:01:45we just run pmppm build. If everything
  10033. 8:01:47goes all right, that's what we want. But
  10034. 8:01:49if something bad happens, this job will
  10035. 8:01:52fail. After that, we are going to upload
  10036. 8:01:54the artifact so that if we want, we can
  10037. 8:01:57reuse the build files in a next job or
  10038. 8:02:01something like that. And the retention
  10039. 8:02:03days is set to one because because if
  10040. 8:02:05you add another feature, we are not
  10041. 8:02:08going to use this uh cache. So there is
  10042. 8:02:11no need for it. It's going to become old
  10043. 8:02:13and it's going to be uh removed. Now
  10044. 8:02:15let's open ci.l and let's add this job
  10045. 8:02:19there. Here is how we do this. I'm going
  10046. 8:02:21to come here and I want this to depend
  10047. 8:02:25on end to end tests because if this
  10048. 8:02:28succeeds I know that at least there is
  10049. 8:02:30no problem in the code so we can build
  10050. 8:02:33and here I will copy the job name and
  10051. 8:02:38let's put it below dust check and that's
  10052. 8:02:41all we need to add now commit all of
  10053. 8:02:44this let's go back to GitHub let's look
  10054. 8:02:47at the put requests the pipeline has
  10055. 8:02:49started I will Wait for the pipeline to
  10056. 8:02:52finish and I will come back. I am back
  10057. 8:02:54and as you can see the front end build
  10058. 8:02:57job has started. Let's click on it to
  10059. 8:03:00make sure that it works. Okay. So now we
  10060. 8:03:02are building the front end as you can
  10061. 8:03:04see and it should work. Uh this is just
  10062. 8:03:08a step that I wanted to add to ensure
  10063. 8:03:10that building the front end succeeds.
  10064. 8:03:13Great. And as you can see we get a green
  10065. 8:03:15check mark. Amazing. Now let's go back
  10066. 8:03:17to the pull request. Let's click on pull
  10067. 8:03:20requests here. Let's click on this one.
  10068. 8:03:24And let's make sure that everything is
  10069. 8:03:26green. Awesome. So now we have finished
  10070. 8:03:28working on continuous integration. Now
  10071. 8:03:31we will work on continuous delivery.
  10072. 8:03:34Before we start deploying the new built
  10073. 8:03:39files to digital ocean, I would like to
  10074. 8:03:42start with uh create working on two
  10075. 8:03:45things. First of all, a backup
  10076. 8:03:48management system. This is going to
  10077. 8:03:50ensure that the servers disk does not
  10078. 8:03:53fill up because if we keep creating
  10079. 8:03:56backups for let's say mail search uh and
  10080. 8:03:59maybe databases if we have them that
  10081. 8:04:02will eat a lot of storage and because we
  10082. 8:04:04are using a cheap digital ocean uh
  10083. 8:04:07virtual machine that's we don't have the
  10084. 8:04:10luxury to uh waste space. So we are
  10085. 8:04:12going to create a script that will clean
  10086. 8:04:14the backups for us and keep only the
  10087. 8:04:17last five. That means we need to SSH to
  10088. 8:04:21the server. Let me do that quickly. I am
  10089. 8:04:24back and as you can see I am logged in.
  10090. 8:04:27Now what I will try to do is the
  10091. 8:04:30following. I will create this clean
  10092. 8:04:32backups script in this location. Now I
  10093. 8:04:35need to provide my password. Great. Now
  10094. 8:04:38I will copy and paste the following code
  10095. 8:04:40and I will explain it to you. First we
  10096. 8:04:43have this keep count variable. Basically
  10097. 8:04:46this this is going to uh control how
  10098. 8:04:49many backups we want to keep. And by
  10099. 8:04:51default it's it is set to five. I will
  10100. 8:04:54keep it that like that but if we want we
  10101. 8:04:56can change it. Here we have a we have an
  10102. 8:04:58offset variable that will add one to
  10103. 8:05:02keep count. We are doing this because of
  10104. 8:05:05this uh huge command that we are running
  10105. 8:05:07here. So I will explain what we are
  10106. 8:05:09doing here. Basically this is a function
  10107. 8:05:11that we are calling here on two folders.
  10108. 8:05:14In my case in this application that I am
  10109. 8:05:17deploying I have mainly search and I
  10110. 8:05:20also have a SQLite database. So for me
  10111. 8:05:24search the backup is going to be stored
  10112. 8:05:26in the dumps folder and for SQLite I
  10113. 8:05:30will store that in the backups folder
  10114. 8:05:32inside the web application. So what I
  10115. 8:05:35want is that I want to give this path to
  10116. 8:05:38this function and keep only the last
  10117. 8:05:41five files inside each folder and this
  10118. 8:05:45is how we do it. So the target is
  10119. 8:05:48basically going to be the path that we
  10120. 8:05:50are passing to the function. If if the
  10121. 8:05:52path exists, we are going to show in the
  10122. 8:05:56screen that we are cleaning it. And um
  10123. 8:05:59after that here here is what we are
  10124. 8:06:01doing. First of all, we are using ls-tp
  10125. 8:06:05so that we can sort the files by time.
  10126. 8:06:08Here we use grap-v
  10127. 8:06:10and here we are inverting the search so
  10128. 8:06:13that we uh skip folders. This command
  10129. 8:06:16will only keep files. And here we have
  10130. 8:06:19tail dash n and we pass the offset here
  10131. 8:06:22and the plus that we are passing here is
  10132. 8:06:25going to basically give us all the files
  10133. 8:06:28that are older than uh offsets. So for
  10134. 8:06:31example if offset is set to six we are
  10135. 8:06:33going to start from there and it's going
  10136. 8:06:36to give me the backup that was from day
  10137. 8:06:38six day seven etc. And we use X arcs to
  10138. 8:06:42pass each file to the remove command.
  10139. 8:06:45It's going to be put here so that we can
  10140. 8:06:47remove it. And this is how this function
  10141. 8:06:50works. And if you want you can play with
  10142. 8:06:53this command on your own. You can copy
  10143. 8:06:55copy paste it and see how it how it
  10144. 8:06:57works. So if you now I can save the
  10145. 8:07:00file. I will exit. Let me show you.
  10146. 8:07:03Let's go back to web app. And as you can
  10147. 8:07:06see so far I don't have any backups
  10148. 8:07:08because I haven't deployed from GitHub.
  10149. 8:07:10But once we start doing that the backup
  10150. 8:07:13folder will be created and uh in terms
  10151. 8:07:16of med search we will have the backups
  10152. 8:07:19in the dumps folder. Now we need to make
  10153. 8:07:22the script executable using sudo chode
  10154. 8:07:25plus x. That's done. Great. Now we need
  10155. 8:07:29to do something interesting. So we need
  10156. 8:07:32to run sudo visudo. This is going to
  10157. 8:07:35allow us to run commands that typically
  10158. 8:07:39require us to enter the password because
  10159. 8:07:41we need to run them using pseudo. But we
  10160. 8:07:43are going to skip that. We are going to
  10161. 8:07:46run them without a password. Why do we
  10162. 8:07:48need to do that? Because uh in g on
  10163. 8:07:51GitHub, we are going to have a job that
  10164. 8:07:54will tell the virtual machine let's say
  10165. 8:07:57to restart engineext or to restart your
  10166. 8:08:00uh backend application. And for that we
  10167. 8:08:02need to run systemctl reload engineext
  10168. 8:08:05and but this requires us to enter sudo.
  10169. 8:08:08We are going to run this command. We go
  10170. 8:08:11at the end of the file and here we need
  10171. 8:08:13to add the following. I will paste this.
  10172. 8:08:16I'll go back to the beginning and I will
  10173. 8:08:18change the username to mine. So for
  10174. 8:08:21example my username is IAD but for make
  10175. 8:08:25sure to change this one. So here what do
  10176. 8:08:27we have? You can see that here we
  10177. 8:08:29specify that we want to run these
  10178. 8:08:31commands without a password. And the
  10179. 8:08:33commands that we that we want to allow
  10180. 8:08:37are systemctl reload engine x supervisor
  10181. 8:08:40ctl restart all and the cleanup scripts.
  10182. 8:08:44Other than that we the other commands
  10183. 8:08:47are going to require a password. Never
  10184. 8:08:50never never uh remove password because
  10185. 8:08:53that's insecure. Let's say that someone
  10186. 8:08:56was able to steal your SSH keys somehow
  10187. 8:09:00and they were able to log into the
  10188. 8:09:01virtual machine. The only thing they can
  10189. 8:09:03do is either reload EngineX, reload,
  10190. 8:09:06restart supervisor and uh run the
  10191. 8:09:09cleanup com backup script. If they want
  10192. 8:09:12to, let's say remove something from a a
  10193. 8:09:15directory owned by sudo by the root
  10194. 8:09:18user, they won't be able to because uh
  10195. 8:09:20Linux will prompt them for the password.
  10196. 8:09:23Okay. Now save the file and exit. Now I
  10197. 8:09:26would like to also explain to you this
  10198. 8:09:28specific file. Let's go. Let's use cat
  10199. 8:09:33and let's call that specific file rs
  10200. 8:09:36sync exclude. Here is what we have. What
  10201. 8:09:39why do we need to do this? Because we
  10202. 8:09:41want to copy the source code from GitHub
  10203. 8:09:45and put it here on digital ocean in this
  10204. 8:09:48specific virtual machine. And the way uh
  10205. 8:09:51we are going to accomplish this is with
  10206. 8:09:53a command called r sync. This is an
  10207. 8:09:56amazing tool that allows you to copy
  10208. 8:09:58files. But the problem is that it's
  10209. 8:10:01going to make sure that what we have
  10210. 8:10:04here on the virtual machine matches what
  10211. 8:10:06we have on GitHub. And the this causes a
  10212. 8:10:09problem because let's say that I added a
  10213. 8:10:11file that I want to have here on the
  10214. 8:10:14virtual machine but that I don't want to
  10215. 8:10:16push on GitHub. The problem is that
  10216. 8:10:18rsync is going to delete this specific
  10217. 8:10:20file that I added here on the virtual
  10218. 8:10:23machine. This is why I have added all of
  10219. 8:10:26this here. You can see that in rs sync
  10220. 8:10:28exclude I tell rync to never delete
  10221. 8:10:33these files from the virtual machine.
  10222. 8:10:36Keep them and uh keep them on top of
  10223. 8:10:39what we have on GitHub. Okay. So for
  10224. 8:10:42example we are keeping backups, we keep
  10225. 8:10:44the same file, we keep node modules etc.
  10226. 8:10:47These are things that I want to keep
  10227. 8:10:49here when I run the rs sync command. I
  10228. 8:10:52am showing you this because now we are
  10229. 8:10:54just preparing. We haven't yet wrote
  10230. 8:10:56wrote the deploy job but we will see
  10231. 8:10:59these things in that yl file. So don't
  10232. 8:11:02worry about this. We are just preparing
  10233. 8:11:04for that step. Great. So now we need to
  10234. 8:11:06go to go to GitHub because we need to
  10235. 8:11:08create an environment. I will show you
  10236. 8:11:10how to do this. Click on settings. Click
  10237. 8:11:13on environments. Click on new
  10238. 8:11:16environment. Here let's call it
  10239. 8:11:18production and click on configure
  10240. 8:11:21environment. Now click on required
  10241. 8:11:24reviewers. We are doing this so that as
  10242. 8:11:26I said when before deploying we will
  10243. 8:11:29have certain number of people that will
  10244. 8:11:31receive an email so that if they want
  10245. 8:11:34they can deploy the application. We
  10246. 8:11:36don't want the deployment to be
  10247. 8:11:38automatic. So that we just have one
  10248. 8:11:40layer of confirmation before confirming.
  10249. 8:11:44Here I will put my own account but if I
  10250. 8:11:46have other team members I can add them
  10251. 8:11:49here and just click on save protection
  10252. 8:11:51rules. Now we need to create a few
  10253. 8:11:54secrets. For that we need to go here
  10254. 8:11:57click on secrets and variables and click
  10255. 8:12:00on actions. These are secrets that are
  10256. 8:12:03going to be used in the deploy job. For
  10257. 8:12:05example, to connect to the virtual
  10258. 8:12:07machine, we need an SSH key. So that
  10259. 8:12:09this is why we need to create these
  10260. 8:12:11secrets inside the repository secrets
  10261. 8:12:15section. We click on this button. I will
  10262. 8:12:17add the following keys. So we need to
  10263. 8:12:20have four of them. We need to have the
  10264. 8:12:23IP address of the virtual machine, my
  10265. 8:12:26user, and uh we need the SSH key and
  10266. 8:12:30finally the mainly search master key.
  10267. 8:12:32These are all the keys that we need to
  10268. 8:12:34create. Let's start with adding the SSH
  10269. 8:12:38key. Now I will open my terminal. I will
  10270. 8:12:41create this a key using this command.
  10271. 8:12:44And here I will just add test test to
  10272. 8:12:48make it obvious. Yeah, let's hit enter.
  10273. 8:12:51So now we are generating the public and
  10274. 8:12:54private keys. And here the the command
  10275. 8:12:57is asking us to add a passphrase. We
  10276. 8:12:59should not add a passphrase. So just hit
  10277. 8:13:02enter. Hit enter again and the uh the
  10278. 8:13:04keys were generated. Why don't why we
  10279. 8:13:07shouldn't add a passphrase? Because when
  10280. 8:13:10we run the deploy job on GitHub, the the
  10281. 8:13:12job should run without being asked for a
  10282. 8:13:15passphrase. That's why we created a new
  10283. 8:13:17key just so that we can use it on GitHub
  10284. 8:13:20to connect to the virtual machine. Uh
  10285. 8:13:23use the cat command to print the public
  10286. 8:13:26key to screen and then copy it. I will
  10287. 8:13:29do that and I will come back. After
  10288. 8:13:31copying the key, go back to the virtual
  10289. 8:13:34machine. Run nano SSH authorized keys.
  10290. 8:13:39After you run this, paste the key in a
  10291. 8:13:42separate line. I will do that and I will
  10292. 8:13:44come back. My public key is now inside
  10293. 8:13:48the virtual machine. Now I need to go
  10294. 8:13:50back to my to the local terminal or to
  10295. 8:13:54the local machine and this time copy the
  10296. 8:13:58private key. Let me do this quickly. So
  10297. 8:14:01I'll just remove public and I'll run the
  10298. 8:14:04command. And here I have the WL copy
  10299. 8:14:07program that allows me to take the
  10300. 8:14:09output of this command and just uh copy
  10301. 8:14:12it to my clipboard. Now go back to
  10302. 8:14:15GitHub and here you need to paste the
  10303. 8:14:18private key in the secret input field
  10304. 8:14:21and use digital ocean SSH key as the
  10305. 8:14:24name. I will do that and and I will come
  10306. 8:14:26back. Awesome. So we are we were able to
  10307. 8:14:29create our first repository secret.
  10308. 8:14:32Later we can either update it or delete
  10309. 8:14:35it. Now let me add Digital Ocean
  10310. 8:14:38username. In this case it's a Mac. Let
  10311. 8:14:41me also add the host IP. And finally, I
  10312. 8:14:45need to add me search master key. If you
  10313. 8:14:48don't remember where we stored the me
  10314. 8:14:52search API key, run this command. sudo
  10315. 8:14:56nano etc me search environment. Copy it
  10316. 8:14:59from there. Paste it here and click on
  10317. 8:15:02add secret. As you can see, I have
  10318. 8:15:04created the four secrets that I will use
  10319. 8:15:07in the deploy job. We are now ready to
  10320. 8:15:11create the deploy job. First, open the
  10321. 8:15:15workflows folder and create a file
  10322. 8:15:19called deploy.yaml.
  10323. 8:15:21Now, let's look at the content of this
  10324. 8:15:23file. The name is manual deploy because
  10325. 8:15:26after merging a boot request, we want to
  10326. 8:15:29have the possibility to click on a
  10327. 8:15:32button manually to deploy the
  10328. 8:15:34application. The way we do that is by
  10329. 8:15:36adding workflow dispatch. We will see
  10330. 8:15:39this later when we merge this put
  10331. 8:15:41request on GitHub. We will have a button
  10332. 8:15:43that will allow us to manually run this
  10333. 8:15:46particular job. And here under jobs, we
  10334. 8:15:49have two. We have build and deploy.
  10335. 8:15:53Build is reusing the work the front- end
  10336. 8:15:56build workflow that we have created uh
  10337. 8:15:59in the CI pipeline. Now under deploy we
  10338. 8:16:03have the name is deploy. This needs to
  10339. 8:16:06run after the build process. And here
  10340. 8:16:09under environment, we have production
  10341. 8:16:12and we point it at the URL. If you have
  10342. 8:16:15different environments, make sure to
  10343. 8:16:16change this. But in our case, we have
  10344. 8:16:19just production. And now here are the
  10345. 8:16:21steps. We will start with the same steps
  10346. 8:16:24that we have seen in the previous
  10347. 8:16:26workflows. First, we check the
  10348. 8:16:28repository. We download the front end
  10349. 8:16:31artifacts because now in the in the
  10350. 8:16:34deploy job we are going to take the
  10351. 8:16:37files that were built in this job and we
  10352. 8:16:39are going to put them in digital ocean.
  10353. 8:16:43This is why we are using this GitHub
  10354. 8:16:45action to download the front- end build
  10355. 8:16:48from this specific path. Up to now as I
  10356. 8:16:51said these are the these are the steps
  10357. 8:16:53that we have been following before and
  10358. 8:16:56the new step which is related to the to
  10359. 8:16:58the deploy job is create backups. What I
  10360. 8:17:02will try to do is first I will just
  10361. 8:17:04commit this and then I will add the
  10362. 8:17:06other step. So let me try to do this. So
  10363. 8:17:10here because we are u this is something
  10364. 8:17:13new I will add add deploy job and I will
  10365. 8:17:17commit this. Now let me publish this
  10366. 8:17:20branch and I want to publish it to
  10367. 8:17:24basically my own fork. I don't want to
  10368. 8:17:26push it to upstream because this is just
  10369. 8:17:29a test repository to show you how things
  10370. 8:17:32work. And now on GitHub I can click on
  10371. 8:17:34this button to create the pull request.
  10372. 8:17:37And here okay so let's see. No I don't
  10373. 8:17:39want to I want to merge it with my own
  10374. 8:17:41branch or yeah and here. So yeah, let's
  10375. 8:17:44just keep things simple and let's just
  10376. 8:17:47hit create put request. Now the first
  10377. 8:17:50thing that will run is basically the CI
  10378. 8:17:53job and then if everything passes, we
  10379. 8:17:56can uh yeah, we can merge this and try
  10380. 8:17:59the deploy job. But while this is
  10381. 8:18:02running, let's go back to here and let
  10382. 8:18:05me undo the changes to show you the
  10383. 8:18:07first step that we are going to perform
  10384. 8:18:10in this deploy job. As you can see this
  10385. 8:18:13specific step is called create backups.
  10386. 8:18:17And here I am going to create backups
  10387. 8:18:19for both SQL light and mele search. But
  10388. 8:18:23you can adapt this to create backups for
  10389. 8:18:25other databases if you are using them.
  10390. 8:18:28And we are using an new uh GitHub action
  10391. 8:18:32called SSH action. This is an amazing
  10392. 8:18:36GitHub action that you can use to
  10393. 8:18:38connect using SSH. Here it is. If you
  10394. 8:18:42want to read more about it and they have
  10395. 8:18:44a few examples here in their GitHub
  10396. 8:18:47repository, if you scroll down a little
  10397. 8:18:49bit, you will find there this quick
  10398. 8:18:51start example that you can just copy and
  10399. 8:18:55uh paste in your workflow and you can
  10400. 8:18:57just tweak a few settings there. And as
  10401. 8:19:00you can see here for example in order to
  10402. 8:19:01connect they are using a username and a
  10403. 8:19:04password. But if you look at my own
  10404. 8:19:07version I am not doing that because we
  10405. 8:19:11have disabled the ability to connect
  10406. 8:19:13using a password and instead we are
  10407. 8:19:16using an SSH key because as we said this
  10408. 8:19:19is more secure than using a password.
  10409. 8:19:23Okay. And here we are using version
  10410. 8:19:251.2.4.
  10411. 8:19:27So if you find that there is a new
  10412. 8:19:29version just go to GitHub look at the
  10413. 8:19:31releases tab and see if there is a new
  10414. 8:19:33release. If that's the case then updates
  10415. 8:19:35the version. Here under environment we
  10416. 8:19:38are specifying so we are adding mail
  10417. 8:19:41search uh and we take that from the
  10418. 8:19:44secrets and under with we have the host
  10419. 8:19:48which is basically the IP address of our
  10420. 8:19:50virtual machine. We have the username
  10421. 8:19:52key and here we pass the environments.
  10422. 8:19:55So here we have me search. We need this
  10423. 8:19:57because we are going to communicate with
  10424. 8:20:00the me search service or server in order
  10425. 8:20:03to create the backups and under script.
  10426. 8:20:06So this is the what I like about this
  10427. 8:20:08GitHub action. This allows me to run a
  10428. 8:20:10script inside the virtual machine. So if
  10429. 8:20:13I collapse this, you can see that's the
  10430. 8:20:15only thing left in this step. Let's
  10431. 8:20:17let's uh go through it step by step.
  10432. 8:20:20First we are creating some variables. We
  10433. 8:20:24have backend directory, backup directory
  10434. 8:20:28and how many backups we want to create.
  10435. 8:20:30So here the maximum amount of backups is
  10436. 8:20:33going to be five. But if you want you
  10437. 8:20:35can change this. And here we create a
  10438. 8:20:37time stamp. We are going to use this to
  10439. 8:20:40create uh when we are going to create
  10440. 8:20:42the backup. So that's the file names are
  10441. 8:20:44going to be different. The the first
  10442. 8:20:46thing we need to do is basically to
  10443. 8:20:48create the backup directory because if
  10444. 8:20:51we go to the virtual machine you will
  10445. 8:20:53find that we don't have a backups folder
  10446. 8:20:56inside web app. This is something new
  10447. 8:20:58and using the make directory command we
  10448. 8:21:01will create it and here you can see that
  10449. 8:21:04we are using this option dashp. It's
  10450. 8:21:08amazing because uh what it does that if
  10451. 8:21:11the back if the backups folder doesn't
  10452. 8:21:13exist, it's going to create it. But if
  10453. 8:21:16it if it finds that we already have a
  10454. 8:21:19backups folder, it's going to skip this
  10455. 8:21:21operation. And after creating the
  10456. 8:21:23backups directory, we are going to
  10457. 8:21:26start. So the first thing here is uh so
  10458. 8:21:29this block is going to is related to
  10459. 8:21:32SQLite. You can see that in my virtual
  10460. 8:21:35machine or in my project I have this
  10461. 8:21:38database inside the backend directory.
  10462. 8:21:41Let me go back to the virtual machine to
  10463. 8:21:43show you how it looks like. As you can
  10464. 8:21:45see I am now inside the virtual machine.
  10465. 8:21:48Let me zoom in a little bit so that we
  10466. 8:21:50can see this better. Let's type ls-la.
  10467. 8:21:54Now let's go inside backend and let's
  10468. 8:21:57see what we have. You can see that we
  10469. 8:22:00have the visitors database. This is a
  10470. 8:22:03SQLite database that I am using uh in my
  10471. 8:22:06application. This is what we want to
  10472. 8:22:08back up uh when we deploy. Let's go back
  10473. 8:22:11to VS Code and let's see. So here we
  10474. 8:22:15have an if block. We are checking if
  10475. 8:22:18this file exists. If it does, we are
  10476. 8:22:21going to move we are going to copy that
  10477. 8:22:23file and we are going to create a uh
  10478. 8:22:26this new file. And as you can see here
  10479. 8:22:28we are using the timestamp as a suffix.
  10480. 8:22:32So we have visitors underscore and we
  10481. 8:22:34put the timestamp. This is helpful
  10482. 8:22:37because after that we are going to sort
  10483. 8:22:39these files and remove the older ones if
  10484. 8:22:42we have more than five backups. Then we
  10485. 8:22:46echo basically that we we were able to
  10486. 8:22:49back up the database. Otherwise, if this
  10487. 8:22:52file doesn't exist, we are going to show
  10488. 8:22:54this warning to let us know that we
  10489. 8:22:57couldn't uh create a backup. That's it
  10490. 8:23:00for SQLite. It's simple. It's just a
  10491. 8:23:02file that we copy. What happens if you
  10492. 8:23:05want to do this with me search? It's a
  10493. 8:23:07little bit tricky because we need to do
  10494. 8:23:09more work. As you can see here, first we
  10495. 8:23:12check if we have the me search key.
  10496. 8:23:14Normally we should because as you can
  10497. 8:23:16see we have passed it to the
  10498. 8:23:18environments uh option here and if we
  10499. 8:23:22look inside we are using this option to
  10500. 8:23:25check if this environment variable does
  10501. 8:23:27exist. If it doesn't we are going to
  10502. 8:23:30exit and return an error. Now here is
  10503. 8:23:33how we this is how we are going to
  10504. 8:23:36basically make a backup. we are going to
  10505. 8:23:39uh make a post request to this specific
  10506. 8:23:43endpoint which is called dumps. And with
  10507. 8:23:46this we we are going to tell me search
  10508. 8:23:49to create a backup for us. But in order
  10509. 8:23:52to do that we need to pass the me search
  10510. 8:23:54key because if you remember we have
  10511. 8:23:57created this server we have created a a
  10512. 8:24:00API key so that no one can just make
  10513. 8:24:04requests to the server. they need to
  10514. 8:24:05have the API key first. After making the
  10515. 8:24:08post request, we add a header that will
  10516. 8:24:10pass that uh me search API key. And here
  10517. 8:24:14you can see that we are running curl
  10518. 8:24:17with the s option which is basically
  10519. 8:24:19silent. And here we what we are doing
  10520. 8:24:22here is that we are tell we are telling
  10521. 8:24:24curl to fetch the HTTP code. And if you
  10522. 8:24:27are not familiar with HTTP codes, you
  10523. 8:24:30can go and search for HTTPS HTTPS status
  10524. 8:24:34code and you can learn more about them.
  10525. 8:24:37You can go here to Mozilla. They have a
  10526. 8:24:40good documentation that explains how
  10527. 8:24:43this works. HTTP status codes will tell
  10528. 8:24:47you if if your request finished
  10529. 8:24:49successfully or not. In this case, uh
  10530. 8:24:52you can see here are the ranges. So we
  10531. 8:24:54have something between 100 to 200 etc.
  10532. 8:24:58and we are going to use this information
  10533. 8:25:00to uh basically check if what we have
  10534. 8:25:03done succeeded or not. Now let let me go
  10535. 8:25:06back. So after capturing the HTTP code
  10536. 8:25:10we will have all of that we will put all
  10537. 8:25:12of that response inside this variable
  10538. 8:25:15and from that we are going to get the
  10539. 8:25:18HTTP code. After getting the HTTP code,
  10540. 8:25:22we will uh compare it to see if it is
  10541. 8:25:25within this range. So if it is greater
  10542. 8:25:27than or equal to 200 and less than or
  10543. 8:25:30equal to 300, this means that we made
  10544. 8:25:33the request successfully. I can show you
  10545. 8:25:36this. If if this seems complex, I will
  10546. 8:25:39copy this and paste it in the virtual
  10547. 8:25:42machine and let's see what we will get.
  10548. 8:25:44First, let's try this um help endpoint
  10549. 8:25:48because it doesn't require us to pass a
  10550. 8:25:51an API key. You can see that we have uh
  10551. 8:25:56-x get. This is not necessary because by
  10552. 8:25:58default when you run a curl command, a
  10553. 8:26:01curly request, it's going to be get.
  10554. 8:26:03It's not we add the -x option when we
  10555. 8:26:06want to perform other actions such as
  10556. 8:26:09post. And here, let me just run curl
  10557. 8:26:12directly to see what we get. So for
  10558. 8:26:14example here we get status available but
  10559. 8:26:17what happens if I add the -w option
  10560. 8:26:20after curl let's add dashw
  10561. 8:26:24and let's see what we get you can see
  10562. 8:26:26that here let me retry the command you
  10563. 8:26:28can see that here we have 200 and this
  10564. 8:26:31is the the status code that we are
  10565. 8:26:33looking for and let's put this inside a
  10566. 8:26:36variable like we did uh in the deploy
  10567. 8:26:39job so you can see that I can wrap
  10568. 8:26:41everything around this Let's do it like
  10569. 8:26:44this and let's add the variable name.
  10570. 8:26:48And I need to close this like so. Now
  10571. 8:26:51let me hit enter and let's see what we
  10572. 8:26:52get. You can see that uh now we need to
  10573. 8:26:55echo the content of this variable to see
  10574. 8:26:58what it what it holds. Let me copy it
  10575. 8:27:01and paste it here. And as you can see we
  10576. 8:27:03are getting the same output. Here we get
  10577. 8:27:05the response from that endpoint telling
  10578. 8:27:07us that the M search server is up and
  10579. 8:27:10running and 200 is the response that we
  10580. 8:27:13got after making this HTTP request. Now
  10581. 8:27:17let me copy this second line. Let's take
  10582. 8:27:21HTTP code. Let's put it here and let's
  10583. 8:27:24again echo that variable. So let me run
  10584. 8:27:28echo and let's copy this and paste it
  10585. 8:27:32below. Let's see what we get. You can
  10586. 8:27:33see that we are getting 200. Why?
  10587. 8:27:36Because here we are taking this output.
  10588. 8:27:39We give it to tail and the tail will
  10589. 8:27:41take the last line which is in this case
  10590. 8:27:44is 200. And this is what we are getting
  10591. 8:27:47here. And the next uh action or command
  10592. 8:27:52is will get just so let me copy this.
  10593. 8:27:55It's going to get the status. It's uh
  10594. 8:27:58because here we are using the set
  10595. 8:28:00command. It's going to remove the status
  10596. 8:28:03code. It's going to take just the other
  10597. 8:28:05part which is the response body. Okay.
  10598. 8:28:07Uh as you can see the these commands are
  10599. 8:28:10simple. They look complex but if you run
  10600. 8:28:12them like what like uh I did uh you will
  10601. 8:28:15find that um they are easy to understand
  10602. 8:28:19and what they are getting is uh going to
  10603. 8:28:21be used here to basically check if the
  10604. 8:28:24request uh was made successfully or not.
  10605. 8:28:27So as you can see here we got 200 as the
  10606. 8:28:31status code. If we compare if we look at
  10607. 8:28:34this condition it's true because the
  10608. 8:28:36HTTP code is greater than or equal to
  10609. 8:28:39200. So that means that we will show
  10610. 8:28:42this in the console showing that the
  10611. 8:28:45request was accepted. But in me search
  10612. 8:28:48when we call for example the dumps
  10613. 8:28:51endpoint it is not going to create the
  10614. 8:28:53endpoints directly because it depends on
  10615. 8:28:56the size of your database. So med search
  10616. 8:28:59will give you an ID so that you can
  10617. 8:29:01track the progress and uh this is what
  10618. 8:29:05we are getting here in the response body
  10619. 8:29:07we will try to look for the task UID.
  10620. 8:29:11Let me try to do this so that so that we
  10621. 8:29:13can see how this works. Instead of
  10622. 8:29:16hitting the health endpoint, I'll try to
  10623. 8:29:18hit the dumps endpoint to see the real
  10624. 8:29:20output that we will get from uh that uh
  10625. 8:29:23specific request. Let's run curl. Let's
  10626. 8:29:26add dash x because as I said here we are
  10627. 8:29:30going to perform a post request instead
  10628. 8:29:33of a get request. And let me add this
  10629. 8:29:36and let's see what we get. You can see
  10630. 8:29:38that now we weren't able to create to
  10631. 8:29:40make the post request because we are
  10632. 8:29:42missing the uh yeah the header. So we
  10633. 8:29:46need to add that. Here is the the other
  10634. 8:29:48missing part. So let me copy it and
  10635. 8:29:51paste it after this. Here is the full
  10636. 8:29:55command that we can run. Now it should
  10637. 8:29:57work because we are passing the API key.
  10638. 8:30:00Let's run this and let's see what we'll
  10639. 8:30:02get. Okay, here is the output and as you
  10640. 8:30:04can see I've told you that me search
  10641. 8:30:06will return the task UID and this is
  10642. 8:30:10what we will try to get in this nest
  10643. 8:30:13command. So if we go back here you can
  10644. 8:30:15see that we have this variable that will
  10645. 8:30:18take the response body and we'll search
  10646. 8:30:20for the task UID using this uh
  10647. 8:30:24expression and uh yeah if we print this
  10648. 8:30:28we will get the task u ID. So again
  10649. 8:30:31let's do the same thing. Let's store
  10650. 8:30:33that information inside dump dump
  10651. 8:30:37response and let's try to get the
  10652. 8:30:38response body. Let's put the response
  10653. 8:30:41here. Let me add this. Okay, that
  10654. 8:30:44worked. Now let's take the response body
  10655. 8:30:49and let's now run the task view ID.
  10656. 8:30:52Let's try to print the content of this
  10657. 8:30:54variable to see if we are getting the
  10658. 8:30:56correct view ID. Okay, that didn't work
  10659. 8:30:59because I forgot to add the other
  10660. 8:31:01options. So, here I have just d - x. So,
  10661. 8:31:05let me add the other ones dash s and
  10662. 8:31:09dash w. Let me add them here. Okay. And
  10663. 8:31:12now it should work. So, let's go back to
  10664. 8:31:15response body. And now let's go back to
  10665. 8:31:18task UID. Let's now try to echo. And as
  10666. 8:31:23you can see, we got the ID. This is what
  10667. 8:31:26we want to basically try to communicate
  10668. 8:31:29with Misarch to keep asking it did the
  10669. 8:31:32task finish or or not. Let's see how we
  10670. 8:31:35can do this. So after getting the task
  10671. 8:31:38ID here we are going to check if it
  10672. 8:31:41exists. So if it doesn't we are going to
  10673. 8:31:43throw an an error and uh basically fail
  10674. 8:31:46the deploy pipeline. Otherwise, if we
  10675. 8:31:48have the task ID, we are going to tell
  10676. 8:31:51mainly search uh by making this curl
  10677. 8:31:54command if the operation finished or
  10678. 8:31:56not. So, let's see what we will get if
  10679. 8:31:58we run this. So, let's do that. And
  10680. 8:32:01okay, so here they say that the
  10681. 8:32:03authorization header again is missing.
  10682. 8:32:06So, we need to add that one. Let's add
  10683. 8:32:08it like this. Let me clear the screen.
  10684. 8:32:11Let's add the authorization header and
  10685. 8:32:13let's see what we will get what we get.
  10686. 8:32:15Okay. So the output is we have a lot of
  10687. 8:32:18things but here you can see that they
  10688. 8:32:20confirm that the ID exists and here we
  10689. 8:32:22have the status which is succeeded. This
  10690. 8:32:25is what we want to see but in the
  10691. 8:32:27beginning it might be incued or
  10692. 8:32:29processed or sometimes it might fail. So
  10693. 8:32:31we are going to take this status
  10694. 8:32:33information and we are going to check uh
  10695. 8:32:36to check it inside the Y loop. Okay. So
  10696. 8:32:38after making the request we are going to
  10697. 8:32:41basically grab the status from the
  10698. 8:32:44output. If it says succeeded like in
  10699. 8:32:48this example, we are going to basically
  10700. 8:32:50show that the dump completed
  10701. 8:32:53successfully and we are going to break
  10702. 8:32:55out out of the while loop. Otherwise, if
  10703. 8:32:58it failed, we are going to fail the job.
  10704. 8:33:02But if it is still uh processing, we are
  10705. 8:33:05going to increase the attempt variable
  10706. 8:33:08and sleep for 2 seconds. And here with
  10707. 8:33:11the max uh amounts of the max retries is
  10708. 8:33:14set to 30 but you can change this. It
  10709. 8:33:17shouldn't take that much but this is how
  10710. 8:33:19we are uh this is the condition that we
  10711. 8:33:22have in the y loop. So if we reach 30 we
  10712. 8:33:24are going to uh break. Okay. So now here
  10713. 8:33:28we are inside this y loop. We can
  10714. 8:33:30collapse it. And after that if for some
  10715. 8:33:33reason we have exhausted these attempts
  10716. 8:33:35we are going to exit. And now we can
  10717. 8:33:38close this and we can focus on the else
  10718. 8:33:41block. So if the status code is not
  10719. 8:33:44within this range, we are going to exit
  10720. 8:33:46because something bad happened. And
  10721. 8:33:48finally we are going to run the this
  10722. 8:33:52specific script that we have created to
  10723. 8:33:55basically uh ensure that we keep at most
  10724. 8:33:59five backups for SQL light and mele
  10725. 8:34:02search. Okay. And uh yeah that's as you
  10726. 8:34:06can see uh that's all we are doing here
  10727. 8:34:09and this is this step is going to run
  10728. 8:34:11whenever we want to deploy our
  10729. 8:34:13application and this is very important
  10730. 8:34:15especially if you have sensitive data in
  10731. 8:34:18your database. Great. So this worked.
  10732. 8:34:21Let's go back to GitHub. And the CI
  10733. 8:34:23pipeline also worked without any
  10734. 8:34:25problem. Amazing. Uh let me commit this.
  10735. 8:34:28Let's say CI add backup job or step. Uh
  10736. 8:34:35let's commit it and let's sync the
  10737. 8:34:37changes. Let's go back again to the
  10738. 8:34:39virtual machine and let's ensure that we
  10739. 8:34:42don't have a backups folder. You can see
  10740. 8:34:43that there is no backups folder and if I
  10741. 8:34:46go to back end let's see so we have the
  10742. 8:34:49visitors DB. Great. Now let's I will try
  10743. 8:34:53to wait for the pipeline to finish and I
  10744. 8:34:56will come back because I need to wait
  10745. 8:34:58for this to finish uh in order to merge
  10746. 8:35:02the p request so that I can go to the
  10747. 8:35:05actions tab and uh click on the deploy
  10748. 8:35:08uh job so that I can deploy the
  10749. 8:35:11application. Okay, I'll wait for this to
  10750. 8:35:13finish and I will come back. I am back
  10751. 8:35:16and as you can see now we can merge the
  10752. 8:35:18pull request because all the tests have
  10753. 8:35:21passed successfully. I'll hit now
  10754. 8:35:23confirm merge and okay that's done.
  10755. 8:35:27Let's also go back here and uh let's go
  10756. 8:35:31to master to fetch the new changes.
  10757. 8:35:34Let's do that. Okay, great. So now we
  10758. 8:35:37have the new deploy file. Let's go back
  10759. 8:35:42to GitHub. Let's click here. And as you
  10760. 8:35:45can see, we have merged the third pull
  10761. 8:35:47request. Now let's now refresh the page.
  10762. 8:35:51Let's go to actions. Let's click on
  10763. 8:35:56manual deploy. This is what I explained
  10764. 8:35:59to you. So now we have merged. As you
  10765. 8:36:02can see, we have a CI step. It
  10766. 8:36:04succeeded. Now we have a second step
  10767. 8:36:07which is continuous delivery. And this
  10768. 8:36:10is how we do this. So as I said we will
  10769. 8:36:14do this manually. We click on run
  10770. 8:36:16workflow and here are the two jobs.
  10771. 8:36:19First of all we are going to build the
  10772. 8:36:21front end. Once this finishes we are
  10773. 8:36:24going to deploy the application. This is
  10774. 8:36:26not going to run automatically. No
  10775. 8:36:30GitHub will stop the deploy job and it's
  10776. 8:36:33going to basically send us a
  10777. 8:36:35notification to let us know if we should
  10778. 8:36:38let this continue or not. And this is
  10779. 8:36:41what we have configured uh earlier. You
  10780. 8:36:45can set as many people as you want so
  10781. 8:36:47that they can click on the deploy uh
  10782. 8:36:50confirmation. And this is what I was
  10783. 8:36:52talking about. You can see that we built
  10784. 8:36:54the front end without any issue. That's
  10785. 8:36:56great. But now we have uh you can see
  10786. 8:36:59that they requested a review from us. We
  10787. 8:37:02click on the button, we review. So we
  10788. 8:37:04want to deploy to production. We confirm
  10789. 8:37:07that and we hit approve. Let's click on
  10790. 8:37:10that and let's see what will happen. So
  10791. 8:37:13the deploy has started and you can see
  10792. 8:37:15that we have four steps. Let's click on
  10793. 8:37:17them to see what what is happening. So
  10794. 8:37:19now we are creating the backups. You can
  10795. 8:37:21see that everything went well. Nothing
  10796. 8:37:24bad happened. Uh and we can read through
  10797. 8:37:27the console. We can see these are the
  10798. 8:37:28messages that are um that we see because
  10799. 8:37:31we have uh we are using the echo
  10800. 8:37:33command. And let's read through this.
  10801. 8:37:35You can see that SQLite backup created
  10802. 8:37:37successfully. Here is the task ID. Here
  10803. 8:37:40is the HTTP status code that we got from
  10804. 8:37:43media search. And at the end, we say
  10805. 8:37:46that backup process finished
  10806. 8:37:48successfully. Amazing. That's what we
  10807. 8:37:50want to see. But let's confirm. Let's go
  10808. 8:37:52to the virtual machine to see if that is
  10809. 8:37:54correct. Uh before running the the
  10810. 8:37:56deploy job, we didn't have a backup
  10811. 8:37:58folder. But now, if I go back to uh web
  10812. 8:38:02app, let's run ls-la.
  10813. 8:38:06As you can see, we have the backups
  10814. 8:38:07folder. That's amazing. Now, let's go
  10815. 8:38:10inside that folder. Backups. Normally,
  10816. 8:38:13we should have just one file because
  10817. 8:38:15this is the first time we are running
  10818. 8:38:17this deploy job. And as you can see,
  10819. 8:38:19here is the time stamp. Now, what I will
  10820. 8:38:22try to do is I will copy this file and I
  10821. 8:38:24will paste it
  10822. 8:38:26four four times because I want to have
  10823. 8:38:29five files. when I will when I will
  10824. 8:38:31deploy the next time and we are not go
  10825. 8:38:34we are going to create the sixth file
  10826. 8:38:35but we are going to remove one of the
  10827. 8:38:38old ones because the script will keep at
  10828. 8:38:41most five files let's use the copy
  10829. 8:38:44command let's copy the file and here
  10830. 8:38:47I'll just change uh 12 to let's say 13
  10831. 8:38:52let's change this again to 14 15 and 16
  10832. 8:38:57let's see how many backups we have 1 2 3
  10833. 8:38:594 and five. Now let's go back to GitHub
  10834. 8:39:03and I will try to rerun all jobs. Okay,
  10835. 8:39:08this will trigger the deploy job again
  10836. 8:39:10and it should create a new backup but
  10837. 8:39:14it's going to delete this one because it
  10838. 8:39:17is the oldest. Let's confirm this. We
  10839. 8:39:19have the output and uh after uh this
  10840. 8:39:23deploy job finishes I will run again ls
  10841. 8:39:26and we will compare um the two lists.
  10842. 8:39:30Let's wait for the build job to finish.
  10843. 8:39:32We have the artifact. Great. And now
  10844. 8:39:36let's hit deploy. Let's click on that
  10845. 8:39:40specific job. We are checking the
  10846. 8:39:42repository. We download the artifacts.
  10847. 8:39:44And here we are creating the backups.
  10848. 8:39:47And yeah, that finished. Let's see. So
  10849. 8:39:50here you can see that we have this
  10850. 8:39:51specific step. Starting cleanup
  10851. 8:39:54retention policy is to keep the last
  10852. 8:39:56five files. Well, let's confirm if
  10853. 8:39:59that's correct. So let's run ls. And as
  10854. 8:40:02you can see, we don't we no longer we no
  10855. 8:40:05longer have this specific database. We
  10856. 8:40:08have 13 up to up to 16. And now we have
  10857. 8:40:11a new upto-date backup of the database.
  10858. 8:40:15This is great. And if we want we can
  10859. 8:40:18also check the dumps folder to see what
  10860. 8:40:21we have there. Normally we should have
  10861. 8:40:23multiple uh backups. So if we go there,
  10862. 8:40:26okay, we don't have the permission, but
  10863. 8:40:28we can run sudo and pass the password.
  10864. 8:40:31And as you can see here, we also have a
  10865. 8:40:33few backups. Awesome. So this is working
  10866. 8:40:36really, really well. Let's keep going.
  10867. 8:40:39This is not the end of the deploy job.
  10868. 8:40:41We still have a few jobs to add. Let's
  10869. 8:40:44click on here and let's create a new
  10870. 8:40:46branch. Let's call it R sync. Okay,
  10871. 8:40:50because this is what we want to do. Let
  10872. 8:40:52me collapse these jobs. So I will
  10873. 8:40:55collapse the checkout step, the download
  10874. 8:40:59front end artifact and also uh the
  10875. 8:41:02creation of the backups. And now we will
  10876. 8:41:05add this new job that will sync the
  10877. 8:41:09files from the from GitHub to the
  10878. 8:41:12droplet. For that we are using SSH
  10879. 8:41:15deploy and rs sync is a command that
  10880. 8:41:19will sync the files. So basically it
  10881. 8:41:22will take whatever we add in GitHub and
  10882. 8:41:25make sure that we have that on the
  10883. 8:41:27virtual machine and uh by default it
  10884. 8:41:30will try to create a mirror. Basically,
  10885. 8:41:32whatever we have on GitHub should be on
  10886. 8:41:35the virtual machine. If we have new
  10887. 8:41:36files on the virtual machine, the rsync
  10888. 8:41:38command will delete them. But we don't
  10889. 8:41:40want that because as you can see, we
  10890. 8:41:42created a backups folder and this folder
  10891. 8:41:45doesn't exist on GitHub. So, if we run
  10892. 8:41:48this, we will risk deleting the backups
  10893. 8:41:50folder and any other file that doesn't
  10894. 8:41:53exist on GitHub. For example, thev file,
  10895. 8:41:56that's another problem. That's why we
  10896. 8:41:58created that rync exclude file to tell
  10897. 8:42:01rync yes try to create the mirror but if
  10898. 8:42:04you find something new in the virtual
  10899. 8:42:06machine please keep it. You can also
  10900. 8:42:09search for this new GitHub action that
  10901. 8:42:11I'm using here. We pass the private key.
  10902. 8:42:14We pass the host and user. So the host
  10903. 8:42:18is the IP address. The username that I
  10904. 8:42:21am using um in my virtual machine. Here
  10905. 8:42:25source will basically copy everything we
  10906. 8:42:27have here and the target is web app and
  10907. 8:42:31here are the arguments that we will pass
  10908. 8:42:33to the rs sync command. Uh so here by
  10909. 8:42:36default we will delete and but we
  10910. 8:42:38exclude these files and folders that are
  10911. 8:42:40inside the rsync exclude command. Okay,
  10912. 8:42:43you can see that this job is simple. So
  10913. 8:42:46let's try to commit it and let's test
  10914. 8:42:48it. Uh yeah, let's just call it ci add r
  10915. 8:42:52sync job. Let's commit this and let's
  10916. 8:42:56publish the branch. We want to publish
  10917. 8:42:58it in to origin. Uh let's go back to
  10918. 8:43:01GitHub. Let's click on pull requests.
  10919. 8:43:04Compare and pull requests. Let's target
  10920. 8:43:08my master branch. And yeah, let's just
  10921. 8:43:11uh create the pull request. I will wait
  10922. 8:43:14for the pipeline to finish and I will
  10923. 8:43:15come back. And like uh the creation of
  10924. 8:43:18the backups, I will deploy manually to
  10925. 8:43:20confirm that the step is working. This
  10926. 8:43:22is the best way to create complex jobs
  10927. 8:43:25is to test each step independently to
  10928. 8:43:28confirm that it works before moving to
  10929. 8:43:30the next step. If you try to write the
  10930. 8:43:32full pipeline, it's going to be yeah,
  10931. 8:43:34it's going to be hard to test because uh
  10932. 8:43:38multiple jobs will fail at the same time
  10933. 8:43:40and it's going to be a nightmare. I
  10934. 8:43:42highly suggest to work on complex
  10935. 8:43:45pipelines like this. Create a step, make
  10936. 8:43:48sure that it works and then move to the
  10937. 8:43:50next one. Same as before, I'll wait for
  10938. 8:43:52the CI pipeline to finish before hitting
  10939. 8:43:54the deploy button. I am back. I can
  10940. 8:43:57merge the pull request. Let's do that.
  10941. 8:44:00And let's click on uh the yeah the
  10942. 8:44:03GitHub action to uh trigger the R sync
  10943. 8:44:07job to verify that it works uh
  10944. 8:44:09correctly. Okay. Now again click on run
  10945. 8:44:12workflow. Make sure to choose master. I
  10946. 8:44:15forgot to mention this before but that's
  10947. 8:44:17very important because master is
  10948. 8:44:19protected and whenever we merge a new
  10949. 8:44:21thing it is ready to be deployed. What
  10950. 8:44:23we want to confirm in this step is that
  10951. 8:44:26the backups folder shouldn't be deleted.
  10952. 8:44:28This is uh very important. We can see
  10953. 8:44:30that here we have a few backups and if I
  10954. 8:44:33go back uh the backups folder shouldn't
  10955. 8:44:36be deleted. Let's verify that this is
  10956. 8:44:38the case. Uh okay let's confirm the
  10957. 8:44:41deployment. Click on production and
  10958. 8:44:44approve and deploy. Let's click on the
  10959. 8:44:46deploy job. We now should have a new job
  10960. 8:44:49which is uh going to run the rs sync
  10961. 8:44:52command. And as you yeah as you can see
  10962. 8:44:54here it is. Okay. So we can see that the
  10963. 8:44:57rsync command is going through
  10964. 8:44:58everything uh in the GitHub repository
  10965. 8:45:01and it says done. Okay. Uh we we
  10966. 8:45:05deployed successfully. But the question
  10967. 8:45:06is do we still have the backups folder?
  10968. 8:45:09Okay. We still have it. Let's see what
  10969. 8:45:11we have inside it. Amazing. So, we have
  10970. 8:45:14everything there. But if we have removed
  10971. 8:45:16this rync exclude file, things will have
  10972. 8:45:19changed. Uh but basically, you get the
  10973. 8:45:21idea. If you want to keep uh files that
  10974. 8:45:24are inside your virtual machine but
  10975. 8:45:26don't exist on GitHub, you should try to
  10976. 8:45:29add a file like this and specify it in
  10977. 8:45:32the arguments. Now, the next step is to
  10978. 8:45:36populate the environment variables.
  10979. 8:45:38Okay. So first of all let me try to add
  10980. 8:45:41the backups folder again to r sync
  10981. 8:45:44exclude it was so it was backups uh save
  10982. 8:45:47the file and exit. Now if we go to back
  10983. 8:45:50end uh sorry let's go to back end let's
  10984. 8:45:53run ls-a you can see that we have thev
  10985. 8:45:57file and I have created this uh manually
  10986. 8:46:00when I when we were testing the the back
  10987. 8:46:03end but we can also create this uh
  10988. 8:46:06directly from the deploy job because we
  10989. 8:46:08have all the secrets we want and if we
  10990. 8:46:11uh look at env.example example. You can
  10991. 8:46:15see that this is the only thing we need.
  10992. 8:46:17We just need to change the mini search
  10993. 8:46:19master key because the other ones are
  10994. 8:46:22not yeah they are not secrets. This is
  10995. 8:46:25just the endpoint and uh this is the
  10996. 8:46:27index name and the environments. It can
  10997. 8:46:29be either development or production but
  10998. 8:46:31the secrets uh is the master key. This
  10999. 8:46:34is what we will try to add. Let's try to
  11000. 8:46:37do that first. Let's go back here. Let's
  11001. 8:46:41click on the repository. Uh okay. So we
  11002. 8:46:45have merged. That means we need to go
  11003. 8:46:46back again to master and let's try to
  11004. 8:46:50pull the latest changes. Okay. As you
  11005. 8:46:53can see we have added the new step here.
  11006. 8:46:55Amazing. Now I will create another
  11007. 8:46:57branch and here let's call it feature
  11008. 8:47:00and let's say create environment file.
  11009. 8:47:06This step is also small. Uh let's add
  11010. 8:47:09this below uh the rs sync job. You can
  11011. 8:47:14see that the name is create a the
  11012. 8:47:16backend env file. Here we are again
  11013. 8:47:19using the SSH action command because it
  11014. 8:47:21allows us to run scripts. Here we are
  11015. 8:47:24using cat and we are redirecting all of
  11016. 8:47:26this content to this file we are
  11017. 8:47:29creating. So this is the the endpoint we
  11018. 8:47:32are this it's local that's why we are
  11019. 8:47:34using local host. The index name this
  11020. 8:47:37you can change it based on the name of
  11021. 8:47:39your index. And here we are using that
  11022. 8:47:42environment variable that we get from
  11023. 8:47:43secrets to populate this environment
  11024. 8:47:45variable inside this file. And finally
  11025. 8:47:48environment is set to production. And we
  11026. 8:47:50end the file. That's all we need to do
  11027. 8:47:52to create a to create thev file. Uh
  11028. 8:47:55let's uh commit this civil
  11029. 8:48:00file. Commit this. Publish the branch to
  11030. 8:48:04origin. Let's go to GitHub and let's
  11031. 8:48:08create the pull request. Okay, we have a
  11032. 8:48:11problem. I need to change this to ghost
  11033. 8:48:13like this. Okay, great. Now, let's
  11034. 8:48:15create the pull request. I'll wait for
  11035. 8:48:18the pipeline to finish and then I will
  11036. 8:48:20come back. Let's merge the pull request
  11037. 8:48:23because the CI pipeline succeeded and
  11038. 8:48:27let's test the deploy job. Click on
  11039. 8:48:31actions. Let's find manual deploy. Let's
  11040. 8:48:35run the workflow on the on the master
  11041. 8:48:37branch and let's see if the environment
  11042. 8:48:39file will be created. This is a simple
  11043. 8:48:42job so it shouldn't fail but yeah it's
  11044. 8:48:45always uh a great idea to test. Let's
  11045. 8:48:48click on review deployments, choose
  11046. 8:48:51production and deploy. Click on the
  11047. 8:48:53deploy job and let's wait for the final
  11048. 8:48:57step to run. As you can see it is there.
  11049. 8:48:59So that means that we uh yeah we are
  11050. 8:49:02using the latest version of that deploy
  11051. 8:49:05file. The RC command has finished and
  11052. 8:49:08now we and we we were also able to
  11053. 8:49:10create the backendv file. That's
  11054. 8:49:13amazing. Yeah, we can verify that we
  11055. 8:49:16have the file there. Um let's see. So
  11056. 8:49:19let's run ls-la.
  11057. 8:49:22And as you can see, today is it's June
  11058. 8:49:2528th, um 11:24 a.m. So that means that
  11059. 8:49:29it's uh correct. Great. Let's go back to
  11060. 8:49:33VS Code again. Let's switch to the
  11061. 8:49:35master branch. Let's pull the latest
  11062. 8:49:38changes.
  11063. 8:49:40Now, we need to install the Python
  11064. 8:49:42dependencies. Let's say that we added a
  11065. 8:49:44new library that the back end depends
  11066. 8:49:47on. If we don't install it, the back end
  11067. 8:49:50will fail. So we need to add a step to
  11068. 8:49:53install the dependencies. But the
  11069. 8:49:54problem that we need to account for is
  11070. 8:49:56that let's say that we have 20
  11071. 8:49:58dependencies and uh we install all of
  11072. 8:50:01those inside the virtual environment
  11073. 8:50:03folder. Uh let me show you. Let's go to
  11074. 8:50:06um v to the virtual machine. You can see
  11075. 8:50:08that we have the virtual environment
  11076. 8:50:10folder. Let's say that something bad
  11077. 8:50:12happened and we were able to install 10
  11078. 8:50:15libraries but the rest failed. If we
  11079. 8:50:18change this virtual environment folder
  11080. 8:50:21and um yeah this not all not all
  11081. 8:50:24dependencies were installed this will
  11082. 8:50:25cause a problem. So what we need to do
  11083. 8:50:27is this step should be atomic meaning if
  11084. 8:50:30it fails we need to roll back and reload
  11085. 8:50:34uh the virtual environment. This means
  11086. 8:50:36that we are going to take a copy of this
  11087. 8:50:38virtual environment folder. We will
  11088. 8:50:40rename it something else. Uh for example
  11089. 8:50:42VNV uh backup. Then we will use pip to
  11090. 8:50:46install the dependencies. That will
  11091. 8:50:48create a new virtual environment folder
  11092. 8:50:50for us. If uh everything went well,
  11093. 8:50:53great. We will delete the backup folder
  11094. 8:50:54that we created and we will keep the new
  11095. 8:50:57one. But if something failed, we will
  11096. 8:50:59roll back and reuse the the backup
  11097. 8:51:02folder so that um we don't accidentally
  11098. 8:51:06break the back end. First of all, we
  11099. 8:51:08need to update the rsync exclude file.
  11100. 8:51:12we need uh to uh update the backend
  11101. 8:51:15section. Uh here are the things that we
  11102. 8:51:18need to add. Remember that I showed you
  11103. 8:51:20that we need to create the logs folder,
  11104. 8:51:23the J unicorn start etc. And here we
  11105. 8:51:26also have the socket. All these things
  11106. 8:51:28do not exist on GitHub. And if we deploy
  11107. 8:51:32that was the problem that I had is that
  11108. 8:51:34these files and folders were deleted.
  11109. 8:51:37But now I have added them here and uh
  11110. 8:51:40yeah they shouldn't be deleted anymore.
  11111. 8:51:42Um so I have gone through the steps that
  11112. 8:51:44we um followed in the previous sub uh
  11113. 8:51:47chapters and you can see that I have the
  11114. 8:51:50socket file I have the scripts and I
  11115. 8:51:53also have the logs folder and I have
  11116. 8:51:55added them to rsync so that they won't
  11117. 8:51:58be deleted anymore in the future and to
  11118. 8:52:01uh also verify that the back end is
  11119. 8:52:03working fine you can see that we can use
  11120. 8:52:05supervisor ctl and here this is the
  11121. 8:52:08application and it is saying running
  11122. 8:52:10which is uh Great. This is what we want
  11123. 8:52:12to see. And if I also open the browser
  11124. 8:52:16and go to this website, you can see that
  11125. 8:52:18it is working. If I click on blogs,
  11126. 8:52:21yeah, they are coming in. And if we
  11127. 8:52:23click on uh let's go to the conclusion
  11128. 8:52:27and let's start clapping normally it
  11129. 8:52:29should work. Yes, you can see that if I
  11130. 8:52:31refresh the page, the the count uh was
  11131. 8:52:34updated because the data is stored. Uh
  11132. 8:52:37and yeah, it means that the back end is
  11133. 8:52:39running. Maybe search is running.
  11134. 8:52:41Everything is working perfectly. Okay.
  11135. 8:52:44Now let's go back. We let's commit this.
  11136. 8:52:47Uh let's say sure update r sync exclude.
  11137. 8:52:52Uh let's commit this. Now we need uh we
  11138. 8:52:54have created the branch. Great. Now we
  11139. 8:52:56need to add the new job inside this
  11140. 8:53:00file. Now let me add let me paste the
  11141. 8:53:03code here. It's long but I'll try to
  11142. 8:53:05explain it. uh to you. The new job name
  11143. 8:53:08is called install Python dependencies.
  11144. 8:53:11And here I have tried to emphasize that
  11145. 8:53:14we are going to uh atomically swap the
  11146. 8:53:17virtual environment. We use the SSH
  11147. 8:53:20action GitHub action to run a script. So
  11148. 8:53:24let's look at what we have here. First,
  11149. 8:53:26we define this virtual environment uh so
  11150. 8:53:29that we can go inside back end. And here
  11151. 8:53:31is the first step. We want to create a
  11152. 8:53:34backup of the virtual environment
  11153. 8:53:36folder. But first, we need to check if
  11154. 8:53:38that directory exists. If it does, we we
  11155. 8:53:41use the move command to create a backup.
  11156. 8:53:44And the new folder name will be virtual
  11157. 8:53:46environment backup. After that, we will
  11158. 8:53:49create a brand new virtual environment.
  11159. 8:53:51We activate it and we use pip install to
  11160. 8:53:55install the dependencies. And here so
  11161. 8:53:58yeah if uh this command failed we are
  11162. 8:54:01going to show the else case which is
  11163. 8:54:03going to remove the virtual environment.
  11164. 8:54:07This is the roll back strategy that I
  11165. 8:54:09was talking about. If it if it if things
  11166. 8:54:12doesn't work as expected we will fall
  11167. 8:54:15through the else block. We will show the
  11168. 8:54:18error to understand what happened and
  11169. 8:54:20then we roll back. But first we need to
  11170. 8:54:23deactivate the virtual environment. We
  11171. 8:54:25remove it and then just to double check
  11172. 8:54:28we check if the virtual environment
  11173. 8:54:30backup exists. If it does, we move it
  11174. 8:54:32back to virtual environment and we exist
  11175. 8:54:35because the installation failed. But if
  11176. 8:54:39everything went well, we will do the
  11177. 8:54:41cleanup. So we have created a new
  11178. 8:54:43virtual environment. It has all the
  11179. 8:54:45dependencies. So now we no longer need
  11180. 8:54:47the backup. We can just delete it. And
  11181. 8:54:50at the end we echo that the virtual
  11182. 8:54:52environment setup has completed. And now
  11183. 8:54:55I can we can commit this um let's say
  11184. 8:54:58pet and here let's say add uh virtual
  11185. 8:55:02environment or let's change this to CI
  11186. 8:55:05because this is what we are working
  11187. 8:55:06with. We can commit and remember that
  11188. 8:55:10the rsync exclude file is now looking
  11189. 8:55:13like this. We can publish the branch. We
  11190. 8:55:16go to origin and let's now click on pull
  11191. 8:55:21requests to create another one that we
  11192. 8:55:24can deploy to pass this new step in the
  11193. 8:55:27job. Okay. Now let's change this to uh
  11194. 8:55:31origin. Let's remove all of this. So
  11195. 8:55:34let's see. So this is the branch we want
  11196. 8:55:36to merge it with master. Okay. And here
  11197. 8:55:39let's change the title to CI add virtual
  11198. 8:55:42environment atomic setup. Click on
  11199. 8:55:45create pull request. Now we just need to
  11200. 8:55:48wait again because uh yeah we need to
  11201. 8:55:51ensure that the CI passes before testing
  11202. 8:55:54the new deploy job. I am back. As you
  11203. 8:55:57can see we can merge the pull requests.
  11204. 8:55:59Let's do that quickly. Now let's click
  11205. 8:56:01on actions. Let's scroll down to manual
  11206. 8:56:05deploy. Click on run workflow and hit
  11207. 8:56:08run workflow. And at the same time I'll
  11208. 8:56:11try to uh looking at the virtual machine
  11209. 8:56:15to see if um when the backup folder will
  11210. 8:56:19be uh created. But first let's wait for
  11211. 8:56:22the build the job to finish and then we
  11212. 8:56:25can run the deployment job in order to
  11213. 8:56:29test the atomic virtual environment uh
  11214. 8:56:33creation. Let's hit review deployment.
  11215. 8:56:37Click on production and approve. Okay,
  11216. 8:56:40let's click on the deploy job and here.
  11217. 8:56:44Okay, let's do clear and ls-la.
  11218. 8:56:49We are syncing the files. Let's hope
  11219. 8:56:52that the logs folder and the other ones
  11220. 8:56:53do not get deleted now. Okay. And now we
  11221. 8:56:56are installing the dependencies. And as
  11222. 8:56:58you can see, we have the virtual
  11223. 8:57:00environment backup. And now we created a
  11224. 8:57:03new virtual environment where we are
  11225. 8:57:05going to install the dependencies. And
  11226. 8:57:07we can confirm this by the date. You can
  11227. 8:57:09see that this virtual environment was
  11228. 8:57:11created uh a week ago. But now this one
  11229. 8:57:14was created today. And we can also see
  11230. 8:57:16that the logs file that the logs folder
  11231. 8:57:19these files were not deleted because we
  11232. 8:57:21have updated the content of the rync uh
  11233. 8:57:25exclude file. Amazing. This is working
  11234. 8:57:28really well. And you can see that the
  11235. 8:57:30deploy job um finished successfully.
  11236. 8:57:33Which means that now if I run ls-la,
  11237. 8:57:35this folder will be removed. Let's
  11238. 8:57:38confirm that. And yep, that's it. That's
  11239. 8:57:40what we what happened. And you can see
  11240. 8:57:43that the date on this folder is um June
  11241. 8:57:4728th. This is working really well. Now,
  11242. 8:57:49let's go back to VS Code here. I need to
  11243. 8:57:53go back to the master branch cuz we need
  11244. 8:57:56to pull the new changes. Let's hit okay.
  11245. 8:58:00Um let's wait for a while. Okay, we have
  11246. 8:58:03a new job here. Great. Now the next step
  11247. 8:58:06is to uh reload the back end as well as
  11248. 8:58:11the engineext configuration because if
  11249. 8:58:13you have made changes to the front end
  11250. 8:58:15or back end, we need to restart the
  11251. 8:58:18application so that the changes take
  11252. 8:58:20effect and for that we will let's go
  11253. 8:58:23back to the website. You can see that
  11254. 8:58:24here in the navbar I have so this is my
  11255. 8:58:28name. I will try to change that and we
  11256. 8:58:31will hit deploy and then come back here
  11257. 8:58:33to the website to see if um yeah the new
  11258. 8:58:36modifications uh are going to be live.
  11259. 8:58:40Let's try to search for the navigation
  11260. 8:58:42bar component and here. Okay. So, let me
  11261. 8:58:46search for my name. Here it is. And I
  11262. 8:58:49will add uh let's say 2026. Okay. So, I
  11263. 8:58:53have changed the uh changed that file.
  11264. 8:58:56Let me create a new branch. Commit that.
  11265. 8:59:00Close the file. We will close the rsync
  11266. 8:59:02excl exclude because we no longer need
  11267. 8:59:04it. And now I will try to add this job.
  11268. 8:59:09Uh let me indent this correctly. So it
  11269. 8:59:12says restart the backend service. Here
  11270. 8:59:15again we are using the SSH action GitHub
  11271. 8:59:19action and inside this job. Here is what
  11272. 8:59:22we are doing inside script. We check we
  11273. 8:59:25try we run the restart all command using
  11274. 8:59:29supervisor ctl. If this succeeds it
  11275. 8:59:33means the back end restarted
  11276. 8:59:36successfully. Otherwise we fail the job.
  11277. 8:59:39Uh after running this we will wait for
  11278. 8:59:41let's say 5 seconds so that uh we can
  11279. 8:59:44run again the status command to check
  11280. 8:59:46that the output will say running. This
  11281. 8:59:49is another layer of confirmation that
  11282. 8:59:52will tell us if the back end is is
  11283. 8:59:54working. Okay. So we will try to push
  11284. 8:59:57this and then I will add another job
  11285. 8:59:59after this that will reload X. Let's
  11286. 9:00:02commit ci restart back end and below
  11287. 9:00:08this I will add uh let me go back here
  11288. 9:00:12let's go down below and let's paste the
  11289. 9:00:15new job uh I will collapse this because
  11290. 9:00:19uh we have uh seen it and uh now we just
  11291. 9:00:22want to focus on the reload engine x job
  11292. 9:00:25here inside the script first we need to
  11293. 9:00:27check that the configuration is correct
  11294. 9:00:29if the configuration is not correct we
  11295. 9:00:31are not going to reload EngineX because
  11296. 9:00:33if we do then we are going to break the
  11297. 9:00:35yeah we are going to break the website
  11298. 9:00:37and we don't want to do that. If the
  11299. 9:00:39syntax is okay we move to the next if
  11300. 9:00:42block we run again here we run the
  11301. 9:00:45reload engineext command. If this
  11302. 9:00:48succeeds great otherwise we are not
  11303. 9:00:50going to run it because the yeah the
  11304. 9:00:53configuration is not correct. And at the
  11305. 9:00:55end we show deployment complete. This is
  11306. 9:00:58the last job in this deploy if workflow
  11307. 9:01:02and if this succeeds we have um created
  11308. 9:01:06uh a good CD workflow that when I hit
  11309. 9:01:10deploy after changing my applications
  11310. 9:01:12code it's going to be live in a few in a
  11311. 9:01:15minute or two. Uh so here let's add
  11312. 9:01:18reload enginex. Let's commit this. I'll
  11313. 9:01:21publish the branch and create a pull
  11314. 9:01:24request. Then I will wait for a few
  11315. 9:01:26minutes for the pipeline to finish and I
  11316. 9:01:29will come back. I am back. Let's merge
  11317. 9:01:32the merge requests or the pull request.
  11318. 9:01:34Let's now go to actions. Click on manual
  11319. 9:01:39deploy. Let's uh where is it? Yeah. And
  11320. 9:01:42here let's click on run workflow on the
  11321. 9:01:44master branch. Let me split the page on
  11322. 9:01:48two so that we can see the changes uh
  11323. 9:01:51quickly. Okay. Now let's click on review
  11324. 9:01:55deployments and let's approve and
  11325. 9:01:57deploy. Let's click on deploy. We'll
  11326. 9:02:00follow the steps. We are checking the
  11327. 9:02:02repository. We download the front end
  11328. 9:02:05artifacts.
  11329. 9:02:06Here are the backups. Okay, we are are
  11330. 9:02:10syncing the files.
  11331. 9:02:12We have installed the dependencies
  11332. 9:02:14without an issue. And now we are trying
  11333. 9:02:17to restart the backend service. You can
  11334. 9:02:20see that the message is saying
  11335. 9:02:21restarting the fast fast API back end.
  11336. 9:02:24Let's hope that this works. We have seen
  11337. 9:02:27that we were able to stop and start the
  11338. 9:02:30the backend service but we have a
  11339. 9:02:33problem. So here it says sudo a terminal
  11340. 9:02:36is required to read the password meaning
  11341. 9:02:38that the v sudo uh change that we did
  11342. 9:02:42didn't work. Let's try to investigate
  11343. 9:02:45why. So here what was what was the last
  11344. 9:02:49message we have seen pass API backend
  11345. 9:02:52that restart is started successfully.
  11346. 9:02:53Okay now let's go back here and let's
  11347. 9:02:56search for that message. Okay so
  11348. 9:02:58supervisor ctl start all worked well but
  11349. 9:03:01I think what happens is that maybe the
  11350. 9:03:04status uh is not allowed because here we
  11351. 9:03:07need to run sudo. So let's verify that.
  11352. 9:03:10Let's open the terminal again. Let's run
  11353. 9:03:13sudo v sudo and let's see what we have
  11354. 9:03:16inside this file. Let's scroll down.
  11355. 9:03:19Okay, you can see that here we have uh
  11356. 9:03:22yeah that's the problem. So here we are
  11357. 9:03:23allowing just restart all. We don't have
  11358. 9:03:26status. That's the problem. So what we
  11359. 9:03:30can do is copy the command. I'll try to
  11360. 9:03:33copy this. Let's go back to the
  11361. 9:03:36terminal. And here let's try to add it
  11362. 9:03:39after this one. Let's type user bin and
  11363. 9:03:43I will paste this command. Supervisor
  11364. 9:03:45ctl status all. Save the file. Exit. Now
  11365. 9:03:51go back to uh let's go back to GitHub
  11366. 9:03:54and let's restart the failed jobs. So
  11367. 9:03:58here uh let me try to make the screen
  11368. 9:04:00bigger to so that I can see what's
  11369. 9:04:01happening here. I will click on rerun
  11370. 9:04:04failed jobs. Let's uh rerun that. Let's
  11371. 9:04:08now click on review deployments and
  11372. 9:04:11let's hope that this time the we won't
  11373. 9:04:14have an error when trying to reload the
  11374. 9:04:16back end. Okay, now we have reached the
  11375. 9:04:19other the step that failed before. But
  11376. 9:04:21now as you can see it uh it didn't fail.
  11377. 9:04:24That's great. And um okay, so now we
  11378. 9:04:27have the same problem while trying to
  11379. 9:04:30reload EngineX. And I think I know the
  11380. 9:04:33um uh how to solve it. I think yeah we
  11381. 9:04:36have the same issue if we look at here
  11382. 9:04:40let's see so we have reload engine x but
  11383. 9:04:43we forgot to add uh engineext-t because
  11384. 9:04:47we are checking the syntax if we go back
  11385. 9:04:51to vs code let's collapse this because
  11386. 9:04:54it succeeded it didn't fail now we need
  11387. 9:04:57to basically uh try to work on this one
  11388. 9:05:00you can see that systemct ctl reload
  11389. 9:05:02engine x is already here it systemctl
  11390. 9:05:06reload engineext. But when we try to uh
  11391. 9:05:10check the configuration, we run
  11392. 9:05:12engineext-t.
  11393. 9:05:14We need to also add this one. To fix
  11394. 9:05:16this, we need to find where the binary
  11395. 9:05:19of is located. But I think normally it
  11396. 9:05:23is located at user sbin
  11397. 9:05:26/enx.
  11398. 9:05:28But we can verify that. I have saved the
  11399. 9:05:31file and now I can run which engine x.
  11400. 9:05:34And as you can see this is the path that
  11401. 9:05:35I have added in b sudo and um okay let
  11402. 9:05:39me just verify it one more time user/
  11403. 9:05:42spbin/engineext and then I added the
  11404. 9:05:45comma. Okay great. So now with this we
  11405. 9:05:48won't um yeah we won't have an error
  11406. 9:05:51when trying to run that specific step.
  11407. 9:05:54Okay let's go back again to GitHub and
  11408. 9:05:56let's try to rerun this failed step. Uh
  11409. 9:06:00let's use rerun all failed jobs and uh
  11410. 9:06:03again let's uh rerun this. I will
  11411. 9:06:06refresh the page to get the confirmation
  11412. 9:06:09is production and approve. Let's click
  11413. 9:06:11on the deploy job. Hopefully this time
  11414. 9:06:14it should work and then I will go back
  11415. 9:06:16to this tab refresh the page and
  11416. 9:06:18hopefully we should see that 2026
  11417. 9:06:22uh will appear here. Let's collapse this
  11418. 9:06:25rync step the create uh backups etc. Now
  11419. 9:06:30we are installing the Python the Python
  11420. 9:06:32dependencies. Uh we arrived at um the
  11421. 9:06:36last steps. This one will not fail
  11422. 9:06:39because we have confirmed that. Uh let's
  11423. 9:06:41just hope that reloading engine X will
  11424. 9:06:43also work and yes it did. Amazing. Uh
  11425. 9:06:47let's uh look at this. So as you can see
  11426. 9:06:49everything is green now. And as you can
  11427. 9:06:51see here, GitHub will also give you the
  11428. 9:06:53link so that you can click on it to see
  11429. 9:06:55if everything uh is looking great. Okay,
  11430. 9:06:58this is the moment of truth. Let's
  11431. 9:07:00refresh the page. And as you can see, we
  11432. 9:07:02have 2026. And this will work when um it
  11433. 9:07:07doesn't matter if you change your front
  11434. 9:07:09end or back end. Both will both uh will
  11435. 9:07:11work. If you change your back end, we
  11436. 9:07:13restart supervisor. We restart yes
  11437. 9:07:16supervisor using the supervisor ctl
  11438. 9:07:18command. And if your front end changes,
  11439. 9:07:21we also reload the engine X. Awesome.
  11440. 9:07:24So, as you can see, we have built the
  11441. 9:07:26full pipeline. And this is how uh how I
  11442. 9:07:28want you to build it. Don't try to write
  11443. 9:07:31it fully. No, go step by step. Try to
  11444. 9:07:34add one step at a time. Verify it
  11445. 9:07:36because as you can see right now, we try
  11446. 9:07:38to add these two steps. They fail. It's
  11447. 9:07:40not a problem. We can go ahead and fix
  11448. 9:07:43them before moving to the next steps.
  11449. 9:07:46And once you do that you you learn how
  11450. 9:07:48to handle errors and it's uh also
  11451. 9:07:52amazing when you try when you fix the
  11452. 9:07:54problem and see uh the green check mark
  11453. 9:07:57uh it makes you happy and developing it
  11454. 9:07:59like this is also fun. Uh so yeah we
  11455. 9:08:02have finished the deploy job and this is
  11456. 9:08:04how it works. So now in the future you
  11457. 9:08:07have seen now that I was creating put
  11458. 9:08:09requests and then I merged them. That's
  11459. 9:08:11the first step. create your uh create a
  11460. 9:08:14new feature branch. Develop your uh the
  11461. 9:08:17yeah your feature or bug fix or
  11462. 9:08:19whatever. Mer make sure that the CI
  11463. 9:08:22pipeline passes. Then merge that request
  11464. 9:08:26with your master branch. Then after that
  11465. 9:08:29move to the second uh step which is to
  11466. 9:08:32deploy. So go to actions and then hit
  11467. 9:08:35the button on the master branch. Don't
  11468. 9:08:37forget that. And uh after that your
  11469. 9:08:40steps are going to go one by one and
  11470. 9:08:42then your application will uh update
  11471. 9:08:44accordingly with the new code that you
  11472. 9:08:46pushed to master. And just like that we
  11473. 9:08:49have finished chapter 5. It was a long
  11474. 9:08:52one and uh this this was the I I would
  11475. 9:08:55say the most interesting chapter because
  11476. 9:08:57we have merged everything we have
  11477. 9:08:59learned before and we try to automate as
  11478. 9:09:01many things as possible. We have one
  11479. 9:09:03more chapter left. In that one we are
  11480. 9:09:04going I will it's a it's not a long one.
  11481. 9:09:07uh I will just show you tools that you
  11482. 9:09:09can install uh on your server so that
  11483. 9:09:12you can monitor let's say uh HTTP
  11484. 9:09:14requests that are hitting your server
  11485. 9:09:17etc. So these are just tools that are
  11486. 9:09:19nice to have and that are easy to
  11487. 9:09:21install and configure.
  11488. 9:09:23We have arrived at module 6. We are
  11489. 9:09:26going to focus on observability. You
  11490. 9:09:30will learn how to parse native engineext
  11491. 9:09:33traffic using go access. I will show you
  11492. 9:09:37how to deploy a dashboard where you can
  11493. 9:09:40see this engineext data using HTTP basic
  11494. 9:09:44authentication. We are going to learn
  11495. 9:09:46about rotating logs and we are going to
  11496. 9:09:50use a chrome job for that. We are going
  11497. 9:09:53to visualize the CPU and memory usage as
  11498. 9:09:57well as process trees using BTOP. And
  11499. 9:10:01finally, I will show you how to find
  11500. 9:10:04people that are or bots that are trying
  11501. 9:10:07to get data from your virtual machine
  11502. 9:10:11and we are going to block those IPs. Now
  11503. 9:10:14let's go to the terminal and let's SSH
  11504. 9:10:17to the virtual machine. Here is my
  11505. 9:10:19terminal and as you can see I am inside
  11506. 9:10:21the machine. I am going to start by
  11507. 9:10:24installing go access. Here we are using
  11508. 9:10:27ibuntu. We can install it very easily
  11509. 9:10:30using this command sudo apt install go
  11510. 9:10:34access. I already have it on my system.
  11511. 9:10:36So that's why it didn't take too much
  11512. 9:10:38time to install it. And how do we use
  11513. 9:10:40this? Okay, let me show you. First, we
  11514. 9:10:42need to try to look at the this path
  11515. 9:10:46that stores the logs. You can see that
  11516. 9:10:49here we have a lot of logs because we
  11517. 9:10:51have just one website on this server. It
  11518. 9:10:54is called my website_com.
  11519. 9:10:57We are seeing this. But if you are if
  11520. 9:10:59you have a virtual machine that is that
  11521. 9:11:01is hosting multiple websites then pick
  11522. 9:11:03one or multiples. So here we are going
  11523. 9:11:06to pick my website. We want to look at
  11524. 9:11:09the access logs and you can see that
  11525. 9:11:11some of them are regular files but some
  11526. 9:11:13of them were compressed and this is what
  11527. 9:11:16I was talking about in the beginning.
  11528. 9:11:18So, Linux is trying to rotate the the
  11529. 9:11:20logs, meaning it it tries to compress
  11530. 9:11:23them to save disk space. But first, we
  11531. 9:11:26are going to look at just this one
  11532. 9:11:28because it's a regular file that we can
  11533. 9:11:30read. And later, I will show you to in
  11534. 9:11:33how to include the zipped files also.
  11535. 9:11:36Now, we know the logs are stored here
  11536. 9:11:38and we know that we need to pick this
  11537. 9:11:40specific uh website. Here is the command
  11538. 9:11:43that we need to use. I will paste it and
  11539. 9:11:46then I will explain what it does. Here
  11540. 9:11:48we are using pseudo because we need to
  11541. 9:11:49read files from this specific directory.
  11542. 9:11:53And here I need to copy this and uh
  11543. 9:11:56replace this placeholder with this
  11544. 9:11:58specific file name. And here the log
  11545. 9:12:01format is set to combined. This is the
  11546. 9:12:04for the default format that enginex
  11547. 9:12:06uses. So if you have if you are using a
  11548. 9:12:09different format, make sure to change
  11549. 9:12:11this option. That's all we need to do.
  11550. 9:12:14Now if I hit enter, let's see what
  11551. 9:12:16happens. You can see that we get this
  11552. 9:12:18amazing in real time dashboard. This web
  11553. 9:12:23server received 122 requests today. And
  11554. 9:12:28here we have 54 unique visitors. Go
  11555. 9:12:31access is showing you the data that is
  11556. 9:12:34stored in the engineext logs. And here
  11557. 9:12:37it is also shows you where it where it
  11558. 9:12:40found the data. And this is the normal
  11559. 9:12:43file that I was talking about. And here
  11560. 9:12:45it shows you so the uh the unique
  11561. 9:12:48visitors we I we have just one person
  11562. 9:12:50that was that was hitting the the web
  11563. 9:12:53server. We can keep scrolling or you can
  11564. 9:12:55hit tab to move to the second uh tab or
  11565. 9:13:00to the second um section. Here we have
  11566. 9:13:03requested files. Some were requesting
  11567. 9:13:06the site map. Some were just visiting
  11568. 9:13:08the root directory. Here we have the
  11569. 9:13:12static requests. So you can see that
  11570. 9:13:14some were checking the robot cxt file.
  11571. 9:13:17We don't have 404s. Okay. Here we get
  11572. 9:13:20the IP addresses of people or bots that
  11573. 9:13:24are trying to reach the web server. Here
  11574. 9:13:28it shows you the operating systems. You
  11575. 9:13:29can see that we have a lot of useful
  11576. 9:13:31data that we can read and try to
  11577. 9:13:34understand what is happening. And here
  11578. 9:13:36it also shows you where the traffic is
  11579. 9:13:38coming from. You can see that some were
  11580. 9:13:41able to find the website from Google.
  11581. 9:13:43Some were uh some traffic was coming
  11582. 9:13:45from our website itself. And here we got
  11583. 9:13:48the HTTP status codes per request. So
  11584. 9:13:52most requests here succeed but some of
  11585. 9:13:54them have client errors. Great. And as
  11586. 9:13:57you can see all of this data is coming
  11587. 9:13:59from one single file. And later I will
  11588. 9:14:03show you how to increase this range by
  11589. 9:14:07incorporating the files that were
  11590. 9:14:09compressed. But before we do that, I
  11591. 9:14:11will show you if you don't if you prefer
  11592. 9:14:13to see a dashboard instead of sshing to
  11593. 9:14:19the machine having to run this command
  11594. 9:14:21to get this terminal dashboard. We can
  11595. 9:14:24tell go access to generate a an HTML
  11596. 9:14:27page that we can access from our
  11597. 9:14:30browser. And this is what we are going
  11598. 9:14:32to do now. But since this data contains
  11599. 9:14:35sensitive information like IP addresses
  11600. 9:14:38and other stuff we don't want everyone
  11601. 9:14:40to see that page. So we are going to use
  11602. 9:14:43HTTP basic authentication to block
  11603. 9:14:46access to that specific page. So you
  11604. 9:14:49need in order to see the data you need
  11605. 9:14:51to provide a username and a password.
  11606. 9:14:54And in order to do that here I will hit
  11607. 9:14:57Ctrl C to exit. We need to install a
  11608. 9:15:00tool called Apache2 utils because it has
  11609. 9:15:05that functionality that allows us to
  11610. 9:15:07create to generate an encrypted password
  11611. 9:15:11file. Great. We have installed Apache to
  11612. 9:15:15utils. Now let me clear the screen and
  11613. 9:15:18let's use it. Here is how we use that
  11614. 9:15:21utility. So here we tell it that we want
  11615. 9:15:23to generate a as I said an encrypted
  11616. 9:15:26password file and we will put that here
  11617. 9:15:28in this location and here the user is
  11618. 9:15:31going to be uh admin. I hit enter and
  11619. 9:15:35now we need to provide a password for
  11620. 9:15:37that specific admin user. Now I need to
  11621. 9:15:40retype the new password and it says add
  11622. 9:15:43in password for user admin. Now we can
  11623. 9:15:46use this username and password to lock
  11624. 9:15:50that specific page. But before we do
  11625. 9:15:52that, we need to generate the go access
  11626. 9:15:57html page. And in order to do that, let
  11627. 9:16:01me go back to this specific command
  11628. 9:16:04where we generate where we get the
  11629. 9:16:07terminal dashboard. And we need to
  11630. 9:16:09adjust a few things. The first part is
  11631. 9:16:12going to stay the same. So we are
  11632. 9:16:14pointing at a specific log file but we
  11633. 9:16:16need to add the following option before
  11634. 9:16:19log format. So here I will add this and
  11635. 9:16:23as you can see here we add dash O which
  11636. 9:16:26basically will try to generate this
  11637. 9:16:30specific HTML page from the data. Once I
  11638. 9:16:33hit enter, you can see that it is going
  11639. 9:16:36to put it inside front end this. And
  11640. 9:16:38this allows me to be able to use this
  11641. 9:16:42file and to check it from my browser.
  11642. 9:16:44And if I want, I can check the engineext
  11643. 9:16:48configuration. It says okay. And now I
  11644. 9:16:50can try to reload it so that engineext
  11645. 9:16:54can serve that specific file. So let's
  11646. 9:16:57go to Firefox. And here let's go to uh
  11647. 9:17:01the website. And now because that
  11648. 9:17:04analytics html file is in the this
  11649. 9:17:08folder, I can access it. But you can see
  11650. 9:17:10it didn't work here because I need to
  11651. 9:17:12create I need to update the engineext
  11652. 9:17:14configuration in order to serve this
  11653. 9:17:17file. First let's u make sure that when
  11654. 9:17:20we go to web app front end and this we
  11655. 9:17:25need to ensure that we have the file
  11656. 9:17:27there. As you as you can see we we do.
  11657. 9:17:29So we have analytics.html HTML. Let me
  11658. 9:17:33make sure that I have typed it
  11659. 9:17:34correctly. Yes, I did. Now that's great.
  11660. 9:17:37We need to open the enginex
  11661. 9:17:39configuration
  11662. 9:17:41and let me try to do that. We use the
  11663. 9:17:45nano. So here I am using nano but you
  11664. 9:17:47can use other text editors. And here we
  11665. 9:17:49are pointing at my my website com inside
  11666. 9:17:54the sites available folder. And here you
  11667. 9:17:57can see that we have we need to come
  11668. 9:17:59here. So here we are serving uh index
  11669. 9:18:02html, we are serving assets and we are
  11670. 9:18:06serving other stuff. So what are we
  11671. 9:18:08going to do is we are going to add
  11672. 9:18:11another location block but we are going
  11673. 9:18:14to do that before the spa fallback
  11674. 9:18:18routes. So we can do it maybe before
  11675. 9:18:20assets or before index html. It it
  11676. 9:18:24doesn't matter. Okay. Uh I will just
  11677. 9:18:26copy the following code and I will paste
  11678. 9:18:29it here. And now I need to try to indent
  11679. 9:18:33this. And here you might see that I have
  11680. 9:18:35changed something here. Root instead of
  11681. 9:18:38specifying this path I have this v this
  11682. 9:18:42variable that I'm using here. I did this
  11683. 9:18:45because uh before I didn't have this
  11684. 9:18:48coming soon page. So when I was uh
  11685. 9:18:51because here I had I was serving other
  11686. 9:18:53stuff. So I just uh changed this
  11687. 9:18:56variable to point to this coming soon
  11688. 9:18:59but basically it's just a variable that
  11689. 9:19:01is holding a path and here so here you
  11690. 9:19:04can see that root is pointing at web app
  11691. 9:19:06front end this and this is why this was
  11692. 9:19:09not working now I can save the file exit
  11693. 9:19:14let's check engineext-t
  11694. 9:19:17it says that the configuration is okay
  11695. 9:19:19and now we can reload the page sorry I
  11696. 9:19:22made a mistake Let's try to run this
  11697. 9:19:25again and let's hit enter. Okay, now
  11698. 9:19:27let's go back to the browser and let's
  11699. 9:19:29refresh the page. And as you can see, I
  11700. 9:19:32can't access that page because I need to
  11701. 9:19:35provide my password. And this is what we
  11702. 9:19:37are using in the configuration. I forgot
  11703. 9:19:40to explain it. So let's go back to this
  11704. 9:19:43file and let's see. You can see that
  11705. 9:19:45root is pointing at the folder because
  11706. 9:19:48there we have the analytics.html
  11707. 9:19:51file. And here we add this o basic to
  11708. 9:19:56tell engineext that this endpoint or
  11709. 9:19:59this file is restricted. We cannot
  11710. 9:20:01access it. And here is what we are
  11711. 9:20:04using. We are using also and here is the
  11712. 9:20:07encrypted file that we have created. So
  11713. 9:20:09if the user or if the person that is
  11714. 9:20:11trying to get this resource if they
  11715. 9:20:13provide the correct user and password
  11716. 9:20:16then serve this file for them otherwise
  11717. 9:20:19don't serve it and show them this
  11718. 9:20:22challenge which is what we are seeing
  11719. 9:20:24here. Now I type admin because that's
  11720. 9:20:26the user that I have created and here I
  11721. 9:20:29need to provide the password. If I make
  11722. 9:20:32a mistake let's say I remove the last
  11723. 9:20:35character it's not going to let me in.
  11724. 9:20:37So I need to provide the correct
  11725. 9:20:39credentials in order to see that
  11726. 9:20:41dashboard. And as you can see now I am
  11727. 9:20:44in. So we need to wait uh for a few
  11728. 9:20:46seconds. Um I'm not sure what is
  11729. 9:20:49happening. Do we have an error here?
  11730. 9:20:51Okay. Okay. Okay. So I see the problem.
  11731. 9:20:53Remember that we are using content
  11732. 9:20:55security policy which is restricting
  11733. 9:20:59this project from loading some some
  11734. 9:21:02data. That's why it is not working. If
  11735. 9:21:05we go, so we need to fix this and this
  11736. 9:21:07is really cool because as I told you
  11737. 9:21:09when you apply the CSP policy, you have
  11738. 9:21:13to keep attention to it and if you
  11739. 9:21:16change your front end, you need to
  11740. 9:21:18always test it to see if there is some
  11741. 9:21:20new dependency that you added or
  11742. 9:21:22something that is not loaded correctly.
  11743. 9:21:25And this is what what happened here. But
  11744. 9:21:27we can solve this easily by going back
  11745. 9:21:30to the engineext configuration. And uh
  11746. 9:21:33let's go up to see what we have. You can
  11747. 9:21:35see that here we have the content
  11748. 9:21:37security policy. And this is what we
  11749. 9:21:40have done. And what we could do here is
  11750. 9:21:42we can uh [clears throat] h have the
  11751. 9:21:44header here just for analytics. HTML so
  11752. 9:21:47that we can override this. Uh okay. So
  11753. 9:21:50we can come here and I will I will try
  11754. 9:21:54to add that. I will paste that here. Let
  11755. 9:21:57me save the file. Exit. Let me check
  11756. 9:22:00that the configuration is okay. And now
  11757. 9:22:04I can reload. I will I will just make
  11758. 9:22:07sure that uh the website is going to
  11759. 9:22:09load correctly and then I'll try to
  11760. 9:22:11explain to you what is happening there.
  11761. 9:22:13Okay. So, we still have a problem here.
  11762. 9:22:15It says that the page settings blocked
  11763. 9:22:18an inline script uh because it violates
  11764. 9:22:21something. Okay. Let's go back and let's
  11765. 9:22:23see what we have here in the
  11766. 9:22:24configuration. I think what I will do
  11767. 9:22:26here since this is a page that only
  11768. 9:22:30admins can access. I will add unsafe
  11769. 9:22:34inline just so that we can see how the
  11770. 9:22:36dashboard looks like. So here we have
  11771. 9:22:38unsafe eval and after that I will add
  11772. 9:22:41unsafe inline. But please never do this
  11773. 9:22:44on your main production site because
  11774. 9:22:46this is a page that is protected. it's
  11775. 9:22:50not it's not going to be an issue.
  11776. 9:22:52That's why I'm adding this and to just
  11777. 9:22:55make sure that it is working. So here
  11778. 9:22:57now I refresh the page and as you can
  11779. 9:22:59see we get the dashboard. It's the same
  11780. 9:23:01information that we will see in the
  11781. 9:23:03terminal. But if you prefer to say that
  11782. 9:23:06you want to see this from your phone or
  11783. 9:23:08you don't have access to the virtual
  11784. 9:23:10machine, you can use the dashboard to
  11785. 9:23:13look at the data. And here you have you
  11786. 9:23:16can for example open the settings. You
  11787. 9:23:18can change the theme if you like. If you
  11788. 9:23:20want a bright theme, you can do that
  11789. 9:23:22here. And here you can see all the
  11790. 9:23:25panels that we talked about. Here it
  11791. 9:23:27shows you the unique visitors per day.
  11792. 9:23:30It shows you the files that were
  11793. 9:23:31requested,
  11794. 9:23:33etc. And if you want to learn more about
  11795. 9:23:35Go Access, you can go to their GitHub
  11796. 9:23:37repository. They have a ton of resources
  11797. 9:23:40and it's an amazing project. You can
  11798. 9:23:42also if you want you can uh as I said go
  11799. 9:23:45to GitHub and here they have their own
  11800. 9:23:49example the so on their website they
  11801. 9:23:51show how this might look like. So if you
  11802. 9:23:54want to to come here to read the
  11803. 9:23:57documentation uh that that would be
  11804. 9:23:59great because they have a lot of
  11805. 9:24:01features and if you click on this image
  11806. 9:24:03on GitHub you see that they also have
  11807. 9:24:06their own dashboard and you can see that
  11808. 9:24:08they have a ton of information and you
  11809. 9:24:11can also add maps. It's amazing. It's an
  11810. 9:24:14amazing project. Great. Now let's go
  11811. 9:24:16back to this to my website. You can see
  11812. 9:24:20that we were able to add this and uh as
  11813. 9:24:24I mentioned here we have we just did a
  11814. 9:24:27shortcut just to be able to solve the
  11815. 9:24:30problem with the CSP but as I mentioned
  11816. 9:24:34and never ever use unsafe inline because
  11817. 9:24:37that goes against security. Now let me
  11818. 9:24:41show you how to do this correctly. First
  11819. 9:24:43we need to add nons. Uh so yeah we need
  11820. 9:24:47to add this. Let me show you. We need to
  11821. 9:24:50add nons dash requests ID to the CSP
  11822. 9:24:55only in the script source. Okay, because
  11823. 9:24:58this is related to loading inline
  11824. 9:25:00scripts. And after that, this was the
  11825. 9:25:02missing piece. I forgot to add it. This
  11826. 9:25:06is what we need to add to uh this
  11827. 9:25:08location block. Here we are passing sub
  11828. 9:25:11filter once off because we want
  11829. 9:25:14engineext to go through the content of
  11830. 9:25:16this file and we don't want it to stop
  11831. 9:25:20uh when it finds the first occurrence of
  11832. 9:25:22the things that we want it to search.
  11833. 9:25:24And here here are the filters we are
  11834. 9:25:25telling it to search for script tags
  11835. 9:25:28that don't have attributes. We want to
  11836. 9:25:30have to search for script tags that have
  11837. 9:25:33attributes. So for example, this one is
  11838. 9:25:35not closed but the first one is closed.
  11839. 9:25:38And for these two we want engineext to
  11840. 9:25:42include the nons value. And this is a
  11841. 9:25:46dynamic ID or yeah request ID that is
  11842. 9:25:49generated whenever we request this file.
  11843. 9:25:52And because of security we want yeah we
  11844. 9:25:56want to make sure to uh include this
  11845. 9:26:00stuff. We are telling EngineX to replace
  11846. 9:26:03these strings with these values and this
  11847. 9:26:06should resolve that problem. So now I
  11848. 9:26:09can save the file. Exit. Let's first
  11849. 9:26:12make sure that the configuration is
  11850. 9:26:15correct. Good. And now we can reload the
  11851. 9:26:18page. Awesome. Now let's go back to the
  11852. 9:26:20page and I will do I will do a hard
  11853. 9:26:23refresh. We can do that by using control
  11854. 9:26:26shiftr. And as you can see it is working
  11855. 9:26:29now. and here. So yeah, we have just
  11856. 9:26:31warnings. We can remove them. So we can
  11857. 9:26:33see that we don't have any errors and we
  11858. 9:26:35can confirm. This is great to play to
  11859. 9:26:37try to play with this because once you
  11860. 9:26:39add a CSP, you will have problems like
  11861. 9:26:42these. And in order to uh understand
  11862. 9:26:44them, you need to read the error that
  11863. 9:26:46you are getting to understand what needs
  11864. 9:26:48to be changed. And here for example, I
  11865. 9:26:51can remove this and see if it is not
  11866. 9:26:53needed. And now I can reload the reload
  11867. 9:26:55the configuration, come back, refresh
  11868. 9:26:58the page. As you can see, we were able
  11869. 9:27:00to load the dashboard but not fully. And
  11870. 9:27:02this is how you do it. Now we see that
  11871. 9:27:05okay, we have a problem. So now we can
  11872. 9:27:07zoom in and read a little bit. It says
  11873. 9:27:09that here uh okay so the pages settings
  11874. 9:27:12blocks an inline script and here from
  11875. 9:27:15being executed we can also click on this
  11876. 9:27:18specific file and as you can see here it
  11877. 9:27:20shows us that we have this specific
  11878. 9:27:23script and what do you see? We have we
  11879. 9:27:26have the type attribute. So it's not a a
  11880. 9:27:28closed script like the one we have here.
  11881. 9:27:31Let's go back to the configuration. You
  11882. 9:27:34can see that here the scripts that we
  11883. 9:27:36captured is closed. Here it is closed
  11884. 9:27:40but this one was not we weren't able to
  11885. 9:27:42load it because now it has an attribute
  11886. 9:27:45and that was the second thing that I've
  11887. 9:27:47added in order to capture that. So let
  11888. 9:27:50me go back and paste the file and here
  11889. 9:27:52let's indent it. And uh we have seen how
  11890. 9:27:55to work with CSP. But I just wanted to
  11891. 9:27:57remind you how we do it. Uh you can use
  11892. 9:28:00LLM to help you with this. Just copy the
  11893. 9:28:03console error, give it your current
  11894. 9:28:05configuration and tell it to give you a
  11895. 9:28:07secure CSP. Sometimes it might tell you
  11896. 9:28:10to uh do the what we did before to get
  11897. 9:28:13rid of the errors quickly, but that's
  11898. 9:28:15not secure. So try to tell it to give
  11899. 9:28:18you a secure CSP and that's also going
  11900. 9:28:21to be very helpful. Okay. Now we can
  11901. 9:28:24save this file after adding this sub
  11902. 9:28:26filter. Let's reload it. I know that the
  11903. 9:28:29configuration is correct. And let's
  11904. 9:28:31refresh. And as you can see everything
  11905. 9:28:34is working perfectly. Amazing. Now let's
  11906. 9:28:36go back to the terminal because now I
  11907. 9:28:38want to talk about log rotation. We have
  11908. 9:28:41seen that when we did ls and looked at
  11909. 9:28:45the var directory, we found that we have
  11910. 9:28:49a lot of zipped files here. And if we
  11911. 9:28:52want to use them, it's not possible. So
  11912. 9:28:56that's why here in the dashboard, we see
  11913. 9:28:58just what is happening today. But let's
  11914. 9:29:00say that I want to see what happened
  11915. 9:29:02during the this month or uh during the
  11916. 9:29:05past year. I need to change the command
  11917. 9:29:07a little bit. So let's see how we can do
  11918. 9:29:10this. For that, we have a utility called
  11919. 9:29:13zeb uh grap. You can search for it.
  11920. 9:29:17Normally it is installed on Linux. So uh
  11921. 9:29:20you can use it and this is how it works
  11922. 9:29:22and it allows you to search inside the
  11923. 9:29:25zipped file. So you don't need to unzip
  11924. 9:29:27them and then search within them. This
  11925. 9:29:30utility allows you to uh search for
  11926. 9:29:32patterns within the file directly and
  11927. 9:29:35it's super useful. We can try we can try
  11928. 9:29:38to do that uh in order to show you how
  11929. 9:29:40that works. I will copy the full command
  11930. 9:29:42and then I will show you what it what it
  11931. 9:29:45does. Let me go back to the terminal. I
  11932. 9:29:48will paste the command here. I need to
  11933. 9:29:50change that placeholder using this
  11934. 9:29:52website. Let's do that quickly. Okay.
  11935. 9:29:56Let's see what we have here. Here you
  11936. 9:29:58can see that we are using a wild card.
  11937. 9:30:00This means we are going to capture every
  11938. 9:30:03file that starts with my
  11939. 9:30:05website_-access.log.
  11940. 9:30:09And this will capture the normal file
  11941. 9:30:11and the other ones that are compressed.
  11942. 9:30:14Now let's look at this Z grab-h
  11943. 9:30:17dot. If we go back to Google, here we
  11944. 9:30:20see the this uh AI generated content. It
  11945. 9:30:23says that here we pass the options and
  11946. 9:30:25the term that we want to search for. And
  11947. 9:30:27here we put dot because we want to
  11948. 9:30:29capture the whole file because that's
  11949. 9:30:31what uh go access is going to use in the
  11950. 9:30:34dashboard. And here we pass the dash h
  11951. 9:30:37option in order to basically tell it to
  11952. 9:30:41hide the file names. And here if you
  11953. 9:30:44search online you'll see that's the this
  11954. 9:30:47confirms it. So dash h means d- no file
  11955. 9:30:51name. And here yeah it's it's not going
  11956. 9:30:53to show the uh the file names in the
  11957. 9:30:55output. But that's how it works. So you
  11958. 9:30:58you give it the the files. Here we use
  11959. 9:31:01the wild card to capture all the the
  11960. 9:31:04files and here we pass that to go access
  11961. 9:31:08and here the dash is telling go access
  11962. 9:31:10to read the unccom log data from the
  11963. 9:31:14standard input because here we are using
  11964. 9:31:16pipe it's going to take the output from
  11965. 9:31:18this and give it uh to go access uh from
  11966. 9:31:22the standard input again so we here we
  11967. 9:31:25have - o web app and we put that inside
  11968. 9:31:27the and we use the combined log format
  11969. 9:31:30that and here we get a problem. So it
  11970. 9:31:32tells us permission denied. That's uh
  11971. 9:31:35understandable. So we need to add sudo
  11972. 9:31:37and uh here is what it is saying we get
  11973. 9:31:41permission denied because when we do
  11974. 9:31:43sudo like this it is going to be applied
  11975. 9:31:45to just z grab and uh after piping that
  11976. 9:31:49we are going to use that permission. So
  11977. 9:31:51we need to change that command to uh to
  11978. 9:31:55look something like this. We need to run
  11979. 9:31:56it inside this shell execution script.
  11980. 9:32:00We are using p sudo and we use bash and
  11981. 9:32:03we pass it the full command that we want
  11982. 9:32:04to that we want to run. And this will uh
  11983. 9:32:07use the pseudo privileges. And this
  11984. 9:32:09normally should work. And as you can see
  11985. 9:32:11we don't get the permission denied error
  11986. 9:32:13like we did before. And now since this
  11987. 9:32:16is inside the this folder I don't need
  11988. 9:32:18to re to reload the engineext
  11989. 9:32:20configuration. I can just update yeah
  11990. 9:32:22refresh the page. And as you can see the
  11991. 9:32:25the duration changed. So now it is
  11992. 9:32:28saying 28th of June to 12th of July
  11993. 9:32:32which is amazing. Uh normally it will be
  11994. 9:32:352 weeks max. But we will solve this
  11995. 9:32:37issue because Linux is going to first
  11996. 9:32:40compress the files but after two weeks
  11997. 9:32:43it is going to download uh to remove or
  11998. 9:32:45to delete old files. And uh yeah now you
  11999. 9:32:49can see we get more data. Now you can
  12000. 9:32:51see the number of visitors per day and
  12001. 9:32:54the number of hits. A visitor can hit
  12002. 9:32:57the server multiple times. That's why
  12003. 9:32:58the number of hits is usually higher
  12004. 9:33:00than the number of visitors. Amazing.
  12005. 9:33:04But what do we want is that we want to
  12006. 9:33:06automate this generation process. We
  12007. 9:33:08don't want to log to the virtual machine
  12008. 9:33:10and every single day generates this uh
  12009. 9:33:14updated uh static HTML file. We want to
  12010. 9:33:18automate this and we know how to do how
  12011. 9:33:20to do that. So we are going to use chron
  12012. 9:33:22tab and we are going to add uh this uh
  12013. 9:33:25file or this command to the end of that
  12014. 9:33:27file. Okay, let me copy the full command
  12015. 9:33:30and I'll paste it here. Here we are
  12016. 9:33:33going to run it uh hourly. So that's why
  12017. 9:33:37we have zero here. It's going to make
  12018. 9:33:39sure to run zap every hour for us. And
  12019. 9:33:43now the only thing I need to change is
  12020. 9:33:45this. Let me save the file and I'll just
  12021. 9:33:47copy that from here. Let's go back to
  12022. 9:33:50Chrome tab and let me change this and
  12023. 9:33:54paste it here. Great. Now we can save
  12024. 9:33:56the file. Exit. And now this is going to
  12025. 9:34:00automatically generate the dashboard.
  12026. 9:34:03And let's say tomorrow if I want to see
  12027. 9:34:06um the stats. I can just go back and uh
  12028. 9:34:10refresh the page. But we still have a
  12029. 9:34:12problem where Linux is deleting old
  12030. 9:34:15files. But we are going to come back to
  12031. 9:34:17that issue and resolve it. For now, we
  12032. 9:34:19will uh stop a little bit and we will go
  12033. 9:34:22to GitHub. I want to show you an amazing
  12034. 9:34:25project that you will find very useful.
  12035. 9:34:27It's called Btop. So, if you go to Btop
  12036. 9:34:31GitHub, it's a way to monitor resources
  12037. 9:34:34and it's super super amazing. The
  12038. 9:34:37application that they have developed
  12039. 9:34:39looks very nice. What I want you to do
  12040. 9:34:41is open the releases page and here the
  12041. 9:34:44last version is 1.4.7 4.7 and here they
  12042. 9:34:47have the pre-ompile binaries uh that we
  12043. 9:34:50can download but since we are here in
  12044. 9:34:53the terminal we need to use the wget get
  12045. 9:34:56command to download that so I'll just
  12046. 9:34:58download this one and I will use um
  12047. 9:35:01first let's use ls okay we have the file
  12048. 9:35:04there I will use tar to unzip that okay
  12049. 9:35:07now we have btop so we need to go inside
  12050. 9:35:10there sorry let's go inside btop and
  12051. 9:35:14this is the source code we can just use
  12052. 9:35:16pseudo make install to compile this
  12053. 9:35:19project. Okay, you can see that this is
  12054. 9:35:21the installer and it installed the
  12055. 9:35:24binaries uh in their respective folder
  12056. 9:35:27so that we can just type btop and uh the
  12057. 9:35:29program uh will run without a problem.
  12058. 9:35:33So now if we type btop it says that okay
  12059. 9:35:35we need to resize the window and uh
  12060. 9:35:38voila as you can see we have everything
  12061. 9:35:40here but sometimes
  12062. 9:35:43Linux will not allow btop to get uh
  12063. 9:35:46sensor data. So for that we can you can
  12064. 9:35:50run this command. So if you get that
  12065. 9:35:51problem you run pseudo set cup and that
  12066. 9:35:55will allow btop to read the sensor data
  12067. 9:35:59without an issue. After doing this, we
  12068. 9:36:02can go back one directory and remove the
  12069. 9:36:07the the files that we have inst uh
  12070. 9:36:09downloaded because now btop is running
  12071. 9:36:12without an issue. And as you can see,
  12072. 9:36:14btop is a replacement for htop or top or
  12073. 9:36:19any uh one of these commands because
  12074. 9:36:22here you can see yes, we get the same
  12075. 9:36:24information but it's hard to read
  12076. 9:36:26visually. Uh it's hard on the eye. But
  12077. 9:36:29Btop is uh is an is an amazing uh
  12078. 9:36:32terminal user interface. As you can see,
  12079. 9:36:35it looks really clean. Let me zoom in a
  12080. 9:36:37little bit just to see what is happening
  12081. 9:36:39here. You can see on top we have the
  12082. 9:36:41CPU. Since this is a lowend virtual
  12083. 9:36:46machine, we have just one core. Uh here
  12084. 9:36:48is that CPU. We have uh 512 MGB of RAM.
  12085. 9:36:54You can see is here. We see that
  12086. 9:36:55currently we are using 48% of memory and
  12087. 9:36:59uh 50% 50 52% is available. We also have
  12088. 9:37:03swap. This is what we have created in
  12089. 9:37:05the beginning. So we are allocating 2 GB
  12090. 9:37:08from disk as a swap memory to help us
  12091. 9:37:11because we don't have a lot of uh RAM
  12092. 9:37:13and uh here so we have disk we have 8 GB
  12093. 9:37:18and here we have network. So it show it
  12094. 9:37:20shows us download and upload speeds and
  12095. 9:37:23here we have the processes and here you
  12096. 9:37:26see you can you can filter you can uh
  12097. 9:37:30switch between tree view so if you hit E
  12098. 9:37:33it's going to show you individual
  12099. 9:37:35processes uh but if you want to see the
  12100. 9:37:38tree you can hit E to yeah yeah group
  12101. 9:37:41the processes uh like so if you want to
  12102. 9:37:45sort you can use the arrow keys
  12103. 9:37:48currently we are sorting by memory but
  12104. 9:37:50you can sort with other stuff. I usually
  12105. 9:37:52keep it to memory because here as you
  12106. 9:37:54can see I don't have a lot of it. So if
  12107. 9:37:56I see that my server is struggling I
  12108. 9:37:58would like to see what is the process
  12109. 9:38:01that is using a ton of resources so that
  12110. 9:38:03I can go here maybe hit K to kill that
  12111. 9:38:08specific process if it is using too much
  12112. 9:38:10memory and uh is making my application
  12113. 9:38:13work u poorly. Okay so that's how we do
  12114. 9:38:17it. You can also filter. So for example
  12115. 9:38:19here I you know that we are using J
  12116. 9:38:21unicorn. So we can look at that. And as
  12117. 9:38:24you can see here we have all of this and
  12118. 9:38:26we can hit E. And here you can see that
  12119. 9:38:29our application is using these three J
  12120. 9:38:33unicorn workers because that's what we
  12121. 9:38:36have specified. But here you can see
  12122. 9:38:38that we have some orphaned uh processes
  12123. 9:38:41that are left here maybe when we were
  12124. 9:38:44reloading the the back end but we forgot
  12125. 9:38:46to delete them and these are consuming
  12126. 9:38:49memory. So what we can do here we can
  12127. 9:38:51just hit K and kill them one uh one by
  12128. 9:38:55one because you can see that some of
  12129. 9:38:56them are using 5 MB of memory and they
  12130. 9:38:59are doing nothing and we know that here
  12131. 9:39:03when we set up the J unicorn file we
  12132. 9:39:06have specified that we want to have
  12133. 9:39:08three Unicorn workers that's why we have
  12134. 9:39:11three of them there and you can see that
  12135. 9:39:13they are grouped by the master J unicorn
  12136. 9:39:16process that's how you know if those are
  12137. 9:39:20orphaned or not. And we can also verify.
  12138. 9:39:22So if I go back to my website, it should
  12139. 9:39:26I yeah it should work without any
  12140. 9:39:28problem. So if I go back here, you can
  12141. 9:39:31see that here I have the coming soon
  12142. 9:39:33page. But that's just something that I
  12143. 9:39:35have added recently. So if I open
  12144. 9:39:37another terminal window and update. So
  12145. 9:39:41let me show you what I'm talking about.
  12146. 9:39:43Here I have this maintenance file just
  12147. 9:39:46to allow me to change between this page
  12148. 9:39:49that you are seeing right now and uh
  12149. 9:39:51this page that contains my uh website.
  12150. 9:39:56So let me reload EngineX. Let's go back
  12151. 9:39:59refresh the page and you can see I get
  12152. 9:40:00the website. And remember last time we
  12153. 9:40:03did the change where we added 2026 here.
  12154. 9:40:05And if I go back to blogs you can see
  12155. 9:40:07that the back end is still running. And
  12156. 9:40:10uh we can also verify something because
  12157. 9:40:14now if I try to kill one of these
  12158. 9:40:16workers what will happen? Let's see. It
  12159. 9:40:18is going to be killed. But as soon as
  12160. 9:40:20that happens J the manager so this
  12161. 9:40:24process manager is going to see that hey
  12162. 9:40:27we have two workers now but uh the the
  12163. 9:40:31configuration says that I need to have
  12164. 9:40:32three workers. So it is going to spin a
  12165. 9:40:34new one to uh fulfill that. If you don't
  12166. 9:40:38remember where we have that, you can
  12167. 9:40:39always go back to web app. Let's go
  12168. 9:40:43there. We open backend and let's go to
  12169. 9:40:47back end. Let's use cd instead of ls.
  12170. 9:40:51And let's see here we have you can see
  12171. 9:40:54that we have j unicorn start. Let's look
  12172. 9:40:56at that file. And as you as you can see
  12173. 9:40:59here we have specified that the number
  12174. 9:41:02of workers should be always three. And
  12175. 9:41:06here what when we are on J unicorn it is
  12176. 9:41:09going to uh ensure that we have three
  12177. 9:41:13UVORN workers. That's why when I tried
  12178. 9:41:16to kill uh one of these workers I I
  12179. 9:41:21don't see two. So one gets deleted and a
  12180. 9:41:24new one comes in. And how do we know
  12181. 9:41:27that? Just look at the process ID. So
  12182. 9:41:29here is the current process ID. Let me
  12183. 9:41:31take a screenshot quickly just to verify
  12184. 9:41:34that this is the case. Um here is the
  12185. 9:41:37screenshot. I will try to kill it again.
  12186. 9:41:40And here is the number. So you see
  12187. 9:41:42before it was uh 827 but now it changed
  12188. 9:41:45to 990.
  12189. 9:41:47And that's amazing. This is the what we
  12190. 9:41:50have in the configuration. And now if I
  12191. 9:41:52go back and refresh the page, you can
  12192. 9:41:53see this is still working because and uh
  12193. 9:41:57these processes are what's handling the
  12194. 9:42:00the requests that are coming from the
  12195. 9:42:03browser. And you can see this is why
  12196. 9:42:05Btop is amazing because it allows you to
  12197. 9:42:07interact with it uh using your mouse and
  12198. 9:42:10keyboard simply instead of top and other
  12199. 9:42:14programs that are hard to use. Okay, I
  12200. 9:42:17have now showed you how to use Btop.
  12201. 9:42:20Now, let's talk about identifying
  12202. 9:42:24bots and uh people that are trying to do
  12203. 9:42:28malicious stuff with your server. Okay?
  12204. 9:42:31And let me also show you how to
  12205. 9:42:35understand what I'm talking about. So,
  12206. 9:42:37if I go back to analytics.html,
  12207. 9:42:40you can see it is still working even
  12208. 9:42:42though we changed to my website. You can
  12209. 9:42:45see that if we focus on requested files.
  12210. 9:42:49Let me see if I can zoom in. Yes, we
  12211. 9:42:52can. But I think what we can do, we can
  12212. 9:42:54also hide some panels. So we can see
  12213. 9:42:58that here we have unique visitors. Can
  12214. 9:43:01we hide that? Yes, we can. Okay. And now
  12215. 9:43:03we have requested URLs. Here you can see
  12216. 9:43:06that this is what we currently have.
  12217. 9:43:08Some people are trying to get the site
  12218. 9:43:10map. Okay, that's fine. But look at
  12219. 9:43:11this. Someone is trying to do some fast
  12220. 9:43:14traversal inside the virtual machine.
  12221. 9:43:17This is malicious. This is not something
  12222. 9:43:18that a normal user will do. We can keep
  12223. 9:43:21looking. This one is this person is
  12224. 9:43:23trying to login somehow. Uh let's see.
  12225. 9:43:26This person is trying to get Yeah, you
  12226. 9:43:29can see there are a lot of malicious
  12227. 9:43:31things. This guy is trying to get
  12228. 9:43:33password and u some configuration
  12229. 9:43:36environment files etc. These are not
  12230. 9:43:40normal users. Basically, there is a
  12231. 9:43:42person or a group of people that are
  12232. 9:43:45building programs that are going to the
  12233. 9:43:49through the internet and trying to find
  12234. 9:43:51web servers. Once they they find your
  12235. 9:43:53web server, they try to find if there
  12236. 9:43:55are vulnerabilities. Basically, if you
  12237. 9:43:57are not good at security, you might leak
  12238. 9:44:00some files. And if they find that you
  12239. 9:44:03are leaking some passwords or some
  12240. 9:44:05common files that we see here in the
  12241. 9:44:07requested files, they will try to uh get
  12242. 9:44:11as many things from you as possible. You
  12243. 9:44:13can see that here they are also trying
  12244. 9:44:15to get some AWS credentials or stuff
  12245. 9:44:17like that. And these bots they might hit
  12246. 9:44:20your server a lot. So if you if you see
  12247. 9:44:23here here so for example this is a new
  12248. 9:44:25web server. I am not getting a lot of
  12249. 9:44:27hits but this will increase from time to
  12250. 9:44:30time but we want to solve this. We want
  12251. 9:44:32to block these people because they are
  12252. 9:44:35just wasting bandwidth. Now let's see
  12253. 9:44:37how to do this. We are not going to do
  12254. 9:44:38it manually. Meaning I am not going to
  12255. 9:44:40come here. Okay look at this request
  12256. 9:44:44come down see which IP uh because here
  12257. 9:44:47we have IP addresses. You can see that
  12258. 9:44:50here we have the IP addresses. So, we
  12259. 9:44:52need to correlate them together and see,
  12260. 9:44:54okay, this IP address is hitting my
  12261. 9:44:56websites a lot. Like, look at this one
  12262. 9:44:58for example. It says hitting the website
  12263. 9:45:01mo almost 2,000 times. That's inhuman. A
  12264. 9:45:04human person will not go through your
  12265. 9:45:06websites and try to refresh the page
  12266. 9:45:082,000 times in uh the span of two weeks.
  12267. 9:45:11So, that's how you know that you have
  12268. 9:45:13some outliers, some uh automated
  12269. 9:45:16programs that are trying to get
  12270. 9:45:18something from your website if it if
  12271. 9:45:20they found it. So here this our security
  12272. 9:45:23is great. So and we don't here we are
  12273. 9:45:25not using PHP. So the resources that
  12274. 9:45:29they are trying to get are not in on the
  12275. 9:45:31website. So that's fine but just so that
  12276. 9:45:34uh we make their life hard. We can't
  12277. 9:45:37block them. So let's see how to do this.
  12278. 9:45:39Now we understood the problem. Let's see
  12279. 9:45:40how to solve it. Let's exit now from
  12280. 9:45:43Btop. We no longer need it. You can do
  12281. 9:45:46two things. You can either look at the
  12282. 9:45:48dashboard here and see the the IP
  12283. 9:45:51addresses that are that have the high
  12284. 9:45:54amount of hits or we can ex uh tell go
  12285. 9:45:58access to give us a JSON file. So if we
  12286. 9:46:02do sudo go access let's look at this
  12287. 9:46:05command we can change it a little bit
  12288. 9:46:08here we are looking just uh at the the
  12289. 9:46:11today's log and here we do dash o to
  12290. 9:46:15specify the output but we can here in
  12291. 9:46:18this case it is an html file but we can
  12292. 9:46:21also generate a JSON file instead of
  12293. 9:46:25html let me do that I'll go here and I
  12294. 9:46:29will remove this path and replace it
  12295. 9:46:31with this one. You can see that I have
  12296. 9:46:33parsed the log file and I have generated
  12297. 9:46:36a JSON inside uh the web app folder.
  12298. 9:46:40Let's ensure that we have the file
  12299. 9:46:42there. And yes, we do. So now we can
  12300. 9:46:45write a simple Python file to analyze
  12301. 9:46:49this data. Here is the content of that
  12302. 9:46:51script. And let's see what we are trying
  12303. 9:46:53to do. First we we load the file. So if
  12304. 9:46:56we find this great we will have this
  12305. 9:46:58data dictionary and otherwise we exit if
  12306. 9:47:02we don't find it we we load the hosts
  12307. 9:47:04and from that we get data and we will
  12308. 9:47:07print the IP addresses. I will save the
  12309. 9:47:10file and I will run it just to see what
  12310. 9:47:13we will get. Okay so this is what we are
  12311. 9:47:16getting. This is the traffic that we get
  12312. 9:47:18today. Okay. So these are all the IP
  12313. 9:47:21addresses that uh reached the web
  12314. 9:47:25server. And here you can see for example
  12315. 9:47:27this IP address sent 76 uh hits today
  12316. 9:47:32and these these uh these ones send just
  12317. 9:47:36three four five. Okay. So these are low.
  12318. 9:47:38That's not a problem. Even 76 it's not
  12319. 9:47:40that big of a problem. But if I go to my
  12320. 9:47:44own personal website which which is um
  12321. 9:47:48an old [clears throat] one uh it has
  12322. 9:47:51been deployed for more than a year. In
  12323. 9:47:53that case I have some cases where one IP
  12324. 9:47:57addresses one IP address will send in
  12325. 9:48:006,000 requests 10,000 requests. Those
  12326. 9:48:03are clearly automated bots that I
  12327. 9:48:06usually block without thinking about
  12328. 9:48:08that. But let's say that this IP address
  12329. 9:48:11uh is a bot. It's not a normal user.
  12330. 9:48:14What we will do? We analyze this output
  12331. 9:48:17and we see okay so these are not doing
  12332. 9:48:19bad things or they are not wasting
  12333. 9:48:22bandwidth. We can keep them now but if
  12334. 9:48:24in the future they change their behavior
  12335. 9:48:26we can spot that. So now we copy the IP
  12336. 9:48:29address and we use the uncomplicated
  12337. 9:48:32firewall to plug them. So we use sudo
  12338. 9:48:35UFW.
  12339. 9:48:37We type deny from this IP address to any
  12340. 9:48:41and this will block that specific IP
  12341. 9:48:43address. And you can see UFW says that
  12342. 9:48:46we have a new rule. Let's confirm that.
  12343. 9:48:49I will clear the screen and I will run
  12344. 9:48:51sudo UFW status. And as you can see, we
  12345. 9:48:56denied this IP address from accessing
  12346. 9:48:59anything from the web server. So now
  12347. 9:49:02when they try to make a request is going
  12348. 9:49:04to be dropped. it's not going to reach
  12349. 9:49:06Ajax at all and that's what we want to
  12350. 9:49:08see and this is how we block nefarious
  12351. 9:49:10actors that are trying to do us harm.
  12352. 9:49:14This was the first sub chapter we have
  12353. 9:49:16talked about observability. Uh but in
  12354. 9:49:19the next sub chapter we are going to
  12355. 9:49:21focus on reliability. That's one is also
  12356. 9:49:24important. We are going to try to put
  12357. 9:49:27your server under stress. Meaning that
  12358. 9:49:30you need to know this virtual machine
  12359. 9:49:33how how much traffic can it support. So
  12360. 9:49:36if I have 100 people who are trying to
  12361. 9:49:39access the website at the same time,
  12362. 9:49:41will my application be able to handle
  12363. 9:49:43that? I cannot just say it like this. I
  12364. 9:49:45need to test that. I need to put my
  12365. 9:49:47server under stress to confirm that yes,
  12366. 9:49:50we can support that. Otherwise, no, we
  12367. 9:49:53need more resources. So we need to use a
  12368. 9:49:55tool that will help us answer this
  12369. 9:49:57question. We will also see solve the
  12370. 9:50:00problem with engineext logs. So we we
  12371. 9:50:02are going to tell index hey please don't
  12372. 9:50:03delete the files that are older than 14
  12373. 9:50:06days. Instead delete files that are
  12374. 9:50:08older than a year or something like
  12375. 9:50:09that. And I'll also show you a tool that
  12376. 9:50:12will that will allow you to analyze the
  12377. 9:50:14disc the disk space to see the uh what
  12378. 9:50:19is what are the things that are
  12379. 9:50:20consuming a lot of storage so that you
  12380. 9:50:22can delete them if you want to. and uh
  12381. 9:50:25more things. So that's what we are going
  12382. 9:50:27to talk about in the next subchapter. In
  12383. 9:50:30this sub chapter, we are going to talk
  12384. 9:50:32about reliability. Let me show you what
  12385. 9:50:35I mean by that. I've mentioned that we
  12386. 9:50:37need to simulate concurrent user traffic
  12387. 9:50:40locally using a any tool. And in the
  12388. 9:50:44Python world, we have locust, which is
  12389. 9:50:46an amazing tool that will allow us to
  12390. 9:50:49simulate a lot of people trying to
  12391. 9:50:51access our website. to answer the
  12392. 9:50:53question, can my website handle x amount
  12393. 9:50:56of traffic? So with locos, we have a
  12394. 9:50:59class called fast http user that will
  12395. 9:51:02allow us to boost execution capacity by
  12396. 9:51:05five times. So that's something that I
  12397. 9:51:06want you to use to benefit from it. And
  12398. 9:51:09we are going to use this tool called
  12399. 9:51:11NCDU to analyze the disk space to see
  12400. 9:51:16what are the things on our virtual
  12401. 9:51:19machine that are consuming space to
  12402. 9:51:20determine if we can delete it or not. If
  12403. 9:51:22we are running out of storage of course
  12404. 9:51:24we are going to use systemd journal D.
  12405. 9:51:28So we are going to enforce memory
  12406. 9:51:30constraints and build a monthly
  12407. 9:51:33automated cache and package cleanup
  12408. 9:51:35system. So we want the system to remove
  12409. 9:51:39things that are normally not used by our
  12410. 9:51:42application monthly. So this is just
  12411. 9:51:44really uh something that we can add and
  12412. 9:51:47it's going to run automatically uh for
  12413. 9:51:49us to save us some space. Amazing.
  12414. 9:51:52That's what this these are all the
  12415. 9:51:53things that we are going to look at. Now
  12416. 9:51:56let's go to the terminal to apply this.
  12417. 9:51:58So last time we saw that uh the last
  12418. 9:52:01thing we did is to block an IP address
  12419. 9:52:04that is trying to do bad things to our
  12420. 9:52:07virtual machine. Okay. Now we can
  12421. 9:52:10continue from this. We need to install a
  12422. 9:52:12tool called locust. But we need to be
  12423. 9:52:16careful. We should not install that here
  12424. 9:52:18on the virtual machine. Instead we need
  12425. 9:52:21to install it on our laptop. Because if
  12426. 9:52:24you install it here on the virtual
  12427. 9:52:25machine and you point it at your server,
  12428. 9:52:28the data that you are going to get is
  12429. 9:52:30going to be incorrect because Locos is
  12430. 9:52:33going to consume some memory and your
  12431. 9:52:35web server is trying to fulfill all
  12432. 9:52:38those requests that are sent by locos
  12433. 9:52:40and it's going to fail or it's not going
  12434. 9:52:42to fail but it's not going to handle all
  12435. 9:52:44of them because locos is there is
  12436. 9:52:46consumer uh CPU and memory. So we want
  12437. 9:52:49to put that on our laptop and then
  12438. 9:52:52perform the the test. And in order to
  12439. 9:52:55install it, you use pip install locust.
  12440. 9:52:58That's how we do it. And um after that,
  12441. 9:53:02you create a Python file uh locally to
  12442. 9:53:05perform the test. Okay. I will open the
  12443. 9:53:07terminal, a new terminal locally, go to
  12444. 9:53:10the correct directory and I will come
  12445. 9:53:13back. I am back and as you can see, I
  12446. 9:53:16have opened a new terminal. I am now
  12447. 9:53:18inside the project. I can go to back end
  12448. 9:53:21and here I have created that file inside
  12449. 9:53:25tests load because this is a uh load
  12450. 9:53:29test and this is the file that I was
  12451. 9:53:31talking about. It is called locust file.
  12452. 9:53:33You can put it wherever you want but in
  12453. 9:53:35my case I decided to put it here because
  12454. 9:53:38it is some type of testing. Now let me
  12455. 9:53:41open VS code to show you uh the contents
  12456. 9:53:44of that file. So let me zoom in and
  12457. 9:53:48let's see what we have here. Obviously
  12458. 9:53:50you need to change this based on your
  12459. 9:53:52application and you want to test a few
  12460. 9:53:55endpoints. So here I have a few
  12461. 9:53:57variables and but these are uh the
  12462. 9:54:00things that you can that you can tell
  12463. 9:54:02locus to test. So you create specific
  12464. 9:54:05tasks. Here I have a few of them and
  12465. 9:54:08each task receives a weight. So a task
  12466. 9:54:12with higher weight is going to be
  12467. 9:54:14preferred over a simple task. So here I
  12468. 9:54:17am giving a higher weight to the uh to
  12469. 9:54:20the latest and uh recommendation
  12470. 9:54:23endpoints as well as the search
  12471. 9:54:25endpoints because these are tasks that
  12472. 9:54:28are heavy that are going to do a lot of
  12473. 9:54:30work and I want locus to uh focus on
  12474. 9:54:34them so that uh because if we have a lot
  12475. 9:54:37of requests that are doing search that
  12476. 9:54:39will use more resources and here in your
  12477. 9:54:42test let's just look at one uh just as
  12478. 9:54:44an example so we tell block us to uh go
  12479. 9:54:47to this endpoint here. We uh we take
  12480. 9:54:50random inputs. So we take a random
  12481. 9:54:53query. Here are the search terms that I
  12482. 9:54:55have here. So I can search for Inkscape,
  12483. 9:54:57Python, M search and um I want to uh
  12484. 9:55:02randomly take the article type, sort
  12485. 9:55:05field and sort order. And because this
  12486. 9:55:07is a post endpoint, I need to have a
  12487. 9:55:10payload. And after doing that I can uh
  12488. 9:55:14send uh a post request using the client.
  12489. 9:55:18And here the so you can see that this is
  12490. 9:55:20the the client that we are that we have
  12491. 9:55:22here. And here is that fast HTTP user
  12492. 9:55:26class that I was talking about that will
  12493. 9:55:28boost the execution capacity by around
  12494. 9:55:30five to six times. And uh you can see
  12495. 9:55:33that it's simple and uh you can do the
  12496. 9:55:35same thing for your other endpoint. But
  12497. 9:55:38again this is specific to my
  12498. 9:55:39application. These are the endpoints
  12499. 9:55:41that I have there. But if you have other
  12500. 9:55:43things, you can change um the endpoints
  12501. 9:55:46to suit your application or your back
  12502. 9:55:48end. Okay. So this is how we write that
  12503. 9:55:51locus file. But now what do we need to
  12504. 9:55:52do? Let me show you. So after coming
  12505. 9:55:55here first I need to activate the cond
  12506. 9:55:57environment because uh locally I I like
  12507. 9:56:00to use Anaconda and here inside that
  12508. 9:56:03virtual environment I already have
  12509. 9:56:04locus. So what I need to do just type
  12510. 9:56:07locus and hit enter. Okay. So there is a
  12511. 9:56:09problem with loading imports. That's not
  12512. 9:56:11an issue. I think I need to go back to
  12513. 9:56:14back end and then run it like this. We
  12514. 9:56:17use locos and we tell it here is the
  12515. 9:56:19file. Okay, now it is working. And as
  12516. 9:56:22you can see by default locos will pick
  12517. 9:56:26the this port 8,89.
  12518. 9:56:29But if you want to specify a port, you
  12519. 9:56:33can do it like so. You can come at the
  12520. 9:56:36end and add the host option uh to add
  12521. 9:56:39the endpoint. But let's just keep things
  12522. 9:56:42simple and let's uh go to this website.
  12523. 9:56:46Okay. So this is how locus looks like.
  12524. 9:56:48Let me use light mode so that you can
  12525. 9:56:50see things clearly. Now what do we need
  12526. 9:56:54to do? Okay. So let's change the number
  12527. 9:56:57of concurrent users. At peak we will
  12528. 9:57:00have 50 people trying to access the
  12529. 9:57:03website. Here the the spawn rate or the
  12530. 9:57:06ramp up rate is going to be five. This
  12531. 9:57:08means uh locos will try to add five new
  12532. 9:57:13users every second. So that's uh what it
  12533. 9:57:16means and host here we need to put the
  12534. 9:57:18production website and make sure to do
  12535. 9:57:22this testing only when uh your website
  12536. 9:57:25is not used by people. So for example
  12537. 9:57:28before launch you will come and do the
  12538. 9:57:31testing or if you have a staging area
  12539. 9:57:33before production you can test that but
  12540. 9:57:35never test production because if you
  12541. 9:57:38increase the number of users that might
  12542. 9:57:40create problems and if you want you can
  12543. 9:57:43also open the advanced options but let's
  12544. 9:57:45keep things simple. Once we do this, we
  12545. 9:57:48will have two things here in this
  12546. 9:57:49terminal. We will see some uh some data
  12547. 9:57:52after stopping and because here we also
  12548. 9:57:55are using the dashboard, we can see it
  12549. 9:57:57here. So that's fine. But we can also I
  12550. 9:57:59can also use go access to see that
  12551. 9:58:03interactive terminal dashboard uh to get
  12552. 9:58:07the data. So let's try to do that. So we
  12553. 9:58:11we have sudo go access. So this is what
  12554. 9:58:14we have used right. Let's run that again
  12555. 9:58:17and let's see. So currently we have 214
  12556. 9:58:20requests. Okay, that's fine. Uh I'll try
  12557. 9:58:23to put this uh below like this. Let me
  12558. 9:58:27also put uh this on top like that. Uh
  12559. 9:58:32but let me decrease uh the font size a
  12560. 9:58:34little bit so that we can see this
  12561. 9:58:36better. Okay, are you ready? So this
  12562. 9:58:39page is fine but since it is going to be
  12563. 9:58:42generated every hour we are not going to
  12564. 9:58:45see realtime data that's why I am going
  12565. 9:58:48to close it and close these tabs because
  12566. 9:58:50we don't need them. Okay let's hit start
  12567. 9:58:52and let's see what will happen. So okay
  12568. 9:58:54so now we are get we are creating the we
  12569. 9:58:58are generating the requests and look
  12570. 9:58:59here you can see that we are getting
  12571. 9:59:01some traffic and here we are also uh so
  12572. 9:59:04this is the amount of data that we are
  12573. 9:59:06consuming right now and uh okay so it is
  12574. 9:59:10running and make sure to run this uh for
  12575. 9:59:135 to 10 minutes don't let it running for
  12576. 9:59:15an hour or more because that might
  12577. 9:59:18create a problem maybe your ISP or if
  12578. 9:59:21you are using cloudflare or uh other
  12579. 9:59:24stuff they might detect that you are
  12580. 9:59:25under a DOS attack and they might block
  12581. 9:59:28the IP. So just run this for 5 minutes
  12582. 9:59:30and then get the data and see uh if your
  12583. 9:59:33server was able to handle all that
  12584. 9:59:35traffic or not. So I will wait for 5
  12585. 9:59:37minutes and then I will come back and
  12586. 9:59:39let me try to make this bigger so that
  12587. 9:59:41we can see things better. Okay. So here
  12588. 9:59:43you see the number of requests. You can
  12589. 9:59:45also stop for example if you reach 8,000
  12590. 9:59:48or something like that. So currently we
  12591. 9:59:50have we we served 1,000 requests. Here
  12592. 9:59:53you get the the data that we are going
  12593. 9:59:56to look at after that. So you here we
  12594. 9:59:58have the average response time, minimum,
  12595. 10:00:01maximum and the current requests per
  12596. 10:00:04second. So for example, this endpoint is
  12597. 10:00:07receiving three requests. Again, as I
  12598. 10:00:09said, I will wait for 5 minutes and then
  12599. 10:00:11I will come back. I am back. We have
  12600. 10:00:14reached 5,000 requests. I will stop now
  12601. 10:00:17because I have the data. Okay. So we can
  12602. 10:00:20read this table or we can also check the
  12603. 10:00:23other tabs. If we click on charts that
  12604. 10:00:26gives us uh that will plot the data. Uh
  12605. 10:00:28so we can see that we started at 123 and
  12606. 10:00:32we finished at 1211 and uh so here what
  12607. 10:00:35do we have? So we have the total
  12608. 10:00:36requests per second. Uh on average we
  12609. 10:00:40were getting 16 requests per second and
  12610. 10:00:42it also shows us the requests that
  12611. 10:00:45failed. So that's interesting. We also
  12612. 10:00:48has 16 requests that were failing per
  12613. 10:00:51second. We have here the response time.
  12614. 10:00:54So normally it's small um but sometimes
  12615. 10:00:57we get these spikes. That's interesting.
  12616. 10:00:59This is the ramp up. So this is the
  12617. 10:01:02number of users. So here we started
  12618. 10:01:04small but then we reached the maximum
  12619. 10:01:06value set to 50. Okay that's good. But
  12620. 10:01:09if you are curious why sometimes we get
  12621. 10:01:12spikes in the response time that's
  12622. 10:01:14normal. This is what we call tail
  12623. 10:01:17latency. And if you are curious, there
  12624. 10:01:19is this amazing article that you can
  12625. 10:01:21read and uh so by Andrew you can see
  12626. 10:01:24that here on this image it it shows you
  12627. 10:01:27that most requests are going to have low
  12628. 10:01:30response time but some of them are going
  12629. 10:01:32to have
  12630. 10:01:34long response times and this is what we
  12631. 10:01:36call tail latency. It has nothing to do
  12632. 10:01:39with your application so don't worry
  12633. 10:01:41about it. Uh but if you want to uh read
  12634. 10:01:44more about it to see why that happens
  12635. 10:01:46even though the request is going to take
  12636. 10:01:49the same amount of time to process, you
  12637. 10:01:52can read this article. I'll make sure to
  12638. 10:01:55uh it is already on the documentation.
  12639. 10:01:58So you can find it there uh if you go to
  12640. 10:02:00the repository. And again just a
  12641. 10:02:04reminder if you don't if you don't know
  12642. 10:02:06what I am talking about, this is the
  12643. 10:02:08repo that uh that I'm that you can go
  12644. 10:02:11to. So it's called fullstack deployment
  12645. 10:02:13handbook and inside the book folder you
  12646. 10:02:16can find the content for this specific
  12647. 10:02:20module and here if you search for tail
  12648. 10:02:24latency you'll find that article here we
  12649. 10:02:27can also go to uh the terminal let's see
  12650. 10:02:31what we have here and we can stop this
  12651. 10:02:32and this will also show us some data. So
  12652. 10:02:35if you it's the same data that we have
  12653. 10:02:37in the dashboard. So you can see that
  12654. 10:02:38here we have 5,000 requests in total and
  12655. 10:02:42these are the error. So you can see that
  12656. 10:02:44we have 429.
  12657. 10:02:46Ah so now I understand why we have this
  12658. 10:02:49error because in my API endpoint I have
  12659. 10:02:52rate limiting. So that's why we get 429
  12660. 10:02:56because once we reach I think 20
  12661. 10:02:58requests per uh per minute uh I block
  12662. 10:03:01the request. So that's why we were
  12663. 10:03:03getting this. So I was confused why we
  12664. 10:03:06have a lot of errors, but that's fine.
  12665. 10:03:08So again, that's just another layer of
  12666. 10:03:10security or it's a layer to block people
  12667. 10:03:14that are that want to scrape your data
  12668. 10:03:16or something like that. So that's why we
  12669. 10:03:18have this. So that's completely
  12670. 10:03:20understandable.
  12671. 10:03:22That's amazing. I told you that the rate
  12672. 10:03:23limiting is done by minutes. So this is
  12673. 10:03:26why we have this specific recurring
  12674. 10:03:28shape because here if you look at 12 six
  12675. 10:03:31okay so the this specific user was below
  12676. 10:03:34the limit but once they reach that the
  12677. 10:03:36number of errors starts to increase
  12678. 10:03:38because they made a lot of requests but
  12679. 10:03:41after the end of that minute we reset so
  12680. 10:03:43that's why they are able to make
  12681. 10:03:46successful requests but then it
  12682. 10:03:47increases. So now let's go back to the
  12683. 10:03:50statistic to the statistics page to see
  12684. 10:03:52what we have here. So on aggregate the
  12685. 10:03:55average response time is 100
  12686. 10:03:57milliseconds. That's amazing. So if we
  12687. 10:03:59look at the search uh endpoint it's done
  12688. 10:04:03is in less than 100 milliseconds. That's
  12689. 10:04:06that's really great. But if we go to max
  12690. 10:04:08which is the SP the tail latency we uh
  12691. 10:04:11we have to wait for 2 seconds. But that
  12692. 10:04:14happens very rarely. So what you want to
  12693. 10:04:16look at is basically the 50th
  12694. 10:04:19percentile. So that's what we have here
  12695. 10:04:21in this chart. this green. Yeah. So, if
  12696. 10:04:24I remove this, if we look at this green
  12697. 10:04:27graph, you can see that this is what we
  12698. 10:04:29want to care about because most requests
  12699. 10:04:31are going to be here. And you can see
  12700. 10:04:33that the response time is slow is small.
  12701. 10:04:35It's less than 100 milliseconds. So,
  12702. 10:04:38that's that's really great. Uh that's
  12703. 10:04:40all I wanted to show you here in locus.
  12704. 10:04:43You also can look at failures,
  12705. 10:04:45exceptions. We don't have those. And if
  12706. 10:04:47you want, you can download the data. So
  12707. 10:04:49now we can close this because we have
  12708. 10:04:51stopped the server here and I can also
  12709. 10:04:54close that. And if you look at Btop you
  12710. 10:04:56can see that the server was doing a lot
  12711. 10:04:58of work uh here. But after that yeah now
  12712. 10:05:01uh it is sitting idle because there are
  12713. 10:05:03no requests. I can also close that. And
  12714. 10:05:06here if you look at this dashboard you
  12715. 10:05:08can see that here are the yeah that's
  12716. 10:05:115,000 requests that we received today.
  12717. 10:05:14And here are the end points that were uh
  12718. 10:05:17that that received a lot of work. And
  12719. 10:05:19you can see this is based on that those
  12720. 10:05:22weights that we specified in the tasks.
  12721. 10:05:25So track search were the ones that had
  12722. 10:05:28the highest weight. That's why the we
  12723. 10:05:30have a lot of uh hits. Amazing. Now we
  12724. 10:05:34can close this and we can look at the
  12725. 10:05:36NCDU utility. You know if you want to
  12726. 10:05:40look at this disk this space you can use
  12727. 10:05:42du-h
  12728. 10:05:43and that gives you this information you
  12729. 10:05:45can aggregate it stuff like that but
  12730. 10:05:47again it's not uh a tool like btop where
  12731. 10:05:51you can interact with it so that's why
  12732. 10:05:53there is a tool called ncdu that allows
  12733. 10:05:56us to inspect the disk util us usage uh
  12734. 10:06:00with a terminal user interface and that
  12735. 10:06:03tool is called ncdu and on ibuntu you
  12736. 10:06:06can use a to install it and once that's
  12737. 10:06:09done you can use sudo incdu and here we
  12738. 10:06:13are going to do a full scan starting
  12739. 10:06:16right at the root directory so that will
  12740. 10:06:19take some time but as you can see
  12741. 10:06:21already we have a nice in application
  12742. 10:06:24running in the terminal yeah we can use
  12743. 10:06:26to analyze the disk usage and as you can
  12744. 10:06:30see I can use the arrows to go through
  12745. 10:06:32all of these and here let me show you
  12746. 10:06:34what we have here so currently the total
  12747. 10:06:37disk usage is 6.2 GB. Here you can see
  12748. 10:06:40that under the user folder we are use we
  12749. 10:06:43have we are using 2 GB and here my web
  12750. 10:06:47application is using 300 mgabytes. If I
  12751. 10:06:49want to understand what is inside user I
  12752. 10:06:51can hit enter. Now I am inside can go to
  12753. 10:06:54library. Okay. So here we have things
  12754. 10:06:57related to Linux. I should not touch
  12755. 10:06:58that. Here we have Python. I should not
  12756. 10:07:00touch that because I am using it. Um so
  12757. 10:07:03that's how you use it. If I go want to
  12758. 10:07:05go back, I use I go up and uh uh so that
  12759. 10:07:09will take me uh to the user folder and
  12760. 10:07:12now I can go to maybe home. Let's see
  12761. 10:07:14what we have there. Okay, so we have my
  12762. 10:07:16user there and this these are all the
  12763. 10:07:18things. So here we have NVM because we
  12764. 10:07:20are using node, we have cache. So maybe
  12765. 10:07:24if you want to remove the pip cache, we
  12766. 10:07:26can come here and hit D. That will
  12767. 10:07:29delete it. Okay. And if you want to
  12768. 10:07:31learn more about the commands, you can
  12769. 10:07:32hit you can press the question mark and
  12770. 10:07:35that will give you this help panel that
  12771. 10:07:38shows you how to move. So if you want to
  12772. 10:07:40move your cursor, you can use the up and
  12773. 10:07:42down keys. If you want to open a
  12774. 10:07:44directory, you hit enter. If you want to
  12775. 10:07:47delete, you use the D key, etc. And you
  12776. 10:07:50can uh use the up and down arrow to see
  12777. 10:07:53the other commands. So let's hit Q to
  12778. 10:07:56close. And let's close out of incu. And
  12779. 10:08:00to do that we use Q in order to close.
  12780. 10:08:02And that's how we use incu to analyze
  12781. 10:08:05disk space and to delete uh any folder
  12782. 10:08:08that is no longer needed. Okay. So now
  12783. 10:08:11let's try to fix the issue with uh
  12784. 10:08:14rotating logs. In order to do that we
  12785. 10:08:17will open the journal D configuration.
  12786. 10:08:20And here I want you to search for this.
  12787. 10:08:22So in order to search, you type, you hit
  12788. 10:08:25Ctrl W and you paste the term that you
  12789. 10:08:28want to search for and just hit enter
  12790. 10:08:31and there it is. So what we need to do,
  12791. 10:08:33we need to uncomment this in order to
  12792. 10:08:35tell Linux to change the amount of of
  12793. 10:08:39logs that we want to use because by
  12794. 10:08:41default on Ubuntu, we allow uh systemd
  12795. 10:08:46journal D. So this damon is going to
  12796. 10:08:48consume up to 10% of your total disk
  12797. 10:08:51volume just to store logs which is a
  12798. 10:08:55lot. So if you want to change that
  12799. 10:08:57default you come here you unccommend
  12800. 10:08:59this option and you set it to 100
  12801. 10:09:02megabyte or any other value. So now
  12802. 10:09:04after we save this we need to restart
  12803. 10:09:07the service. So how do we do that? We
  12804. 10:09:10use systemctl and we restart it and we
  12805. 10:09:13now we can run status to see if it is
  12806. 10:09:16running and yes it is. That will uh
  12807. 10:09:19reduce the amount of space that we
  12808. 10:09:21allocate to logs. But in order to fix
  12809. 10:09:24the engineext issue we go here uh etc
  12810. 10:09:29log rotate and we go to engineext. And
  12811. 10:09:32as you can see here under rotate we have
  12812. 10:09:3514 days. So after for everything older
  12813. 10:09:38than 14 days will be deleted. I will
  12814. 10:09:40change that to 365.
  12815. 10:09:43And this value depends on the disk space
  12816. 10:09:46that you have left. So if you don't have
  12817. 10:09:48a lot, this is going to cause you a
  12818. 10:09:50problem because storing 365 files, it's
  12819. 10:09:54a lot. Verify that you have enough space
  12820. 10:09:56before doing this. Okay. Yeah, I'll just
  12821. 10:09:58do it because in my case, it's uh it's
  12822. 10:10:00not an issue. And I will exit. And it
  12823. 10:10:03also depends if your website receives a
  12824. 10:10:05lot of traffic because let's say that I
  12825. 10:10:07only received let's say a thousand
  12826. 10:10:09requests a day that's not a lot. So the
  12827. 10:10:11log file is going to be small but if I
  12828. 10:10:13receive 100,000 requests that's a lot.
  12829. 10:10:15So one file is going to be very huge.
  12830. 10:10:18Multiply that by 365
  12831. 10:10:20and uh imagine the amount of disk space
  12832. 10:10:23that you will be consuming. So yeah now
  12833. 10:10:26we won't we won't delete older files and
  12834. 10:10:29in the dashboard we will be able to see
  12835. 10:10:31a large uh duration so that we can see
  12836. 10:10:34what how what is happening across months
  12837. 10:10:37or weeks. Finally we are going to create
  12838. 10:10:40an automated script. I will put it
  12839. 10:10:43inside user local bin because if you
  12840. 10:10:46remember when when you put a a bash
  12841. 10:10:48script there you can run it in any
  12842. 10:10:50location. So that's the benefit of
  12843. 10:10:52putting it right there. And this
  12844. 10:10:55specific file it's small it's not that
  12845. 10:10:57big and this is what it is going to do.
  12846. 10:11:00So here set e is awesome. So if we have
  12847. 10:11:04an error is any step we are going to
  12848. 10:11:06terminate and we are going to exit
  12849. 10:11:07because we want to run all of these
  12850. 10:11:09steps without an issue. First we clean
  12851. 10:11:13um anything from apt and we use auto
  12852. 10:11:17remove with dash y to accept the the
  12853. 10:11:21things that we are going to delete. The
  12854. 10:11:23journal ctl vacuum time is a command
  12855. 10:11:27that will delete logs that are older
  12856. 10:11:29than 2 days. Here we are removing pip
  12857. 10:11:33cache and pmppm cache. And we print echo
  12858. 10:11:36system cleanup completed. And I want to
  12859. 10:11:39do this let's say once a month. Okay, so
  12860. 10:11:41I will save the file, exit. I will use C
  12861. 10:11:44cho to make it executable. Let's go back
  12862. 10:11:48to chron tab. Let's go to the end of the
  12863. 10:11:50file and let's add the following line.
  12864. 10:11:54And this is going to run this um script
  12865. 10:11:58at 3:00 a.m. in the morning on the first
  12866. 10:12:02day of every month. This is what we have
  12867. 10:12:05why we have this. And the logs are going
  12868. 10:12:07to be stored inside this file. But we
  12869. 10:12:10can see if we are getting the correct
  12870. 10:12:13echo message. Okay. Now I can save and
  12871. 10:12:16exit and that will be run that that
  12872. 10:12:19specific script will run uh once a
  12873. 10:12:21month. But you can also test it because
  12874. 10:12:23as I mentioned once we put that thing
  12875. 10:12:25there you can see that once I hit tab it
  12876. 10:12:28detects it. And now I can hit enter and
  12877. 10:12:30it says that I need to use pseudo. Okay
  12878. 10:12:33that's understandable. And because we
  12879. 10:12:35have put it inside p sudo that's fine.
  12880. 10:12:37So it's it is going to run without an
  12881. 10:12:38issue. So now it is uh using apt get to
  12882. 10:12:42clean the cache. This is the vacuum. So
  12883. 10:12:45you can see that we deleted logs that
  12884. 10:12:47are older than 2 days and you can see
  12885. 10:12:48they are using a lot of space. So here
  12886. 10:12:51we have maybe seven uh so 82 megabytes
  12887. 10:12:55and we have the correct echo message and
  12888. 10:12:58this is what we should see in that log
  12889. 10:12:59file. Amazing. We have finished this
  12890. 10:13:02reliability subchapter. Now we have one
  12891. 10:13:06more subchapter that I want to add
  12892. 10:13:08before ending this book or this course
  12893. 10:13:10and that one will be will be about
  12894. 10:13:13continuous security. If you remember
  12895. 10:13:15before uh we have created a pipeline
  12896. 10:13:20that runs uh let's see so we have SUS
  12897. 10:13:23and we also have a light security scan
  12898. 10:13:26using OASP zap but that one runs in 2
  12899. 10:13:29minutes so that's why we have included
  12900. 10:13:31it in the pipeline because it is not
  12901. 10:13:34going to block us but there is a a heavy
  12902. 10:13:37where it is so this one is lightweight
  12903. 10:13:39but there is a heavy version of this
  12904. 10:13:42that takes a lot of time that's why we
  12905. 10:13:44should not put it in the pipeline
  12906. 10:13:45because otherwise instead of waiting for
  12907. 10:13:478 minutes we might wait for 30 minutes
  12908. 10:13:49or more that's why I didn't include it
  12909. 10:13:51in the pipeline but in the next sub
  12910. 10:13:53chapter I will show you how to create a
  12911. 10:13:56GitHub action that will run daily and
  12912. 10:13:59that action is going to run that heavy
  12913. 10:14:02security dynamic security scan. So
  12914. 10:14:05that's what we are going to see in the
  12915. 10:14:06next sub chapter. It's uh it's a bonus
  12916. 10:14:09that I wanted to add to show you um how
  12917. 10:14:12that happens. And the beauty about that
  12918. 10:14:15one is that it's going to run
  12919. 10:14:16automatically. We don't need to trigger
  12920. 10:14:18it with a pull request or something like
  12921. 10:14:20that. It is going to run let's say every
  12922. 10:14:22day at 3:00 a.m. or uh something like
  12923. 10:14:25that. We can specify maybe even hourly
  12924. 10:14:27if you want. And uh once when we see an
  12925. 10:14:29error there, it means hey we have a
  12926. 10:14:31problem that we need to solve. But never
  12927. 10:14:33include that in your pipeline because
  12928. 10:14:35that will make it very very slow. We
  12929. 10:14:37arrived at the last sub chapter in
  12930. 10:14:40module 6. It is titled continuous
  12931. 10:14:43security. Let's see what we are going to
  12932. 10:14:45talk about. We have mentioned in the end
  12933. 10:14:48of the previous sub chapter that in the
  12934. 10:14:50pipeline we are performing a light
  12935. 10:14:52dynamic testing. So we want to move from
  12936. 10:14:55that state into performing a complete
  12937. 10:14:58synchronized stack. And that's what I
  12938. 10:15:01mean by a heavy security scanning
  12939. 10:15:04because we need to run the front end, we
  12940. 10:15:06need to run the back end and other
  12941. 10:15:08services. In my case, that other service
  12942. 10:15:10is M search. So we want to have all of
  12943. 10:15:12these things interacting together while
  12944. 10:15:14running the dynamic testing. We are
  12945. 10:15:17going to also use OAS, but we are going
  12946. 10:15:19to configure it a little bit to perform
  12947. 10:15:21that heavy scan. And as I said, we are
  12948. 10:15:25going to use a an automated GitHub
  12949. 10:15:28action that will use the chrome syntax
  12950. 10:15:30like we did in the chrome tab uh
  12951. 10:15:32recently to run this scan following a
  12952. 10:15:35specific uh frequency or interval. And
  12953. 10:15:39like before we are going to use that uh
  12954. 10:15:42zap rule set that specific TSV file to
  12955. 10:15:46uh avoid uh false alarms. So things
  12956. 10:15:49related to engineext security headers
  12957. 10:15:51stuff like that. We are here in my
  12958. 10:15:54second account. This is my fork. I need
  12959. 10:15:57to uh click on the repository. Uh let me
  12960. 10:16:00remove these uh tabs. We don't need
  12961. 10:16:03them. And here on GitHub, you can hit
  12962. 10:16:06the dot key to open uh VS Code directly.
  12963. 10:16:10So if you want to do things quickly, uh
  12964. 10:16:13you can do them that way. So just hit uh
  12965. 10:16:16the dot key and that that will open VS
  12966. 10:16:19Code. Uh so here it says the extension
  12967. 10:16:22yes allow login. Let's continue. The
  12968. 10:16:26only thing we need to add is a new uh
  12969. 10:16:28workflow and here we are in the master
  12970. 10:16:31branch. So we cannot push directly to it
  12971. 10:16:34because it is protected. So let's create
  12972. 10:16:36a new branch. Let's call this feed daily
  12973. 10:16:40bas scan and let's create it from the
  12974. 10:16:44head. Let's switch to that branch. Okay.
  12975. 10:16:47Now open the GitHub folder and add this
  12976. 10:16:51specific file inside the workflows
  12977. 10:16:53folder daily deep security scan. I will
  12978. 10:16:58copy the full content and I will paste
  12979. 10:17:00it here. You will see that this is
  12980. 10:17:02similar to the other file where it is
  12981. 10:17:04this dust scan. Uh I'll put them next to
  12982. 10:17:07each other so that we can see we can see
  12983. 10:17:09the difference. The only thing that we
  12984. 10:17:11have here, you can see that here we have
  12985. 10:17:13on workflow call. But here we also add
  12986. 10:17:17this option which is to schedule this.
  12987. 10:17:20So this means that this GitHub action
  12988. 10:17:24will run daily at 6 UTC. We don't need
  12989. 10:17:29to. Yes, we have the option to run it
  12990. 10:17:32manually, but on top of that, GitHub
  12991. 10:17:35will read this chrome syntax and it is
  12992. 10:17:38going to understand that we wanted to
  12993. 10:17:41run this for us every day at 6 uh UTC.
  12994. 10:17:45And that's the the only the the first
  12995. 10:17:48difference, but we have another one. So
  12996. 10:17:50here uh so because this is a deep scan,
  12997. 10:17:52we want to time it out. So if something
  12998. 10:17:55bad happened maybe uh we didn't install
  12999. 10:17:58dependencies correctly or something was
  13000. 10:17:59not working uh well we don't want this
  13001. 10:18:03job to get stuck. So we are going to
  13002. 10:18:05fail if it takes more than 30 minutes
  13003. 10:18:08and this value can be adapted based on
  13004. 10:18:10the scale of your application. So if you
  13005. 10:18:13have a lot of endpoints and a lot of
  13006. 10:18:15services the scan will take a lot of
  13007. 10:18:18time. So you want to run it maybe two,
  13008. 10:18:20three or five times to get the average
  13009. 10:18:22time and then put it here. But if we see
  13010. 10:18:25if we look at the other stuff, let me uh
  13011. 10:18:28decrease the font size. First of all, we
  13012. 10:18:30define the environment variables for me
  13013. 10:18:33search. But then the next steps are
  13014. 10:18:35similar. We check the repository. We
  13015. 10:18:38install Python. We install the backend
  13016. 10:18:41dependencies. Uh we are here. We after
  13017. 10:18:45that we install me search. Uh okay then
  13018. 10:18:49we start it we use that script to see
  13019. 10:18:53the so let's see so here we are starting
  13020. 10:18:55mill search and uh here you can see that
  13021. 10:18:57we have that seed script here it is here
  13022. 10:18:59is that same step and we also start the
  13023. 10:19:02back end so here maybe I could uh put
  13024. 10:19:06this here to have the same order let's
  13025. 10:19:09put it there you can see that here we
  13026. 10:19:10have se test data we start the backend
  13027. 10:19:14server and after that so here we stop
  13028. 10:19:17because we were testing just the back
  13029. 10:19:19end. We weren't testing the other things
  13030. 10:19:22in the stack. So we can see that here
  13031. 10:19:24after arriving at this we just pointed
  13032. 10:19:26at the open API JSON because we have a
  13033. 10:19:28fast API back end that will tell Zap all
  13034. 10:19:32the end points. But here we continue. We
  13035. 10:19:35install we set up PNPM. We install
  13036. 10:19:38NodeJS. We install the front end
  13037. 10:19:40dependencies. We build the front end.
  13038. 10:19:43And then we start it. Here we are using
  13039. 10:19:45pmppm preview because we want to
  13040. 10:19:47simulate a production environment. We
  13041. 10:19:49are not using pmppm dev because that is
  13042. 10:19:51a dev server. We want to use pmppm
  13043. 10:19:54preview. And here we uh like before we
  13044. 10:19:57are using a for loop just to ensure that
  13045. 10:19:58the front end started and and it is
  13046. 10:20:01ready to uh be used. And finally we
  13047. 10:20:04perform the full scan this time. And if
  13048. 10:20:07you look at the image that we are using
  13049. 10:20:09it's different. So here we have action
  13050. 10:20:11API scan because this is uh used for API
  13051. 10:20:15endpoints but here we are using the full
  13052. 10:20:18scan and here you can verify the version
  13053. 10:20:22to see if there are new ones. If there
  13054. 10:20:24are make sure to update and here the
  13055. 10:20:27target also changes. So we are pointing
  13056. 10:20:28at the front end. It's like a user that
  13057. 10:20:30will go there and try to do malicious
  13058. 10:20:33stuff. uh we are we don't we don't just
  13059. 10:20:35point at the back end and we are reusing
  13060. 10:20:38that TSV file and uh yeah the this the
  13061. 10:20:42other options are are the same but after
  13062. 10:20:44doing this you can see that we are going
  13063. 10:20:46to test everything in our stack mainly
  13064. 10:20:48search the front end and the back end as
  13065. 10:20:51you can see both of them are similar we
  13066. 10:20:52just uh added running the front end and
  13067. 10:20:56uh we changed the image that we are
  13068. 10:20:58using here to action full scan amazing
  13069. 10:21:02now let's commit this file. So let's
  13070. 10:21:05come here and let's say that field add a
  13071. 10:21:09new workflow for full dust scan commit
  13072. 10:21:13this and push it to this new branch that
  13073. 10:21:15we have created. And now we can create a
  13074. 10:21:18new merge request and point it at my
  13075. 10:21:21master branch. And I hope that we don't
  13076. 10:21:25have a problem with the dependencies. I
  13077. 10:21:28think we will because it's been a few
  13078. 10:21:30weeks since I've worked on this. But if
  13079. 10:21:33we yeah if I get some problem while
  13080. 10:21:36auditing the dependencies I'll try to
  13081. 10:21:38resolve them and I will come back and uh
  13082. 10:21:40Okay. So let's wait for this to finish
  13083. 10:21:43and then we can go to the actions tab
  13084. 10:21:46and look for that new file and then we
  13085. 10:21:48can run it manually from here. Let's
  13086. 10:21:51wait for this to yes thankfully the
  13087. 10:21:54auditing step passed. That's amazing. Uh
  13088. 10:21:58so that means that this will will not
  13089. 10:22:00fail hopefully because we haven't
  13090. 10:22:01changed anything in the source code. I
  13091. 10:22:04am back and as you can see we can merge
  13092. 10:22:06the pull requests because we don't have
  13093. 10:22:09any error. Let's confirm the merge and I
  13094. 10:22:12can also close this tab because I no
  13095. 10:22:15longer need it. Let's go back to master
  13096. 10:22:18and yeah as you can see it merged now.
  13097. 10:22:21Now we can click on actions and we
  13098. 10:22:24should see this new scan. Yes, here it
  13099. 10:22:27is. Daily deep security scan. Let's
  13100. 10:22:30click on it. And as you can see,
  13101. 10:22:32normally if we wait, it should run at 6
  13102. 10:22:34in the morning every day. But now it is
  13103. 10:22:3812:00 a.m. or 12:00 p.m. So I cannot
  13104. 10:22:41wait for that. So let's just hit run
  13105. 10:22:43workflow. Make sure that it is on master
  13106. 10:22:45and hit run. And uh yeah, it's just one
  13107. 10:22:49simple job. If we click on it, we will
  13108. 10:22:52see the the steps. We installed Python
  13109. 10:22:55and now we install all the dependencies
  13110. 10:22:58that we need for the back end. We
  13111. 10:23:00downloaded M search. Now we start it and
  13112. 10:23:04we need to seed it with data so that the
  13113. 10:23:06end points will work and won't return
  13114. 10:23:10errors. We have restarted the started
  13115. 10:23:12the back end and as you can see we sent
  13116. 10:23:14a request to help to ensure that server
  13117. 10:23:16has started. Now we are installing
  13118. 10:23:19NodeJS
  13119. 10:23:21the front end dependencies. We are
  13120. 10:23:23building the front end. That shouldn't
  13121. 10:23:25take a lot of time. Okay, that's done.
  13122. 10:23:27Now we start the front end using PMP
  13123. 10:23:29view. And we see the front end is ready.
  13124. 10:23:32Great. And now we are starting the full
  13125. 10:23:35scan. Hopefully that I haven't forgot
  13126. 10:23:39anything to add to that TSV file.
  13127. 10:23:43Normally this should pass because uh I
  13128. 10:23:45haven't changed anything in the back end
  13129. 10:23:47and I have tested this before on my
  13130. 10:23:49personal project or on my websites that
  13131. 10:23:52I have deployed to production. So it
  13132. 10:23:54shouldn't fail. But since this will take
  13133. 10:23:57some time, I will wait for it and then I
  13134. 10:23:59will come back. I am back and as you can
  13135. 10:24:01see the scan didn't fail. That's a good
  13136. 10:24:04sign. And in my case it took 6 minutes.
  13137. 10:24:07You can see that this is already uh
  13138. 10:24:09taking three times more time than the
  13139. 10:24:12light one. The light one took 2 minutes
  13140. 10:24:15and this one took six. So, and it runs
  13141. 10:24:17successfully and this is going to run uh
  13142. 10:24:19every single day. But as I said, if you
  13143. 10:24:22have a a large application, my personal
  13144. 10:24:24work is not that big. So, I have a few
  13145. 10:24:26endpoints that's why it took 6 minutes.
  13146. 10:24:28But if you have a lot of applications, a
  13147. 10:24:31lot of services in your app, this time
  13148. 10:24:33will increase drastically. And that's
  13149. 10:24:36all I wanted to show you in this
  13150. 10:24:37subchapter. Thank you for watching. The
  13151. 10:24:40next video will be about we will look at
  13152. 10:24:43all the things that we have learned
  13153. 10:24:45together across this long journey that
  13154. 10:24:48we took from the first sub chapter where
  13155. 10:24:50we were just talking about what we are
  13156. 10:24:53going to do. And now as you can see we
  13157. 10:24:55are able to perform scans, block IP
  13158. 10:24:59addresses and do a lot a lot of things.
  13159. 10:25:03And I hope that you have learned a ton
  13160. 10:25:04from this course. The the next video
  13161. 10:25:06will be simple. It's not going to be
  13162. 10:25:08very long, but we will try to at least
  13163. 10:25:10give you something to that that you can
  13164. 10:25:13use to basically tell you um maybe
  13165. 10:25:16remind you of all the things that you
  13166. 10:25:18have learned. Congratulations on
  13167. 10:25:21reaching the end of the course. You have
  13168. 10:25:24successfully journeyied from a bare
  13169. 10:25:27Linux server to a fully hardened
  13170. 10:25:32self-sustaining production application.
  13171. 10:25:34These are all the things you have built.
  13172. 10:25:37In the first two chapters, I have showed
  13173. 10:25:41you how to harden SSH access by removing
  13174. 10:25:46the ability to authenticate with
  13175. 10:25:48password, removing the ability to
  13176. 10:25:51connect as root user. You also learned
  13177. 10:25:55how to play with the uncomplicated
  13178. 10:25:58firewall. We have learned how to use
  13179. 10:26:01engineext socket proxying to talk to our
  13180. 10:26:04J unicorn/ Uvic application. On chapter
  13181. 10:26:09three and four we have focused on
  13182. 10:26:12performance and data. Here you have
  13183. 10:26:15learned how to isolate the the me search
  13184. 10:26:20engine by creating a new user that we
  13185. 10:26:23called me search and that user was
  13186. 10:26:26managing the this service and uh we also
  13187. 10:26:31made sure that the environment variables
  13188. 10:26:34that med search requires are stored in a
  13189. 10:26:37way that cannot be read by other users.
  13190. 10:26:40We have played with go access which
  13191. 10:26:43allows us to read the enginex logs to
  13192. 10:26:47create really beautiful dashboards that
  13193. 10:26:49shows us what is happening on our web
  13194. 10:26:52server. We have also learned how to use
  13195. 10:26:54cloudflare CDN to serve the static files
  13196. 10:26:58quickly across the world across the
  13197. 10:27:00globe and we have we have used SSL
  13198. 10:27:03certificates to make your website
  13199. 10:27:06secure. And finally in the last two
  13200. 10:27:08chapters we talked about automation and
  13201. 10:27:11security. Here you have learned about
  13202. 10:27:14pre-commit hooks so that you don't push
  13203. 10:27:16code that is broken. So you need to pass
  13204. 10:27:20a few tests in order to be able to
  13205. 10:27:22commit and push. You have learned about
  13206. 10:27:25CI/CD testing pipelines, atomic
  13207. 10:27:28rollbacks, automated
  13208. 10:27:31dynamic application security testing and
  13209. 10:27:34also uh testing the libraries that we
  13210. 10:27:38are using in our application. After
  13211. 10:27:40doing everything, now our application is
  13212. 10:27:43ready for production. Now your system is
  13213. 10:27:46observable. You have go access which
  13214. 10:27:49allows you to read the logs and get
  13215. 10:27:52realtime metrics. It's automated meaning
  13216. 10:27:56we will have zero downtime. We have seen
  13217. 10:27:59that even if we kill a UVON worker the J
  13218. 10:28:04Unicorn process manager will create one
  13219. 10:28:06for us. So even if you have a lot of
  13220. 10:28:09traffic and maybe one of the workers
  13221. 10:28:11dies everything is automated. So you
  13222. 10:28:14will have zero downtime when we deploy
  13223. 10:28:17our our application. If something
  13224. 10:28:20happened while installing the
  13225. 10:28:21dependencies, the application is not
  13226. 10:28:24going to crash. We are going to roll
  13227. 10:28:26back and use the all dependencies that
  13228. 10:28:29we had before the deployment. And
  13229. 10:28:32finally which is this is the most
  13230. 10:28:33important point security. We have made
  13231. 10:28:36sure that people cannot log in using SSH
  13232. 10:28:40as root or by using a password. We you
  13233. 10:28:43have SSL certificates that renew
  13234. 10:28:45automatically so that people who connect
  13235. 10:28:47to your website are connected securely
  13236. 10:28:50and we have done a lot of testing jobs
  13237. 10:28:53in our CI/CD pipeline. I really hope
  13238. 10:28:56that you enjoyed going through this
  13239. 10:28:58course with me and now we are completely
  13240. 10:29:01ready to build, launch and scale your
  13241. 10:29:03features with absolute confidence. Thank
  13242. 10:29:06you for following along and happy
  13243. 10:29:08building.

About this transcript

This page contains the full transcript of How to Deploy, Secure, and Automate Full-Stack Web Apps – Course for Beginners by freeCodeCamp.org, generated from the public captions YouTube serves with the video. The transcript has 100,405 words across 13,243 segments, with the original timestamps preserved so you can click any line to jump to that moment in the embedded player.

What you can do with it

Use the transcript to take notes, quote the speaker, build a study guide, generate a summary with ChatGPT or Claude via the YouTube Summary tool, or export it as a timed subtitle file with YouTube to SRT. You can also re-open it in the transcriber to translate the transcript into 100+ languages.

Free YouTube transcript tool

YouTube2Text is a free YouTube transcript generator — no signup, no daily limit. Paste any YouTube link and get the full transcript instantly, with timestamps, click-to-jump, translation to 100+ languages, AI prompts for ChatGPT, Claude, and Gemini, and exports to TXT, SRT, VTT, or Markdown.