<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Mariadb – Serverküche</title><link>https://serverkueche.de/tags/mariadb/</link><description>Mariadb – Neueste Beiträge von Serverküche</description><generator>Hugo</generator><language>de-DE</language><managingEditor>feedback@serverkueche.de (Serverküche)</managingEditor><webMaster>feedback@serverkueche.de (Serverküche)</webMaster><copyright>2026 Serverküche</copyright><lastBuildDate>Sun, 19 Jul 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://serverkueche.de/tags/mariadb/index.xml" rel="self" type="application/rss+xml"/><item><title>Nextcloud selbst hosten: deine eigene Cloud hinter Traefik</title><link>https://serverkueche.de/tutorials/nextcloud-eigene-cloud/</link><pubDate>Sun, 19 Jul 2026 00:00:00 +0000</pubDate><author>feedback@serverkueche.de (Serverküche)</author><guid>https://serverkueche.de/tutorials/nextcloud-eigene-cloud/</guid><description>Nextcloud mit Docker hinter Traefik aufsetzen: eigene Cloud für Dateien, Kalender und Kontakte – mit MariaDB, Redis und automatischem HTTPS.</description><content:encoded><![CDATA[<p>Deine Dateien, dein Kalender, deine Kontakte – aber auf deinem Server statt bei einem
Cloud-Konzern. <strong>Nextcloud</strong> ist das Flaggschiff des Selfhostings: eine vollwertige
Cloud, die du selbst betreibst. In diesem Rezept setzen wir sie sauber hinter Traefik
auf, mit eigener Datenbank, Caching und automatischem HTTPS.</p>
<h2 id="was-bauen-wir">Was bauen wir?</h2>
<p>Am Ende läuft <strong>Nextcloud 34</strong> hinter deinem Traefik-Proxy, erreichbar unter
<code>https://cloud.DEINE_DOMAIN</code> mit gültigem Let&rsquo;s-Encrypt-Zertifikat. Nextcloud ist deine
private Cloud: Dateien synchronisieren (wie bei Dropbox), Kalender und Kontakte über
alle Geräte, Fotos, Notizen, Office-Dokumente. Du verbindest den offiziellen
<strong>Desktop-Sync-Client</strong> und die <strong>Handy-Apps</strong> mit deinem Server – die Daten liegen
dabei ausschließlich bei dir.</p>
<p>Wir setzen bewusst auf das <strong>klassische <code>nextcloud</code>-Image</strong> (nicht auf „Nextcloud
All-in-One&quot;) plus <strong>MariaDB</strong> als Datenbank und <strong>Redis</strong> fürs Caching und File-Locking.
Diese Kombination ist stabil, gut dokumentiert und passt exakt in das Traefik-Muster aus
der Serverküche.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-sky-300 bg-sky-50 dark:border-sky-800 dark:bg-sky-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">ℹ️</span>Warum nicht Nextcloud AIO?
  </p>
  <div class="prose-kitchen text-sm">Nextcloud bietet auch ein „All-in-One&quot;-Paket (AIO) an. Das bringt aber sein <strong>eigenes
TLS und eigene Ports</strong> mit und will den Reverse-Proxy-Teil selbst übernehmen – das
beißt sich mit einem bestehenden Traefik. Für unser Setup ist das klassische Image die
richtige, kontrollierbare Wahl.</div>
</div>
<h2 id="voraussetzungen">Voraussetzungen</h2>
<ul>
<li>Ein laufender <strong>Traefik-Reverse-Proxy</strong> mit dem gemeinsamen <code>proxy</code>-Netzwerk und dem
Let&rsquo;s-Encrypt-Resolver <code>le</code> – wie im Tutorial
<a href="/tutorials/reverse-proxy-traefik/">Reverse Proxy mit Traefik</a> aufgebaut.</li>
<li>Eine Subdomain <code>cloud.DEINE_DOMAIN</code>, deren DNS-Record (A/AAAA) auf deine Server-IP
zeigt – siehe <a href="/tutorials/domain-mit-server-verbinden/">Domain mit Server verbinden</a>.</li>
<li>Ein funktionierendes <strong>Backup</strong>. Eine Cloud ist der Ort, an dem Datenverlust am
meisten wehtut – richte zuerst <a href="/tutorials/backups-mit-restic/">Backups mit Restic</a>
ein.</li>
</ul>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-herb-400 bg-herb-50 dark:border-herb-700 dark:bg-herb-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">🧑‍🍳</span>Wie groß muss der Server sein?
  </p>
  <div class="prose-kitchen text-sm">Nextcloud ist genügsamer als sein Ruf: Für den privaten Gebrauch oder eine kleine
