\documentclass[12pt,oneside,a4paper]{book}

% Język polski
\usepackage{amssymb}
\usepackage{polski}
\usepackage[polish]{babel}

%Opcja dla edytorów kodujących polskie znaki w utf8
\usepackage[utf8]{inputenc}

\usepackage{microtype}
\usepackage{fancyhdr}
\usepackage{pstricks}
\usepackage{blindtext}
\usepackage[T1]{fontenc}
\usepackage{authblk}
\usepackage{placeins}
\usepackage{tocloft}
\usepackage{hyperref}
\usepackage{listings}
\usepackage{chngcntr}
\usepackage{lmodern}
\usepackage{pstricks}
\usepackage{enumitem}
\usepackage{xcolor}
\lstset{basicstyle=\ttfamily,
  showstringspaces=false,
  commentstyle=\color{red},
  keywordstyle=\color{blue}
}
% Włączenie wcięcia w pierwszym akapicie
\usepackage{indentfirst}

% Możliwość dodwania obrazków
\usepackage{graphicx}

% Zmiana nazwy bib
\def\bibname{Literatura}

%\DisableLigatures{encoding = *, family = * }

% Wyłączenie countowania img po chapterze.
\usepackage{chngcntr}
\counterwithout{figure}{chapter}

% Zmiana rozkładu lini w dokumencie
\linespread{1.3}

\renewcommand*{\lstlistingname}{\textbf{Kod}}
\lstset{
  basicstyle=\fontsize{11}{13}\selectfont\ttfamily,
  columns=fullflexible,
  frame=single,
  breaklines=true,
  %postbreak=\mbox{\textcolor{red}{$\hookrightarrow$}\space},
}

%--------------- Wydruk jednostronny
\fancyhead[C]{}
\fancyfoot[C]{\thepage}
\fancyhead[L]{\footnotesize\rightmark}
\fancyhead[R]{}


