How to deploy a Laravel App on an Azure Ubuntu server
Tags: laravel, devops, linux, webdev
Published: 2022-01-23 08:52:24

Okay so this post is not a tutorial in the full sense of it, rather than to show/demonstrate the steps I took to deploy my Laravel app on a dedicated Linux server on Azure. I've been deploying Laravel apps on shared hosting servers although you will agree with me that some shared hosting environments comes with its own problems of not having SSH access to run some artisan commands and having to manually upload changes via FTP, which is prone to errors. I wrote this as a personal reference but I hope someone finds this useful.

1. I created a free account on portal.azure.com which gives you free access to about $200 credit and avails you to a host of the various services available on Azure's cloud offerings. 

2. Create a resource, choose Ubuntu 20.04 virtual machine. Place it in your desired resource group. Choose the region desired and name the machine appropriately.
![Create Linux VM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rwtymgomztzocrcy073i.PNG)

3. Size: since this is a demo app, it is critical we go with the most minimal size as possible to save costs and also that will be sufficiently enough to accommodate our application size. In my case I went with the Standard b1s (1 virtual CPU and 1GB memory) that translates to 8 USD monthly. This is more than enough to run a development Laravel application. 

![Set VM Image size](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8x4dgjr3s0iebllz5f8d.PNG)

4.Move to the next step "Administrator account" for Authentication type, select password, set your username and password. Check HTTP and SSH in the inbound public rules. This ensures that our application is visible to the public and also means we can SSH to the server using the admin details created above. Once done let's create the virtual machine.

![Admin username/Password](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ypyeu1q63p7bvzco12ar.PNG)

5.Once you are done, click on Create and wait for Azure to provision the machine. We have created our machine, so how do we start uploading files? Click on "Go to resource" where you will see some vital information: 
![VM Info](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5f6nwy1c30mhag2c25vx.PNG)
"Public IP" is the IP assigned to the server. This is what you give people to access your website. It is also what you use to login to the server via SSH. You can choose a DNS like "example.azureapp.com" under the DNS name though like shown in the screenshot.

6.Open Putty on your Windows environment and enter the Public IP assigned to us in Step 5 above and choose port 22. This will open up a shell command to logon to Linux environment. When prompted, login with the Admin Username and password created in step 4. We are now in the Linux environment.

![SSH Access](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/60i4xwxkl0j71bvm32w3.PNG)

7.We want to install Apache, MySQL and PHP in turn on the server.
Let us update the package list to ensure we are installing the latest packages on the server:  ```php 
sudo apt-get update
```
**Install Apache**: ```php 
sudo apt-get install apache2
```
You can test the installation of the Apache by browsing to your site's public IP. A welcome page will be displayed.

**Install MySQL**: ```php
 sudo apt-get install mysql-server
```

Continue to configure the mysql server by continuing with the command ```php
sudo mysql_secure_installation
``` You will be prompted configure passsword for the root user. Once you are done you can test your installation by logging in ```php
sudo mysql -u root -p
```

**Install PHP**: ```php 
sudo apt-get install php libapache2-mod-php php-mysql php-curl php-gd php-json php-zip
```

Once done you need to restart the apache server: ```php
sudo service apache2 restart
```

**Install PHPMyadmin**: ```php
sudo apt-get install phpmyadmin
```
Follow the steps and confirm your installation by navigating to 
your_site_public_ip/phpmyadmin

8.We have installed the LAMP stack on our server. Now is the time to download our files to the server. We have two options: Git deployment and local FTP upload.

**Git**: on the SSH, navigate to the web directory of the linux server  (/var/www/html) by using the following: ```php
cd /var/www/html
``` This is the root directory for our website.

I assume by now you have pushed your latest laravel updates to a git repository. Type the command ```php
git clone your_repo_address.git
``` to download latest version of your app. Further updates can be gotten via ```php
git pull
```, like we normally do.
We now have our files in the environment and can start configuration. We will need to generate our application key and update composer information. But first we need to give our user access to some directories: 
```php 
sudo chown -R $USER:www-data storage
sudo chown -R $USER:www-data bootstrap/cache
```

Then we set our directory permission: 
```php 
sudo chmod -R 775 storage
sudo chmod -R 775 bootstrap/cache
```
 
Once this is done we can create our own env file by ```php
cp .env.example .env
``` Edit your env variables by following the command ```php
 sudo nano .env
``` and use CTRL+X to exit when done.

Then ```php
 artisan key:generate
```

**FTP**: Open up FileZilla, create a new site setting as shown below.. Host is the site's Public IP, enter your username and password, if everything is ok you will be logged in to the root directory. You can change that and navigate to /var/www/html.
Here is where you can upload your Laravel project on to the server.
![FTP setup](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6yuj4kgqp8jtg35ts4rq.PNG)

9.We have now deployed our app to the server. There is one more snag though. You may observe that while trying to navigate to the site you may be getting a 500 internal server error. This is because Laravel's root directory is not in the root /var/www/html like a regular PHP project but under the public folder.
We need to configure some Apache files to re-route our requests to the public folder: `php sudo nano /etc/apache2/sites-available/000-default.conf`. 
In the file you will see something like
 ```php 
VirtualHosts *80
```
 Immediately under this come down and type:

```php 
<Directory /var/www/{your-directory}>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    Require all granted
</Directory>
```

Modify the .htaccess file under public to reflect the following changes:

```php 
<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Send Requests To Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]


</IfModule>
  <IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteCond %{REQUEST_URI} !^public
    RewriteRule ^(.*)$ public/$1 [L]
    </IfModule>
```

Don't forget to activate the rewrite module of your Apache server as well:
```php 
sudo nano /etc/apache2/apache2.conf
```

```php 
<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
```

Finally we restart apache server using `sudo service apache2 restart` and we are able to view our Laravel application.