Familie (1–5 Nutzer) reichen <strong>2 vCPU und 4 GB RAM</strong> gut aus – der getestete VPS 1000
passt. Der Flaschenhals ist der Arbeitsspeicher: Bei zu wenig RAM fängt der Server an zu
swappen und wird zäh. Redis (bauen wir gleich ein) entlastet spürbar. Für Nextcloud
Office/Collabora oder viele parallele Nutzer solltest du eher 8 GB einplanen.</div>
</div>
<p>Wie groß dein Server für deine Nutzerzahl sein sollte, schätzt dir der
<a href="/serverempfehlung/">Server-Rechner</a> in ein paar Klicks.</p>
<div class="not-prose my-6 overflow-hidden rounded-xl border border-paprika-200 bg-paprika-50 dark:border-paprika-800 dark:bg-paprika-900/20">
  <div class="flex items-center justify-between border-b border-paprika-200 bg-paprika-100 px-4 py-1.5 text-xs font-semibold uppercase tracking-wide text-paprika-700 dark:border-paprika-800 dark:bg-paprika-900/40 dark:text-paprika-300">
    <span>🍳 Empfehlung</span>
    <span title="Mit * markierte Links sind Affiliate-Links.">Anzeige</span>
  </div>
  <div class="flex flex-col gap-4 p-4 sm:flex-row sm:items-center sm:justify-between">
    <div>
      <p class="text-lg font-bold text-slate-900 dark:text-white">VPS 1000 G12</p>
      <p class="mt-1 text-sm text-slate-600 dark:text-slate-300">4 vCore · 8 GB RAM · 256 GB NVMe</p>
      <p class="mt-1 text-sm font-semibold text-paprika-700 dark:text-paprika-400">ab 10,36 €/Monat</p>
      <p class="mt-2 text-sm text-slate-600 dark:text-slate-400">Für eine private Nextcloud mit ein paar Nutzern reicht der VPS 1000 gut aus.</p>
    </div>
    <a href="https://www.netcup.com/de/server/vps/vps-1000-g12-12m?ref=44083" rel="sponsored noopener" target="_blank"
   class="inline-flex shrink-0 items-center justify-center rounded-lg bg-paprika-600 px-5 py-2.5 font-semibold text-white transition-colors hover:bg-paprika-700">
  Zu netcup →
</a>

  </div><div class="px-4 pb-4"><p class="not-prose my-3 flex flex-wrap items-center gap-x-2 gap-y-1 rounded-lg border border-herb-500/40 bg-herb-50 px-3 py-2 text-sm text-slate-700 dark:bg-herb-900/20 dark:text-slate-200">
  <span>💶 <strong>5 € Gutschein</strong> für netcup-Neukunden:</span>
  <code class="rounded bg-white px-2 py-0.5 font-mono text-sm font-semibold text-herb-800 dark:bg-slate-800 dark:text-herb-400">36nc17844976032</code>
  <span class="text-xs text-slate-500 dark:text-slate-400">(nur Neukunden, keine Domains)</span>
</p></div>
</div>

