Files

276 lines
20 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ourpad — Projects</title>
<link href="https://fonts.googleapis.com/css2?family=Geist:wght@300;400;500;600&family=Geist+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
:root {
--black: #171717;
--white: #ffffff;
--gray-600: #4d4d4d;
--gray-400: #808080;
--gray-100: #ebebeb;
--gray-50: #fafafa;
--link-blue: #0072f5;
--focus-blue: hsla(212, 100%, 48%, 1);
--badge-bg: #ebf5ff;
--badge-text: #0068d6;
--ring: rgba(0,0,0,0.08) 0px 0px 0px 1px;
--card-shadow: rgba(0,0,0,0.08) 0px 0px 0px 1px, rgba(0,0,0,0.04) 0px 2px 2px, rgba(0,0,0,0.04) 0px 8px 8px -8px, #fafafa 0px 0px 0px 1px;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Geist', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
font-feature-settings: 'liga';
background: var(--white);
color: var(--black);
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
nav {
position: sticky; top: 0; background: var(--white);
box-shadow: var(--ring); padding: 0 24px; height: 56px;
display: flex; align-items: center; justify-content: space-between; z-index: 100;
}
.nav-brand { font-size: 18px; font-weight: 600; letter-spacing: -0.36px; color: var(--black); text-decoration: none; }
.nav-links { display: flex; gap: 24px; align-items: center; }
.nav-links a { font-size: 14px; font-weight: 500; color: var(--gray-600); text-decoration: none; transition: color 0.15s; }
.nav-links a:hover { color: var(--black); }
.hero { text-align: center; padding: 100px 24px 64px; }
.hero h1 { font-size: 48px; font-weight: 600; line-height: 1.0; letter-spacing: -2.4px; margin-bottom: 16px; }
.hero p { font-size: 20px; font-weight: 400; line-height: 1.8; color: var(--gray-600); max-width: 560px; margin: 0 auto; }
.section { max-width: 1200px; margin: 0 auto; padding: 0 24px 64px; }
.section-header { display: flex; align-items: center; gap: 8px; margin-bottom: 32px; }
.section-header h2 { font-size: 28px; font-weight: 600; letter-spacing: -1.12px; }
.section-header .badge { display: inline-flex; align-items: center; background: var(--badge-bg); color: var(--badge-text); font-size: 12px; font-weight: 500; padding: 0 10px; height: 24px; border-radius: 9999px; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 16px; }
.grid-4 { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.card {
background: var(--white); box-shadow: var(--card-shadow); border-radius: 8px;
padding: 24px; text-decoration: none; color: inherit;
transition: box-shadow 0.2s, transform 0.15s; display: flex; flex-direction: column; gap: 12px;
}
.card:hover { box-shadow: rgba(0,0,0,0.12) 0px 0px 0px 1px, rgba(0,0,0,0.06) 0px 2px 4px, rgba(0,0,0,0.04) 0px 12px 12px -8px, #fafafa 0px 0px 0px 1px; transform: translateY(-1px); }
.card.nolink { pointer-events: none; } /* but still show hover */
.card.nolink:hover { transform: none; box-shadow: var(--card-shadow); }
.card-header { display: flex; align-items: center; gap: 10px; }
.card-icon { width: 36px; height: 36px; border-radius: 6px; display: flex; align-items: center; justify-content: center; font-size: 18px; flex-shrink: 0; }
.card-title { font-size: 18px; font-weight: 600; letter-spacing: -0.36px; }
.card-desc { font-size: 13px; font-weight: 400; color: var(--gray-600); line-height: 1.6; }
.card-meta { display: flex; gap: 6px; flex-wrap: wrap; margin-top: auto; }
.tag { font-family: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, monospace; font-size: 10px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.3px; color: var(--gray-400); padding: 2px 8px; background: var(--gray-50); border-radius: 4px; }
.tag.active { background: #ecfdf5; color: #065f46; }
.tag.wip { background: #fef3c7; color: #92400e; }
.tag.internal { background: #f3e8ff; color: #7c3aed; }
/* Service mini-card */
.svc-card {
display: flex; align-items: center; gap: 12px; padding: 14px 18px;
background: var(--white); box-shadow: var(--ring); border-radius: 8px;
text-decoration: none; transition: box-shadow 0.15s;
}
.svc-card:hover { box-shadow: rgba(0,0,0,0.15) 0px 0px 0px 1px, rgba(0,0,0,0.04) 0px 2px 4px; }
.svc-icon { font-size: 20px; flex-shrink: 0; }
.svc-name { font-size: 14px; font-weight: 500; color: var(--black); }
.svc-desc { font-size: 12px; color: var(--gray-400); margin-top: 1px; }
.svc-internal { opacity: 0.7; }
.svc-internal:hover { opacity: 1; }
.alt-bg { background: var(--gray-50); padding: 64px 24px; box-shadow: rgba(0,0,0,0.04) 0px -1px 0px 0px, rgba(0,0,0,0.04) 0px 1px 0px 0px; }
.alt-bg .section { padding-bottom: 0; }
.alt-bg + .alt-bg { box-shadow: rgba(0,0,0,0.04) 0px 1px 0px 0px; padding-top: 48px; }
footer { text-align: center; padding: 32px 24px; font-size: 13px; color: var(--gray-400); }
footer a { color: var(--link-blue); text-decoration: none; }
@media (max-width: 768px) {
.hero { padding: 48px 24px 40px; }
.hero h1 { font-size: 32px; letter-spacing: -1.6px; }
.hero p { font-size: 16px; }
.grid, .grid-4 { grid-template-columns: 1fr; }
.section-header h2 { font-size: 22px; }
.nav-links { display: none; }
}
</style>
</head>
<body>
<nav>
<a href="/" class="nav-brand">Ourpad</a>
<div class="nav-links">
<a href="https://gitea.ourpad.casa">Gitea</a>
<a href="https://pass.ourpad.casa">Pass Vault</a>
<a href="https://dashboard.ourpad.casa">Dashboard</a>
</div>
</nav>
<section class="hero">
<h1>Projects &amp; Services</h1>
<p>Self-hosted tools and infrastructure powering the Ourpad home lab — 2 Proxmox nodes, 16 LXCs, 30+ services.</p>
</section>
<!-- PROJECTS -->
<div class="section">
<div class="section-header"><h2>Projects</h2><span class="badge">6</span></div>
<div class="grid">
<a href="https://gitea.ourpad.casa/shawn/pass-vault" class="card">
<div class="card-header"><div class="card-icon" style="background:#fef3c7;">🔐</div><span class="card-title">Pass Vault</span></div>
<p class="card-desc">Browser-based password manager — GPG-encrypted pass store with dark-themed web UI. Mobile responsive, systemd service.</p>
<div class="card-meta"><span class="tag">FastAPI</span><span class="tag">pass</span><span class="tag active">active</span></div>
</a>
<a href="https://gitea.ourpad.casa/shawn/canteen-asset-tracker" class="card">
<div class="card-header"><div class="card-icon" style="background:#e0f2fe;">📍</div><span class="card-title">Canteen Asset Tracker</span></div>
<p class="card-desc">Mobile webapp for tracking canteen assets — machine-id scanning, OCR, GPS check-ins, geofences, CSV export.</p>
<div class="card-meta"><span class="tag">FastAPI</span><span class="tag">SQLite</span><span class="tag wip">in progress</span></div>
</a>
<a href="https://gitea.ourpad.casa/shawn/canteen-web-app" class="card">
<div class="card-header"><div class="card-icon" style="background:#fce7f3;">🌐</div><span class="card-title">Canteen Web App</span></div>
<p class="card-desc">Full-stack frontend for canteen management — login, navigation, asset CRUD, and reporting interface.</p>
<div class="card-meta"><span class="tag">Frontend</span><span class="tag wip">in progress</span></div>
</a>
<a href="https://gitea.ourpad.casa/shawn/project-directory" class="card">
<div class="card-header"><div class="card-icon" style="background:#ecfdf5;">📂</div><span class="card-title">Project Directory</span></div>
<p class="card-desc">This page — a living index of all Ourpad projects, services, and infrastructure. Served via NPMplus.</p>
<div class="card-meta"><span class="tag">HTML/CSS</span><span class="tag active">active</span></div>
</a>
<a href="https://github.com/NousResearch/hermes-agent" class="card">
<div class="card-header"><div class="card-icon" style="background:#ede9fe;">🤖</div><span class="card-title">Hermes Agent</span></div>
<p class="card-desc">AI agent framework — 3 profiles, cron jobs, kanban boards, MCP tools, multi-model delegation. The brain of the lab.</p>
<div class="card-meta"><span class="tag">Python</span><span class="tag">AI/ML</span><span class="tag active">active</span></div>
</a>
<a href="https://obsidian.md" class="card">
<div class="card-header"><div class="card-icon" style="background:#f1f5f9;">📝</div><span class="card-title">Obsidian Vault</span></div>
<p class="card-desc">Knowledge management — three-layer vault (Inbox → Notes → Archive), LLM Wiki, daily notes, automated reviews.</p>
<div class="card-meta"><span class="tag">Obsidian</span><span class="tag">Dataview</span><span class="tag active">active</span></div>
</a>
</div>
</div>
<!-- PUBLIC SERVICES -->
<div class="alt-bg">
<div class="section">
<div class="section-header"><h2>Public Services</h2><span class="badge">16</span></div>
<p style="font-size:13px;color:var(--gray-400);margin:-16px 0 24px;">All accessible via <code style="background:var(--gray-50);padding:1px 6px;border-radius:3px;">*.ourpad.casa</code> behind NPMplus + Cloudflare</p>
<div class="grid-4">
<a href="https://gitea.ourpad.casa" class="svc-card"><span class="svc-icon">🦊</span><div><div class="svc-name">Gitea</div><div class="svc-desc">Self-hosted Git — repos, issues, CI</div></div></a>
<a href="https://pass.ourpad.casa" class="svc-card"><span class="svc-icon">🔐</span><div><div class="svc-name">Pass Vault</div><div class="svc-desc">Web-based secret management</div></div></a>
<a href="https://projects.ourpad.casa" class="svc-card"><span class="svc-icon">📂</span><div><div class="svc-name">Project Directory</div><div class="svc-desc">This page</div></div></a>
<a href="https://dashboard.ourpad.casa" class="svc-card"><span class="svc-icon">🏠</span><div><div class="svc-name">Heimdall Dashboard</div><div class="svc-desc">Service landing page</div></div></a>
<a href="https://sonarr.ourpad.casa" class="svc-card"><span class="svc-icon">📺</span><div><div class="svc-name">Sonarr</div><div class="svc-desc">TV show automation</div></div></a>
<a href="https://radarr.ourpad.casa" class="svc-card"><span class="svc-icon">🎬</span><div><div class="svc-name">Radarr</div><div class="svc-desc">Movie automation</div></div></a>
<a href="https://jellyseerr.ourpad.casa" class="svc-card"><span class="svc-icon">🎞️</span><div><div class="svc-name">Jellyseerr</div><div class="svc-desc">Media requests</div></div></a>
<a href="https://deluge.ourpad.casa" class="svc-card"><span class="svc-icon">📥</span><div><div class="svc-name">Deluge</div><div class="svc-desc">Torrent client</div></div></a>
<a href="https://jellyfin.ourpad.casa" class="svc-card"><span class="svc-icon">▶️</span><div><div class="svc-name">Jellyfin</div><div class="svc-desc">Media streaming</div></div></a>
<a href="https://obsidian.ourpad.casa" class="svc-card"><span class="svc-icon">🔄</span><div><div class="svc-name">Obsidian LiveSync</div><div class="svc-desc">CouchDB sync server</div></div></a>
<a href="https://inventory.ourpad.casa" class="svc-card"><span class="svc-icon">📦</span><div><div class="svc-name">Inventree</div><div class="svc-desc">Inventory management</div></div></a>
<a href="https://npmplus.ourpad.casa" class="svc-card"><span class="svc-icon">🌐</span><div><div class="svc-name">NPMplus</div><div class="svc-desc">Reverse proxy admin</div></div></a>
<a href="https://admin.ourpad.casa" class="svc-card"><span class="svc-icon">🖥️</span><div><div class="svc-name">Proxmox Admin</div><div class="svc-desc">VE management UI</div></div></a>
<a href="https://media.ourpad.casa" class="svc-card"><span class="svc-icon">💾</span><div><div class="svc-name">Proxmox Media</div><div class="svc-desc">Secondary VE host</div></div></a>
<a href="https://rustdesk.ourpad.casa" class="svc-card"><span class="svc-icon">🖧</span><div><div class="svc-name">RustDesk</div><div class="svc-desc">Remote desktop relay</div></div></a>
<a href="https://canteen.ourpad.casa" class="svc-card"><span class="svc-icon">🏗️</span><div><div class="svc-name">Canteen App</div><div class="svc-desc">Asset tracker (WIP)</div></div></a>
</div>
</div>
</div>
<!-- INTERNAL SERVICES -->
<div class="alt-bg">
<div class="section">
<div class="section-header"><h2>Internal Services</h2><span class="badge">10</span></div>
<p style="font-size:13px;color:var(--gray-400);margin:-16px 0 24px;">Not publicly exposed — accessible via Tailscale or internal network only</p>
<div class="grid-4">
<span class="svc-card svc-internal"><span class="svc-icon">🔍</span><div><div class="svc-name">Prowlarr</div><div class="svc-desc">Indexer aggregator (CT 104)</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">📚</span><div><div class="svc-name">Readarr</div><div class="svc-desc">Book management (CT 108)</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">⚙️</span><div><div class="svc-name">Configarr</div><div class="svc-desc">Config sync (CT 107)</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">📦</span><div><div class="svc-name">Unpackerr</div><div class="svc-desc">RAR extraction (CT 114)</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">💬</span><div><div class="svc-name">Element Synapse</div><div class="svc-desc">Matrix server (CT 112)</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">🐳</span><div><div class="svc-name">Portainer</div><div class="svc-desc">Docker management (CT 100:9443)</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">🧠</span><div><div class="svc-name">Hermes WebUI</div><div class="svc-desc">Agent dashboard (CT 102:8787)</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">⌨️</span><div><div class="svc-name">Deskbrid</div><div class="svc-desc">Desktop automation</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">☁️</span><div><div class="svc-name">Cloudflare DDNS</div><div class="svc-desc">Dynamic DNS updater (CT 105)</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">🔗</span><div><div class="svc-name">Tailscale</div><div class="svc-desc">Mesh VPN — 2 nodes</div></div></span>
</div>
</div>
</div>
<!-- INFRASTRUCTURE -->
<div class="alt-bg">
<div class="section">
<div class="section-header"><h2>Infrastructure</h2></div>
<div class="grid">
<span class="card nolink">
<div class="card-header"><div class="card-icon" style="background:#fef2f2;">🖥️</div><span class="card-title">Primary Proxmox</span></div>
<p class="card-desc"><strong>192.168.0.144</strong> — VE 8.4, 31GB RAM, 14 LXCs. Docker LXC, arr stack, NAS, Hermes.</p>
<div class="card-meta"><span class="tag">pve</span><span class="tag">ZFS</span></div>
</span>
<span class="card nolink">
<div class="card-header"><div class="card-icon" style="background:#eff6ff;">🌐</div><span class="card-title">Secondary Proxmox</span></div>
<p class="card-desc"><strong>192.168.0.110</strong> — NPMplus reverse proxy, Jellyfin, Cloudflare DDNS. 3 LXCs.</p>
<div class="card-meta"><span class="tag">NPMplus</span><span class="tag">Edge</span></div>
</span>
<span class="card nolink">
<div class="card-header"><div class="card-icon" style="background:#f0fdf4;">💾</div><span class="card-title">NAS Storage</span></div>
<p class="card-desc"><strong>3.6TB ext4</strong> at /mnt/nas — bind-mounted into all arr LXCs. Media library, torrents, backups.</p>
<div class="card-meta"><span class="tag">/dev/sdb</span><span class="tag">ext4</span></div>
</span>
<span class="card nolink">
<div class="card-header"><div class="card-icon" style="background:#f5f3ff;">🔒</div><span class="card-title">Networking</span></div>
<p class="card-desc"><strong>Cloudflare</strong> DNS + proxy (68.202.6.107) → NPMplus (192.168.0.115) → internal services. <strong>Tailscale</strong> mesh for remote access.</p>
<div class="card-meta"><span class="tag">ourpad.casa</span><span class="tag">TLS 1.3</span></div>
</span>
</div>
</div>
</div>
<!-- LXC INVENTORY -->
<div class="alt-bg">
<div class="section">
<div class="section-header"><h2>LXC Inventory</h2><span class="badge">17</span></div>
<p style="font-size:13px;color:var(--gray-400);margin:-16px 0 24px;">All containers across both Proxmox hosts</p>
<div class="grid-4">
<span class="svc-card svc-internal"><span class="svc-icon">🐳</span><div><div class="svc-name">CT 100 docker</div><div class="svc-desc">192.168.0.223 · Gitea, Portainer, LiveSync</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">🐧</span><div><div class="svc-name">CT 101 debian</div><div class="svc-desc">Debian utility container</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">🧠</span><div><div class="svc-name">CT 102 hermes</div><div class="svc-desc">100.89.190.113 · Hermes Agent host</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">📺</span><div><div class="svc-name">CT 103 sonarr</div><div class="svc-desc">192.168.0.178 · Sonarr</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">🔍</span><div><div class="svc-name">CT 104 prowlarr</div><div class="svc-desc">192.168.0.225 · Prowlarr</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">🎬</span><div><div class="svc-name">CT 105 radarr</div><div class="svc-desc">192.168.0.123 · Radarr</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">🎞️</span><div><div class="svc-name">CT 106 jellyseerr</div><div class="svc-desc">192.168.0.229 · Jellyseerr</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">⚙️</span><div><div class="svc-name">CT 107 configarr</div><div class="svc-desc">192.168.0.238 · Configarr</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">📚</span><div><div class="svc-name">CT 108 readarr</div><div class="svc-desc">192.168.0.193 · Readarr</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">📥</span><div><div class="svc-name">CT 109 deluge</div><div class="svc-desc">192.168.0.243 · Deluge</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">💬</span><div><div class="svc-name">CT 112 elementsynapse</div><div class="svc-desc">192.168.0.220 · Matrix</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">📦</span><div><div class="svc-name">CT 114 unpackerr</div><div class="svc-desc">192.168.0.119 · Unpackerr</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">🏠</span><div><div class="svc-name">CT 115 heimdall</div><div class="svc-desc">192.168.0.213 · Dashboard</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">📋</span><div><div class="svc-name">CT 116 inventree</div><div class="svc-desc">192.168.0.132 · Inventory</div></div></span>
<!-- Secondary host -->
<span class="svc-card svc-internal"><span class="svc-icon">🌐</span><div><div class="svc-name">CT 102 npmplus</div><div class="svc-desc">192.168.0.115 · Reverse proxy</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">▶️</span><div><div class="svc-name">CT 104 jellyfin</div><div class="svc-desc">192.168.0.125 · Media server</div></div></span>
<span class="svc-card svc-internal"><span class="svc-icon">☁️</span><div><div class="svc-name">CT 105 cloudflare-ddns</div><div class="svc-desc">Dynamic DNS updater</div></div></span>
</div>
</div>
</div>
<footer>
<p>Built with <a href="https://github.com/NousResearch/hermes-agent">Hermes Agent</a> · Served via <a href="https://gitea.ourpad.casa">Gitea</a> + NPMplus · <a href="https://gitea.ourpad.casa/shawn/project-directory">Source</a></p>
</footer>
</body>
</html>