%\renewcommand{\chaptermark}[1]{%
%\markboth{\MakeUppercase{%
%\chaptername}\ \thechapter.%
%\ #1}{}}

\renewcommand{\sectionmark}[1]{\markright{\thesection.\ #1}}

\setcounter{secnumdepth}{3}

\renewcommand*\thesection{\arabic{section}}
\renewcommand*\thesubsection{\arabic{section}.\arabic{subsection}}
\renewcommand*\thesubsubsection{%
  \arabic{section}.\arabic{subsection}.\arabic{subsubsection}%
}

\setcounter{tocdepth}{3}
\setcounter{secnumdepth}{3}

\pagestyle{fancy}

\begin{document}
%\maketitle

\begin{titlepage}
\centering
\includegraphics[width=0.35\textwidth]{img/uam-logo.pdf}\par
{\scshape\large Wydział Matematyki i Informatyki \par}
\vspace{0.75cm}
{\small Maciej Głowacki \\ Numer albumu: 434689\par}
\vspace{0.2cm}
{\small Filip Izydorczyk \\ Numer albumu: 434700\par}
\vspace{0.2cm}
{\small Marcin Woźniak \\ Numer albumu: 434812\par}
\vspace{0.2cm}
{\small Hubert Wrzesiński \\ Numer albumu: 434813\par}
\vspace{1.5cm}
{\large\bfseries PlanNaPlan - Dokumentacja wdrożeniowa}
\vspace{0.7cm}
\vfill

% Bottom of the page
Poznań, styczeń 2021
\end{titlepage}


\thispagestyle{empty}
\tableofcontents

\newpage
\section{Instalacja}
\subsection{Backend}
\subsubsection{Kompilowanie aplikacji ze źródła}

\begin{itemize}
\item \textbf{Krok 0:} Wymagania: \\
  - System operacyjny: Linux \\
  - Java 14 \\
  - Maven \\
  - Baza Danych (np. MariaDB) \\
  - Osobny user do uruchamiania aplikacji np. backend

\item \textbf{Krok 1:} Pobranie repozytorium ze źródła:

\begin{lstlisting}[
frame=single,
numbers=none,
]
% git clone http://git.plannaplan.pl/filipizydorczyk/backend.git
\end{lstlisting}

\item \textbf{Krok 2:} Zmiana środowiska backendowego na produkcyjne:
\begin{lstlisting}[
frame=single,
numbers=none,
]
% echo "spring.profiles.active=prod" > restservice/src/main/resources/application.properties
\end{lstlisting}

\item \textbf{Krok 3:} Instalacja pluginów za pomocą \lstinline{maven}:
\begin{lstlisting}[
frame=single,
numbers=none,
]
% mvn clean
% mvn install
\end{lstlisting}

\item \textbf{Krok 4:} Kompilowanie środowiska:
\begin{lstlisting}[
frame=single,
numbers=none,
]
% cd restservice
% mvn clean package spring-boot:repackage
\end{lstlisting}

\item \textbf{Krok 5:} Utworzenie folderu oraz skopiowanie aplikacji:
\begin{lstlisting}[
frame=single,
numbers=none,
]
% mkdir -p /opt/plannaplan-backend/logs
% cp -rv restservice/target/*.jar /opt/plannaplan-backend/backend.jar
\end{lstlisting}

\item \textbf{Krok 6:} Dodanie pustej bazy danych, a także użytkownika dla backend'u.

\item \textbf{Krok 7:} Samo uruchomienie aplikacji - wiąże się z ustawieniem
  zmiennych środowiskowych. Polecamy stworzenie skryptu w Bashu aby to wszytsko
  było przetrzymywane tylko w tym skrypcie. Przykładowy skrypt \ref{skryptBash}.
\begin{lstlisting}[
language=bash,
label=skryptBash,
frame=single,
numbers=left,
caption={Skrypt uruchamiający backend aplikacji}
]
#!/bin/sh
SERVICE_NAME="PlanNaPlan Backend"
DIR="/opt/plannaplan-backend"

export PATH=$PATH:$JAVA_HOME/bin

export PLANNAPLAN_MYSQL_DB_HOST=""
export PLANNAPLAN_MYSQL_DB_PORT=""
export PLANNAPLAN_MYSQL_DB=""
export PLANNAPLAN_MYSQL_DB_USERNAME=""
export PLANNAPLAN_MYSQL_DB_PASSWORD=""
export PLANNAPLAN_EMAIL=""
export PLANNAPLAN_EMAIL_HOST=""
export PLANNAPLAN_EMAIL_PORT=""
export PLANNAPLAN_EMAIL_USERNAME=""
export PLANNAPLAN_EMAIL_PASSWORD=""
export PLANNAPLAN_CONSUMER_KEY=""
export PLANNAPLAN_CONSUMER_SECRET=""

java -jar $DIR/backend.jar >> $DIR/log-$(/usr/bin/date -I).log 2>&1
echo $! > /tmp/sd-plananplan.pid
\end{lstlisting}

\item \textbf{Krok 8:} Uzupełnienie skryptu (nr. \ref{skryptBash}) swoimi danymi produkcyjnymi.

\item \textbf{Krok 9:} Utworzenie serwisu, aby backend startował przy
  uruchomieniu serwera.
\begin{lstlisting}[
language=bash,
label=systemD,
frame=single,
numbers=left,
caption={Deamon uruchamiający backend aplikacji.}
]
[Unit]
Description=PlanNaPlan Backend
After=network.target

[Service]
Type=simple
ExecStart="/opt/plannaplan-backend/plannaplan-backend.sh"
WorkingDirectory=/opt/plannaplan-backend
User=backend        #WYBRANY USER W KROKU 0
Group=backend       #WYBRANY USER W KROKU 0
Environment=PATH=$PATH:$JAVA_HOME/bin
StartLimitInterval=30

[Install]
WantedBy=multi-user.target
\end{lstlisting}

\item \textbf{Krok 10:} Przeładownie \lstinline{systemctl}:
\begin{lstlisting}[
frame=single,
numbers=none,
]
% systemctl daemon-reload
\end{lstlisting}

\item \textbf{Krok 11:} Włączenie aby aplikacja uruchamiała się przy starcie
  systemu oraz pierwsze jej uruchomienie, a także status:
\begin{lstlisting}[
frame=single,
numbers=none,
]
% systemctl enable plannaplan-backend
% systemctl start plannaplan-backend
% systemctl status plannaplan-backend
\end{lstlisting}
\end{itemize}

\subsubsection{Binarna wersja aplikacji} \label{sssec:num1}

\begin{itemize}
\item \textbf{Krok 0:} Wymagania: \\
  - System operacyjny: Linux \\
  - Java 14 \\
  - Baza Danych (np. MariaDB) \\
  - Osobny user do uruchamiania aplikacji np. backend

\item \textbf{Krok 1:} Pobranie binarnej.\\
Wszytskie wersje binarane aplikacji znajdują się \url{https://git.plannaplan.pl/filipizydorczyk/backend}

\item \textbf{Krok 2:} Utworzenie folderu oraz skopiowanie binarnej wersji
  aplikacji do folderu \lstinline{/opt/plannaplan-backend/}

\item \textbf{Krok 3:} Dodanie pustej bazy danych, a także użytkownika dla backend'u.

\item \textbf{Krok 4:} Samo uruchomienie aplikacji - wiąże się z ustawieniem
  zmiennych środowiskowych. Polecamy stworzenie skryptu w Bashu aby to wszytsko
  było przetrzymywane tylko w tym skrypcie. Przykładowy skrypt \ref{skryptBash}.

\item \textbf{Krok 5:} Uzupełnienie skryptu (nr. \ref{skryptBash}) swoimi danymi produkcyjnymi.

\item \textbf{Krok 6:} Utworzenie serwisu, aby backend startował przy
  uruchomieniu serwera. Przykładowy kod nr. \ref{systemD}.

\item \textbf{Krok 7:} Przeładownie \lstinline{systemctl}:
\begin{lstlisting}[
frame=single,
numbers=none,
]
% systemctl daemon-reload
\end{lstlisting}

\item \textbf{Krok 8:} Włączenie aby aplikacja uruchamiała się przy starcie
  systemu oraz pierwsze jej uruchomienie, a także status:
\begin{lstlisting}[
frame=single,
numbers=none,
]
% systemctl enable plannaplan-backend
% systemctl start plannaplan-backend
% systemctl status plannaplan-backend
\end{lstlisting}
\end{itemize}

\subsection{Frontend}
\subsubsection{Budowanie strony ze źródła} \label{sssec:num2}
\begin{itemize}
\item \textbf{Krok 0:} Wymagania: \\
  - System operacyjny: Linux \\
  - Yarn \\
  - Httpd \\
  -- Zainstalowany certyfikat SSL (np. Let's Encrypt \footnote{Strona Let's Encrypt:
  \url{https://letsencrypt.org/}}) \\
  - Osobny user do uruchamiania aplikacji np. frontend

\item \textbf{Krok 1:} Pobranie repozytorium ze źródła:
\begin{lstlisting}[
frame=single,
numbers=none,
]
% git clone http://git.plannaplan.pl/y0rune/frontend.git
\end{lstlisting}

\item \textbf{Krok 2:} Dodanie zmiennej środowiskowej razem z adresem URL
  aplikacji backend:
\begin{lstlisting}[
frame=single,
numbers=none,
]
% echo "REACT_APP_API_URL=https://wmi-backend.plannaplan.pl" > .env
\end{lstlisting}

\item \textbf{Krok 3:} Zainstalowanie pluginów za pomocą \lstinline{Yarn}:
\begin{lstlisting}[
frame=single,
numbers=none,
]
% yarn
\end{lstlisting}

\item \textbf{Krok 4:} Zbudowanie statycznej strony:
\begin{lstlisting}[
frame=single,
numbers=none,
]
% yarn run build
\end{lstlisting}

\item \textbf{Krok 5:} Skopiowanie plików z folderu \lstinline{build/} do
  lokalizacji strony w \lstinline{Httpd} (np. \lstinline{/var/www/plannaplan.pl})

\item \textbf{Krok 6:} Przykładowa konfiguracja (Kod nr. \ref{apacheKonf}) \lstinline{Httpd} dla
  statycznej strony w katalogu \lstinline{/var/www/plannaplan.pl}.

\begin{lstlisting}[
language=bash,
label=apacheKonf,
frame=single,
numbers=left,
caption={Konfiguracja statycznej strony w Httpd.}
]
<VirtualHost *:80>
   RewriteEngine on
   RewriteCond %{SERVER_NAME} = #URL DO STRONY
   RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

<VirtualHost *:443>
        SSLEngine on
        ServerName #URL DO STRONY :443
        DocumentRoot /var/www/plannaplan.pl/
        ServerAdmin #EMAIL ADMINISTRATORA
        SSLCertificateFile /etc/letsencrypt/live/full.plannaplan.pl/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/full.plannaplan.pl/privkey.pem
        Include /etc/letsencrypt/options-ssl-apache.conf

        <Directory /var/www/plannaplan.pl/>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride All
                Allow from all
                Options -Indexes
        </Directory>
</VirtualHost>
\end{lstlisting}

\item \textbf{Krok 7:} Restart \lstinline{Httpd} za pomocą \lstinline{systemctl}
\begin{lstlisting}[
frame=single,
numbers=none,
]
% systemctl httpd restart
\end{lstlisting}

\end{itemize}

\newpage
\section{Wdrożenie aplikacji}
\subsection{Pierwsze ręczne wdrożenie}
Każdy z naszych serwisów czyli Backend, Frontend, Baza Danych zostały wdrożone
do serwerów, które znajdują się w chmurze Google Cloud
Platform\footnote{Chmura Google: \url{https://cloud.google.com}}. Dodatkowo ze względów
bezpieczeństwa ruch jest przekierowany przez serwer Proxy.

\begin{figure}[hbt!]
	\centering
	\includegraphics[width=0.8\textwidth]{img/infra.pdf}
	\caption{Infrastruktura naszej aplikacji}
	\footnotesize{Źródło: Opracowanie własne}
	\label{fig:infra}
\end{figure}

\subsubsection{Proxy}
Serwer znajduje się w chmurze Vultr\footnote{Chmura Vultr: \url{https://www.vultr.com/}}. Pełni on role serwera
proxy \footnote{Definicja serwera proxy. Link:
\url{https://en.wikipedia.org/wiki/Proxy_server} }.

\vspace{5px}

Informacje o serwerze:
\begin{itemize}[noitemsep]
\item 1vCPU
\item 1 GB pamięci RAM
\item 25 GB pojemność dysku
\item System Operacyjny: Gentoo Linux \footnote{Strona główna dystrybucji: \url{https://gentoo.org}}
\item Lokalizacja: Frankfurt, Niemcy
\end{itemize}

\subsubsection{Backend}

Wdrożenie backendu aplikacji odbywało się podobnie jak to zostało opisane w
podrozdziale \ref{sssec:num1}.

\vspace{5px}

Informacje o serwerze:
\begin{itemize}[noitemsep]
\item 1vCPU
\item 1.7 GB pamięci RAM
\item 20 GB pojemność dysku
\item System Operacyjny: CentOS 8
\item Lokalizacja: Frankfurt, Niemcy
\end{itemize}

\subsubsection{Frontend}

Wdrożenie frontendu aplikacji odbywało się podobnie jak to zostało opisane w
podrozdziale \ref{sssec:num2}.

\vspace{5px}

Informacje o serwerze:
\begin{itemize}[noitemsep]
\item 1vCPU
\item 600 MB pamięci RAM
\item 20 GB pojemność dysku
\item System Operacyjny: CentOS 8
\item Lokalizacja: Frankfurt, Niemcy
\end{itemize}

\subsubsection{Baza danych}

Wdrożenie bazy danych (MariaDB\footnote{Strona projektu MariaDB \url{https://mariadb.org/}} w naszym przypadku) polegało na zainstalowaniu jej na osobnej maszynie.

\vspace{5px}

Informacje o serwerze:
\begin{itemize}[noitemsep]
\item 1vCPU
\item 600 MB pamięci RAM
\item 20 GB pojemność dysku
\item System Operacyjny: CentOS 8
\item Lokalizacja: Frankfurt, Niemcy
\end{itemize}

\subsection{Automatyzacja wdrożenia na produkcje}
Z powodu dość czasochłonnej każdorazowej zmiany na produkcję, doszliśmy do
wniosku, że automatyzacja jest czymś koniecznym w naszym projekcie.
Gdy odbywają się prace, które mają na celu poprawę aplikacji, każda taka zmiana
odbywa się na osobnej gałęzi (branchu). Następnie, osoba wykonująca zmianę prosi
o zmianę (w Pull Request) a kolejna osoba sprawdza czy wszystkie testy
przechodzą na lokalnej maszynie użytkownika. W dalszym kroku akceptuje zmiany a
następnie repozytorium klonowane jest do kilku instancji (GitLab, GitHub, Gitea)
w celu zapasowej oraz przeprowadzenia kompilacji i wdrożenie jej na wybrany
serwis.

\subsubsection{Backend}
Automatyzacja backendu odbywa się w kilku krokach:

\begin{itemize}
\item {build - aplikacja jest kompilowana, jeżeli wszytsko przejdzie zgodnie z
  planem CI/CD uruchamia kolejny krok.}
\item {deploy\_production - binarny plik jest wysyłany do serwera, serwis
  \lstinline{plannaplan-backend} jest restartowny. W celu przeładowania
  aplikacji.}
\end{itemize}

\begin{lstlisting}[
label=backendYaml,
frame=single,
numbers=left,
caption={Konfiguracja CI/CD backendu}
]
stages:
  - build
  - deploy

build:
  stage: build
  image: maven
  script:
    - echo "Start building App"
    - echo "spring.profiles.active=prod" > restservice/src/main/resources/application.properties
    - mvn clean
    - mvn install
    - cd restservice
    - mvn clean package spring-boot:repackage
    - echo "Build successfully!"
  artifacts:
    expire_in: 1 hour
    paths:
      - restservice/target/
  only:
    - master

deploy_production:
  stage: deploy
  before_script:
    - apt-get update
    - apt-get --yes --force-yes install rsync
  script:
    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
    - eval $(ssh-agent -s)
    - ssh-add <(echo "$SSH_PRIVATE_KEY")
    - mkdir -p ~/.ssh
    - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
    - echo "Deploying to server"
    - ssh backend@wmi-backend-gc.plannaplan.pl -t "sudo systemctl stop plannaplan-backend"
    - ssh backend@wmi-backend-gc.plannaplan.pl -t "rm -rf /opt/plannaplan-backend/backend.jar"
    - rsync --progress restservice/target/*.jar backend@wmi-backend-gc.plannaplan.pl:/opt/plannaplan-backend/backend.jar
    - sleep 5
    - ssh backend@wmi-backend-gc.plannaplan.pl -t "sudo systemctl start plannaplan-backend"
    - echo "Deployed"
  only:
    - master
\end{lstlisting}


\subsubsection{Frontend}

\begin{itemize}
\item {build - aplikacja jest kompilowana, jeżeli wszytsko przejdzie zgodnie z
  planem CI/CD uruchamia kolejny krok.}
\item {deploy\_production - statyczna strona  wysyłana do serwera, serwis
  \lstinline{httpd} jest restartowny. W celu przeładowania aplikacji.}
\end{itemize}

\begin{lstlisting}[
label=backendYaml,
frame=single,
numbers=left,
caption={Konfiguracja CI/CD frontendu}
]
stages:
  - build
  - deploy

build:
  stage: build
  image: node
  script:
    - echo "Start building App"
    - echo "REACT_APP_API_URL=https://wmi-backend.plannaplan.pl" > .env
    - yarn
    - CI= yarn run build
    - echo "Build successfully!"
  artifacts:
    expire_in: 1 hour
    paths:
      - build
      - node_modules/

deploy_production:
  stage: deploy
  before_script:
    - apt-get update
    - apt-get --yes --force-yes install rsync
  script:
    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
    - eval $(ssh-agent -s)
    - ssh-add <(echo "$SSH_PRIVATE_KEY")
    - mkdir -p ~/.ssh
    - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
    - echo "Deploying to server"
    - rsync --progress -r build/* --delete website@wmi-frontend.plannaplan.pl:/var/www/plannaplan.pl
    - echo "Deployed"
  only:
    - master
\end{lstlisting}

\end{document}