<h2 id="schritt-für-schritt">Schritt für Schritt</h2>
<h3 id="schritt-1-dns-record-anlegen">Schritt 1: DNS-Record anlegen</h3>
<p>Lege bei deinem DNS-Anbieter einen Eintrag <code>cloud.DEINE_DOMAIN</code> an, der auf deine
Server-IP zeigt (A-Record für IPv4, AAAA für IPv6). Prüfe, dass er aufgelöst wird:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">dig +short cloud.DEINE_DOMAIN</span></span></code></pre></div>
</div>
<p>Du solltest deine Server-IP sehen. Erst wenn der Record steht, kann Traefik später das
HTTPS-Zertifikat holen.</p>
<h3 id="schritt-2-das-proxy-subnetz-ermitteln">Schritt 2: Das proxy-Subnetz ermitteln</h3>
<p>Nextcloud sitzt hinter Traefik. Damit Nextclouds Brute-Force-Schutz die <strong>echte</strong>
Besucher-IP erkennt (und nicht die interne Traefik-IP sperrt), müssen wir Traefik als
„vertrauenswürdigen Proxy&quot; eintragen. Dazu brauchst du das Subnetz deines
<code>proxy</code>-Netzwerks:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker network inspect proxy -f <span class="s1">&#39;{{(index .IPAM.Config 0).Subnet}}&#39;</span></span></span></code></pre></div>
</div>
<p>Du bekommst etwas wie <code>172.18.0.0/16</code>. <strong>Merke dir diesen Wert</strong> – er kommt gleich als
<code>TRUSTED_PROXIES</code> in die Konfiguration.</p>
<h3 id="schritt-3-die-composeyaml-anlegen">Schritt 3: Die compose.yaml anlegen</h3>
<p>Leg einen Ordner an und wechsle hinein:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">mkdir -p ~/nextcloud <span class="o">&amp;&amp;</span> <span class="nb">cd</span> ~/nextcloud</span></span></code></pre></div>
</div>
<p>Erstelle die <code>compose.yaml</code>. Ersetze <code>cloud.DEINE_DOMAIN</code>, alle Passwörter und das
<code>TRUSTED_PROXIES</code>-Subnetz aus Schritt 2:</p>
<div class="sk-code">
  <span class="sk-code-head">YAML</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">services</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">nc-db</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">mariadb:11.4</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">nc-db</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">command</span><span class="p">:</span><span class="w"> </span>--<span class="l">transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">environment</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">MARIADB_ROOT_PASSWORD</span><span class="p">:</span><span class="w"> </span><span class="l">EIN_STARKES_ROOT_PASSWORT</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">MARIADB_DATABASE</span><span class="p">:</span><span class="w"> </span><span class="l">nextcloud</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">MARIADB_USER</span><span class="p">:</span><span class="w"> </span><span class="l">nextcloud</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">MARIADB_PASSWORD</span><span class="p">:</span><span class="w"> </span><span class="l">EIN_STARKES_DB_PASSWORT</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">nc_db:/var/lib/mysql</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">healthcheck</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">test</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;CMD&#34;</span><span class="p">,</span><span class="w"> </span><span class="s2">&#34;healthcheck.sh&#34;</span><span class="p">,</span><span class="w"> </span><span class="s2">&#34;--connect&#34;</span><span class="p">,</span><span class="w"> </span><span class="s2">&#34;--innodb_initialized&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">interval</span><span class="p">:</span><span class="w"> </span><span class="l">10s</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">timeout</span><span class="p">:</span><span class="w"> </span><span class="l">5s</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">retries</span><span class="p">:</span><span class="w"> </span><span class="m">6</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">networks</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">default]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">restart</span><span class="p">:</span><span class="w"> </span><span class="l">unless-stopped</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">nc-redis</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">redis:8-alpine</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">nc-redis</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">command</span><span class="p">:</span><span class="w"> </span><span class="l">redis-server --requirepass EIN_STARKES_REDIS_PASSWORT</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">networks</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">default]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">restart</span><span class="p">:</span><span class="w"> </span><span class="l">unless-stopped</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">nc-app</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">nextcloud:34-apache</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">nc-app</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">depends_on</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">nc-db</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">service_healthy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">nc-redis</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">service_started</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">environment</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">MYSQL_HOST</span><span class="p">:</span><span class="w"> </span><span class="l">nc-db</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">MYSQL_DATABASE</span><span class="p">:</span><span class="w"> </span><span class="l">nextcloud</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">MYSQL_USER</span><span class="p">:</span><span class="w"> </span><span class="l">nextcloud</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">MYSQL_PASSWORD</span><span class="p">:</span><span class="w"> </span><span class="l">EIN_STARKES_DB_PASSWORT</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">REDIS_HOST</span><span class="p">:</span><span class="w"> </span><span class="l">nc-redis</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">REDIS_HOST_PASSWORD</span><span class="p">:</span><span class="w"> </span><span class="l">EIN_STARKES_REDIS_PASSWORT</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">NEXTCLOUD_TRUSTED_DOMAINS</span><span class="p">:</span><span class="w"> </span><span class="l">cloud.DEINE_DOMAIN</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">OVERWRITEPROTOCOL</span><span class="p">:</span><span class="w"> </span><span class="l">https</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">OVERWRITECLIURL</span><span class="p">:</span><span class="w"> </span><span class="l">https://cloud.DEINE_DOMAIN</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">TRUSTED_PROXIES</span><span class="p">:</span><span class="w"> </span><span class="m">172.18.0.0</span><span class="l">/16</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">PHP_MEMORY_LIMIT</span><span class="p">:</span><span class="w"> </span><span class="l">1024M</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">PHP_UPLOAD_LIMIT</span><span class="p">:</span><span class="w"> </span><span class="l">10G</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">nc_html:/var/www/html</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">labels</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.enable=true&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.nc.rule=Host(`cloud.DEINE_DOMAIN`)&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.nc.entrypoints=websecure&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.nc.tls.certresolver=le&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.routers.nc.middlewares=nc-dav&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.services.nc.loadbalancer.server.port=80&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="c"># .well-known-Redirect für CalDAV/CardDAV (siehe unten)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.middlewares.nc-dav.redirectregex.regex=https://(.*)/.well-known/(?:card|cal)dav&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.middlewares.nc-dav.redirectregex.replacement=https://cloud.DEINE_DOMAIN/remote.php/dav/&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="s2">&#34;traefik.http.middlewares.nc-dav.redirectregex.permanent=true&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">networks</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">default, proxy]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">restart</span><span class="p">:</span><span class="w"> </span><span class="l">unless-stopped</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">nc_html</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">nc_db</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">networks</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">default</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">proxy</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">external</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span></span></span></code></pre></div>
