Set up Gitea, etc.

This commit is contained in:
Magdolna Nagy
2026-09-30 19:53:11 -04:00
parent a05bdd9454
commit baf66d8d28
7 changed files with 492 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
Gitea Overleaf evidence package
Files:
- giteaStartup.tex
Chapter fragment to add to the group's main Overleaf document with:
\input{giteaStartup}
Screenshots:
- gitea-persistence-repository.png
persistence-test repository after replacement
- gitea-persistence-issue-1.png
persistence verification issue #1
- gitea-admin-activity.png
Gitea activity/repository view
- gitea-pr-issue-1-merged.png
merged pull request for issue #1
- gitea-pr-issue-2-merged.png
merged pull request for issue #2
No passwords are included.
Binary file not shown.

After

Width:  |  Height:  |  Size: 371 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

+472
View File
@@ -0,0 +1,472 @@
% Insert this file into the group report with:
% \input{giteaStartup}
%
% Required packages in the main document:
% \usepackage{graphicx}
% \usepackage{minted}
% \usepackage{hyperref}
%
% This chapter intentionally does not use minted's caption option. Captions
% are written as ordinary LaTeX text so it remains compatible with the
% minted configuration already used by the group report.
\chapter{Startup Foundation with Gitea}
\section{Overview}
The startup's initial operational work hub was deployed on a DigitalOcean
Droplet using Gitea. The deployment provides a private Git service for the
team, including repositories, issues, pull requests, and collaborative code
review.
The public Git service is available at:
\begin{center}
\url{https://git.ssw590.tech}
\end{center}
The domain used for the service is \texttt{ssw590.tech}, and the Gitea
hostname is \texttt{git.ssw590.tech}. The service runs on an Ubuntu
DigitalOcean Droplet with Docker Compose. Gitea uses the official
\texttt{gitea/gitea} container image pinned to version \texttt{1.27.3}.
\section{Domain and GitHub Student Developer Pack}
The domain \texttt{ssw590.tech} was obtained through the GitHub Student
Developer Pack using Name.com. GitHub's current Student Developer Pack
lists Name.com as providing a free domain from a selection of extensions,
and separately lists the .TECH offer as one standard .TECH domain free for
one year. Thus, the initial registration used for this project was free
under the student offer.
The project domain is:
\begin{itemize}
\item Domain: \texttt{ssw590.tech}
\item Registrar: Name.com
\item Gitea hostname: \texttt{git.ssw590.tech}
\item Initial student-offer term: one year
\item Automatic renewal date shown by Name.com: September 30, 2027
\end{itemize}
The renewal price is not a fixed GitHub Student Developer Pack price.
Name.com states that renewals are charged at the then-current renewal fee.
The automatic-renewal setting is enabled for this domain. This means the
team must maintain a valid payment method if the domain is to remain active
after the student-offer term.
\section{DNS Configuration}
The DNS record for the Gitea service points the hostname
\texttt{git.ssw590.tech} to the DigitalOcean Droplet's public IPv4 address:
\begin{center}
\texttt{157.230.10.81}
\end{center}
The hostname was verified independently by accessing it from outside the
Droplet. The HTTPS request succeeded, demonstrating that the hostname
resolved to the deployed service and that the service was reachable through
the public Internet.
A command-line DNS lookup can also be recorded in the final submission:
\begin{minted}{bash}
dig +short git.ssw590.tech A
\end{minted}
The expected result is the Droplet's public IPv4 address.
\section{DigitalOcean Droplet and Docker}
The DigitalOcean Droplet runs Ubuntu and was configured for password-based
SSH authentication. The Droplet was accessed with:
\begin{minted}{bash}
ssh root@157.230.10.81
\end{minted}
Docker Engine and Docker Compose were installed on the Droplet. The final
Gitea deployment was managed from:
\begin{minted}{bash}
cd ~/gitea
\end{minted}
The Gitea Compose configuration pins the official image to version
\texttt{1.27.3} rather than using an unversioned \texttt{latest} tag.
\begin{minted}{yaml}
services:
gitea:
image: gitea/gitea:1.27.3
container_name: gitea
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- ./data/gitea:/data
networks:
- gitea
networks:
gitea:
driver: bridge
\end{minted}
The official image source is the Gitea container repository:
\url{https://hub.docker.com/r/gitea/gitea}.
The image version was verified with:
\begin{minted}{bash}
docker compose ps
\end{minted}
The resulting service showed:
\begin{minted}{text}
gitea/gitea:1.27.3
\end{minted}
\section{SQLite Database}
SQLite was selected for the Gitea database because the deployment is a
small startup work hub and does not require a separate database service for
this assignment.
The Gitea configuration contains:
\begin{minted}{text}
DB_TYPE = sqlite3
PATH = /data/gitea/gitea.db
\end{minted}
The database file exists inside the persistent Docker bind mount. It was
verified on the Droplet with:
\begin{minted}{bash}
ls -lh ~/gitea/data/gitea/gitea/gitea.db
\end{minted}
The file was approximately 2.1 MB at the time of verification.
The corresponding file inside the container was also verified:
\begin{minted}{bash}
docker exec gitea ls -lh /data/gitea/gitea.db
\end{minted}
\section{Persistent Storage}
The Docker Compose configuration maps the host directory
\texttt{./data/gitea} to \texttt{/data} inside the Gitea container:
\begin{minted}{yaml}
volumes:
- ./data/gitea:/data
\end{minted}
This is important because Gitea stores its database, repositories, SSH
configuration, attachments, package data, indexes, and other application
state below \texttt{/data}. The database was observed on the host at:
\begin{minted}{text}
/root/gitea/data/gitea/gitea/gitea.db
\end{minted}
The mount itself was inspected with:
\begin{minted}{bash}
docker inspect gitea --format '{{json .Mounts}}'
\end{minted}
The result showed the host path
\texttt{/root/gitea/data/gitea} mounted read/write at \texttt{/data}.
\section{Container Replacement and Persistence Test}
Persistence was explicitly tested by recording the existing container,
recreating it, and then checking that Gitea data remained available.
Before replacement, the container identity was recorded with:
\begin{minted}{bash}
docker inspect gitea --format '{{.Id}}'
\end{minted}
The persistent mount was also recorded with:
\begin{minted}{bash}
docker inspect gitea --format '{{json .Mounts}}'
\end{minted}
The Gitea service was then force-recreated:
\begin{minted}{bash}
docker compose up -d --force-recreate gitea
\end{minted}
After the replacement, the running services were verified with:
\begin{minted}{bash}
docker compose ps
\end{minted}
The new container continued to use the same host-backed data directory.
The SQLite database remained present:
\begin{minted}{bash}
ls -lh ~/gitea/data/gitea/gitea/gitea.db
\end{minted}
The Gitea repository and issue used for the persistence test also remained
available after the replacement. This demonstrates that the application
state was stored in the persistent volume rather than only in the
container's writable layer.
\section{Persistence Evidence}
Figure~\ref{fig:gitea-persistence-repository} shows the
\texttt{persistence-test} repository after the container replacement.
\begin{figure}[htbp]
\centering
\includegraphics[width=0.90\textwidth]{gitea-persistence-repository.png}
\caption{Gitea persistence-test repository after container replacement}
\label{fig:gitea-persistence-repository}
\end{figure}
Figure~\ref{fig:gitea-persistence-issue} shows issue \#1 from the same
repository after the replacement.
\begin{figure}[htbp]
\centering
\includegraphics[width=0.90\textwidth]{gitea-persistence-issue-1.png}
\caption{Persistence verification issue \#1 after container replacement}
\label{fig:gitea-persistence-issue}
\end{figure}
\section{Startup Repository and Team Collaboration}
The startup repository used for the development workflow is
\texttt{ssw590-startup}. No separate Gitea organization was required for
the assignment, so the repository itself is used as the team's shared
workspace.
Team members were added to the Gitea project using their individual
accounts. The usernames used for the team accounts are:
\begin{itemize}
\item \texttt{mfriedma1}
\item \texttt{alexn41}
\item \texttt{so.stoeckel}
\end{itemize}
Passwords are intentionally not included in the report.
The repository README was completed, and five issues were created and
assigned as part of the team's issue-driven development workflow.
\section{Issue and Pull Request Workflow}
The first implementation task was tracked as issue \#1,
``Implement product landing page.'' A feature branch named
\texttt{feature/issue-1-landing-page} was used for the implementation.
The work was submitted as a pull request and reviewed before being merged
into \texttt{main}.
Figure~\ref{fig:gitea-pr-issue-1} shows the merged pull request for issue
\#1. The screenshot records the assignment, commit, review comment,
merge, and deletion of the feature branch.
\begin{figure}[htbp]
\centering
\includegraphics[width=0.90\textwidth]{gitea-pr-issue-1-merged.png}
\caption{Merged pull request implementing issue \#1}
\label{fig:gitea-pr-issue-1}
\end{figure}
The second implementation task was tracked as issue \#2 and used the
feature branch \texttt{feature/issue-2-tests}. The pull request added the
repository validation tests and was merged into \texttt{main}.
Figure~\ref{fig:gitea-pr-issue-2} shows the completed merge.
\begin{figure}[htbp]
\centering
\includegraphics[width=0.90\textwidth]{gitea-pr-issue-2-merged.png}
\caption{Merged pull request for issue \#2 repository validation tests}
\label{fig:gitea-pr-issue-2}
\end{figure}
Figure~\ref{fig:gitea-activity} shows the Gitea activity view containing
the repository and issue activity.
\begin{figure}[htbp]
\centering
\includegraphics[width=0.90\textwidth]{gitea-admin-activity.png}
\caption{Gitea repository and issue activity}
\label{fig:gitea-activity}
\end{figure}
\section{HTTPS with Caddy and Let's Encrypt}
Gitea is not directly exposed to the public Internet on port 3000 in the
final deployment. A Caddy reverse proxy is used in front of Gitea.
The final service layout is:
\begin{center}
\texttt{Internet -> Caddy :443 -> Gitea :3000}
\end{center}
Caddy publishes ports 80 and 443 on the Droplet while Gitea's port 3000 is
kept internal to the Docker network. The Gitea container therefore shows
port 3000 as an internal container port rather than as a host-published
port.
The current service state was verified with:
\begin{minted}{bash}
docker compose ps
\end{minted}
The output showed Caddy publishing ports 80 and 443 and Gitea exposing
port 3000 only to the Docker network.
Gitea's public URL was configured as:
\begin{minted}{text}
DOMAIN = git.ssw590.tech
ROOT_URL = https://git.ssw590.tech
\end{minted}
\section{Let's Encrypt Certificate Verification}
Caddy automatically obtained a Let's Encrypt certificate for
\texttt{git.ssw590.tech}. The Caddy log showed successful ACME
authorization and certificate issuance.
The live HTTPS service was verified externally with:
\begin{minted}{bash}
curl -4 -I https://git.ssw590.tech
\end{minted}
The response was HTTP/2 200.
Plain HTTP was also tested:
\begin{minted}{bash}
curl -4 -I http://git.ssw590.tech
\end{minted}
The response was:
\begin{minted}{text}
HTTP/1.1 308 Permanent Redirect
Location: https://git.ssw590.tech/
\end{minted}
This demonstrates that HTTP requests are redirected to HTTPS.
The certificate itself was inspected with:
\begin{minted}{bash}
echo | openssl s_client \
-connect git.ssw590.tech:443 \
-servername git.ssw590.tech 2>/dev/null \
| openssl x509 -noout -issuer -subject -dates
\end{minted}
The observed certificate information was:
\begin{minted}{text}
issuer=... Let's Encrypt ...
subject=CN = git.ssw590.tech
notBefore=Sep 30 17:50:34 2026 GMT
notAfter=Dec 29 17:50:33 2026 GMT
\end{minted}
Caddy's automatic certificate management is also responsible for renewal,
so a separate manual renewal job is not required.
\section{Firewall Configuration}
The DigitalOcean Cloud Firewall was configured to allow the ports required
by the deployment:
\begin{center}
\begin{tabular}{lll}
\textbf{Protocol} & \textbf{Port} & \textbf{Source} \\
TCP & 22 & All IPv4 \\
TCP & 80 & All IPv4 and All IPv6 \\
TCP & 443 & All IPv4 and All IPv6
\end{tabular}
\end{center}
Port 80 is required for normal HTTP access and HTTP-to-HTTPS redirection,
while port 443 provides the public HTTPS service. SSH on port 22 is used
for administration.
Port 3000 is not opened in the DigitalOcean firewall. An external
connection test to the public address on port 3000 timed out, while
external access to ports 80 and 443 succeeded. This confirms that Gitea
is reached through Caddy rather than directly through its application port.
\section{Restart Behavior}
The Compose service uses:
\begin{minted}{yaml}
restart: unless-stopped
\end{minted}
This instructs Docker to restart Gitea after an unexpected container or
Docker daemon restart, while still allowing an intentional manual stop to
remain stopped.
The deployment can therefore be brought back up with:
\begin{minted}{bash}
docker compose up -d
\end{minted}
and its state checked with:
\begin{minted}{bash}
docker compose ps
\end{minted}
\section{Deployment Summary}
The completed startup work hub has the following architecture:
\begin{enumerate}
\item \texttt{ssw590.tech} was registered using the GitHub Student
Developer Pack offer through Name.com.
\item \texttt{git.ssw590.tech} was configured to resolve to the
DigitalOcean Droplet.
\item Gitea \texttt{1.27.3} was deployed using the official
\texttt{gitea/gitea} image.
\item SQLite was selected for the Gitea database.
\item Gitea application data was stored in the persistent
\texttt{./data/gitea:/data} bind mount.
\item Container replacement was tested and the repository and issue
data persisted.
\item The \texttt{ssw590-startup} repository was created for team
collaboration.
\item Team members were added and issues were assigned.
\item Pull requests were used to review and merge work into
\texttt{main}.
\item Caddy was placed in front of Gitea as a reverse proxy.
\item Let's Encrypt provided the live TLS certificate for
\texttt{git.ssw590.tech}.
\item HTTP was redirected to HTTPS.
\item Port 3000 remained closed to external clients.
\end{enumerate}
The resulting deployment provides the team with a persistent,
version-pinned, HTTPS-protected Git service suitable for the startup's
initial development workflow.