my-homelab-configs/apps/website/homelab-tree.php

262 lines
12 KiB
PHP

<?php
require_once __DIR__ . '/lang_helper.php';
$blogHref = 'blog.php?lang=' . urlencode($lang);
?>
<!DOCTYPE html>
<html lang="<?php echo $lang; ?>">
<head>
<meta charset="UTF-8">
<title><?php echo $text['tree_title']; ?> - <?php echo $text['name']; ?></title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<nav class="top-nav">
<div class="nav-left">Juvenal Diaz</div>
<div class="nav-right">
<?php foreach ($availableLangs as $code): ?>
<a href="homelab-tree.php?lang=<?php echo $code; ?>"><?php echo strtoupper($code); ?></a>
<?php endforeach; ?>
|
<a href="index.php?lang=<?php echo $lang; ?>"
data-translate data-key="nav_home"
data-en="<?php echo htmlspecialchars($en['nav_home']); ?>">
<?php echo $text['nav_home']; ?>
</a>
<a href="cv.php?lang=<?php echo $lang; ?>"
data-translate data-key="nav_cv"
data-en="<?php echo htmlspecialchars($en['nav_cv']); ?>">
<?php echo $text['nav_cv']; ?>
</a>
<a href="blog.php?lang=<?php echo $lang; ?>"
data-translate data-key="nav_blog"
data-en="<?php echo htmlspecialchars($en['nav_blog']); ?>">
<?php echo $text['nav_blog']; ?>
</a>
<a href="demos.php?lang=<?php echo $lang; ?>"
data-translate data-key="nav_demos"
data-en="<?php echo htmlspecialchars($en['nav_demos']); ?>">
<?php echo $text['nav_demos']; ?>
</a>
</div>
</nav>
<main class="tree-page">
<section class="tree-hero" aria-labelledby="tree-title">
<div class="section-heading">
<p class="section-kicker"
data-translate data-key="tree_kicker"
data-en="<?php echo htmlspecialchars($en['tree_kicker']); ?>">
<?php echo $text['tree_kicker']; ?>
</p>
<h1 id="tree-title"
data-translate data-key="tree_title"
data-en="<?php echo htmlspecialchars($en['tree_title']); ?>">
<?php echo $text['tree_title']; ?>
</h1>
<p data-translate data-key="tree_subtitle"
data-en="<?php echo htmlspecialchars($en['tree_subtitle']); ?>">
<?php echo $text['tree_subtitle']; ?>
</p>
<a class="tree-back-link" href="<?php echo htmlspecialchars($blogHref); ?>"
data-translate data-key="tree_back_to_blog"
data-en="<?php echo htmlspecialchars($en['tree_back_to_blog']); ?>">
<?php echo $text['tree_back_to_blog']; ?>
</a>
</div>
<div class="tree-stage" aria-label="Christmas tree version of the homelab architecture">
<svg class="christmas-homelab" viewBox="0 0 1040 940" role="img" aria-labelledby="christmas-map-title christmas-map-desc">
<title id="christmas-map-title">Homelab Christmas tree map</title>
<desc id="christmas-map-desc">A Christmas tree where each tree part represents a homelab component, from DNS and TLS at the star to storage and backups in the roots.</desc>
<rect class="tree-sky" x="0" y="0" width="1040" height="940" rx="24"></rect>
<circle class="tree-light tree-light-blue" cx="120" cy="92" r="5"></circle>
<circle class="tree-light tree-light-gold" cx="240" cy="150" r="4"></circle>
<circle class="tree-light tree-light-red" cx="842" cy="94" r="5"></circle>
<circle class="tree-light tree-light-green" cx="910" cy="178" r="4"></circle>
<circle class="tree-light tree-light-blue" cx="752" cy="126" r="4"></circle>
<g class="tree-star">
<polygon points="520,42 538,88 588,88 548,118 564,166 520,136 476,166 492,118 452,88 502,88"></polygon>
<text x="520" y="105">Public DNS + TLS</text>
<text class="tree-small" x="520" y="126">lab2025.duckdns.org</text>
</g>
<path class="garland garland-blue" d="M300 238 C410 284 622 196 742 244"></path>
<path class="garland garland-gold" d="M234 372 C384 440 674 310 820 382"></path>
<path class="garland garland-red" d="M168 540 C348 628 720 452 884 552"></path>
<text class="tree-garland-label" x="732" y="232">Tailscale mesh</text>
<text class="tree-garland-label" x="802" y="366">NodePorts</text>
<text class="tree-garland-label" x="830" y="526">GitOps sync</text>
<polygon class="tree-layer tree-layer-top" points="520,140 314,320 430,320 254,470 396,470 182,650 858,650 644,470 786,470 610,320 726,320"></polygon>
<polygon class="tree-layer tree-layer-shadow" points="520,214 358,346 452,346 306,470 428,470 250,620 792,620 612,470 734,470 588,346 682,346"></polygon>
<g class="tree-ornament ornament-blue" transform="translate(430 266)">
<circle r="38"></circle>
<text y="-7">Gitea</text>
<text class="tree-small" y="14">repo + web UI</text>
</g>
<g class="tree-ornament ornament-gold" transform="translate(592 276)">
<circle r="38"></circle>
<text y="-7">Actions</text>
<text class="tree-small" y="14">runner</text>
</g>
<g class="tree-ornament ornament-red" transform="translate(346 392)">
<circle r="40"></circle>
<text y="-8">Gitleaks</text>
<text class="tree-small" y="14">secrets</text>
</g>
<g class="tree-ornament ornament-purple" transform="translate(520 398)">
<circle r="44"></circle>
<text y="-10">OpenTofu</text>
<text class="tree-small" y="12">lab.sh apply</text>
</g>
<g class="tree-ornament ornament-teal" transform="translate(696 394)">
<circle r="40"></circle>
<text y="-8">Trivy</text>
<text class="tree-small" y="14">posture</text>
</g>
<g class="tree-ornament ornament-green" transform="translate(278 534)">
<circle r="42"></circle>
<text y="-8">Calico</text>
<text class="tree-small" y="14">network</text>
</g>
<g class="tree-ornament ornament-blue" transform="translate(430 548)">
<circle r="42"></circle>
<text y="-8">Argo CD</text>
<text class="tree-small" y="14">sync loop</text>
</g>
<g class="tree-ornament ornament-red" transform="translate(592 548)">
<circle r="42"></circle>
<text y="-8">Registry</text>
<text class="tree-small" y="14">:30500</text>
</g>
<g class="tree-ornament ornament-gold" transform="translate(750 532)">
<circle r="42"></circle>
<text y="-8">Buildx</text>
<text class="tree-small" y="14">arm64</text>
</g>
<g class="tree-ornament ornament-teal" transform="translate(350 646)">
<circle r="44"></circle>
<text y="-9">Website</text>
<text class="tree-small" y="13">portfolio pod</text>
</g>
<g class="tree-ornament ornament-purple" transform="translate(522 664)">
<circle r="46"></circle>
<text y="-9">Gitea app</text>
<text class="tree-small" y="13">Git service</text>
</g>
<g class="tree-ornament ornament-green" transform="translate(700 646)">
<circle r="44"></circle>
<text y="-9">Demos</text>
<text class="tree-small" y="13">static app</text>
</g>
<g class="tree-bell" transform="translate(226 442)">
<path d="M0,-24 C24,-18 30,12 22,30 L-22,30 C-30,12 -24,-18 0,-24 Z"></path>
<circle cy="34" r="7"></circle>
<text x="0" y="56">probes</text>
</g>
<g class="tree-bell" transform="translate(812 446)">
<path d="M0,-24 C24,-18 30,12 22,30 L-22,30 C-30,12 -24,-18 0,-24 Z"></path>
<circle cy="34" r="7"></circle>
<text x="0" y="56">health checks</text>
</g>
<rect class="tree-trunk" x="468" y="650" width="104" height="142" rx="12"></rect>
<text class="tree-trunk-text" x="520" y="700">Debian</text>
<text class="tree-trunk-text tree-small" x="520" y="722">control plane</text>
<text class="tree-trunk-text tree-small" x="520" y="744">192.168.100.68</text>
<path class="tree-root" d="M520 790 C456 814 390 822 310 822"></path>
<path class="tree-root" d="M520 790 C584 816 660 824 740 822"></path>
<path class="tree-root" d="M520 790 C506 830 486 852 438 870"></path>
<path class="tree-root" d="M520 790 C536 830 566 852 612 870"></path>
<text class="tree-root-label" x="306" y="850">OpenEBS retained PVs</text>
<text class="tree-root-label" x="734" y="850">external SSD</text>
<text class="tree-root-label" x="520" y="894">Gitea dumps + restore drills</text>
<g class="tree-gift gift-blue" transform="translate(118 738)">
<rect width="128" height="84" rx="8"></rect>
<path d="M64 0 L64 84 M0 30 L128 30"></path>
<text x="64" y="56">OCI edge</text>
<text class="tree-small" x="64" y="74">nginx/HAProxy</text>
</g>
<g class="tree-gift gift-red" transform="translate(760 738)">
<rect width="148" height="84" rx="8"></rect>
<path d="M74 0 L74 84 M0 30 L148 30"></path>
<text x="74" y="56">Raspberry Pi</text>
<text class="tree-small" x="74" y="74">arm64 worker</text>
</g>
<g class="tree-gift gift-green" transform="translate(256 800)">
<rect width="132" height="72" rx="8"></rect>
<path d="M66 0 L66 72 M0 26 L132 26"></path>
<text x="66" y="48">backlog</text>
<text class="tree-small" x="66" y="64">roadmap gifts</text>
</g>
<g class="tree-gift gift-gold" transform="translate(642 800)">
<rect width="142" height="72" rx="8"></rect>
<path d="M71 0 L71 72 M0 26 L142 26"></path>
<text x="71" y="48">monitoring</text>
<text class="tree-small" x="71" y="64">future lights</text>
</g>
</svg>
</div>
</section>
<section class="tree-key" aria-labelledby="tree-key-title">
<div class="section-heading">
<p class="section-kicker"
data-translate data-key="tree_key_kicker"
data-en="<?php echo htmlspecialchars($en['tree_key_kicker']); ?>">
<?php echo $text['tree_key_kicker']; ?>
</p>
<h2 id="tree-key-title"
data-translate data-key="tree_key_title"
data-en="<?php echo htmlspecialchars($en['tree_key_title']); ?>">
<?php echo $text['tree_key_title']; ?>
</h2>
<p data-translate data-key="tree_key_intro"
data-en="<?php echo htmlspecialchars($en['tree_key_intro']); ?>">
<?php echo $text['tree_key_intro']; ?>
</p>
</div>
<ul class="tree-key-list">
<li><strong>Star:</strong> public DNS, TLS, and the entry point users actually type.</li>
<li><strong>Garlands:</strong> Tailscale routing, NodePorts, and the GitOps sync loop connecting the layers.</li>
<li><strong>Branches:</strong> Kubernetes namespaces and workloads that carry the visible services.</li>
<li><strong>Ornaments:</strong> Gitea, Actions, Argo CD, Buildx, Trivy, Gitleaks, Calico, registry, website, demos, and the Gitea app.</li>
<li><strong>Bells:</strong> probes and health checks that make noise before users do.</li>
<li><strong>Trunk:</strong> the Debian control-plane node that holds the platform upright.</li>
<li><strong>Roots:</strong> OpenEBS retained volumes, external SSD storage, Gitea dumps, and restore discipline.</li>
<li><strong>Gifts:</strong> the OCI edge host, Raspberry Pi worker, monitoring ideas, and the improvement backlog.</li>
</ul>
</section>
</main>
<script>
const OTHER_PAGES = ['/index.php', '/cv.php', '/blog.php'];
</script>
<?php require_once __DIR__ . '/partials/translation_ui.php'; ?>
</body>
</html>