#!/usr/bin/env python3
"""MacLustr public website (multi-page). Stdlib only (Python 3.9+).
Runs on m2u64, serves http://0.0.0.0:8004 -> ngrok www.maclustr.io."""
import json, os, html
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from urllib.parse import urlparse
HERE = os.path.dirname(os.path.abspath(__file__))
PORT = 8004
CONTACT = "spbou4@protonmail.com"
NODES = json.load(open(os.path.join(HERE, "nodes.json")))
TIER_ORDER = {"ULTRA": 0, "MAX": 1, "PRO": 2, "BASE": 3}
TCOLOR = {"ULTRA": "#5B21B6", "MAX": "#7C3AED", "PRO": "#2563EB", "BASE": "#0891B2"}
def esc(s): return html.escape(str(s))
def gb_to_tb(g): return f"{g/1024:.1f} TB" if g >= 1024 else f"{g} GB"
def store_gb(v):
v = (v or "").strip()
if v.endswith("TB"): return int(float(v.replace("TB", "").strip())) * 1024
if v.endswith("GB"): return int(float(v.replace("GB", "").strip()))
return 0
# ---- modern line icons (Lucide-style, stroke=currentColor) ----
_P = {
"cpu":' ',
"server":' ',
"cloud":' ',
"zap":' ',
"lock":' ',
"command":' ',
"mail":' ',
"arrow":' ',
"layers":' ',
"db":' ',
"globe":' ',
"check":' ',
"gauge":' ',
"gpu":' ',
"chip":' ',
"hd":' ',
}
def icon(name, size=24, cls=""):
return (f'{_P.get(name,"")} ')
CSS = """
:root{--bg:#fafbfd;--card:#fff;--ink:#0e1016;--ink2:#3a3f4b;--mut:#737a89;--line:#edeff4;
--acc:#7c3aed;--acc2:#2f6bff;--ring:rgba(124,58,237,.14);
--sh:0 1px 2px rgba(16,24,40,.04),0 1px 3px rgba(16,24,40,.06);
--sh2:0 12px 40px rgba(16,24,40,.10);--r:22px}
*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{font-family:-apple-system,BlinkMacSystemFont,"SF Pro Display","SF Pro Text",Helvetica,Arial,sans-serif;
background:var(--bg);color:var(--ink);line-height:1.6;-webkit-font-smoothing:antialiased;letter-spacing:-.01em}
a{color:inherit;text-decoration:none}
svg{display:block}
.wrap{max-width:1080px;margin:0 auto;padding:0 20px}
/* nav */
.nav{position:sticky;top:0;z-index:20;background:rgba(250,251,253,.72);backdrop-filter:saturate(180%) blur(16px);border-bottom:1px solid var(--line)}
.nav .in{max-width:1080px;margin:0 auto;padding:13px 20px;display:flex;align-items:center;gap:12px}
.nav .logo{width:32px;height:32px;border-radius:9px;box-shadow:var(--sh)}
.nav .nm{font-weight:800;font-size:17px;letter-spacing:-.02em}
.nav .links{margin-left:auto;display:flex;align-items:center;gap:6px}
.nav .links a{padding:8px 13px;border-radius:11px;font-size:14px;font-weight:600;color:var(--mut);transition:.15s}
.nav .links a:hover{color:var(--ink);background:#f1f2f7}
.nav .links a.on{color:var(--ink);background:#eef0f6}
.nav .cta{margin-left:6px;background:var(--ink);color:#fff!important;padding:9px 16px!important;border-radius:11px;font-weight:700}
.nav .cta:hover{background:#000;opacity:1}
@media(max-width:640px){.nav .links a:not(.cta){display:none}}
/* generic */
.kick{display:inline-flex;align-items:center;gap:7px;font-size:12.5px;font-weight:700;letter-spacing:.3px;color:var(--acc);
background:var(--ring);padding:6px 13px;border-radius:999px}
.eyebrow{text-align:center}
h1{font-size:clamp(40px,7.5vw,74px);font-weight:830;letter-spacing:-.035em;line-height:1.02}
h2{font-size:clamp(28px,5vw,42px);font-weight:800;letter-spacing:-.03em;line-height:1.08}
.grad{background:linear-gradient(105deg,var(--acc),var(--acc2));-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
.lead{font-size:clamp(16px,2.4vw,20px);color:var(--mut);max-width:660px;line-height:1.55}
.section{padding:62px 0}
.center{text-align:center}.mx{margin-left:auto;margin-right:auto}
.btn{display:inline-flex;align-items:center;gap:9px;font-weight:750;font-size:15.5px;padding:14px 24px;border-radius:14px;transition:.15s}
.btn.p{background:var(--ink);color:#fff;box-shadow:var(--sh2)}
.btn.p:hover{transform:translateY(-1px)}
.btn.g{background:var(--card);color:var(--ink);border:1px solid var(--line);box-shadow:var(--sh)}
.btn.g:hover{background:#f6f7fb}
.row-btn{display:flex;gap:12px;flex-wrap:wrap}
.hero{padding:74px 0 24px;text-align:center}
.hero .logo{width:84px;height:84px;border-radius:22px;box-shadow:var(--sh2);margin:0 auto 24px}
.hero .lead{margin:20px auto 0}
.hero .row-btn{justify-content:center;margin-top:32px}
/* stats */
.stats{display:grid;grid-template-columns:repeat(5,1fr);gap:13px;margin-top:54px}
@media(max-width:780px){.stats{grid-template-columns:repeat(2,1fr)}}
.stat{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:22px 16px;text-align:center;box-shadow:var(--sh)}
.stat .ic{color:var(--acc);margin:0 auto 10px;width:24px}
.stat .n{font-size:clamp(24px,4.6vw,34px);font-weight:830;letter-spacing:-.03em;font-variant-numeric:tabular-nums}
.stat .l{font-size:12px;font-weight:650;text-transform:uppercase;letter-spacing:.5px;color:var(--mut);margin-top:3px}
/* feature cards */
.cards{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:36px}
@media(max-width:820px){.cards{grid-template-columns:1fr}}
.fcard{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:26px;box-shadow:var(--sh);transition:.18s}
.fcard:hover{box-shadow:var(--sh2);transform:translateY(-2px)}
.fcard .ic{width:50px;height:50px;border-radius:15px;display:flex;align-items:center;justify-content:center;color:#fff;
background:linear-gradient(135deg,var(--acc),var(--acc2));box-shadow:0 6px 16px var(--ring);margin-bottom:16px}
.fcard h3{font-size:20px;font-weight:780;letter-spacing:-.02em}
.fcard p{color:var(--mut);font-size:14.8px;margin-top:8px}
.fcard ul{list-style:none;margin-top:14px;display:grid;gap:8px}
.fcard li{display:flex;gap:9px;font-size:14px;color:var(--ink2)}
.fcard li svg{color:var(--acc);flex:0 0 auto;margin-top:3px}
/* nodes */
.tier{display:flex;align-items:center;gap:12px;margin:34px 0 14px}
.tier .pill{display:inline-flex;align-items:center;color:#fff;font-weight:750;font-size:13px;padding:6px 15px;border-radius:10px}
.tier .d{color:var(--mut);font-size:13.5px}
.nodes{display:grid;grid-template-columns:repeat(auto-fill,minmax(252px,1fr));gap:14px}
.node{background:var(--card);border:1px solid var(--line);border-radius:18px;padding:18px;box-shadow:var(--sh);position:relative;overflow:hidden}
.node:before{content:"";position:absolute;left:0;top:0;bottom:0;width:4px;background:var(--tc)}
.node .h{display:flex;align-items:baseline;gap:8px}
.node .nm{font-size:22px;font-weight:820;letter-spacing:-.02em}
.node .md{margin-left:auto;font-size:12px;color:var(--mut);font-weight:600}
.node .ch{font-size:12.5px;color:var(--ink2);font-weight:700;margin-top:1px}
.node .sp{display:grid;grid-template-columns:1fr 1fr;gap:6px 16px;margin-top:14px;font-size:13.5px}
.node .sp>div{display:flex;justify-content:space-between;border-bottom:1px solid var(--line);padding-bottom:5px}
.node .sp span{color:var(--mut)}.node .sp b{font-weight:700;font-variant-numeric:tabular-nums}
/* split / about */
.split{display:grid;grid-template-columns:1.1fr .9fr;gap:40px;align-items:center}
@media(max-width:820px){.split{grid-template-columns:1fr;gap:24px}}
.mini{display:grid;grid-template-columns:1fr 1fr;gap:12px}
.mini .stat{padding:18px 14px;text-align:left}.mini .stat .ic{margin:0 0 8px}
/* steps */
.steps{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:34px;counter-reset:s}
@media(max-width:820px){.steps{grid-template-columns:1fr}}
.step{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:24px;box-shadow:var(--sh)}
.step .no{width:34px;height:34px;border-radius:11px;background:var(--ring);color:var(--acc);font-weight:800;display:flex;align-items:center;justify-content:center;margin-bottom:13px}
.step h3{font-size:18px;font-weight:760}.step p{color:var(--mut);font-size:14.5px;margin-top:6px}
/* contact band */
.band{background:linear-gradient(140deg,#15102a,#1f1640 55%,#10213f);color:#fff;border-radius:30px;padding:clamp(36px,6vw,64px);text-align:center;box-shadow:var(--sh2)}
.band h2{color:#fff}.band p{color:#cdc8e6;max-width:620px;margin:14px auto 0;font-size:17px}
.band .mail{display:inline-flex;align-items:center;gap:11px;margin-top:28px;background:#fff;color:#15102a;font-weight:800;
font-size:clamp(15px,3.6vw,21px);padding:16px 28px;border-radius:15px;word-break:break-all}
.chips{display:flex;gap:9px;justify-content:center;flex-wrap:wrap;margin-top:22px}
.chips span{background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.16);padding:7px 15px;border-radius:999px;font-size:13.5px;font-weight:600}
/* pricing plans */
.plans{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-top:36px}
@media(max-width:900px){.plans{grid-template-columns:repeat(2,1fr)}}
@media(max-width:520px){.plans{grid-template-columns:1fr}}
.plan{background:var(--card);border:1px solid var(--line);border-radius:var(--r);padding:24px;box-shadow:var(--sh);display:flex;flex-direction:column}
.plan.hot{border-color:transparent;background:linear-gradient(160deg,#1a1230,#231a40);color:#fff;box-shadow:var(--sh2)}
.plan .tg{display:inline-flex;align-self:flex-start;color:#fff;font-weight:750;font-size:12px;padding:5px 12px;border-radius:8px;letter-spacing:.4px}
.plan h3{font-size:21px;font-weight:800;margin-top:14px;letter-spacing:-.02em}
.plan .from{font-size:12.5px;color:var(--mut);margin-top:14px;font-weight:600}
.plan.hot .from{color:#bdb6da}
.plan .price{font-size:40px;font-weight:840;letter-spacing:-.03em;line-height:1}
.plan .price small{font-size:15px;font-weight:700;color:var(--mut)}
.plan.hot .price small{color:#bdb6da}
.plan p{color:var(--mut);font-size:13.8px;margin-top:12px}
.plan.hot p{color:#cdc8e6}
.plan ul{list-style:none;margin-top:14px;display:grid;gap:7px;flex:1}
.plan li{display:flex;gap:8px;font-size:13.3px;color:var(--ink2)}
.plan.hot li{color:#e7e2f5}
.plan li svg{color:var(--acc);flex:0 0 auto;margin-top:2px}
.plan.hot li svg{color:#b794ff}
.plan a.cta2{margin-top:18px;text-align:center;background:var(--ink);color:#fff;font-weight:750;padding:12px;border-radius:12px;font-size:14.5px}
.plan.hot a.cta2{background:#fff;color:#1a1230}
/* pricing table */
.ptable{margin-top:18px;border:1px solid var(--line);border-radius:18px;overflow:hidden;box-shadow:var(--sh);background:var(--card)}
.pscroll{overflow-x:auto}
table.pg{border-collapse:collapse;width:100%;min-width:620px;font-size:14px}
table.pg th,table.pg td{text-align:right;padding:13px 14px;border-bottom:1px solid var(--line);white-space:nowrap}
table.pg th:first-child,table.pg td:first-child,table.pg th:nth-child(2),table.pg td:nth-child(3){text-align:left}
table.pg thead th{font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--mut);font-weight:750;background:#fafbfd}
table.pg tbody tr:last-child td{border-bottom:0}
table.pg tbody tr:hover{background:#fafbfd}
table.pg .node-nm{font-weight:800;letter-spacing:-.01em}
table.pg .tg{display:inline-block;color:#fff;font-size:11px;font-weight:750;padding:3px 9px;border-radius:7px}
table.pg .spec{color:var(--mut);font-variant-numeric:tabular-nums}
table.pg .ml{font-weight:800;font-variant-numeric:tabular-nums}
table.pg .aws{color:var(--mut);text-decoration:line-through;font-variant-numeric:tabular-nums}
table.pg .num{font-variant-numeric:tabular-nums}
.note{color:var(--mut);font-size:12.5px;margin-top:14px;line-height:1.6}
/* whole-cluster banner */
.clusterbox{background:linear-gradient(140deg,#15102a,#1f1640 55%,#10213f);color:#fff;border-radius:28px;padding:clamp(28px,5vw,52px);box-shadow:var(--sh2);margin-top:34px}
.clusterbox .kick{background:rgba(255,255,255,.14);color:#fff}
.clusterbox h2{color:#fff;margin-top:14px}
.clusterbox .sub2{color:#cdc8e6;margin-top:10px;font-size:16.5px;max-width:640px}
.cl-prices{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-top:26px}
@media(max-width:680px){.cl-prices{grid-template-columns:repeat(2,1fr)}}
.cl-prices>div{background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.15);border-radius:16px;padding:18px 16px}
.cl-prices .hl{background:#fff;color:#15102a;border-color:#fff}
.cl-prices .l{font-size:11.5px;font-weight:750;text-transform:uppercase;letter-spacing:.5px;opacity:.82}
.cl-prices .n{font-size:clamp(22px,3.6vw,32px);font-weight:840;letter-spacing:-.03em;margin-top:5px;font-variant-numeric:tabular-nums}
.cl-prices .p{font-size:12px;opacity:.7;margin-top:2px}
.cl-incl{display:flex;flex-wrap:wrap;gap:8px;margin-top:24px}
.cl-incl span{background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.16);padding:7px 14px;border-radius:999px;font-size:13px;font-weight:600}
.clusterbox .btn{margin-top:26px;background:#fff;color:#15102a}
.clusterbox .fine{color:#b3aace;font-size:12.5px;margin-top:16px;line-height:1.6}
/* footer */
footer{border-top:1px solid var(--line);margin-top:30px}
footer .in{max-width:1080px;margin:0 auto;padding:30px 20px;display:flex;gap:14px;align-items:center;flex-wrap:wrap;color:var(--mut);font-size:13.5px}
footer .nm{display:flex;align-items:center;gap:9px;font-weight:750;color:var(--ink)}
footer .nm img{width:24px;height:24px;border-radius:7px}
footer .lk{margin-left:auto;display:flex;gap:18px}
footer .lk a:hover{color:var(--ink)}
"""
def nav(active):
def lk(href, label, key):
return f'{label} '
return f"""
MacLustr
{lk('/','Home','home')}{lk('/nodes','Nodes','nodes')}{lk('/services','Services','services')}{lk('/pricing','Pricing','pricing')}{lk('/about','About','about')}
Request access """
def footer():
return f""""""
def shell(title, active, body, desc=""):
return f"""
{esc(title)}
{nav(active)}{body}{footer()}"""
def totals():
return dict(
n=len(NODES),
cpu=sum(n["ncpu"] for n in NODES),
gpu=sum(n["gpu"] for n in NODES),
ne=sum(n["ne"] for n in NODES),
ram=sum(n["mem"] for n in NODES),
store=sum(store_gb(n["internal"]) + store_gb(n["external"]) for n in NODES),
)
def stat(ic, n, l):
return f''
def stats_block():
t = totals()
return (f''
f'{stat("server",t["n"],"Nodes")}'
f'{stat("cpu",t["cpu"],"CPU cores")}'
f'{stat("chip",t["ram"],"GB unified RAM")}'
f'{stat("gpu",t["gpu"],"GPU cores")}'
f'{stat("hd",gb_to_tb(t["store"]),"SSD storage")}'
f'
')
def node_card(n):
storage = f'{n["internal"]} SSD' + (f' + {n["external"]} ext' if n["external"] else "")
return (f''
f'
{esc(n["alias"])} {esc(n["model"])}
'
f'
{esc(n["chip"])}
'
f'
'
f'
CPU {n["ncpu"]}c
'
f'
GPU {n["gpu"]}c
'
f'
RAM {n["mem"]} GB
'
f'
Neural {n["ne"]}c
'
f'
Storage {esc(storage)}
'
f'
')
def nodes_grouped():
order = sorted(NODES, key=lambda n: (TIER_ORDER.get(n["tier"], 9), -n["ncpu"], -n["mem"]))
tiers = {}
for n in order: tiers.setdefault(n["tier"], []).append(n)
desc = {"ULTRA": "Mac Studio · M-series Ultra — heaviest compute & training",
"MAX": "Mac Studio / MacBook Pro · M-series Max — high-throughput workloads",
"PRO": "Mac mini · M-series Pro — balanced services & build agents",
"BASE": "Mac mini / MacBook Air · M-series — lightweight always-on services"}
out = ""
for t, lst in tiers.items():
out += (f'{esc(t)} '
f'{len(lst)} node{"s" if len(lst)>1 else ""} · {esc(desc.get(t,""))}
'
f'{"".join(node_card(n) for n in lst)}
')
return out
# ---------- pages ----------
def page_home():
t = totals()
body = f"""
{icon('command',16)} Self-hosted · Apple Silicon
The self-hosted Apple Silicon cluster
A private cluster of {t['n']} Apple Silicon Macs — Mac Studio, MacBook Pro, Mac mini and MacBook Air — networked for distributed compute, hosting and private cloud.
{stats_block()}
Why MacLustr
Real hardware, not a rented VM
We pool genuine Apple Silicon — {t['cpu']} CPU cores, {t['ram']} GB unified memory, {t['gpu']} GPU cores and {t['ne']} Neural Engine cores — into one cluster you fully control.
{icon('zap')}
Distributed compute Spread heavy jobs across {t['n']} machines — ML training & inference, simulation, batch processing and rendering.
{icon('cloud')}
Private cloud Your own always-on infrastructure: APIs, databases, model servers and storage on dedicated hardware.
{icon('command')}
Native macOS True Apple Silicon for macOS/iOS builds, CI agents and anything that must run on real Macs.
{contact_band()}
"""
return shell("MacLustr — Self-Hosted Apple Silicon Compute Cluster", "home", body,
f"MacLustr is a self-hosted cluster of {t['n']} Apple Silicon Macs for compute, hosting and private cloud.")
def page_nodes():
t = totals()
body = f"""
{icon('layers',16)} The fleet
Every node, fully specced
{t['n']} dedicated Apple Silicon Macs, grouped by tier. Pick the one that matches your workload.
{stats_block()}
{nodes_grouped()}
{contact_band()}
"""
return shell("Nodes — MacLustr", "nodes", body, "Full specifications of every MacLustr cluster node.")
def page_services():
body = f"""
{icon('server',16)} Services
What you can run on MacLustr
Three ways to put our Apple Silicon to work — rent it by the job, host a service, or get a private slice of cloud.
{icon('gauge')}
Compute
Rent cores and GPU / Neural Engine time for demanding jobs.
{icon('check',16)} ML training & inference {icon('check',16)} Simulation & data processing {icon('check',16)} Batch jobs & rendering
{icon('globe')}
Hosting
Run a service on a dedicated node with a real public endpoint.
{icon('check',16)} Websites & APIs {icon('check',16)} Bots & background workers {icon('check',16)} Public HTTPS endpoint
{icon('lock')}
Private cloud
An isolated, always-on slice of the cluster that's yours.
{icon('check',16)} Storage & databases {icon('check',16)} Model & app servers {icon('check',16)} Dedicated, isolated resources
How it works
From request to running
1
Tell us your workload Email a short description — what you want to run, rough resources and how long.
2
We match a node We pick the right tier — Ultra, Max, Pro or Base — and set up access.
3
You go live Get credentials / an endpoint and start running. Monitor each node's live page anytime.
{contact_band()}
"""
return shell("Services — MacLustr", "services", body, "Compute, hosting and private cloud on the MacLustr Apple Silicon cluster.")
def page_about():
t = totals()
# model breakdown
counts = {}
for n in NODES: counts[n["model"]] = counts.get(n["model"], 0) + 1
chips = " · ".join(f"{v}× {k}" for k, v in sorted(counts.items(), key=lambda x: -x[1]))
body = f"""
{icon('cpu',16)} About
A cluster built from real Macs
MacLustr is a self-hosted cluster of {t['n']} Apple Silicon Macs running native macOS. Instead of renting generic cloud VMs, we pool genuine Mac hardware — fast unified memory, powerful GPUs and Neural Engines, and energy-efficient Apple Silicon — into one cluster you can run heavy workloads on.
The fleet spans {esc(chips)} — from top-tier Ultra Studios for training down to efficient minis and Airs for always-on services.
{stat("cpu",t["cpu"],"CPU cores")}
{stat("chip",t["ram"],"GB RAM")}
{stat("gpu",t["gpu"],"GPU cores")}
{stat("command",t["ne"],"Neural cores")}
{stat("server",t["n"],"Nodes")}
{stat("hd",gb_to_tb(t["store"]),"SSD")}
Principles
Why self-hosted
{icon('lock')}
Yours, end to end Dedicated hardware you control — no noisy neighbours, no surprise migrations.
{icon('zap')}
Efficient & fast Apple Silicon delivers huge unified memory and performance per watt.
{icon('gauge')}
Transparent Every node has a live status page — see real CPU, memory and disk anytime.
{contact_band()}
"""
return shell("About — MacLustr", "about", body, "About the MacLustr self-hosted Apple Silicon cluster.")
def page_contact():
body = f"""
{icon('mail',16)} Contact
Let's find the right node for you
Need compute, hosting or private cloud on one of our nodes? Send a short note about your workload and we'll get back to you.
{contact_band()}
What to include
{icon('gauge')}
Your workload What you want to run — compute job, a service to host, or a private cloud space.
{icon('chip')}
Rough resources Cores, memory, GPU, storage — even a ballpark helps us match a tier.
{icon('db')}
Duration One-off job or always-on? Let us know the timeframe.
"""
return shell("Contact — MacLustr", "contact", body, f"Contact MacLustr at {CONTACT} for compute, hosting and cloud.")
# ---- pricing (USD). MacLustr rate ~= 10% below a comparable AWS EC2 Mac Dedicated Host. ----
# rate = MacLustr $/h ; AWS est. $/h = rate / 0.9 ; day = rate*24 ; month = rate*730
RATES = {
"m3u96a": 8.44, "m3u96b": 8.44, "m2u64": 7.47,
"m4m64a": 7.47, "m4m64b": 7.47, "m4bp48": 6.72, "m4m36": 5.41, "m4bp36": 5.41,
"m2m32": 1.40, "m2m32b": 1.40, "m2m32c": 1.40, "m1m32": 1.35,
"m4mc": 0.77, "m2m16": 0.99, "m4ma": 1.11, "m4mb": 0.96,
"m3ba24": 0.59, "m3ba16": 0.51, "m2m8a": 0.43, "m2m8b": 0.43,
}
PLANS = [
("ULTRA", "#5B21B6", "AI & heavy compute", 7.50, True,
"M-series Ultra & M4 Max with 64–96 GB unified memory. Built for model training, large-context inference and the heaviest jobs.",
["64–96 GB unified memory", "Up to 60 GPU + 32 Neural cores", "Dedicated, isolated host", "24h minimum"]),
("MAX", "#7C3AED", "High-throughput power", 5.50, False,
"M4 Max nodes with 36–48 GB. Strong GPU and compute for demanding production workloads.",
["36–48 GB unified memory", "40 GPU cores · 16 CPU cores", "Latest-gen Apple Silicon", "Dedicated host"]),
("STUDIO", "#2563EB", "Dedicated mid-tier", 1.35, False,
"M2 / M1 Max Studios with ~32 GB. Reliable dedicated power at an accessible price.",
["30–32 GB unified memory", "24–30 GPU cores", "Always-on dedicated node", "Great price/perf"]),
("WORKER", "#0891B2", "CI · hosting · light AI", 0.43, False,
"Mac mini & MacBook Air (M-series Pro/Base). Perfect for CI/CD, web hosting, agents and light inference.",
["8–24 GB unified memory", "Mac mini / MacBook Air", "Web & API hosting, CI runners", "Pay only for what you run"]),
]
def fmt(v): return f"${v:,.2f}"
def fmt0(v): return f"${v:,.0f}"
def plan_card(p):
tier, color, tag, frm, hot, desc, feats = p
feats_html = "".join(f"{icon('check',16)} {f} " for f in feats)
return (f''
f'
{tier} '
f'
{tag} '
f'
from
'
f'
{fmt(frm)}/hour
'
f'
{desc}
'
f'
Request access ')
def pricing_rows():
rows = ""
order = sorted(NODES, key=lambda n: -RATES.get(n["slug"], 0))
for n in order:
h = RATES.get(n["slug"], 0)
aws = h / 0.9
day = h * 24
month = h * 730
spec = f'{n["ncpu"]}C / {n["gpu"]}G / {n["mem"]}GB'
rows += (f'{esc(n["alias"])} '
f'{esc(n["tier"])} '
f'{esc(spec)} '
f'{fmt(aws)} '
f'{fmt(h)} '
f'{fmt(day)} '
f'{fmt0(month)}/mo ')
return rows
def whole_cluster():
compute_h = sum(RATES.values())
storage_mo = 35000 * 0.05 + 45000 * 0.02 # 35 TB SSD + 45 TB HDD external
total_h = compute_h + storage_mo / 730
day = total_h * 24
month = total_h * 730
year = total_h * 8760
t = totals()
def cell(label, val, per, hl=False):
return (f'')
return f"""
{icon('layers',16)} Whole infrastructure
Rent the entire cluster
Every node and all external storage, exclusively yours — a turn-key private Apple Silicon cloud.
{cell("Hourly", fmt(total_h), "per hour")}
{cell("Daily", fmt0(day), "24 hours")}
{cell("Monthly", fmt0(month), "730 hours", hl=True)}
{cell("Yearly", fmt0(year), "8,760 hours")}
{t['n']} nodes {t['cpu']} CPU cores {t['ram']} GB RAM {t['gpu']} GPU cores {t['ne']} Neural cores 35 TB SSD + 45 TB HDD external
Reserve the full cluster {icon('arrow',18)}
Includes every node (with their internal SSDs) plus the full 80 TB external storage pool — 35 TB SSD and 45 TB HDD. Annual and long-term commitments qualify for a custom discount.
"""
def page_pricing():
body = f"""
{icon('gauge',16)} Pricing
Dedicated Apple Silicon, ~10% below AWS
Transparent per-node pricing, benchmarked against AWS EC2 Mac Dedicated Hosts (24-hour minimum). Rent by the hour, day, month or year.
{whole_cluster()}
{icon('server',16)} By the node
Or pick a plan
{"".join(plan_card(p) for p in PLANS)}
{icon('layers',16)} Full price list
Every node, per hour
Hourly rate, plus 24-hour and 730-hour (monthly) totals. AWS column shows a comparable EC2 Mac Dedicated Host estimate.
Prices in USD. Specs shown as CPU cores / GPU cores / unified memory. MacLustr /h is our rate; AWS est. is a comparable AWS EC2 Mac Dedicated Host (on-demand, 24h minimum) — MacLustr runs about 10% below. Monthly assumes 730 hours of continuous use; short jobs are billed hourly. Custom and long-term plans available on request.
{icon('hd',16)} Storage add-ons
Need more space?
Attach external storage to any node — fast SSD for hot data, high-capacity HDD for archives and backups. Pay per gigabyte, per month.
{icon('hd')}
External SSD
Fast SSD storage for active datasets, databases and model weights.
$0.05 / GB · month
{icon('check',16)} ≈ $50 per TB · month {icon('check',16)} Up to 35 TB available {icon('check',16)} High throughput, low latency
{icon('db')}
External HDD
High-capacity spinning disk for archives, backups and cold storage.
$0.02 / GB · month
{icon('check',16)} ≈ $20 per TB · month {icon('check',16)} Up to 45 TB available {icon('check',16)} Ideal for backups & archives
Storage add-ons are billed per GB-month and attach to any rented node. Total external pools available: 35 TB SSD and 45 TB HDD . Larger or dedicated volumes available on request.
{contact_band()}
"""
return shell("Pricing — MacLustr", "pricing", body,
"MacLustr pricing: dedicated Apple Silicon nodes ~10% below comparable AWS EC2 Mac Dedicated Hosts.")
def contact_band():
return f"""
Need compute, hosting or cloud?
If you need any kind of computation, hosting or private cloud on one of our nodes, write to us — describe your workload and we'll find the right node.
{icon('mail',20)}{CONTACT}
Compute jobs ML training / inference Web & API hosting Private cloud macOS CI
"""
ROUTES = {"": page_home, "nodes": page_nodes, "services": page_services,
"pricing": page_pricing, "about": page_about, "contact": page_contact}
LOGO_PATH = os.path.join(HERE, "logo.svg")
LOGO = open(LOGO_PATH).read() if os.path.exists(LOGO_PATH) else " "
class H(BaseHTTPRequestHandler):
def log_message(self, *a): pass
def _send(self, code, body, ctype="text/html; charset=utf-8"):
b = body.encode() if isinstance(body, str) else body
self.send_response(code)
self.send_header("Content-Type", ctype)
self.send_header("Content-Length", str(len(b)))
self.send_header("Cache-Control", "no-store")
self.end_headers()
try: self.wfile.write(b)
except (BrokenPipeError, ConnectionResetError): pass
def do_GET(self):
path = urlparse(self.path).path.strip("/")
if path in ("health", "healthz"): return self._send(200, "ok", "text/plain")
if path == "logo.svg": return self._send(200, LOGO, "image/svg+xml")
if path in ROUTES: return self._send(200, ROUTES[path]())
nf = 'Page not found Sorry, that page does not exist.
'
return self._send(404, shell("Not found — MacLustr", "", nf))
if __name__ == "__main__":
srv = ThreadingHTTPServer(("0.0.0.0", PORT), H)
print(f"MacLustr landing on :{PORT} ({len(NODES)} nodes)")
srv.serve_forever()