Simple Angular CI/CD pipeline with GitLab & AWS

In this tutorial, I will show you how to set up a simple CI/CD pipeline that compiles code on GitLab and then deploys to AWS EC2 via AWS CodeDeploy. This tutorial assumes:

  1. You have a working EC2 Ubuntu instance set up with a web server such as Nginx or Apache running and configured. 
  2. You have an existing code repository hosting an Angular project on GitLab.

Technologies Used: 

  • Angular 7
  • Gitlab CI/CD
  • AWS S3
  • AWS CodeDeploy
  • AWS EC2 Ubuntu 18.04 LTS

I’ve made a start project that I will be referencing throughout this project on Github will all the files you need already built in. Check it out here!

Step 1 – Create an S3 to AWS CodeDeploy Pipeline

I really don’t like dropping links in tutorials like this, however, for the sake of not re-writing Amazon’s documentation, I will have to tell you to follow all instructions in the tutorial in the link below. Only once you finished the tutorial will you be able to continue with the rest of this tutorial. Once you’re done with Amazon’s tutorial, you will have a CD pipeline ready to go waiting for GitLab to send the code.

https://docs.aws.amazon.com/codepipeline/latest/userguide/tutorials-simple-s3.html

If you have successfully completed the above tutorial, any changes pushed to your S3 bucket will be deployed immediately to your EC2 instance. Then steps below will show you how to upload your production bundle to S3 from Gitlab to complete the CI/CD pipeline.

Step 2 – Create an appspec.yml 

Welcome back! The first thing we’ll have to do is create an appspec.yml file in the src/ folder of our project. The appspec.yml will tell AWS CodeDeploy to deploy your code in a specific file directory on the server – in our case, it’s the /var/www/ directory. 

version: 0.0
os: linux
files:
  - source: ./
    destination: /var/www/

Then we have to tell angular to include this file as an asset so it stays preserved during the production build. To do this, we edit the assets block in our angular.json file to include "src/appspec.yml":

