diff --git a/.gitea/workflows/deploy-old.yaml.off b/.gitea/workflows/deploy-old.yaml.off
deleted file mode 100644
index 8878c4b..0000000
--- a/.gitea/workflows/deploy-old.yaml.off
+++ /dev/null
@@ -1,102 +0,0 @@
-name: Build and Deploy Container
-
-env:
- TARGET_HOST: host.containers.internal
- #TARGET_HOST: www.valtrix.systems
- TARGET_USER: traefik
- APP_DIR: /home/traefik/valtrix-website
- CONTAINER_NAME: valtrix-website
- QUADLET_FILE: ./deploy/valtrix-website.container
- SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
- SSH_KNOWN_HOSTS: ${{ secrets.SSH_KNOWN_HOSTS }}
-
-on:
- push:
- branches:
- - main
- - develop
-
-jobs:
- build_and_deploy:
- runs-on: ubuntu-latest
- steps:
- - name: Pre-clean Git global config (avoid https→ssh rewrite)
- shell: bash
- run: |
- set -euo pipefail
- git --version || true
- echo "Global git config before:" || true
- git config --global --list || true
- # Remove any url.*.insteadof rules that force SSH for gitea.smb-corp.de
- for key in $(git config --global --get-regexp '^url\\..*\\.insteadof$' 2>/dev/null | awk '{print $1}'); do
- if echo "$key" | grep -qi 'gitea\\.smb-corp\\.de'; then
- echo "Removing global mapping: $key"
- git config --global --unset-all "$key" || true
- fi
- done
- # Ensure no global sshCommand forces SSH
- git config --global --unset-all core.sshCommand || true
- echo "Global git config after:" || true
- git config --global --list || true
- - name: Setup SSH for git/scp
- shell: bash
- run: |
- install -m 700 -d ~/.ssh
- printf "%s\n" "$SSH_PRIVATE_KEY" > ~/.ssh/id_ed25519
- chmod 600 ~/.ssh/id_ed25519
- printf "%s\n" "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts || true
- chmod 644 ~/.ssh/known_hosts
- # Ensure host keys are present to avoid interactive prompts
- (ssh-keygen -F "$TARGET_HOST" >/dev/null || ssh-keyscan -H "$TARGET_HOST" >> ~/.ssh/known_hosts) || true
- (ssh-keygen -F gitea.smb-corp.de >/dev/null || ssh-keyscan -H gitea.smb-corp.de >> ~/.ssh/known_hosts) || true
-
- - name: Checkout Repository
- uses: actions/checkout@v4
- - name: Copy entire repository to target host (scp -> atomic replace)
- shell: bash
- run: |
- set -euo pipefail
- # Work in a temp directory to avoid partial updates and handle ownership issues more clearly
- TMP_DIR="$APP_DIR.tmp.$(date +%s)"
- echo "Creating remote temp dir $TMP_DIR"
- ssh -o BatchMode=yes -i ~/.ssh/id_ed25519 $TARGET_USER@$TARGET_HOST "mkdir -p '$TMP_DIR'"
-
- echo "Copying repository files to $TARGET_HOST:$TMP_DIR via scp (includes hidden files)"
- # Enable dotglob so hidden files are included in the glob
- shopt -s dotglob || true
- # Copy all files and directories in the repo root to the remote temp dir
- scp -r -o BatchMode=yes -i ~/.ssh/id_ed25519 ./* $TARGET_USER@$TARGET_HOST:$TMP_DIR/
-
- echo "Attempting atomic replacement of $APP_DIR with $TMP_DIR"
- # Try to remove existing dir and move temp into place. If removal fails due to permissions, leave temp and error.
- ssh -o BatchMode=yes -i ~/.ssh/id_ed25519 $TARGET_USER@$TARGET_HOST "set -euo pipefail; if [ -d '$APP_DIR' ]; then rm -rf '$APP_DIR' || { echo 'ERROR: cannot remove existing $APP_DIR (permissions)'; exit 2; } fi; mv '$TMP_DIR' '$APP_DIR'"
- echo "Copy and replace finished"
-
- - name: Build container on target host
- run: |
- # Expand $APP_DIR locally so the remote shell receives the concrete path
- ssh $TARGET_USER@$TARGET_HOST "set -euo pipefail; echo -e \"$APP_DIR \n\n\"; cd '$APP_DIR' && echo 'PWD:' \$(pwd) && ls -la . && podman build -t $CONTAINER_NAME:latest ."
-
- - name: Backup Quadlet file
- run: |
- ssh $TARGET_USER@$TARGET_HOST "
- test -f ~/.config/containers/systemd/$CONTAINER_NAME.container && \
- cp ~/.config/containers/systemd/$CONTAINER_NAME.container ~/.config/containers/systemd/$CONTAINER_NAME.container.bak || true
- "
-
- - name: Replace Quadlet file
- run: |
- scp ./$QUADLET_FILE $TARGET_USER@$TARGET_HOST:~/.config/containers/systemd/
- ssh $TARGET_USER@$TARGET_HOST '
- systemctl --user daemon-reload && echo "Reloaded user systemd daemon" && \
- systemctl --user restart valtrix-website.service
- '
-
- - name: Verify deployment
- run: |
- ssh $TARGET_USER@$TARGET_HOST '
- podman ps --filter "name=valtrix" --format "table {{.Names}}\t{{.Image}}\t{{.Status}}" || echo "No running container named $CONTAINER_NAME"
- echo "Container logs of $CONTAINER_NAME:"
- podman logs valtrix-website
- podman logs $CONTAINER_NAME --tail 20
- '
\ No newline at end of file
diff --git a/Containerfile b/Containerfile
index 7770436..239b61e 100644
--- a/Containerfile
+++ b/Containerfile
@@ -1,26 +1,36 @@
-# Multi-stage build for Astro static site
-FROM node:22-alpine AS builder
+# syntax=docker/dockerfile:1.7
+
+###########
+# BUILD STAGE
+###########
+FROM cgr.dev/chainguard/node:latest-dev AS build
WORKDIR /app
-# Install deps
+# Copy dependency manifests
COPY package*.json ./
-RUN npm ci || npm install
-# Copy sources and build static output
+# Install all deps (inkl. dev)
+RUN --mount=type=cache,target=/root/.npm npm ci
+
+# Copy app source and build
COPY . .
RUN npm run build
-# ---- Runtime stage ----
-FROM node:22-alpine AS runtime
-WORKDIR /app
+###########
+# RUNTIME STAGE
+###########
+FROM cgr.dev/chainguard/node:latest
ENV NODE_ENV=production
-ENV PORT=3000
-ENV WEB_ROOT=/app/dist
-ENV TZ=Europe/Berlin
-ENV ASTRO_TELEMETRY_DISABLED=1
-COPY --from=builder /app/dist /app/dist
-COPY server.mjs /app/server.mjs
-# Drop root: use the pre-created node user
+WORKDIR /app
+
+# Copy only what’s needed to run
+COPY --from=build /app/package*.json ./
+COPY --from=build /app/node_modules ./node_modules
+COPY --from=build /app/dist ./dist
+COPY --from=build /app/server.mjs ./server.mjs
+
+# Chainguard runs as nonroot by default (user `nonroot`)
USER node
#EXPOSE 3000
-CMD ["node", "/app/server.mjs"]
+
+CMD ["node", "./server.mjs"]
\ No newline at end of file
diff --git a/Containerfile.old b/Containerfile.old
new file mode 100644
index 0000000..7770436
--- /dev/null
+++ b/Containerfile.old
@@ -0,0 +1,26 @@
+# Multi-stage build for Astro static site
+FROM node:22-alpine AS builder
+WORKDIR /app
+
+# Install deps
+COPY package*.json ./
+RUN npm ci || npm install
+
+# Copy sources and build static output
+COPY . .
+RUN npm run build
+
+# ---- Runtime stage ----
+FROM node:22-alpine AS runtime
+WORKDIR /app
+ENV NODE_ENV=production
+ENV PORT=3000
+ENV WEB_ROOT=/app/dist
+ENV TZ=Europe/Berlin
+ENV ASTRO_TELEMETRY_DISABLED=1
+COPY --from=builder /app/dist /app/dist
+COPY server.mjs /app/server.mjs
+# Drop root: use the pre-created node user
+USER node
+#EXPOSE 3000
+CMD ["node", "/app/server.mjs"]
diff --git a/src/layouts/Base.astro b/src/layouts/Base.astro
index bad24ba..ea393e3 100644
--- a/src/layouts/Base.astro
+++ b/src/layouts/Base.astro
@@ -4,13 +4,15 @@ const { title = "Valtrix – Struktur schafft Wert", description = "Cloud, Secur
// Language & routing helpers
const pathname = Astro.url.pathname;
const isEn = pathname.startsWith('/en');
+const isDe = pathname.startsWith('/de');
const lang = isEn ? 'en' : 'de';
-const prefix = isEn ? '/en' : '';
-const stripEn = (p) => p.replace(/^\/en(?=\/|$)/, '');
-const altHref = isEn ? (stripEn(pathname) || '/') : ('/en' + (pathname === '/' ? '' : pathname));
+// Default to /de for links so navigation always points to language-prefixed routes
+const prefix = isEn ? '/en' : '/de';
+const stripLang = (p) => p.replace(/^\/(?:en|de)(?=\/|$)/, '');
+const altHref = isEn ? ('/de' + (stripLang(pathname) || '/')) : ('/en' + (stripLang(pathname) || '/'));
// Canonical/alternate URLs (use provided path when present for og/link tags)
const canonicalPath = path || pathname;
-const deHref = stripEn(canonicalPath) || '/';
+const deHref = canonicalPath.startsWith('/de') ? canonicalPath : ('/de' + (canonicalPath === '/' ? '' : canonicalPath));
const enHref = canonicalPath.startsWith('/en') ? canonicalPath : ('/en' + (canonicalPath === '/' ? '' : canonicalPath));
// Nav labels per language
const labels = isEn ? {
diff --git a/src/pages/cases.astro b/src/pages/de/cases.astro
similarity index 75%
rename from src/pages/cases.astro
rename to src/pages/de/cases.astro
index e6ee3ea..580a9d9 100644
--- a/src/pages/cases.astro
+++ b/src/pages/de/cases.astro
@@ -1,15 +1,15 @@
---
-import Base from "../layouts/Base.astro";
+import Base from "../../layouts/Base.astro";
const items = [
{ slug: "cloud-migration", title: "Sichere Cloud-Migration (AWS/Azure)", summary: "Landing Zone, Zero-Trust, Pipeline & Observability in 6 Wochen." },
{ slug: "k8s-hardening", title: "Kubernetes Hardening & GitOps", summary: "CIS Benchmarks, OPA Policies-as-Code, ArgoCD Rollouts." }
];
---
-
{i.summary}
Case ansehen diff --git a/src/pages/de/cases/cloud-migration.astro b/src/pages/de/cases/cloud-migration.astro new file mode 100644 index 0000000..a6daefb --- /dev/null +++ b/src/pages/de/cases/cloud-migration.astro @@ -0,0 +1,36 @@ +--- +import Base from "../../../layouts/Base.astro"; +--- +Enterprise-Migration von On-Prem nach Cloud mit Fokus auf Sicherheit & Compliance.
+ +Sichere AWS/Azure Landing Zone, segmentiertes Netzwerk, zentralisiertes IAM.
+Guardrails, IaC (Terraform/OpenTofu), GitOps, Observability, Cost Controls.
+Schnelleres Deployment, Auditfähigkeit, reduzierte Risiken & Kosten.
+Produktionsreifes K8s‑Setup mit Härtung nach CIS, durchgängigen Policies‑as‑Code und GitOps‑Deployments.
+ +Sicheres Cluster‑Baseline: identitätszentrierte Zugriffe, Netzwerk‑Segmentierung, saubere Supply Chain.
+CIS Benchmarks, OPA/Gatekeeper oder Kyverno Policies, Pod Security Standards, signierte Artefakte & GitOps (Argo CD).
+Reproduzierbare Deployments, Policy‑konforme Releases, Auditfähigkeit und reduzierte Angriffsfläche.
+Mehrstufige Environments (dev/stage/prod) mit Branch/Tag‑Strategie, Kustomize‑Overlays und PR‑basierten Changes.
+RBAC Least‑Privilege, NetworkPolicies default‑deny, Pod Security, Image‑Scanning, Secrets‑Management.
+Diese Hinweise informieren darüber, wie wir personenbezogene Daten beim Besuch dieser Website verarbeiten. Die Website ist als statische Seite umgesetzt; es werden keine Tracking‑ oder Marketing‑Cookies eingesetzt und keine externen Ressourcen (z. B. Google Fonts, Analytics, Formdienste) geladen.
Verantwortlicher im Sinne der DSGVO ist: Valtrix. Anschrift siehe Impressum. E‑Mail: kontakt@valtrix.systems
+Verantwortlicher im Sinne der DSGVO ist: Valtrix. Anschrift siehe Impressum. E‑Mail: kontakt@valtrix.systems
VALTRIX GmbH i.G.
Am Wassergraben 4, 10179 Berlin
diff --git a/src/pages/de/index.astro b/src/pages/de/index.astro new file mode 100644 index 0000000..2b2a831 --- /dev/null +++ b/src/pages/de/index.astro @@ -0,0 +1,82 @@ +--- +import Base from "../../layouts/Base.astro"; +const benefits = [ + { title: "Zero-Trust & Härtung", text: "Security-by-Design, CIS/BSI-Richtlinien, automatisierte Policies." }, + { title: "Cloud Foundations", text: "Landing Zones, Identity, Observability – sauber & skalierbar." }, + { title: "Automatisierung", text: "IaC/CI/CD, GitOps, wiederholbar & auditfähig." } +]; +const approach = [ + { title: 'Assess', text: 'Risiko- und Reifegradanalyse: schneller Quick-Scan, klare Prioritäten.' }, + { title: 'Design', text: 'Zielarchitektur & Guardrails: sichere, skalierbare Blueprint-Entwürfe.' }, + { title: 'Build', text: 'IaC, Pipelines & Policies-as-Code: reproduzierbar und überprüfbar.' }, + { title: 'Run', text: 'Monitoring, Audits & Kostentransparenz: nachhaltig betreibbar.' } +]; +--- ++ Wir verbinden Struktur und Wert: sichere Cloud-Architekturen, Automatisierung und Compliance – pragmatisch und messbar. +
+{b.text}
+Zero-Trust, IAM, Hardening, Audits, BSI/ISO‑orientierte Prozesse.
+RAG/Agenten, Automatisierung von Betriebsprozessen, sichere Integration.
+{a.text}
+