minmon/docs/minmon-homelab-report.tex

568 lines
23 KiB
TeX

\documentclass[12pt,a4paper]{report}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[indonesian]{babel}
\usepackage[a4paper,margin=2.8cm]{geometry}
\usepackage{graphicx}
\usepackage{float}
\usepackage{array}
\usepackage{booktabs}
\usepackage{longtable}
\usepackage{hyperref}
\usepackage{xcolor}
\usepackage{listings}
\usepackage{enumitem}
\usepackage{titlesec}
\usepackage{setspace}
\hypersetup{
colorlinks=true,
linkcolor=blue!60!black,
urlcolor=blue!60!black,
pdftitle={Laporan Proyek Minmon Homelab},
pdfauthor={[Nama Mahasiswa]}
}
\onehalfspacing
\setlist[itemize]{noitemsep, topsep=4pt}
\setlist[enumerate]{noitemsep, topsep=4pt}
\renewcommand{\chaptername}{BAB}
\titleformat{\chapter}[display]
{\bfseries\Large}
{\chaptername\ \thechapter}
{0.5em}
{\Large}
\definecolor{codebg}{RGB}{248,248,248}
\definecolor{bordergray}{RGB}{210,210,210}
\lstdefinestyle{minmoncode}{
backgroundcolor=\color{codebg},
basicstyle=\ttfamily\small,
breaklines=true,
frame=single,
rulecolor=\color{bordergray},
showstringspaces=false,
tabsize=2,
keywordstyle=\color{blue!60!black}\bfseries,
commentstyle=\color{green!40!black},
stringstyle=\color{red!50!black}
}
\lstdefinelanguage{TypeScript}{
keywords={import,from,export,const,return,if,await,async,type,string,number,boolean,null,undefined},
sensitive=true,
morecomment=[l]{//},
morecomment=[s]{/*}{*/},
morestring=[b]",
morestring=[b]'
}
\newcommand{\uipath}[1]{\texttt{#1}}
\newcommand{\uibutton}[1]{\textbf{#1}}
\newcommand{\uiscreenshot}[2]{
\begin{figure}[H]
\centering
\includegraphics[width=0.94\textwidth]{#1}
\caption{#2}
\end{figure}
}
\newcommand{\uidiagram}[2]{
\begin{figure}[H]
\centering
\includegraphics[width=0.94\textwidth,height=0.72\textheight,keepaspectratio]{#1}
\caption{#2}
\end{figure}
}
\begin{document}
\begin{titlepage}
\centering
{\Large \textbf{LAPORAN PROYEK DAN MANUAL BOOK}}\\[1.2cm]
{\Huge \textbf{MINMON}}\\[0.4cm]
{\Large Dashboard Inventaris dan Monitoring Homelab Berbasis Web}\\[1.2cm]
\begin{tabular}{ll}
\textbf{Nama Mahasiswa} & : \makebox[7cm]{\hrulefill}\\
\textbf{NIM} & : \makebox[7cm]{\hrulefill}\\
\textbf{Program Studi} & : \makebox[7cm]{\hrulefill}\\
\textbf{Mata Kuliah} & : \makebox[7cm]{\hrulefill}\\
\textbf{Dosen Pengampu} & : \makebox[7cm]{\hrulefill}\\
\textbf{Institusi} & : \makebox[7cm]{\hrulefill}\\
\textbf{Tahun Akademik} & : \makebox[7cm]{\hrulefill}
\end{tabular}
\vfill
{\large Dokumen ini disusun untuk mendeskripsikan proyek \textit{Minmon} yang digunakan untuk mendata dan memonitor inventaris homelab, khususnya lingkungan kecil yang terdiri dari beberapa server dengan banyak service dan domain terkait.}\\[1cm]
{\large \today}
\end{titlepage}
\tableofcontents
\clearpage
\chapter{Pendahuluan}
\section{Latar Belakang}
Homelab adalah lingkungan laboratorium komputer pribadi yang biasanya dibangun di rumah atau lingkungan kecil untuk belajar, mencoba, dan menjalankan layanan server secara mandiri. Dalam homelab, pengguna dapat mengelola server fisik, mini PC, virtual machine, container, jaringan lokal, serta berbagai aplikasi seperti dashboard, database, media server, reverse proxy, dan automation tools. Homelab modern tidak lagi hanya berisi satu mesin dengan satu layanan. Dalam praktiknya, satu homelab kecil dapat terdiri dari beberapa server, banyak service, serta sejumlah domain atau subdomain yang harus diarahkan ke alamat IP yang benar. Ketika jumlah aset ini bertambah, pencatatan manual menjadi sulit dipelihara karena data server, service, domain, dan catatan operasional tersebar di berbagai tempat.
Minmon dikembangkan sebagai dashboard inventaris dan monitoring ringan berbasis web untuk membantu pemilik homelab mengelola aset tersebut dalam satu aplikasi terpusat. Aplikasi ini tidak ditujukan untuk deployment automation, melainkan untuk kebutuhan dokumentasi, inventaris, relasi data, dan validasi DNS sederhana. Dalam konteks penggunaan pribadi, proyek ini cocok untuk skenario homelab yang terdiri dari beberapa server dengan banyak service dan domain yang perlu dicatat serta dipantau.
Implementasi saat ini menyediakan autentikasi admin, dashboard ringkasan, CRUD untuk server, service, domain, dan catatan, serta fitur pemeriksaan DNS A record. Selain itu, relasi antar entitas juga sudah diterapkan melalui select input agar pengguna tidak perlu memasukkan ID relasi secara manual. Dengan demikian, Minmon dapat berfungsi sebagai pusat data operasional homelab yang lebih rapi, konsisten, dan mudah diperluas.
\section{Tujuan}
Tujuan dari pengembangan proyek ini adalah sebagai berikut:
\begin{itemize}
\item Membangun aplikasi web yang dapat digunakan untuk mengelola inventaris homelab secara terstruktur.
\item Menyediakan fitur CRUD untuk data server, service, domain, dan catatan dalam satu dashboard terproteksi.
\item Menyediakan pemeriksaan DNS sederhana untuk memverifikasi apakah domain mengarah ke IP server yang diharapkan.
\item Mempermudah dokumentasi relasi data, misalnya service yang berjalan pada server tertentu dan catatan yang melekat pada server tertentu.
\item Menjadi contoh implementasi aplikasi web penuh berbasis React, tRPC, Drizzle ORM, PostgreSQL, dan better-auth.
\end{itemize}
\section{Manfaat}
Manfaat dari proyek ini antara lain:
\begin{itemize}
\item Membantu pemilik homelab mendokumentasikan server, service, domain, dan catatan dalam satu tempat.
\item Mengurangi kesalahan input relasi data karena hubungan antar data dipilih melalui field pilihan.
\item Memudahkan pengecekan domain melalui fitur pemeriksaan DNS berbasis A record / IPv4.
\item Memberikan gambaran ringkas kondisi homelab melalui ringkasan dashboard.
\item Menjadi bahan laporan akademik dan contoh produk perangkat lunak yang benar-benar dapat dipakai.
\end{itemize}
\chapter{Metode Pengembangan}
\section{Tahap Pengembangan}
Tahap pengembangan proyek Minmon dapat dijelaskan secara ringkas sebagai berikut:
\begin{enumerate}
\item \textbf{Identifikasi kebutuhan}\\
Menentukan kebutuhan utama untuk inventaris homelab, yaitu pengelolaan data server, service, domain, dan catatan, serta kebutuhan monitoring DNS sederhana.
\item \textbf{Perancangan data dan relasi}\\
Menentukan entitas inti, yaitu server, service, domain, dan catatan. Setiap service terkait ke satu server, setiap domain terkait ke satu service, dan setiap catatan terkait ke satu server.
\item \textbf{Perancangan backend}\\
Mengimplementasikan router tRPC untuk operasi daftar data, detail, tambah, ubah, hapus, serta ringkasan dashboard. Pemeriksaan DNS diimplementasikan sebagai operasi khusus pada data domain.
\item \textbf{Perancangan frontend}\\
Membangun halaman login, ringkasan dashboard, halaman daftar data, halaman tambah data, dan halaman detail/edit untuk setiap entitas. Form relasi dibuat menggunakan pilihan data agar lebih aman dan mudah dipakai.
\item \textbf{Integrasi dan validasi}\\
Menghubungkan frontend ke backend dengan TanStack Query dan tRPC client, lalu memastikan operasi data, pembaruan ulang data, serta tampilan ringkasan berjalan dengan baik.
\item \textbf{Pengujian dan penyempurnaan}\\
Melakukan pemeriksaan tipe, pengecekan alur CRUD, pengecekan DNS, perbaikan kestabilan urutan daftar data, dan penyempurnaan interaksi UI seperti hapus dua langkah dan pemicu DNS dari badge status.
\end{enumerate}
\section{Identitas/Keunikan Produk}
Minmon memiliki identitas produk sebagai dashboard inventaris dan monitoring ringan untuk homelab. Keunikan produk ini dibanding pencatatan manual biasa adalah sebagai berikut:
\begin{itemize}
\item Fokus pada skenario homelab kecil-menengah, yaitu beberapa server dengan banyak service dan domain.
\item Menggabungkan inventaris dan dokumentasi operasional dalam satu aplikasi.
\item Menyediakan relasi data yang jelas antara server, service, domain, dan catatan.
\item Memiliki pemeriksaan DNS A record yang terintegrasi langsung pada alur domain.
\item Menampilkan catatan yang terkait langsung pada halaman detail server.
\item Menggunakan autentikasi admin sehingga dashboard tidak dapat diakses tanpa sesi.
\end{itemize}
Untuk penggunaan pribadi, Minmon cocok sebagai pusat dokumentasi homelab yang tidak hanya menyimpan data inventaris, tetapi juga membantu memastikan domain masih mengarah ke IP yang benar dan memudahkan pelacakan catatan operasional pada setiap server.
\section{Diagram-diagram UML (use case, class, activity, state chart, sequence, collaboration)}
Bagian ini berisi rancangan UML yang disusun berdasarkan implementasi aktual Minmon. Diagram disisipkan sebagai gambar agar alur sistem dapat dibaca langsung di dalam laporan. Struktur diagram mencerminkan aktor admin, modul frontend React, router tRPC, database PostgreSQL melalui Drizzle ORM, dan modul pemeriksaan DNS.
\subsection{Use Case Diagram}
Use case utama dalam sistem ini meliputi:
\begin{itemize}
\item Admin sign in
\item Admin mengakses ringkasan dashboard
\item Admin mengelola server
\item Admin mengelola service
\item Admin mengelola domain
\item Admin menjalankan pemeriksaan DNS dari halaman daftar atau detail domain
\item UI menjalankan pemeriksaan DNS setelah domain dibuat atau diperbarui
\item Admin mengelola catatan
\item Admin melihat catatan pada detail server
\item Admin sign out
\end{itemize}
\uidiagram{diagrams/use-case.png}{Use Case Diagram Minmon}
\subsection{Class Diagram}
Entitas utama pada sistem adalah:
\begin{itemize}
\item \textbf{Server}: id, name, primaryIpAddress, secondaryIpAddress, operatingSystem, location, provider, description, status, createdAt, updatedAt
\item \textbf{Service}: id, serverId, name, type, internalPort, externalPort, protocol, status, description, createdAt, updatedAt
\item \textbf{Domain}: id, serviceId, name, expectedServerIp, lastResolvedIp, lastResolvedIps, resolutionStatus, lastCheckedAt, remarks, lastCheckMessage, createdAt, updatedAt
\item \textbf{Catatan}: id, serverId, title, content, category, createdAt, updatedAt
\end{itemize}
Hubungan utama:
\begin{itemize}
\item Server 1..* Service secara konseptual, tetapi secara database dapat 0..*.
\item Server 1..* Catatan secara konseptual, tetapi secara database dapat 0..*.
\item Service 1..* Domain secara konseptual, tetapi secara database dapat 0..*.
\end{itemize}
\uidiagram{diagrams/class.png}{Class Diagram Minmon}
\subsection{Activity Diagram}
Activity diagram berikut menampilkan alur pemeriksaan DNS yang sesuai dengan implementasi saat ini, yaitu dipicu oleh UI setelah domain ditambahkan/diperbarui atau dijalankan manual dari halaman daftar/detail domain:
\begin{enumerate}
\item Admin membuat, memperbarui, atau memeriksa domain.
\item UI memanggil operasi \texttt{domains.create}, \texttt{domains.update}, atau \texttt{domains.check} sesuai aksi.
\item Setelah create/update berhasil, UI memanggil \texttt{domains.check} untuk menjalankan pemeriksaan DNS.
\item Backend melakukan resolve IPv4 A record.
\item Backend membandingkan hasil resolve dengan \texttt{expectedServerIp}.
\item Backend menyimpan status dan hasil resolve ke database.
\item UI memperbarui ulang data dan menampilkan status baru.
\end{enumerate}
\uidiagram{diagrams/activity.png}{Activity Diagram DNS Check}
\subsection{State Chart Diagram}
State chart yang disarankan adalah state untuk status DNS domain:
\begin{itemize}
\item UNRESOLVED
\item MATCH
\item MISMATCH
\end{itemize}
Transisi utama:
\begin{itemize}
\item DNS berhasil dan IP cocok $\rightarrow$ MATCH
\item DNS berhasil tetapi IP tidak cocok $\rightarrow$ MISMATCH
\item DNS gagal resolve $\rightarrow$ UNRESOLVED
\end{itemize}
\uidiagram{diagrams/state-chart.png}{State Chart Domain DNS}
\subsection{Sequence Diagram}
Sequence diagram yang cocok untuk proyek ini adalah alur tambah domain dan pemeriksaan DNS lanjutan, karena UI langsung memanggil pemeriksaan DNS setelah domain berhasil dibuat:
\begin{itemize}
\item Admin
\item Web UI
\item tRPC client/API
\item Database
\item Domain check module
\item DNS Resolver
\end{itemize}
\uidiagram{diagrams/sequence.png}{Sequence Diagram Create Domain and Check DNS}
\subsection{Collaboration Diagram}
Collaboration diagram menunjukkan interaksi aktual antara route terproteksi, halaman dashboard, TanStack Query, router tRPC, database, dan modul pemeriksaan DNS:
\begin{itemize}
\item Admin
\item Dashboard UI dan route terproteksi
\item better-auth client
\item TanStack Query dan tRPC router
\item Database
\item Modul DNS lookup
\end{itemize}
\uidiagram{diagrams/collaboration.png}{Collaboration Diagram Minmon}
\section{Coding Minimal 80 Baris}
Bagian ini menampilkan kode asli dari file \uipath{packages/api/src/routers/services.ts}. Kode ini dipilih karena berjumlah 82 baris dan mewakili logika inti backend, yaitu protected CRUD untuk entitas service, validasi relasi ke server, penghitungan ringkasan domain, dan operasi database menggunakan Drizzle ORM.
\begin{lstlisting}[style=minmoncode,language=TypeScript,caption={Kode servicesRouter: CRUD Service dan validasi relasi, 82 baris}]
import { db } from "@minmon/db";
import { domain, service } from "@minmon/db";
import { count, desc, eq } from "drizzle-orm";
import { protectedProcedure, router } from "../index";
import {
byIdSchema,
serviceCreateSchema,
serviceListSchema,
serviceUpdateSchema,
} from "./schemas";
import {
createEntityId,
requireServer,
requireService,
stripUndefined,
} from "./utils";
export const servicesRouter = router({
list: protectedProcedure.input(serviceListSchema).query(async ({ input }) => {
if (!input?.serverId) {
return db.select().from(service).orderBy(desc(service.createdAt), desc(service.id));
}
await requireServer(input.serverId);
return db
.select()
.from(service)
.where(eq(service.serverId, input.serverId))
.orderBy(desc(service.createdAt), desc(service.id));
}),
byId: protectedProcedure.input(byIdSchema).query(async ({ input }) => {
const item = await requireService(input.id);
const [domainCount] = await db.select({ count: count() }).from(domain).where(eq(domain.serviceId, input.id));
return {
...item,
summary: {
domains: domainCount?.count ?? 0,
},
};
}),
create: protectedProcedure.input(serviceCreateSchema).mutation(async ({ input }) => {
await requireServer(input.serverId);
const [created] = await db
.insert(service)
.values({
id: createEntityId(),
...input,
})
.returning();
return created;
}),
update: protectedProcedure.input(serviceUpdateSchema).mutation(async ({ input }) => {
const { id, serverId, ...changes } = input;
await requireService(id);
if (serverId) {
await requireServer(serverId);
}
const [updated] = await db
.update(service)
.set(stripUndefined({ serverId, ...changes }))
.where(eq(service.id, id))
.returning();
return updated;
}),
delete: protectedProcedure.input(byIdSchema).mutation(async ({ input }) => {
await requireService(input.id);
await db.delete(service).where(eq(service.id, input.id));
return { id: input.id };
}),
});
\end{lstlisting}
Penjelasan singkat kode di atas:
\begin{itemize}
\item \texttt{list} mengambil daftar service, baik seluruh service maupun service berdasarkan \texttt{serverId}, dengan urutan stabil berdasarkan \texttt{createdAt} dan \texttt{id}.
\item \texttt{byId} mengambil detail service dan menambahkan ringkasan jumlah domain yang terhubung ke service tersebut.
\item \texttt{create} memvalidasi server induk terlebih dahulu sebelum menyimpan service baru.
\item \texttt{update} memastikan service yang diedit ada, lalu memvalidasi server baru jika relasi \texttt{serverId} diubah.
\item \texttt{delete} memastikan data service ada sebelum dihapus dari database.
\end{itemize}
\chapter{Manual Book}
\section{Gambaran Umum Penggunaan}
Bagian ini menjelaskan cara menggunakan aplikasi Minmon berdasarkan implementasi saat ini. Gaya penjelasan dibuat seperti manual book: langkah demi langkah, ringkas, dan fokus pada hasil yang diharapkan.
\section{Login ke Sistem}
\textbf{Path akses:} \uipath{/login}
\begin{enumerate}
\item Jalankan aplikasi web dan server backend dari root proyek menggunakan perintah \texttt{bun run dev}.
\item Buka browser ke alamat \uipath{http://localhost:5173}.
\item Jika belum login, sistem akan mengarahkan ke \uipath{/login}.
\item Masukkan email admin dan password.
\item Tekan tombol \uibutton{Sign In}.
\end{enumerate}
\textbf{Hasil yang diharapkan:} pengguna masuk ke halaman \uipath{/dashboard}.
Tampilan halaman login berisi form email dan password untuk admin. Apabila data benar, sistem membuat session melalui better-auth dan mengarahkan pengguna ke dashboard.
\uiscreenshot{screenshots/manual-login.png}{Halaman Login Minmon}
\section{Membuka Dashboard Summary}
\textbf{Path akses:} \uipath{/dashboard}
Halaman dashboard menampilkan ringkasan:
\begin{itemize}
\item total server,
\item total service,
\item total domain,
\item jumlah DNS match / mismatch / unresolved,
\item service yang inactive/down,
\item catatan terbaru.
\end{itemize}
\textbf{Langkah penggunaan:}
\begin{enumerate}
\item Login sebagai admin.
\item Setelah diarahkan ke dashboard, periksa kartu ringkasan di bagian atas.
\item Gunakan link area untuk membuka halaman Servers, Services, Domains, atau Catatan.
\end{enumerate}
Dashboard summary berfungsi sebagai halaman awal setelah login. Pengguna dapat langsung melihat kondisi umum inventaris sebelum masuk ke halaman CRUD masing-masing modul.
\uiscreenshot{screenshots/manual-dashboard.png}{Dashboard Summary Minmon}
\section{Mengelola Data Server}
\textbf{Path akses:} \uipath{/dashboard/servers}
\subsection{Menambah Server}
\begin{enumerate}
\item Buka menu Servers.
\item Klik tombol \uibutton{Add server}.
\item Isi data server seperti nama, IP utama, lokasi, provider, dan status.
\item Klik \uibutton{Save server}.
\end{enumerate}
\textbf{Hasil yang diharapkan:} data server tersimpan dan pengguna diarahkan ke halaman detail server.
\uiscreenshot{screenshots/manual-servers-list.png}{Halaman Daftar Server}
\uiscreenshot{screenshots/manual-server-create.png}{Form Tambah Server}
\subsection{Melihat Detail Server}
\textbf{Path akses:} \uipath{/dashboard/servers/\$serverId}
Pada halaman ini pengguna dapat:
\begin{itemize}
\item melihat ringkasan server,
\item mengedit data server,
\item melihat catatan yang terkait dengan server tersebut.
\end{itemize}
Halaman detail server menjadi pusat informasi untuk satu server tertentu karena menampilkan data utama server dan catatan yang terhubung dengan server tersebut.
\uiscreenshot{screenshots/manual-server-detail.png}{Halaman Detail Server}
\section{Mengelola Data Service}
\textbf{Path akses:} \uipath{/dashboard/services}
\subsection{Menambah Service}
\begin{enumerate}
\item Buka menu Services.
\item Klik \uibutton{Add service}.
\item Pilih server induk pada field \textit{Server}.
\item Isi nama service, tipe, port, protokol, status, dan deskripsi.
\item Klik \uibutton{Save service}.
\end{enumerate}
\textbf{Hasil yang diharapkan:} service tersimpan dan terhubung ke server yang dipilih.
\uiscreenshot{screenshots/manual-services-list.png}{Halaman Daftar Service}
\uiscreenshot{screenshots/manual-service-create.png}{Form Tambah Service}
\section{Mengelola Data Domain}
\textbf{Path akses:} \uipath{/dashboard/domains}
\subsection{Menambah Domain}
\begin{enumerate}
\item Buka menu Domains.
\item Klik \uibutton{Add domain}.
\item Pilih service induk pada field \textit{Service}.
\item Isi nama domain dan expected IP bila diperlukan.
\item Klik \uibutton{Save domain}.
\end{enumerate}
\textbf{Catatan:} jika expected IP dikosongkan, backend akan menggunakan IP server induk dari service terkait.
\uiscreenshot{screenshots/manual-domain-create.png}{Form Tambah Domain}
\subsection{Menjalankan DNS Check}
\begin{enumerate}
\item Buka halaman daftar domain.
\item Tekan badge status DNS pada baris domain yang ingin dicek.
\item Tunggu proses pemeriksaan selesai.
\item Lihat hasil baru pada kolom status dan IP hasil resolve.
\end{enumerate}
\textbf{Hasil yang diharapkan:} status berubah menjadi \texttt{MATCH}, \texttt{MISMATCH}, atau \texttt{UNRESOLVED}.
Pada halaman daftar domain, badge status DNS juga berfungsi sebagai tombol aksi. Ketika ditekan, sistem menjalankan proses pemeriksaan DNS dan memperbarui status pada baris domain tersebut.
\uiscreenshot{screenshots/manual-domains-list.png}{Halaman Daftar Domain dan Status DNS}
\section{Mengelola Data Catatan}
\textbf{Path akses:} \uipath{/dashboard/notes}
\subsection{Menambah Catatan}
\begin{enumerate}
\item Buka menu Catatan.
\item Klik tombol tambah catatan.
\item Pilih server pada field \textit{Server}.
\item Isi judul, kategori, dan isi catatan.
\item Klik tombol simpan catatan.
\end{enumerate}
\textbf{Hasil yang diharapkan:} catatan tersimpan dan terhubung ke server terpilih.
\uiscreenshot{screenshots/manual-notes-list.png}{Halaman Daftar Catatan}
\uiscreenshot{screenshots/manual-note-create.png}{Form Tambah Catatan}
\subsection{Melihat Catatan pada Detail Server}
\begin{enumerate}
\item Buka halaman detail server.
\item Scroll ke bagian catatan server.
\item Lihat daftar catatan yang hanya terkait dengan server tersebut.
\end{enumerate}
\textbf{Hasil yang diharapkan:} catatan yang tampil hanyalah catatan dengan \texttt{serverId} yang sesuai.
\section{Aksi Hapus Data}
Pada daftar server, service, domain, dan catatan, aksi hapus saat ini menggunakan alur dua langkah:
\begin{enumerate}
\item Klik ikon trash.
\item Tombol berubah menjadi ikon check sebagai konfirmasi.
\item Klik ikon check untuk benar-benar menghapus data.
\end{enumerate}
\textbf{Catatan penting:}
\begin{itemize}
\item Hapus server akan menghapus service, domain, dan catatan terkait melalui cascade delete.
\item Hapus service akan menghapus domain terkait melalui cascade delete.
\end{itemize}
\chapter{Kesimpulan dan Saran}
\section*{Kesimpulan}
\addcontentsline{toc}{section}{Kesimpulan}
Minmon berhasil diimplementasikan sebagai aplikasi web untuk inventaris dan monitoring ringan homelab. Sistem ini sudah mencakup autentikasi admin, ringkasan dashboard, CRUD untuk server, service, domain, dan catatan, serta pemeriksaan DNS A record. Dalam konteks penggunaan homelab pribadi dengan beberapa server dan banyak service/domain, aplikasi ini sudah cukup representatif untuk membantu pencatatan aset, dokumentasi operasional, dan validasi domain.
Keunggulan utama implementasi saat ini adalah struktur relasi yang jelas, form relasi berbasis select, ringkasan dashboard yang langsung informatif, serta adanya catatan yang bisa ditampilkan langsung pada halaman detail server. Selain itu, interaksi UI juga sudah dibuat lebih aman melalui delete dua langkah dan urutan list yang stabil.
\section*{Saran}
\addcontentsline{toc}{section}{Saran}
Saran pengembangan untuk tahap berikutnya antara lain:
\begin{itemize}
\item Menambahkan fitur pencarian, filter, dan pagination pada halaman daftar data.
\item Menambahkan histori hasil pemeriksaan DNS agar perubahan status domain dapat dilacak dari waktu ke waktu.
\item Menambahkan multi-role authentication jika aplikasi ingin dipakai lebih dari satu pengguna.
\item Menambahkan dukungan monitoring lain selain DNS A record, misalnya masa berlaku SSL, ping, atau health endpoint HTTP.
\item Menambahkan histori aktivitas agar perubahan data server, service, domain, dan catatan dapat ditelusuri lebih mudah.
\end{itemize}
\end{document}