====== LAMP on Debian 12 ======
===== Apache 2.4 Installation =====
- Install apache 2.4$ sudo apt update
$ sudo apt install apache2
- Add one of the two commands to add the user to apache's user group:$ sudo adduser www-data
$ sudo usermod -a -G www-data
- Setup your virtual hosts
- Create sub folders in ''/var/log/apache2'' if you setup log files for the virtual hosts in sub folders
- Install and configure [[deb11:certbot|Let's Encrypt Certbot]]
==== Settings ====
* Harden apache
* change //ServerTokens// and //ServerSignature// in /etc/apache2/conf.d/security.conf
* add //Require all granted// to your web space, possibly exclude black listed ip addresses, and restrict access to phpmyadmin etc. Put a respective conf file into /etc/apache2/conf.d.
* ''MaxRequestedWorkers'': modify /etc/apache2/mods-available/mdm-prefork.conf and restart apache2$ sudo apache2ctl -V | grep MPM
vim /etc/apache2/mods-available/mdm-prefork.conf
MaxRequestedWorkers 400
ServerLimit 400
$ sudo service apache2 restart
==== Links ====
* [[https://community.letsencrypt.org/t/multiple-servers-one-ip-address-home-setup-issue/64210|Multiple servers one IP address]]
* [[https://stackoverflow.com/questions/2364840/what-is-the-size-limit-of-a-post-request|What is the size limit of a post request?]]
* [[https://confluence.jaytaala.com/display/TKB/Securing+Apache+and+blocking+a+list+of+ip+addresses|Securing Apache and blocking a list of ip addresses]]
* [[https://support.plesk.com/hc/en-us/articles/214529205--Apache-keeps-going-down-on-a-Plesk-server-server-reached-MaxRequestWorkers-setting|Apache keeps going down on a Plesk server: server reached MaxRequestWorkers setting]]
===== PHP Installation =====
- Install packages$ sudo apt update
$ sudo apt install -y curl wget gnupg2 ca-certificates lsb-release apt-transport-https software-properties-common
- Add the SURY repository to your system$ echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/sury-php.list
- Import the repository key$ wget -qO- https://packages.sury.org/php/apt.gpg | sudo tee /etc/apt/trusted.gpg.d/sury.gpg
- Install the desired PHP version, where V is the major and v is the minor version number, for example 5.6 or 7.4$ sudo apt update
$ sudo apt install phpV.v
- Enable modules:$ sudo a2enmod ssl
$ sudo a2enmod proxy
$ sudo a2enmod proxy_http
$ sudo a2enmod rewrite
==== Settings ====
* ''php.ini'' for production:max_execution_time = 120
max_input_vars = 2000
memory_limit = 512M
post_max_size = 32M
sys_temp_dir = "/tmp"
upload_tmp_dir = "/tmp"
upload_max_filesize = 16M
date.timezone = Asia/Bangkok
* ''php.ini'' for development:output_buffering=off
short_open_tag = On
max_execution_time=120
max_input_time=150
max_input_vars = 2000
memory_limit = 512M
error_reporting=E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors=On
post_max_size = 32M
sys_temp_dir = "/tmp"
upload_tmp_dir = "/tmp"
upload_max_filesize=128M
date.timezone=Asia/Bangkok
* Check ini files
* apache2: load a php file with the following content
* cli:php --ini
==== Links ====
* [[https://deb.sury.org/|DEB.SURY.ORG]]
* [[https://www.php.net/manual/en/configuration.file.php|php.net - The configuration file]]
* [[https://opensource.com/article/22/9/deprecated-linux-apt-key|Fix the apt-key deprecation error in Linux]]
* [[https://www.howtoforge.com/how-to-specify-a-custom-php.ini-for-a-website-apache2-with-mod_php|How To Specify A Custom php.ini For A Web Site]]
===== PHP Extensions =====
* PHP extensions for Joomla:$ sudo apt install phpV.v-{bz2 curl gd mbstring mysql xml zip bcmath} phpV.v-{json}
* PHP extensions for Wiki:$ sudo apt install phpV.v-{bz2 curl gd mbstring mysql xml zip sqlite3} phpV.v-{json}
* Restart the service with one of the 2 commands below:$ sudo service apache2 restart
===== Set or change PHP version =====
- Set the desired PHP version for Apache2 and restart the service with one of the 2 commands below:sudo a2dismod phpV.v
sudo a2enmod phpV.v
sudo systemctl restart apache2
sudo service apache2 restart
- Set the desired PHP version for CLI:sudo update-alternatives --set php /usr/bin/phpV.v
sudo update-alternatives --set phar /usr/bin/pharV.v
sudo update-alternatives --set phar.phar /usr/bin/phar.pharV.v
- Check PHP cli Versionphp -v
- Check PHP apache2 Version: call phpinfo(); in a script
- Once you have installed a required extension, use the below command to verify itphp -m | grep -i mysql
==== Links ====
* [[https://tecadmin.net/switch-between-multiple-php-version-on-debian/|How to Switch between Multiple PHP Version on Debian 12/11/10]]
* [[https://tecadmin.net/install-multiple-php-version-with-apache-on-debian/|How to Install Multiple PHP Version with Apache on Debian 11/10]]
===== Xdebug =====
- Open terminal and write following command:php -i > /var/www/html/php_info.txt
- Copy the output from /var/www/html/php_info.txt
- Go to the [[https://xdebug.org/wizard|Xdebug: Installation Wizard]], and paste the output inside the text box on the page. It will analyze the output and will recommend the most suited package of Xdebug.
- Download that package from the output before by clicking on it's name, for example xdebug-3.3.2.tgz
- Install the pre-requisites for compiling PHP extensionssudo apt install phpV.v-dev autoconf automake
- Unpack the downloaded file with ''tar -xvzf xdebug-3.3.2.tgz'' within a temp folder, then change to that folder, run ''phpize'' and check it's output:cd xdebug-3.3.2
phpize
Configuring for:
PHP Api Version: 20230831 (8.3)
Zend Module Api No: 20230831
Zend Extension Api No: 420230831
- If it does not, you are using the wrong phpize. Please follow [[https://xdebug.org/docs/faq#custom-phpize|this FAQ entry]] and skip the next step.
- Run:./configure
make
- Copy the module to:sudo cp modules/xdebug.so /usr/lib/php/20230831
- Add the configuration in a new file to ''/etc/php//[apache2|cli]/conf.d/80-xdebug.ini'' (V.v is the php version, e.g. ''8.3''):
* **Xdebug 2 config**zend_extension = /usr/lib/php/20230831/xdebug.so
xdebug.remote_enable=1
xdebug.profiler_enable=0
xdebug.profiler_enable_trigger=1
xdebug.trace_output_dir=PATH_TO_OUTPUT
xdebug.profiler_output_dir=PATH_TO_OUTPUT
xdebug.gc_stats_output_dir=PATH_TO_OUTPUT
xdebug.remote_log=PATH_TO_LOG/xdebug.log
xdebug.remote_port=9000
xdebug.remote_host=127.0.0.1
* **Xdebug 3 config**zend_extension = /usr/lib/php/20230831/xdebug.so
xdebug.mode=debug,develop
xdebug.start_with_request=trigger
xdebug.start_upon_error=no
xdebug.output_dir=PATH_TO_OUTPUT
xdebug.log=/PATH/TO/LOG/xdebug.log
xdebug.log_level=10
xdebug.var_display_max_children=-1
xdebug.var_display_max_data=-1
xdebug.var_display_max_depth=-1
xdebug.client_port=9003
xdebug.client_host=127.0.0.1
- ''PATH_TO_OUTPUT'' and ''PATH_TO_LOG'' must be writable for the php process (apache or cli)
- Make sure the xdebug configuration is loaded last (e.g., ''zend_extension'' directive must be below the line for OPcache)
- Also update php.ini files in adjacent directories (//apache2// and //cli//), as your system might be configured with a separate php.ini file for the web server and command line.
- Read [[#wsl_windows_subsystem_for_linux|WSL (Windows Subsystem for Linux)]] if you are running your LAMP server inside WSL
- Read [[https://xdebug.org/docs/upgrade_guide|Upgrading from Xdebug 2 to 3]] if you are upgrading
- Restart your webserver after configuration changes
- Create a PHP page with ''''. Load it in a browser and look for the info on the Xdebug module. If you see it next to the Zend logo, you have been successful!
- Create a PHP page with ''''. Load it in a browser to verify the Xdebug configuration
- On the command line, you can also ''php -m''. This lists all loaded modules. Xdebug should appear twice there (once under 'PHP Modules' and once under 'Zend Modules')
==== Links ====
* [[https://xdebug.org/docs/install|Xdebug: Installation]]
* [[https://xdebug.org/docs/all_settings|Xdebug: all settings]]
* [[https://xdebug.org/docs/upgrade_guide|Upgrading from Xdebug 2 to 3]]
===== MariaDB 10.11.6 Installation =====
- Install$ sudo apt install mariadb-server
- Start MariaDB$ sudo service mariadb start
- Secure the installation following [[https://linuxgenie.net/how-to-install-mariadb-on-debian-12-bookworm-distribution/|How to Install MariaDB on Debian 12 Bookworm Distribution]]$ sudo mariadb-secure-installation
- Assign a password to root
- Dump all databases on the old server$ sudo mysqldump --all-databases > sql_file.sql
- Copy ''sql_file.sql'' to the new server and remove databases ''mysql'' and ''phpmyadmin'' from the dump file, then import with$ sudo mysql < sql_file.sql
===== phpMyAdmin =====
* [[deb11:phpmyadmin|phpMyAdmin]]
===== WSL (Windows Subsystem for Linux) =====
* For Windows Subsystem for Linux, create a **Virtual Host** file with document root in ///mnt//htdocs// or similar, if you need to access it through the Windows file system.
* You should set the apache user to the one who owns the files in the document root, which helps avoiding problems with permissions on the Windows NTFS file system:export APACHE_RUN_USER=
export APACHE_RUN_GROUP=
* Restart apache and remove session variables if any:/etc/init.d/apache2 restart
rm /var/lib/php/sessions/*
* You can check the current apache user with:ps -ef | egrep '(httpd|apache2|apache)' | grep -v `whoami` | grep -v root | head -n1 | awk '{print $1}'
* Replace the apache default user and group permissions of //www-data// with the one of . run:sudo chown root: /var/lib/phpmyadmin/blowfish_secret.inc.php
sudo chown -R : /var/lib/tmp
sudo chown root: /etc/phpmyadmin/config-db.php
* Check permissions of the folder containing the http files according to [[https://thegeekpage.com/solved-failed-to-enumerate-objects-in-the-container-windows-10-error/|“Failed to Enumerate Objects in the Container” Windows 10 Error]]. Most importantly, make sure all files are owned by the same user. Run a (windows) command shell on the windows path of that folder as administrator and run:takeown /F X:\FULL_PATH_TO_FOLDER
takeown /F X:\FULL_PATH_TO_FOLDER /r /d y
icacls X:\FULL_PATH_TO_FOLDER /grant Administrators:F
icacls X:\FULL_PATH_TO_FOLDER /grant Administrators:F /t
==== WSL1 with Xdebug ====
* WSL1 runs networking in ''bridged'' mode
* You do not need to set ''xdebug.client_host'' (Xdebug2: ''xdebug.remote_host'')
* Will work with default configuration settings
==== WSL2 (NAT) ====
* WSL2 set to ''NAT'' networking mode (default)
* Your Linux box runs within a Hyper-V Virtual Machine
* You can access the Windows host through the IP address stored in ''/etc/resolv.conf''
* ''xdebug.client''_host must be configured to use this IP address. Separate the directive from the xdebug settings by copying it into a separate file to be loaded after the xdebug settings, then run a script to update this IP address before starting or restarting the LAMP server:#!/bin/bash
IP=$(ip route show | grep -i default | awk '{ print $3}')
INI="/home/bco/conf/xdebug.host.ini"
echo -e "[Xdebug]" > $INI
echo -e "xdebug.client_host=$IP" >> $INI
* Check the xdebug logfile with ''tail -f /path/to/log/xdebug.log'' until this is working properly
=== Windows host IP address ===
* Alternatively you could use the Windows host IP address (feasible if it remains the same through re-boots) in which case you need to add a firewall rule to allow access through the xdebug port. Command to run in an elevated PowerShell:New-NetFirewallRule -DisplayName "xdebug" -InterfaceAlias "vEthernet (WSL (Hyper-V firewall))" -Direction Inbound -Protocol TCP -LocalPort 9003 -Action Allow
* Commands to check or remove the firewall rule:Get-NetFirewallRule -DisplayName "xdebug"
Remove-NetFirewallRule -DisplayName "xdebug"
==== WSL2 (mirrored) ====
* WSL2 set to ''mirrored'' networking mode
* This networking mode is available for Windows 11 23H2 and later
* To enabled ''mirrored'' mode, save the following content as file ''.wslconfig'' into folder ''C:\Users\'' on your Windows host[wsl2]
networkingMode=mirrored
* Your Linux box runs within a Hyper-V Virtual Machine
* You can access the Windows host through the IP address ''127.0.0.1'', no firewall rule is necessary
* ''xdebug.client''_host must be configured to use this IP address
* Check the xdebug logfile with ''tail -f /path/to/log/xdebug.log'' until this is working properly
* Note that WSL in ''mirrored'' mode is less secure and can be directly accessed from your LAN
==== Links ====
* [[https://gist.github.com/SomajitDey/68e8cd639e3bf592bded035630cf86ec|How to forward WSL2 port to Windows port and vice versa]]
===== SSL for localhost =====
==== Ignore invalid certificates ====
* You can just use the default ssl conf file in /etc/apache2/sites-available which makes use of the snakeoil certificate. Modify DocumentRoot and add Directory permissions.
* Paste this in chrome, enable, and chrome will ignore invalid certificates for localhost:chrome://flags/#allow-insecure-localhost
==== Create certificate for localhost ====
- Make a folder to keep your certificate files and change to that folder, for example ~/certs/ssl.
- Generate RootCA.pem, RootCA.key & RootCA.crt:openssl req -x509 -nodes -new -sha256 -days 1024 -newkey rsa:2048 -keyout RootCA.key -out RootCA.pem -subj "/C=US/CN=Example-Root-CA"
openssl x509 -outform pem -in RootCA.pem -out RootCA.crt
- Create a file domains.ext that lists all your local domains:authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
DNS.2 = localhost.yourdomain.tld
DNS.3 = machine1.yourdomain.tld
DNS.4 = machine2.yourdomain.tld
- Generate localhost.key, localhost.csr, and localhost.crt:openssl req -new -nodes -newkey rsa:2048 -keyout localhost.key -out localhost.csr -subj "/C=US/ST=YourState/L=YourCity/O=Example-Certificates/CN=localhost.local"
openssl x509 -req -sha256 -days 1024 -in localhost.csr -CA RootCA.pem -CAkey RootCA.key -CAcreateserial -extfile domains.ext -out localhost.crt
- Configure Apache:SSLEngine on
SSLCertificateFile "/home/user/certs/ssl/localhost.crt"
SSLCertificateKeyFile "/home/user/certs/ssl/localhost.key"
- Restart Apache
- At this point, the site would load with a warning about self-signed certificates. In order to get a green lock, your new local CA has to be added to the trusted Root Certificate Authorities in your OS or browser.
* For Windows 10 Chrome & Edge: Windows 10 recognizes .crt files, so you can right-click and open //RootCA.crt//.
* Select //Install Certificate...//, select //Local Machine//, then select //Trusted Root Certification Authorities// and confirm.
* You might need to clear cookies and cache for the browser to pick up the certificate from the server
- If you want to utilitze the certificate for an Endian Firewall, do the following:
* Rename the files //server.crt//, //server.csr//, and //server.key// in folder /etc/httpd and etc/httpd/cert
* Copy the newly generate certificate files //localhost.crt//, //localhost.csr//, and //localhost.key// to //server.crt//, //server.csr//, and //server.key// in folder /etc/httpd
* Copy the newly generate certificate file //localhost.crt// to //server.crt// in folder /etc/httpd/certs and append the parameters from the renamed original //server.crt// file
* Restart httpd
* You can check the domain names included in the original certificate:openssl x509 -text < $CERT_FILE
==== Links ====
* [[https://www.sslshopper.com/ssl-checker.html|SSL Checker]]
* [[https://community.letsencrypt.org/t/correct-steps-to-add-another-domain-to-existing-certificate/64654/2|Correct steps to add another domain to existing certificate]]
* [[https://websiteforstudents.com/revoking-lets-encrypt-certificates-on-ubuntu-18-04-16-04/|Revoking Let’s Encrypt Certificates]]
* [[https://medium.com/@mhagemann/correct-way-to-delete-a-certbot-ssl-certificate-e8ee123e6e01|Correct Way to Delete a Certbot SSL Certificate]]
* [[https://www.jesusamieiro.com/remove-revoke-a-domain-in-lets-encrypt/|Remove a domain in Let’s Encrypt]]
* [[https://linuxgenie.net/how-to-install-mariadb-on-debian-12-bookworm-distribution/|How to Install MariaDB on Debian 12 Bookworm Distribution]]
* [[https://gist.github.com/cecilemuller/9492b848eb8fe46d462abeb26656c4f8|How to create an HTTPS certificate for localhost domains]] (reference)
* [[https://letsencrypt.org/docs/certificates-for-localhost/|Let's Encrypt: Certificates for localhost]]
* [[https://www.section.io/engineering-education/how-to-get-ssl-https-for-localhost/|How to Get SSL HTTPS for localhost]]
* [[https://www.digicert.com/kb/ssl-support/apache-fix-common-ssl-errors.htm|Troubleshooting Apache SSL Certificate Errors]]
* [[https://medium.com/@mhagemann/correct-way-to-delete-a-certbot-ssl-certificate-e8ee123e6e01|Correct Way to Delete a Certbot SSL Certificate]]
* [[https://certbot.eff.org/docs/install.html#certbot-auto|Remove certbot-auto]]
* [[https://stackoverflow.com/questions/7580508/getting-chrome-to-accept-self-signed-localhost-certificate|Getting Chrome to accept self-signed localhost certificate]]
* [[https://stackoverflow.com/questions/10175812/how-to-create-a-self-signed-certificate-with-openssl|How to create a self-signed certificate with OpenSSL]]
* [[https://www.ssls.com/knowledgebase/how-to-install-an-ssl-certificate-on-apache/|How to install an SSL Certificate on Apache]]
===== Proxy =====
* Setup a VirtualHost on your main apache server, which for this example is now called "proxy".
* There needs to be another (regular) VirtualHost file on the backuppc server, which for this example is now called "host".
* The SSL certificates are served from the "proxy" through access to https://sub.domain.tld
* The "host" serves an unencrypted site through port 80. This assumes your local network is secure.
==== VirtualHost on the "proxy" server ====
* sub.domain.tld: external domain name with which you access the "host" behind the "proxy"
* host.yourdomain.tld: internal domain name of your "host". You may also choose to have both names the same.
ServerName sub.domain.tld
Redirect 301 / https://sub.domain.tld
ServerName sub.domain.tld
ServerAdmin you@domain.tld
DocumentRoot /var/www/html/yoursite
SSLEngine on
RedirectMatch ^/$ /yourapp/ # use this if backuppc is not the default app, or if you need to access another app on the same server
ProxyPass "http://host.yourdomain.tld/yourapp/"
ProxyPassReverse "http://host.yourdomain.tld/yourapp/"
Require all granted
# add other options such as Files and Directory permissions
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/sub.domain.tld/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/sub.domain.tld/privkey.pem
==== Links ====
* [[https://serverfault.com/questions/486042/use-apache-as-a-https-to-http-proxy|Use apache as a HTTPS to HTTP Proxy]]
* [[https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html|Reverse Proxy Guide]]
* [[https://www.jamescoyle.net/how-to/116-simple-apache-reverse-proxy-example|Simple Apache reverse proxy example]]