Document initial Gitea deployment and team access; refs #1
This commit is contained in:
1 parent
28070817c2
commit
da6a369420
12 files changed
+342
-32
No files matched your search
@@ -0,0 +1,283 @@
|
||||
\chapter{Startup Foundation with Gitea}
|
||||
\ChapterLabel{GiteaFoundation}
|
||||
\index{Gitea}\index{SQLite}\index{Docker Compose}\index{Elastic IP}\index{SSH tunnel}
|
||||
|
||||
This chapter records the initial Inviscid work hub on the existing Amazon EC2
|
||||
server. AWS is used in place of the assignment's DigitalOcean deployment.
|
||||
The dated screenshots record completed work; pending items below are not
|
||||
represented as passed. This draft covers Victor's deployment and access setup.
|
||||
|
||||
\section{Student Pack Domain and DNS}
|
||||
Victor submitted school enrollment evidence to GitHub Education on October 12,
|
||||
2026. Academic status was approved that day, but the portal displayed
|
||||
``Awaiting Benefits'' and stated that partner offers would activate after
|
||||
72 hours (Figure~\ref{Figure:GiteaBenefits}). At the October 15 drafting
|
||||
checkpoint, Victor reported that benefits were still unavailable.
|
||||
|
||||
\textbf{Pending:} redeem an eligible Student Pack domain offer; record the
|
||||
provider, eligibility, first-year charge, renewal charge, expiration, and renewal
|
||||
owner; configure the selected Gitea hostname and capture an independent DNS
|
||||
lookup. \texttt{inviscid.net} is a preference, not a registered or verified
|
||||
domain in this record. The selected offer must determine which extension is
|
||||
eligible. The intended DNS A record will point the selected hostname to
|
||||
\texttt{100.49.80.94}. Domain ownership and renewal will be recorded when the
|
||||
offer is redeemed; no registration cost or expiry is invented here.
|
||||
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{figures/gitea/student-pack-approved-awaiting-benefits.png}
|
||||
\caption{October 12: academic status approved, with partner benefits still awaiting activation. This establishes the dependency blocking domain redemption, not a completed registration.}
|
||||
\label{Figure:GiteaBenefits}
|
||||
\end{figure}
|
||||
|
||||
\section{Pinned Gitea Deployment}
|
||||
The existing \texttt{ssw590-group-web} instance runs Ubuntu 26.04 LTS on a
|
||||
\texttt{t3.micro} in \texttt{us-east-1}. The initial resource check recorded
|
||||
908 MiB total memory, 468 MiB available memory, and 3.1 GiB available root disk.
|
||||
Docker Compose reported version 5.6.0. The existing Color Buttons container
|
||||
continued to serve host port 80 while Gitea was initialized privately.
|
||||
|
||||
\begin{tabularx}{\linewidth}{L{3.5cm}Y}
|
||||
\caption{Recorded Gitea Deployment\label{Table:GiteaDeployment}}\\
|
||||
\toprule \textbf{Setting} & \textbf{Value}\\ \midrule
|
||||
Instance & \texttt{i-025a57432604c8d4b}, \texttt{ssw590-group-web}\\
|
||||
Current public address & Elastic IP \texttt{100.49.80.94}\\
|
||||
Private address & \texttt{172.31.19.91}\\
|
||||
Official image & \texttt{docker.gitea.com/gitea:28.1.0}\\
|
||||
Container & \texttt{inviscid-gitea-1}\\
|
||||
Remote working directory & \path{/home/ubuntu/gitea}\\
|
||||
Persistent volume & \texttt{inviscid\_gitea\_data}, mounted at \path{/data}\\
|
||||
Docker network & \texttt{inviscid\_services}\\
|
||||
Restart policy & \texttt{unless-stopped}\\
|
||||
Published backend & \texttt{127.0.0.1:3000:3000}; no public backend mapping\\
|
||||
Temporary public URL setting & \url{http://localhost:3000/}; SSH-tunnel access only\\
|
||||
\bottomrule
|
||||
\end{tabularx}
|
||||
|
||||
The official Docker installation guide supports persistent application storage
|
||||
and SQLite initialization. We pinned a version rather than using a floating
|
||||
\texttt{latest} tag. The recorded repository digest is:
|
||||
\begin{minted}[fontsize=\scriptsize]{text}
|
||||
docker.gitea.com/gitea@sha256:f505a0d3a41323b786e05942fc7a4075e07ae7c169fd9485649aa55ee543a21a
|
||||
\end{minted}
|
||||
|
||||
The non-secret configuration is maintained in
|
||||
\href{https://github.com/byterand/SSW590-DevOps/tree/main/docker/gitea}{the team's versioned deployment directory}.
|
||||
The following file is the initial localhost-only configuration. Its URL settings
|
||||
must be updated for the registered HTTPS hostname before final submission.
|
||||
\inputminted{yaml}{docker/gitea/compose.yaml}
|
||||
|
||||
Victor copied the directory from the Windows workstation to EC2 using
|
||||
\texttt{scp}. In the remote directory, he validated, pulled, and started it:
|
||||
\begin{minted}{bash}
|
||||
cd ~/gitea
|
||||
sudo docker compose config --quiet
|
||||
sudo docker compose pull
|
||||
sudo docker compose up -d
|
||||
sudo docker compose ps
|
||||
sudo docker compose logs --tail=40 gitea
|
||||
\end{minted}
|
||||
Validation returned without an error, the pinned image pulled, and Compose
|
||||
created the volume, network, and container. Startup logs showed Gitea 28.1.0
|
||||
listening internally on port 3000 and preparing its installation page.
|
||||
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{figures/gitea/compose-validation-pull.png}
|
||||
\caption{October 12: successful Compose validation and pull of the pinned official image.}
|
||||
\label{Figure:GiteaPull}
|
||||
\end{figure}
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{figures/gitea/container-startup.png}
|
||||
\caption{October 12: container startup and localhost port mapping. The image exposes an internal SSH port, but no host SSH mapping was published for Gitea.}
|
||||
\label{Figure:GiteaStartup}
|
||||
\end{figure}
|
||||
|
||||
Victor associated the Elastic IP with the same instance, replacing the earlier
|
||||
\texttt{54.221.175.174} address. The containers remained running. SSH and tunnel
|
||||
commands were updated to use the new address; the data and private address did
|
||||
not change.
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{figures/gitea/elastic-ip-association.png}
|
||||
\caption{October 12: Elastic IP 100.49.80.94 associated with the existing instance.}
|
||||
\label{Figure:GiteaElasticIP}
|
||||
\end{figure}
|
||||
|
||||
\section{Database and Persistence}
|
||||
SQLite was selected for the small two-person deployment. It requires no
|
||||
separate database service or network port. The database is at
|
||||
\path{/data/gitea/gitea.db}, within the same persistent named volume that holds
|
||||
application configuration and repository data. The volume exists outside the
|
||||
disposable container layer. Generated configuration, database contents, and
|
||||
secrets are not stored in the Git repository.
|
||||
|
||||
The following checks were executed on October 12:
|
||||
\begin{minted}{bash}
|
||||
sudo docker inspect inviscid-gitea-1 --format '{{range .Mounts}}{{println .Type .Name .Destination}}{{end}}'
|
||||
sudo docker compose exec -T gitea ls -lh /data/gitea/gitea.db
|
||||
sudo docker stats --no-stream
|
||||
free -h
|
||||
df -h /
|
||||
\end{minted}
|
||||
The mount check showed \texttt{inviscid\_gitea\_data} at \path{/data}; the
|
||||
SQLite file existed and was approximately 2.1 MiB. Gitea used approximately
|
||||
187 MiB RAM in that snapshot, with 367 MiB system memory and 2.8 GiB disk
|
||||
available. These are single observations, not load-test results.
|
||||
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{figures/gitea/storage-resources.png}
|
||||
\caption{October 12: named-volume mount, database file, and resource checks. These verify storage configuration, not survival of a container replacement.}
|
||||
\label{Figure:GiteaStorage}
|
||||
\end{figure}
|
||||
|
||||
\textbf{Pending---Payton:} record a repository and issue, replace only the
|
||||
Gitea container without deleting its volume, and show that both remain usable.
|
||||
Include identifiers, exact command, before/after evidence, and conclusion.
|
||||
This required test is distinct from the optional backup/restore exercise.
|
||||
|
||||
\section{HTTPS and Certificate Renewal}
|
||||
\textbf{Pending---Payton:} compare two certificate options and justify one;
|
||||
configure Caddy using the final hostname, persistent certificate state, and
|
||||
private forwarding to \texttt{gitea:3000}; update Gitea's domain and public URL;
|
||||
record issuer, expiry, redirect, renewal automation, and a successful renewal
|
||||
test or dry run. The existing website's host-port-80 mapping must be resolved
|
||||
before Caddy publishes that port. Public HTTPS is not claimed in this draft.
|
||||
|
||||
Initial access used an SSH tunnel from the workstation:
|
||||
\begin{minted}{bash}
|
||||
ssh -i /path/to/your-private-key -o ExitOnForwardFailure=yes -N -L 127.0.0.1:3000:127.0.0.1:3000 ubuntu@100.49.80.94
|
||||
\end{minted}
|
||||
The browser opened \url{http://localhost:3000/}; transport between workstation
|
||||
and server was encrypted by SSH, but this is not hostname-based HTTPS and does
|
||||
not satisfy the final certificate requirement. Each workstation needs its own
|
||||
tunnel. The \texttt{-N} option keeps the connection open without a remote shell.
|
||||
|
||||
\section{Firewall and External Exposure}
|
||||
The attached AWS security group is \texttt{ssw590-web-sg}, identifier
|
||||
\texttt{sg-0a9eb6dcfc906e78b}. The October 15 screenshot records these IPv4 rules:
|
||||
\begin{tabularx}{\linewidth}{L{2cm}L{4cm}Y}
|
||||
\toprule \textbf{TCP port} & \textbf{Source} & \textbf{Purpose}\\ \midrule
|
||||
22 & \texttt{100.8.28.98/32} & Victor's home SSH access\\
|
||||
22 & \texttt{155.246.151.38/32} & Victor's campus source; connection still timed out during the reported attempt\\
|
||||
22 & \texttt{108.35.228.38/32} & Payton's administrative SSH access\\
|
||||
80 & \texttt{0.0.0.0/0} & Existing HTTP website; final proxy redirect/validation behavior pending\\
|
||||
443 & \texttt{0.0.0.0/0} & Permitted for planned Caddy HTTPS; opening a rule does not verify a live HTTPS endpoint\\
|
||||
\bottomrule
|
||||
\end{tabularx}
|
||||
No public IPv6 address was shown in the supplied EC2 summary. The provided
|
||||
inbound-rule screenshot contains IPv4 rules only. Outbound rules, any other
|
||||
attached security groups, and final external exposure require Payton's review.
|
||||
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{figures/gitea/security-group-team-access.png}
|
||||
\caption{October 15: saved security-group rules, including Payton's source-specific SSH rule. This is configuration evidence, not an external port scan.}
|
||||
\label{Figure:GiteaFirewall}
|
||||
\end{figure}
|
||||
|
||||
During an October 13 campus connection attempt, SSH timed out. Victor's public
|
||||
IP had changed from the home address; a campus-specific rule was added, but
|
||||
that attempt still failed. Campus filtering was considered but not established.
|
||||
On October 15 Victor reported successful SSH access; the exact network for
|
||||
that successful session was not recorded. Rules should track current approved
|
||||
source addresses rather than permitting public administrative SSH.
|
||||
|
||||
\textbf{Pending---Payton:} externally test 443, 80, restricted administrative
|
||||
SSH, backend 3000, and database exposure; record source, time, expected and
|
||||
actual results, and corrections. Document outbound rules and final Docker
|
||||
publishing. HTTPS encrypts an allowed connection; it does not close unrelated
|
||||
ports. Local HTTP 200 and loopback mappings do not independently prove public
|
||||
firewall behavior.
|
||||
|
||||
\section{Startup Team Workflow}
|
||||
Victor initialized Gitea with site title \texttt{Inviscid}, created the
|
||||
\texttt{victor} administrator, and disabled public self-registration. A separate
|
||||
\texttt{payton} regular account was created with a temporary password and
|
||||
mandatory password change. A shared Gitea account is not used.
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{figures/gitea/member-accounts.png}
|
||||
\caption{October 12: separate victor and payton accounts; victor has the site-administrator role. This does not yet establish organization permissions or successful Payton login.}
|
||||
\label{Figure:GiteaMembers}
|
||||
\end{figure}
|
||||
|
||||
On October 15 Victor added Payton's public SSH key to the remote Ubuntu
|
||||
account's authorized keys, preserving the existing key and using directory/file
|
||||
permissions 700/600. His source IP was allowed separately. Victor subsequently
|
||||
reported that Payton connected over SSH successfully; Gitea login testing was
|
||||
still underway. Both currently use the Linux \texttt{ubuntu} account with
|
||||
separate keys, so Linux account-level attribution remains shared.
|
||||
|
||||
\textbf{Pending---Payton and both authors:} confirm Payton's Gitea login and
|
||||
password change; create the organization, product repository, README, member
|
||||
roles, and five actionable issues. Link the organization and repository here.
|
||||
Then each author completes an issue-linked branch and PR, receives peer review,
|
||||
merges, and closes the issue. Capture both complete cycles. The initial GitHub
|
||||
push is not counted as a reviewed Gitea PR.
|
||||
|
||||
\section{Architecture and Operation}
|
||||
The current private initialization path is shown in
|
||||
Figure~\ref{Figure:GiteaInitialPath}. Payton will add a final deployment diagram
|
||||
showing browser HTTPS to Caddy and private forwarding to Gitea.
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\fbox{\parbox{0.92\linewidth}{\centering
|
||||
Workstation browser: localhost:3000\\
|
||||
$\downarrow$ local SSH tunnel\\
|
||||
AWS security group: approved source to TCP 22\\
|
||||
$\downarrow$ EC2: 100.49.80.94\\
|
||||
EC2 loopback:3000 to Gitea container:3000\\
|
||||
$\downarrow$ persistent named volume\\
|
||||
\texttt{inviscid\_gitea\_data}: repositories, SQLite, configuration}}
|
||||
\caption{Initial SSH-tunnel access path. Caddy and hostname-based HTTPS are not yet verified.}
|
||||
\label{Figure:GiteaInitialPath}
|
||||
\end{figure}
|
||||
|
||||
The completed local check \texttt{curl -I http://127.0.0.1:3000/} returned
|
||||
HTTP 200. Logs, container status, and the image digest were collected without
|
||||
printing configuration secrets.
|
||||
\begin{figure}[htbp]
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{figures/gitea/http-image-digest.png}
|
||||
\caption{October 12: local HTTP 200 and exact image digest.}
|
||||
\label{Figure:GiteaHTTP}
|
||||
\end{figure}
|
||||
|
||||
The following are operational commands, not additional claimed test results:
|
||||
\begin{minted}{bash}
|
||||
cd ~/gitea
|
||||
sudo docker compose ps
|
||||
sudo docker compose logs --tail=40 gitea
|
||||
sudo docker compose restart gitea
|
||||
\end{minted}
|
||||
Closing a workstation tunnel does not stop Gitea on EC2. Reconnect the tunnel
|
||||
for browser access. Container replacement should retain the named volume;
|
||||
never delete that volume as part of the persistence check. Before destructive
|
||||
cleanup, retain needed data. Victor owns the class AWS environment; compute,
|
||||
EBS, and public IPv4 are billable and covered by budget alerts rather than a
|
||||
spending cap. End-of-course cleanup must include the instance, unneeded storage,
|
||||
and release of the Elastic IP; stopping the instance alone is not full cleanup.
|
||||
|
||||
\section{Manual Quality and Controls}
|
||||
This revision adds the Gitea chapter, updates the Hosts inventory and Elastic IP
|
||||
cleanup notes, and adds Gitea account and SSH-key handling hints to the Passwords
|
||||
register. No passwords, private keys, database contents, or generated
|
||||
\texttt{app.ini} are included. Existing security policies are distinguished
|
||||
from observed deployment facts where necessary. Material AI help is recorded
|
||||
in \ChapterRef{AIPromptLog}. The linked history entry identifies both table
|
||||
updates. Optional backup/restore extra credit is outside this draft's scope.
|
||||
|
||||
\textbf{Pending before submission:} finish all pending sections, update DNS
|
||||
and final Compose/proxy configuration, complete the required team workflow,
|
||||
verify external exposure and renewal, compile the combined PDF, inspect its
|
||||
pages and links, and submit only the PDF. No deadline time was supplied for
|
||||
the professor's extension to Thursday, October 15, 2026; check Canvas.
|
||||
|
||||
\paragraph{Technical references.}
|
||||
\href{https://docs.gitea.com/installation/install-with-docker/}{Gitea Docker installation};
|
||||
\href{https://docs.gitea.com/administration/config-cheat-sheet/}{Gitea configuration};
|
||||
\href{https://education.github.com/pack}{GitHub Student Developer Pack};
|
||||
\href{https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html}{AWS Elastic IP documentation}.
|
||||
Reference in new issue
Block a user