Cheat Sheet: Deploy Laravel to AWS Ligthsail

I often have to quickly set up an AWS Lightsail instance and deploy a Laravel project to it. The process is pretty straightforward, but still, I usually forget where to find some files or which commands exactly to execute.

Here is a complete cheat sheet for setting up an AWS Lightsail Instance, deploying Laravel to it, and setting up the domain and SSL certificate.

I will assume that you have already created an Instance using LAMP as an image, created a public IP address, and attached it.

1. Update the instance

> sudo apt-get update

2. Install NPM

In case NPM is not installed yet:

> sudo apt-get install npm

3. Prepare the folder for your Laravel project:

> sudo mkdir /opt/bitnami/projects
> sudo chown $USER /opt/bitnami/projects

4. Get the files of your laravel project.

In this example, I am using Git.

> git clone <URL-TO-YOUR-REPOSITORY>
> sudo chown $USER /opt/bitnami/projects/<YOUR-APP-FOLDER-NAME>

5. Install Composer and NPM dependencies

> cd /opt/bitnami/projects/<YOUR-APP-FOLDER-NAME>
> composer install
> npm install

6. Set up proper files permissions

> sudo chown daemon:daemon /opt/bitnami/projects/<YOUR-APP-FOLDER-NAME>/storage

7. Get your application password

> cat ~/bitnami_application_password

8. Create a MySQL Database and user

I will assume you are using MySQL 8, as shipped with the default LAMP image.

> mysql -u root -p // Using the application password of step 7
mysql> create database DATABASE_NAME;
mysql> create user 'USER_NAME'@'%' identified by 'PASSWORD';
mysql> grant all privileges on DATABASE_NAME.* TO 'USER_NAME'@'%';
mysql> flush privileges;

In case you want to be able to connect to MySQL from outside your Lightsail instance, you need to do the following steps:

  1. Open the port 3306 on the Lightsail Firewall
  2. In the file /opt/bitnami/mysql/my.cnf, comment out the line that starts with “bind-address”
  3. Restart MySQL with sudo /opt/bitnami/ctlscript.sh restart mysql

9. Set up your .env

Go back to your project folder

> mv .env.example .env

Copy the user and password, making sure you use ‘localhost” on DB_HOST:

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=<YOUR-DB-NAME>
DB_USERNAME=<YOUR-USER-NAME>
DB_PASSWORD=<PASSWORD>

Generate the key:

> php artisan key:generate 

And finally, run the migration:

> php artisan migrate 

10. Set up the Virtual Host

Create the /opt/bitnami/apache2/conf/vhosts/<YOUR-APP-FOLDER-NAME>-vhost.conf and put this onto it:

<VirtualHost 127.0.0.1:80 _default_:80>
  ServerAlias *
  DocumentRoot /opt/bitnami/projects/<YOUR-APP-FOLDER-NAME>/public
  <Directory "/opt/bitnami/projects/<YOUR-APP-FOLDER-NAME>/public">
    Options -Indexes +FollowSymLinks -MultiViews
    AllowOverride All
    Require all granted
  </Directory>
</VirtualHost>

Do the same now with /opt/bitnami/apache2/conf/vhosts/<YOUR-APP-FOLDER-NAME>-https-vhost.conf:

<VirtualHost 127.0.0.1:443 _default_:443>
  ServerAlias *
  DocumentRoot /opt/bitnami/projects/<YOUR-APP-FOLDER-NAME>/public
  SSLEngine on
  SSLCertificateFile "/opt/bitnami/apache2/conf/bitnami/certs/server.crt"
  SSLCertificateKeyFile "/opt/bitnami/apache2/conf/bitnami/certs/server.key"
  <Directory "/opt/bitnami/projects/<YOUR-APP-FOLDER-NAME>/public">
    Options -Indexes +FollowSymLinks -MultiViews
    AllowOverride All
    Require all granted
  </Directory>
</VirtualHost>

And restart Apache

> sudo /opt/bitnami/ctlscript.sh restart apache

By now, your Laravel project should be working if you browse to the public IP address of your instance.

11. Use a domain

Point the domain or subdomain you want to use to your instance’s public IP and change the APP_URL of the Laravel’s .env file.

By now, your Laravel project should be working if you browse to the domain you chose but without SSL certificate.

12. Generate an SSL certificate.

I will just copy here the needed commands based on this article: Tutorial: Using Let’s Encrypt SSL certificates with your LAMP instance in Amazon Lightsail

> sudo apt-get install software-properties-common
> sudo apt-add-repository ppa:certbot/certbot -y
> sudo apt-get update -y
> sudo apt-get install certbot -y
> DOMAIN=<YOUR-DOMAIN>
> WILDCARD=*.$DOMAIN
> sudo certbot -d $DOMAIN -d $WILDCARD --manual --preferred-challenges dns certonly

Now you will have to add one or two TXT entries to your domain. Make sure each TXT entries are already visible before continuing by using this tool: https://mxtoolbox.com/TXTLookup.aspx.

> sudo /opt/bitnami/ctlscript.sh stop
> sudo mv /opt/bitnami/apache/conf/bitnami/certs/server.crt /opt/bitnami/apache/conf/bitnami/certs/server.crt.old
> sudo mv /opt/bitnami/apache/conf/bitnami/certs/server.key /opt/bitnami/apache/conf/bitnami/certs/server.key.old
> sudo ln -s /etc/letsencrypt/live/$DOMAIN/privkey.pem /opt/bitnami/apache/conf/bitnami/certs/server.key
> sudo ln -s /etc/letsencrypt/live/$DOMAIN/fullchain.pem /opt/bitnami/apache/conf/bitnami/certs/server.crt

If you are not using CloudFront to configure the redirection from HTTP to HTTPS as I usually do, read the section about configuring this redirection on the article I linked before.

Restart Apache, and you should be ready to go.

> sudo /opt/bitnami/ctlscript.sh restart

Finally, do not forget to harden your server if you will use it on production!

Updated: 22.10.2020

– Sources: