Deploying Your Portfolio On an AWS Lightsail Server

Patrick Marschlowitz
8 min readNov 4, 2020

Introduction

If you’re like me then you’ve been asking yourself this question for awhile, “Where do I host my online developer portfolio?”. There are a lot of options and even more opinions floating around the web on this exact question, but I want to add another option that I rarely see anyone discussing, deploying on an AWS Lightsail server. Lightsail servers are fast, fully customizable, and best of all cheap (I pay ~3.50 a month). The biggest downside to going this route is the lack of simple implementation, I know from experience that this is not an easy route to take, as it requires a lot of research and time.

Hosting your portfolio on a self administrated and configured cloud server may sound like a daunting task for any new developer, so I decided to write this article to bridge that gap and help others along the same path I went. This is by no means the easiest route, but for the extra effort you will put in you get a lower price, the speed of AWS, and the knowledge gained along the way. This option is definitely not for everyone, and this is by all means not a fully encompassing guide, this is just the gist of setting it up, and the way to overcome the hurdles I faced along along the way.

Generating a Lightsail Instance

Most of the steps to actually spinning up a new Lightsail instance are cut and dry. You can follow along with AWS’ own guide to setting it up here.
Please note The only thing you should do different than the guide suggests is when asked to pick an instance image, pick Node.js this just preinstalls Node.js. You could also go with the MEAN stack, as it comes with extra things you may want on your server, but you can always add those later through Node.js. You can go a different route here and always install any of these things at a later time though.

Setting Up a Spending Budget

So we want to make sure that if our server is breached that the attacker cant rack up an enormous bill on our server having it work endlessly. To do this, we need to go to our Lightsail page, and at the top right of the screen is a button for billing. From billing go to budgets, and create a budget. This will insure that if you exceed this spending limit, the server instance is stopped, instead of continuing to rack up a bill.

SSH Into Your Lightsail Instance

So you’re server is now live, but you need a way to access your Lightsail server. You can go the manual route and use the terminal replacing the * and the contents inside of them with your information.

ssh -i *location of your SSH key* bitnami@*your lightsail public IP*

However this is a big pain when you are moving many files back and forth from your computer to the server and editing existing files, as every single command requires the path on the server to copy to, and the path on your computer to copy from.

scp -i *ssh key location* -r *local path to copy from* bitnami@*lightsail public IP*:*server path to copy to*

We can do better than this. With an SCP client we can access our server with our SSH key and drag and drop files between our computer and our server. AWS provides a guide on how to setup an SCP client and generate an SSH key here. I used WinSCP for this, however the guide uses PuTTY. The method of configuring either of them are very similar and I have no opinion on which you use.

Setting Up Our Domain and DNS

I wont be going in depth on how to setup a domain name or DNS server but I will give you the gist of it along with some minor points that need to be made for our Lightsail to be able to serve multiple websites.

For your domain name you will most likely want to go with whoever has the cheapest offer for the name you want, I ended up with NameCheap, but if it was cheaper elsewhere I would have gone there.

Please note NEVER let your payments go past due on a domain. I have heard horror stories of people paying a few bucks a month on their domain name, to being required to pay hundreds of dollars to get it back because the domain host jacked up the price after they defaulted on a payment.

For my DNS server I went with Cloudflare because I had friend who was helping me out with this portion of the project who had some experience with them before. DNS servers also have a nice benefit of caching our webpage, so most of the time a request for our webpage comes in, it gets served by the DNS server rather than our server, saving us money on our Lightsail server which bills on usage.

Heading to the DNS management page we want to add records to our website. Our Type A record is the thing that allows people to use our newly purchased domain name to reach our servers IP address. Our CNAME records are our subdomains, we generate 1 for www just to make sure anyone who adds it before our URL can reach the server, and we generate as many more as needed for all of our projects that we will add to our server.

Each one of these allows us unique routes for our projects. For instance if we have a project called breakout we would create a subdomain called breakout that would be reached at https://breakout.webdevpat.com This allows us to link to live versions of our projects in our portfolio projects section using the same server. This will be explained in depth in the next section.

Hosting Multiple Websites on Our Lightsail

Most of what we will be doing will take place at /opt/bitnami/apache2/htdocs on our server. In fact if you are itching to see something run on your server now, you can dump a website build folder into htdocs now and visit your URL in a web browser, since htdocs is the default directory our server uses for requests. Moving forward though we want our server to be able to host multiple websites, after all what good is a portfolio without projects?

