Expand: full service catalog — 16 public + 10 internal + 17 LXC inventory
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Ourpad — Project Directory
|
||||
|
||||
A living index of self-hosted projects, tools, and infrastructure powering the Ourpad home lab.
|
||||
A living index of self-hosted projects, tools, and infrastructure powering the Ourpad home lab — 2 Proxmox nodes, 17 LXCs, 30+ services.
|
||||
|
||||
## Projects
|
||||
|
||||
@@ -13,27 +13,74 @@ A living index of self-hosted projects, tools, and infrastructure powering the O
|
||||
| [Hermes Agent](https://github.com/NousResearch/hermes-agent) | Python, AI/ML | 🟢 Active |
|
||||
| [Obsidian Vault](https://obsidian.md) | Obsidian, Markdown, Dataview | 🟢 Active |
|
||||
|
||||
## Services
|
||||
## Public Services (via `*.ourpad.casa`)
|
||||
|
||||
- **Gitea** — Self-hosted Git at [gitea.ourpad.casa](https://gitea.ourpad.casa)
|
||||
- **Pass Vault** — Web-based secret manager at [pass.ourpad.casa](https://pass.ourpad.casa)
|
||||
- **Proxmox VE** — 2-node cluster (192.168.0.144 + 192.168.0.110)
|
||||
- **NPMplus** — Reverse proxy for `*.ourpad.casa` subdomains
|
||||
- **Deluge** — Torrent client (media stack)
|
||||
- **Jellyfin** — Media streaming server
|
||||
- **Sonarr + Radarr** — TV & movie automation
|
||||
- **Tailscale** — Mesh VPN (2 nodes)
|
||||
| Service | URL | Description |
|
||||
|---|---|---|
|
||||
| Gitea | [gitea.ourpad.casa](https://gitea.ourpad.casa) | Self-hosted Git — repos, issues, CI |
|
||||
| Pass Vault | [pass.ourpad.casa](https://pass.ourpad.casa) | Web-based secret management |
|
||||
| Project Directory | [projects.ourpad.casa](https://projects.ourpad.casa) | This page |
|
||||
| Heimdall Dashboard | [dashboard.ourpad.casa](https://dashboard.ourpad.casa) | Service landing page |
|
||||
| Sonarr | [sonarr.ourpad.casa](https://sonarr.ourpad.casa) | TV show automation |
|
||||
| Radarr | [radarr.ourpad.casa](https://radarr.ourpad.casa) | Movie automation |
|
||||
| Jellyseerr | [jellyseerr.ourpad.casa](https://jellyseerr.ourpad.casa) | Media requests |
|
||||
| Deluge | [deluge.ourpad.casa](https://deluge.ourpad.casa) | Torrent client |
|
||||
| Jellyfin | [jellyfin.ourpad.casa](https://jellyfin.ourpad.casa) | Media streaming |
|
||||
| Obsidian LiveSync | [obsidian.ourpad.casa](https://obsidian.ourpad.casa) | CouchDB sync server |
|
||||
| Inventree | [inventory.ourpad.casa](https://inventory.ourpad.casa) | Inventory management |
|
||||
| NPMplus | [npmplus.ourpad.casa](https://npmplus.ourpad.casa) | Reverse proxy admin |
|
||||
| Proxmox Admin | [admin.ourpad.casa](https://admin.ourpad.casa) | VE management UI |
|
||||
| Proxmox Media | [media.ourpad.casa](https://media.ourpad.casa) | Secondary VE host |
|
||||
| RustDesk | [rustdesk.ourpad.casa](https://rustdesk.ourpad.casa) | Remote desktop relay |
|
||||
| Canteen App | [canteen.ourpad.casa](https://canteen.ourpad.casa) | Asset tracker (WIP) |
|
||||
|
||||
## Internal Services (Tailscale / internal only)
|
||||
|
||||
| Service | Location | Notes |
|
||||
|---|---|---|
|
||||
| Prowlarr | CT 104 (192.168.0.225) | Indexer aggregator |
|
||||
| Readarr | CT 108 (192.168.0.193) | Book management |
|
||||
| Configarr | CT 107 (192.168.0.238) | Config sync |
|
||||
| Unpackerr | CT 114 (192.168.0.119) | RAR extraction |
|
||||
| Element Synapse | CT 112 (192.168.0.220) | Matrix server |
|
||||
| Portainer | CT 100:9443 | Docker management |
|
||||
| Hermes WebUI | CT 102:8787 | Agent dashboard |
|
||||
| Deskbrid | CT 102 (local) | Desktop automation |
|
||||
| Cloudflare DDNS | CT 105 (192.168.0.110) | Dynamic DNS updater |
|
||||
| Tailscale | Mesh VPN | 2 nodes |
|
||||
|
||||
## Infrastructure
|
||||
|
||||
- **Primary Proxmox** (192.168.0.144): Docker LXC, arr stack, NAS
|
||||
- **Secondary Proxmox** (192.168.0.110): NPMplus, Jellyfin, Cloudflare DDNS
|
||||
- **NAS**: 3.6TB ext4 at `/mnt/nas`, bind-mounted into LXCs
|
||||
- **Domain**: `ourpad.casa` via Cloudflare
|
||||
| Component | Details |
|
||||
|---|---|
|
||||
| Primary Proxmox | 192.168.0.144 — VE 8.4, 31GB RAM, 14 LXCs |
|
||||
| Secondary Proxmox | 192.168.0.110 — NPMplus, Jellyfin, DDNS |
|
||||
| NAS Storage | 3.6TB ext4 at /mnt/nas, bind-mounted into LXCs |
|
||||
| Docker LXC | CT 100 (192.168.0.223) — Gitea, Portainer, LiveSync, Nginx |
|
||||
| Networking | Cloudflare DNS + proxy (68.202.6.107) → NPMplus (192.168.0.115) |
|
||||
| VPN | Tailscale mesh — oplabs + pixel-9a |
|
||||
|
||||
## Deployment
|
||||
## LXC Inventory
|
||||
|
||||
This page is served as a static site from the Docker LXC (CT 100) behind NPMplus at `projects.ourpad.casa`. Updates are pushed to this repo and deployed automatically.
|
||||
| CT ID | Name | Host | IP | Service |
|
||||
|---|---|---|---|---|
|
||||
| 100 | docker | pve | 192.168.0.223 | Docker — Gitea, Portainer, LiveSync, Nginx |
|
||||
| 101 | debian | pve | — | Debian utility |
|
||||
| 102 | hermes | pve | 100.89.190.113 | Hermes Agent host |
|
||||
| 103 | sonarr | pve | 192.168.0.178 | Sonarr |
|
||||
| 104 | prowlarr | pve | 192.168.0.225 | Prowlarr |
|
||||
| 105 | radarr | pve | 192.168.0.123 | Radarr |
|
||||
| 106 | jellyseerr | pve | 192.168.0.229 | Jellyseerr |
|
||||
| 107 | configarr | pve | 192.168.0.238 | Configarr |
|
||||
| 108 | readarr | pve | 192.168.0.193 | Readarr |
|
||||
| 109 | deluge | pve | 192.168.0.243 | Deluge |
|
||||
| 112 | elementsynapse | pve | 192.168.0.220 | Matrix |
|
||||
| 114 | unpackerr | pve | 192.168.0.119 | Unpackerr |
|
||||
| 115 | heimdall-dashboard | pve | 192.168.0.213 | Dashboard |
|
||||
| 116 | inventree | pve | 192.168.0.132 | Inventory |
|
||||
| 102 | npmplus | 192.168.0.110 | 192.168.0.115 | Reverse proxy |
|
||||
| 104 | jellyfin | 192.168.0.110 | 192.168.0.125 | Media server |
|
||||
| 105 | cloudflare-ddns | 192.168.0.110 | — | Dynamic DNS |
|
||||
|
||||
---
|
||||
|
||||
|
||||
+167
-347
@@ -15,17 +15,12 @@
|
||||
--gray-50: #fafafa;
|
||||
--link-blue: #0072f5;
|
||||
--focus-blue: hsla(212, 100%, 48%, 1);
|
||||
--dev-blue: #0a72ef;
|
||||
--preview-pink: #de1d8d;
|
||||
--ship-red: #ff5b4f;
|
||||
--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';
|
||||
@@ -34,230 +29,68 @@
|
||||
line-height: 1.5;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
/* Nav */
|
||||
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;
|
||||
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 */
|
||||
.hero {
|
||||
text-align: center;
|
||||
padding: 120px 24px 80px;
|
||||
}
|
||||
.hero h1 {
|
||||
font-size: 48px;
|
||||
font-weight: 600;
|
||||
line-height: 1.0;
|
||||
letter-spacing: -2.4px;
|
||||
color: var(--black);
|
||||
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 */
|
||||
.section {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 24px 80px;
|
||||
}
|
||||
.section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
.section-header h2 {
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
letter-spacing: -1.28px;
|
||||
color: var(--black);
|
||||
}
|
||||
.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 */
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
/* Card */
|
||||
.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);
|
||||
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; }
|
||||
|
||||
.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: 20px;
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.4px;
|
||||
color: var(--black);
|
||||
}
|
||||
.card-desc {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: var(--gray-600);
|
||||
line-height: 1.6;
|
||||
}
|
||||
.card-meta {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
margin-top: auto;
|
||||
}
|
||||
.tag {
|
||||
font-family: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, monospace;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
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;
|
||||
/* 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; }
|
||||
|
||||
/* Links section */
|
||||
.links-section {
|
||||
background: var(--gray-50);
|
||||
padding: 80px 24px;
|
||||
box-shadow: rgba(0,0,0,0.04) 0px -1px 0px 0px;
|
||||
}
|
||||
.links-grid {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
.link-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 16px 20px;
|
||||
background: var(--white);
|
||||
box-shadow: var(--ring);
|
||||
border-radius: 8px;
|
||||
text-decoration: none;
|
||||
transition: box-shadow 0.15s;
|
||||
}
|
||||
.link-card:hover {
|
||||
box-shadow: rgba(0,0,0,0.15) 0px 0px 0px 1px, rgba(0,0,0,0.04) 0px 2px 4px;
|
||||
}
|
||||
.link-card .lc-icon {
|
||||
font-size: 20px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.link-card .lc-text {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--black);
|
||||
}
|
||||
.link-card .lc-sub {
|
||||
font-size: 12px;
|
||||
color: var(--gray-400);
|
||||
}
|
||||
.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 */
|
||||
footer {
|
||||
text-align: center;
|
||||
padding: 32px 24px;
|
||||
font-size: 13px;
|
||||
color: var(--gray-400);
|
||||
}
|
||||
footer a {
|
||||
color: var(--link-blue);
|
||||
text-decoration: none;
|
||||
}
|
||||
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: 64px 24px 48px; }
|
||||
.hero h1 { font-size: 36px; letter-spacing: -1.8px; }
|
||||
.hero { padding: 48px 24px 40px; }
|
||||
.hero h1 { font-size: 32px; letter-spacing: -1.6px; }
|
||||
.hero p { font-size: 16px; }
|
||||
.grid { grid-template-columns: 1fr; }
|
||||
.section-header h2 { font-size: 24px; }
|
||||
.grid, .grid-4 { grid-template-columns: 1fr; }
|
||||
.section-header h2 { font-size: 22px; }
|
||||
.nav-links { display: none; }
|
||||
}
|
||||
</style>
|
||||
@@ -269,183 +102,170 @@
|
||||
<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 & Services</h1>
|
||||
<p>Self-hosted tools and infrastructure powering the Ourpad home lab — built with open source, deployed on Proxmox.</p>
|
||||
<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="section-header"><h2>Projects</h2><span class="badge">6</span></div>
|
||||
<div class="grid">
|
||||
|
||||
<!-- Pass Vault -->
|
||||
<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>
|
||||
<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>
|
||||
|
||||
<!-- Canteen Asset Tracker -->
|
||||
<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>
|
||||
<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">Vanilla JS</span>
|
||||
<span class="tag wip">in progress</span>
|
||||
</div>
|
||||
<div class="card-meta"><span class="tag">FastAPI</span><span class="tag">SQLite</span><span class="tag wip">in progress</span></div>
|
||||
</a>
|
||||
|
||||
<!-- Canteen Web App -->
|
||||
<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 canteen management frontend — 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>
|
||||
<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>
|
||||
|
||||
<!-- Project Directory -->
|
||||
<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>
|
||||
<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">Static</span>
|
||||
<span class="tag active">active</span>
|
||||
</div>
|
||||
<div class="card-meta"><span class="tag">HTML/CSS</span><span class="tag active">active</span></div>
|
||||
</a>
|
||||
|
||||
<!-- Hermes Agent -->
|
||||
<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 powering this setup — profiles, cron jobs, kanban boards, MCP tools, and multi-model delegation.</p>
|
||||
<div class="card-meta">
|
||||
<span class="tag">Python</span>
|
||||
<span class="tag">AI/ML</span>
|
||||
<span class="tag active">active</span>
|
||||
</div>
|
||||
<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>
|
||||
|
||||
<!-- Obsidian Vault -->
|
||||
<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 system — three-layer vault (Inbox→Notes→Archive), LLM Wiki, daily notes, and automated review.</p>
|
||||
<div class="card-meta">
|
||||
<span class="tag">Obsidian</span>
|
||||
<span class="tag">Markdown</span>
|
||||
<span class="tag">Dataview</span>
|
||||
<span class="tag active">active</span>
|
||||
</div>
|
||||
<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>
|
||||
|
||||
<!-- Services & Infrastructure -->
|
||||
<div class="links-section">
|
||||
<div class="section-header" style="max-width:1200px;margin:0 auto 32px;padding:0;">
|
||||
<h2>Services & Infrastructure</h2>
|
||||
<span class="badge">8</span>
|
||||
<!-- 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 class="links-grid">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="https://gitea.ourpad.casa" class="link-card">
|
||||
<span class="lc-icon">🦊</span>
|
||||
<div>
|
||||
<div class="lc-text">Gitea</div>
|
||||
<div class="lc-sub">Self-hosted Git — repos, issues, CI</div>
|
||||
</div>
|
||||
</a>
|
||||
<!-- 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">
|
||||
|
||||
<a href="https://pass.ourpad.casa" class="link-card">
|
||||
<span class="lc-icon">🔐</span>
|
||||
<div>
|
||||
<div class="lc-text">Pass Vault</div>
|
||||
<div class="lc-sub">Web-based secret management</div>
|
||||
</div>
|
||||
</a>
|
||||
<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>
|
||||
|
||||
<span class="link-card">
|
||||
<span class="lc-icon">🖥️</span>
|
||||
<div>
|
||||
<div class="lc-text">Proxmox VE</div>
|
||||
<div class="lc-sub">2-node cluster — VMs, LXCs, NAS</div>
|
||||
</div>
|
||||
</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="link-card">
|
||||
<span class="lc-icon">🌐</span>
|
||||
<div>
|
||||
<div class="lc-text">NPMplus</div>
|
||||
<div class="lc-sub">Reverse proxy — *.ourpad.casa</div>
|
||||
</div>
|
||||
<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="link-card">
|
||||
<span class="lc-icon">📥</span>
|
||||
<div>
|
||||
<div class="lc-text">Deluge</div>
|
||||
<div class="lc-sub">Torrent client — media stack</div>
|
||||
</div>
|
||||
<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="link-card">
|
||||
<span class="lc-icon">🎬</span>
|
||||
<div>
|
||||
<div class="lc-text">Jellyfin</div>
|
||||
<div class="lc-sub">Media streaming server</div>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
<span class="link-card">
|
||||
<span class="lc-icon">📺</span>
|
||||
<div>
|
||||
<div class="lc-text">Sonarr + Radarr</div>
|
||||
<div class="lc-sub">TV & movie automation</div>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
<span class="link-card">
|
||||
<span class="lc-icon">⚡</span>
|
||||
<div>
|
||||
<div class="lc-text">Tailscale</div>
|
||||
<div class="lc-sub">Mesh VPN — 2 nodes</div>
|
||||
</div>
|
||||
<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>
|
||||
|
||||
Reference in New Issue
Block a user