Komplettanleitung Mariadb & Nextcloud mit Nginx Proxy
Um den Einstieg in die Installation von Nextcloud zu vereinfachen, habe ich mir überlegt eine Komplettanleitung zu schrieben, die folgende Komponenten auf einem Ubuntu (oder Debian basiertem OS) installiert:
- nginx (Webserver / Proxy)
- Let’s Encrypt
- Docker
- Mariadb (in Docker)
- Nextcloud (in Docker)
- NFTables + Firewallregeln
Vorbereitung
Es sollte vorab schon ein DNS Eintrag für die Cloud vorbereitet werden. In diesem Bespiel wird nextcloud.dr3st.de verwendet, dieser ist anzupassen. Bitte einen A oder CNAME Eintrag anlegen, der letztlich auf die öffentliche IP des Servers zeigt. Keine iFrame- / Weiterleitungs-Einstellung
Die Mariadb (Mysql-Server) wird so so einrichtet, dass diese auch für andere Dienste verwendet werden kann, damit nicht weitere Instanzen gestartet werden müssen. Viele anleitungen sind so gebaut, dass für jede Anwendung ein eigener MySQL-Server eingerichtet werden soll, was ich unsinnig finde.
Außerdem wird die Firewall-Einstellung von Docker nicht deaktiviert, die generelle Absicherung aber dennoch mit NFTables realisiert. Somit ist gewährleistet, dass bestehende Setups möglichst nicht beeinträchtigt werden. Wer dennoch die Firewall aufgeräumter haben möchte, kann den optinalen Hinweis in der Anleitung berücksichtigen. Hierbei aber bitte vorsichtig sein, da man bestehende Installationen unereichbar machen könnte!
Die Befehle sind mit root-Rechten ausgeführt! Enige davon, gerade die Konfigurationsdateien anlegen, können nicht mit sudo ausgeführt werden, weil die Berechtigungen sonst fehlerhaft sind. Daher bietet sich vorab der Login als root, oder “sudo -i” an.
Installation
apt update && \
apt install nftables docker.io docker-compose mariadb-client pwgen
Firewall
Konfiguration
Zuerst richten wir die Firewall ein um sicherzugehen, das der Datenbank-Server nach der Installation nicht direkt im Internet erreichbar ist.
Existiert die Konfiguration bereits, sollte Zeile 12 berücksichtigt werden.
|
|
Firewall Restart
# -c (Check) -f (File)
nft -c -f /etc/nftables.conf
#Keine Fehlermeldung? Gut ... :
systemctl restart nftables.service
systemctl enable nftables.service
MariaDB
zunächst legen wir die Konfiguration an, hierbei wird ein Passwort gewürfelt und die docker-compose.yml generiert.
Container Konfiguration
# Passwort generieren (32 Stellen, siehe head -c 32)
MDB_PW=$(openssl rand 512 | sha512sum | head -c 32)
# Ordner anlegen und betreten
mkdir -p /srv/docker/git/mariadb
# Konfiguration anlegen (einfach kopieren)
cat > /srv/docker/git/mariadb/docker-compose.yml <<EOF
version: "3"
services:
mariadb:
image: mariadb:10.6
container_name: mariadb
network_mode: host
environment:
TZ: "UTC"
MYSQL_ROOT_PASSWORD: "${MDB_PW}"
volumes:
- /srv/docker/containers/mariadb/data:/var/lib/mysql
restart: unless-stopped
EOF
Client Config (my.cnf)
Zusätzlich speichern wir die Verbindungsdaten in der lokalen “my.cnf” damit eine Verbindung ohne Passwort-Eingabe möglich ist:
[ ! -f "${HOME}/.my.cnf" ] && \
cat > ${HOME}/.my.cnf <<EOF
[mysql]
host=127.0.0.1
user=root
password=${MDB_PW}
[client]
host=127.0.0.1
user=root
password=${MDB_PW}
[mysqldump]
host=127.0.0.1
user=root
password=${MDB_PW}
EOF
Container start
cd /srv/docker/git/mariadb
docker-compose pull
docker-compose up -d
Datenbank Test & Zugangsdaten
Das Testen der Verbindung ist nun möglich und es werden die Logindaten für die Nextcloud-Datenbank angelegt.
# Passwort generieren und den Admin Username eintippen
NCDB_PW=$(openssl rand 512 | sha512sum | head -c 32)
ADMIN_PW=$(openssl rand 512 | sha512sum | head -c 32)
# Eingaben notwendig! Hier als Beispiel:
read -r -p "enter Nextcloud Admin User-Email:" ADMIN_USER
admin@dr3st.de
read -r -p "enter Nextcloud Domain:" NC_DOMAIN
nextcloud.dr3st.de
# diese Befehle legen die Datenbank und Zugangsdaten an
mysql -e 'CREATE DATABASE nextcloud /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */;'
mysql -e "GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextcloud'@'%' IDENTIFIED BY '${NCDB_PW}';"
Nextcloud
mkdir -p /srv/docker/git/nextcloud
# Netzwerk anlegen, damit dieses von mehreren Anwendungen
# genutzt werden kann und nicht an einer Docker-Compose Datei hängt
docker network create --gateway 10.11.12.1 --subnet 10.11.12.0/24 --opt com.docker.network.bridge.name=br_apps br_apps
# Nextcloud docker-compose.yml anlegen (Passwort wird durch Variable eingetragen!)
cat > /srv/docker/git/nextcloud/docker-compose.yml <<EOF
version: '3'
services:
nextcloud:
container_name: nextcloud
image: nextcloud:24
volumes:
- /srv/docker/containers/nextcloud/data/:/var/www/html/
# Passwörter ausgelagert
- ./secrets/:/run/secrets/:ro
environment:
MYSQL_DATABASE_FILE: "/run/secrets/mysql_database.txt"
MYSQL_USER_FILE: "/run/secrets/mysql_user.txt"
MYSQL_PASSWORD_FILE: "/run/secrets/mysql_password.txt"
MYSQL_HOST: "10.11.12.1"
NEXTCLOUD_ADMIN_USER_FILE: "/run/secrets/admin_user.txt"
NEXTCLOUD_ADMIN_PASSWORD_FILE: "/run/secrets/admin_password.txt"
NEXTCLOUD_TRUSTED_DOMAINS: "${NC_DOMAIN}"
TRUSTED_PROXIES: "10.11.12.1"
restart: unless-stopped
networks:
default:
ipv4_address: 10.11.12.2
networks:
default:
external:
name: br_apps
EOF
# Container starten
cd /srv/docker/git/nextcloud
mkdir -p secrets
echo "${NCDB_PW}" > secrets/mysql_password.txt
echo "${ADMIN_PW}" > secrets/admin_password.txt
echo "${ADMIN_USER}" > secrets/admin_user.txt
echo "nextcloud" > secrets/mysql_database.txt
echo "nextcloud" > secrets/mysql_user.txt
docker-compose pull
docker-compose up -d
# Admin Passwort zum notieren ausgeben
cat secrets/admin_password.txt
Nginx & Certbot (Let’s Encrypt)
Zuerst wird nginx installiert und der Autostart aktiviert.
apt install nginx certbot
systemctl enable nginx
Zertifikat erzeugen
Danach wird das Zertifikat von Let’s Encrypt angefordert. Dieses wird übrigens automatisch erneuert, weil das Certbot-Paket einen Cronjob mitliefert (/etc/cron.d/certbot).
# email@domain.de ersetzen! Dies muss nicht die Cloud Admin-Email sein!
certbot certonly --webroot -w /var/www/html/ --email email@domain.de --non-interactive --agree-tos -d ${NC_DOMAIN} --rsa-key-size 4096
# im Normalfall wird eine ähnliche Ausgabe angezeigt:
#IMPORTANT NOTES:
# - Congratulations! Your certificate and chain have been saved at:
# /etc/letsencrypt/live/..../fullchain.pem
Und die Nginx-Konfiguration angelegt. Wichtig hierbei ist die Domain anzupassen!
# NC_DOMAIN wurde weiter oben bereits erfragt und nun
# hier verwendet und automatisch eingetragen!
cat > /etc/nginx/sites-enabled/${NC_DOMAIN}.conf <<EOF
server {
server_name ${NC_DOMAIN};
listen 0.0.0.0:80;
location ~ .well-known {
root /var/www/html;
}
location / {
return 301 https://${NC_DOMAIN}$request_uri;
}
}
server {
server_name ${NC_DOMAIN};
listen 0.0.0.0:443 ssl http2;
access_log /var/log/nginx/${NC_DOMAIN}.access.log;
error_log /var/log/nginx/${NC_DOMAIN}.error.log;
root /var/www/html;
ssl_certificate /etc/letsencrypt/live/${NC_DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${NC_DOMAIN}/privkey.pem;
client_max_body_size 4096m;
proxy_max_temp_file_size 4096m;
# Proxy for nextcloud docker
location / {
add_header Strict-Transport-Security "max-age=63072000" always;
add_header X-Frame-Options SAMEORIGIN;
proxy_cookie_path / "/; secure; HttpOnly";
# And don't forget to include our proxy parameters
include /etc/nginx/proxy_params;
# Connect to local port
proxy_pass http://10.11.12.2:80;
}
}
EOF
Nginx reload
nginx -t && systemctl reload nginx.service
Zugangsdaten
Im Anschluss sollte die Nextcloud im Browser erreichbar sein. Die Logindaten entsprechen denen, die man selbst festgelegt hat. Ausgeben kann man diese aber noch mal nachträglich:
cd /srv/docker/git/nextcloud
# Benutzername
cat secrets/admin_user.txt
# Passwort
cat secrets/admin_password.txt
Nachwort und Netzwerk-Information
Warum das separate Netz?
Man möchte dem Nextcloud-Container und allen eventuell noch folgenden Anwendungen statische IP-Adressen geben um diese in der Nginx-Konfiguration hinterlegen zu können. In diesem Beispiel ist es die 10.11.12.2, hätte man allerdings das Docker Netzwerk genommen (docker0), hätte dies irgendeine IP aus dem Netz 172.17.0.0/16 sein können., weil dieses Netz keine statische Zuweisung erlaubt.
Ich bevorzuge allerdings planbare Konfigurationen und wähle daher diesen Weg, denn somit spart man sich den unnötigen Docker-Proxy, der in vielen Anleitungen genutzt wird. Nextcloud kann nämlich von Nginx direkt erreicht werden!
MariaDB und Nginx laufen im Standard Netzwerk (Namespace), sodass diese sowohl an öffentlichen IP-Adressen, als auch allen Docker Netzwerken lauschen können. Deshalb sind weitere Anwendungen auch in der Lage mit Mariadb zu kommunizieren (hier z.B. 10.11.12.1:3306). Anwendungen in anderen Netzen (z.B. docker0, oder anderen zukünftigen br-apps2, br-xyz, …) sind somit in der Lage über die IP-Adresse des Hosts Verbindungen aufzubauen.
Netzwerk | IP-Netz | Host-IP | Container IPs |
---|---|---|---|
br-apps | 10.11.12.0/24 | 10.11.12.1 | 10.11.12.2 - 10.11.13.254 |
br-apps2 | 192.168.22.0/24 | 192.168.22.1 | 192.168.22.2 - 192.168.22.254 |
neuland | 172.19.199.0/24 | 172.19.199.1 | 172.19.199.2 - 172.19.199.254 |
Wie man erkennen kann, erhält der Host selbst die .1 in den Netzen, sodass dieser jeden Container erreichen kann. Die Container erreichen den Host (und Anwendungen im selben Netzwerk).
Somit können Container die Datenbank, den Webserver und alle Anwendungen im Host-Namespace erreichen, sofern diese mittels Firewall nicht unterbunden werden.
Die Nutzung des Host Namespaces wird durch “network_mode: host” oder “–network host” Einstellung festgelegt. Weil jedes Netzwerk für sich eine Layer2 Domäne darstellt, können die Netze untereinander nur sprechen, wenn der Host die Anfragen zwischen den Netzen routet.