</div>
<p>Was hier wichtig ist:</p>
<ul>
<li><strong>Drei Container:</strong> <code>nc-app</code> (Nextcloud), <code>nc-db</code> (MariaDB), <code>nc-redis</code>. Nur <code>nc-app</code>
hängt im <strong><code>proxy</code>-Netz</strong> (für Traefik) <em>und</em> im internen <code>default</code>-Netz. Datenbank und
Redis bleiben ausschließlich intern – sie haben <strong>kein <code>ports:</code></strong> und sind von außen
nicht erreichbar.</li>
<li><strong>Zwei Named Volumes:</strong> <code>nc_html</code> (Programmcode, <code>config.php</code>, Nutzerdaten) und
<code>nc_db</code> (die MariaDB-Daten). Das <code>nc_db</code>-Volume ist Pflicht: Ohne den Eintrag landet
die Datenbank in einem <strong>anonymen</strong> Volume, und ein <code>docker compose down</code> gefolgt
von <code>up</code> würde sie <strong>unwiederbringlich verlieren</strong>.</li>
<li><strong><code>healthcheck</code> + <code>depends_on: service_healthy</code>:</strong> Nextcloud startet schneller als die
Datenbank initialisiert ist. Ohne diesen Healthcheck scheitert die Erstinstallation an
einem „Connection refused&quot;. So wartet der App-Container, bis MariaDB wirklich bereit ist.</li>
<li><strong><code>NEXTCLOUD_TRUSTED_DOMAINS</code>:</strong> ohne die eigene Domain hier begrüßt dich Nextcloud mit
„Zugriff über eine nicht vertrauenswürdige Domäne&quot;.</li>
<li><strong><code>OVERWRITEPROTOCOL: https</code></strong> sagt Nextcloud, dass es hinter HTTPS läuft – sonst baut
es interne Links als <code>http://</code> und Logins/Redirects brechen.</li>
<li><strong><code>TRUSTED_PROXIES</code>:</strong> das Subnetz aus Schritt 2. Damit erkennt Nextcloud die echte
Client-IP; sonst sperrt der Brute-Force-Schutz die Traefik-IP.</li>
<li><strong><code>PHP_MEMORY_LIMIT</code> / <code>PHP_UPLOAD_LIMIT</code>:</strong> die Defaults (512 MB) sind für große
Uploads zu klein. Hier großzügig gesetzt.</li>
<li><strong><code>loadbalancer.server.port=80</code>:</strong> das Apache-Image lauscht im Container auf Port 80.</li>
<li><strong>Die <code>nc-dav</code>-Middleware</strong> löst ein klassisches Nextcloud-Problem – dazu gleich mehr.</li>
</ul>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-amber-400 bg-amber-50 dark:border-amber-700 dark:bg-amber-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">⚠️</span>CalDAV/CardDAV: der .well-known-Redirect
  </p>
  <div class="prose-kitchen text-sm">Nextcloud möchte Kalender-/Kontakt-Clients über <code>/.well-known/caldav</code> und