...
"tsConfig": "src/tsconfig.app.json",
            "assets": [
              "src/favicon.ico",
              "src/assets",
              "src/manifest.json",
              "src/appspec.yml"
            ],
            "styles": [
...

Step 3 – Create .gitlab-ci.yml

Gitlab offers a continuous integration service if you add a

.gitlab-ci.yml

file to the root directory fo your code repository. I’ve provided a sample .gitlab-ci.yml file as seen in example Github project. Please be sure to update the group name and repository name for your own project. If you copy this code please be sure to use your own repository name.

image: node:10

stages:
  - build
  - deploy

build:
  stage: 'build'
  script:
    - apt update
    - apt-get install -y nodejs
    - npm install -y npm@6.11.0
    - nodejs -v
    - npm -v
    - ls -la -F
    - npm ci
    - npx ng build --prod
  cache:
    paths:
      - node_modules/
  artifacts:
    when: on_success
    name: '$CI_JOB_NAME-$CI_COMMIT_REF_NAME'
    paths:
      - dist/angular-gitlab-ci-cd-example/
  only:
    - dev
    - master

deploy:
  stage: 'deploy'
  environment:
    name: production
  script:
    - apt update
    - apt install -y software-properties-common
    - apt install -y python-dev
    - apt install -y python-pip
    - pip install awscli
    - aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID
    - aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY
    - aws configure set region us-east-1
    - ls -la -F
    - mv dist/angular-gitlab-ci-cd-example/appspec.yml dist/
    - cd dist
    - ls -al -F
    - cd ..
    - aws deploy push --application-name angular-gitlab-ci-cd-example --s3-location $AWS_S3_LOCATION --ignore-hidden-files --source dist
  only:
    - master

If you commit to your master branch with this file in the root directory of your project, a CI pipeline will initiate with two steps outlined line-by-line below:

The Build Stage

1.Update the packages in the node:10 Docker container

- apt update

2. Install node & npm

- apt-get install -y nodejs
- npm install -y npm@6.11.0
- nodejs -v
- npm -v

3. Run npm install

- npm install

4. Build the production bundle of Angular using the local cli

- npx ng build --prod

6. Tell GitLab to cache your node_modules so that your project builds faster next time around

cache: 
    paths: 
      - node_modules/

7. This code block creates a build artifact that will be passed onto the next stage in the pipeline if all operations in the container run without error. In the case of Angular7, I’m passing the created dist/ directory to the next stage so that GitLab can send it to AWS to be deployed

  artifacts: 
    when: on_success    
    name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
    paths: 
      - dist/angular-gitlab-ci-cd-example/

8. This keyword tells GitLab only to run this stage when a commit is pushed to either the master and dev branches. You can customize any stage to run a specific set of branched or all branches if that’s what you need. 

  only:
    - dev
    - master

The Deploy Stage

1. Update the packages on the node:10 Docker image, install the python libraries needed for AWS CLI and then install the AWS CLI.

script: 
    - apt update
    - apt install -y software-properties-common
    - apt install -y python-dev  
    - apt install -y python-pip
    - pip install awscli

2. Navigate to your CI/CD settings in GitLab and add the following variables for your $AWS_ACCESS_KEY_ID and $AWS_SECRET_ACCESS_KEY from the CodeDeploy IAM User you created earlier from following the AWS tutorial in Step 1. You should also include the $AWS_S3_LOCATION as a CI/CD variable as well in the following format:

s3://your-bucket-name/your-bundle-name.zip

The <key> will be by the same name as the zip created from the build stage.

3. In this step, we are configuring the AWS CLI with the IAM Credentials of a user with the correct CodePipeline policies attached.

    - aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID
    - aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY
    - aws configure set region us-east-1

4. Remember from step 1 how we made sure the appspec.yml was preserved in the dist/ production bundle? Well, now we have to move it out it to the same directory level as the dist/ folder so that it sits on the same level as the dist/ folder. We have to do this to make the appspec.yml visible to AWS. If we do not do this, the AWS CLI will throw an error stating that it cannot find the appspec.yml file in the next step.

- mv dist/angular-gitlab-ci-cd-example/appspec.yml dist/
- cd dist
- cd .. 

5. Use the AWS CLI to deploy the dist/ bundle to AWS S3

 - aws deploy push --application-name angular-gitlab-ci-cd-example --s3-location $AWS_S3_LOCATION --ignore-hidden-files --source dist
only:
    - master

You’re Done!

Once you push your code to the master branch, navigate to the CI/CD pipeline and watch your code being built. Once GitLab is done building the production bundle, it will send it to AWS S3, which in turn will be deployed onto your live server moments later. I would love to hear your feedback on how I can improve this simple pipeline. 

4 Simple Things To Make Your Personal Website More Aesthetic

The purpose of this article is to highlight some small adjustments you can make to your personal site that will make a huge difference in usability and aesthetics. You don’t need to be an expert web designer or developer to make these changes. I’ve written this article after reviewing 100+ personal websites across the web which were custom built, WordPress, Square Space, etc. sites

1. Standardize your typography

Creating a standard typography for your site will make it easier for your users to recognize if the text on the page represents links/anchor tags, paragraph text, annotations, titles, and navigation links. Setting a standard typography means that the font and style used for paragraphs should be the same on every page of your application. (i.e. All paragraph text will be of font size 16px in Helvetica-Neue font. All text contained within buttons will be uppercase size 14px font.). That being said, all text with the same meaning or function should have the same font and text style.

Here is a simple typography generated via
Type Scale

type-scale

The folks over at Material Design also have a detailed typography scale you can use for reference.

2. Color scheme

For those who want to create a more aesthetically pleasing experience while users navigate your site, it may be worth spending a few minutes to create a matching color scheme for your website. I use often coolors.co to generate color schemes for my website builds.

Screenshot from coolors.co:

coolorsco

After picking a color scheme make sure you’re consistently making sure all your elements of the same function have the same styles. (i.e. All button on your page are green with white text which. Once your user sees this button once they will recognize all other green blobs with white on the page as buttons.)

3. Set max content width

All content on the page should be kept within a certain max with. When is last time you were on a web page on your desktop and your eyes had to move from the left side of the screen all the way to the right side of the screen to read a paragraph?

max-content

All content should be focused in one section so that it’s easier for a user to read.

4. Favicon

For those of you building a personal brand, I think having a favicon on your site will make you look that much more official and serious. Not having a favicon on your web page may make your personal site look incomplete and give the impression that it’s still under construction.

no-favicon

5 Atom packages that will speed up your workflow

The purpose of this article is to share 5 Atom packages that I use constantly that have sped up my workflow. Let’s start!

atom-beautify

atom-beautify on atom packages

With atom-beautify you never have to worry making sure your code is perfectly indented throughout the entire page. By hitting a designated set of hotkeys this package will take you unformatted code and indent it perfectly as if you spend the next 15 minutes indenting it yourself. The creators of this project made beautifiers for all types of code formats and languages such as JS, ESLint, Nginx, Vue, and many more.

autoclose-html

autoclose-html on atom packages
As you can probably infer from the name of the of the package, autoclose-html will automatically insert the closing HTML tag after you close the opening tag.

emmet

emmet on atom packages

emmet has had the largest impact on speeding up my web development workflow. Generating HTML code blocks has never been easier with the set of hotkey shortcuts this package comes pre-packaged with. For those who use a front-end framework like Bootstrap4 are familiar with writing the following code:

Screen Shot 2018-10-08 at 1.49.39 PM

For some of us, this code becomes muscle memory at some point. However, with emmet we can simply write the following:

div.row>div.col*3

and hit tab on the keyboard and generate the same code above.

emmet hotkey cheat sheet

minimap

minimap on atom packages

minimap generates a map of all the code in your open document/script file where you can quickly navigate to any point in your open source file no time at all. This is a huge step up from using a combination Ctrl + F and memory to jump between lines of code.

platformio-ide-terminal

platformio-ide-terminal on atom packages

This package allows you to open up multiple terminal instances in Atom in your current working directly. This is very convenient since you don’t have to open up another application to access the terminal.

Productivity as a DIY project

Guest Author: Mario Villacres

As I was wrapping up my time at Fullstack Academy, the future seemed bright. I had an in-demand skill set in my arsenal and after three months of drilling algorithms and learning best practices in web development, landing a position as a web developer was all but guaranteed.

And although my time in the classroom was done, I continued to get my money’s worth from Fullstack. I was assigned a career counselor who would continue to help me in my efforts to break into the world of tech, whether it be mock interviews or salary negotiation tips.

In order to make it easier for her to keep track of where I stood in the interview process with a given company, she had set up an account on Asana for me to record my progress. After trying Asana for a week, however, I was not a fan. This was not my first project management tool — I’ve used both Trello and Todoist extensively — and Asana felt cluttered by comparison.

I shared my gripes with my career counselor, she said I could simply keep her in the loop via Slack. Through this minor experience, however, I came to realize how much time I had been wasting switching between multiple services, which totally defeats the purpose of “productivity” apps.

Seeking a single source of productivity

Rather than have all my projects and tasks splintered across multiple services, I decided to consolidate all my projects onto a single platform. The only issue was which one to use.

Trello’s kanban boards were great for large-scale projects, but left much to be desired for one-off tasks (e.g. “Buy milk today”). On the other hand, Todoist’s single stream of tasks made it difficult to visualize workflow. I sought out other services that might have been a better compromise, but each service I sought out came with its own off-putting limitations (oftentimes it was the price tag).

Seeking a single source of productivity

It seems silly in retrospect. Here I was in search of a web app that would fulfill my particular needs, forgetting for a moment that I had just spent the past 3 months developing the skills I would need to build it myself! And so began my quest to build my perfect web app.

The building of Dharana

I chose the name Dharana both in reference to Asana (as both words refer to concepts from the Eight Limbs of Yoga) and as a way to describe what would be the experience of using my app — the word dharana in Sanskrit has several related meanings, including “a collection of the mind” and “uninterrupted focus.”

Tools Used

I was delighted to find out that Todoist was built with several of the same tools I had learned at Fullstack, and so I began building my app with a similar structure, adding my own twists along the way. Ultimately, Dharana’s tech stack was the following:

  • React on the front end, as each task and kanban list could easily be thought of as components
  • Redux in order to allow tasks to appear under various filtered/queried views (one of my favorite features of Todoist)
  • Node and Express on the back end for their flexibility
  • PostgreSQL as the database as the data easily lent itself to a relational structure

New faces, new influences

Anybody that has been job hunting within the past few years will tell you that it is simply not enough to get your resume circulated to the right people, your reputation also needs to make the rounds.

It’s for this reason that I began attending meetups almost daily since leaving Fullstack. One particular meetup group that I became fond of was the React NYC meetup. Every two weeks, they bring in some of the best professionals in the tech industry to give a presentation on how their companies go about using React in their online offerings. Each time I attend a React NYC event, I walk away learning something new and feeling like I’ve better refined my understanding of contemporary best practices on the front end.

Whenever I learned something that I felt would improve the experience of Dharana, I would spend the time to refactor the project; I usually ended up extremely satisfied by the results. Slowly, I began approaching my building of Dharana less as an end goal, and more as an open-ended exploration.

What’s next for Dharana?

While the current culture in tech dictates that developers must monetize everything under the sun, I’m in no rush to make Dharana into a full-blown business.

I have no doubt that Dharana could be a tool that several people might find useful in their daily lives, but for now, I’m very much content with Dharana being something that’s just for me.

Link to Mario’s Original Post on Medium

Stuck on 92% Chunk Optimization on Angular Production Builds?

The purpose of this article is to show you how I overcame an out-of-memory issue while building the production version of my Angular web application on my Ubuntu server by adding swap space.

Please keep in mind that building the Angular production bundle using another cloud providers resources (like building Angular on an AWS EC2) can get expensive fast. In light of that I figured out a way to automatically build and deploy Angular production builds essentially for free on GitLab.

The Problem

While Angular CLI was building the production build on the server, the machine returned a process out of memory error message. Here is what the stack trace looked like on the terminal:


FATAL ERROR: Committing semi space failed. 
Allocation failed - process out of memory 
1: node::Abort() [ng build --prod --aot]

At the time of writing this post this was my technology stack:

• Ubuntu 16.04.5 LTS (xenial)
• Node 8.12.0
• Angular CLI 6.1.3
• Angular 6.1.2

The Solution

After some doing some online research I found that a solution to this problem was to add additional swap space on my server. In this post, I will show you how I added swap space to my Ubuntu 16.04.5 LTS.

What is Swap Space?

Swap space is essentially emergency RAM that that sits on your hard drive and is utilized whenever you’re running your RAM close to max capacity. Sometimes large programs make the entire system need extra memory. Swap space can be a dedicated partition of your hard drive, a swap file, or a combination of both. The steps below will show you how to add more swap space to your machine.

Click here for the Official Ubuntu Swap Faq

Checking System Swap Information

First, we will check out our system to see if there are any existing swap configurations with the following:

$ sudo swapon --show

If the machine does not return an output then your system does not swap space available.

You can verify that there is no active swap using the free utility:

$ free -h

If you see a row of 0B‘s in the Swap row, no swap is active on the system.

Check Available Hard Drive Space

The most common way of allocating space for swap is to use a separate partition devoted to the task. However, altering the partitioning scheme is not always possible. We can just as easily create a swap file that resides on an existing partition.

Before we do this, we should check the current disk usage by typing:

$ df -h

The device under /dev in the output is our disk in this case.

For machines with less than 1 GB, it is highly recommended that the swap space should be at bare minimum equal to the amount of RAM. On top of that, it’s also recommended that swap space is at maximum, twice the amount of RAM depending on the currently available disk space. If need more swap space than twice your RAM then you should upgrade your server or add more RAM.

Create a Swap File

Let’s create a file of the swap size that we want to be called swapfile in our root directory.

My server had 512MB of RAM so for this example I will create a 1GB file with fallocate. Please adjust the file size to meet the needs of your own server.

More information on fallocate

$ sudo fallocate -l 1G /swapfile

Once the swap file is created we can verify that the correct amount of space was allocated with the following command:

$ ls -lh /swapfile

output:

$ -rw-r--r-- 1 root root 1.0G Oct 02 12:15 /swapfile

Enabling the Swap File

With the swap file available we need to tell the machine to leverage the extra space available in the swap file. First, we need to set the swap file permissions to 600 to prevent other users from being from being able to access or modify the file.

$ sudo chmod 600 /swapfile

Format the file as swap with mkswap:

$ sudo mkswap /swapfile

More information on mkswap

output:

Setting up swapspace version 1, size = 1024 MiB (1073737728 bytes)
no label, UUID=41e86209-3802-424b-9a9d-d7683142dab7

After marking the file as swap space, we can enable the swap file allowing our system to start utilizing it:

sudo swapon /swapfile

We can verify that the swap space is available by typing:

$ sudo swapon --show

The terminal should return an output like the following:


NAME      TYPE  SIZE USED PRIO
/swapfile file 1024M   0B   -1

Enable the Swap File Permanently

If we reboot our server at the current moment, the machine won’t keep any of the changes we’ve made to the hard drive partition. To make the changes permanent we will have to copy our swap to the /etc/fstab.

$ sudo cp /etc/fstab /etc/fstab.bak

Last we must add the swap file details to /etc/fstab to make it available at boot up permanently.

echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Final Notes


Aside from this one case, there are many other reasons that one would need swap space which is included but not limited to memory consuming programs, hibernation (suspend-to-ask), unforeseeable circumstances, or optimizing memory usage. Please let me know if I could improve this post by making anything more clear!

Dockerized Flask App with Nginx & PostgreSQL

The purpose of the article is to share my Github project dockerized-nginx-flask-postgres , a dockerized Flask application that starts 3 docker container setup. This article assumes that you have docker and docker-compose installed on your local as you will need these tools to run this project. To run my project $ git clone my repository and then run the following command in the root directory of the project:

$ docker_init.sh

When this command is run a few things will happen:

  1. docker-compose will build the 3 container setup
  2. docker-compose will spin up the cluster on one network
  3. Flask-Migrate will initialize the PostgreSQL database with basic user authentication tables

When Docker finishes initializing the application you will see the following output in of your terminal:

$ ------------------------------------ 
$ The cluster has been initialized 
$ Navigate to http://localhost:8080 
$ to see the running flask app 
$ ------------------------------------ 

Open the browser to http://localhost:8080 and if the compilation of the application was successful then you will see the message Time to get building on the web page.

What’s the Goal of this Project

The goal of this project is to build an adaptable and modular stack that can be configured to be a lean full-stack framework or API depending on your business objectives needs with little to no configuration.

Why I Chose These Technologies

  • Docker – Leveraging the modularity of Docker allowed me to structure the application in a way such that anyone who forks my repository can switch out the source code, web server, or database to whatever technologies they feel comfortable using. For example, switching out PostgreSQL for MySQL is as easy as updating the docker-compose.yml and 1 line of code in the Alembic configuration and that’s it! When technologies change you will be able to swap out any container to stay one step ahead of disruption.
  • Nginx – Nginx was specifically written to address the performance limitations of Apache web servers. It can be deployed as a standalone web server or front-end proxy for other servers. Nginx was designed to support high concurrency where each worker process can handle thousands of HTTP connections simultaneously.
  • Flask – Most of my experiences in web development have come from working with full-stack frameworks such as Laravel or CakePHP that are out of the box and heavy solutions. Full-stack frameworks are great to have many layers of abstraction for a reason, however, they abstract away a lot of what goes on under the hood. I chose Flask because I have full control of what goes on in my application and only import the libraries that are essential to the application. Flask is everything you need it to be and nothing you don’t want it to be. Building out each feature and functionality from scratch has given me a much better understanding of what happens behind the scenes of full-stack frameworks.
  • PostgreSQL – I chose PostgreSQL because it is a powerful open source RDBMS (relational database management system) and I’m most familiar with. Since Flask does not have an ORM (object-relational model) library built in I use Flask-Migrate to manage the evolution of my database.

What’s Next on My TODO List?

  • Mapping the hot reload port on the Flask Container to my Local for faster development
  • Show how to connect your PostgreSQL container to Navicat for PostgreSQL
  • Show configuration for using MySQL instead of PostgreSQL
  • Show how to connect a MySQL DB visitation tool (e.g. MySQL Workbench) to the right port on the database docker container
  • Build out restful routes to populate the basic user authentication tables

Let’s Collaborate

Check it out on Github – I would love to collaborate with anyone! Pass this project along to anyone who you know would benefit from using it or be interested in improving it with me. I will update this blog post as I improve this project.

My top 5 Sketch plugins to increase productivity

The purpose of this article is to share what I think are the most valuable sketch plugins to my workflow when designing desktop and mobile screens. Enjoy!

1. Runner

Sketch Runner Plugin

Regardless of what you’re designing on Sketch, you will need Sketch runner to speed up your Sketch workflow. With this plugin, you will be able to search through all available plugins and Sketch menu commands without having to navigate through those long drop downs. You can also insert symbols, jump to any page, apply text & layer styles, and install new plugins.

2. Content Generator

Sketch Content Generator Plugin

Almost every client or project I’ve worked on has required me to populate my screens with fake data such as names, phone numbers, geo locations, profile images, etc which took a lot of my time because I had to come up with believable data off the top of my head for at least 50 rows of data. The content generator allows you to populate any number of rows of dummy data such as avatars, names, photos, geodata, etc in seconds.

3. Spell Check Whole Page

Sketch Content Generator Plugin

There are few mistakes more embarrassing allowing a spelling error slip through the cracks from design all the way into production. Spell check whole page allows you to spell check all text of every layer on the current page you are on. I also supplement this plugin by typing all of my screen text into Grammarly to check my grammar as well.

4. Merge Duplicate Symbols

Sketch Content Generator Plugin

As I have become savvier utilizing the power of Sketch symbols this tool has saved me a lot of time cleaning up my duplicate symbols from copying and pasting other symbols. This plugin allows you to merge symbols with the same name. You simply choose the one you want to keep and press OK. The other symbols will be removed, and all of their instances will be replaced by the one you choose to keep.

5. Symbol Organizer

Sketch Symbol Organizer Plugin

There comes a point where you have 50+ symbols throughout your Sketch file and you are dreading looking at the symbols page because of how messy you know it will be. Fortunately, the symbol organizer plugin organizes your symbols page alphabetically into groupings determined by symbols names in a clean grid.

Final Notes

I hope that these Sketch plugins add value to your daily workflow. What Sketch plugins have either changed the way you design or increase your productivity? Write them below!

Deploy an Angular App in Production with Nginx & Ubuntu on EC2

This purpose of this tutorial is to show you how to configure Nginx to serve an Angular app on AWS EC2. This tutorial assumes the following:

  • You already have an Amazon Web Services account (if not you can make one here) and have basic knowledge of security groups
  • You already have a purchased a domain name and have associated it with a publicly accessible IP address
  • You have an existing Angular Project hosted on a code repository (Github, GitLab, BitBucket, etc.) and have some basic knowledge of Angular

Summary of technologies used

  • Ubuntu 16.04 LTS
  • Nginx 1.10.3
  • AWS EC2
  • Angular 6.1.3

Step overview

  • Step 1 – Open an EC2 instance
  • Step 2 – Install packages and dependencies
  • Step 3 – Configure Nginx
  • Step 4 – Deployment

Step 1 – Open an EC2 instance

Log into your AWS account, navigate to the EC2 Dashboard, and select “Launch Instance”. From the list of AMIs select Ubuntu Server 16.04 LTS (HVM).

While setting up the instance, you will be brought to a page where you select the instance type. Select t2.micro (free tier eligible). Once selected, click “Review and Launch” at the bottom of the page. On the next page click “Launch” on the bottom of the page as well.

Once launched it will take a few minutes for AWS to boot up your very own EC2 instance. Store your generated key pair in a safe place on your local computer. (Here’s documentation from AWS on how to handle your key pair)

Note: You may have to adjust the security group on your EC2 instance so that your website is publicly available. There’s plenty of resources and stack overflow questions solving this potential issue.


Step 2 – Install packages and dependencies

Time to ssh into your Ubuntu server with:

ssh -i ~/path-to-your-key-pair ubuntu@ec2-your-public-ip.compute-1.amazonaws.com

Once you have successfully logged into your public server it’s time to install some packages. Execute these commands from within your Ubuntu machine:

# update Ubuntu's local package index 
$ sudo apt-get update 

# install git 
$ sudo apt-get install -y git 

# install Nginx 
$ sudo apt-get install -y nginx 

# clear out the local repository of retrieved package files 
$ sudo apt-get -s clean 

Step 3 – Configure Nginx

If you are new to Nginx I highly recommend reading the following to understand what these next steps actually do.

Common Pitfalls using Nginx

Nginx Quick Start

Nginx Configuration

Navigate the sites-available directory.

$ cd /etc/nginx/sites-available

and use your preferred editor (I use vim) to create a new file. In this case we’re storing our nginx configuration as example.com.

$ sudo vim example.com

Enter the following in your new file:

server {     
    listen 80;      
    listen [::]:80;            
    root /var/www/your-angular-app-name/dist;   
    server_tokens off;   
    index index.html index.htm;     
 
    location / {         
        # First attempt to server request as file, then         
        # as directory, then fall back to displaying a 404.          
        try_files $uri $uri/ /index.html =404;      
    } 
}

***The line root /var/www/your-angular-app-name/dist will tell Nginx where the index.html file is for your compiled Angular app.

Save your new file and symlink it to the sites-enabled folder.

$ cd /etc/nginx/sites-enabled 
$ sudo ln -s ../sites-available/example.com 
$ ls -l

Remove the default file that comes with Nginx in the sites-enabled directory. This default file was placed here by Nginx when it was installed.

$ sudo rm default

For good practice run a test on your Nginx configuration to correct any configuration or syntax errors (syntax always gets the best of us).

$ sudo nginx -t

• Restart Nginx:

$ sudo nginx -s reload

Step 4 – Deployment

Before deploying an angular application we must use the Angular CLI to create the production build that will be served on our EC2. You have the option of building the production bundle right on your local or on your live server. If you are working by yourself on a project, it’s okay to build and add the generated dist folder to git source control. Otherwise you should avoid adding the compiled dist bundle to git when working with others to avoid merge conflicts from everyone’s own build.

Angular CLI documentation on deployments

Below I will show you two ways to deploy your app. Both methods below are ok to “test the waters” to build small applications to understand how to deploy an Angular app but I don’t recommend you keep deploying Angular in the ways detailed below. It is well worth your time to learn how to build an automation pipeline that takes care of this process for you. See my article building a simple CI/CD pipeline from GitLab to AWS. (You can build and deploy your Angular app virtually free!)

Path 1: Building the production bundle locally

In the case that you are building the production build on your local you will need to run:

$ ng build --prod

If there are no errors when Angular is building the production bundle then a dist directory will be generated in the root directory (/) of your project.

Check in the new dist dist folder to source control so that you can pull it into your server.

You will then have to ssh into your EC2 and clone the git repository into the /var/www/ directory.

$ cd /var/www
var/www $ git clone https://your-project-name

Note: You may need to use the $ sudo flag if your user inside the server does not have the right permissions to run these commands.

Restart Nginx:

$ sudo nginx -s reload

Navigate to your URL or Elastic IP address and your site should be live! If all you see is an Nginx 404 page then double check the directory on the root ...; line in your Nginx sites-available file is pointing to the right directory.

Path 2: Building on the server

DISCLAIMER: Depending on how large your application is this following method can run up your cloud provider bill.

In the case that you are building the production build on your server, you will then have to ssh into your EC2 and clone the git repository into the /var/www/ directory:

$ cd /var/www
var/www $ git clone https://your-project-name

Note: You may need to use the $ sudo flag if your user inside the server does not have the right permissions to run these commands.

Now it’s time to create the production build right on the server by making sure you currently are in your source code directory. First we must install some additional dependencies on the EC2 instance with the following commands:

# install node package manager 
$ sudo apt-get install -y npm 

# install curl 
$ sudo apt-get install -y curl  
  
# install node.js $ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash - 
 

# update node.js 
$ sudo apt-get install -y nodejs 
 
# install the Angular CLI 
$ sudo npm install -g @angular/cli  

Next we navigate to the directory where we cloned the repository

$ cd /var/www/the-project-you-just-cloned

Once in the project directory, you will run:

$ ng build --prod

If there is an issue with the production build then your website will display the generic Nginx 404 page. To avoid this I highly recommend testing the production build process by running the $ ng build --prod command on your local first for testing.

Once the dist folder has been built we will restart Nginx. Nginx has already been configured to look at the var/www/your-project/dist from our configuration above.

Restart Nginx:

$ sudo nginx -s reload

Navigate to your URL or Elastic IP address and your site should be live! If all you see is an Nginx 404 page then double check the directory on the root ...; line in your Nginx sites-available file is pointing to the right directory.


If you have this process down pat and want more of a challenge then check out my next post on building a simple CI/CD pipeline from GitLab to AWS.

How to preserve your static assets in the production bundle

If you want your static assets (images, svgs, etc.) to show up in production you’ll have to do the following:

  1. In your angular.json make sure that your assets folder holding your static assets is included in the assets block like so:
“tsconfig”:…
“assets”: [
  “src/favicon.ico”,
  “src/assets”,
  “src/robots.txt”,
  “src/sitemap.xml”
],
“styles”:…

With this addition to angular.json, you’re telling angular where to find the assets when you reference them throughout your code in the build process.

2. Make sure that you’re referencing the correct directory path to your assets in your HTML blocks. In the configuration above, each asset in the assets folder should be accessed like the following:

<img src="/assets/images/my_cool_image.jpg" /> 

Now when you build and deploy, the assets should show up because Angular knows where to find them now.

You’re done!

If you’ve followed all these steps, you’ll be able to navigate to your site domain in any browser and see your basic angular app up and running. If not, remember it can take up to 48 hours for any DNS changes to fully propagate if you’ve just associated your Elastic IP to your domain name manager! Thanks for reading!

Small Startup? Need to find tech talent?

The purpose of the article is to share my experiences finding tech talent with a small budget. If your company is a native or web application it’s absolutely imperative that you have a great technology foundation that meets your business’ needs – and is built by the right people. Here’s a list of mediums that may help you find tech talent in no particular order:

“People are not your most important asset. The right people are.” – Jim Collins

1. Meetups

Meetups are a great way of networking yourself amongst a group of people who generally have the same set of interests. Nowadays you can find a meet up that’s focused around certain technologies, frameworks or content management systems that your business needs.

Post a succinct description of the position and a way to contact you on the message boards of the groups you’re trying to target. Be mindful not to spam the groups with your job postings as you may want to check in with the group admins for guidelines regarding job postings on the group message board. The group admins may even help you reach the right people you’re looking for.

https://www.meetup.com/

1. AngelList

Angel list is great for finding talent that’s specifically looking for startup work. Make a company profile, add your job, and start inviting candidates to look at your job posting. When you do get a match on AngelList, be proactive and quickly respond to any developers questions about your job posting.

I would not recommend posting your job on platforms such as LinkedIn or Indeed Prime for those looking for employment on those sites are probably looking for a stable job with full benefits – not a volatile startup with no guarantee of success.

https://angel.co/

3. Code Bootcamps

Contact local code boot camps in your area and ask to speak with someone responsible for making sure the new graduates are employed ASAP after they graduate. When you reach out to these schools you will have to provide them with a short description of your ideal candidate. In turn, they will send you resumes and introduce you to the candidates that you wish to interview.  The majority of the candidates will not have 5+ years of development experience, however, most are eager to learn and jump into the next opportunity if given the chance.

4. Freelancers

Leveraging the plethora of freelancers out there is a great idea. If you’ve hired a freelancer just based on a cheap hourly rate or quote, don’t be surprised when you’re about to hit a deadline and you find out that almost nothing is production ready. Simply put, you get what you pay for. It would be best if you had a tech-savvy person, CTO, or product manager on your team that can negotiate with and properly screens the freelancers. 

https://www.upwork.com

Final Notes

Don’t focus too much on finding someone who is super passionate about your brilliant startup idea. You may be spinning your wheels looking for the “perfect fit” who fits the exact mold of what you’re looking for. You’re much better off looking for someone who loves to build awesome things regardless of what it is they’re building.

Know of another cost-efficient way to find great talent? Comment and let me know!