This commit is contained in:
Anders Böttcher
2026-05-13 10:56:45 +02:00
9 changed files with 49 additions and 38 deletions
+19 -2
View File
@@ -40,9 +40,26 @@ yarn-error.log*
# typescript # typescript
*.tsbuildinfo *.tsbuildinfo
next-env.d.ts next-env.d.ts
# build artifacts
/dist/
/build/
/.next/
/frontend/.turbo/
# bun
.bun/
bunfig.toml.local
# cache & logs
.turbo/
*.log
lerna-debug.log*
# user data & uploads
/frontend/data/uploads/ /frontend/data/uploads/
/frontend/data/*.db /frontend/data/*.db
/frontend/data/*.db-wal /frontend/data/*.db-wal
/frontend/data/*.db-shm /frontend/data/*.db-shm
/frontend/data/meta.json.migrated /frontend/data/*.migrated
/frontend/data/users.json.migrated /data/uploads/
+23 -4
View File
@@ -24,20 +24,39 @@ WORKDIR /app
ENV NODE_ENV=production ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1 ENV NEXT_TELEMETRY_DISABLED=1
# Suppress debconf warnings in Docker
ENV DEBIAN_FRONTEND=noninteractive
# Dedicated non-root user # Dedicated non-root user
RUN addgroup --system --gid 1001 nodejs && \ RUN apt-get update && \
apt-get install -y --no-install-recommends adduser && \
rm -rf /var/lib/apt/lists/* && \
addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs adduser --system --uid 1001 nextjs
# Next.js standalone output # Create writable data directory with proper permissions
RUN mkdir -p /app/data/uploads && \
chown -R nextjs:nodejs /app/data && \
chmod 750 /app/data && \
chmod 700 /app/data/uploads
# Copy only production artifacts from builder (no source code, no node_modules)
COPY --from=builder /app/public ./public COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
# Writable data directory for file uploads # Secure filesystem permissions
RUN mkdir -p /app/data/uploads && chown -R nextjs:nodejs /app/data RUN chmod 755 /app && \
chmod 755 /app/.next && \
chmod 755 /app/public
# Switch to non-root user
USER nextjs USER nextjs
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD bun --eval "import('http').then(h => h.request('http://localhost:3000/', res => process.exit(res.statusCode === 200 ? 0 : 1)).end())" || exit 1
EXPOSE 3000 EXPOSE 3000
ENV PORT=3000 ENV PORT=3000
+1 -1
View File
@@ -5,7 +5,7 @@
set -euo pipefail set -euo pipefail
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
TAG="${1:-backerup-website:latest}" TAG="${1:-gitea.doomlabs.de/kptltd00m/backerup-website:latest}"
echo "==> Building image: $TAG" echo "==> Building image: $TAG"
docker build \ docker build \
+1 -1
View File
@@ -5,7 +5,7 @@
set -euo pipefail set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
TAG="${1:-backerup-website:latest}" TAG="${1:-gitea.doomlabs.de/kptltd00m/backerup-website:latest}"
# 1. Build # 1. Build
"$SCRIPT_DIR/build.sh" "$TAG" "$SCRIPT_DIR/build.sh" "$TAG"
+1 -1
View File
@@ -1,6 +1,6 @@
services: services:
backerup-website: backerup-website:
image: backerup-website:latest image: gitea.doomlabs.de/kptltd00m/backerup-website:latest
container_name: backerup-website container_name: backerup-website
restart: unless-stopped restart: unless-stopped
ports: ports:
-14
View File
@@ -1,14 +0,0 @@
[
{
"token": "-jB8pMdeKu",
"originalName": "liquidity-db.config.json",
"displayName": "DB",
"size": 5606,
"type": "config",
"uploadedAt": "2026-05-11T21:18:55.259Z",
"description": "Skibidi Ligma",
"group": "production",
"containerName": "liquidity-db",
"image": "postgres:16-alpine"
}
]
-10
View File
@@ -1,10 +0,0 @@
[
{
"id": "00c94c52-f312-4152-a6ee-e3ce0b23b5f8",
"username": "admin",
"passwordHash": "827c32b2234fc18911ec8579ad6863df63b8cc3835b1f3a3f04016dfcd46f22e609cc3c99d5e09959ff8f2787f4169206ad5a9ca83beec2e70c14f8cca110cc8",
"salt": "c2030b38b34b2810f715453350100729",
"role": "admin",
"createdAt": "2026-05-12T12:46:52.082Z"
}
]
+1 -2
View File
@@ -14,8 +14,7 @@ const securityHeaders = [
const nextConfig: NextConfig = { const nextConfig: NextConfig = {
output: "standalone", output: "standalone",
serverExternalPackages: ["@libsql/client"], serverExternalPackages: ["@libsql/client"], productionBrowserSourceMaps: false, experimental: {
experimental: {
serverActions: { serverActions: {
bodySizeLimit: "500mb", bodySizeLimit: "500mb",
}, },
+1 -1
View File
@@ -75,7 +75,7 @@ export async function proxy(request: NextRequest) {
if (token) { if (token) {
try { try {
const { payload: p } = await jwtVerify(token, getSecretKey(), { algorithms: ['HS256'] }) const { payload: p } = await jwtVerify(token, getSecretKey(), { algorithms: ['HS256'] })
payload = p payload = p as { userId?: string; username?: string; role?: string }
} catch { } catch {
// expired or tampered — treat as unauthenticated // expired or tampered — treat as unauthenticated
} }