1.0.38
This commit is contained in:
6 files changed
+318
-5
No files matched your search
@@ -0,0 +1,61 @@
|
|||||||
|
# Dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Build output
|
||||||
|
build/
|
||||||
|
.svelte-kit/
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# Git
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
|
||||||
|
# CI/CD
|
||||||
|
.drone.yml
|
||||||
|
deployment/
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
tests/
|
||||||
|
|
||||||
|
# Hawser agent (separate project)
|
||||||
|
hawser/
|
||||||
|
|
||||||
|
# Updater (separate project)
|
||||||
|
updater/
|
||||||
|
|
||||||
|
# Test image
|
||||||
|
test-image/
|
||||||
|
|
||||||
|
# Landing page
|
||||||
|
webpage/
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
.DS_Store
|
||||||
|
*.log
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
|
||||||
|
# Sensitive files
|
||||||
|
scripts/keys/
|
||||||
|
data/
|
||||||
|
*.pem
|
||||||
|
*.key
|
||||||
|
*.crt
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
*.md
|
||||||
|
!README.md
|
||||||
|
|
||||||
|
# Development files
|
||||||
|
docker-compose*.yml
|
||||||
|
!docker-compose.yml
|
||||||
|
bun.lock
|
||||||
|
tsconfig.json
|
||||||
|
.prettierrc
|
||||||
|
.eslintrc*
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
# syntax=docker/dockerfile:1.4
|
||||||
|
# Dockhand Backup Helper - Minimal restic image (Wolfi-based, zero CVEs)
|
||||||
|
#
|
||||||
|
# Rebuild trigger: the dockhand-backup-image pipeline is change-gated on this
|
||||||
|
# file. Bumping this comment forces a build so docker.io/fnsys/dockhand-backup:latest
|
||||||
|
# is (re)published to Docker Hub — the tag DEFAULT_HELPER_IMAGE (restic.ts) pulls.
|
||||||
|
# (re-triggered after fixing the ARM-builder Docker Hub login secret)
|
||||||
|
# (buildx steps consolidated into one block scalar)
|
||||||
|
# (remote ARM login: pipe password over stdin, no quoted interpolation)
|
||||||
|
# (use write-capable dockerhub token so the Docker Hub push authorizes)
|
||||||
|
# (revert rclone — the rclone: backend is unfinished/removed; see vault rclone.md)
|
||||||
|
FROM alpine:3.21 AS os-builder
|
||||||
|
|
||||||
|
ARG TARGETARCH
|
||||||
|
WORKDIR /work
|
||||||
|
|
||||||
|
ARG APKO_VERSION=0.30.34
|
||||||
|
RUN apk add --no-cache curl \
|
||||||
|
&& ARCH=$([ "$TARGETARCH" = "arm64" ] && echo "arm64" || echo "amd64") \
|
||||||
|
&& curl -sL "https://github.com/chainguard-dev/apko/releases/download/v${APKO_VERSION}/apko_${APKO_VERSION}_linux_${ARCH}.tar.gz" \
|
||||||
|
| tar -xz --strip-components=1 -C /usr/local/bin \
|
||||||
|
&& chmod +x /usr/local/bin/apko
|
||||||
|
|
||||||
|
RUN APKO_ARCH=$([ "$TARGETARCH" = "arm64" ] && echo "aarch64" || echo "x86_64") \
|
||||||
|
&& printf '%s\n' \
|
||||||
|
"contents:" \
|
||||||
|
" repositories:" \
|
||||||
|
" - https://packages.wolfi.dev/os" \
|
||||||
|
" keyring:" \
|
||||||
|
" - https://packages.wolfi.dev/os/wolfi-signing.rsa.pub" \
|
||||||
|
" packages:" \
|
||||||
|
" - wolfi-base" \
|
||||||
|
" - ca-certificates" \
|
||||||
|
" - busybox" \
|
||||||
|
" - restic" \
|
||||||
|
"entrypoint:" \
|
||||||
|
" command: /bin/sh" \
|
||||||
|
"archs:" \
|
||||||
|
" - ${APKO_ARCH}" \
|
||||||
|
> apko.yaml
|
||||||
|
|
||||||
|
RUN apko build apko.yaml dockhand-backup:latest output.tar \
|
||||||
|
&& mkdir -p rootfs \
|
||||||
|
&& tar -xf output.tar \
|
||||||
|
&& LAYER=$(tar -tf output.tar | grep '.tar.gz$' | head -1) \
|
||||||
|
&& tar -xzf "$LAYER" -C rootfs
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
COPY --from=os-builder /work/rootfs /
|
||||||
|
COPY scripts/backup-entrypoint.sh /entrypoint.sh
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# syntax=docker/dockerfile:1.4
|
||||||
|
# Dockhand Backup Helper — BASELINE build (Alpine/musl, amd64 only)
|
||||||
|
#
|
||||||
|
# The normal helper (Dockerfile.backup) is Wolfi-based; Wolfi compiles its restic
|
||||||
|
# and glibc for x86-64-v2 (SSE4.2/POPCNT). On older x86_64 CPUs without those
|
||||||
|
# instructions (TrueNAS, old Intel Atom/Celeron — the same hardware that needs the
|
||||||
|
# baseline Dockhand image) the Wolfi helper dies immediately:
|
||||||
|
# restic: "This program can only be run on AMD64 processors with v2 microarchitecture"
|
||||||
|
# busybox: "Fatal glibc error: CPU does not support x86-64-v2"
|
||||||
|
# so backups are completely broken for baseline users.
|
||||||
|
#
|
||||||
|
# Alpine's musl + its restic build run on x86-64-v1 (verified on a QEMU v1 CPU), so
|
||||||
|
# the baseline helper is a plain Alpine image with restic. amd64 only — baseline is a
|
||||||
|
# workaround for old x86_64 hardware, not an ARM concern.
|
||||||
|
#
|
||||||
|
# Rebuild trigger: the pipeline is change-gated on this file — bumping this comment
|
||||||
|
# forces a rebuild so the versioned/-baseline tags are (re)published.
|
||||||
|
# (revert rclone — the rclone: backend is unfinished/removed; see vault rclone.md)
|
||||||
|
FROM alpine:3.21
|
||||||
|
|
||||||
|
# restic + tar (busybox) + a real shell + CA certs cover everything the helper does:
|
||||||
|
# restic backup/restore/forget, the metadata shell script (set -e, tar), and TLS to
|
||||||
|
# the backup repository.
|
||||||
|
RUN apk add --no-cache restic ca-certificates tar
|
||||||
|
|
||||||
|
COPY scripts/backup-entrypoint.sh /entrypoint.sh
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
+14
-4
@@ -26,8 +26,8 @@ RUN gcc -shared -fPIC -O2 -o /tmp/libgetrandom-shim.so /tmp/getrandom-shim.c
|
|||||||
|
|
||||||
# Copy package files and install dependencies (--ignore-scripts blocks malicious postinstall hooks)
|
# Copy package files and install dependencies (--ignore-scripts blocks malicious postinstall hooks)
|
||||||
COPY package.json package-lock.json ./
|
COPY package.json package-lock.json ./
|
||||||
RUN npm ci --ignore-scripts \
|
RUN MAKEFLAGS="-j$(nproc)" npm ci --ignore-scripts \
|
||||||
&& npm rebuild better-sqlite3 argon2
|
&& MAKEFLAGS="-j$(nproc)" npm rebuild better-sqlite3 argon2
|
||||||
|
|
||||||
# Copy source code and build
|
# Copy source code and build
|
||||||
COPY . .
|
COPY . .
|
||||||
@@ -44,7 +44,7 @@ RUN cp -r node_modules/better-sqlite3/build /tmp/better-sqlite3-build \
|
|||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
# Stage 2: Go Collector Builder
|
# Stage 2: Go Collector Builder
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
FROM golang:1.25.8 AS go-builder
|
FROM golang:1.25.12 AS go-builder
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY collector/ ./collector/
|
COPY collector/ ./collector/
|
||||||
RUN cd collector && CGO_ENABLED=0 go build -o /app/bin/collection-worker .
|
RUN cd collector && CGO_ENABLED=0 go build -o /app/bin/collection-worker .
|
||||||
@@ -90,7 +90,8 @@ ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt \
|
|||||||
HOME=/home/dockhand \
|
HOME=/home/dockhand \
|
||||||
PUID=1001 \
|
PUID=1001 \
|
||||||
PGID=1001 \
|
PGID=1001 \
|
||||||
LD_PRELOAD=/usr/lib/libgetrandom-shim.so
|
LD_PRELOAD=/usr/lib/libgetrandom-shim.so \
|
||||||
|
DOCKHAND_VARIANT=baseline
|
||||||
|
|
||||||
# Copy application files with correct ownership
|
# Copy application files with correct ownership
|
||||||
COPY --from=app-builder --chown=dockhand:dockhand /app/node_modules ./node_modules
|
COPY --from=app-builder --chown=dockhand:dockhand /app/node_modules ./node_modules
|
||||||
@@ -123,6 +124,15 @@ RUN chmod +x ./scripts/*.sh ./scripts/**/*.sh 2>/dev/null || true
|
|||||||
RUN mkdir -p /home/dockhand/.dockhand/stacks /app/data \
|
RUN mkdir -p /home/dockhand/.dockhand/stacks /app/data \
|
||||||
&& chown dockhand:dockhand /app/data /home/dockhand /home/dockhand/.dockhand /home/dockhand/.dockhand/stacks
|
&& chown dockhand:dockhand /app/data /home/dockhand /home/dockhand/.dockhand /home/dockhand/.dockhand/stacks
|
||||||
|
|
||||||
|
# OCI image annotations (#1217) — lets tooling map this image back to its
|
||||||
|
# source repo (image registry name differs from GitHub repo name).
|
||||||
|
LABEL org.opencontainers.image.source="https://github.com/Finsys/dockhand" \
|
||||||
|
org.opencontainers.image.url="https://dockhand.pro" \
|
||||||
|
org.opencontainers.image.title="Dockhand" \
|
||||||
|
org.opencontainers.image.description="Docker management" \
|
||||||
|
org.opencontainers.image.vendor="Finsys" \
|
||||||
|
org.opencontainers.image.licenses="BUSL-1.1"
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||||
|
|||||||
@@ -0,0 +1,163 @@
|
|||||||
|
# syntax=docker/dockerfile:1.4
|
||||||
|
# =============================================================================
|
||||||
|
# Dockhand Docker Image - RISC-V 64-bit (Experimental)
|
||||||
|
# =============================================================================
|
||||||
|
# Experimental riscv64 build. Wolfi has no riscv64 packages, and official
|
||||||
|
# node:24-alpine/slim images don't include riscv64 either. Alpine edge repos
|
||||||
|
# have nodejs 24 for riscv64, so we use those directly.
|
||||||
|
#
|
||||||
|
# docker-compose is not packaged for riscv64 in Alpine, so we build it from
|
||||||
|
# source using Go (which has full riscv64 support).
|
||||||
|
#
|
||||||
|
# lightningcss (used by Vite) has no riscv64 prebuilt binary, so we split
|
||||||
|
# the build: Vite runs on the build platform (fast, has lightningcss), then
|
||||||
|
# native addons are rebuilt on riscv64 (QEMU, slower but necessary).
|
||||||
|
#
|
||||||
|
# Build:
|
||||||
|
# docker buildx build --platform linux/riscv64 -f Dockerfile.riscv64 \
|
||||||
|
# -t registry.bor6.pl/dockhand:riscv64-test --push .
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Stage 1: Docker Compose Builder (Go - cross-compile from build platform)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Alpine edge has docker-cli for riscv64 but NOT docker-compose.
|
||||||
|
# Build it from source since Go has excellent riscv64 cross-compilation.
|
||||||
|
FROM --platform=$BUILDPLATFORM golang:1.25.9-alpine AS compose-builder
|
||||||
|
ARG TARGETARCH
|
||||||
|
|
||||||
|
RUN apk add --no-cache git
|
||||||
|
|
||||||
|
RUN git clone --depth 1 --branch v2.36.1 https://github.com/docker/compose.git /src/compose
|
||||||
|
|
||||||
|
WORKDIR /src/compose
|
||||||
|
RUN CGO_ENABLED=0 GOARCH=$TARGETARCH go build -trimpath -ldflags="-s -w" -o /usr/bin/docker-compose ./cmd
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Stage 2: JS Builder (runs on build platform - has lightningcss binaries)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Vite/lightningcss have no riscv64 prebuilt binaries. Since Vite produces
|
||||||
|
# plain JS bundles with no arch dependency, we build on the host platform.
|
||||||
|
FROM --platform=$BUILDPLATFORM node:24-alpine AS js-builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN apk add --no-cache git curl python3 make g++ gcc musl-dev
|
||||||
|
|
||||||
|
COPY package.json package-lock.json ./
|
||||||
|
RUN MAKEFLAGS="-j$(nproc)" npm ci --ignore-scripts \
|
||||||
|
&& MAKEFLAGS="-j$(nproc)" npm rebuild
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Stage 3: Native Addon Builder (runs on riscv64 via QEMU)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# better-sqlite3 and argon2 have C/C++ native addons that must be compiled
|
||||||
|
# for the target architecture (riscv64).
|
||||||
|
FROM --platform=$TARGETPLATFORM alpine:edge AS addon-builder
|
||||||
|
|
||||||
|
RUN apk add --no-cache --repository=https://dl-cdn.alpinelinux.org/alpine/edge/main \
|
||||||
|
--repository=https://dl-cdn.alpinelinux.org/alpine/edge/community \
|
||||||
|
nodejs npm python3 make g++ gcc musl-dev
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package.json package-lock.json ./
|
||||||
|
RUN MAKEFLAGS="-j$(nproc)" npm ci --omit=dev --ignore-scripts \
|
||||||
|
&& MAKEFLAGS="-j$(nproc)" npm rebuild better-sqlite3 argon2 \
|
||||||
|
&& rm -rf node_modules/@types
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Stage 4: Go Collector Builder (cross-compile from build platform)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
FROM --platform=$BUILDPLATFORM golang:1.25.9 AS go-builder
|
||||||
|
ARG TARGETARCH
|
||||||
|
WORKDIR /app
|
||||||
|
COPY collector/ ./collector/
|
||||||
|
RUN cd collector && CGO_ENABLED=0 GOARCH=$TARGETARCH go build -o /app/bin/collection-worker .
|
||||||
|
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
# Stage 5: Final Image (Alpine edge runtime)
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
FROM alpine:edge
|
||||||
|
|
||||||
|
# Install runtime packages from main + community repos
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
--repository=https://dl-cdn.alpinelinux.org/alpine/edge/main \
|
||||||
|
--repository=https://dl-cdn.alpinelinux.org/alpine/edge/community \
|
||||||
|
nodejs \
|
||||||
|
ca-certificates \
|
||||||
|
tzdata \
|
||||||
|
docker-cli \
|
||||||
|
docker-cli-buildx \
|
||||||
|
sqlite \
|
||||||
|
postgresql17-client \
|
||||||
|
git \
|
||||||
|
openssh-client \
|
||||||
|
curl \
|
||||||
|
tini \
|
||||||
|
su-exec \
|
||||||
|
libstdc++
|
||||||
|
|
||||||
|
# Copy docker-compose built from source (not available as Alpine package for riscv64)
|
||||||
|
COPY --from=compose-builder /usr/bin/docker-compose /usr/bin/docker-compose
|
||||||
|
|
||||||
|
# Create docker compose plugin symlink
|
||||||
|
RUN mkdir -p /usr/libexec/docker/cli-plugins \
|
||||||
|
&& ln -sf /usr/bin/docker-compose /usr/libexec/docker/cli-plugins/docker-compose
|
||||||
|
|
||||||
|
# Create dockhand user and group
|
||||||
|
RUN addgroup -g 1001 dockhand \
|
||||||
|
&& adduser -u 1001 -G dockhand -h /home/dockhand -D dockhand
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Set up environment variables
|
||||||
|
ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt \
|
||||||
|
NODE_ENV=production \
|
||||||
|
PORT=3000 \
|
||||||
|
HOST=0.0.0.0 \
|
||||||
|
DATA_DIR=/app/data \
|
||||||
|
HOME=/home/dockhand \
|
||||||
|
PUID=1001 \
|
||||||
|
PGID=1001
|
||||||
|
|
||||||
|
# Copy node_modules with riscv64 native addons
|
||||||
|
COPY --from=addon-builder --chown=dockhand:dockhand /app/node_modules ./node_modules
|
||||||
|
|
||||||
|
# Copy built JS app from cross-platform builder
|
||||||
|
COPY --from=js-builder --chown=dockhand:dockhand /app/package.json ./
|
||||||
|
COPY --from=js-builder --chown=dockhand:dockhand /app/build ./build
|
||||||
|
COPY --from=js-builder --chown=dockhand:dockhand /app/server.js ./
|
||||||
|
|
||||||
|
# Copy Go collector binary
|
||||||
|
COPY --from=go-builder --chown=dockhand:dockhand /app/bin/collection-worker ./bin/collection-worker
|
||||||
|
|
||||||
|
# Copy database migrations
|
||||||
|
COPY --chown=dockhand:dockhand drizzle/ ./drizzle/
|
||||||
|
COPY --chown=dockhand:dockhand drizzle-pg/ ./drizzle-pg/
|
||||||
|
|
||||||
|
# Copy legal documents
|
||||||
|
COPY --chown=dockhand:dockhand LICENSE.txt PRIVACY.txt ./
|
||||||
|
|
||||||
|
# Copy entrypoint script
|
||||||
|
COPY docker-entrypoint-node.sh /usr/local/bin/docker-entrypoint.sh
|
||||||
|
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
|
||||||
|
|
||||||
|
# Copy emergency scripts
|
||||||
|
COPY --chown=dockhand:dockhand scripts/emergency/ ./scripts/
|
||||||
|
RUN chmod +x ./scripts/*.sh ./scripts/**/*.sh 2>/dev/null || true
|
||||||
|
|
||||||
|
# Create data directories
|
||||||
|
RUN mkdir -p /home/dockhand/.dockhand/stacks /app/data \
|
||||||
|
&& chown dockhand:dockhand /app/data /home/dockhand /home/dockhand/.dockhand /home/dockhand/.dockhand/stacks
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||||
|
CMD curl -f http://localhost:${PORT:-3000}/ || exit 1
|
||||||
|
|
||||||
|
ENTRYPOINT ["/sbin/tini", "--", "/usr/local/bin/docker-entrypoint.sh"]
|
||||||
|
CMD []
|
||||||
@@ -2,7 +2,7 @@ import type { LayoutServerLoad } from './$types';
|
|||||||
import { redirect } from '@sveltejs/kit';
|
import { redirect } from '@sveltejs/kit';
|
||||||
import { isAuthEnabled, validateSession } from '$lib/server/auth';
|
import { isAuthEnabled, validateSession } from '$lib/server/auth';
|
||||||
import { hasAdminUser } from '$lib/server/db';
|
import { hasAdminUser } from '$lib/server/db';
|
||||||
import { BACKUPS_ENABLED } from '$lib/server/features';
|
import { BACKUPS_ENABLED } from '$lib/server/features';
|
||||||
|
|
||||||
// Routes that don't require authentication
|
// Routes that don't require authentication
|
||||||
const PUBLIC_PATHS = ['/login'];
|
const PUBLIC_PATHS = ['/login'];
|
||||||
|
|||||||
Reference in new issue
Block a user