import type { Metadata } from "next"; import Link from "next/link"; import TerminalTyper from "../components/TerminalTyper"; import AnimateIn from "../components/AnimateIn"; import CountUp from "../components/CountUp"; import SpotlightCard from "../components/SpotlightCard"; import { LINKS } from "@/lib/links"; import { getLinks } from "@/lib/links-db"; export const metadata: Metadata = { title: "Updaterup — Docker Container Updates", description: "Automated Docker container update manager. Check running containers for new image versions and update them in one click — or on a cron schedule.", }; /* ── SVG Icons ─────────────────────────────────────────────── */ const RefreshIcon = () => ( ); const CubeIcon = () => ( ); const MagnifyIcon = () => ( ); const LayersIcon = () => ( ); const ClockIcon = () => ( ); const BookIcon = () => ( ); const TerminalIcon = () => ( ); const DownloadIcon = () => ( ); const EyeIcon = () => ( ); const ArrowUpIcon = () => ( ); const LinkIcon = () => ( ); const GitHubIcon = () => ( ); /* ── Data ───────────────────────────────────────────────────── */ const features = [ { icon: , gradient: "from-violet-500/15 to-purple-600/15", border: "border-violet-500/20", iconBg: "bg-violet-500/10", iconColor: "text-violet-400", title: "Container inventory", body: "Lists all running (and optionally stopped) containers with their current image, tag, and digest — your live fleet at a glance.", }, { icon: , gradient: "from-purple-500/15 to-fuchsia-600/15", border: "border-purple-500/20", iconBg: "bg-purple-500/10", iconColor: "text-purple-400", title: "Digest-based detection", body: "Pulls the latest image manifest and compares SHA digests — no false positives from re-tagged images. Knows exactly when a real update is available.", }, { icon: , gradient: "from-fuchsia-500/15 to-violet-600/15", border: "border-fuchsia-500/20", iconBg: "bg-fuchsia-500/10", iconColor: "text-fuchsia-400", title: "One-click update", body: "Stops, removes, and recreates the container with the new image — preserving all original binds, ports, env vars, restart policy, and networks.", }, { icon: , gradient: "from-indigo-500/15 to-violet-600/15", border: "border-indigo-500/20", iconBg: "bg-indigo-500/10", iconColor: "text-indigo-400", title: "Batch operations", body: "Check or update all containers at once with a single click. Updaterup handles each container sequentially to avoid Docker socket contention.", }, { icon: , gradient: "from-violet-500/15 to-indigo-600/15", border: "border-violet-500/20", iconBg: "bg-violet-500/10", iconColor: "text-violet-400", title: "Cron schedules", body: "Create named schedules with check-only or check & auto-update modes, targeting specific containers or your entire fleet.", }, { icon: , gradient: "from-purple-500/15 to-violet-600/15", border: "border-purple-500/20", iconBg: "bg-purple-500/10", iconColor: "text-purple-400", title: "Audit history & live logs", body: "Full update audit trail with container, image, status, trigger, and digest. Plus a live ring-buffer log viewer with level and context filtering.", }, ]; const steps = [ { n: "01", icon: , color: "bg-violet-500/20 text-violet-400", title: "Connect", body: "Mount the Docker socket. Updaterup auto-discovers all running containers immediately on startup.", }, { n: "02", icon: , color: "bg-purple-500/20 text-purple-400", title: "Check", body: "Compare local image digests against the registry. Outdated containers are flagged instantly.", }, { n: "03", icon: , color: "bg-fuchsia-500/20 text-fuchsia-400", title: "Review", body: "The dashboard shows all pending updates with image info and last-check timestamps.", }, { n: "04", icon: , color: "bg-indigo-500/20 text-indigo-400", title: "Update", body: "One click to update — Updaterup stops, removes, and recreates the container with zero config drift.", }, ]; const pills = [ { label: "Open source", color: "text-violet-400 bg-violet-500/10 border-violet-500/20" }, { label: "Zero cloud deps", color: "text-purple-400 bg-purple-500/10 border-purple-500/20" }, { label: "Self-hosted", color: "text-fuchsia-400 bg-fuchsia-500/10 border-fuchsia-500/20" }, { label: "Docker native", color: "text-indigo-400 bg-indigo-500/10 border-indigo-500/20" }, ]; const stats = [ { num: 100, suffix: "%", label: "Open source", sub: "source available" }, { num: 0, suffix: "", label: "Config drift", sub: "on container update" }, { num: 7, suffix: "", label: "UI pages", sub: "full management" }, { num: 0, suffix: "", label: "Cloud dependencies", sub: "runs on your infra" }, ]; /* ── Page ───────────────────────────────────────────────────── */ export default async function UpdaterupPage() { const links = await getLinks(); return ( <> {/* ═══ Hero ═══════════════════════════════════════════════ */}
{/* ── Animated aurora blobs ── */}
{/* Pills */}
{pills.map((p) => ( {p.label} ))}
{/* Headline */}

Container updates,
automated.

{/* Subtitle */}

Updaterup watches your running containers for new image versions and lets you update them with a single click — or automatically on a cron schedule. Zero config drift, full audit history, all from a self-hosted UI.

{/* CTA buttons */}
Get started Also see Backerup Gitea
{/* ── Terminal card ── */}
updaterup · quick start
live
{/* ═══ Stats bar ══════════════════════════════════════════ */}
{stats.map((s, i) => (
{s.label}
{s.sub}
))}
{/* ═══ Features ═══════════════════════════════════════════ */}
Features

Everything you need

A complete Docker update lifecycle — from continuous digest monitoring to scheduled auto-updates and a full audit trail, all from one self-hosted UI.

{features.map((f, i) => (
{f.icon}

{f.title}

{f.body}

))}
{/* ═══ How it works ════════════════════════════════════════ */}
How it works

Up and running in minutes

{steps.map((s, i) => (
{s.icon}
{s.n}

{s.title}

{s.body}

))}
{/* ═══ Zero config drift callout ══════════════════════════ */}
{/* Left: text */}
How updates work

Zero config drift, guaranteed

When Updaterup recreates a container, it reads the full{" "} docker inspect output and rebuilds the container with the exact same configuration — nothing is lost or changed except the image digest.

    {[ { name: "Binds & volumes", desc: "all mount points preserved" }, { name: "Port mappings", desc: "identical host bindings" }, { name: "Env vars & labels", desc: "full environment intact" }, { name: "Restart policy & networks", desc: "same behaviour post-update" }, ].map((item) => (
  • {item.name} — {item.desc}
  • ))}
{/* Right: update flow diagram */}
{[ { icon: "🔍", step: "inspect", desc: "docker inspect ", color: "text-violet-400" }, { icon: "⬇️", step: "pull", desc: "docker pull :latest", color: "text-purple-400" }, { icon: "⏹", step: "stop", desc: "docker stop ", color: "text-amber-400" }, { icon: "🗑", step: "remove", desc: "docker rm ", color: "text-rose-400" }, { icon: "🚀", step: "create", desc: "docker run [original config]", color: "text-emerald-400" }, ].map(({ icon, step, desc, color }, i) => (
{String(i + 1).padStart(2, "0")} {icon} {step} {desc}
))}
{/* ═══ Quick start ════════════════════════════════════════ */}
Quick start

Setup with docker-compose

The easiest way to get Updaterup running is with docker-compose for declarative, reproducible deployments.

docker-compose setup
{/* ═══ Final CTA ══════════════════════════════════════════ */}

Keep your containers current.

Open source, self-hosted, and free forever. Stop manually checking for image updates and let Updaterup handle it automatically.

); }