<code>/.well-known/carddav</code> zu <code>/remote.php/dav/</code> schicken. Hinter einem Reverse Proxy
funktioniert Nextclouds eigener Redirect nicht zuverlässig – das führt später zu einer
Warnung im Sicherheits-Check und zu Problemen bei der Kalender-Einrichtung. Die
<code>nc-dav</code>-Middleware oben erledigt den Redirect direkt in Traefik. Wichtig: Das Muster
muss die <strong>volle <code>https://…</code>-URL</strong> matchen – <code>redirectregex</code> prüft immer die komplette
URL, nicht nur den Pfad. Ein reines Pfad-Muster wie <code>^/.well-known/…</code> greift deshalb
nie.</div>
</div>
<h3 id="schritt-4-starten-und-den-erst-setup-durchlaufen">Schritt 4: Starten und den Erst-Setup durchlaufen</h3>
<p>Starte den Stack:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker compose up -d</span></span></code></pre></div>
</div>
<p>Beim ersten Start initialisiert MariaDB die Datenbank und Nextcloud entpackt sich –
das dauert ein bis zwei Minuten. Verfolge es im Log:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker compose logs -f nc-app</span></span></code></pre></div>
</div>
<p>Beim ersten Lauf entpackt das Image Nextcloud ins Volume; du siehst Zeilen wie
<code>Initializing nextcloud 34.0.1.2 ...</code> und schließlich <code>Initializing finished</code>, gefolgt
vom Apache-Start. Erscheint stattdessen wiederholt <code>restarting</code>, wirf einen Blick in den
Abschnitt „Wenn es nicht funktioniert&quot;. Mit <code>Strg+C</code> verlässt du die Log-Ansicht wieder
(der Container läuft weiter).</p>
<p>Ruf dann <code>https://cloud.DEINE_DOMAIN</code> auf. Traefik holt beim ersten Zugriff das
Zertifikat (kann ein paar Sekunden dauern). Weil wir Datenbank und Redis schon per
Umgebungsvariablen konfiguriert haben, erkennt Nextcloud das automatisch und fragt nur
noch nach einem <strong>Administrationskonto</strong>:</p>
<p><figure class="my-6"><img src="/tutorials/nextcloud-eigene-cloud/nextcloud-setup_hu_bd390b1b06152f06.webp" srcset="/tutorials/nextcloud-eigene-cloud/nextcloud-setup_hu_54205e140ab4df51.webp 480w, /tutorials/nextcloud-eigene-cloud/nextcloud-setup_hu_bd390b1b06152f06.webp 768w, /tutorials/nextcloud-eigene-cloud/nextcloud-setup_hu_6aed3ce169effeae.webp 1200w, /tutorials/nextcloud-eigene-cloud/nextcloud-setup_hu_2dd5324525c2b322.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/nextcloud-eigene-cloud/nextcloud-setup_hu_b8b96096d363578.webp"
    alt="Der Nextcloud-Erst-Setup erkennt die Autoconfig und fragt nur noch nach Name und Passwort des Administrationskontos" title="Erst-Setup: Datenbank ist vorkonfiguriert, du legst nur das Admin-Konto an"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Erst-Setup: Datenbank ist vorkonfiguriert, du legst nur das Admin-Konto an</figcaption></figure></p>
<p>Vergib einen Admin-Namen und ein starkes Passwort und klick auf <strong>Installieren</strong>.
Nextcloud richtet die Instanz ein – danach landest du auf der Anmeldeseite:</p>
<p><figure class="my-6"><img src="/tutorials/nextcloud-eigene-cloud/nextcloud-login_hu_80e3fea49ed0fa5d.webp" srcset="/tutorials/nextcloud-eigene-cloud/nextcloud-login_hu_7b6cf30b4bed90d8.webp 480w, /tutorials/nextcloud-eigene-cloud/nextcloud-login_hu_80e3fea49ed0fa5d.webp 768w, /tutorials/nextcloud-eigene-cloud/nextcloud-login_hu_31fcd7effc10218d.webp 1200w, /tutorials/nextcloud-eigene-cloud/nextcloud-login_hu_f9021634b2859d48.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/nextcloud-eigene-cloud/nextcloud-login_hu_76d7c24abc8fef7e.webp"
    alt="Die Nextcloud-Anmeldeseite unter der eigenen HTTPS-Domain" title="Die Anmeldeseite unter cloud.DEINE_DOMAIN – mit gültigem HTTPS von Traefik"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Die Anmeldeseite unter cloud.DEINE_DOMAIN – mit gültigem HTTPS von Traefik</figcaption></figure></p>
<p>Nach dem Login begrüßt dich das <strong>Dashboard</strong>, und unter <strong>Dateien</strong> findest du deine
Cloud mit ein paar Beispieldateien:</p>
<p><figure class="my-6"><img src="/tutorials/nextcloud-eigene-cloud/nextcloud-dashboard_hu_c73d63376be11028.webp" srcset="/tutorials/nextcloud-eigene-cloud/nextcloud-dashboard_hu_8b8b0eae69ca9f5.webp 480w, /tutorials/nextcloud-eigene-cloud/nextcloud-dashboard_hu_c73d63376be11028.webp 768w, /tutorials/nextcloud-eigene-cloud/nextcloud-dashboard_hu_234eec6f42d11461.webp 1200w, /tutorials/nextcloud-eigene-cloud/nextcloud-dashboard_hu_74337e3e851cbd62.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/nextcloud-eigene-cloud/nextcloud-dashboard_hu_bb8653ade3e6bf20.webp"
    alt="Das Nextcloud-Dashboard mit dem Widget „Empfohlene Dateien&quot;" title="Das Dashboard nach dem ersten Login"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Das Dashboard nach dem ersten Login</figcaption></figure></p>
