From 6e2951734e171f36e79531ac7592ad44f02e2c9e Mon Sep 17 00:00:00 2001
From: an14051
Date: Tue, 12 May 2026 16:11:53 +0200
Subject: [PATCH] feat: update links to Gitea and enhance TerminalTyper for
docker-compose support
---
frontend/app/components/TerminalTyper.tsx | 150 ++++++++++++++++------
frontend/app/layout.tsx | 18 +--
frontend/app/page.tsx | 35 ++---
frontend/lib/links.ts | 20 +--
4 files changed, 142 insertions(+), 81 deletions(-)
diff --git a/frontend/app/components/TerminalTyper.tsx b/frontend/app/components/TerminalTyper.tsx
index 1c32e95..7919775 100644
--- a/frontend/app/components/TerminalTyper.tsx
+++ b/frontend/app/components/TerminalTyper.tsx
@@ -6,24 +6,59 @@ import { LINKS } from "@/lib/links";
interface Line {
type: "comment" | "cmd" | "cmd-cont" | "output" | "success" | "error";
text: string;
+ copyable?: boolean;
}
-function buildLines(): Line[] {
+function buildDockerRunLines(): Line[] {
return [
- { type: "comment", text: "# Pull the latest Backerup image" },
- { type: "cmd", text: `docker pull ${LINKS.dockerImage}` },
- { type: "output", text: `latest: Pulling from ${LINKS.dockerImage.split(":")[0]}` },
- { type: "output", text: "Digest: sha256:a3f8b1c2d9e4f7g6h5..." },
- { type: "success", text: "✓ Status: Image is up to date" },
- { type: "comment", text: "# Start Backerup with Docker socket access" },
- { type: "cmd", text: "docker run -d --name backerup \\" },
- { type: "cmd-cont", text: ` -p ${LINKS.uiPort}:${LINKS.uiPort} \\` },
- { type: "cmd-cont", text: " -v /var/run/docker.sock:/var/run/docker.sock \\" },
- { type: "cmd-cont", text: ` ${LINKS.dockerImage}` },
- { type: "success", text: "✓ Container started · a7f82c3d1b09" },
+ { type: "comment", text: "# Quick start: Run Backerup directly" },
+ { type: "cmd", text: "docker run -d --name backerup \\", copyable: true },
+ { type: "cmd-cont", text: ` -p ${LINKS.uiPort}:80 \\`, copyable: true },
+ { type: "cmd-cont", text: " -v /var/run/docker.sock:/var/run/docker.sock \\", copyable: true },
+ { type: "cmd-cont", text: " -v ${BACKUP_DIR:-/backups}:/backups \\", copyable: true },
+ { type: "cmd-cont", text: " -v backerup-config:/app/config \\", copyable: true },
+ { type: "cmd-cont", text: " -e BACKUP_DIR=/backups \\", copyable: true },
+ { type: "cmd-cont", text: " -e BACKUP_CONFIG_DIR=/app/config \\", copyable: true },
+ { type: "cmd-cont", text: ` -e HOST_BACKUP_DIR=/backups \\`, copyable: true },
+ { type: "cmd-cont", text: ` ${LINKS.dockerImage}`, copyable: true },
+ { type: "output", text: "a7f82c3d1b09" },
+ { type: "success", text: "✓ Container started" },
+ { type: "success", text: "✓ Ready at http://localhost:8080" },
];
}
+function buildDockerComposeLines(): Line[] {
+ return [
+ { type: "comment", text: "# Using docker-compose for easier management" },
+ { type: "cmd", text: "cat > docker-compose.yml << 'EOF'", copyable: false },
+ { type: "output", text: "services:" },
+ { type: "output", text: " backerup:" },
+ { type: "output", text: ` image: ${LINKS.dockerImage}` },
+ { type: "output", text: " ports:" },
+ { type: "output", text: ` - \"${LINKS.uiPort}:80\"` },
+ { type: "output", text: " volumes:" },
+ { type: "output", text: " - /var/run/docker.sock:/var/run/docker.sock" },
+ { type: "output", text: " - ${BACKUP_DIR:-/backups}:/backups" },
+ { type: "output", text: " - backerup-config:/app/config" },
+ { type: "output", text: " environment:" },
+ { type: "output", text: " - BACKUP_DIR=/backups" },
+ { type: "output", text: " - BACKUP_CONFIG_DIR=/app/config" },
+ { type: "output", text: " - HOST_BACKUP_DIR=${BACKUP_DIR:-/backups}" },
+ { type: "output", text: " restart: unless-stopped" },
+ { type: "output", text: "volumes:" },
+ { type: "output", text: " backerup-config:" },
+ { type: "output", text: "EOF" },
+ { type: "success", text: "✓ docker-compose.yml created" },
+ { type: "cmd", text: "docker compose up -d", copyable: false },
+ { type: "output", text: "[+] Building 2.3s (12/12) FINISHED" },
+ { type: "success", text: "✓ Ready at http://localhost:8080" },
+ ];
+}
+
+function buildLines(mode: "docker-run" | "docker-compose" = "docker-run"): Line[] {
+ return mode === "docker-run" ? buildDockerRunLines() : buildDockerComposeLines();
+}
+
function lineSpeed(line: Line) {
if (line.type === "output" || line.type === "success" || line.type === "error") return 12;
if (line.type === "comment") return 22;
@@ -47,16 +82,44 @@ function lineColor(line: Line) {
}
}
-function linePrompt(line: Line) {
+function linePrompt(line: Line): string {
if (line.type === "cmd") return "$ ";
if (line.type === "cmd-cont") return " ";
return "";
}
-export default function TerminalTyper() {
- const LINES = buildLines();
+export default function TerminalTyper({ mode = "docker-run" }: { mode?: "docker-run" | "docker-compose" } = {}) {
+ const LINES = buildLines(mode);
const [doneLines, setDoneLines] = useState([]);
const [current, setCurrent] = useState<{ idx: number; chars: number } | null>({ idx: 0, chars: 0 });
+ const [copied, setCopied] = useState(false);
+
+ const copyToClipboard = () => {
+ let textToCopy = "";
+
+ if (mode === "docker-compose") {
+ // For docker-compose, copy the YAML content only
+ const startIdx = LINES.findIndex(line => line.type === "output" && line.text === "services:");
+ const endIdx = LINES.findIndex((line, i) => i > startIdx && line.type === "output" && line.text === "EOF");
+
+ if (startIdx !== -1 && endIdx !== -1) {
+ // Copy the YAML content
+ textToCopy = LINES.slice(startIdx, endIdx)
+ .map(line => line.text)
+ .join("\n");
+ }
+ } else {
+ // For docker-run, copy all cmd and cmd-cont lines
+ textToCopy = LINES.filter(line => line.type === "cmd" || line.type === "cmd-cont")
+ .map(line => line.text.trim())
+ .join("\n");
+ }
+
+ navigator.clipboard.writeText(textToCopy).then(() => {
+ setCopied(true);
+ setTimeout(() => setCopied(false), 2000);
+ });
+ };
useEffect(() => {
if (!current) return;
@@ -86,30 +149,41 @@ export default function TerminalTyper() {
}, [current]);
return (
-
- {doneLines.map((i) => {
- const line = LINES[i];
- const prompt = linePrompt(line);
- return (
-
- {prompt && {prompt} }
- {line.text}
-
- );
- })}
+
+
+
+
+
+ {copied ? "Copied!" : "Copy command"}
+
+
+ {doneLines.map((i) => {
+ const line = LINES[i];
+ const prompt = linePrompt(line);
+ return (
+
+ {prompt && {prompt} }
+ {line.text}
+
+ );
+ })}
- {current && current.idx < LINES.length && (() => {
- const line = LINES[current.idx];
- const prompt = linePrompt(line);
- const partial = line.text.slice(0, current.chars);
- return (
-
- {prompt && {prompt} }
- {partial}
-
-
- );
- })()}
+ {current && current.idx < LINES.length && (() => {
+ const line = LINES[current.idx];
+ const prompt = linePrompt(line);
+ const partial = line.text.slice(0, current.chars);
+ return (
+
+ {prompt && {prompt} }
+ {partial}
+
+
+ );
+ })()}
+
);
}
diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx
index 708aef7..0ff6519 100644
--- a/frontend/app/layout.tsx
+++ b/frontend/app/layout.tsx
@@ -96,13 +96,13 @@ export default async function RootLayout({
Share
- GitHub
+ Gitea
{session?.role === "admin" && (
@@ -180,7 +180,7 @@ export default async function RootLayout({
Browse configs
Share a backup
Documentation
- Changelog
+ Changelog
@@ -188,10 +188,10 @@ export default async function RootLayout({
diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx
index 3114486..445d0f4 100644
--- a/frontend/app/page.tsx
+++ b/frontend/app/page.tsx
@@ -263,13 +263,13 @@ export default function LandingPage() {
- GitHub
+ Gitea
@@ -512,10 +512,10 @@ export default function LandingPage() {
Quick start
- One command to start
+ Setup with docker-compose
- Backerup runs as a Docker container. Give it access to your Docker socket and you're done.
+ The easiest way to get Backerup running is with docker-compose for declarative, reproducible deployments.
@@ -523,24 +523,11 @@ export default function LandingPage() {
- terminal
+ docker-compose setup
+
+
+
-
- # Pull & run — replace /path/to/backups with your backup destination {"\n"}
- $
- {"docker run -d \\"} {"\n"}
- {" "}
- {"--name backerup \\"} {"\n"}
- {" "}
- {`-p ${LINKS.uiPort}:${LINKS.uiPort} \\`} {"\n"}
- {" "}
- {"-v /var/run/docker.sock:/var/run/docker.sock \\"} {"\n"}
- {" "}
- {"-v /path/to/backups:/data \\"} {"\n"}
- {" "}
- {LINKS.dockerImage} {"\n"}
- {`✓ Open http://localhost:${LINKS.uiPort} to get started`}
-
@@ -571,13 +558,13 @@ export default function LandingPage() {