Ubuntu LAMP setup for Laravel
Nav • May 15, 2020
ubuntuIf you need a local server for testing, or want to set up a production server, below are the step-by-step instructions on how to install a Ubuntu server. The focus will be on setting up a LAMP stack to host Laravel sites. We'll configure OpenSSH, Firewall, MySQL, PHP, and mount a network shared drive.
Install server
You have a few options for installing a local server. VMware Fusion or Workstation and Oracle VirtualBox are popular choices. On the cloud you have many choices such as Digital Ocean, AWS, Google to name a few.
If you choose to use the cloud, you don't need to install it manually, you can skip to the Login using SSH section.
If a local server is the way you're going, then download Ubuntu Server version from Ubuntu directly. ubuntu.com/download/server.
Do a fresh install. There's not much you need to worry about with the install. Most default settings will do.
If you're setting up a static IP, you may need help with configuring it. Use this link to calculate IP if required: subnet-calculator.com/cidr.php
Login using SSH
On a fresh install of Ubuntu server, you are able to login using SSH. So from your terminal type:
ssh username@serverip
Then enter the password you chose during installation.
Set root user password
By default, Ubuntu does not allow you to set a root password during install. I personally like to have access to the root user, so it's the first thing I change. Log into the server, and switch to root user.
sudo -i
Enter your password. Then to set the root password:
passwd
Network setup
If you need to make adjustments to your network settings, the file is located here:
sudo pico /etc/netplan/50-cloud-init.yaml
Below is a sample of what this file should look like. Credit
# This file is generated from information provided by
# the datasource. Changes to it will not persist across an instance.
# To disable cloud-init's network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
network:
ethernets:
enp0s3:
dhcp4: false
addresses: [192.168.1.202/24]
gateway4: 192.168.1.1
nameservers:
addresses: [8.8.8.8,8.8.4.4,192.168.1.1]
version: 2
I usually have multiple network cards, some for internal communication and some for external. Some are hardwired directly to equipment, so depending on your needs, it can get pretty complicated. If you're having any issues with setting up a static IP, there is a reference article here. Link
Server IP
If you need to verify the server IP, paste the command below.
curl http://icanhazip.com
Update server
Update the server to the latest patches. There's always a few security packages that should be added.
sudo apt update
sudo apt upgrade
SSH
Next, secure up SSH. We want to turn off authentication via password, and login through SSH keys.
On your mac, just open a new terminal window and run:
ssh-keygen
I usually keep defaults, and skip the passphrase. This will generate two files in your ~/.ssh
folder. id_rsa
and id_rsa.pub
. Copy the contents of id_rsa.pub
.
Now add the key to your Ubuntu server. Navigate to your home folder. Then type:
mkdir .ssh
cd .ssh
sudo pico authorized_keys
Then paste your key.
Depending on how you plan on logging in, either using your username (recommended) or root, you can paste the keys under the appropriate user folder.
If the above gives you any issues, there are a few other ways to get your key on to the server. Checkout Digital Ocean's docs.
Disable password authentication
By turning off the password authentication, you will only be able to login using the ssh keys. Personally, I setup all my servers with this method. Passwords are so insecure, and a pain to remember.
Edit the OpenSSH config file.
sudo pico /etc/ssh/sshd_config
Add the following to the bottom of the file. It's up to you if you want to allow root to login remotely. Some will say it's not a secure thing to do, and they are correct. So omit PermitRootLogin yes
if you dont want root login.
PasswordAuthentication no
PermitRootLogin yes
Restart ssh server.
sudo systemctl restart ssh
Firewall
Check the firewall status, it should show as disabled.
sudo ufw status
You can also list the applications available to add to your firewall rules.
sudo ufw app list
Add OpenSSH. There are two ways to do this, one you can allow the application privileges, and the second way is to open ports.
sudo ufw allow "OpenSSH"
sudo ufw enable
A few helpful tools
ifconfig
does not come pre-installed anymore. Alternatively, you can also use ip a
.
sudo apt install net-tools
Also, let's just make sure these are installed.
sudo apt install -y git curl wget zip unzip
Install Apache
sudo apt install apache2
Enable rewrite mod, and restart Apache
sudo a2enmod rewrite
sudo systemctl restart apache2
Update firewall to allow http & https communication.
sudo ufw allow in "Apache Full"
Installing MySQL
sudo apt install mysql-server
Let's secure up mysql.
sudo mysql_secure_installation
### VALIDATE PASSWORD COMPONENT - N
### Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
### Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
### Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
### Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
In case you need it, the config file is located at:
/etc/mysql/mysql.conf.d/mysqld.cnf
Give root user access to login remotely, at least to tunnel login. Most SQL clients will allow you to tunnel in via SSH and login to your MySQL. It's much better this way as you don't need to open firewall ports, etc.
sudo mysql
Create a root user access. This is optional. I prefer to tunnel in and have access to all the databases on the server.
CREATE USER 'root'@'%' IDENTIFIED BY 'someawesomesecurepassword';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';
exit
To give an application or developer access to a specific database, I prefer this method. If I know multiple people are working on one server it's best to keep access separated.
CREATE DATABASE client_database;
CREATE USER 'dev_username'@'%' IDENTIFIED WITH mysql_native_password BY 'SuperSecurePassword!';
GRANT alter,create,delete,drop,index,insert,select,update,trigger,alter routine,create routine, execute, create temporary tables on client_database.* to 'dev_username';
FLUSH PRIVILEGES;
exit
If you ever need to update the user's password:
ALTER USER 'dev_username'@'%' IDENTIFIED BY 'NewSuperPa55!';
MySLQ remote login
Using a SQL client, to login remotely as root, there is one other setting that needs to be changed. We need to change the way the root user is authenticated.
sudo mysql -u root
USE mysql;
SELECT User, Host, plugin FROM mysql.user;
As you can see in the query, the root user is using the auth_socket plugin
You may get errors trying to login. The way to solve this is you can set the root user to use the mysql_native_password plugin.
sudo mysql -u root
USE mysql;
UPDATE user SET plugin='mysql_native_password' WHERE User='root';
FLUSH PRIVILEGES;
exit;
Restart mysql
sudo systemctl restart mysql
Just a note, by default, root @ localhost password is blank.
Install php 7.4
sudo apt install php7.4 libapache2-mod-php
Ensure php extensions are all installed. This is probably overkill, but remove the ones you don't need.
sudo apt install php7.4-mysql php7.4-common php7.4-bcmath openssl php7.4-json php7.4-mbstring php7.4-dom php7.4-zip php7.4-soap
Move index.php to the top of the list.
sudo pico /etc/apache2/mods-enabled/dir.conf
Test PHP installation.
sudo pico /var/www/html/info.php
Paste this in the file, and save.
<?php
phpinfo();
?>
Now visit the website to check your php installation.
http://your-ip/info.php
Install Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
Make Composer executable.
sudo chmod +x /usr/local/bin/composer
Do a version check.
composer --version
Optional - mount a network windows server hard drive
If you have a shared folder that you need to access from your Ubuntu machine, this should help. In my case, I usually need to mount an Indesign server output folder.
mkdir /mnt/idscc
sudo pico /etc/fstab
Add this line. This will give you full read/write access, as long as the account allows it.
Now this is not the most secure method of mounting the hard drive. You are entering passwords in plain text. There are better ways to do this if security is an issue.
//192.168.0.100/wwwroot /mnt/idscc cifs vers=1.0,username=Administrator,password=SomeSecurePassword!,file_mode=0777,dir_mode=0777,iocharset=utf8,sec=ntlm 0 0
Mount the drive.
mount -a
SSH key on your Ubuntu server
If you need to add the server's ssh key to a provider, another server, etc., run:
ssh-keygen
Clone your Laravel site, make the folder is writable.
chmod -R 777 storage
chmod -R 777 bootstrap
Apache site
Make a virtual host.
sudo pico /etc/apache2/sites-available/navcodes.dev.conf
Customize the code below and paste into the .conf file.
<VirtualHost *:80>
ServerName navcodes.dev:80
DocumentRoot "/var/www/navcodes/public"
<Directory "/var/www/navcodes/public">
AllowOverride all
LimitRequestBody 0
Options Indexes FollowSymLinks MultiViews
Order allow,deny
allow from all
Require all granted
</Directory>
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,NE,R=301]
RewriteCond %{SERVER_NAME} =navcodes.dev
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
Activate site.
sudo a2ensite navcodes.dev.conf
Restart Apache.
sudo systemctl restart apache2
Encrypt
Install certbot on server. Follow the instruction on certbot. https://certbot.eff.org.