<p><figure class="my-6"><img src="/tutorials/nextcloud-eigene-cloud/nextcloud-dateien_hu_8c55170c4ab25cd1.webp" srcset="/tutorials/nextcloud-eigene-cloud/nextcloud-dateien_hu_b1b801f2689f8212.webp 480w, /tutorials/nextcloud-eigene-cloud/nextcloud-dateien_hu_8c55170c4ab25cd1.webp 768w, /tutorials/nextcloud-eigene-cloud/nextcloud-dateien_hu_2b1999b825fcf10.webp 1200w, /tutorials/nextcloud-eigene-cloud/nextcloud-dateien_hu_b18f6036e55a9058.webp 1920w" sizes="(min-width: 768px) 768px, 100vw"
    width="768" height="432"
    data-full="/tutorials/nextcloud-eigene-cloud/nextcloud-dateien_hu_eb10dcee28315b64.webp"
    alt="Die Dateien-Oberfläche von Nextcloud mit Ordnern und Beispieldateien" title="Die Dateien-App – das Herzstück deiner eigenen Cloud"
    loading="lazy" decoding="async" class="rounded-lg"><figcaption class="mt-2 text-sm text-center text-slate-500 italic">Die Dateien-App – das Herzstück deiner eigenen Cloud</figcaption></figure></p>
<h3 id="schritt-5-hintergrund-jobs-cron-einrichten">Schritt 5: Hintergrund-Jobs (Cron) einrichten</h3>
<p>Nextcloud muss regelmäßig Aufgaben erledigen (Aufräumen, Benachrichtigungen,
Vorschaubilder). Standardmäßig passiert das per „AJAX&quot; bei jedem Seitenaufruf – das ist
unzuverlässig. Der empfohlene Weg ist ein <strong>Cron-Sidecar</strong>: ein zweiter Container mit
demselben Image, der nur <code>cron.php</code> ausführt. Ergänze in der <code>compose.yaml</code> einen
Service:</p>
<div class="sk-code">
  <span class="sk-code-head">YAML</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="w">  </span><span class="nt">nc-cron</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="l">nextcloud:34-apache</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">container_name</span><span class="p">:</span><span class="w"> </span><span class="l">nc-cron</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">entrypoint</span><span class="p">:</span><span class="w"> </span><span class="l">/cron.sh</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">depends_on</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">nc-db</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">condition</span><span class="p">:</span><span class="w"> </span><span class="l">service_healthy</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">volumes</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">nc_html:/var/www/html</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">networks</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">default]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">restart</span><span class="p">:</span><span class="w"> </span><span class="l">unless-stopped</span></span></span></code></pre></div>
</div>
<p>Der Sidecar teilt sich das <code>nc_html</code>-Volume mit der App und führt die Jobs alle fünf
Minuten aus. Übernimm die Änderung und stell den Modus in Nextcloud auf „Cron&quot;:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker compose up -d
</span></span><span class="line"><span class="cl">docker <span class="nb">exec</span> -u www-data nc-app php occ background:cron</span></span></code></pre></div>
</div>
<p>Unter <strong>Verwaltung → Grundeinstellungen</strong> sollte jetzt „Cron&quot; aktiv sein.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-herb-400 bg-herb-50 dark:border-herb-700 dark:bg-herb-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">🧑‍🍳</span>occ – das Kommandozeilen-Werkzeug
  </p>
  <div class="prose-kitchen text-sm"><p><code>occ</code> ist Nextclouds Admin-Werkzeug. Du rufst es immer als Nutzer <code>www-data</code> im
