V3
Many many many changes, honestly just read the release notes
27
docs/src/app/[...mdxPath]/page.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import { generateStaticParamsFor, importPage } from "nextra/pages";
|
||||
import { useMDXComponents } from "@/mdx-components";
|
||||
|
||||
export const generateStaticParams = generateStaticParamsFor("mdxPath");
|
||||
|
||||
interface Props {
|
||||
params: Promise<{ mdxPath: string[] }>;
|
||||
}
|
||||
|
||||
export async function generateMetadata(props: Props) {
|
||||
const params = await props.params;
|
||||
const { metadata } = await importPage(params.mdxPath);
|
||||
return metadata;
|
||||
}
|
||||
/* eslint-disable-next-line */
|
||||
const Wrapper = useMDXComponents({}).wrapper;
|
||||
|
||||
export default async function Page(props: Props) {
|
||||
const params = await props.params;
|
||||
const result = await importPage(params.mdxPath);
|
||||
const { default: MDXContent, toc, metadata } = result;
|
||||
return (
|
||||
<Wrapper toc={toc} metadata={metadata}>
|
||||
<MDXContent {...props} params={params} />
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
BIN
docs/src/app/apple-icon.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 176 KiB |
|
After Width: | Height: | Size: 107 KiB |
BIN
docs/src/app/assets/blue_theme.png
Normal file
|
After Width: | Height: | Size: 134 KiB |
BIN
docs/src/app/assets/cup.gif
Normal file
|
After Width: | Height: | Size: 163 KiB |
BIN
docs/src/app/assets/hero-dark.png
Normal file
|
After Width: | Height: | Size: 90 KiB |
BIN
docs/src/app/assets/hero-mobile-dark.png
Normal file
|
After Width: | Height: | Size: 252 KiB |
BIN
docs/src/app/assets/hero-mobile.png
Normal file
|
After Width: | Height: | Size: 254 KiB |
BIN
docs/src/app/assets/hero.png
Normal file
|
After Width: | Height: | Size: 124 KiB |
252
docs/src/app/components/Browser.tsx
Normal file
23
docs/src/app/components/Card.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { Icon as IconType } from "@tabler/icons-react";
|
||||
|
||||
export function Card({
|
||||
name,
|
||||
icon: Icon,
|
||||
description,
|
||||
}: {
|
||||
name: string;
|
||||
icon: IconType;
|
||||
description: string;
|
||||
}) {
|
||||
return (
|
||||
<div className="p-4 bg-white dark:bg-black group">
|
||||
<Icon className="text-black size-7 group-hover:size-9 dark:text-white inline mr-2 transition-[width,height] duration-200" />
|
||||
<span className="align-middle text-2xl font-bold text-black dark:text-white">
|
||||
{name}
|
||||
</span>
|
||||
<p className="text-xl font-semibold text-neutral-500 dark:text-neutral-500">
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
33
docs/src/app/components/GradientText.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import React from "react";
|
||||
import { clsx } from "clsx";
|
||||
|
||||
export function GradientText({
|
||||
text,
|
||||
innerClassName,
|
||||
className,
|
||||
blur,
|
||||
}: {
|
||||
text: string;
|
||||
innerClassName: string;
|
||||
className?: string;
|
||||
blur: number;
|
||||
}) {
|
||||
return (
|
||||
<div className={clsx("relative", className)}>
|
||||
<p
|
||||
className={clsx("bg-clip-text text-transparent w-fit", innerClassName)}
|
||||
>
|
||||
{text}
|
||||
</p>
|
||||
<p
|
||||
className={clsx(
|
||||
"pointer-events-none absolute top-0 hidden select-none bg-clip-text text-transparent dark:block",
|
||||
innerClassName,
|
||||
)}
|
||||
style={{ filter: `blur(${blur}px)` }}
|
||||
>
|
||||
{text}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
31
docs/src/app/components/GridPattern.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import { useId } from "react";
|
||||
|
||||
const SIZE = 36;
|
||||
|
||||
export function GridPattern() {
|
||||
const id = useId();
|
||||
|
||||
return (
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="pointer-events-none absolute inset-0 bottom-0 left-0 right-0 top-0 h-full w-full -z-10 bg-white stroke-neutral-200 dark:stroke-white/10 dark:bg-black"
|
||||
>
|
||||
<defs>
|
||||
<pattern
|
||||
id={id}
|
||||
width={SIZE}
|
||||
height={SIZE}
|
||||
patternUnits="userSpaceOnUse"
|
||||
x={-1}
|
||||
y={-1}
|
||||
>
|
||||
<path
|
||||
d={`M.5 ${SIZE}V.5H${SIZE}`}
|
||||
fill="none"
|
||||
/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" strokeWidth={0} fill={`url(#${id})`} />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
29
docs/src/app/components/Head.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
"use client";
|
||||
|
||||
import { Head as NextraHead } from "nextra/components";
|
||||
|
||||
export function Head() {
|
||||
return (
|
||||
<NextraHead>
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
<meta
|
||||
name="theme-color"
|
||||
media="(prefers-color-scheme: light)"
|
||||
content="#ffffff"
|
||||
/>
|
||||
<meta
|
||||
name="theme-color"
|
||||
media="(prefers-color-scheme: dark)"
|
||||
content="#111111"
|
||||
/>
|
||||
<meta
|
||||
name="og:image"
|
||||
content="https://raw.githubusercontent.com/sergi0g/cup/main/docs/public/cup-og.png"
|
||||
/>
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content="https://cup.sergi0g.dev" />
|
||||
<meta name="apple-mobile-web-app-title" content="Cup" />
|
||||
</NextraHead>
|
||||
);
|
||||
}
|
||||
57
docs/src/app/components/Logo.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
export default function Logo() {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 128 128"
|
||||
style={{ height: "calc(var(--nextra-navbar-height) * 0.6)" }}
|
||||
>
|
||||
<path
|
||||
style={{ fill: "#A6CFD6" }}
|
||||
d="M65.12,17.55c-17.6-0.53-34.75,5.6-34.83,14.36c-0.04,5.2,1.37,18.6,3.62,48.68s2.25,33.58,3.5,34.95
|
||||
c1.25,1.37,10.02,8.8,25.75,8.8s25.93-6.43,26.93-8.05c0.48-0.78,1.83-17.89,3.5-37.07c1.81-20.84,3.91-43.9,3.99-45.06
|
||||
C97.82,30.66,94.2,18.43,65.12,17.55z"
|
||||
/>
|
||||
<path
|
||||
style={{ fill: "#DCEDF6" }}
|
||||
d="M41.4,45.29c-0.12,0.62,1.23,24.16,2.32,27.94c1.99,6.92,9.29,7.38,10.23,4.16
|
||||
c0.9-3.07-0.38-29.29-0.38-29.29s-3.66-0.3-6.43-0.84C44,46.63,41.4,45.29,41.4,45.29z"
|
||||
/>
|
||||
<path
|
||||
style={{ fill: "#6CA4AE" }}
|
||||
d="M33.74,32.61c-0.26,8.83,20.02,12.28,30.19,12.22c13.56-0.09,29.48-4.29,29.8-11.7
|
||||
S79.53,21.1,63.35,21.1C49.6,21.1,33.96,25.19,33.74,32.61z"
|
||||
/>
|
||||
<path
|
||||
style={{ fill: "#DC0D27" }}
|
||||
d="M84.85,13.1c-0.58,0.64-9.67,30.75-9.67,30.75s2.01-0.33,4-0.79c2.63-0.61,3.76-1.06,3.76-1.06
|
||||
s7.19-22.19,7.64-23.09c0.45-0.9,21.61-7.61,22.31-7.93c0.7-0.32,1.39-0.4,1.46-0.78c0.06-0.38-2.34-6.73-3.11-6.73
|
||||
C110.47,3.47,86.08,11.74,84.85,13.1z"
|
||||
/>
|
||||
<path
|
||||
style={{ fill: "#8A1F0F" }}
|
||||
d="M110.55,7.79c1.04,2.73,2.8,3.09,3.55,2.77c0.45-0.19,1.25-1.84,0.01-4.47
|
||||
c-0.99-2.09-2.17-2.74-2.93-2.61C110.42,3.6,109.69,5.53,110.55,7.79z"
|
||||
/>
|
||||
<g>
|
||||
<path
|
||||
style={{ fill: "#8A1F0F" }}
|
||||
d="M91.94,18.34c-0.22,0-0.44-0.11-0.58-0.3l-3.99-5.77c-0.22-0.32-0.14-0.75,0.18-0.97
|
||||
c0.32-0.22,0.76-0.14,0.97,0.18l3.99,5.77c0.22,0.32,0.14,0.75-0.18,0.97C92.21,18.3,92.07,18.34,91.94,18.34z"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
style={{ fill: "#8A1F0F" }}
|
||||
d="M90.28,19.43c-0.18,0-0.35-0.07-0.49-0.2l-5.26-5.12c-0.28-0.27-0.28-0.71-0.01-0.99
|
||||
c0.27-0.28,0.71-0.28,0.99-0.01l5.26,5.12c0.28,0.27,0.28,0.71,0.01,0.99C90.64,19.36,90.46,19.43,90.28,19.43z"
|
||||
/>
|
||||
</g>
|
||||
<g>
|
||||
<path
|
||||
style={{ fill: "#8A1F0F" }}
|
||||
d="M89.35,21.22c-0.12,0-0.25-0.03-0.36-0.1l-5.6-3.39c-0.33-0.2-0.44-0.63-0.24-0.96
|
||||
c0.2-0.33,0.63-0.44,0.96-0.24l5.6,3.39c0.33,0.2,0.44,0.63,0.24,0.96C89.82,21.1,89.59,21.22,89.35,21.22z"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
116
docs/src/app/components/pages/home.tsx
Normal file
@@ -0,0 +1,116 @@
|
||||
import React from "react";
|
||||
import "./styles.css";
|
||||
|
||||
import { Browser } from "../Browser";
|
||||
import { Card } from "../Card";
|
||||
import {
|
||||
IconAdjustments,
|
||||
IconArrowRight,
|
||||
IconBarrierBlockOff,
|
||||
IconBolt,
|
||||
IconFeather,
|
||||
IconGitMerge,
|
||||
IconPuzzle,
|
||||
IconServer,
|
||||
IconTerminal,
|
||||
} from "@tabler/icons-react";
|
||||
import { GitHubIcon } from "nextra/icons";
|
||||
import { GridPattern } from "../GridPattern";
|
||||
import { GradientText } from "../GradientText";
|
||||
import Link from "next/link";
|
||||
|
||||
export default async function Home() {
|
||||
return (
|
||||
<>
|
||||
<div className="relative home bg-radial-[ellipse_at_center] from-transparent from-20% to-white dark:to-black">
|
||||
<GridPattern />
|
||||
<div className="px-4 pt-16 pb-8 sm:pt-24 lg:px-8">
|
||||
<div className="flex w-full flex-col items-center justify-between">
|
||||
<div>
|
||||
<h1 className="mx-auto max-w-2xl text-center text-6xl leading-none font-extrabold tracking-tighter text-black sm:text-7xl dark:text-white">
|
||||
The easiest way to manage your
|
||||
<GradientText
|
||||
text="container updates."
|
||||
className="mx-auto w-fit"
|
||||
innerClassName="bg-linear-to-r/oklch from-blue-500 to-green-500"
|
||||
blur={30}
|
||||
/>
|
||||
</h1>
|
||||
<h3 className="mx-auto mt-6 max-w-3xl text-center text-xl leading-tight font-medium text-neutral-500 dark:text-neutral-400">
|
||||
Cup is a small utility with a big impact. Simplify your
|
||||
container management workflow with fast and efficient update
|
||||
checking, a full-featured CLI and web interface, and more.
|
||||
</h3>
|
||||
</div>
|
||||
<div className="mt-8 grid w-fit grid-cols-2 gap-4 *:flex *:items-center *:gap-2 *:rounded-lg *:px-3 *:py-2">
|
||||
<Link
|
||||
href="/docs"
|
||||
className="hide-focus group h-full bg-black text-white dark:bg-white dark:text-black"
|
||||
>
|
||||
Get started
|
||||
<IconArrowRight className="ml-auto mr-1 transition-transform duration-300 ease-out group-hover:translate-x-1 group-focus:translate-x-1 dark:!text-black" />
|
||||
</Link>
|
||||
<a
|
||||
href="https://github.com/sergi0g/cup"
|
||||
target="_blank"
|
||||
className="hide-focus h-full bg-white dark:bg-black text-nowrap border border-black/15 transition-colors duration-200 ease-in-out hover:border-black/40 dark:border-white/15 hover:dark:border-white/40 hover:dark:shadow-sm focus:dark:border-white/30"
|
||||
>
|
||||
Star on GitHub
|
||||
<GitHubIcon className="ml-auto size-4 md:size-5" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="py-10 flex translate-y-32 justify-center" id="hero">
|
||||
<Browser />
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-white dark:bg-black py-12 px-8 w-full">
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<div className="grid md:grid-cols-2 md:grid-rows-4 lg:grid-cols-4 lg:grid-rows-2 w-full max-w-7xl gap-px border border-transparent bg-black/10 dark:bg-white/10">
|
||||
<Card
|
||||
name="Built for speed."
|
||||
icon={IconBolt}
|
||||
description="Cup is written in Rust and every release goes through extensive profiling to squeeze out every last drop of performance."
|
||||
/>
|
||||
<Card
|
||||
name="Configurable."
|
||||
icon={IconAdjustments}
|
||||
description="Make Cup yours with the extensive configuration options available. Customize and tailor it to your needs."
|
||||
/>
|
||||
<Card
|
||||
name="Extend it."
|
||||
icon={IconPuzzle}
|
||||
description="JSON output enables you to connect Cup with your favorite integrations, build automations and more."
|
||||
/>
|
||||
<Card
|
||||
name="CLI available."
|
||||
icon={IconTerminal}
|
||||
description="Do you like terminals? Cup has a CLI. Check for updates quickly without spinning up a server."
|
||||
/>
|
||||
<Card
|
||||
name="Multiple servers."
|
||||
icon={IconServer}
|
||||
description="Run multiple Cup instances and effortlessly check on them through one web interface."
|
||||
/>
|
||||
<Card
|
||||
name="Unstoppable."
|
||||
icon={IconBarrierBlockOff}
|
||||
description="Cup is designed to check for updates without using up any rate limits. 10 images per hour won't be a problem, even with 100 images."
|
||||
/>
|
||||
<Card
|
||||
name="Lightweight."
|
||||
icon={IconFeather}
|
||||
description="No need for a powerful server and endless storage. The tiny 5.4 MB binary won't hog your CPU and memory."
|
||||
/>
|
||||
<Card
|
||||
name="Open source."
|
||||
icon={IconGitMerge}
|
||||
description="All source code is publicly available in our GitHub repository. We're looking for contributors!"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
26
docs/src/app/components/pages/styles.css
Normal file
@@ -0,0 +1,26 @@
|
||||
article:has(.home) {
|
||||
padding-inline: 0;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
article div.x\:mt-16:last-child:empty {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
#hero {
|
||||
animation-name: hero;
|
||||
animation-duration: 1500ms;
|
||||
animation-delay: 500ms;
|
||||
animation-timing-function: ease-in-out;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
@keyframes hero {
|
||||
from {
|
||||
translate: 0 8rem;
|
||||
}
|
||||
to {
|
||||
translate: 0 0;
|
||||
}
|
||||
}
|
||||
BIN
docs/src/app/favicon.ico
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
17
docs/src/app/globals.css
Normal file
@@ -0,0 +1,17 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
@variant dark (&:where(.dark, .dark *));
|
||||
|
||||
.nextra-card .tabler-icon:hover {
|
||||
color: rgb(17 24 39 / var(--tw-text-opacity));
|
||||
}
|
||||
.nextra-card .tabler-icon {
|
||||
color: rgb(55 65 81 / var(--tw-text-opacity));
|
||||
}
|
||||
.nextra-card .tabler-icon:is(.dark *) {
|
||||
color: rgb(229 229 229 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.nextra-card .tabler-icon:is(.dark *):hover {
|
||||
color: rgb(250 250 250 / var(--tw-text-opacity));
|
||||
}
|
||||
55
docs/src/app/layout.tsx
Normal file
@@ -0,0 +1,55 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Footer, Layout, Navbar, ThemeSwitch } from "nextra-theme-docs";
|
||||
import { getPageMap } from "nextra/page-map";
|
||||
import { GeistSans } from "geist/font/sans";
|
||||
import "nextra-theme-docs/style.css";
|
||||
import "./globals.css";
|
||||
import { Head } from "./components/Head";
|
||||
import Logo from "./components/Logo";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Cup",
|
||||
description: "The easiest way to manage your container updates",
|
||||
};
|
||||
|
||||
const logo = (
|
||||
<div className="flex items-center">
|
||||
<Logo />
|
||||
<h1 className="ml-2 font-bold">Cup</h1>
|
||||
</div>
|
||||
);
|
||||
|
||||
const navbar = (
|
||||
<Navbar logo={logo} projectLink="https://github.com/sergi0g/cup" chatLink="https://discord.gg/jmh5ctzwNG">
|
||||
<ThemeSwitch lite className="cursor-pointer" />
|
||||
</Navbar>
|
||||
);
|
||||
|
||||
const footer = <Footer> </Footer>;
|
||||
|
||||
export default async function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
return (
|
||||
<html
|
||||
lang="en"
|
||||
dir="ltr"
|
||||
suppressHydrationWarning
|
||||
className={`${GeistSans.className} antialiased`}
|
||||
>
|
||||
<Head />
|
||||
<body>
|
||||
<Layout
|
||||
navbar={navbar}
|
||||
pageMap={await getPageMap()}
|
||||
footer={footer}
|
||||
docsRepositoryBase="https://github.com/sergi0g/cup"
|
||||
>
|
||||
<div>{children}</div>
|
||||
</Layout>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
23
docs/src/app/page.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { useMDXComponents } from "@/mdx-components";
|
||||
import { Heading, NextraMetadata } from "nextra";
|
||||
import Home from "./components/pages/home";
|
||||
|
||||
/* eslint-disable-next-line */
|
||||
const Wrapper = useMDXComponents({}).wrapper;
|
||||
|
||||
const toc: Heading[] = [];
|
||||
|
||||
export const metadata: NextraMetadata = {
|
||||
title: "Cup - The easiest way to manage your container updates",
|
||||
description: "Simple, fast, efficient Docker image update checking",
|
||||
filePath: "",
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
// @ts-expect-error This component passes all extra props to the underlying component, but that possibility does not exist in the type declarations. A comment there indicates that passing extra props is intended functionality.
|
||||
<Wrapper toc={toc} metadata={metadata} className={"x:mx-auto x:flex"}>
|
||||
<Home />
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
17
docs/src/content/_meta.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
export default {
|
||||
index: {
|
||||
theme: {
|
||||
sidebar: false,
|
||||
toc: false,
|
||||
breadcrumb: false,
|
||||
pagination: false,
|
||||
timestamp: false,
|
||||
layout: "full",
|
||||
},
|
||||
display: "hidden",
|
||||
},
|
||||
docs: {
|
||||
type: "page",
|
||||
title: "Documentation",
|
||||
},
|
||||
};
|
||||
5
docs/src/content/docs/_meta.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export default {
|
||||
installation: {},
|
||||
usage: {},
|
||||
configuration: {},
|
||||
};
|
||||
43
docs/src/content/docs/community-resources/docker-compose.mdx
Normal file
@@ -0,0 +1,43 @@
|
||||
# Docker Compose
|
||||
|
||||
Many users find it useful to run Cup with Docker Compose, as it enables them to have it constantly running in the background and easily control it. Cup's lightweight resource use makes it ideal for this use case.
|
||||
|
||||
There have been requests for an official Docker Compose file, but I believe you should customize it to your needs.
|
||||
|
||||
Here is an example of what I would use (by [@ioverho](https://github.com/ioverho)):
|
||||
|
||||
```yaml
|
||||
services:
|
||||
cup:
|
||||
image: ghcr.io/sergi0g/cup:latest
|
||||
container_name: cup # Optional
|
||||
restart: unless-stopped
|
||||
command: -c /config/cup.json serve
|
||||
ports:
|
||||
- 8000:8000
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./cup.json:/config/cup.json
|
||||
```
|
||||
|
||||
If you don't have a config, you can use this instead:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
cup:
|
||||
image: ghcr.io/sergi0g/cup:latest
|
||||
container_name: cup # Optional
|
||||
restart: unless-stopped
|
||||
command: serve
|
||||
ports:
|
||||
- 8000:8000
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
```
|
||||
|
||||
Cup can run with a non-root user, but needs to be in a docker group. Assuming user id of 1000 and `docker` group id of 999 you can add this to the `services.cup` key in the docker compose:
|
||||
```yaml
|
||||
user: "1000:999"
|
||||
```
|
||||
|
||||
The compose can be customized further of course, if you choose to use a different port, another config location, or would like to change something else. Have fun!
|
||||
@@ -0,0 +1,79 @@
|
||||
import Image from "next/image";
|
||||
import widget1 from "@/app/assets/350767810-42eccc89-bdfd-426a-a113-653abe7483d8.png";
|
||||
import widget2 from "@/app/assets/358304960-e9f26767-51f7-4b5a-8b74-a5811019497b.jpeg";
|
||||
|
||||
# Homepage Widget
|
||||
|
||||
Some users have asked for a homepage widget.
|
||||
|
||||
## Docker Compose with the widget configured via labels:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
cup:
|
||||
image: ghcr.io/sergi0g/cup
|
||||
container_name: cup
|
||||
command: -c /config/cup.json serve -p 8000
|
||||
volumes:
|
||||
- ./config/cup.json:/config/cup.json
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
ports:
|
||||
- 8000:8000
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
homepage.group: Network
|
||||
homepage.name: Cup
|
||||
homepage.icon: /icons/cup-with-straw.png
|
||||
homepage.href: http://myserver:8000
|
||||
homepage.ping: http://myserver:8000
|
||||
homepage.description: Checks for container updates
|
||||
homepage.widget.type: customapi
|
||||
homepage.widget.url: http://myserver:8000/api/v3/json
|
||||
homepage.widget.mappings[0].label: Monitoring
|
||||
homepage.widget.mappings[0].field.metrics: monitored_images
|
||||
homepage.widget.mappings[0].format: number
|
||||
homepage.widget.mappings[1].label: Up to date
|
||||
homepage.widget.mappings[1].field.metrics: up_to_date
|
||||
homepage.widget.mappings[1].format: number
|
||||
homepage.widget.mappings[2].label: Updates
|
||||
homepage.widget.mappings[2].field.metrics: updates_available
|
||||
homepage.widget.mappings[2].format: number
|
||||
```
|
||||
|
||||
Preview:
|
||||
|
||||
<Image src={widget1} />
|
||||
|
||||
Credit: [@agrmohit](https://github.com/agrmohit)
|
||||
|
||||
## Widget in Homepage's config file format:
|
||||
|
||||
```yaml
|
||||
widget:
|
||||
type: customapi
|
||||
url: http://<SERVER_IP>:9000/api/v3/json
|
||||
refreshInterval: 10000
|
||||
method: GET
|
||||
mappings:
|
||||
- field:
|
||||
metrics: monitored_images
|
||||
label: Monitored images
|
||||
format: number
|
||||
- field:
|
||||
metrics: up_to_date
|
||||
label: Up to date
|
||||
format: number
|
||||
- field:
|
||||
metrics: updates_available
|
||||
label: Available updates
|
||||
format: number
|
||||
- field:
|
||||
metrics: unknown
|
||||
label: Unknown
|
||||
format: number
|
||||
```
|
||||
|
||||
Preview:
|
||||
|
||||
<Image src={widget2} />
|
||||
Credit: [@remussamoila](https://github.com/remussamoila)
|
||||
12
docs/src/content/docs/configuration/agent.mdx
Normal file
@@ -0,0 +1,12 @@
|
||||
# Agent mode
|
||||
|
||||
If you'd like to have only the server API exposed without the dashboard, you can run Cup in agent mode.
|
||||
|
||||
Modify your config like this:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"agent": true
|
||||
// Other options
|
||||
}
|
||||
```
|
||||
26
docs/src/content/docs/configuration/authentication.mdx
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Callout } from "nextra/components";
|
||||
|
||||
# Authentication
|
||||
|
||||
Some registries (or specific images) may require you to be authenticated. For those, you can modify `cup.json` like this:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"registries": {
|
||||
"<YOUR_REGISTRY_DOMAIN_1>": {
|
||||
"authentication": "<YOUR_TOKEN_1>"
|
||||
// Other options
|
||||
},
|
||||
"<YOUR_REGISTRY_DOMAIN_2>" {
|
||||
"authentication": "<YOUR_TOKEN_2>"
|
||||
// Other options
|
||||
},
|
||||
// ...
|
||||
}
|
||||
// Other options
|
||||
}
|
||||
```
|
||||
|
||||
You can use any registry, like `ghcr.io`, `quay.io`, `gcr.io`, etc.
|
||||
|
||||
<Callout emoji="⚠️">For Docker Hub, use `registry-1.docker.io`</Callout>
|
||||
12
docs/src/content/docs/configuration/automatic-refresh.mdx
Normal file
@@ -0,0 +1,12 @@
|
||||
# Automatic refresh
|
||||
|
||||
Cup can automatically refresh the results when running in server mode. Simply add this to your config:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"refresh_interval": "0 0,30 * 0 0" // Check twice an hour
|
||||
// Other options
|
||||
}
|
||||
```
|
||||
|
||||
You can use a cron expression to specify the refresh interval. The reference is [here](https://github.com/Hexagon/croner-rust#pattern)
|
||||
22
docs/src/content/docs/configuration/ignore-registry.mdx
Normal file
@@ -0,0 +1,22 @@
|
||||
# Ignored registries
|
||||
|
||||
If you want to skip checking images from some registries, you can modify your config like this:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"registries": {
|
||||
"<SOME_REGISTRY_DOMAIN_1>": {
|
||||
"ignore": true
|
||||
// Other options
|
||||
},
|
||||
"<SOME_REGISTRY_DOMAIN_2>" {
|
||||
"ignore": false
|
||||
// Other options
|
||||
},
|
||||
// ...
|
||||
}
|
||||
// Other options
|
||||
}
|
||||
```
|
||||
|
||||
This configuration option is a bit redundant, since you can achieve the same with [this option](/docs/configuration/include-exclude-images). It's recommended to use that.
|
||||
@@ -0,0 +1,35 @@
|
||||
# Include/Exclude images
|
||||
|
||||
If you want to exclude some images (e.g. because they have too many tags and take too long to check), you can add the following to your config:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"images": {
|
||||
"exclude": [
|
||||
"ghcr.io/immich-app/immich-machine-learning",
|
||||
"postgres:15"
|
||||
]
|
||||
// ...
|
||||
}
|
||||
// Other options
|
||||
}
|
||||
```
|
||||
|
||||
For an image to be excluded, it must start with one of the strings you specify above. That means you could use `ghcr.io` to exclude all images from ghcr.io or `ghcr.io/sergi0g` to exclude all my images (why would you do that?).
|
||||
|
||||
|
||||
If you want Cup to always check some extra images that aren't available locally, you can modify your config like this:
|
||||
```jsonc
|
||||
{
|
||||
"images": {
|
||||
"extra": [
|
||||
"mysql:8.0",
|
||||
"nextcloud:30"
|
||||
]
|
||||
// ...
|
||||
}
|
||||
// Other options
|
||||
}
|
||||
```
|
||||
|
||||
Note that you must specify images with version tags, otherwise Cup will exit with an error!
|
||||
111
docs/src/content/docs/configuration/index.mdx
Normal file
@@ -0,0 +1,111 @@
|
||||
---
|
||||
asIndexPage: true
|
||||
---
|
||||
|
||||
import { Steps, Callout, Cards } from "nextra/components";
|
||||
import {
|
||||
IconPaint,
|
||||
IconLockOpen,
|
||||
IconKey,
|
||||
IconPlug,
|
||||
IconServer,
|
||||
} from "@tabler/icons-react";
|
||||
|
||||
# Configuration
|
||||
|
||||
## Custom docker socket
|
||||
|
||||
Sometimes, there may be a need to specify a custom docker socket. Cup provides the `-s` option for this.
|
||||
|
||||
For example, if using Podman, you might do
|
||||
|
||||
```bash
|
||||
$ cup -s /run/user/1000/podman/podman.sock check
|
||||
```
|
||||
|
||||
This option is also available in the configuration file and it's best to put it there.
|
||||
|
||||
<Cards.Card
|
||||
icon={<IconPlug />}
|
||||
title="Custom Docker socket"
|
||||
href="/docs/configuration/socket"
|
||||
/>
|
||||
|
||||
## Configuration file
|
||||
|
||||
Cup has an option to be configured from a configuration file named `cup.json`.
|
||||
|
||||
<Steps>
|
||||
### Create the configuration file
|
||||
Create a `cup.json` file somewhere on your system. For binary installs, a path like `~/.config/cup.json` is recommended.
|
||||
If you're running with Docker, you can create a `cup.json` in the directory you're running Cup and mount it into the container. _In the next section you will need to use the path where you **mounted** the file_
|
||||
|
||||
### Configure Cup from the configuration file
|
||||
|
||||
Follow the guides below to customize your `cup.json`
|
||||
|
||||
<Cards>
|
||||
<Cards.Card
|
||||
icon={<IconKey />}
|
||||
title="Authentication"
|
||||
href="/docs/configuration/authentication"
|
||||
/>
|
||||
<Cards.Card
|
||||
icon={<IconLockOpen />}
|
||||
title="Insecure registries"
|
||||
href="/docs/configuration/insecure-registries"
|
||||
/>
|
||||
<Cards.Card
|
||||
icon={<IconPaint />}
|
||||
title="Theme"
|
||||
href="/docs/configuration/theme"
|
||||
/>
|
||||
<Cards.Card
|
||||
icon={<IconServer />}
|
||||
title="Multiple servers"
|
||||
href="/docs/configuration/servers"
|
||||
/>
|
||||
</Cards>
|
||||
|
||||
Here's a full example:
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/sergi0g/cup/main/cup.schema.json",
|
||||
"version": 3,
|
||||
"images": {
|
||||
"exclude": ["ghcr.io/immich-app/immich-machine-learning"],
|
||||
"extra": ["ghcr.io/sergi0g/cup:v3.0.0"]
|
||||
},
|
||||
"registries": {
|
||||
"myregistry.com": {
|
||||
"authentication": "<YOUR_TOKEN_HERE>"
|
||||
}
|
||||
},
|
||||
"servers": {
|
||||
"Raspberry Pi": "https://server.local:8000"
|
||||
},
|
||||
"theme": "blue"
|
||||
}
|
||||
```
|
||||
|
||||
<Callout>
|
||||
If you want autocompletions and error checking for your editor, there is a
|
||||
JSON schema available. Use it by adding a `"$schema":
|
||||
"https://raw.githubusercontent.com/sergi0g/cup/main/cup.schema.json"` entry in
|
||||
your `cup.json` file.
|
||||
</Callout>
|
||||
|
||||
### Run Cup with the new configuration file
|
||||
|
||||
To let Cup know that you'd like it to use a custom configuration file, you can use the `-c` flag, followed by the _absolute_ path of the file.
|
||||
|
||||
```bash
|
||||
$ cup -c /home/sergio/.config/cup.json check
|
||||
```
|
||||
|
||||
```bash
|
||||
$ docker run -tv /var/run/docker.sock:/var/run/docker.sock -v /home/sergio/.config/cup.json:/config/cup.json ghcr.io/sergi0g/cup -c /config/cup.json serve
|
||||
```
|
||||
|
||||
</Steps>
|
||||
32
docs/src/content/docs/configuration/insecure-registries.mdx
Normal file
@@ -0,0 +1,32 @@
|
||||
import { Callout } from "nextra/components";
|
||||
|
||||
# Insecure registries
|
||||
|
||||
For the best security, Cup only connects to registries over SSL (HTTPS) by default. However, for people running a local registry that doesn't support SSL, this may be a problem.
|
||||
|
||||
To solve this problem, you can specify exceptions in your `cup.json`.
|
||||
|
||||
Here's what it looks like:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"registries": {
|
||||
"<INSECURE_REGISTRY_1>": {
|
||||
"insecure": true
|
||||
// Other options
|
||||
},
|
||||
"<INSECURE_REGISTRY_2>" {
|
||||
"insecure": true
|
||||
// Other options
|
||||
},
|
||||
// ...
|
||||
}
|
||||
// Other options
|
||||
}
|
||||
```
|
||||
|
||||
<Callout emoji="⚠️">
|
||||
When configuring an insecure registry that doesn't run on port 80, don't
|
||||
forget to specify the port (i.e. use `localhost:5000` instead of `localhost`
|
||||
if your registry is running on port `5000`)
|
||||
</Callout>
|
||||
15
docs/src/content/docs/configuration/servers.mdx
Normal file
@@ -0,0 +1,15 @@
|
||||
# Multiple servers
|
||||
|
||||
Besides checking for local image updates, you might want to be able to view update stats for all your servers running Cup in a central place. If you choose to add more servers to your Cup configuration, Cup will retrieve the current list of updates from your other servers and it will be included in the results.
|
||||
|
||||
Just add something like this to your config:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"servers": {
|
||||
"Cool server 1": "http://your-other-server-running-cup:8000",
|
||||
"Other server": "http://and-another-one:9000"
|
||||
}
|
||||
// Other options
|
||||
}
|
||||
```
|
||||
19
docs/src/content/docs/configuration/socket.mdx
Normal file
@@ -0,0 +1,19 @@
|
||||
# Custom socket
|
||||
|
||||
If you need to specify a custom Docker socket (e.g. because you're using Podman), you can use the `socket` option. Here's an example:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"socket": "/run/user/1000/podman/podman.sock"
|
||||
// Other options
|
||||
}
|
||||
```
|
||||
|
||||
You can also specify a TCP socket if you're using a remote Docker host or a [proxy](https://github.com/Tecnativa/docker-socket-proxy):
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"socket": "tcp://localhost:2375"
|
||||
// Other options
|
||||
}
|
||||
```
|
||||
31
docs/src/content/docs/configuration/theme.mdx
Normal file
@@ -0,0 +1,31 @@
|
||||
import { Callout } from "nextra/components";
|
||||
import Image from "next/image";
|
||||
|
||||
import blue from "@/app/assets/blue_theme.png";
|
||||
import neutral from "@/app/assets/hero-dark.png";
|
||||
|
||||
# Theme
|
||||
|
||||
<Callout emoji="⚠️">This configuration option is only for the server</Callout>
|
||||
|
||||
Cup initially had a blue theme which looked like this:
|
||||
|
||||
<Image alt="Screenshot of blue theme" src={blue} />
|
||||
|
||||
This was replaced by a more neutral theme which is now the default:
|
||||
|
||||
<Image alt="Screenshot of neutral theme" src={neutral} />
|
||||
|
||||
However, you can get the old theme back by adding the `theme` key to your `cup.json`
|
||||
Available options are `default` and `blue`.
|
||||
|
||||
Here's an example:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"theme": "blue"
|
||||
// Other options
|
||||
}
|
||||
```
|
||||
|
||||
Note that the difference between the 2 themes is almost impossible to perceive when your system is in light mode.
|
||||
71
docs/src/content/docs/contributing.mdx
Normal file
@@ -0,0 +1,71 @@
|
||||
import { Steps } from "nextra/components";
|
||||
|
||||
# Contributing
|
||||
|
||||
First of all, thanks for taking time to contribute to Cup! This guide will help you set up a development environment and make your first contribution.
|
||||
|
||||
## Setting up a development environment
|
||||
|
||||
Requirements:
|
||||
|
||||
- A computer running Linux
|
||||
- Rust (usually installed from https://rustup.rs/)
|
||||
- Node.js 22+ and Bun 1+
|
||||
|
||||
<Steps>
|
||||
### Fork the repository
|
||||
This is where you'll be pushing your changes before you create a pull request. Make sure to _create a new branch_ for your changes.
|
||||
### Clone your fork
|
||||
```bash
|
||||
git clone https://github.com/<YOUR_USERNAME>/cup
|
||||
```
|
||||
If you use SSH:
|
||||
```bash
|
||||
git clone git@github.com:<YOUR_USERNAME>/cup`)
|
||||
```
|
||||
### Switch to your newly created branch (e.g. if your branch is called `improve-logging`, run `git checkout improve-logging`)
|
||||
### Set up the frontend
|
||||
```bash
|
||||
$ cd web
|
||||
$ bun install
|
||||
$ cd ..
|
||||
$ ./build.sh
|
||||
```
|
||||
</Steps>
|
||||
|
||||
You're ready to go!
|
||||
|
||||
## Project architecture
|
||||
|
||||
Cup can be run in 2 modes: CLI and server.
|
||||
|
||||
All CLI specific functionality is located in `src/formatting.rs` and some other files in functions prefixed with `#[cfg(feature = "cli")]`.
|
||||
|
||||
All server specific functionality is located in `src/server.rs` and `web/`.
|
||||
|
||||
## Important notes
|
||||
|
||||
- When making any changes, always make sure to write optimize your code for:
|
||||
|
||||
- Performance: You should always benchmark Cup before making changes and after your changes to make sure there is none (or a very small) difference in time. Profiling old and new code is also good.
|
||||
- Readability: Include comments describing any new functions you create, give descriptive names to variables and when making a design decision or a compromise, ALWAYS include a comment explaining what you did and why.
|
||||
|
||||
- If you plan on developing the frontend without making backend changes, it is highly recommended to run `cup serve` in the background and start the frontend in development mode from `web/` with `bun dev`.
|
||||
|
||||
- If you make changes to the frontend, always remember to prefix your build command with the `build.sh` script which takes care of rebuilding the frontend. For example: `./build.sh cargo build -r`
|
||||
|
||||
- When adding new features to Cup (e.g. configuration options), make sure to update the documentation (located in `docs/`). Refer to other pages in the documentation, or to the [official docs](https://nextra.site) for any questions you may have. The docs use `pnpm` as their package manager.
|
||||
|
||||
- If you need help with finishing something (e.g. you've made some commits and need help with writing docs, you want some feedback about a design decision, etc.), you can open a draft PR and ask for help there.
|
||||
|
||||
## Submitting a PR
|
||||
|
||||
To have your changes included in Cup, you will need to create a pull request.
|
||||
|
||||
Before doing so, please make sure you have run `cargo clippy` and resolved all warnings related to your changes and have formatted your code with `cargo fmt`. This ensures Cup's codebase is consistent and uses good practices for code.
|
||||
|
||||
After you're done with that, commit your changes and push them to your branch.
|
||||
|
||||
Next, open your fork on Github and create a pull request. Make sure to include the changes you made, which issues it addresses (if any) and any other info you think is important.
|
||||
|
||||
Happy contributing!
|
||||
34
docs/src/content/docs/index.mdx
Normal file
@@ -0,0 +1,34 @@
|
||||
import Image from "next/image";
|
||||
import cup from "@/app/assets/cup.gif";
|
||||
import { Cards } from "nextra/components";
|
||||
import { IconBrandDocker, IconPackage } from "@tabler/icons-react";
|
||||
|
||||
# Introduction
|
||||
|
||||
<Image src={cup} alt="Animated GIF of Cup's CLI in action" unoptimized />
|
||||
|
||||
Cup is a lightweight alternative to [What's up Docker?](https://github.com/getwud/wud) written in Rust.
|
||||
|
||||
# Features ✨
|
||||
|
||||
- 🚀 Extremely fast. Cup takes full advantage of your CPU and is hightly optimized, resulting in lightning fast speed. On my Raspberry Pi 5, it took 3.7 seconds for 58 images!
|
||||
- Supports most registries, including Docker Hub, ghcr.io, Quay, lscr.io and even Gitea (or derivatives)
|
||||
- Doesn't exhaust any rate limits. This is the original reason I created Cup. It was inspired by [What's up docker?](https://github.com/getwud/wud) which would always use it up.
|
||||
- Beautiful CLI and web interface for checking on your containers any time.
|
||||
- The binary is tiny! At the time of writing it's just 5.4 MB. No more pulling 100+ MB docker images for a such a simple program.
|
||||
- JSON output for both the CLI and web interface so you can connect Cup to integrations. It's easy to parse and makes webhooks and pretty dashboards simple to set up!
|
||||
|
||||
# Installation
|
||||
|
||||
<Cards>
|
||||
<Cards.Card
|
||||
icon={<IconBrandDocker />}
|
||||
title="With Docker"
|
||||
href="/docs/installation/docker"
|
||||
/>
|
||||
<Cards.Card
|
||||
icon={<IconPackage />}
|
||||
title="As a binary"
|
||||
href="/docs/installation/binary"
|
||||
/>
|
||||
</Cards>
|
||||
8
docs/src/content/docs/installation/_meta.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export default {
|
||||
docker: {
|
||||
title: "With Docker",
|
||||
},
|
||||
binary: {
|
||||
title: "As a binary",
|
||||
},
|
||||
};
|
||||
28
docs/src/content/docs/installation/binary.mdx
Normal file
@@ -0,0 +1,28 @@
|
||||
import { Callout, Cards, Steps } from "nextra/components";
|
||||
import { IconFileDescription } from "@tabler/icons-react";
|
||||
|
||||
# As a binary
|
||||
|
||||
## Introduction
|
||||
|
||||
This guide will help you install Cup from a binary.
|
||||
|
||||
## Installation
|
||||
|
||||
<Steps>
|
||||
### Download binary
|
||||
Go to https://github.com/sergi0g/cup/releases/latest.
|
||||
|
||||
Depending on your system's architecture, choose the binary for your system. For example, for an `x86_64` machine, you should download `cup-x86_64-unknown-linux-musl`
|
||||
|
||||
<Callout>
|
||||
You can use the command `uname -i` to find this
|
||||
</Callout>
|
||||
### Add binary to path
|
||||
Move the binary you downloaded to a directory in your path. You can usually get a list those directories by running `echo $PATH`. On most Linux systems, moving it to `~/.local/bin` is usually enough.
|
||||
</Steps>
|
||||
|
||||
That's it! Cup is ready to be used. Head over to the Usage page to get started.
|
||||
|
||||
<br />
|
||||
<Cards.Card icon={<IconFileDescription />} title="Usage" href="/docs/usage" />
|
||||
27
docs/src/content/docs/installation/docker.mdx
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Callout, Cards } from "nextra/components";
|
||||
import { IconFileDescription } from "@tabler/icons-react";
|
||||
|
||||
# With Docker
|
||||
|
||||
## Introduction
|
||||
|
||||
This guide will help you install Cup as a Docker container. It is the easiest installation method and also makes updating Cup very easy.
|
||||
|
||||
## Installation
|
||||
|
||||
To get started, open up a terminal and run the following command.
|
||||
|
||||
```bash
|
||||
$ docker pull ghcr.io/sergi0g/cup
|
||||
```
|
||||
|
||||
<Callout emoji="⚠️">
|
||||
If you aren't a member of the `docker` group, please ensure you run all
|
||||
commands as a user who is. In most cases, you'll just need to prefix the
|
||||
`docker` commands with `sudo`
|
||||
</Callout>
|
||||
|
||||
That's it! Cup is ready to be used. Head over to the Usage page to get started.
|
||||
|
||||
<br />
|
||||
<Cards.Card icon={<IconFileDescription />} title="Usage" href="/docs/usage" />
|
||||
79
docs/src/content/docs/integrations.mdx
Normal file
@@ -0,0 +1,79 @@
|
||||
import { Callout, Cards } from "nextra/components";
|
||||
import { IconServer, IconTerminal } from "@tabler/icons-react"
|
||||
|
||||
# Integrations
|
||||
|
||||
At the moment, Cup has no built-in integrations, but it provides an API for the server and JSON output for the CLI, which can enable you to connect Cup to your own integrations.
|
||||
|
||||
## JSON data
|
||||
|
||||
The data returned from the API or from the CLI is in JSON and looks like this:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
// Statistics useful for displaying on dashboards.
|
||||
// You could calculate these yourself based on the rest of the data,
|
||||
// but they're provided for easier integration with other systems.
|
||||
"metrics": {
|
||||
"monitored_images": 5,
|
||||
"up_to_date": 2,
|
||||
"updates_available": 3,
|
||||
"major_updates": 1,
|
||||
"minor_updates": 0,
|
||||
"patch_updates": 0,
|
||||
"other_updates": 2,
|
||||
"unknown": 0,
|
||||
},
|
||||
// A list of image objects with all related information.
|
||||
"images": [
|
||||
{
|
||||
"reference": "ghcr.io/sergi0g/cup:latest",
|
||||
"parts": {
|
||||
// The information Cup extracted about the image from the reference. Mostly useful for debugging and the way the web interface works.
|
||||
"registry": "ghcr.io",
|
||||
"repository": "sergi0g/cup",
|
||||
"tag": "latest",
|
||||
},
|
||||
"result": {
|
||||
"has_update": true, // `true` when an image has an update of any kind, `false` when up to date and `null` when unknown.
|
||||
"info": {
|
||||
// `null` if up to date
|
||||
"type": "digest", // Can also be `version` when Cup detects the tag contains a version.
|
||||
// If `type` is "digest":
|
||||
"local_digests": [
|
||||
// A list of local digests present for the image
|
||||
"sha256:b7168e5f6828cbbd3622fa19965007e4611cf42b5f3c603008377ffd45a4fe00",
|
||||
],
|
||||
"remote_digest": "sha256:170f1974d8fc8ca245bcfae5590bc326de347b19719972bf122400fb13dfa42c", // Latest digest available in the registry
|
||||
// If `type` is "version":
|
||||
"version_update_type": "major", // Loosely corresponds to SemVer versioning. Can also be `minor` or `patch`.
|
||||
"new_tag": "v3.3.3", // The tag of the latest image.
|
||||
},
|
||||
"error": null, // If checking for the image fails, will be a string with an error message.
|
||||
},
|
||||
"time": 869, // Time in milliseconds it took to check for the update. Useful for debugging.
|
||||
"server": "Lithium", // The name of the server which the image was checked for updates on. `null` if from the current machine.
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
<Callout emoji="⚠️">
|
||||
Please keep in mind that the above may not always be up to date. New fields
|
||||
may be added, or some types extended. If you notice that, just open an issue
|
||||
and they'll be updated. Changes to the JSON data schema will _always_ happen
|
||||
in a backwards-compatible way. In case backwards-incompatible changes are
|
||||
made, these docs will be updated. For something more up-to-date, you can
|
||||
take a look at https://github.com/sergi0g/cup/blob/main/web/src/types.ts
|
||||
</Callout>
|
||||
|
||||
For retrieving the above data, refer to the CLI and server pages:
|
||||
|
||||
<Cards>
|
||||
<Cards.Card icon={<IconTerminal />} title="CLI" href="/docs/usage/cli" />
|
||||
<Cards.Card
|
||||
icon={<IconServer />}
|
||||
title="Server"
|
||||
href="/docs/usage/server"
|
||||
/>
|
||||
</Cards>
|
||||
25
docs/src/content/docs/nightly.mdx
Normal file
@@ -0,0 +1,25 @@
|
||||
import { Callout } from "nextra/components";
|
||||
|
||||
# Using the latest version
|
||||
|
||||
The installation instructions you previously followed describe how to install Cup's stable version.
|
||||
|
||||
However, it is only updated when a new release is created, so if you want the latest features, you'll need to install Cup's nightly version.
|
||||
|
||||
Cup's nightly version always contains the latest changes in the main branch.
|
||||
|
||||
<Callout emoji="⚠️">
|
||||
There is no guarantee that the nightly version will always work. There may be
|
||||
breaking changes or a bad commit and it may not work properly. Install nightly
|
||||
only if you know what you are doing. These instructions will assume you have
|
||||
the technical know-how to follow them. If you do not, please use the stable
|
||||
release!
|
||||
</Callout>
|
||||
|
||||
## With Docker
|
||||
|
||||
Instead of `ghcr.io/sergi0g/cup`, use `ghcr.io/sergi0g/cup:nightly`
|
||||
|
||||
## As a binary
|
||||
|
||||
Go to a [nightly workflow run](https://github.com/sergi0g/cup/actions/workflows/nightly.yml) and download the artifact for your system.
|
||||
99
docs/src/content/docs/usage/cli.mdx
Normal file
@@ -0,0 +1,99 @@
|
||||
import Image from "next/image";
|
||||
import cup from "@/app/assets/cup.gif";
|
||||
import { Callout } from "nextra/components";
|
||||
|
||||
# CLI
|
||||
|
||||
Cup's CLI provides the `cup check` command.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
### Check for all updates
|
||||
|
||||
```ansi
|
||||
$ cup check
|
||||
[32;1m✓[0m Done!
|
||||
[90;1m~ Local images[0m
|
||||
[90;1m╭─────────────────────────────────────────┬──────────────────────────────────┬─────────╮[0m
|
||||
[90;1m│[36;1mReference [90;1m│[36;1mStatus [90;1m│[36;1mTime (ms)[90;1m│[0m
|
||||
[90;1m├─────────────────────────────────────────┼──────────────────────────────────┼─────────┤[0m
|
||||
[90;1m│[0mpostgres:15-alpine [90;1m│[0m[31mMajor update (15 → 17) [0m[90;1m│[0m788 [90;1m│[0m
|
||||
[90;1m│[0mghcr.io/immich-app/immich-server:v1.118.2[90;1m│[0m[33mMinor update (1.118.2 → 1.127.0) [0m[90;1m│[0m2294 [90;1m│[0m
|
||||
[90;1m│[0mollama/ollama:0.4.1 [90;1m│[0m[33mMinor update (0.4.1 → 0.5.12) [0m[90;1m│[0m533 [90;1m│[0m
|
||||
[90;1m│[0madguard/adguardhome:v0.107.52 [90;1m│[0m[34mPatch update (0.107.52 → 0.107.57)[0m[90;1m│[0m1738 [90;1m│[0m
|
||||
[90;1m│[0mjc21/nginx-proxy-manager:latest [90;1m│[0m[32mUp to date [0m[90;1m│[0m583 [90;1m│[0m
|
||||
[90;1m│[0mlouislam/uptime-kuma:1 [90;1m│[0m[32mUp to date [0m[90;1m│[0m793 [90;1m│[0m
|
||||
[90;1m│[0mmoby/buildkit:buildx-stable-1 [90;1m│[0m[32mUp to date [0m[90;1m│[0m600 [90;1m│[0m
|
||||
[90;1m│[0mtecnativa/docker-socket-proxy:latest [90;1m│[0m[32mUp to date [0m[90;1m│[0m564 [90;1m│[0m
|
||||
[90;1m│[0mubuntu:latest [90;1m│[0m[32mUp to date [0m[90;1m│[0m585 [90;1m│[0m
|
||||
[90;1m│[0mwagoodman/dive:latest [90;1m│[0m[32mUp to date [0m[90;1m│[0m585 [90;1m│[0m
|
||||
[90;1m│[0mrolebot:latest [90;1m│[0m[90mUnknown [0m[90;1m│[0m174 [90;1m│[0m
|
||||
[90;1m╰─────────────────────────────────────────┴──────────────────────────────────┴─────────╯[0m
|
||||
[36;1m INFO[0m ✨ Checked 11 images in 8312ms
|
||||
```
|
||||
|
||||
### Check for updates to specific images
|
||||
|
||||
```ansi
|
||||
$ cup check node:latest
|
||||
[32;1m✓[0m Done!
|
||||
[90;1m~ Local images[0m
|
||||
[90;1m╭───────────┬────────────────┬─────────╮[0m
|
||||
[90;1m│[36;1mReference [90;1m│[36;1mStatus [90;1m│[36;1mTime (ms)[90;1m│[0m
|
||||
[90;1m├───────────┼────────────────┼─────────┤[0m
|
||||
[90;1m│[0mnode:latest[90;1m│[0m[34mUpdate available[0m[90;1m│[0m788 [90;1m│[0m
|
||||
[90;1m╰───────────┴────────────────┴─────────╯[0m
|
||||
[36;1m INFO[0m ✨ Checked 1 images in 310ms
|
||||
```
|
||||
|
||||
```ansi
|
||||
$ cup check nextcloud:30 postgres:14 mysql:8.0[38;5;12m
|
||||
[32;1m✓[0m Done!
|
||||
[90;1m~ Local images[0m
|
||||
[90;1m╭────────────┬────────────────────────┬─────────╮[0m
|
||||
[90;1m│[36;1mReference [90;1m│[36;1mStatus [90;1m│[36;1mTime (ms)[90;1m│[0m
|
||||
[90;1m├────────────┼────────────────────────┼─────────┤[0m
|
||||
[90;1m│[0mpostgres:14 [90;1m│[0m[31mMajor update (14 → 17) [0m[90;1m│[0m195 [90;1m│[0m
|
||||
[90;1m│[0mmysql:8.0 [90;1m│[0m[31mMajor update (8.0 → 9.2)[0m[90;1m│[0m382 [90;1m│[0m
|
||||
[90;1m│[0mnextcloud:30[90;1m│[0m[32mUp to date [0m[90;1m│[0m585 [90;1m│[0m
|
||||
[90;1m╰────────────┴────────────────────────┴─────────╯[0m
|
||||
[36;1m INFO[0m ✨ Checked 3 images in 769ms
|
||||
```
|
||||
|
||||
## Enable icons
|
||||
|
||||
You can also enable icons if you have a [Nerd Font](https://nerdfonts.com) installed.
|
||||
|
||||
<Image src={cup} alt="GIF of Cup's CLI" unoptimized />
|
||||
|
||||
## JSON output
|
||||
|
||||
When integrating Cup with other services (e.g. webhooks or a dashboard), you may find Cup's JSON output functionality useful.
|
||||
|
||||
It provides some useful metrics (see [server](/docs/usage/server) for more information), along with a list of images and whether they have an update or not. Note that at the moment it does not match the detailed API the server provides.
|
||||
|
||||
```
|
||||
$ cup check -r
|
||||
{"metrics":{"monitored_images":26,"up_to_date":2,"updates_available":23,"major_updates":8,"minor_updates":6,"patch_updates":2,"other_updates":7,"unknown":1},"images":{"ghcr.io/immich-app/immich-server:v1.106.4":false,"portainer/portainer-ce:2.20.3-alpine":false,"ghcr.io/runtipi/runtipi:v3.4.1":false,...}}
|
||||
```
|
||||
|
||||
<Callout emoji="⚠️">
|
||||
When parsing Cup's output, capture only `stdout`, otherwise you might not get
|
||||
valid JSON (if there are warnings)
|
||||
</Callout>
|
||||
|
||||
## Usage with Docker
|
||||
|
||||
If you're using the Docker image, just replace all occurences of `cup` in the examples with `docker run -tv /var/run/docker.sock:/var/run/docker.sock ghcr.io/sergi0g/cup`.
|
||||
|
||||
For example, this:
|
||||
|
||||
```bash
|
||||
$ cup check node:latest
|
||||
```
|
||||
|
||||
becomes:
|
||||
|
||||
```bash
|
||||
$ docker run -tv /var/run/docker.sock:/var/run/docker.sock ghcr.io/sergi0g/cup check node:latest
|
||||
```
|
||||
15
docs/src/content/docs/usage/index.mdx
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
asIndexPage: true
|
||||
---
|
||||
|
||||
import { IconServer, IconTerminal } from "@tabler/icons-react";
|
||||
import { Cards } from "nextra/components";
|
||||
|
||||
# Usage
|
||||
|
||||
You can use Cup in 2 different ways. As a CLI or as a server. You can learn more about each mode on its corresponding page
|
||||
|
||||
<Cards>
|
||||
<Cards.Card icon={<IconTerminal />} title="CLI" href="/docs/usage/cli" />
|
||||
<Cards.Card icon={<IconServer />} title="Server" href="/docs/usage/server" />
|
||||
</Cards>
|
||||
55
docs/src/content/docs/usage/server.mdx
Normal file
@@ -0,0 +1,55 @@
|
||||
import { Callout } from "nextra/components";
|
||||
|
||||
# Server
|
||||
|
||||
The server provides the `cup serve` command.
|
||||
|
||||
## Basic usage
|
||||
|
||||
```ansi
|
||||
$ cup serve
|
||||
[36;1m INFO [0mStarting server, please wait...
|
||||
[36;1m INFO [0m✨ Checked 8 images in 8862ms
|
||||
[36;1m INFO [0mReady to start!
|
||||
[94;1m HTTP [0m[32mGET[0m / [32m200[0m in 0ms
|
||||
[94;1m HTTP [0m[32mGET[0m /assets/index.js [32m200[0m in 3ms
|
||||
[94;1m HTTP [0m[32mGET[0m /assets/index.css [32m200[0m in 0ms
|
||||
[94;1m HTTP [0m[32mGET[0m /api/v3/json [32m200[0m in 0ms
|
||||
```
|
||||
|
||||
This will launch the server on port `8000`. To access it, visit `http://<YOUR_IP>:8000` (replace `<YOUR_IP>` with the IP address of the machine running Cup.)
|
||||
|
||||
<Callout>
|
||||
The URL `http://<YOUR_IP>:8000/api/v3/json` is also available for usage with integrations.
|
||||
</Callout>
|
||||
|
||||
## Use a different port
|
||||
|
||||
Pass the `-p` argument with the port you want to use
|
||||
|
||||
```ansi
|
||||
$ cup serve -p 9000
|
||||
[36;1m INFO [0mStarting server, please wait...
|
||||
[36;1m INFO [0m✨ Checked 8 images in 8862ms
|
||||
[36;1m INFO [0mReady to start!
|
||||
[94;1m HTTP [0m[32mGET[0m / [32m200[0m in 0ms
|
||||
[94;1m HTTP [0m[32mGET[0m /assets/index.js [32m200[0m in 3ms
|
||||
[94;1m HTTP [0m[32mGET[0m /assets/index.css [32m200[0m in 0ms
|
||||
[94;1m HTTP [0m[32mGET[0m /api/v3/json [32m200[0m in 0ms
|
||||
```
|
||||
|
||||
## Usage with Docker
|
||||
|
||||
If you're using the Docker image, just replace all occurences of `cup` in the examples with `docker run -tv /var/run/docker.sock:/var/run/docker.sock -p <PORT>:<PORT> ghcr.io/sergi0g/cup`, where `<PORT>` is the port Cup will be using.
|
||||
|
||||
For example, this:
|
||||
|
||||
```bash
|
||||
$ cup serve -p 9000
|
||||
```
|
||||
|
||||
becomes:
|
||||
|
||||
```bash
|
||||
$ docker run -tv /var/run/docker.sock:/var/run/docker.sock -p 9000:9000 ghcr.io/sergi0g/cup serve -p 9000
|
||||
```
|
||||
13
docs/src/mdx-components.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { useMDXComponents as getThemeComponents } from "nextra-theme-docs";
|
||||
import { MDXComponents } from "nextra/mdx-components";
|
||||
|
||||
// Get the default MDX components
|
||||
const themeComponents = getThemeComponents();
|
||||
|
||||
// Merge components
|
||||
export function useMDXComponents(components: MDXComponents) {
|
||||
return {
|
||||
...themeComponents,
|
||||
...components,
|
||||
};
|
||||
}
|
||||