Note: This setup is only for development on local machine, it is not ready for production! To set up a server with LEMP stack ready for production please inform yourself more about performances and security issues.
Prerequisites
You should already have installed Ubuntu 20.04 server or desktop.
Installing PHP
First we will install PHP and after that we will install all extensions that are required to run Laravel.
Note: We will install PHP version 8.1, which is latest version in time when this article is written. If you want to install some other version replace 'php8.1' with the version you want, e.g. php7.4
First we need to add package archive for PHP:
sudo add-apt-repository ppa:ondrej/phpAfter that install PHP with command:
sudo apt install php8.1If everything goes right you should now have PHP installed on your machine. To test it, run command to see current PHP version and you should see that it's version 8.1.
$ php -v
PHP 8.1.2 (cli) (built: Jan 24 2022 10:42:33) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.2, Copyright (c) Zend TechnologiesNext, we need to install PHP extensions required to run Laravel applications. At time this article is written latest Laravel version is 9 and PHP extensions required are:
- BCMath PHP Extension
- Ctype PHP Extension
- DOM PHP Extension
- Fileinfo PHP Extension
- JSON PHP Extension
- Mbstring PHP Extension
- OpenSSL PHP Extension
- PCRE PHP Extension
- PDO PHP Extension
- Tokenizer PHP Extension
- XML PHP Extension
Some of the extensions are already installed with PHP, but ones that aren't, we should install manually.
To see extensions installed run command:
php -mYou should get the list of all currently installed extensions.
In the next step we will install all PHP extensions that are missing:
sudo apt install php8.1-bcmath php8.1-dom php8.1-mbstring php8.1-xmlWe will also install a couple of PHP extensions that are not required for basic Laravel application, but you will probably need them for anything slightly more complicated.
sudo apt install php8.1-curl php8.1-sqlite3 php8.1-xdebug php8.1-redis php8.1-zipAt the end, we need to install extensions for Nginx and MySQL:
sudo apt install php8.1-fpm php8.1-mysqlNext, we should turn on option to display errors in php.ini configuration file. Open that file with Vim text editor and find "display_errors" and "display_startup_errors" and set their values to be "On":
sudo vim /etc/php/8.1/fpm/php.ini; /etc/php/8.1/fpm/php.ini
...
display_errors = On
display_startup_errors = OnAs last step for setting up PHP, you should restart PHP service:
sudo service php8.1-fpm restartInstalling Composer
To be able to use Laravel, you need to have a composer installed.
First, go to your home directory:
cd $homeWith the next couple of commands, you will download composer installer and install it on your machine.
curl -sS https://getcomposer.org/installer -o /tmp/composer-setup.php
HASH=`curl -sS https://composer.github.io/installer.sig`
php -r "if (hash_file('SHA384', '/tmp/composer-setup.php') === '$HASH') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
sudo php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composerRun command for composer version to check if the composer is successfully installed, you should get information about composer version that is installed on your machine:
$ composer --version
Composer version 2.1.14 2021-11-30 10:51:43Installing MySQL
As first step you should install MySQL server:
sudo apt install mysql-serverAfter MySQL server is successfully installed, you should start a server:
sudo service mysql startNext, you should configure some security rules. Run command for secure installation and follow given steps:
sudo mysql_secure_installationAfter that is finished, log in to MySQL server as root user:
sudo mysql -u rootIn the next step, we will create a new user and give him all privileges:
CREATE USER 'your_username'@'localhost' IDENTIFIED BY 'your_password';If you are getting error that password is not strong enough, and you are sure you want to use a weak password, run this command and after that try to create the user again:
SET GLOBAL validate_password.policy=LOW;Next, give all permissions to this user:
GRANT ALL PRIVILEGES ON *.* TO 'your_username'@'localhost' WITH GRANT OPTION;Log out from MySQL server with "exit" command:
exitThen log in again but this time with the user you just created:
sudo mysql -u your_username -pIt will ask you for a password, enter the password you choose for the user in previous steps.
When you logged in, create a new database:
create database laravel_app;MySQL server is now ready, and we created new database "laravel_app" that we can use for our Laravel application.
To use the database we just created your environment variables should be:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_app
DB_USERNAME=your_username
DB_PASSWORD=your_passwordInstalling Nginx
To install Nginx run command:
sudo apt install nginxThat's it, Nginx is installed.
Create Laravel Application
Now that we have successfully set up PHP, MySQL and Nginx we can create our Laravel application.
First, create directory at /var/www with the chosen name for application:
sudo mkdir /var/www/laravelapp.testAfter that change permissions for that directory to have read and write privileges:
sudo chmod -R ugo+rw /var/www/laravelapp.testGo to the directory of our application and create a new Laravel application using Composer:
cd /var/www/laravelapp.test
composer create-project laravel/laravel --prefer-dist .Next, create a configuration file for Nginx at /etc/nginx/sites-available/ with the same name as our project directory:
sudo vim /etc/nginx/sites-available/laravelapp.test# /etc/nginx/sites-available/laravelapp.test
server {
listen 80;
listen [::]:80;
server_name laravelapp.test www.laravelapp.test;
root /var/www/laravelapp.test/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
index index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME
$realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}Create a symbolic link of configuration file in /etc/nginx/sites-enabled/ directory:
sudo ln -s /etc/nginx/sites-available/laravelapp.test /etc/nginx/sites-enabledCheck if Nginx configuration is ok:
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successfulIf everything is ok, reload Nginx server:
sudo systemctl reload nginxAt the end, add app domain to hosts file:
sudo vim /etc/hosts# /etc/hosts
...
127.0.0.1 laravelapp.testThat's it, if everything is done correctly you should be able to access your Laravel application at http://laravelapp.test
Note: If you get some error with storage or bootstrap directory, just give read and write permissions to that directory
sudo chmod -R ugo+rw /var/www/laravelapp.test/storageInstalling Redis
It's not necessary, but I can highly recommend installing a Redis database also, especially if you plan to use some of the advanced features of Laravel framework, like Queues.
If you don't need or want to use Redis, just skip this section.
First, install Redis server:
sudo apt install redis-serverNext, in configuration file find "supervised" and set it to be "systemd":
sudo vim /etc/redis/redis.conf# redis.conf
...
supervised systemdRestart Redis service:
sudo systemctl restart redis-server.serviceCheck if status is "Active":
sudo systemctl status redis-server.serviceIf everything is alright, log in to the Redis server:
redis-cliTo test a server, enter "ping" and you should get "PONG" as response:
redis> ping
PONGTo test if Redis is working correctly, we will set the new variable and try to get it:
redis> set test_variable "This is test variable"redis> get test_variable
"This is test variable"Then test if Redis is able to persist data even after it's been stopped. Log out from Redis server, restart server, log in again and try to get test variable we just created.
redis> exitsudo systemctl restart redis-serverredis-cliredis> get test_variable
"This is test variable"Next, we should make some changes in configuration file:
sudo vim /etc/redis/redis.confTo make sure Redis is available only to our local machine find "bind" and set it to be "127.0.0.1 ::1". It should be like that by default, but if it's not change it.
# redis.conf
...
bind 127.0.0.1 ::1Set up a password for Redis database:
# redis.conf
...
requirepass your_passwordSave and close configuration file and restart Redis.
sudo systemctl restart redis-server.serviceTo check if a password is set up correctly log in to Redis database and try to set a new key. It should fail because authentication is required.
redis-cliredis> set new_key "Test new key"
NOAUTH Authentication required.Authenticate with the password we just set and try again, it should work now.
redis> auth your_password
OKredis> set new_key "Test new key"
OKredis> get new_key
"Test new key"That's it, Redis server is now installed and configured.
To use Redis database your environment variables should be:
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=your_password
REDIS_PORT=6379Installing MailHog
To test email sending from your application, you can use fake SMTP server like MailHog.
For this package to work, you should have installed "golang" programming language. To install it run command:
sudo apt-get -y install golang-goAfter that, get MailHog from official Github repository:
go get github.com/mailhog/MailHogThat's it, MailHog is installed on your machine. Every time you want to use MailHog just run command:
~/go/bin/MailHogAnd your SMTP server will be available at http://localhost:8025.
To use MailHog SMTP server to test email sending in your application use this environment variables:
MAIL_MAILER=smtp
MAIL_HOST=localhost
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=someaddress@example.com
MAIL_FROM_NAME="${APP_NAME}"Installing Minio
Minio is high performance object storage with API compatible with Amazon S3. It's great option if you want to test a file uploading with Amazon S3 disk.
Get Minio with command:
wget https://dl.min.io/server/minio/release/linux-amd64/minioChange permissions of the directory to have access permission:
chmod +x minioThat's it, Minio is ready. Every time you want to use it just run command:
sudo MINIO_ROOT_USER=your_username MINIO_ROOT_PASSWORD=your_password ~/minio server /mnt/data --console-address ":9001"After that you can use it at http://127.0.0.1:9000 with credentials you choose in previous step.
To use Minio in your application use this environment variables:
FILESYSTEM_DRIVER=s3
AWS_ACCESS_KEY_ID=your_username
AWS_SECRET_ACCESS_KEY=your_password
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=your_bucket
AWS_ENDPOINT=http://127.0.0.1:9000
AWS_USE_PATH_STYLE_ENDPOINT=trueInstalling Ngrok
If you want to share your application with someone, you can create a public URL with Ngrok.
First download and install Ngrok:
curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null && echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | sudo tee /etc/apt/sources.list.d/ngrok.list && sudo apt update && sudo apt install ngrokIn the next step you should go to https://ngrok.com/ and create account. With that account you should be able to get API key.
Authenticate Ngrok with API key you get for your account:
ngrok authtoken your_tokenThat's it, Ngrok is ready. To share your project, go to the project directory and run command:
ngrok http 80Or you can expose a project by domain name:
ngrok http -host-header=laravelapp.test 80Conclusion
You now have working local development server with installed PHP, MySQL, Nginx, MailHog, Minio and Ngrok.
For every new application you need to repeat steps described in Create Laravel Application section. Optionally, if you need to use MySQL database you need to create a new one as it is described in Installing MySQL section.
Enjoy!