Refine portfolio design and screenshot layouts

This commit is contained in:
Keith Casko
2026-06-20 22:45:38 -04:00
parent 6bfa37f727
commit 596c8add21
2 changed files with 743 additions and 513 deletions
+184 -168
View File
@@ -3,218 +3,234 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ByteGeist Cloud</title> <meta name="description" content="ByteGeist is Keith Casko's self-hosted infrastructure lab and engineering case study." />
<title>ByteGeist — Self-hosted infrastructure</title>
<link rel="icon" href="assets/images/bytegeist-logo.png" />
<link rel="stylesheet" href="style.css" /> <link rel="stylesheet" href="style.css" />
</head> </head>
<body> <body>
<header class="site-header"> <header class="site-header">
<a class="brand" href="#"> <a class="brand" href="#top" aria-label="ByteGeist home">
<img src="assets/images/bytegeist-logo.png" alt="ByteGeist logo" /> <img src="assets/images/bytegeist-logo.png" alt="" />
<span>ByteGeist</span> <span>ByteGeist</span>
</a> </a>
<nav> <nav aria-label="Primary navigation">
<a href="#architecture">Architecture</a> <a href="#architecture">Architecture</a>
<a href="#operations">Operations</a> <a href="#systems">Systems</a>
<a href="#security">Security</a> <a href="#lessons">Lessons</a>
<a href="#development">Development</a>
<a href="#platform">Platform</a>
<a href="#recovery">Recovery</a>
</nav> </nav>
<a class="nav-button" href="https://wiki.casko.dev">Docs</a> <a class="text-link header-link" href="https://wiki.casko.dev">Read the docs <span>↗</span></a>
</header> </header>
<main> <main id="top">
<section class="hero"> <section class="hero">
<div class="hero-copy"> <div class="hero-copy">
<p class="eyebrow">Self-Hosted Infrastructure Platform</p> <p class="kicker"><span></span> Home lab / ongoing project</p>
<h1>Infrastructure, security, monitoring, and automation <span>built from scratch.</span></h1> <h1>A production-minded cloud, running on my own hardware.</h1>
<p> <p class="hero-intro">
ByteGeist Cloud is a self-hosted infrastructure platform built on Ubuntu, Docker, ByteGeist is where I test infrastructure decisions for real: identity, observability,
Authentik, Grafana, Loki, Prometheus, CrowdSec, Gitea, and Woodpecker CI. deployments, security, and recovery. It currently runs 26 Docker containers on Ubuntu.
</p> </p>
<div class="actions"> <div class="actions">
<a href="#architecture" class="button primary">Explore Architecture</a> <a href="#architecture" class="button primary">See how it works</a>
<a href="https://git.casko.dev" class="button secondary">View Git Server</a> <a href="https://git.casko.dev" class="text-link">Browse the Git server <span>↗</span></a>
</div> </div>
</div> </div>
<div class="hero-art"> <figure class="hero-visual">
<img src="assets/images/bytegeist-logo.png" alt="ByteGeist cyber ghost logo" /> <img src="assets/images/portfolio-grafana-operations.png" alt="ByteGeist operations dashboard in Grafana" />
</div> <figcaption>
<span>Live operations view</span>
Grafana / Prometheus / cAdvisor
</figcaption>
</figure>
</section> </section>
<section class="stats"> <section class="project-facts" aria-label="Project facts">
<div><strong>26</strong><span>Containers</span></div> <div><span>01</span><strong>26 containers</strong><small>deployed with Compose</small></div>
<div><strong>20+</strong><span>Services</span></div> <div><span>02</span><strong>Central identity</strong><small>SSO and 2FA via Authentik</small></div>
<div><strong>11</strong><span>Protected Apps</span></div> <div><span>03</span><strong>Full observability</strong><small>metrics, logs, and uptime</small></div>
<div><strong>SSO</strong><span>Authentik</span></div> <div><span>04</span><strong>Documented recovery</strong><small>tested restore procedures</small></div>
<div><strong>CI/CD</strong><span>Woodpecker</span></div>
</section> </section>
<section id="architecture" class="split-section"> <section id="architecture" class="architecture section-rule">
<div class="panel large"> <div class="section-heading">
<p class="eyebrow">Architecture Overview</p> <p class="section-index">01 / Architecture</p>
<h2>Designed like a small production platform.</h2> <div>
<h2>One server, treated like a platform.</h2>
<p> <p>
Traffic flows through Nginx Proxy Manager, access is controlled through Authentik, Public traffic terminates at Nginx Proxy Manager. Authentik handles identity before
and the environment is monitored, logged, secured, backed up, and documented. requests reach protected services. Metrics, logs, CI, and backups remain separate
concerns, so each can fail or change without taking the whole stack with it.
</p> </p>
<img src="assets/images/bytegeist-architecture.png" alt="ByteGeist architecture diagram" /> </div>
</div> </div>
<div class="panel about"> <figure class="architecture-figure">
<p class="eyebrow">About ByteGeist</p> <img src="assets/images/bytegeist-architecture.png" alt="Detailed ByteGeist infrastructure architecture diagram" />
<h2>Built to prove real infrastructure skills.</h2> <figcaption>Current architecture — updated as services are added or retired.</figcaption>
</figure>
<div class="principles">
<article>
<span>Access</span>
<h3>Authenticate once</h3>
<p>OIDC where supported; forward auth for services that do not speak it natively.</p>
</article>
<article>
<span>Operations</span>
<h3>Make failures visible</h3>
<p>Host and container metrics, centralized logs, and independent uptime checks.</p>
</article>
<article>
<span>Recovery</span>
<h3>Assume the host is replaceable</h3>
<p>Configuration lives in Git. Persistent data is backed up with rebuild notes.</p>
</article>
</div>
</section>
<section id="systems" class="systems section-rule">
<div class="section-heading compact">
<p class="section-index">02 / Selected systems</p>
<div>
<h2>The parts I spend time on.</h2>
<p>Not a catalog of logos—a record of what is running, why it exists, and what I learned building it.</p>
</div>
</div>
<article class="system-story">
<div class="story-copy">
<p class="story-number">01</p>
<p class="story-label">Observability</p>
<h3>Useful signals before pretty dashboards.</h3>
<p>
Prometheus collects host and container metrics while Loki receives logs through
Grafana Alloy. The dashboards answer practical questions: what is down, what changed,
and which container is consuming the host.
</p>
<ul> <ul>
<li>Centralized SSO and 2FA</li> <li>Grafana</li><li>Prometheus</li><li>Loki</li><li>Alloy</li>
<li>Monitoring and log aggregation</li>
<li>Automated CI/CD pipelines</li>
<li>Threat detection and response</li>
<li>Backups and disaster recovery</li>
<li>Technical documentation</li>
</ul> </ul>
</div> </div>
</section> <div class="story-images">
<img src="assets/images/portfolio-grafana-operations.png" alt="Grafana infrastructure metrics dashboard" />
<section id="operations" class="section"> <img src="assets/images/portfolio-grafana-logs.png" alt="Centralized container logs in Grafana" />
<p class="eyebrow">Operations</p>
<h2>Monitoring & Logging</h2>
<div class="card-grid two">
<article class="card">
<img src="assets/images/portfolio-grafana-operations.png" alt="Grafana operations dashboard" />
<h3>Infrastructure Monitoring</h3>
<p>Grafana dashboards show uptime, CPU, memory, disk, container metrics, and system health.</p>
</article>
<article class="card">
<img src="assets/images/portfolio-grafana-logs.png" alt="Grafana logs dashboard" />
<h3>Centralized Logging</h3>
<p>Loki and Grafana provide searchable logs for containers and infrastructure troubleshooting.</p>
</article>
</div> </div>
</section>
<section id="security" class="section">
<p class="eyebrow">Security</p>
<h2>Identity & Threat Protection</h2>
<div class="card-grid two">
<article class="card">
<img src="assets/images/portfolio-authentik-applications.png" alt="Authentik application portal" />
<h3>Centralized Identity</h3>
<p>Authentik provides SSO, OAuth2, OIDC, Forward Auth, access control, and 2FA.</p>
</article> </article>
<article class="card"> <article class="system-story reverse">
<img src="assets/images/portfolio-crowdsec-decisions.png" alt="CrowdSec decisions list" /> <div class="story-copy">
<h3>Threat Detection & Response</h3> <p class="story-number">02</p>
<p>CrowdSec detects malicious SSH activity and creates firewall decisions to block attackers.</p> <p class="story-label">Identity & security</p>
</article> <h3>One identity layer, fewer exposed edges.</h3>
</div>
</section>
<section id="development" class="section">
<p class="eyebrow">Development</p>
<h2>Git Hosting & CI/CD</h2>
<div class="card-grid two">
<article class="card">
<img src="assets/images/portfolio-gitea-dashboard.png" alt="Gitea dashboard" />
<h3>Self-Hosted Git</h3>
<p>Gitea hosts infrastructure code, documentation, project files, and portfolio development.</p>
</article>
<article class="card">
<img src="assets/images/portfolio-woodpecker-pipeline.png" alt="Woodpecker successful pipeline" />
<h3>CI/CD Automation</h3>
<p>Woodpecker runs automated pipelines connected to Gitea repositories.</p>
</article>
</div>
</section>
<section id="platform" class="section">
<p class="eyebrow">Platform</p>
<h2>Service Portal</h2>
<div class="card-grid two">
<article class="card">
<img src="assets/images/portfolio-cloud-dashboard-overview.png" alt="Dashy overview" />
<h3>Operations Portal</h3>
<p>Dashy provides quick access to infrastructure, observability, and development services.</p>
</article>
<article class="card">
<img src="assets/images/portfolio-cloud-dashboard-services.png" alt="Dashy services" />
<h3>Service Catalog</h3>
<p>Organized access to security tools, utilities, file management, and public sites.</p>
</article>
</div>
</section>
<section id="recovery" class="section">
<p class="eyebrow">Recovery</p>
<h2>Documentation & Disaster Recovery</h2>
<div class="feature-card">
<img src="assets/images/portfolio-wiki-disaster-recovery.png" alt="Disaster recovery documentation" />
<div>
<h3>Recovery Planning</h3>
<p> <p>
ByteGeist includes documented restore procedures, backup validation, service inventory, Authentik provides SSO, OIDC, forward auth, and 2FA across eleven applications.
DNS information, recovery priorities, and full environment rebuild planning. CrowdSec watches hostile traffic and creates firewall decisions alongside key-only SSH,
UFW, and TLS.
</p> </p>
<ul>
<li>Authentik</li><li>CrowdSec</li><li>UFW</li><li>Let's Encrypt</li>
</ul>
</div> </div>
<div class="story-images">
<img src="assets/images/portfolio-authentik-applications.png" alt="Applications protected by Authentik" />
<img src="assets/images/portfolio-crowdsec-decisions.png" alt="CrowdSec security decisions" />
</div>
</article>
<article class="system-story">
<div class="story-copy">
<p class="story-number">03</p>
<p class="story-label">Development</p>
<h3>Code and delivery stay in-house.</h3>
<p>
Gitea stores infrastructure code and documentation. Woodpecker runs repository-linked
pipelines, including the build and deployment path for this site.
</p>
<ul>
<li>Gitea</li><li>Woodpecker CI</li><li>Docker</li><li>Git</li>
</ul>
</div>
<div class="story-images">
<img src="assets/images/portfolio-gitea-dashboard.png" alt="Self-hosted Gitea dashboard" />
<img src="assets/images/portfolio-woodpecker-pipeline.png" alt="Successful Woodpecker CI pipeline" />
</div>
</article>
<article class="system-story reverse">
<div class="story-copy">
<p class="story-number">04</p>
<p class="story-label">Platform & recovery</p>
<h3>The boring work is part of the system.</h3>
<p>
Dashy keeps service access legible. The wiki records inventory, DNS, restore order,
backup validation, and the steps required to rebuild the environment from a clean host.
</p>
<ul>
<li>Dashy</li><li>Wiki.js</li><li>Restic</li><li>Runbooks</li>
</ul>
</div>
<div class="story-images">
<img src="assets/images/portfolio-cloud-dashboard-overview.png" alt="ByteGeist internal service portal" />
<img src="assets/images/portfolio-wiki-disaster-recovery.png" alt="ByteGeist disaster recovery runbook" />
</div>
</article>
</section>
<section id="lessons" class="lessons section-rule">
<div class="section-heading compact">
<p class="section-index">03 / Lessons</p>
<div>
<h2>What actually took work.</h2>
</div>
</div>
<div class="lesson-list">
<article>
<span>01</span>
<h3>OIDC is mostly careful bookkeeping.</h3>
<p>Redirect URIs, claims, group mapping, and user provisioning all need to agree across both ends.</p>
</article>
<article>
<span>02</span>
<h3>Backups are unfinished until restore is documented.</h3>
<p>I track data location, dependencies, restore order, DNS, certificates, and validation—not just archive jobs.</p>
</article>
<article>
<span>03</span>
<h3>Observability has to support a decision.</h3>
<p>A smaller dashboard that explains an incident is more useful than a wall of metrics nobody checks.</p>
</article>
<article>
<span>04</span>
<h3>Convenience can weaken the boundary.</h3>
<p>Every exposed service has a cost. SSO, least privilege, and fewer public endpoints keep that cost explicit.</p>
</article>
</div> </div>
</section> </section>
<section class="section challenges"> <section class="closing">
<p class="eyebrow">Technical Challenges</p> <p class="section-index">Project notes</p>
<h2>Problems Solved</h2> <h2>This environment is still changing.</h2>
<div class="challenge-grid"> <p>
<div> I use ByteGeist to practice the parts of infrastructure work that tutorials tend to skip:
<h3>OIDC Integration</h3> upgrades, failure modes, access policy, noisy logs, and recovery.
<p>Resolved redirect URI mismatches, user provisioning, and authorization issues.</p> </p>
</div> <a class="button primary" href="https://wiki.casko.dev">Open the documentation <span>↗</span></a>
<div>
<h3>Forward Auth</h3>
<p>Integrated Authentik Forward Auth with reverse proxy protected services.</p>
</div>
<div>
<h3>Observability</h3>
<p>Built centralized metrics and logging using Grafana, Prometheus, Loki, and Alloy.</p>
</div>
<div>
<h3>Security Hardening</h3>
<p>Implemented SSH key-only login, Fail2Ban, CrowdSec, UFW, TLS, and SSO.</p>
</div>
</div>
</section>
<section class="skills">
<h2>Core Skills Demonstrated</h2>
<div class="skills-list">
<span>Linux Administration</span>
<span>Docker & Compose</span>
<span>Reverse Proxies</span>
<span>Networking</span>
<span>TLS / SSL</span>
<span>DNS Management</span>
<span>Identity Management</span>
<span>SSO / OAuth2 / OIDC</span>
<span>Monitoring & Observability</span>
<span>Centralized Logging</span>
<span>CI/CD Automation</span>
<span>Security Hardening</span>
<span>Threat Detection & Response</span>
<span>Backup Strategy</span>
<span>Disaster Recovery</span>
<span>Technical Documentation</span>
</div>
</section> </section>
</main> </main>
<footer> <footer>
<span>ByteGeist Cloud</span> <a class="brand" href="#top">
<p>Built and maintained by Keith Casko</p> <img src="assets/images/bytegeist-logo.png" alt="" />
<span>ByteGeist</span>
</a>
<p>A self-hosted infrastructure project by Keith Casko.</p>
<p>Built with plain HTML and CSS.</p>
</footer> </footer>
</body> </body>
</html> </html>
+551 -337
View File
File diff suppressed because it is too large Load Diff