# Amazon Web Services

**Prerequisites: AWS account!**

{% hint style="danger" %} <mark style="color:red;">**IMPORTANT! Dupa terminarea modulului Cloud Computing, asigurati-va ca stergeti toate resursele AWS create pentru a evita costuri suplimentare. Puteti de asemenea sa stergeti detaliile de billing (ceea ce probabil va duce la suspendarea contului, ceea ce va doriti avand in vedere ca tot ce vom porni este de test)**</mark>
{% endhint %}

Amazon Web Services este unul dintre ce mai mari furnizori de servicii in Cloud. Insumeaza acum peste 200 de servicii.

Unul dintre cele mai utilizate servicii este EC2 (Elastic Compute Cloud) care pune la dispozitie masini virtuale. Scopul nostru este de a porni o astfel de masina virtuala, a ne conecta la ea si a face disponibila aplicatia creata in pasii anteriori catre internet.

## 1. Lansare masina virtuala

* Din pagina principala, accesam EC2 (search -> type EC2)

<figure><img src="/files/HGArVSg2uCzDkFpoGJa7" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %} <mark style="color:red;">**Asigurati-va ca sunteti in regiunea eu-central-1 (Frankfurt)**</mark>
{% endhint %}

* **Dupa ce va asigurati ca sunteti in regiunea corecta**, apasati **Launch an instance**

<figure><img src="/files/LAEmPifCkxumqcPH7ZTj" alt=""><figcaption></figcaption></figure>

* Denumiti instanta de masina virtuala cum doriti
* Alegeti Ubuntu. 22.04. Instance type - t2.micro

<figure><img src="/files/MZtEJL61vo5ibqk1cyO3" alt=""><figcaption></figcaption></figure>

* Key pair (login) - Create a new key pair. Denumiti-o cum doriti -> save. Se va salva automat. Nu o pierdeti

<figure><img src="/files/5YDrACjlcPTP1hsZZZpG" alt=""><figcaption></figcaption></figure>

* Network settings - allow all

<figure><img src="/files/2mFRirJkcu8ymbJtdKP5" alt=""><figcaption></figcaption></figure>

* Launch si asteptam sa porneasca instanta
* Puteti vedea instanta apasand pe Instances in meniul din stanga

<figure><img src="/files/FBKA1dmHogrWLlBRy9fr" alt=""><figcaption></figcaption></figure>

## 2. Atasarea unui Elastic IP

{% hint style="warning" %}
AWS atribuie o adresa IP unica instantelor create. **Aceasta este realocata altei instante in momentul in care inchidem instanta noastra, iar la repornire va primi alta. Acest comportament poate duce la confuzie si erori neprevazute.** Pentru a ne asigura ca masina noastra virtuala are o adresa constanta, ii vom atribui o adresa IP Elastica (**Elastic IP**).
{% endhint %}

* Din meniul din stanga, click **Elastic IPs -> Allocate Elastic IP address**

<figure><img src="/files/c5R17gtrIEqdDGdY5uvY" alt=""><figcaption></figcaption></figure>

* All default, click **Allocate**
* Inapoi in Dashboard-ul Elastic IPs, selectati adresa nou creata -> Actions -> Associate Elastic IP address (sau apasati pe bannerul verde care ar trebui sa apara deasupra paginii)

<figure><img src="/files/0EYkemkYyLSyTpRKk4hB" alt=""><figcaption></figcaption></figure>

* Alegeti instanta nou creata, click Associate

<figure><img src="/files/yOHuxjLZZpzWGF6S6W8R" alt=""><figcaption></figcaption></figure>

* In Dashboard-ul Instances veti vedea in dreptul instantei create, pe coloana Elastic IP (probabil va trebui sa scrolati), adresa IP Elastica asociata
* Acum ne putem conecta la instanta nou creata

## 3. Conectarea la instanta EC2

{% hint style="info" %}
Pentru usurinta, mutati cheia generata la pasul anterior intr-un folder apropiat de cel in care ati lucrat pana acum (ca sa nu o cautati in downloads de fiecare data cand aveti nevoie de ea)
{% endhint %}

* Identificati adresa IP a instantei create (Elastic IP). Vom avea nevoie de ea pentru a ne conecta la instanta
* In folderul in care ati salvat cheia, deschideti un terminal (eu folosesc git bash)
* Rulati comanda: (-i indica faptul ca ne conectam utilizand o cheie (identity\_file))

```bash
ssh -i <cheia>.<extensia> ubuntu@<adresa_ip>

exemplu:
ssh -i cloud-computing.pem ubuntu@4.18.2.77

```

* Probabi veti fi intrebati daca doriti sa salvati adresa IP in known\_hosts. Type yes.
* We're in!

## 4. Configurarea instantei EC2

**Folosind consola instantei create in pasul anterior...**

### 4.1. Actualizam pachetele din instanta

* Run **sudo apt update**
* Run **sudo apt upgrade**

### **4.2. Instalam** Nginx

* Run **sudo apt install nginx**
* Run **sudo service nginx start**
* Accessing the server from a browser now shows a "Welcome to nginx!" message

### 4.3. Modificam configurarea Nginx

* Run **sudo nano /etc/nginx/sites-available/default** pentru a accesa fisierul de configurare nginx
* Stergeti tot ce este in fisier si copiati urmatorul cod. Astfel vom indica faptul ca ne dorim ca serverul nostru sa afiseze aplicatia care va rula pe portul 3000 (dupa ce o vom deschide)