Inside of htdocs we want to create a folder for each website we will host on our server. Each of these folders then will contain a build version of our sites inside of them. The problem is, none of our websites are visible through our URL’s. First we will need to configure our virtual host to understand which incoming URL requests go to which project folder.

If you navigate to opt/bitnami/apache2/conf/extra you will see a file named httpd-vhosts.conf before we do anything create a backup of this file by copying it and pasting it with a new name of httpd-vhosts.conf.bak FYI this is always a good practice when messing with any files that we may want to reset in the future. Opening the .conf file we will see it looks like this.


<VirtualHost *:80>
ServerAdmin webmaster@dummy-host.example.com
DocumentRoot “/opt/bitnami/apache2/docs/dummy-host.example.com”
ServerName dummy-host.example.com
ServerAlias www.dummy-host.example.com
ErrorLog “logs/dummy-host.example.com-error_log”
CustomLog “logs/dummy-host.example.com-access_log” common
</VirtualHost>
<VirtualHost *:80>
ServerAdmin webmaster@dummy-host2.example.com
DocumentRoot “/opt/bitnami/apache2/docs/dummy-host2.example.com”
ServerName dummy-host2.example.com
ErrorLog “logs/dummy-host2.example.com-error_log”
CustomLog “logs/dummy-host2.example.com-access_log” common
</VirtualHost>

All lines starting with # are comments for apache files. We want to get rid of both of these existing virtual host tags and replace them with the code block below. We need one of these tags for our root URL and one for every subdomain. I’ve added comments here to clarify what to fill into each of these spaces.

#The 80 is the port incoming requests come through, you can leave 80
<VirtualHost *:80>
#Place your email address here
ServerAdmin yourEmail@gmail.com
#This is the location of this specific project folder
DocumentRoot “/opt/bitnami/apache2/htdocs/portfolio”
#this is the url that is associated with the project folder
ServerName webdevpat.com
#This is the location of this specific project folder
<Directory /opt/bitnami/apache2/htdocs/portfolio>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
</Directory>
#Specifies where your error and log files go
ErrorLog “/opt/bitnami/apache2/htdocs/logs/portfolio-error_log”
CustomLog “/opt/bitnami/apache2/htdocs/logs/portfolio-access_log” common
</VirtualHost>

For each virtual host tag we add for our subdomain projects we need to add 3 extra lines inside of that virtual host tag. This lets our server know that we want different files served for different subdomains.

# This is the path from htdocs to your project folder
ServerPath “/breakout/”
RewriteEngine On
RewriteRule “^(/breakout/.*)” “/opt/bitnami/apache2/htdocs/breakout”

If all of this is saved you can now restart your Lightsail instance. Congratulations you are now running multiple projects on your own Lightsail server!

Preventing URL Not Found Error

So if you are running any single page web applications on your server you may have noticed an issue where if you press the back button on your browser you are met with a URL Not Found error. This happens because the URL in your browser window when trying to access a route in your project such as breakout.webdevpat.com\about\ does not match any of the files and folder inside of your server, since a single page web application only has its root project file, and all extra routes are handled by that project file (before the time of single page web apps all pages in a website would have their own individual file). Fortunately this is a simple fix!

For every single page web application that is hosted on the server, we need to add another file inside of that project folder named .htaccess Inside of this folder add the following. replacing index.html with whatever the root html document of your project is. Most likely it is index.html and nothing will be changed.

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ — [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>

This will make sure that no matter which path a user attempts to access in our single page web application, it always points to that individual file.

Adding a Server Snapshot

A server snapshot is essentially a backup of our server as it was when the snapshot was created. This is useful for ensuring that if anything goes sideways, we have a point to return to. Be aware this adds some very small extra fees to your monthly bill. To create a snapshot go to the page for your Lightsail instance, select Snapshots from the navigation ribbon, and select create snapshot.

Conclusion

Well that’s it for my article, I hope this helped you out along the way as many of these problems were very challenging and required a tremendous time investment to figure out. I would love to hear from you folks about your experience with this article. Was there anything I missed? Things that you wish were clarified farther? Extra problems you had to solve? Please let me know by contacting me at https://webdevpat.com/contact so I can update the article for anyone in the future using this. Happy Hacking!

--

--