Instructions to set up a basic LAMP+SSH server environment
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

493 lines
26 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. Linux servers - Exercise 3
  2. ==============
  3. *Disclaimer:*
  4. --------------
  5. This exercise is a part of [Linux Server Administration (ICT4TN021, spring 2018) // Linux-palvelimet (ICT4TN021, kevät 2018)](http://www.haaga-helia.fi/fi/opinto-opas/opintojaksokuvaukset/ICT4TN021) school course organized as a part of Information Technology studies in Haaga-Helia university of Applied Sciences, Helsinki, Finland. Course lecturer [Tero Karvinen](http://terokarvinen.com/) has defined the original assignment descriptions in Finnish presented in this document in English. Answers and translations have been written by Pekka Helenius (me, ~ Fincer).
  6. *Table of contents:*
  7. --------------
  8. - [a) **Installation of HTTP server environment** Install Apache web server and set up a working web environment for each system user (http://example.com/~tero). Test the correct functionality with a sample website.](https://github.com/Fincer/linux-server-setup/blob/master/exercises/h3.md#a-install-apache-web-server-and-set-up-a-working-web-environment-for-each-system-user-httpexamplecomtero-test-the-correct-functionality-with-a-sample-website)
  9. - [b) **HTTP server logs** Browse and explore the websites on your local host. Find out any hints of successful (200 ok) website load events and failed load events (for instance, 404 not found). Analyse the relevant lines.](https://github.com/Fincer/linux-server-setup/blob/master/exercises/h3.md#b-browse-and-explore-the-websites-on-your-local-host-find-out-any-hints-of-successful-200-ok-website-load-events-and-failed-load-events-for-instance-404-not-found-analyse-the-relevant-lines)
  10. - [c) **HTTP server error event** Create a purposeful error in any code line which is executed by Apache web server (PHP or Python, for instance). Find out any relevant log lines and analyse them in detail.](https://github.com/Fincer/linux-server-setup/blob/master/exercises/h3.md#c-create-a-purposeful-error-in-any-code-line-which-is-executed-by-apache-web-server-php-or-python-for-instance-find-out-any-relevant-log-lines-and-analyse-them-in-detail)
  11. - [e) **Database management** Install and try out PhpMyAdmin or similar out-of-the-box web-based database management solution.](https://github.com/Fincer/linux-server-setup/blob/master/exercises/h3.md#e-install-and-try-out-phpmyadmin-or-similar-out-of-the-box-web-based-database-management-solution)
  12. - [f) **Web application** Create a web application which executes a simple calculation for the user (BMI calculator, for instance)](https://github.com/Fincer/linux-server-setup/blob/master/exercises/h3.md#f-create-a-web-application-which-executes-a-simple-calculation-for-the-user-bmi-calculator-for-instance)
  13. --------------
  14. **a)** Install Apache web server and set up a working web environment for each system user (http://example.com/~tero). Test the correct functionality with a sample website.
  15. --------------
  16. **Answer:**
  17. ```
  18. #!/bin/sh
  19. ############
  20. # List package names of Uncomplicated Firewall ja Apache HTTP web server in a new variable PROGRAMS
  21. #
  22. PROGRAMS="ufw apache2"
  23. ############
  24. # Define new function 'install'
  25. #
  26. # Function 'install' - BEGIN
  27. function install() {
  28. ############
  29. # Look for executable 'apt-get', silent error printing (stderr), print count of matching strings.
  30. # Define these checks in a new variable APT_CHECK so that these checks can easily be performed later in the script.
  31. #
  32. # grep part could have been excluded but it is still good to check that this file is not compromised and is truly
  33. # an executable binary file.
  34. #
  35. # EXAMPLE If the system is compromised and the attacker replaces file /usr/bin/apt-get with his/her own version, the following
  36. # APT_CHECK might successfully pass without additional grep pipe (check additional notes below).
  37. #
  38. # Demonstration is as follows (in root shell, because we assume that the attacker has access to root account).
  39. # It is pretty clear that if the attacker has root access, almost all hope is lost because the attacker can likely access and modify almost any part in the system. However, we don't speculate with this option here.
  40. #
  41. # root@my-machine:/home/phelenius# echo -e "#\!/bin/sh\necho \"Attacker's code\"\n" > /usr/bin/malicious
  42. # root@my-machine:/home/phelenius# chmod +x /usr/bin/malicious
  43. # root@my-machine:/home/phelenius# which malicious
  44. # /usr/bin/malicious
  45. #
  46. # The file /usr/bin/malicious is identified as executable. However, if we check its mimetype, we can find out the following:
  47. # root@my-machine:/home/phelenius# file --mime-type $(which malicious)
  48. # /usr/bin/malicious: text/plain
  49. #
  50. # Therefore we can find out the executable we though would be a binary is simply a text file. In similar way, the following APT_CHECK command would pass without grep pipe which fills the security gap a little bit. However, there's still a hole. A major risk still exist because attacker could have replaced the valid apt-get executable with his/her own malicious binary file (with correct mimetype application/x-sharedlib). In this scenario, a checksum validation should seriously be considered (compare against a trusted apt-get binary file).
  51. #
  52. APT_CHECK=$(file --mime-type $(which apt-get) 2> /dev/null | grep -o application | wc -w)
  53. ############
  54. # The next if statement has the following conditions:
  55. # if apt-get command is found in the system (APT_CHECK variable check), and...
  56. # ...if the current user is not root (UID is not 0), and...
  57. # ...the current user belongs to sudo group
  58. #
  59. if [[ $APT_CHECK -eq 1 ]] && [[ $(id -u) -ne 0 ]] && [[ $(groups | grep -o sudo | wc -w) -eq 1 ]]; then
  60. ############
  61. # Update packages from sources listed in /etc/apt/sources.list file and in /etc/apt/sources.d/ directory
  62. #
  63. sudo apt-get update
  64. ############
  65. # Install programs, which have been defined in the variable PROGRAMS
  66. #
  67. sudo apt-get -y install $PROGRAMS
  68. ############
  69. # If the previous command succeeded, pass and execute the commands inside if statement
  70. #
  71. if [[ $? -eq 0 ]]; then
  72. ############
  73. # Enable Apache2 specific userdir module
  74. #
  75. sudo a2enmod userdir
  76. ############
  77. # Enable "ServerName" parameter with value 'www.example.com' in Apache's default page configuration file (000-default.conf)
  78. #
  79. sudo sed -i 's/#ServerName www\.example\.com/ServerName www\.example\.com/' /etc/apache2/sites-enabled/000-default.conf
  80. ############
  81. # Add "ServerAlias" after "ServerName" in Apache's default page configuration file (000-default.conf)
  82. #
  83. sudo sed -i '/ServerName www\.example\.com/a\ \ \ \ \ \ \ \ ServerAlias example\.com' /etc/apache2/sites-enabled/000-default.conf
  84. ############
  85. # Add new local virtual host example.com to /etc/hosts file
  86. #
  87. echo -e "127.0.0.1\texample.com" | sudo tee -a /etc/hosts
  88. ############
  89. # Restart Apache2 HTTP web server daemon
  90. #
  91. sudo systemctl restart apache2.service
  92. fi
  93. fi
  94. }
  95. # Function 'install' - END
  96. ############
  97. # Execute the function 'install', described above
  98. #
  99. install
  100. ############
  101. # Create public_html directory in the current user's home directory (either $HOME or ~ can be used)
  102. #
  103. mkdir -p ~/public_html/
  104. ############
  105. # Create a new file index.html inside $HOME/public_html with the following html contents:
  106. #
  107. echo -e '\
  108. <!DOCTYPE html>\n \
  109. <html>\n \
  110. \t<head>\n \
  111. \t\t<title>Test</title>\n \
  112. \t</head>\n \
  113. \t<body>\n \
  114. \t\t<h1>Test</h1>\n \
  115. \t</body>\n \
  116. </html>\n \
  117. ' \
  118. > ~/public_html/index.html
  119. # About the echo command:
  120. # \t stands for tabulator
  121. # \n stands for a newline
  122. # \ stands for a newline for multiline input in shell environment
  123. # > stands for writing the contents of the echo command into the file/output mentioned after this symbol.
  124. # -e stands for "enable interpretation of backslash escapes" (meaning that you can use \t \n \r \s....symbols in echo command)
  125. #################################
  126. # Is the following procedure secure? However, something found in the internet:
  127. #
  128. # "Basically, the Apache server does not only require read permissions of all files it serves, but the execution permission of all directories in the path of your virtual host."
  129. # https://askubuntu.com/questions/451922/apache-access-denied-because-search-permissions-are-missing
  130. #
  131. chmod 701 $HOME
  132. ############
  133. # Test the created site with the default graphical web browser as the current user (retrieved with whoami command + bash internal command substitution method)
  134. #
  135. xdg-open http://example.com/~$(whoami)/
  136. ```
  137. **b)** Browse and explore the websites on your local host. Find out any hints of successful (200 ok) website load events and failed load events (for instance, 404 not found). Analyse the relevant lines.
  138. --------------
  139. **Answer:**
  140. **NOTE!** My detailed answer to this assignment is in the previous exercise 2, section a) (successful & failed event + analysing them). Link: [Exercise 2](https://github.com/Fincer/linux-server-setup/blob/master/exercises/h2.md)
  141. In my answer I have analysed Apache web server log lines. The logic is exactly same than required in this assignment. Apache logs each event when a client (web browser, for instance) try to access a file or location in server.
  142. **c)** Create a purposeful error in any code line which is executed by Apache web server (PHP or Python, for instance). Find out any relevant log lines and analyse them in detail.
  143. --------------
  144. **Answer:**
  145. Let's install PHP 7.0 with Apache2, and execute a shell script which does as required.
  146. ```
  147. #!/bin/sh
  148. ############
  149. # Look for executable 'apt-get', silent error printing (stderr), print count of matching strings.
  150. # Define these checks in a new variable APT_CHECK so that these checks can easily be performed later in the script.
  151. APT_CHECK=$(file --mime-type $(which apt-get) 2> /dev/null | grep -o application | wc -w)
  152. ############
  153. # Look for executable 'wget', silent error printing (stderr), print count of matching strings.
  154. # Define these checks in a new variable WGET_CHECK so that these checks can easily be performed later in the script.
  155. WGET_CHECK=$(file --mime-type $(which wget) 2> /dev/null | grep -o application | wc -w)
  156. ############
  157. # Print count of matching strings which have retrieved by checking any packages containing 'apache2' on Debian system.
  158. # Define this check in a new variable APACHE2_CHECK so that this check can easily be performed later in the script.
  159. APACHE2_CHECK=$(dpkg --get-selections | grep apache2 | wc -l)
  160. ############
  161. # External PHP code download link (NOTE! Downloading untrusted files is not recommended in security oriented system environments!)
  162. # Define this command in a new variable SAMPLE_CODE so that it can easily be called later in the script.
  163. SAMPLE_CODE="https://gist.githubusercontent.com/pchatterjee/3756368/raw/40c241c344c3e8d2333cc0c496e2782d9a1e6d93/calculator_v2.php"
  164. ############
  165. # The next if statement has the following conditions:
  166. # if apt-get command is found in the system (APT_CHECK variable check), and...
  167. # ...if the current user is not root (UID is not 0), and...
  168. # ...the current user belongs to sudo group
  169. #
  170. if [[ $APT_CHECK -eq 1 ]] && [[ $(id -u) -ne 0 ]] && [[ $(groups | grep -o sudo | wc -w) -eq 1 ]]; then
  171. ############
  172. # If apache2 is installed in the system, then...
  173. #
  174. if [[ $APACHE2_CHECK -gt 0 ]]; then
  175. ############
  176. # install PHP 7.0 and relevant Apache2 PHP 7.0 modules
  177. #
  178. sudo apt-get install -y php7.0 libapache2-mod-php
  179. ############
  180. # Comment the following lines in file /etc/apache2/modules-available/php7.0.conf, so that PHP works for with userdir module.
  181. #
  182. # TODO Better method should be coded. The current method has a risk that it replaces wrong lines, especially if there are multiple similar lines in a file.
  183. # Better approach would be to replace lines by starting from line which includes pattern <IfModule and ending to line matching pattern </IfModule
  184. # However, because content structure of php7.0.conf file is not complicated at this moment, the current solution "works".
  185. # Better approach must be implemented if handling any more complex php7.0.conf file.
  186. #
  187. sed -i 's?<IfModule mod_userdir\.c>?#<IfModule mod_userdir\.c>?' /etc/apache2/mods-enabled/php7.0.conf
  188. sed -i 's?<Directory /home/\*/public_html>?#<Directory /home/\*/public_html>?' /etc/apache2/mods-enabled/php7.0.conf
  189. sed -i 's?php_admin_flag engine Off?#php_admin_flag engine Off?' /etc/apache2/mods-enabled/php7.0.conf
  190. sed -i 's?</Directory>?#</Directory>?' /etc/apache2/mods-enabled/php7.0.conf
  191. sed -i 's?</IfModule>?#</IfModule>?' /etc/apache2/mods-enabled/php7.0.conf
  192. ############
  193. # If command wget is available on the system, then...
  194. #
  195. if [[ $WGET_CHECK -eq 1 ]]; then
  196. ############
  197. # Download sample PHP code into directory $HOME/public_html/
  198. # NOTE! Can we trust the downloaded code?
  199. #
  200. echo -e "\nDownloading sample PHP code for testing purposes (requires internet connection, security risk exists! Use local trusted code if system hardening means anything to you...)\n"
  201. #
  202. wget -P $HOME/public_html/ $SAMPLE_CODE
  203. ############
  204. # Let's generate a purposeful error in file $HOME/public_html/calculator_v2.php by altering the code with sed command (switch -> switchasd)
  205. #
  206. sed -i 's/switch($op) {/switchasd($op) {/' $HOME/public_html/calculator_v2.php
  207. ############
  208. # Let's try to open the erroneous PHP site with the default graphical web browser.
  209. # xdg-open command refers to default program defined to open specific mimetypes or protocols in Linux operating system.
  210. #
  211. xdg-open http://example.com/~$(whoami)/calculator_v2.php
  212. ############
  213. # Command 'wget' is not found in the system
  214. #
  215. else
  216. echo -e "\nInstall application 'wget' before downloading a sample code"
  217. fi
  218. ############
  219. # Packages matching string 'apache2' can't be found in the system by doing the check via Debian package manager
  220. #
  221. else
  222. echo -e "\nYou need to install Apache web server before PHP 7.0\n"
  223. exit
  224. fi
  225. fi
  226. ```
  227. Apache web server prints out the following error message in `/var/log/apache2/error.log` while trying to open local website `example.com/~phelenius/calculator_v2.php`:
  228. ```
  229. [Wed Feb 07 00:20:02.923994 2018] [:error] [pid 14260] [client 127.0.0.1:38430] PHP Parse error: syntax error, unexpected 'case' (T_CASE) in /home/phelenius/public_html/calculator_v2.php on line 20
  230. [Wed Feb 07 00:20:03.203824 2018] [:error] [pid 14259] [client 127.0.0.1:38432] PHP Parse error: syntax error, unexpected 'case' (T_CASE) in /home/phelenius/public_html/calculator_v2.php on line 20
  231. [Wed Feb 07 00:20:03.684123 2018] [:error] [pid 14258] [client 127.0.0.1:38434] PHP Parse error: syntax error, unexpected 'case' (T_CASE) in /home/phelenius/public_html/calculator_v2.php on line 20
  232. [Wed Feb 07 00:20:03.932480 2018] [:error] [pid 14268] [client 127.0.0.1:38436] PHP Parse error: syntax error, unexpected 'case' (T_CASE) in /home/phelenius/public_html/calculator_v2.php on line 20
  233. [Wed Feb 07 00:20:04.269771 2018] [:error] [pid 14261] [client 127.0.0.1:38438] PHP Parse error: syntax error, unexpected 'case' (T_CASE) in /home/phelenius/public_html/calculator_v2.php on line 20
  234. [Wed Feb 07 00:20:04.470184 2018] [:error] [pid 14262] [client 127.0.0.1:38440] PHP Parse error: syntax error, unexpected 'case' (T_CASE) in /home/phelenius/public_html/calculator_v2.php on line 20
  235. ```
  236. Apache web server complains multiple times about a PHP syntax error in `/home/phelenius/public_html/calculator_v2.php` file, on line 20.
  237. Mentioned PIDs (Process IDs) belong to apache2 process:
  238. ```
  239. phelenius@my-machine:~$ ps aux |grep -E "14261|14262|14268|14258|14259|14260"
  240. www-data 14258 0.0 0.5 253844 11648 ? S 00:16 0:00 /usr/sbin/apache2 -k start
  241. www-data 14259 0.0 0.5 253844 11648 ? S 00:16 0:00 /usr/sbin/apache2 -k start
  242. www-data 14260 0.0 0.5 253844 11648 ? S 00:16 0:00 /usr/sbin/apache2 -k start
  243. www-data 14261 0.0 0.7 254136 14372 ? S 00:16 0:00 /usr/sbin/apache2 -k start
  244. www-data 14262 0.0 0.5 253844 11648 ? S 00:16 0:00 /usr/sbin/apache2 -k start
  245. www-data 14268 0.0 0.5 253844 11648 ? S 00:16 0:00 /usr/sbin/apache2 -k start
  246. ```
  247. IP address `127.0.0.1` refers to local host, numbers `38430`, `38432`, `38434`, `38436`, `38438` and `38440` to the ports where the connection has been established from.
  248. The equivalent log events in `/var/log/apache2/access.log`:
  249. ```
  250. 127.0.0.1 - - [07/Feb/2018:00:20:02 +0200] "GET /~phelenius/calculator_v2.php HTTP/1.1" 500 185 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3300.0 Iron Safari/537.36"
  251. 127.0.0.1 - - [07/Feb/2018:00:20:03 +0200] "GET /~phelenius/calculator_v2.php HTTP/1.1" 500 185 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3300.0 Iron Safari/537.36"
  252. 127.0.0.1 - - [07/Feb/2018:00:20:03 +0200] "GET /~phelenius/calculator_v2.php HTTP/1.1" 500 185 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3300.0 Iron Safari/537.36"
  253. 127.0.0.1 - - [07/Feb/2018:00:20:03 +0200] "GET /~phelenius/calculator_v2.php HTTP/1.1" 500 185 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3300.0 Iron Safari/537.36"
  254. 127.0.0.1 - - [07/Feb/2018:00:20:04 +0200] "GET /~phelenius/calculator_v2.php HTTP/1.1" 500 185 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3300.0 Iron Safari/537.36"
  255. 127.0.0.1 - - [07/Feb/2018:00:20:04 +0200] "GET /~phelenius/calculator_v2.php HTTP/1.1" 500 185 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3300.0 Iron Safari/537.36"
  256. ```
  257. - User's client program (address `127.0.0.1` / `localhost` + client is web browser in this case) tries to retrieve server website `/~phelenius/calculator_v2.php` for which the Apache web server has responded with error code 500 ([HTTP_INTERNAL_SERVER_ERROR](https://ci.apache.org/projects/httpd/trunk/doxygen/group__HTTP__Status.html#ga5d9777e02c26063c2985e39ef71091d2)).
  258. - User ID is simply a line symbol
  259. - Log time is "07/Feb/2018:00:20:04 +0200" (and similar)
  260. - HTTP method used is [GET](https://www.w3schools.com/tags/ref_httpmethods.asp)
  261. - has [HTTP Referer](https://en.wikipedia.org/wiki/HTTP_referer)
  262. - size of the object is `185` (reported to the client program)
  263. - [User agent header](https://en.wikipedia.org/wiki/User_agent) reported by the client. According to the agent string, client browser has been gecko-based [Epiphany web browser](https://en.wikipedia.org/wiki/Epiphany_(GNOME)), using x86_64 processor architecture. This string can be manipulated in the client end. For instance, a desktop client web browser can pretend to be a mobile browser.
  264. Default syntax for Apache log files follow the layout which is described [here](https://httpd.apache.org/docs/2.4/logs.html) under section 'Common Log Format'.
  265. **e)** Install and try out PhpMyAdmin or similar out-of-the-box web-based database management solution.
  266. --------------
  267. **Answer:**
  268. **NOTE!** We assume that the established Linux system has a working Apache HTTP daemon web server and PHP 5.0 or PHP 7.0 script language packages installed as Apache modules (see tasks [a)](https://github.com/Fincer/linux-server-setup/blob/master/exercises/h3.md#a-install-apache-web-server-and-set-up-a-working-web-environment-for-each-system-user-httpexamplecomtero-test-the-correct-functionality-with-a-sample-website) and [c)](https://github.com/Fincer/linux-server-setup/blob/master/exercises/h3.md#c-create-a-purposeful-error-in-any-code-line-which-is-executed-by-apache-web-server-php-or-python-for-instance-find-out-any-relevant-log-lines-and-analyse-them-in-detail) above).
  269. **1.** [phpMyAdmin](https://en.wikipedia.org/wiki/PhpMyAdmin) requires MySQL/MariaDB database back-end server. Let's install MySQL database server with its runtime dependencies on Debian-based distribution (Ubuntu 16.04.3 LTS in this case).
  270. ```
  271. sudo apt-get -y install mysql-server
  272. ```
  273. **2.** Local administrator (assumed to belong to sudo group) is asked to set a new password for root MySQL database root account:
  274. **NOTE!** This description applies to Ubuntu 16.04 LTS. Newer OS releases may not ask you to set MySQL password after MySQL server installation. If you don't see a blue screen stating "While not mandatory...", run the following command instead:
  275. ```
  276. sudo mysql_secure_installation
  277. ```
  278. ```
  279. Configuring mysql-server-5.7
  280. While not mandatory, it is highly recommended that you set a password for the MySQL administrative "root" user.
  281. If this field is left blank, the password will not be changed.
  282. New password for the MySQL "root" user:
  283. ```
  284. We should choose a strong password (`Hu8aS1n?tI23` or `Tu$pAR!iMu65` etc. Can be generated with a password generator program `pwgen` as well). We should use a password which we don't use in other environments.
  285. **NOTE!** If unsure, check and configure your keyboard layout so that the password you supply will be correctly set up.
  286. When you have entered your password, press `TAB` and then press `<Ok>` (or just `ENTER` key). Type the password again and continue.
  287. **3.** Let's install [phpMyAdmin](https://en.wikipedia.org/wiki/PhpMyAdmin) with its runtime dependencies on Debian-based distribution (Ubuntu 16.04.3 LTS in this case).
  288. ```
  289. sudo apt-get install -y phpmyadmin
  290. ```
  291. Accept the installation with extra dependencies.
  292. **4.** On Debian-based systems, the next screen states:
  293. ```
  294. Configuring phpmyadmin
  295. Please choose the web server that should be automatically configured to run phpMyAdmin.
  296. Web server to reconfigure automatically:
  297. [] apache2
  298. [] lighttpd
  299. ```
  300. Because we assume that you have Apache2 and not lighttpd, we should select `apache2`. Press `SPACE` key so that option `apache2` will have asterix in the brackets (`[*]`). After that, press `TAB` key to move your current selection to `<Ok>` and press `ENTER` key.
  301. **5.** The next screen states:
  302. ```
  303. Configuring phpmyadmin
  304. The phpmyadmin package must have a database installed and configured before it can be used. This can be optionally handled with dbconfig-common.
  305. If you are an advanced database administrator and know that you want to perform this configuration manually, or if your database has already been installed and configured, you should refuse this option. Details on what needs to be done should most likely be provided in /usr/share/doc/phpmyadmin.
  306. Otherwise, you should probably choose this option.
  307. Configure database for phpmyadmin with dbconfig-common?
  308. ```
  309. The most common selection in this step is `<Yes>` (alternative to `<No>`). For choosing a right choice, the following manuals can be used:
  310. [Configure the database with dbconfig-common](https://docs.openstack.org/ocata/fr/install-guide-debconf/debconf/debconf-dbconfig-common.html)
  311. [dbconfig-common.pdf](https://www.debian.org/doc/manuals/dbconfig-common/dbconfig-common.pdf)
  312. [Stackoverflow - What means dbconfig-common](https://stackoverflow.com/questions/31403273/what-means-dbconfig-common)
  313. Additionally, for instance:
  314. ![dbconfig-common_1](https://docs.openstack.org/ocata/fr/install-guide-debconf/_images/dbconfig-common_keep_admin_pass.png)
  315. ![dbconfig-common_1](https://docs.openstack.org/ocata/fr/install-guide-debconf/_images/dbconfig-common_used_for_remote_db.png)
  316. Let's choose option `<Yes>` because we don't have earlier database in our system. More secure, although more troublesome, approach would be selecting `<No>`, according to the material references above.
  317. **NOTE!** dpkg tool `dpkg-reconfigure` makes it possible to change package-related configuration in Debian-based systems afterwards (for instance, `sudo dpkg-reconfigure phpmyadmin`). However, pay special attention and use extra care if you do any configurations afterwards.
  318. **6.** The next screen asks system administrator to set up MySQL database-related password for phpmyadmin MySQL user:
  319. ```
  320. Configuring phpmyadmin
  321. Please provide a password for phpmyadmin to register with the database server. If left blank, a random password will be generated.
  322. MySQL application password for phpmyadmin:
  323. ```
  324. Let's pick up a strong password for phpmyadmin. Take a look on step 2. for setting up a strong password. Use different password here.
  325. **7.** If you are not asked to set up a default phpmyadmin username or password, please run `sudo dpkg-reconfigure phpmyadmin`. The default phpmyadmin username is usually `phpmyadmin` and the login password is the one you write down by executing the command mentioned earlier in this step.
  326. **8.** Let's try accessing phpMyAdmin front page:
  327. ```
  328. xdg-open http://localhost/phpmyadmin
  329. ```
  330. If the installation has been successful, the web browser view should look like this:
  331. ![phpmyadmin-loginpage](https://rootninja.files.wordpress.com/2010/10/image38.png)
  332. **9.** Log in to phpMyAdmin with the following credentials:
  333. - **user name:** `phpmyadmin` (or any other defined during phpmyadmin installation)
  334. - **password:** password defined in step 7.
  335. **10.** If successfully logged in, the web browser view should be as follows (phpMyAdmin - Front page):
  336. ![phpmyadmin-frontpage](https://github.com/Fincer/linux-server-setup/blob/master/images/phpmyadmin-resized.png)
  337. phpMyAdmin - Database configuration sample:
  338. ![phpmyadmin-dbconfpage](https://github.com/Fincer/linux-server-setup/blob/master/images/phpmyadmin-2-resized.png)
  339. **f)** Create a web application which executes a simple calculation for the user (BMI calculator, for instance)
  340. --------------
  341. **Answer:**
  342. **NOTE!** We assume that the Linux installation has a working Apache HTTP daemon web server with correct PHP support enabled. Apache server has `userdir` module enabled, and some local user has `public_html` folder created in `$HOME` folder.
  343. **1.** Let's create the following, very simple PHP code and save it to `~/public_html/rainfall.php` (current user)
  344. ```
  345. <?php
  346. $rainfalls = array(54.2, 43.1, 37.5, 25.6, 10.2, 15.7, 29.4, 41.9, 55.6, 69.1, 77.2, 64.3);
  347. // Print output
  348. echo "Total rainfall is " . array_sum($rainfalls) . " millimeters in a year.";
  349. ?>
  350. ```
  351. **2.** Let's open the php file with the default graphical web browser found in the local Linux system:
  352. ```
  353. xdg-open http://example.com/~$(whoami)/rainfall.php
  354. ```
  355. Result:
  356. ![php-sample-image-1](https://github.com/Fincer/linux-server-setup/blob/master/images/php-example-rainfall.png)