RC: (upload) astro initial structure

This commit is contained in:
Raul Costa
2026-04-01 00:19:49 +01:00
commit 8c11192e7b
29 changed files with 8561 additions and 0 deletions

331
src/pages/hardware.astro Normal file
View File

@@ -0,0 +1,331 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
// ── Hardware data — edit this as your inventory grows ──────────
const hardware = {
compute: [
{
name: 'Proxmox Node 01',
model: 'Dell PowerEdge R730',
specs: ['2× Intel Xeon E5-2680v4 (28C/56T total)', '256GB DDR4 ECC LRDIMM', '2× 10GbE SFP+', 'iDRAC8 Enterprise', 'H730 RAID (passthrough)'],
role: 'Primary Proxmox hypervisor · VM host',
status: 'online',
location: 'homelab rack · U4',
},
{
name: 'Proxmox Node 02',
model: 'Dell PowerEdge R720',
specs: ['2× Intel Xeon E5-2670 (16C/32T total)', '128GB DDR3 ECC RDIMM', '2× 1GbE', 'iDRAC7 Enterprise'],
role: 'Secondary Proxmox node · backup workloads',
status: 'online',
location: 'homelab rack · U6',
},
{
name: 'Raspberry Pi 4 (8GB)',
model: 'Raspberry Pi 4 Model B',
specs: ['Broadcom BCM2711 (4× Cortex-A72)', '8GB LPDDR4', '2× USB 3.0, Gigabit Ethernet', '64GB Samsung Pro Endurance microSD'],
role: 'PXE boot server · ISC26 cluster deployment',
status: 'online',
location: 'desk · USB-C powered',
},
],
storage: [
{
name: 'ZFS NAS — zfs-oporto',
model: 'Custom Proxmox VM → ZFS passthrough',
specs: ['4× Seagate IronWolf 8TB (RAIDZ2)', '2× Samsung 870 EVO 1TB (SSD special class vdev)', 'ZFS 2.2 — RAIDZ expansion capable', '~20TB usable raw (RAIDZ2 overhead)'],
role: 'Primary NAS · NFS exports to K8s · Immich storage',
status: 'online',
location: 'pve-01 · RAIDZ2',
},
{
name: 'Longhorn Cluster Storage',
model: 'Distributed across k8s-worker1/2',
specs: ['2× 500GB NVMe (worker1)', '2× 500GB NVMe (worker2)', '3-replica default policy'],
role: 'Kubernetes persistent volumes · Longhorn CSI',
status: 'online',
location: 'k8s-worker1 / k8s-worker2',
},
],
networking: [
{
name: 'OPNsense Firewall',
model: 'Protectli VP2420',
specs: ['Intel Celeron J6413', '8GB DDR4', '4× 2.5GbE Intel i226', '64GB eMMC', 'OPNsense 26.1'],
role: 'Edge router · Firewall · WireGuard VPN · Unbound DNS · GeoIP blocks',
status: 'online',
location: 'homelab rack · U1',
},
{
name: 'Core Switch',
model: 'Cisco SG300-28PP',
specs: ['24× PoE+ 1GbE', '2× 1GbE combo SFP', 'Layer 3 managed', '375W PoE budget'],
role: 'Core VLAN switch · LAG to hypervisors',
status: 'online',
location: 'homelab rack · U2',
},
{
name: 'AP',
model: 'Ubiquiti U6-Lite',
specs: ['WiFi 6 (802.11ax)', '2.4 + 5GHz', 'PoE powered'],
role: 'Wireless · separate IoT SSID on VLAN50',
status: 'online',
location: 'ceiling mount',
},
],
work_hpc: [
{
name: 'ARCHER2 (EPCC)',
model: 'HPE Cray EX — AMD EPYC 7742',
specs: ['5,860 compute nodes', '2× AMD EPYC 7742 (128C/node)', '256GB DDR4 ECC/node', 'HPE Slingshot 11 100Gb/s HSN', '14.1 PiB Lustre storage'],
role: 'UK National HPC facility · sysadmin',
status: 'production',
location: 'EPCC · Edinburgh',
},
{
name: 'Cirrus (EPCC)',
model: 'SGI ICE XA / HPE ProLiant XL230a',
specs: ['280 compute nodes', '2× Intel Xeon E5-2695v4 (36C/node)', '256GB DDR4/node', 'Intel OmniPath HSN', 'Cirrus EX GPU partition: HPE Cray EX235n'],
role: 'EPCC Tier-2 HPC · sysadmin · GPU partition admin',
status: 'production',
location: 'EPCC · Edinburgh',
},
{
name: 'ISC26 Competition Cluster',
model: 'Atos BullSequana XH2000',
specs: ['1× BullSequana XD670 GPU node (4× NVIDIA H100 80GB)', '8× BullSequana XD2000 CPU nodes', 'NDR 400Gb/s InfiniBand fabric (Cornelis)', 'Raspberry Pi 4 PXE deployment server'],
role: 'ISC26 Student Cluster Competition — Hamburg 2026',
status: 'building',
location: 'EPCC · Edinburgh',
},
],
peripherals: [
{
name: 'Main Monitor',
model: 'LG 27UK850-W',
specs: ['27" 4K IPS', 'USB-C 60W PD', 'HDR400', 'USB-C + HDMI + DP'],
role: 'Primary display',
status: 'online',
},
{
name: '3D Printer',
model: 'Anycubic Kobra S1',
specs: ['FDM · 220×220×250mm build volume', 'Auto-levelling', 'Direct drive'],
role: 'Printing rack accessories, cable guides, custom mounts',
status: 'idle',
},
{
name: 'Laser Printer',
model: 'Kyocera ECOSYS M2135dn',
specs: ['A4 mono laser MFP', 'Duplex · LAN · ADF', '35ppm'],
role: 'Documents · printing homelab diagrams',
status: 'idle',
},
],
};
const categories = [
{ key: 'compute', label: 'Compute', icon: '▣' },
{ key: 'storage', label: 'Storage', icon: '◈' },
{ key: 'networking', label: 'Networking', icon: '⇅' },
{ key: 'work_hpc', label: 'Work / HPC', icon: '⬡' },
{ key: 'peripherals',label: 'Peripherals & Misc', icon: '◎' },
];
---
<BaseLayout title="Hardware" description="Full hardware inventory — homelab and work HPC systems">
<div class="hardware-page">
<!-- Hero -->
<div class="page-hero container">
<div class="accent-line"></div>
<h1>Hardware <span class="text-accent">Inventory</span></h1>
<p class="text-muted font-mono" style="font-size:0.88rem;margin-top:0.5rem">
Everything physical I touch, rack and bench · last updated 2025
</p>
</div>
<!-- Jump nav -->
<div class="container jump-nav">
{categories.map(cat => (
<a href={`#${cat.key}`} class="jump-chip">
<span class="text-accent">{cat.icon}</span>
<span>{cat.label}</span>
</a>
))}
</div>
<!-- Category sections -->
{categories.map(cat => (
<section class="section container hw-section" id={cat.key}>
<div class="hw-section-header">
<span class="hw-icon text-accent">{cat.icon}</span>
<h2>{cat.label}</h2>
</div>
<div class="hw-grid">
{(hardware as any)[cat.key].map((item: any) => (
<div class="card hw-card">
<div class="hw-card-header">
<div>
<div class="hw-name font-display">{item.name}</div>
<div class="hw-model font-mono">{item.model}</div>
</div>
<span
class="hw-status tag"
style={
item.status === 'online' ? '' :
item.status === 'production' ? 'color:#00D2BE;border-color:#00D2BE;background:rgba(0,210,190,0.08)' :
item.status === 'building' ? 'color:#FFB800;border-color:#FFB800;background:rgba(255,184,0,0.08)' :
'color:var(--text-muted);border-color:var(--border-subtle);background:transparent'
}
>{item.status}</span>
</div>
<ul class="hw-specs">
{item.specs.map((s: string) => (
<li class="hw-spec">
<span class="spec-bullet text-accent">▸</span>
<span>{s}</span>
</li>
))}
</ul>
<div class="hw-footer">
<span class="hw-role text-muted">{item.role}</span>
{item.location && (
<span class="hw-location font-mono">{item.location}</span>
)}
</div>
</div>
))}
</div>
</section>
))}
<!-- Total count footer -->
<div class="container hw-totals">
<div class="card" style="padding:1.5rem;text-align:center">
<p class="font-mono text-muted" style="font-size:0.8rem">
{Object.values(hardware).flat().length} items catalogued ·
<span class="text-accent">rack::log hardware registry</span>
</p>
</div>
</div>
</div>
</BaseLayout>
<style>
.hardware-page { padding-top: 8rem; padding-bottom: 4rem; }
.page-hero { margin-bottom: 2.5rem; }
/* Jump nav */
.jump-nav {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin-bottom: 4rem;
}
.jump-chip {
display: inline-flex;
align-items: center;
gap: 0.4rem;
padding: 0.35rem 0.9rem;
border: 1px solid var(--border-subtle);
border-radius: 20px;
font-family: var(--font-mono);
font-size: 0.78rem;
color: var(--text-muted);
background: var(--bg-surface);
transition: all var(--transition-fast);
}
.jump-chip:hover {
border-color: var(--border-glow);
color: var(--petronas-teal);
background: var(--petronas-glow);
}
/* Section header */
.hw-section { padding-top: 3rem; padding-bottom: 1rem; }
.hw-section-header {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 1.75rem;
}
.hw-icon { font-size: 1.4rem; }
/* Cards */
.hw-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 1.25rem;
}
.hw-card { display: flex; flex-direction: column; gap: 1rem; }
.hw-card-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 1rem;
}
.hw-name {
font-size: 1.05rem;
font-weight: 700;
color: var(--text-primary);
}
.hw-model {
font-size: 0.72rem;
color: var(--petronas-teal);
margin-top: 0.2rem;
}
.hw-status { white-space: nowrap; flex-shrink: 0; }
/* Specs list */
.hw-specs {
list-style: none;
display: flex;
flex-direction: column;
gap: 0.35rem;
flex: 1;
}
.hw-spec {
display: flex;
align-items: baseline;
gap: 0.5rem;
font-size: 0.83rem;
color: var(--text-secondary);
line-height: 1.4;
}
.spec-bullet { font-size: 0.6rem; flex-shrink: 0; margin-top: 0.15rem; }
/* Footer */
.hw-footer {
display: flex;
flex-direction: column;
gap: 0.25rem;
padding-top: 0.75rem;
border-top: 1px solid var(--border-subtle);
}
.hw-role { font-size: 0.8rem; }
.hw-location { font-size: 0.68rem; color: var(--text-muted); }
/* Totals */
.hw-totals { margin-top: 4rem; }
@media (max-width: 600px) {
.hw-grid { grid-template-columns: 1fr; }
}
</style>