mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 19:13:34 +00:00
1054 lines
72 KiB
HTML
1054 lines
72 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>Self-host and scale web apps without Kubernetes complexity | Uncloud</title>
|
||
<meta name="description"
|
||
content="Take your Docker Compose apps to production with zero-downtime deployments, automatic HTTPS, and cross-machine scaling. Self-hosting made reliable without the complexity.">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<link href="./style.css" rel="stylesheet">
|
||
<link rel="apple-touch-icon" href="./images/apple-touch-icon.png" sizes="180x180"/>
|
||
<link rel="icon" type="image/svg+xml" href="./images/logo.svg"/>
|
||
<link rel="alternate icon" type="image/png" href="./images/favicon.png" sizes="96x96"/>
|
||
|
||
<!-- OpenGraph tags for social media -->
|
||
<meta property="og:title"
|
||
content="Self-host and scale web apps without Kubernetes complexity | Uncloud"/>
|
||
<meta property="og:description"
|
||
content="Take your Docker Compose apps to production with zero-downtime deployments, automatic HTTPS, and cross-machine scaling. Self-hosting made reliable without the complexity."/>
|
||
<meta property="og:image" content="https://uncloud.run/images/logo-wide.png"/>
|
||
<meta property="og:image:alt" content="Uncloud logo - Self-host web apps with ease"/>
|
||
<meta property="og:url" content="https://uncloud.run"/>
|
||
<meta property="og:type" content="website"/>
|
||
<meta property="og:site_name" content="Uncloud"/>
|
||
<!-- Twitter card tags -->
|
||
<meta property="twitter:domain" content="uncloud.run">
|
||
<meta property="twitter:url" content="https://uncloud.run">
|
||
<meta name="twitter:card" content="summary_large_image">
|
||
<meta name="twitter:title"
|
||
content="Self-host and scale web apps without Kubernetes complexity | Uncloud">
|
||
<meta name="twitter:description"
|
||
content="Take your Docker Compose apps to production with zero-downtime deployments, automatic HTTPS, and cross-machine scaling. Self-hosting made reliable without the complexity.">
|
||
<meta name="twitter:image" content="https://uncloud.run/images/logo-wide.png">
|
||
<meta name="twitter:image:alt" content="Uncloud logo - Self-host web apps with ease">
|
||
<style>
|
||
/* Prevent all inline SVGs from appearing full screen */
|
||
svg {
|
||
max-width: 24px;
|
||
max-height: 24px;
|
||
}
|
||
|
||
.text-balance {
|
||
text-wrap: balance;
|
||
}
|
||
</style>
|
||
</head>
|
||
|
||
<body class="font-inter antialiased bg-white text-zinc-900 tracking-tight">
|
||
|
||
<!-- Page wrapper -->
|
||
<div class="flex flex-col min-h-screen overflow-hidden supports-[overflow:clip]:overflow-clip">
|
||
|
||
<!-- Site header -->
|
||
<header class="absolute top-2 md:top-6 w-full z-30">
|
||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||
<div class="flex items-center justify-between h-14">
|
||
<!-- Site branding -->
|
||
<div class="shrink-0 mr-4">
|
||
<a class="flex items-center" href="/">
|
||
<img class="w-8 h-8 rounded-lg shadow-sm shadow-zinc-950/20" src="./images/logo.svg" alt="Logo"
|
||
width="32" height="32">
|
||
<span class="ml-2 font-semibold text-lg text-zinc-900">uncloud</span>
|
||
</a>
|
||
</div>
|
||
|
||
<!-- Navigation links -->
|
||
<nav class="flex grow">
|
||
<!-- Left side navigation -->
|
||
<ul class="flex items-center">
|
||
<li>
|
||
<a class="text-sm font-medium text-zinc-500 hover:text-zinc-900 px-2 sm:px-5 py-2 transition"
|
||
href="/docs">Docs</a>
|
||
</li>
|
||
<li>
|
||
<a class="text-sm font-medium text-zinc-500 hover:text-zinc-900 px-2 sm:px-5 py-2 transition"
|
||
href="/blog">Blog</a>
|
||
</li>
|
||
<li>
|
||
<a class="text-sm font-medium text-zinc-500 hover:text-zinc-900 px-2 sm:px-5 py-2 transition"
|
||
href="https://psviderski.substack.com/" target="_blank">Newsletter</a>
|
||
</li>
|
||
</ul>
|
||
<!-- Right side navigation -->
|
||
<ul class="flex grow justify-end items-center shrink-0">
|
||
<li>
|
||
<a class="text-sm font-medium text-zinc-500 hover:text-zinc-900 px-2 sm:px-5 py-2 flex items-center transition"
|
||
href="https://discord.gg/eR35KQJhPu">
|
||
<svg class="w-4 h-4 sm:mr-1 fill-current" xmlns="http://www.w3.org/2000/svg"
|
||
viewBox="0 0 24 24">
|
||
<path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z"/>
|
||
</svg>
|
||
<span class="ml-1 hidden sm:inline">Discord</span>
|
||
</a>
|
||
</li>
|
||
<li>
|
||
<a class="text-sm font-medium text-zinc-500 hover:text-zinc-900 px-1 sm:px-5 py-2 flex items-center transition"
|
||
href="https://github.com/psviderski/uncloud">
|
||
<svg class="w-4 h-4 sm:mr-1 fill-current" xmlns="http://www.w3.org/2000/svg"
|
||
viewBox="0 0 24 24">
|
||
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
|
||
</svg>
|
||
<span class="ml-1 hidden sm:inline">GitHub</span>
|
||
<!-- Populated only when the star count is successfully fetched from the GitHub API. -->
|
||
<span class="js-github-stars text-zinc-400 ml-1 hidden sm:inline tabular-nums"></span>
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- Page content -->
|
||
<main class="grow">
|
||
|
||
<!-- Hero -->
|
||
<section
|
||
class="relative before:absolute before:inset-0 before:h-80 before:pointer-events-none before:bg-gradient-to-b before:from-zinc-100 before:-z-10">
|
||
<div class="pt-32 pb-12 md:pt-40 md:pb-20">
|
||
<!-- Section content -->
|
||
<div class="px-4 sm:px-6">
|
||
<div class="max-w-3xl mx-auto">
|
||
<div class="text-center pb-12 md:pb-16">
|
||
<h1 class="font-inter-tight text-4xl md:text-5xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-zinc-500 via-zinc-900 to-zinc-900 pb-4">
|
||
Multi-machine Docker Compose for production
|
||
</h1>
|
||
<p class="text-lg text-zinc-500 mb-8">
|
||
Uncloud creates a Docker cluster with self-configuring WireGuard mesh, zero-downtime
|
||
deploys, cross-machine scaling, automatic HTTPS via Caddy, service discovery, and an
|
||
intuitive CLI.
|
||
Everything you need to run web apps on cloud VMs or your own hardware, using
|
||
familiar Compose files. Without cluster-management overhead.
|
||
</p>
|
||
<p class="text-base text-zinc-500 mb-8">
|
||
A simpler alternative to
|
||
<span class="font-medium text-zinc-700">Kubernetes</span>,
|
||
<span class="font-medium text-zinc-700">Swarm</span>,
|
||
<span class="font-medium text-zinc-700">Nomad</span>, and
|
||
<span class="font-medium text-zinc-700">Kamal</span>.
|
||
</p>
|
||
<div class="max-w-xs mx-auto sm:max-w-none sm:inline-flex sm:justify-center space-y-4 sm:space-y-0 sm:space-x-4">
|
||
<div>
|
||
<a class="btn text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow flex items-center justify-center"
|
||
href="https://github.com/psviderski/uncloud/?tab=readme-ov-file#-quick-start">
|
||
<svg class="w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
|
||
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
||
stroke-linejoin="round">
|
||
<path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z"/>
|
||
<path d="m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z"/>
|
||
<path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0"/>
|
||
<path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"/>
|
||
</svg>
|
||
Deploy your first app
|
||
</a>
|
||
</div>
|
||
<div>
|
||
<a class="btn text-zinc-600 bg-white hover:text-zinc-900 w-full shadow flex items-center justify-center"
|
||
href="https://github.com/psviderski/uncloud">
|
||
<svg class="w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
|
||
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
||
stroke-linejoin="round">
|
||
<path d="m12 2 3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2Z"/>
|
||
</svg>
|
||
Star on GitHub
|
||
<span class="js-github-stars ml-2 text-sm font-normal text-zinc-400 tabular-nums"></span>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Demo screencast -->
|
||
<div class="max-w-6xl mx-auto px-4 sm:px-6 flex justify-center pb-12 md:pb-20 relative before:absolute before:-top-12 before:left-1/2 before:-translate-x-1/2 before:w-96 before:h-96 before:bg-zinc-900 before:opacity-[.15] before:rounded-full before:blur-3xl before:-z-10">
|
||
<video class="block w-full rounded-lg shadow-2xl"
|
||
controls playsinline preload="metadata"
|
||
aria-label="Demo: build, push, and deploy an app to two machines with a Compose file"
|
||
poster="https://media.uncloud.run/uc-deploy-demo.webp">
|
||
<source src="https://media.uncloud.run/uc-deploy-demo.mp4" type="video/mp4">
|
||
Your browser does not support the video tag.
|
||
</video>
|
||
</div>
|
||
|
||
<!-- Stats -->
|
||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||
<div class="max-w-sm mx-auto grid gap-12 sm:grid-cols-2 md:grid-cols-4 md:-mx-5 md:gap-0 items-start md:max-w-none">
|
||
<!-- GitHub stars -->
|
||
<a href="https://github.com/psviderski/uncloud" target="_blank" rel="noopener"
|
||
class="group block relative text-center md:px-5 after:hidden md:after:block after:absolute after:right-0 after:top-1/2 after:-translate-y-1/2 after:w-px after:h-8 after:border-l after:border-zinc-300 after:border-dashed last:after:hidden">
|
||
<h4 class="font-inter-tight text-2xl md:text-3xl font-bold tabular-nums mb-2"><span
|
||
x-data="counter(githubStarsK)" x-text="counterValue">5.2</span>K+</h4>
|
||
<p class="text-zinc-500 transition-colors group-hover:text-zinc-800">GitHub
|
||
stars</p>
|
||
</a>
|
||
|
||
<!-- Downloads -->
|
||
<a href="https://github.com/psviderski/uncloud/releases" target="_blank" rel="noopener"
|
||
class="group block relative text-center md:px-5 after:hidden md:after:block after:absolute after:right-0 after:top-1/2 after:-translate-y-1/2 after:w-px after:h-8 after:border-l after:border-zinc-300 after:border-dashed last:after:hidden">
|
||
<h4 class="font-inter-tight text-2xl md:text-3xl font-bold tabular-nums mb-2"><span
|
||
x-data="counter(downloadsK)" x-text="counterValue">21</span>K+</h4>
|
||
<p class="text-zinc-500 transition-colors group-hover:text-zinc-800">Downloads</p>
|
||
</a>
|
||
|
||
<!-- Hacker News front-page -->
|
||
<a href="https://news.ycombinator.com/item?id=46144275" target="_blank" rel="noopener"
|
||
class="group block relative text-center md:px-5 after:hidden md:after:block after:absolute after:right-0 after:top-1/2 after:-translate-y-1/2 after:w-px after:h-8 after:border-l after:border-zinc-300 after:border-dashed last:after:hidden">
|
||
<h4 class="font-inter-tight text-2xl md:text-3xl font-bold tabular-nums mb-2"><span
|
||
x-data="counter(2)" x-text="counterValue">2</span>x</h4>
|
||
<p class="text-zinc-500 transition-colors group-hover:text-zinc-800">Hacker News
|
||
front page</p>
|
||
</a>
|
||
|
||
<!-- Discord members. -->
|
||
<a href="https://uncloud.run/discord" target="_blank" rel="noopener"
|
||
class="group block relative text-center md:px-5 after:hidden md:after:block after:absolute after:right-0 after:top-1/2 after:-translate-y-1/2 after:w-px after:h-8 after:border-l after:border-zinc-300 after:border-dashed last:after:hidden">
|
||
<h4 class="font-inter-tight text-2xl md:text-3xl font-bold tabular-nums mb-2"><span
|
||
x-data="counter(380)" x-text="counterValue">380</span></h4>
|
||
<p class="text-zinc-500 transition-colors group-hover:text-zinc-800">Fans on
|
||
Discord</p>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Testimonial -->
|
||
<section class="relative bg-zinc-900 overflow-hidden">
|
||
<!-- Soft glow echoing the hero. -->
|
||
<div class="pointer-events-none absolute inset-0" aria-hidden="true">
|
||
<div class="absolute left-1/2 top-0 w-[36rem] h-[36rem] -translate-x-1/2 -translate-y-1/3 rounded-full bg-zinc-700 opacity-20 blur-3xl"></div>
|
||
</div>
|
||
<div class="relative max-w-6xl mx-auto px-4 sm:px-6">
|
||
<div class="py-16 md:py-24">
|
||
<figure class="max-w-3xl mx-auto text-center">
|
||
<span class="block font-inter-tight text-7xl leading-none text-zinc-700 select-none"
|
||
aria-hidden="true">“</span>
|
||
<blockquote
|
||
class="-mt-5 font-inter-tight text-2xl sm:text-3xl lg:text-4xl font-medium leading-snug text-balance text-zinc-400">
|
||
We’re moving <span class="text-zinc-100">300+ websites</span> onto
|
||
<span class="text-zinc-100">a dozen Uncloud machines</span>, where each owner gets their own
|
||
machines to run whatever they need.
|
||
</blockquote>
|
||
<a class="group inline-flex items-center gap-1.5 mt-6 text-sm font-medium text-zinc-300 underline decoration-zinc-400 underline-offset-4 hover:text-zinc-100 hover:decoration-zinc-100 transition-colors"
|
||
href="https://cncz.science.ru.nl/news/2026-04-15_uncloud/" target="_blank" rel="noopener">
|
||
Read Radboud University’s announcement
|
||
<svg class="w-4 h-4 shrink-0 no-underline transition-transform group-hover:translate-x-0.5"
|
||
fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" d="M5 12h14m-6-6 6 6-6 6"/>
|
||
</svg>
|
||
</a>
|
||
<figcaption class="mt-10 flex items-center justify-center gap-4">
|
||
<img class="w-14 h-14 rounded-full shadow-lg shadow-zinc-950/40"
|
||
src="https://avatars.githubusercontent.com/u/353371?v=4"
|
||
width="56" height="56" loading="lazy" decoding="async" alt="Miek Gieben">
|
||
<div class="text-left">
|
||
<div class="font-inter-tight font-semibold text-zinc-100">Miek Gieben</div>
|
||
<div class="text-sm text-zinc-400">
|
||
Creator of CoreDNS · ex-Google SRE · Radboud University
|
||
</div>
|
||
</div>
|
||
</figcaption>
|
||
</figure>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Workflow: chess-layout feature blocks. Each row alternates text/terminal. -->
|
||
<section id="workflow" class="relative bg-white">
|
||
<div class="py-12 md:py-20">
|
||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||
|
||
<!-- 01 · Create a cluster (text left, terminal right) -->
|
||
<article class="grid lg:grid-cols-2 gap-10 lg:gap-16 items-center">
|
||
<!-- Text -->
|
||
<div class="lg:max-w-md">
|
||
<div class="font-mono text-xs font-medium uppercase tracking-[0.18em] text-zinc-600 mb-4">
|
||
Create a cluster
|
||
</div>
|
||
<h2 class="font-inter-tight text-3xl md:text-4xl font-bold text-zinc-900 mb-4">
|
||
Turn any Linux machines into a Docker cluster
|
||
</h2>
|
||
<p class="text-lg text-zinc-500 mb-6">
|
||
Uncloud creates a lightweight decentralised cluster of Docker hosts that share their
|
||
state peer-to-peer. The cluster keeps running even if some machines go down.
|
||
<br><br>
|
||
Each machine joins a secure WireGuard mesh network, so services can talk to each other
|
||
across machines.
|
||
</p>
|
||
<ul class="space-y-3 text-zinc-500">
|
||
<li class="flex gap-3 items-start">
|
||
<svg class="w-4 h-4 text-green-500 shrink-0 mt-1" fill="none"
|
||
stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||
d="M5 13l4 4L19 7"/>
|
||
</svg>
|
||
Mix cloud VMs and bare-metal servers
|
||
</li>
|
||
<li class="flex gap-3 items-start">
|
||
<svg class="w-4 h-4 text-green-500 shrink-0 mt-1" fill="none"
|
||
stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||
d="M5 13l4 4L19 7"/>
|
||
</svg>
|
||
No control plane or quorum to maintain
|
||
</li>
|
||
<li class="flex gap-3 items-start">
|
||
<svg class="w-4 h-4 text-green-500 shrink-0 mt-1" fill="none"
|
||
stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||
d="M5 13l4 4L19 7"/>
|
||
</svg>
|
||
Cheap enough to run a cluster per team, project, or client
|
||
</li>
|
||
<li class="flex gap-3 items-start">
|
||
<svg class="w-4 h-4 text-green-500 shrink-0 mt-1" fill="none"
|
||
stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||
d="M5 13l4 4L19 7"/>
|
||
</svg>
|
||
SSH is all you need
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<!-- Terminal -->
|
||
<div class="rounded-xl bg-zinc-950 border border-zinc-800 shadow-2xl shadow-zinc-950/40 overflow-hidden"
|
||
role="img"
|
||
aria-label="Terminal: uc machine init installs Docker and Uncloud on the first machine over SSH and initialises the cluster, uc machine add joins a second machine over WireGuard, and uc machine ls lists both machines as ready.">
|
||
<div class="flex items-center gap-2 px-4 py-3.5 bg-zinc-900">
|
||
<span class="w-3 h-3 rounded-full bg-[#e05a4f]"></span>
|
||
<span class="w-3 h-3 rounded-full bg-[#e0a552]"></span>
|
||
<span class="w-3 h-3 rounded-full bg-[#5bbf6a]"></span>
|
||
</div>
|
||
<pre class="font-mono text-[13px] leading-relaxed text-zinc-400 p-5 overflow-x-auto"><span
|
||
class="font-bold text-green-500">$</span> <span class="text-zinc-200">uc machine init</span> --name prod-1 root@137.123.45.67
|
||
...
|
||
<span class="text-green-500">✔</span> Docker installed and configured
|
||
<span class="text-green-500">✔</span> Uncloud machine daemon installed and started
|
||
Cluster initialised with machine <span class="text-zinc-200">prod-1</span> and saved as context <span
|
||
class="text-zinc-200">default</span>
|
||
in your local config (~/.config/uncloud/config.yaml)
|
||
|
||
<span class="font-bold text-green-500">$</span> <span class="text-zinc-200">uc machine add</span> --name prod-2 ubuntu@65.21.45.67
|
||
...
|
||
<span class="text-green-500">✔</span> Uncloud machine daemon installed and started
|
||
Machine <span class="text-zinc-200">prod-2</span> joined the cluster.
|
||
|
||
<span class="font-bold text-green-500">$</span> <span class="text-zinc-200">uc machine ls</span>
|
||
<span class="font-medium text-zinc-200">NAME STATE ADDRESS PUBLIC IP WIREGUARD ENDPOINTS</span>
|
||
prod-1 <span class="text-green-500">Up</span> 10.210.0.1/24 137.123.45.67 10.0.0.95:51820, 137.123.45.67:51820
|
||
prod-2 <span class="text-green-500">Up</span> 10.210.1.1/24 65.21.45.67 192.168.40.243:51820, 65.21.45.67:51820</pre>
|
||
</div>
|
||
|
||
<!-- Supporting quote, pinned under the terminal column -->
|
||
<blockquote class="lg:col-start-2 border-l-[3px] border-zinc-400 pl-5">
|
||
<p class="text-zinc-600">
|
||
“In my opinion, Swarm is dead, Nomad is not anymore a free software since it was
|
||
bought by IBM. So the only robust alternative to the bloat of K8s is Uncloud.”
|
||
</p>
|
||
<cite class="block mt-3 text-sm not-italic text-zinc-500">
|
||
<a class="font-medium text-zinc-600 underline decoration-zinc-300 underline-offset-2 hover:text-zinc-900 hover:decoration-zinc-400 transition-colors"
|
||
href="https://discord.com/channels/1371726032104587335/1371726032838594565/1462397723834712118"
|
||
target="_blank" rel="noopener">Frédéric Logier (fredix) on Discord</a>
|
||
</cite>
|
||
</blockquote>
|
||
</article>
|
||
|
||
<!-- Next rows go here. Even rows flip sides: add `lg:order-2` to the
|
||
terminal and `lg:order-1` to the text, or reverse the column order. -->
|
||
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Value proposition -->
|
||
<section class="relative bg-zinc-50">
|
||
<div class="py-12 md:py-20">
|
||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||
<div class="max-w-3xl mx-auto text-center pb-12 md:pb-20">
|
||
<h2 class="font-inter-tight text-3xl md:text-4xl font-bold text-zinc-900 mb-4">
|
||
PaaS-like workflow on your own servers
|
||
</h2>
|
||
<p class="text-lg text-zinc-500">
|
||
Deploy with the simplicity of Heroku or Fly.io while keeping full control over your
|
||
infrastructure.
|
||
</p>
|
||
</div>
|
||
|
||
<div class="max-w-xs mx-auto sm:max-w-none grid sm:grid-cols-2 md:grid-cols-3 gap-8 sm:gap-4 lg:gap-8">
|
||
<!-- Your Infrastructure -->
|
||
<article
|
||
class="flex flex-col border border-transparent [background:linear-gradient(theme(colors.white),theme(colors.zinc.50))_padding-box,linear-gradient(120deg,theme(colors.zinc.300),theme(colors.zinc.100),theme(colors.zinc.300))_border-box] rounded-lg">
|
||
<div class="grow flex flex-col p-5 pt-6">
|
||
<div class="flex items-center space-x-3 mb-4">
|
||
<svg class="inline-flex stroke-zinc-400 shrink-0" xmlns="http://www.w3.org/2000/svg"
|
||
width="20" height="20" fill="none"
|
||
stroke-width="2" viewBox="0 0 24 24">
|
||
<rect width="8" height="8" x="2" y="2" rx="1"/>
|
||
<rect width="9" height="8" x="13" y="2" rx="1"/>
|
||
<rect width="11" height="9" x="2" y="13" rx="1"/>
|
||
<rect width="6" height="9" x="16" y="13" rx="1"/>
|
||
</svg>
|
||
<h3 class="font-inter-tight font-semibold text-zinc-900">
|
||
Your infrastructure
|
||
</h3>
|
||
</div>
|
||
<div class="text-sm text-zinc-500">
|
||
<ul class="space-y-3">
|
||
<li class="flex gap-3 items-start">
|
||
<svg class="w-4 h-4 text-green-500 shrink-0 mt-0.5" fill="none"
|
||
stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||
d="M5 13l4 4L19 7"/>
|
||
</svg>
|
||
Full control over your servers and data
|
||
</li>
|
||
<li class="flex gap-3 items-start">
|
||
<svg class="w-4 h-4 text-green-500 shrink-0 mt-0.5" fill="none"
|
||
stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||
d="M5 13l4 4L19 7"/>
|
||
</svg>
|
||
Predictable costs without per-request pricing
|
||
</li>
|
||
<li class="flex gap-3 items-start">
|
||
<svg class="w-4 h-4 text-green-500 shrink-0 mt-0.5" fill="none"
|
||
stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||
d="M5 13l4 4L19 7"/>
|
||
</svg>
|
||
No vendor lock-in or platform dependencies
|
||
</li>
|
||
<li class="flex gap-3 items-start">
|
||
<svg class="w-4 h-4 text-green-500 shrink-0 mt-0.5" fill="none"
|
||
stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||
d="M5 13l4 4L19 7"/>
|
||
</svg>
|
||
SSH into machines and debug with standard tools
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
|
||
<!-- Familiar Docker Compose workflow -->
|
||
<article
|
||
class="flex flex-col border border-transparent [background:linear-gradient(theme(colors.white),theme(colors.zinc.50))_padding-box,linear-gradient(120deg,theme(colors.zinc.300),theme(colors.zinc.100),theme(colors.zinc.300))_border-box] rounded-lg">
|
||
<div class="grow flex flex-col p-5 pt-6">
|
||
<div class="flex items-center space-x-3 mb-4">
|
||
<svg class="inline-flex fill-zinc-400 shrink-0" xmlns="http://www.w3.org/2000/svg"
|
||
width="20"
|
||
height="20" viewBox="0 0 24 24">
|
||
<path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"/>
|
||
</svg>
|
||
<h3 class="font-inter-tight font-semibold text-zinc-900">Familiar Docker Compose
|
||
workflow</h3>
|
||
</div>
|
||
<div class="text-sm text-zinc-500">
|
||
<ul class="space-y-3">
|
||
<li class="flex gap-3 items-start">
|
||
<svg class="w-4 h-4 text-green-500 shrink-0 mt-0.5" fill="none"
|
||
stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||
d="M5 13l4 4L19 7"/>
|
||
</svg>
|
||
Build, push, and deploy with one command
|
||
</li>
|
||
<li class="flex gap-3 items-start">
|
||
<svg class="w-4 h-4 text-green-500 shrink-0 mt-0.5" fill="none"
|
||
stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||
d="M5 13l4 4L19 7"/>
|
||
</svg>
|
||
No image registry required
|
||
</li>
|
||
<li class="flex gap-3 items-start">
|
||
<svg class="w-4 h-4 text-green-500 shrink-0 mt-0.5" fill="none"
|
||
stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||
d="M5 13l4 4L19 7"/>
|
||
</svg>
|
||
Zero-downtime rolling deployments
|
||
</li>
|
||
<li class="flex gap-3 items-start">
|
||
<svg class="w-4 h-4 text-green-500 shrink-0 mt-0.5" fill="none"
|
||
stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||
d="M5 13l4 4L19 7"/>
|
||
</svg>
|
||
Scale replicas across machines
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
|
||
<!-- Low Maintenance -->
|
||
<article
|
||
class="flex flex-col border border-transparent [background:linear-gradient(theme(colors.white),theme(colors.zinc.50))_padding-box,linear-gradient(120deg,theme(colors.zinc.300),theme(colors.zinc.100),theme(colors.zinc.300))_border-box] rounded-lg">
|
||
<div class="grow flex flex-col p-5 pt-6">
|
||
<div class="flex items-center space-x-3 mb-4">
|
||
<svg class="inline-flex fill-zinc-400 shrink-0" xmlns="http://www.w3.org/2000/svg"
|
||
width="20"
|
||
height="20" viewBox="0 0 24 24">
|
||
<path d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"/>
|
||
</svg>
|
||
<h3 class="font-inter-tight font-semibold text-zinc-900">Low maintenance</h3>
|
||
</div>
|
||
<div class="text-sm text-zinc-500">
|
||
<ul class="space-y-3">
|
||
<li class="flex gap-3 items-start">
|
||
<svg class="w-4 h-4 text-green-500 shrink-0 mt-0.5" fill="none"
|
||
stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||
d="M5 13l4 4L19 7"/>
|
||
</svg>
|
||
No control plane or quorum to manage
|
||
</li>
|
||
<li class="flex gap-3 items-start">
|
||
<svg class="w-4 h-4 text-green-500 shrink-0 mt-0.5" fill="none"
|
||
stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||
d="M5 13l4 4L19 7"/>
|
||
</svg>
|
||
Secure cross-machine communication without opening ports
|
||
</li>
|
||
<li class="flex gap-3 items-start">
|
||
<svg class="w-4 h-4 text-green-500 shrink-0 mt-0.5" fill="none"
|
||
stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||
d="M5 13l4 4L19 7"/>
|
||
</svg>
|
||
Services find each other automatically
|
||
</li>
|
||
<li class="flex gap-3 items-start">
|
||
<svg class="w-4 h-4 text-green-500 shrink-0 mt-0.5" fill="none"
|
||
stroke="currentColor" viewBox="0 0 24 24">
|
||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||
d="M5 13l4 4L19 7"/>
|
||
</svg>
|
||
Automatic HTTPS via Let's Encrypt
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- How it works + Features -->
|
||
<section
|
||
class="relative bg-zinc-800 text-zinc-400 after:absolute after:top-0 after:right-0 after:h-full after:w-96 after:pointer-events-none after:bg-gradient-to-l after:from-zinc-800 max-lg:after:hidden">
|
||
<div class="py-12 md:py-20">
|
||
|
||
<div class="max-w-xl lg:max-w-6xl mx-auto px-4 sm:px-6">
|
||
<div class="lg:flex space-y-12 lg:space-y-0 lg:space-x-12 2xl:space-x-24">
|
||
|
||
<!-- Content -->
|
||
<div class="lg:max-w-none lg:min-w-[524px]">
|
||
<div class="mb-8">
|
||
<div class="inline-flex text-sm font-medium text-zinc-400 px-4 py-0.5 border border-transparent [background:linear-gradient(theme(colors.zinc.800),theme(colors.zinc.800))_padding-box,linear-gradient(120deg,theme(colors.zinc.700),theme(colors.zinc.700/0),theme(colors.zinc.700))_border-box] rounded-full mb-4">
|
||
How it works
|
||
</div>
|
||
<h3 class="font-inter-tight text-3xl font-bold text-zinc-100 mb-4">
|
||
Simple by design,<br>
|
||
powerful in practice
|
||
</h3>
|
||
<p class="text-lg">
|
||
Uncloud replaces complex clusters with a simple network of machines working
|
||
seamlessly together — no maintenance overhead, just reliable infrastructure.
|
||
</p>
|
||
</div>
|
||
|
||
<!-- Items -->
|
||
<div class="mb-8 md:mb-0 space-y-2">
|
||
<!-- Secure private network -->
|
||
<div class="text-left flex items-center px-6 py-4 rounded border border-transparent">
|
||
<svg class="shrink-0 fill-zinc-400 mr-3" xmlns="http://www.w3.org/2000/svg"
|
||
width="24" height="24">
|
||
<path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z"/>
|
||
</svg>
|
||
<div>
|
||
<div class="font-inter-tight text-lg font-semibold text-zinc-200 mb-1">
|
||
Secure private network
|
||
</div>
|
||
<div>
|
||
Each machine joins a WireGuard mesh network with automatic peer discovery
|
||
and NAT traversal. Containers get unique IPs and can communicate directly
|
||
across machines.
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Fully decentralised -->
|
||
<div class="text-left flex items-center px-6 py-4 rounded border border-transparent">
|
||
<svg class="shrink-0 fill-zinc-400 stroke-zinc-400 mr-3"
|
||
xmlns="http://www.w3.org/2000/svg"
|
||
width="24" height="24">
|
||
<path d="M4 4h16M4 4v16M4 4L20 20M20 4v16M20 4L4 20M4 20h16 M4 1.5a2.5 2.5 0 110 5 2.5 2.5 0 010-5M20 1.5a2.5 2.5 0 110 5 2.5 2.5 0 010-5M4 17.5a2.5 2.5 0 110 5 2.5 2.5 0 010-5M20 17.5a2.5 2.5 0 110 5 2.5 2.5 0 010-5"/>
|
||
</svg>
|
||
<div>
|
||
<div class="font-inter-tight text-lg font-semibold text-zinc-200 mb-1">
|
||
Fully decentralised
|
||
</div>
|
||
<div>
|
||
Unlike traditional orchestrators, there's no central control plane to
|
||
maintain. Each machine maintains a synchronised copy of the cluster
|
||
state
|
||
through peer-to-peer communication, keeping cluster operations
|
||
functional
|
||
even if some machines go offline.
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Smart CLI -->
|
||
<div class="text-left flex items-center px-6 py-4 rounded border border-transparent">
|
||
<svg class="shrink-0 fill-zinc-400 mr-3" xmlns="http://www.w3.org/2000/svg"
|
||
width="24" height="24">
|
||
<path d="M20 4H4c-1.11 0-2 .89-2 2v12c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4V8h16v10zm-2-1h-6v-2h6v2zM7.5 17l-1.41-1.41L8.67 13l-2.58-2.59L7.5 9l4 4-4 4z"/>
|
||
</svg>
|
||
<div>
|
||
<div class="font-inter-tight text-lg font-semibold text-zinc-200 mb-1">
|
||
Smart CLI
|
||
</div>
|
||
<div>
|
||
Control your entire infrastructure using intuitive Docker-like commands from
|
||
anywhere. Deploy, monitor, and scale applications across all your machines
|
||
while the CLI only needs SSH access to a single machine.
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Diagram -->
|
||
<div class="relative lg:max-w-none">
|
||
<div class="relative flex flex-col">
|
||
<figure class="w-full lg:mt-36">
|
||
<img class="lg:max-w-none mx-auto rounded-xl shadow-2xl"
|
||
src="./images/diagram.webp" width="700" alt="Uncloud cluster diagram"/>
|
||
<figcaption class="text-center text-sm mt-2">
|
||
Multi-provider cluster of 3 machines
|
||
</figcaption>
|
||
</figure>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Features blocks -->
|
||
<div class="max-w-6xl mx-auto px-4 sm:px-6 mt-12 lg:mt-24">
|
||
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-8 lg:gap-16">
|
||
<!-- Deploy anywhere -->
|
||
<div>
|
||
<div class="flex items-center mb-1">
|
||
<svg class="fill-zinc-400 mr-2" xmlns="http://www.w3.org/2000/svg" width="16"
|
||
height="16">
|
||
<path d="M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm5.9 7H12c-.1-1.5-.4-2.9-.8-4.1 1.4.9 2.3 2.4 2.7 4.1zM8 14c-.6 0-1.8-1.9-2-5h4c-.2 3.1-1.4 5-2 5zM6 7c.2-3.1 1.3-5 2-5s1.8 1.9 2 5H6zM4.9 2.9C4.4 4.1 4.1 5.5 4 7H2.1c.4-1.7 1.3-3.2 2.8-4.1zM2.1 9H4c.1 1.5.4 2.9.8 4.1-1.4-.9-2.3-2.4-2.7-4.1zm9 4.1c.5-1.2.7-2.6.8-4.1h1.9c-.4 1.7-1.3 3.2-2.7 4.1z"/>
|
||
</svg>
|
||
<h3 class="font-inter-tight font-semibold text-zinc-200">Deploy anywhere</h3>
|
||
</div>
|
||
<p class="text-sm">Run your apps on any Linux machine — from cloud VMs and
|
||
dedicated servers to bare metal at your office or home.</p>
|
||
</div>
|
||
|
||
<!-- Automatic HTTPS -->
|
||
<div>
|
||
<div class="flex items-center mb-1">
|
||
<svg class="fill-zinc-400 mr-2" xmlns="http://www.w3.org/2000/svg" width="16"
|
||
height="16">
|
||
<path d="M13 7.5V6c0-2.76-2.24-5-5-5S3 3.24 3 6v1.5H2v7h12v-7h-1zM6 6c0-1.1.9-2 2-2s2 .9 2 2H6zm3 6H7v-2h2v2z"/>
|
||
</svg>
|
||
<h3 class="font-inter-tight font-semibold text-zinc-200">Automatic HTTPS</h3>
|
||
</div>
|
||
<p class="text-sm">Get free TLS certificates and automatic HTTPS for your
|
||
domains with zero configuration using built-in Caddy reverse proxy.</p>
|
||
</div>
|
||
|
||
<!-- Load balancing -->
|
||
<div>
|
||
<div class="flex items-center mb-1">
|
||
<svg class="fill-zinc-400 stroke-zinc-400 mr-2" xmlns="http://www.w3.org/2000/svg"
|
||
width="16"
|
||
height="16" stroke-linejoin="round" stroke-linecap="round" stroke-width="1.5"
|
||
fill="none">
|
||
<circle cy="4.334" cx="8.175" r="2.162"/>
|
||
<path d="M6.657 6.44l-4.268 7.108m.056.195l-1.189-3.498m1.245 3.484l3.736-1.273m3.442-6.072l3.932 7.22m.056.097l1.259-3.4m-1.287 3.414l-3.652-1.231"/>
|
||
</svg>
|
||
<h3 class="font-inter-tight font-semibold text-zinc-200">Load balancing</h3>
|
||
</div>
|
||
<p class="text-sm">Distribute traffic across container replicas running on
|
||
different machines for improved reliability and performance.</p>
|
||
</div>
|
||
|
||
<!-- Service discovery -->
|
||
<div>
|
||
<div class="flex items-center mb-1">
|
||
<svg class="fill-zinc-400 mr-2" xmlns="http://www.w3.org/2000/svg" width="16"
|
||
height="16">
|
||
<path d="M7 14c-3.86 0-7-3.14-7-7s3.14-7 7-7 7 3.14 7 7-3.14 7-7 7ZM7 2C4.243 2 2 4.243 2 7s2.243 5 5 5 5-2.243 5-5-2.243-5-5-5Zm8.707 12.293a.999.999 0 1 1-1.414 1.414L11.9 13.314a8.019 8.019 0 0 0 1.414-1.414l2.393 2.393Z"/>
|
||
</svg>
|
||
<h3 class="font-inter-tight font-semibold text-zinc-200">Service discovery</h3>
|
||
</div>
|
||
<p class="text-sm">Access any service by its name from any container using the
|
||
built-in DNS that automatically tracks services across your network.</p>
|
||
</div>
|
||
|
||
<!-- Infrastructure as Code -->
|
||
<div>
|
||
<div class="flex items-center mb-1">
|
||
<svg class="fill-zinc-400 mr-2" xmlns="http://www.w3.org/2000/svg" width="16"
|
||
height="16">
|
||
<path d="M5 3L0 8l5 5 1.5-1.5L3 8l3.5-3.5L5 3zm6 0l-1.5 1.5L13 8l-3.5 3.5L11 13l5-5-5-5z"/>
|
||
</svg>
|
||
<h3 class="font-inter-tight font-semibold text-zinc-200">Infrastructure as Code</h3>
|
||
</div>
|
||
<p class="text-sm">Define your entire app stack in a familiar Docker Compose
|
||
file. No need to learn a new config format.</p>
|
||
</div>
|
||
|
||
<!-- No vendor lock-in -->
|
||
<div>
|
||
<div class="flex items-center mb-1">
|
||
<svg class="stroke-zinc-400 mr-2" xmlns="http://www.w3.org/2000/svg" width="16"
|
||
height="16" stroke-width="1.8" fill="none" stroke-linecap="round"
|
||
stroke-linejoin="round">
|
||
<path d="M4.5 11.5h-0.7a2.8 2.8 0 0 1 0-5.6 3.7 3.7 0 0 1 7.4 0 2.8 2.8 0 0 1 0 5.6h-6.7"/>
|
||
<path d="M2 2L14 13"/>
|
||
</svg>
|
||
<h3 class="font-inter-tight font-semibold text-zinc-200">No vendor lock-in</h3>
|
||
</div>
|
||
<p class="text-sm">Mix cloud providers and your own hardware freely to
|
||
optimise costs and performance, without changing how you deploy or manage apps.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Demo Section -->
|
||
<section class="relative bg-white text-zinc-800">
|
||
<div class="py-12 md:py-20">
|
||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||
<div class="max-w-3xl mx-auto text-center pb-12 md:pb-16">
|
||
<h2 class="font-inter-tight text-3xl md:text-4xl font-bold text-zinc-900 mb-4">
|
||
See in action
|
||
</h2>
|
||
<p class="text-lg text-zinc-500">
|
||
Deploy a highly available web app with automatic HTTPS across multiple regions and
|
||
on-premises in just a couple minutes.
|
||
</p>
|
||
</div>
|
||
|
||
<div class="max-w-3xl mx-auto px-4 sm:px-6 flex justify-center pb-12 relative before:absolute before:-top-12 before:w-96 before:h-96 before:bg-zinc-900 before:opacity-[.15] before:rounded-full before:blur-3xl before:-z-10">
|
||
<script src="https://fast.wistia.com/player.js" async></script>
|
||
<script src="https://fast.wistia.com/embed/k47uwt9uau.js" async type="module"></script>
|
||
<style>wistia-player[media-id='k47uwt9uau']:not(:defined) {
|
||
background: center / contain no-repeat url('https://fast.wistia.com/embed/medias/k47uwt9uau/swatch');
|
||
display: block;
|
||
filter: blur(5px);
|
||
padding-top: 58.33%;
|
||
}</style>
|
||
<wistia-player media-id="k47uwt9uau" aspect="1.7142857142857142"
|
||
class="w-full rounded-xl shadow-lg"></wistia-player>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- CTA -->
|
||
<section id="subscribe">
|
||
<div class="py-12 md:py-20 border-t border-zinc-200">
|
||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||
<div class="relative max-w-3xl mx-auto text-center">
|
||
<h2 class="font-inter-tight text-3xl md:text-4xl font-bold text-zinc-900 mb-4">
|
||
Be part of the development
|
||
<em class="relative not-italic inline-flex justify-center items-end">
|
||
journey
|
||
<svg class="absolute fill-zinc-300 w-[calc(100%+1rem)] -z-10"
|
||
style="max-width: none;"
|
||
xmlns="http://www.w3.org/2000/svg" width="120" height="10" viewBox="0 0 120 10"
|
||
aria-hidden="true" preserveAspectRatio="none">
|
||
<path d="M118.273 6.09C79.243 4.558 40.297 5.459 1.305 9.034c-1.507.13-1.742-1.521-.199-1.81C39.81-.228 79.647-1.568 118.443 4.2c1.63.233 1.377 1.943-.17 1.89Z"/>
|
||
</svg>
|
||
</em>
|
||
</h2>
|
||
<p class="text-lg text-zinc-500 mb-8">
|
||
Subscribe to follow the progress and get early insights into new features.<br>
|
||
See <a href="https://psviderski.substack.com/" target="_blank"
|
||
class="text-zinc-900 hover:underline">previous newsletters</a>.
|
||
</p>
|
||
|
||
<!-- Subscribe form -->
|
||
<div class="flex justify-center">
|
||
<iframe src="https://psviderski.substack.com/embed" width="480" height="150"
|
||
style="border:1px solid #EEE; background:white;" frameborder="0"
|
||
scrolling="no"></iframe>
|
||
</div>
|
||
|
||
<div class="mt-6 text-sm text-zinc-500">
|
||
<p>
|
||
Want to contribute? Check out the
|
||
<a href="https://github.com/psviderski/uncloud/issues"
|
||
class="text-zinc-900 hover:underline">GitHub issues</a>
|
||
and join the
|
||
<a href="https://discord.gg/eR35KQJhPu"
|
||
class="text-zinc-900 hover:underline">Discord server</a>.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
</main>
|
||
|
||
<!-- Site footer -->
|
||
<footer>
|
||
<div class="max-w-6xl mx-auto px-4 sm:px-6">
|
||
<!-- Top area: Blocks -->
|
||
<div class="grid sm:grid-cols-12 gap-8 py-8 md:py-12 border-t border-zinc-200">
|
||
<!-- 1st block - Brand -->
|
||
<div class="sm:col-span-6 md:col-span-6 lg:col-span-8 max-md:order-1 flex flex-col">
|
||
<div class="mb-4">
|
||
<!-- Logo -->
|
||
<a class="flex items-center" href="index.html">
|
||
<img class="w-8 h-8 rounded shadow-sm shadow-zinc-950/20" src="./images/logo.svg"
|
||
alt="Logo">
|
||
<span class="ml-2 font-semibold text-lg text-zinc-900">uncloud</span>
|
||
</a>
|
||
</div>
|
||
<div class="grow text-sm text-zinc-500">
|
||
Made with ❤️ by
|
||
<a class="underline hover:text-zinc-900" href="https://github.com/psviderski">
|
||
Pasha Sviderski
|
||
</a>
|
||
in Australia
|
||
</div>
|
||
|
||
<!-- Social links -->
|
||
<ul class="flex space-x-4 mt-4 mb-1">
|
||
<li>
|
||
<a class="flex justify-center items-center text-zinc-700 hover:text-zinc-900 transition"
|
||
href="https://discord.gg/eR35KQJhPu" aria-label="Discord">
|
||
<svg class="fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
|
||
width="20"
|
||
height="20">
|
||
<path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z"/>
|
||
</svg>
|
||
</a>
|
||
</li>
|
||
<li>
|
||
<a class="flex justify-center items-center text-zinc-700 hover:text-zinc-900 transition"
|
||
href="https://x.com/psviderski" aria-label="X/Twitter">
|
||
<svg class="fill-current" xmlns="http://www.w3.org/2000/svg" width="20" height="20">
|
||
<path d="m7.063 3 3.495 4.475L14.601 3h2.454l-5.359 5.931L18 17h-4.938l-3.866-4.893L4.771 17H2.316l5.735-6.342L2 3h5.063Zm-.74 1.347H4.866l8.875 11.232h1.36L6.323 4.347Z"/>
|
||
</svg>
|
||
</a>
|
||
</li>
|
||
<li>
|
||
<a class="flex justify-center items-center text-zinc-700 hover:text-zinc-900 transition"
|
||
href="https://t.me/spyyy" aria-label="Telegram">
|
||
<svg class="fill-current" xmlns="http://www.w3.org/2000/svg" width="20" height="20">
|
||
<path d="M17.968 3.276a.338.338 0 0 0-.232-.253 1.192 1.192 0 0 0-.63.045S3.087 8.106 2.286 8.664c-.172.121-.23.19-.259.272-.138.4.293.573.293.573l3.613 1.177a.388.388 0 0 0 .183-.011c.822-.519 8.27-5.222 8.7-5.38.068-.02.118 0 .1.049-.172.6-6.606 6.319-6.64 6.354a.138.138 0 0 0-.05.118l-.337 3.528s-.142 1.1.956 0a30.66 30.66 0 0 1 1.9-1.738c1.242.858 2.58 1.806 3.156 2.3a1 1 0 0 0 .732.283.825.825 0 0 0 .7-.622S17.894 5.292 17.98 3.909c.008-.135.021-.217.021-.317a1.177 1.177 0 0 0-.032-.316Z"/>
|
||
</svg>
|
||
</a>
|
||
</li>
|
||
<li>
|
||
<a class="flex justify-center items-center text-zinc-700 hover:text-zinc-900 transition"
|
||
href="https://github.com/psviderski/uncloud" aria-label="GitHub">
|
||
<svg class="fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
|
||
width="20"
|
||
height="20">
|
||
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
|
||
</svg>
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<!-- 2nd block - Documentation -->
|
||
<div class="sm:col-span-6 md:col-span-3 lg:col-span-2">
|
||
|
||
<h6 class="text-sm text-zinc-800 font-medium mb-2">Documentation</h6>
|
||
<ul class="text-sm space-y-2">
|
||
<li>
|
||
<a class="text-zinc-500 hover:text-zinc-900 transition"
|
||
href="/docs/#use-cases">Use cases</a>
|
||
</li>
|
||
<li>
|
||
<a class="text-zinc-500 hover:text-zinc-900 transition"
|
||
href="/docs/getting-started/deploy-demo-app">Quick start</a>
|
||
</li>
|
||
<li>
|
||
<a class="text-zinc-500 hover:text-zinc-900 transition"
|
||
href="/blog">Blog</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<!-- 3rd block - Resources -->
|
||
<div class="sm:col-span-6 md:col-span-3 lg:col-span-2">
|
||
<h6 class="text-sm text-zinc-800 font-medium mb-2">Resources</h6>
|
||
<ul class="text-sm space-y-2">
|
||
<li>
|
||
<a class="text-zinc-500 hover:text-zinc-900 transition"
|
||
href="https://github.com/psviderski/uncloud">GitHub project</a>
|
||
</li>
|
||
<li>
|
||
<a class="text-zinc-500 hover:text-zinc-900 transition"
|
||
href="https://github.com/psviderski/uncloud/releases">Releases</a>
|
||
</li>
|
||
<li>
|
||
<a class="text-zinc-500 hover:text-zinc-900 transition"
|
||
href="https://github.com/psviderski/uncloud/blob/main/LICENSE">License</a>
|
||
</li>
|
||
<li>
|
||
<a class="text-zinc-500 hover:text-zinc-900 transition"
|
||
href="https://discord.gg/eR35KQJhPu">Community</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
|
||
</div>
|
||
|
||
<script src="./js/vendors/alpinejs.min.js" defer></script>
|
||
<script>
|
||
(function () {
|
||
// Fetch the GitHub stars count. Resolves to the live number or null if the request fails.
|
||
const starsPromise = fetch('https://api.github.com/repos/psviderski/uncloud')
|
||
.then(function (res) {
|
||
if (!res.ok) throw new Error('GitHub API ' + res.status);
|
||
return res.json();
|
||
})
|
||
.then(function (data) {
|
||
return typeof data.stargazers_count === 'number' ? data.stargazers_count : null;
|
||
})
|
||
.catch(function () {
|
||
return null;
|
||
});
|
||
|
||
starsPromise.then(function (count) {
|
||
if (count === null) return;
|
||
document.querySelectorAll('.js-github-stars').forEach(function (el) {
|
||
el.textContent = formatStars(count);
|
||
});
|
||
});
|
||
|
||
function formatStars(count) {
|
||
if (count < 1000) return String(count);
|
||
// Round to one decimal on the nearest 100 (e.g. 5250 -> 5.3k), matching GitHub's rounding.
|
||
return Math.round(count / 100) / 10 + 'k';
|
||
}
|
||
|
||
// Stats counter target for GitHub stars, in thousands.
|
||
window.githubStarsK = starsPromise.then(function (count) {
|
||
return count === null ? null : Math.round(count / 100) / 10;
|
||
});
|
||
|
||
// Fetch total GitHub downloads via the shields.io badge endpoint.
|
||
// Resolves to the absolute count, or null if the request fails.
|
||
const downloadsPromise = fetch('https://img.shields.io/github/downloads/psviderski/uncloud/total.json')
|
||
.then(function (res) {
|
||
if (!res.ok) throw new Error('shields.io ' + res.status);
|
||
return res.json();
|
||
})
|
||
.then(function (data) {
|
||
// data.value is a formatted string like "21k", "1.2M", or "950".
|
||
const m = /^([\d.]+)\s*([kM]?)/.exec(data.value || '');
|
||
if (!m) return null;
|
||
return parseFloat(m[1]) * {'': 1, k: 1e3, M: 1e6}[m[2]];
|
||
})
|
||
.catch(function () {
|
||
return null;
|
||
});
|
||
|
||
// Stats counter target for total downloads, in thousands.
|
||
window.downloadsK = downloadsPromise.then(function (total) {
|
||
return total === null ? null : Math.round(total / 1000);
|
||
});
|
||
|
||
<!-- Animate counter -->
|
||
document.addEventListener('alpine:init', () => {
|
||
Alpine.data('counter', (target = 0, duration = 2000) => ({
|
||
startTimestamp: null,
|
||
step: null,
|
||
rawValue: 0,
|
||
counterValue: 0,
|
||
target: target,
|
||
precision: 0,
|
||
animationRequestId: null,
|
||
animationCompleted: false,
|
||
observer: null,
|
||
fallback: 0,
|
||
init() {
|
||
// Capture the static value rendered in the markup as the fallback.
|
||
this.fallback = parseFloat(this.$el.textContent)
|
||
// Intersection observer to watch visibility.
|
||
this.observer = new IntersectionObserver(entries => {
|
||
entries.forEach(entry => {
|
||
// Check if element is in view.
|
||
if (entry.isIntersecting && !this.animationCompleted) {
|
||
this.startAnimation()
|
||
}
|
||
})
|
||
})
|
||
this.observer.observe(this.$el)
|
||
},
|
||
startAnimation() {
|
||
this.observer && this.observer.disconnect() // Animate once, stop further intersection callbacks.
|
||
Promise.resolve(this.target).then((target) => {
|
||
// Fall back to the markup value when failed to fetch the up-to-date value.
|
||
if (!Number.isFinite(target)) target = this.fallback
|
||
this.precision = (target % 1 === 0) ? 0 : (target.toString().split('.')[1] || '').length
|
||
this.step = (timestamp) => {
|
||
if (!this.startTimestamp) this.startTimestamp = timestamp
|
||
const progress = Math.min((timestamp - this.startTimestamp) / duration, 1)
|
||
const easedProgress = this.easeOut(progress)
|
||
this.rawValue = parseFloat((easedProgress * target).toFixed(this.precision))
|
||
this.counterValue = this.rawValue.toFixed(this.precision)
|
||
if (progress < 1) {
|
||
this.animationRequestId = window.requestAnimationFrame(this.step)
|
||
} else {
|
||
this.animationCompleted = true
|
||
}
|
||
}
|
||
this.animationRequestId = window.requestAnimationFrame(this.step)
|
||
})
|
||
},
|
||
easeOut(t) {
|
||
return 1 - Math.pow(1 - t, 5)
|
||
},
|
||
destroy() {
|
||
// Detach the handler to avoid memory and side-effect leakage.
|
||
this.animationRequestId && window.cancelAnimationFrame(this.step)
|
||
this.observer && this.observer.disconnect()
|
||
},
|
||
}))
|
||
})
|
||
})();
|
||
</script>
|
||
|
||
</body>
|
||
|
||
</html>
|