This is a Canonical Question about Securing a LAMP stack
What are the absolute guidelines for securing a LAMP server?
Server Fault is a question and answer site for system and network administrators. It only takes a minute to sign up.Sign up to join this community
David's answer is a good baseline of the general principles of server hardening. As David indicated, this is a huge question. The specific techniques you take could depend highly on your environment and how your server will be used. Warning, this can take a lot of work in a test environment to build out and get done right. Followed by a lot of work to integrate into your production environment, and more importantly, business process.
First, however, check to see if your organization has any hardening policies, as those might be the most directly relevant. If not, depending on your role, this might be a great time to build them out. I would also recommend tackling each component separately from the bottom up.
There are lots of good guides available to help you out. This list may or may not help you depending on your distribution.
Apache can be fun to secure. I find it easier to harden the OS and maintain usability than either Apache or PHP.
This runs headlong into the whole idea of Secure Programming Practices, which is an entire discipline of its own. SANS and OWASP have a ridiculous amount of information on the subject, so I won't try to replicate it here. I will focus on the runtime configuration and let your developers worry about the rest. Sometimes the 'P' in LAMP refers to Perl, but usually PHP. I am assuming the latter.
You've asked a question that is, quite frankly, worthy of a few books on the topic. But there are some general basic guidelines that work well:
Hope that helps you get started.
Here is a good checklist I like to start with.
Adding to what David suggests, the more modular your installation, by that I mean restricting access to certain users/groups created specifically for one task and limiting their scope, the more secure your LAMP stack: An example of this is to have an Apache user for Apache files/folders with permissions set accordingly and not in any groups that can access critical system files/folders. A user that can access the MySql tables that are associated with your websites that you are going to serve and only those tables. Additionally, you can restrict their access to give the minimum amount of access from a PHP call. Also, make sure that the MySQL username used/exposed through the PHP file is not the same username or password used for another user.
What this means: if either the apache user or the MySql user are compromised, they can't do any harm outside the scope of the folder(s) apache has access to (in the case of the apache user) and outside the table(s)/database(s) (in the case of the user for the MySQL database).
If somehow the MySQL user were to be compromised, they couldn't, for instance, access the database and drop all the databases from MySQL and ruin all your data. They MIGHT under some circumstances be able to drop tables or insert information in some tables in an isolated database, which is why it is important to only grant table access where it is absolutely necessary and only grant the permissions needed...if you don't need to have drop tables privileges or update privileges, then don't give them to that user.
Also, if for some reason your administrative account username and password are found out for MySQL, if you use a different username than any usernames on your system, they have to first break the security of your system before getting into your database to do damage. The same holds true about the apache user and access to files.
Example time! I'm going to give a system example to sort of simplify the idea.
say you have users on your system (root should be disabled for security through something like umod -l or passwd -l, etc.): john, barney, terence, and lisa.
you could create a user in MySQL with the name of bigbird (make sure you use a hashed password). Bigbird only has select privileges and update privileges, but not drop or create, and certainly not . Additionally, you create another administrative MySQL user with the name garfield for working on the MySQL database and you delete the root user from the MySQL database so that it can't be comprimised. garfield has been granted . privileges throughout MySQL (effectively, this is just renaming root).
now, you create either an apache group or a user and we'll call it apweb2. Appweb2 is not a member of other groups, and all files/folders for apache are stored in /home/apweb2/. Each virtual host would have its own subfolder and each of these hosts would have document root set to that subfolder. Symlinks would be disabled in order to not accidentally provide access to the rest of the system.
Also, you can restrict ssh access to certain users only (or certain groups, I like to put them in the ssh group, and make that the only thing able to use ssh).
Also, you can choose which users have sudo privileges to restrict things even further. Another step you can take it further is to make any ssh users not able to sudo, you could create special users that can use sudo that can't use ssh, so that once you ssh in, you have to log into another user to have access to sudo.
So, by modularizing each segment, if one is compromised, the whole stack won't be compromised and you can remedy the 1 problem instead of having to start all over again from scratch.
I found this document from SANS.org really helpful http://www.sans.org/score/checklists/linuxchecklist.pdf
At the present time, do not neglect container virtualization, namely Docker, systemd-nspawn and the mechanisms of container virtualization on which they are built (namespaces, cgroups). Using container virtualization allows you to isolate processes, for example, if one of the services is compromised, an attacker will not gain access to other services.
In the case of LAMP, it is possible to use, for example, four Docker containers with SSH-server, Apache, MySQL, PHP-FPM/Python/Perl/etc.