\documentclass[12pt,a4paper]{article} % ============================================================ % Packages % ============================================================ \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage{lmodern} \usepackage[margin=2.5cm]{geometry} \usepackage{graphicx} \usepackage{hyperref} \usepackage{xcolor} \usepackage{listings} \usepackage{booktabs} \usepackage{enumitem} \usepackage{fancyhdr} \usepackage{titlesec} \usepackage{float} \usepackage{longtable} \usepackage{caption} \usepackage{textcomp} \setlength{\headheight}{14pt} \addtolength{\topmargin}{-2pt} % ============================================================ % Colors and Styling % ============================================================ \definecolor{azureblue}{HTML}{0078D4} \definecolor{codegray}{HTML}{F5F5F7} \definecolor{textdark}{HTML}{1D1D1F} \definecolor{linkblue}{HTML}{0071E3} \hypersetup{ colorlinks=true, linkcolor=azureblue, urlcolor=linkblue, citecolor=azureblue, pdftitle={Task Manager -- Cloud Deployment Documentation}, pdfauthor={Gopi Suvanam} } \lstset{ backgroundcolor=\color{codegray}, basicstyle=\ttfamily\small, breaklines=true, frame=single, rulecolor=\color{gray!30}, captionpos=b, tabsize=2, showstringspaces=false, keywordstyle=\color{azureblue}\bfseries, commentstyle=\color{gray}, stringstyle=\color{green!50!black} } \pagestyle{fancy} \fancyhf{} \fancyhead[L]{\small\textcolor{gray}{Task Manager -- Cloud Deployment}} \fancyhead[R]{\small\textcolor{gray}{SK1 Final Exam}} \fancyfoot[C]{\thepage} \renewcommand{\headrulewidth}{0.4pt} \titleformat{\section}{\Large\bfseries\color{azureblue}}{}{0em}{}[\vspace{-0.5em}\textcolor{azureblue}{\rule{\textwidth}{0.5pt}}] \titleformat{\subsection}{\large\bfseries\color{textdark}}{}{0em}{} % ============================================================ \begin{document} % ============================================================ % ---- Title Page ------------------------------------------- \begin{titlepage} \centering \vspace*{3cm} {\Huge\bfseries\color{azureblue} Task Manager}\\[0.5cm] {\LARGE Cloud Deployment Documentation}\\[2cm] \begin{tabular}{rl} \textbf{Course:} & Cloud Technologies / Web Application Deployment \\ \textbf{Student:} & Gopi Suvanam \\ \textbf{Login:} & gs699he \\ \textbf{Date:} & \today \\ \textbf{Cloud:} & Microsoft Azure (Azure for Students) \\ \textbf{Repository:} & \url{https://git.kemt.fei.tuke.sk/gs699he/zkt25} \\ \end{tabular} \vspace{3cm} \includegraphics[width=0.65\textwidth]{architecture.png} \vfill {\small Technical University of Ko\v{s}ice -- KEMT FEI} \end{titlepage} \tableofcontents \newpage % ============================================================= \section{Application Overview} % ============================================================= The \textbf{Task Manager} is a full-stack web application for creating, reading, updating, and deleting (CRUD) tasks. It is deployed to \textbf{Microsoft Azure} using Docker Compose on an Azure Virtual Machine. \subsection{Key Features} \begin{itemize}[nosep] \item RESTful API with full CRUD operations \item Apple-inspired premium UI with glassmorphism \item Redis caching (30s TTL) for API optimization \item PostgreSQL database with persistent volume and backup scripts \item Automatic HTTPS via Caddy + Let's Encrypt \item Fully automated deployment via shell scripts \item Auto-restart on container failure \end{itemize} % ============================================================= \section{Architecture} % ============================================================= The application uses a \textbf{5-container microservices architecture} on an Azure VM, orchestrated by Docker Compose. \begin{figure}[H] \centering \includegraphics[width=0.72\textwidth]{architecture.png} \caption{Architecture -- 5 Docker containers on Azure VM} \label{fig:architecture} \end{figure} \subsection{Container Descriptions} \begin{longtable}{@{}p{2.8cm}p{3cm}p{7.7cm}@{}} \toprule \textbf{Container} & \textbf{Image} & \textbf{Purpose} \\ \midrule \endhead Caddy & caddy:2-alpine & Reverse proxy with automatic HTTPS/TLS via Let's Encrypt. Ports 80, 443. \\[6pt] Frontend & nginx:alpine & Serves static HTML/CSS/JS, proxies \texttt{/api/} to backend. \\[6pt] API & node:20-alpine & Express.js REST API with CRUD endpoints. \\[6pt] PostgreSQL & postgres:16-alpine & Persistent database with Docker named volume. \\[6pt] Redis & redis:7-alpine & In-memory cache with AOF persistence. \\ \bottomrule \end{longtable} \subsection{Network Isolation} \begin{itemize}[nosep] \item \texttt{frontend-net} -- Caddy, Frontend, API \item \texttt{backend-net} -- API, PostgreSQL, Redis \end{itemize} Database and cache are \textbf{not accessible} from the internet. Only the API bridges both networks. % ============================================================= \section{Azure Services Used} % ============================================================= \begin{longtable}{@{}p{4.5cm}p{9cm}@{}} \toprule \textbf{Service} & \textbf{Usage} \\ \midrule \endhead Azure VM (Standard\_B1s) & Ubuntu 24.04, 1 vCPU, 1 GB RAM. Runs Docker. \\[6pt] Public IP + DNS & \texttt{*.westeurope.cloudapp.azure.com} for HTTPS. \\[6pt] Azure for Students & \$100 free credit, no credit card required. \\[6pt] Let's Encrypt & Free TLS certificates via Caddy (auto-renewal). \\[6pt] cloud-init & Installs Docker on first VM boot automatically. \\ \bottomrule \end{longtable} % ============================================================= \section{File Descriptions} % ============================================================= \begin{longtable}{@{}p{4.5cm}p{9cm}@{}} \toprule \textbf{File} & \textbf{Description} \\ \midrule \endhead \texttt{docker-compose.yaml} & 5 services, 2 networks, persistent volumes. \\[4pt] \texttt{prepare-app.sh} & Creates Azure VM, installs Docker, deploys app. \\[4pt] \texttt{remove-app.sh} & Deletes Azure resource group (all resources). \\[4pt] \texttt{backup-db.sh} & SSH + pg\_dump for database backups. \\[4pt] \texttt{view-logs.sh} & Retrieves container logs via SSH. \\[4pt] \texttt{cloud-init.yaml} & Auto-installs Docker on VM first boot. \\[4pt] \texttt{env.example} & Template for secrets (copied to .env). \\[4pt] \texttt{caddy/Caddyfile} & HTTPS reverse proxy configuration. \\[4pt] \texttt{frontend/} & Nginx Dockerfile, config, static files. \\[4pt] \texttt{api/} & Node.js Dockerfile, Express server, DB pool. \\[4pt] \texttt{db/init.sql} & Database schema and sample data. \\[4pt] \texttt{docs/} & This documentation + architecture diagram. \\ \bottomrule \end{longtable} % ============================================================= \section{Configuration} % ============================================================= All settings via environment variables in \texttt{.env} (gitignored). \begin{longtable}{@{}p{4.5cm}p{4.5cm}p{4.5cm}@{}} \toprule \textbf{Variable} & \textbf{Description} & \textbf{Default} \\ \midrule \endhead \texttt{POSTGRES\_PASSWORD} & Database password & \textit{(required)} \\ \texttt{AZURE\_RESOURCE\_GROUP} & Resource group name & taskmanager-rg \\ \texttt{AZURE\_LOCATION} & Azure region & westeurope \\ \texttt{AZURE\_VM\_SIZE} & VM size & Standard\_B1s \\ \texttt{AZURE\_DNS\_LABEL} & DNS subdomain & taskmanager-gs699he \\ \bottomrule \end{longtable} \subsection{Security} \begin{itemize}[nosep] \item \texttt{.env} in \texttt{.gitignore} -- secrets never in Git \item Databases on isolated Docker network \item HTTPS enforced by Caddy (HTTP $\rightarrow$ HTTPS redirect) \item Security headers in Nginx \item SSH key authentication (no password login) \end{itemize} % ============================================================= \section{Deployment Instructions} % ============================================================= \subsection{Prerequisites} \begin{enumerate}[nosep] \item Azure CLI: \texttt{curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash} \item Azure for Students subscription activated \item \texttt{az login} completed \end{enumerate} \subsection{Deploy} \begin{lstlisting}[language=bash] # Clone and configure git clone git@git.kemt.fei.tuke.sk:gs699he/zkt25.git cd zkt25/sk1 cp env.example .env nano .env # Set POSTGRES_PASSWORD # Deploy to Azure ./prepare-app.sh # Creates: Resource Group -> VM -> Docker -> Containers # Access: # https://taskmanager-gs699he.westeurope.cloudapp.azure.com \end{lstlisting} \subsection{Remove (after exam)} \begin{lstlisting}[language=bash] ./remove-app.sh # Deletes entire resource group (VM, IP, disk, NSG) \end{lstlisting} % ============================================================= \section{Data Persistence and Backups} % ============================================================= \subsection{Volumes} \begin{itemize}[nosep] \item \texttt{taskapp-pgdata} -- PostgreSQL data \item \texttt{taskapp-redisdata} -- Redis AOF \item \texttt{taskapp-caddy-data} -- TLS certificates \end{itemize} \subsection{Backup} \begin{lstlisting}[language=bash] ./backup-db.sh # Output: backups/taskmanager_backup_20260519_020000.sql \end{lstlisting} \subsection{Auto-Restart} All containers: \texttt{restart: always}. Docker starts on boot via systemd. % ============================================================= \section{Access Logs} % ============================================================= \begin{lstlisting}[language=bash] ./view-logs.sh # All logs ./view-logs.sh --caddy # HTTPS proxy logs ./view-logs.sh --api -f # Follow API logs real-time \end{lstlisting} Log sources: \begin{itemize}[nosep] \item \textbf{Caddy}: JSON -- client IP, status, TLS version \item \textbf{API}: \texttt{METHOD /path STATUS duration} \item \textbf{Nginx}: Combined log format \end{itemize} % ============================================================= \section{Cost Analysis} % ============================================================= \subsection{Azure for Students -- Monthly Costs} \begin{longtable}{@{}p{5cm}p{5cm}r@{}} \toprule \textbf{Resource} & \textbf{Configuration} & \textbf{Monthly} \\ \midrule \endhead Azure VM & Standard\_B1s (1 vCPU, 1 GB) & \$7.59 \\ Public IP & Static IPv4 & \$3.00 \\ OS Disk & 30 GB Premium SSD & \$1.20 \\ TLS Certificate & Let's Encrypt (free) & \$0.00 \\ \midrule \textbf{Total} & & \textbf{\$11.79} \\ \textbf{Annual} & & \textbf{\$141.48} \\ \bottomrule \end{longtable} Azure for Students provides \$100 free credit -- enough for approximately 8 months of operation. \subsection{Comparison} \begin{longtable}{@{}p{4cm}p{5cm}r@{}} \toprule \textbf{Provider} & \textbf{Plan} & \textbf{Monthly} \\ \midrule \endhead Azure (Students) & B1s + \$100 credit & \$11.79 \\ AWS & t3.micro (free 12mo) & \$8.50 \\ DigitalOcean & Basic Droplet 2 GB & \$12.00 \\ Hostinger & KVM 1 (4 GB) & \$5.99 \\ \bottomrule \end{longtable} % ============================================================= \section{AI Usage Declaration} % ============================================================= \begin{itemize}[nosep] \item \textbf{Google Antigravity (Gemini)}: Generated scripts, Docker Compose, Nginx/Caddy config, and this documentation. \item \textbf{Architecture diagram}: AI-generated from technical specification. \end{itemize} All content reviewed, tested, and adapted. Student understands all components. \end{document}