App-Container auf: <code>docker exec -u www-data nc-app php occ &lt;befehl&gt;</code>. Zwei nützliche
Aufräum-Befehle direkt nach der Installation:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker <span class="nb">exec</span> -u www-data nc-app php occ db:add-missing-indices
</span></span><span class="line"><span class="cl">docker <span class="nb">exec</span> -u www-data nc-app php occ config:system:set default_phone_region --value<span class="o">=</span>DE</span></span></code></pre></div>
</div></div>
</div>
<h3 id="schritt-6-die-clients-verbinden">Schritt 6: Die Clients verbinden</h3>
<p>Jetzt der eigentliche Nutzen. Es gibt drei Wege, deine Cloud zu benutzen:</p>
<ol>
<li><strong>Desktop-Sync-Client</strong> (Windows/macOS/Linux): Installiere den „Nextcloud Desktop&quot;-
Client, gib als Server-Adresse <code>https://cloud.DEINE_DOMAIN</code> ein, melde dich an und
wähle einen lokalen Ordner. Dateien werden wie bei Dropbox synchronisiert.
Mit den <strong>virtuellen Dateien</strong> (Windows/macOS) belegen sie erst dann Platz auf der
Platte, wenn du sie öffnest – praktisch, wenn deine Cloud größer ist als die lokale
Festplatte.</li>
<li><strong>Handy-App</strong> (Android/iOS): die offizielle Nextcloud-App, gleiche Server-Adresse.
Ideal für den automatischen <strong>Foto-Upload</strong> vom Smartphone.</li>
<li><strong>Kalender &amp; Kontakte:</strong> In den Systemeinstellungen deines Geräts ein CalDAV-/
CardDAV-Konto mit der Adresse <code>https://cloud.DEINE_DOMAIN</code> anlegen – dank der
<code>.well-known</code>-Middleware aus Schritt 3 funktioniert die automatische Erkennung.</li>
</ol>
<p>Funktionen wie Kalender, Kontakte oder Mail sind eigene <strong>Apps</strong>, die du unter
<strong>Verwaltung → Apps</strong> mit einem Klick nachinstallierst – Nextcloud ist also erweiterbar,
ohne dass du am Server etwas anfassen musst.</p>
<div class="not-prose my-6 rounded-lg border-l-4 p-4 border-amber-400 bg-amber-50 dark:border-amber-700 dark:bg-amber-900/20">
  <p class="mb-1 flex items-center gap-2 font-semibold text-slate-900 dark:text-white">
    <span aria-hidden="true">⚠️</span>Nicht mit dem Admin-Konto arbeiten
  </p>
  <div class="prose-kitchen text-sm">Das Administrationskonto aus Schritt 4 ist für die <strong>Verwaltung</strong> gedacht, nicht für den
Alltag. Leg dir unter <strong>Verwaltung → Konten</strong> ein normales Nutzerkonto an und synchronisiere
deine Dateien darüber. So ist dein mächtiges Admin-Konto nicht ständig auf allen Geräten
angemeldet – ein einfacher, aber wirksamer Sicherheitsgewinn. Für Familie oder Team legst
du hier weitere Konten an; jedes bekommt seinen eigenen, verschlüsselten Bereich.</div>
</div>
<h2 id="wenn-es-nicht-funktioniert">Wenn es nicht funktioniert</h2>
<p><strong>Symptom:</strong> „<strong>Zugriff über eine nicht vertrauenswürdige Domäne</strong>&quot; statt der Login-Seite.</p>
<p><strong>Ursache &amp; Lösung:</strong> Deine Domain steht nicht in <code>trusted_domains</code>. Prüfe
<code>NEXTCLOUD_TRUSTED_DOMAINS</code> in der Compose-Datei. Nachträglich setzen geht per occ:
<code>docker exec -u www-data nc-app php occ config:system:set trusted_domains 1 --value=cloud.DEINE_DOMAIN</code>.</p>
<p><strong>Symptom:</strong> Der Sicherheits-Check meldet „<strong>Your web server is not set up properly to
resolve .well-known/caldav</strong>&quot;.</p>
<p><strong>Ursache &amp; Lösung:</strong> Der CalDAV/CardDAV-Redirect greift nicht. Kontrolliere die
<code>nc-dav</code>-Middleware-Labels (Schritt 3) und dass der Router sie über
<code>...routers.nc.middlewares=nc-dav</code> einbindet. Das Regex muss die volle
<code>https://…</code>-URL matchen – <code>redirectregex</code> prüft die komplette URL, nicht nur den Pfad.</p>
<p><strong>Symptom:</strong> Warnung „<strong>The &lsquo;Strict-Transport-Security&rsquo; HTTP header is not set</strong>&quot;.</p>
<p><strong>Ursache &amp; Lösung:</strong> Der HSTS-Header fehlt. Setz ihn als Traefik-Middleware und häng sie
an den Router:
<code>traefik.http.middlewares.nc-secure.headers.stsSeconds=15552000</code>. Häng sie zusätzlich zur
<code>nc-dav</code>-Middleware an den Router (<code>...routers.nc.middlewares=nc-dav,nc-secure</code>). Der Header
muss vom Proxy kommen, nicht von Nextcloud. In
<a href="/tutorials/nextcloud-optimieren-absichern/">Teil 2</a> richten wir genau diese
<code>nc-secure</code>-Middleware vollständig ein (inklusive <code>includeSubdomains</code>).</p>
<p><strong>Symptom:</strong> Große Uploads brechen ab oder enden mit einem Timeout / „413&quot;.</p>
<p><strong>Ursache &amp; Lösung:</strong> Das PHP-Limit ist zu klein. Erhöhe <code>PHP_UPLOAD_LIMIT</code> und
<code>PHP_MEMORY_LIMIT</code> (Schritt 3) und starte den Container neu. In seltenen Fällen greifen
diese Variablen nicht – dann ein eigenes <code>php.ini</code>-Snippet ins Image mounten.</p>
<p><strong>Symptom:</strong> Beim ersten Start bricht die Installation mit „<strong>MySQL server has gone
away</strong>&quot; oder „Connection refused&quot; ab.</p>
<p><strong>Ursache &amp; Lösung:</strong> Der App-Container war schneller als die Datenbank. Genau dagegen
ist der <code>healthcheck</code> mit <code>depends_on: condition: service_healthy</code> da – prüfe, dass beide
in deiner Compose-Datei vorhanden sind, und starte mit <code>docker compose up -d</code> neu.</p>
<h2 id="wartung--backups">Wartung &amp; Backups</h2>
<ul>
<li>
<p><strong>Backups sind bei einer Cloud Pflicht.</strong> Ein konsistentes Backup braucht <strong>drei
Dinge</strong>: die <strong>Datenbank</strong> (MariaDB-Dump), das <strong>Datenverzeichnis</strong> (deine Dateien) und
die <strong>Konfiguration</strong> (<code>config.php</code>). Versetze Nextcloud vor dem Backup kurz in den
Wartungsmodus, damit Datenbank und Dateien zueinander passen:</p>
<div class="sk-code">
  <span class="sk-code-head">Terminal</span>
  <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker <span class="nb">exec</span> -u www-data nc-app php occ maintenance:mode --on