```
// /etc/nginx/sites-available/default
server {
        location / {
                proxy_pass http://localhost:3000/;
        }
}
```

* Ctrl + S ca sa salvati
* Ctrl + X ca sa iesiti din fisier
* Run **sudo service nginx reload** pentru a incarca fisierul de configurare modificat
* Accesand acum adresa serverului, vom primi mesajul de eroare 502. Este in regula

### 4.4. Instalam Docker

{% hint style="info" %}
Instructiunile detaliate pentru instalarea Docker pe o instanta EC2 cu Ubuntu 22.04 le puteti gasi si aici: <https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-22-04>

Pentru a fi siguri ca nu uitam o comanda, le voi lista si in aceasta documentatie
{% endhint %}

* Run **sudo apt install apt-transport-https ca-certificates curl software-properties-common**
* Run **curl -fsSL <https://download.docker.com/linux/ubuntu/gpg> | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg**
* Run **echo "deb \[arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] <https://download.docker.com/linux/ubuntu> $(lsb\_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null**
* Run **sudo apt update**
* Run **apt-cache policy docker-ce**
* Run **sudo apt install docker-ce**
* Run **sudo systemctl status docker**
* **Output should look like this now:**

<figure><img src="/files/JEEzAF73mYZjkrUcDaNg" alt=""><figcaption></figcaption></figure>

* Ctrl + C to exit

### 4.5. Enable Docker usage without sudo

Inainte de a asigura acces sudo pentru comenzile docker, va trebui sa adaugam o parola pentru userul ubuntu (creat de AWS la pornirea instantei EC2)

* Run **sudo su -**
* Run **passwd ubuntu**
* Setati o parola (si notati-o intr-un fisier local / nu o pierdeti)
* Ne intoarcem la userul ubuntu. Run: **su -l ubuntu**

Acum putem asigura acces sudo pentru comenzile docker

* Run **sudo usermod -aG docker ${USER}**
* Run **su - ${USER}**
* Introduceti parola pe care ati setat-o la pasul precedent
* Done!
* Pentru a testa ca totul a mers conform planului, rulati **docker images**
* Output should look like this:

<figure><img src="/files/8H0FJ2BZORLhUt685dau" alt=""><figcaption></figcaption></figure>

### 4.6. Pregatim proiectul pentru a fi introdus intr-o imagine Docker

* Modificam fisierul next.config.js pentru a indica faptul ca pregatim proiectul pentru a fi trimis in productie. Inseram linia **output: "standalone"**

```
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  output: "standalone",
}

module.exports = nextConfig
```

* In root-ul proiectului NextJS din calculatorul personal, vom crea fisierul Dockerfile (<mark style="color:red;">**atentie, denumirea trebuie sa fie exact Dockerfile**</mark>) cu urmatorul continut (copy paste - documentatia oficiala Vercel)

```docker
FROM node:18-alpine AS base

# Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app

# Install dependencies based on the preferred package manager
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
  if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
  elif [ -f package-lock.json ]; then npm ci; \
  elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \
  else echo "Lockfile not found." && exit 1; \
  fi


# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
# ENV NEXT_TELEMETRY_DISABLED 1

RUN yarn build

# If using npm comment out above and use below instead
# RUN npm run build

# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app

ENV NODE_ENV production
# Uncomment the following line in case you want to disable telemetry during runtime.
# ENV NEXT_TELEMETRY_DISABLED 1

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder /app/public ./public

# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3000

ENV PORT 3000

CMD ["node", "server.js"]
```

In root-ul proiectului NextJS, vom crea fisierul .dockerignore (<mark style="color:red;">**atentie, denumirea trebuie sa fie exact Dockerfile**</mark>) cu urmatorul continut (copy paste - documentatia oficiala Vercel)

```docker
Dockerfile
.dockerignore
node_modules
npm-debug.log
README.md
.next
.git
```

* Salvam si trimitem in repository-ul remote modificarile pentru ca le vom accesa din instanta noastra EC2 (**git add .** , **git commit -m "Docker init"** , **git push origin \[numele branch-ului]** in terminal)

### 4.7. Aducem proiectul in instanta noastra

Inapoi in consola instantei EC2 configurate vom aduce proiectul NextJS cu ajutorul Git. Pentru aceasta avem nevoie de link-ul de clonare al repository-ului nostru. Il gasiti in GitHub - clone (am trecut prin acest proces [aici](/cloud-computing-2023-simpre/seminar-1/set-up-nextjs-project.md))

* Clonam repository-ul - git clone \[link\_repo] (un folder cu numele repository-ul va fi creat automat)
* Run **ls** pentru a vedea continutul folderului curent. Ar trebui sa vedeti numele folderului care contine repository-ul
* Run **cd \[nume\_repo]** pentru a accesa folderul
* Adaugam fisierul .env:
  * Run **touch .env**
  * Run **sudo nano .env**
  * Copiati continutul fisierului .env de pe calculatorul vostru in fisierul .env creat in instanta
  * Ctrl + S to save
  * Ctrl + X to exit
* Run <mark style="color:red;">**docker build -t nextjs-docker .**</mark> (Atentie, este un punct (.) dupa numele imaginii, nu il uitati)
* Asteptam
* Daca rulam **docker images** vom vedea imaginea nou creata
* Pornim un proces utilizand imaginea creata. Run **docker run -d --restart always -p 3000:3000 nextjs-docker**
* Daca accesam adresa instantei, vom vedea aplicatia noastra!


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gurita-alexandru.gitbook.io/cloud-computing-2023-simpre/seminar-3/amazon-web-services.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