</span></span><span class="line"><span class="cl">docker <span class="nb">exec</span> nc-db mariadb-dump -u root -pEIN_STARKES_ROOT_PASSWORT nextcloud &gt; nextcloud-db.sql
</span></span><span class="line"><span class="cl">docker <span class="nb">exec</span> -u www-data nc-app php occ maintenance:mode --off</span></span></code></pre></div>
</div>
<p>Sichere den Dump zusammen mit dem <code>nc_html</code>-Volume <strong>verschlüsselt und off-site</strong> mit
<a href="/tutorials/backups-mit-restic/">Restic</a> – das rohe <code>nc_db</code>-Volume musst du dank des
Dumps nicht zusätzlich sichern. Im <code>nc_html</code>-Volume stecken sowohl der
Programmcode und die <code>config.php</code> als auch – unter <code>data/</code> – <strong>deine eigentlichen
Nutzerdateien</strong>. Wächst deine Cloud stark, kannst du dieses <code>data/</code>-Verzeichnis später
auf ein eigenes, größeres Volume auslagern; fürs erste reicht ein Volume für alles.</p>
</li>
<li>
<p><strong>Updates: immer nur eine Hauptversion pro Schritt.</strong> Von 34 auf 35, nie direkt auf 36.
Setz den Image-Tag hoch (<code>nextcloud:35-apache</code>), dann <code>docker compose pull</code> und
<code>docker compose up -d</code>. Der Container führt das nötige <code>occ upgrade</code> beim Start
<strong>automatisch</strong> aus. <strong>Vorher immer ein Backup</strong> anlegen. Den Cron-Sidecar auf dieselbe
Version heben.</p>
</li>
<li>
<p><strong>Sicherheit prüfen.</strong> Lass nach dem Aufsetzen den offiziellen
<a href="https://scan.nextcloud.com/">Nextcloud Security Scan</a> gegen deine Domain laufen (Ziel:
Note A) und arbeite die Warnungen aus der Admin-Übersicht ab. Die Übersicht unter
<strong>Verwaltung → Übersicht</strong> führt automatische Prüfungen durch und zeigt genau, was noch
fehlt. Halte Nextcloud aktuell – Sicherheitslücken werden zeitnah geschlossen, aber nur,
wenn du updatest.</p>
</li>
<li>
<p><strong>Ehrlich zum Aufwand:</strong> Eine selbst gehostete Cloud will gepflegt werden. Rechne mit
einem Update-Durchgang etwa monatlich und einem regelmäßigen Blick in die
Admin-Übersicht. Dafür gehören die Daten dann wirklich dir.</p>
</li>
</ul>
]]></content:encoded></item></channel></rss>