[[!meta title="Cloud-Server der Starship Factory"]] [[!toc startlevel=2]] # Cloud-Server Der Cloud-Server dient zum Austausch von Dateien und Informationen zwischen den Mitgliedern der Starship Factory. Er dient primär zur Bereitstellung einer NextCloud-Instanz für diese Zweck. Neben dieser ist zusätzlich ein LDAP-Server zur Benutzerverwaltung und Authentifizierung installiert. Der Cloud-Server wurde von Bernd Kalbfuss (aka Langweiler) eingerichtet. Er wird aktuell von den folgenden Personen administriert: | Name | Spitzname/Benutzername | E-Mail | | --------------- | ---------------------- | ------------------------- | | Bernd Kalbfuss | langweiler | langweiler@rueblitorte.de | | Fabian Thoma | fabianthoma | f@bianthoma.me | | Cedric Spindler | zedcat | cedric.spindler@gmail.com | ## Hardware Der Cloud-Server läuft auf einem HP ProLiant ML110-Server der vermutlich 5. Generation. Er besitzt eine CPU mit zwei Kernen. Die Leistungsdaten der CPU sind wie folgt: | Merkmal | Wert | | ------------- | ---- | | Product | Intel(R) Xeon(R) CPU 3065@2.33GHz | | Vendor | Intel Corp. | | Physical ID | 4 | | Bus info | cpu@0 | | Version | C1 | | Slot | CPU 1 | | Size | 2012MHz | | Capacity | 3300MHz | | Width | 64 bits | | Clock | 1333MHz | | Capabilities | lm fpu fpu_exception wp vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ht tm pbe syscall nx x86-64 constant_tsc arch_perfmon pebs bts rep_good nopl cpuid aperfmperf pni dtes64 monitor ds_cpl smx est tm2 ssse3 cx16 xtpr pdcm lahf_lm pti dtherm cpufreq | | Configuration | cores=2 enabledcores=2 threads=2 | Der Server ist insgesamt 6 GB (2 x 2GB, 2 x 1 GB) RAM bestückt. Es handelt sich um SDR2 ECC RAM mit 800 MHz Taktfrequenz. Der Server ist mit den folgenden Laufwerken (Festplatten mit Magnetspeicher) ausgestattet: | # | Description | Product | Vendor | Physical ID | Bus info | Logical name | Version | Serial | Size | | - | ----------- | ---------------- | --------------- | ------------ | ------------ | -------------| ------- | --------------- | -------------- | | 0 | ATA Disk | GB0160CAABV | | 0 | scsi@0:0.0.0 | /dev/sda | HPG1 | 5RX79N7K | 149GiB (160GB) | | 1 | ATA Disk | WDC WD10EARS-00Y | Western Digital | 1 | scsi@0:0.1.0 | /dev/sdb | 0A80 | WD-WCAV58006740 | 931GiB (1TB) | | 2 | ATA Disk | GB0160CAABV | | 2 | scsi@1:0.0.0 | /dev/sdc | HPG1 | 5RX795WB | 149GiB (160GB) | | 3 | ATA Disk | WDC WD10EARS-00Y | Western Digital | 3 | scsi@1:0.1.0 | /dev/sdd | 0A80 | WD-WCAV58065900 | 931GiB (1TB) | ## Netzeinbindung Der Server ist über eine Gigabit-Ethernetschnittstelle mit dem lokalen Netz der Starship Factory verbunden. Der primäre Hostname ist ***cloud.lab.starship-factory.ch***. Es sind die folgenden DNS-Einträge gesetzt: | Netzwerk | Hostnamen | IPv4 | Bemerkung | | -------- | ------------------------------------------------------------ | ------------- | ---------------------------- | | LAN | cloud.lab.starship-factory.ch
ldab.lab.starship-factory.chsind | 100.64.1.200 | Interne Adresses des Servers | | WAN | cloud.lab.starship-factory.ch
ldap.lap.starship-factory.ch | 5.226.148.123 | Externe Adresse des Routers | Auf dem WAN-Router sind für IPv4 die folgenden Port-Weiterleitungen eingerichtet: | Dienst | Port WAN-Router | Port Cloud-Server | | ------ | --------------- | ----------------- | | http | 80 | 80 | | https | 443 | 443 | | ssh | 49160 | 22 | ## Grundkonfiguration Als Betriebssystem kommt *GNU/Linux* zum Einsatz. Als Distribution wird [OpenMediaVault](https://www.openmediavault.org/), welches auf *Debian* basiert, verwendet. Soweit nicht anders angegeben, wurden zusätzliche Pakete/Software stets aus dem offiziellen Debian-Repository mittels *apt* installiert. Aktuell sind die folgenden Komponenten zusätzlich installiert: * System Security Services Daemon * Uncomplicated Firewall * Fail2Ban * Let's encrypt Certbot * Docker ### Volumen und Partitionierung Die Laufwerke sind wie folgt partitioniert und in das Dateisystem eingebunden: | # | Logical name | Partition | Mountpoint | Bemerkungen | | - | ------------ | --------- | ------------------------------------ | ------------ | | 0 | sda | sda1 | /boot | | | | | sda2 | | | | | | md0 | | RAID0 device | | | | md0p1 | [SWAP] | | | | | md0p2 | / | | | 1 | sdb | md1 | /srv/dev-disk-by-id-md-name-debian-1 | RAID0 device | | 2 | sdc | sdc1 | /boot | Not used | | | | sdc2 | | | | | | md0 | | RAID0 device | | | | md0p1 | [SWAP] | | | | | md0p2 | / | | | 3 | sdd | md1 | /srv/dev-disk-by-id-md-name-debian-1 | RAID0 device | Die RAID-Speicher sind als Soft-Raids mittels *md* konfiguriert. Der Bootloader *Grub* ist im MBR des Laufwerks *sda* installiert. Er ist so konfiguriert, dass er aus der Partition *sda1* bootet. Das Verzeichnis */var/lib/docker/volumes* wurde mittels eines symbolischen Links vom Wurzeldateisystem auf *md0p2* in das Verzeichnis */srv/dev-disk-by-id-md-name-debian-1/docker/volumes* auf der grösseren Datenpartition *md1* verlagert. ### Openmediavault Die Web-Konfigurationsoberfläche von *OpenMediaVault* ist über die folgenden Adressen zu erreichen: | Protokoll | URL | | --------- | --------------------- | | http | http://:5000/ | | https | https://:5001/ | Die Anfrage via *http* wird automatisch auf *https* umgeleitet. Bisher wurde nur ein selbstgezeichnetes Zertifikat hinterlegt, so dass beim ersten Zugriff eine Ausnahmeregel eingerichtet werden muss. Die Anmeldung erfolgt mittels des Benutzers *admin* oder eines anderen zuvor angelegten Benutzerkontos. Die System-Administratoren wurden der Unix-Gruppe *openmediavault-admin* hinzugefügt, um ihnen administrative Rechte innerhalb der Konfigurationsoberfläche zu gewähren. Die Konfiguration von OMV wurde mittels der folgenden Einträge in der Systemkonfigurationsdatei angepasst: **/etc/default/openmediavault** ... OMV_NFSD_MOUNTDOPTS="-p 32767" Der Eintrag für *OMV_NFSD_MOUNTDOPTS* zwingt den *NFS-mountd* auf einen festen Port, so dass eine statische Firewall-Regel angelegt werden kann. Informationen zur erweiterten Konfiguration können dem [OMV-Handbuch](https://openmediavault.readthedocs.io/en/5.x/various/advset.html) entnommen werden. Die restliche Konfiguration wurde mittels der Konfigurations-Oberfläche vorgenommen und ist im Folgenden nicht weiter dokumentiert. ### Sicherheit Das Authentifizierungssystem ist um den *System Security Services Demon (sssd)* erweitert, um die Authentifizierung gegen *LDAP* zu ermöglichen. Die LDAP-Benutzer werden lokal zwischengespeichert, so dass die Autentifizierung auch im Fall eines Ausfalls des LDAP-Servers weiterhin möglich ist. **/etc/sssd/sssd.conf** [sssd] config_file_version = 2 services = nss, pam domains = starship-factory.ch #debug = 7 [nss] filter_groups = root filter_users = root #debug = 7 [pam] [domain/starship-factory.ch] # SSSD can resolve user information from a number of different sources # such as LDAP, local files, and Active Directory. This option sets # the domain's source of identity information. id_provider = ldap # As with identity providers, SSSD can authenticate in a variety of ways. # By default, SSSD will use the value of id_provider. #auth_provider = ldap # The access provider controls the source for determining who is allowed # to access the system. Even if a user successfully authenticates, if they # don't meet the criteria provider by the access provider, they will be # denied access. access_provider = ldap # The verbosity of this domains log file. #debug = 7 # Enumeration is discouraged for performance reasons. enumerate = true # The URI(s) of the directory server(s) used by this domain. ldap_uri = ldaps://ldap.lab.starship-factory.ch # The LDAP search base you want SSSD to use when looking # for entries. There are options for search bases for various types # of searches, such as users. Read the sssd-ldap man page for details. ldap_search_base = dc=starship-factory,dc=ch # The DN used to search your directory with. It must have read access to # everything your system needs. ldap_default_bind_dn = cn=omv-ldap-user,ou=system-users,dc=starship-factory,dc=ch # The password of the bind DN. ldap_default_authtok = # This enables or disables credential caching. I.e. after successfully # authenticating a user, the credentials will be stored locally. If the # domain is unavailable, users will still be able to login using the # cached information. cache_credentials = true # By default, the credential cache never expires. If you want sssd to # remove cached credentials, this option will cause them to expire # after the number of days it is set to. #account_cache_expiration = 0 # These define the criteria the access provider uses to control who # is allowed to login. In this case, any user that matches the # LDAP filter in this example will be allowed access. Any entry # that has an objectClass of posixAccount will be allowed access. ldap_access_order = filter ldap_access_filter = (objectClass=posixAccount) # The file containing CA certificates you want sssd to trust. ldap_tls_cacert = /etc/ssl/certs/ca-certificates.crt # The TLS ciphers you wish to use. SSSD uses OpenSSL style cipher # suites #ldap_tls_cipher_suite = HIGH # This defines how sssd will handle server certificates. Demand means # that we are requiring the host portion of the URI to match the # certificate's subject or an SAN, the current time is within the valid # times on the certificate, and that it's signing chain ends with a CA # in the file defined by ldap_tls_cacert. ldap_tls_reqcert = demand # Use this if users are being logged in at /. # This example specifies /home/DOMAIN-FQDN/user as $HOME. Use with pam_mkhomedir.so override_homedir = /home/%u # Always use bash shell. This is required since Synology diskstation # returns "sh" as the default setting and the shell cannot be modified # in the web interface. override_shell = /bin/bash Um die Sicherheit zu erhöhen, ist die *Uncomplicated Firewall (ufw)* installiert und aktiviert. Die *default policy* ist *deny*. Die folgenden Ports bzw. Anwendungen sind für den externen Zugriff freigegeben: ```3 To Action From -- ------ ---- Samba ALLOW Anywhere 21/tcp ALLOW Anywhere 5001 ALLOW Anywhere 5000 ALLOW Anywhere 32767 ALLOW Anywhere NFS ALLOW Anywhere SSH ALLOW Anywhere WWW ALLOW Anywhere WWW Secure ALLOW Anywhere LDAP ALLOW Anywhere LDAPS ALLOW Anywhere Samba (v6) ALLOW Anywhere (v6) 21/tcp (v6) ALLOW Anywhere (v6) 5001 (v6) ALLOW Anywhere (v6) 5000 (v6) ALLOW Anywhere (v6) 32767 (v6) ALLOW Anywhere (v6) NFS (v6) ALLOW Anywhere (v6) SSH (v6) ALLOW Anywhere (v6) WWW (v6) ALLOW Anywhere (v6) WWW Secure (v6) ALLOW Anywhere (v6) LDAP (v6) ALLOW Anywhere (v6) LDAPS (v6) ALLOW Anywhere (v6) ``` Der Port 21 ist für den FTP-Dienst geöffnet, die Ports 5000 und 5001 für die OMV-Konfigurationsoberfläche (*http* und *https*). Der Port 32767 wird für die Verbindung zum NFS-mountd benötigt. Weiterhin ist das Paket *fail2ban* installiert, um *"Brute force"*-Angriffen vorzubeugen. Die Möglichkeit der Anmeldung von *root* mittels *SSH* wurde deaktiviert. ### Reverse Proxy Auf dem Cloud-Server ist ein *Nginx*-Web-Server installiert und als inverser Proxy konfiguriert. Über diesen werden externe *http*-Anfragen an die Docker-Container weitergeleitet und gegebenenfalls verschlüsselt (*https*). Konkret ermöglicht der Reverse Proxy den Zugriff auf die *NextCloud*-Instanz sowie die Konfigurationsoberflächen für den *LDAP*-Server. Die Konfiguration ist in der Datei */etc/nginx/sites-available/nextcloud-reverse-proxy* hinterlegt. Die Konfiguration ist durch Verlinkung in das Verzeichnis */etc/nginx/sites-enabled* aktiviert. **/etc/nginx/sites-available/nextcloud-reverse-proxy** server { listen 80; server_name cloud.lab.starship-factory.ch ldap.lab.starship-factory.ch; if ($host = ldap.lab.starship-factory.ch) { return 301 https://$host$request_uri; } # managed by Certbot if ($host = cloud.lab.starship-factory.ch) { return 301 https://$host$request_uri; } # managed by Certbot return 404; # managed by Certbot } server { listen 443 ssl; server_name cloud.lab.starship-factory.ch; # Apply letsencrypt nginx ssl configuration include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot # If you use Lets Encrypt, you should just need to change the domain. # Otherwise, change this to the path to full path to your domains public certificate file. ssl_certificate /etc/letsencrypt/live/cloud.lab.starship-factory.ch/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/cloud.lab.starship-factory.ch/privkey.pem; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot # Log Location. the Nginx User must have R/W permissions. Usually by ownership. access_log /var/log/nginx/access.log; # Allow up to 512M upload size client_max_body_size 512M; location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://cloud.lab.starship-factory.ch:8080; proxy_read_timeout 30; } } server { listen 443 ssl; server_name ldap.lab.starship-factory.ch; # Apply letsencrypt nginx ssl configuration include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot # If you use Lets Encrypt, you should just need to change the domain. # Otherwise, change this to the path to full path to your domains public certificate file. ssl_certificate /etc/letsencrypt/live/cloud.lab.starship-factory.ch/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/cloud.lab.starship-factory.ch/privkey.pem; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot # Log Location. the Nginx User must have R/W permissions. Usually by ownership. access_log /var/log/nginx/access.log; # Forward to LDAP account manager location / { # Allow access from local network, but deny rest of the world. allow 100.64.0.0/16; deny all; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://cloud.lab.starship-factory.ch:8100/; proxy_read_timeout 30; } # Forward to phpldapadmin location /phpldapadmin/ { # Allow access from local network, but deny rest of the world. allow 100.64.0.0/16; deny all; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://cloud.lab.starship-factory.ch:8090/; proxy_read_timeout 30; } } ***Hinweis:*** Aus Sicherheitsgründen wurde der Zugriff auf die LAP-Konfigurationsoberflächen auf das lokale Netzwerk begrenzt. Die SSL-Zertifikate wurden mittels des Let's Encrypt *certbot* erstellt und werden regelmässig erneuert. Hier zu ist das folgende Skript hinterlegt: **/etc/cron.monthly/renew-certificates** #!/bin/bash # Renew all let's encrypt certificates /usr/bin/certbot renew -n ## Backup Zur Sicherung aller Daten wurde eine externe Sicherung mittels *BackupPC* eingerichtet. Die Sicherung erfolgt auf dem Backup-Server *rueblitorte.de*, welcher sich physikalisch in D-79576 Weil am Rhein, Deutschland befindet. Der Server wird von Bernd Kalbfuss (aka Langweiler) betrieben. Für den Zugriff mittels SSH wurde der Benutzer *backuppc* angelegt und der Gruppe *ssh* hinzugefügt. Die Authentifizierung erfolgt mittels eines Schlüsselpaares. Dem Benutzer wurden beschränkte sudo-Rechte eingeräumt: **/etc/sudoers** ... # Allow backuppc user to run rsync with root privileges backuppc ALL=(root) NOPASSWD: /usr/bin/rsync, /usr/local/bin/backup-mode, /usr/local/bin/production-mode ... Um den Rechner in einen für das Backup sicheren Modus zu bringen und im Anschluss wieder zu reaktivieren, wurden zwei Skripte erstellt. Diese werden von BackupPC vor und nach dem Backup ausgeführt. **/usr/local/bin/backup-mode** #!/bin/bash echo "Switching host to backup mode." # Pause critical docker containers /usr/bin/docker pause nextcloud /usr/bin/docker pause database **/usr/local/bin/production-mode** ```3 #!/bin/bash echo "Switching host to production mode." # Unpause critical docker containers /usr/bin/docker unpause database /usr/bin/docker unpause nextcloud ``` Um zu verhindern, dass der Server nach einem fehlgeschlagenen/abgebrochenen Backup im Backup-Modus verbleibt, wurde das *crontab* um den folgenden Eintrag erweitert: **/etc/crontab** ... # Unpause docker containers in case of failed backup 00 5 * * * root /usr/local/bin/production-mode >/dev/null 2>&1 ... ## LDAP Zur Benutzerverwaltung und Authentifizierung wurde auf dem Cloud-Server ein *OpenLDAP*-Server sowie die Konfigurationsoberflächen *LDAP Account Manager* und *phpldapadmin* installiert. Der LDAP-Server kann via *ldap* über der Port 389 unverschlüsselt sowie via *ldaps* über den Port 636 verschlüsselt angesprochen werden. *STARTTLS* auf dem Port 389 wurde bisher **nicht** konfiguriert. Die Konfigurationsoberfläche *LDAP Account Manager* ist über den Reverse Proxy unter der Adresse https://ldap.lab.starship-factory.ch/ zu erreichen, die Konfigurationsoberfläche *phpldapadmin* unter der der Adresse https://ldap.lab.starship-factory.ch/phpldapadmin/. Im Normallfall sollte die Konfigurationsoberfläche *LDAP Account Manager* verwendet werden, da diese einen wesentlich höheren Komfort bietet. Für Spezialfälle (z.B. die Verwaltung der Gruppen für die Administratoren und System-Benutzer) muss phpldapadmin verwendet werden, da der LDAP Account Manager entsprechende Funktionen in der freien Version nicht unterstützt. ### Docker Der *OpenLDAP*-Server sowie die Administrationsoberflächen *LDAP Account Manager* und *phpldapadmin* wurden mittels *Docker* eingerichtet. Konkret wurden hierfür die folgenden Abbilder von *hub.docker.com* mittels `docker pull` bezogen: | Repository | Tag | Image ID | Size | | ---------------------- | ------ | ------------ | ----- | | osixia/phpldapadmin | latest | dbb580facde3 | 309MB | | osixia/openldap | latest | 31d1d6e16394 | 257MB | | ldapaccountmanager/lam | stable | 8b4da396b5eb | 384MB | Die Container wurden mittels `docker-compose` anhand der folgenden Datei erstellt: **docker-compose.yml** version: '3' volumes: db: conf: certs: admin: lam: services: ldap: image: osixia/openldap container_name: openldap restart: always ports: - "389:389" - "636:636" volumes: - db:/var/lib/ldap - conf:/etc/ldap - certs:/container/service/slapd/assets/certs environment: - LDAP_ORGANISATION=starship-factory - LDAP_DOMAIN=starship-factory.ch - LDAP_ADMIN_PASSWORD= - LDAP_TLS_CRT_FILENAME=cert.pem - LDAP_TLS_KEY_FILENAME=privkey.pem - LDAP_TLS_CA_CRT_FILENAME=chain.pem - LDAP_TLS_VERIFY_CLIENT=try phpldapamin: image: osixia/phpldapadmin container_name: phpldapadmin restart: always volumes: - adminhinzufügt:/var/www/phpldapadmin links: - ldap:ldap-host ports: - "8090:80" - "8091:443" environment: - PHPLDAPADMIN_LDAP_HOSTS=ldap-host - PHPLDAPADMIN_HTTPS=false lam: image: ldapaccountmanager/lam:stable container_name: lam restart: always volumes: - lam:/var/lib/ldap-account-manager/config ports: - "8100:80" environment: - LAM_SKIP_PRECONFIGURE=false - LDAP_DOMAIN=starship-factory.ch - LDAP_ORGANISATION="Starship Factory" - LDAP_BASE_DN=dc=starship-factory,dc=ch - LDAP_USERS_DN=ou=users,dc=starship-factory,dc=ch - LDAP_GROUPS_DN=ou=groups,dc=starship-factory,dc=ch - LDAP_SERVER=ldaps://ldap.lab.starship-factory.ch:636 - LAM_DISABLE_TLS_CHECK=false - LDAP_USER=cn=admin,dc=starship-factory,dc=ch - LAM_PASSWORD= - LAM_LANG=de_DE ***Hinweis zu ldap:*** Wird der OpenLDAP-Container mittels `docker-compose down` und im Anschluss `docker-compose up -d` erneut erstellt, so kommt es zu einer Fehlermeldung, da die Datei *ldap.conf* im Volumen *ldap_conf* fehlt. Es besteht lediglich ein symbolischer Link auf eine Datei, welche nicht mehr existiert. Der LDAP-Server startet in diesem Fall nicht, wie mittels `docker logs -f openldap` nachvollzogen werden kann. Um den Fehler zu beheben, muss die Datei aus dem Ordner *ldap_conf.bak* ergänzt werden. ***Hinweis zu lam***: Die Option "LAM_SKIP_PRECONFIGURE=false" sollte lediglich bei der ersten Erstellung des Docker-Containers deaktiviert sein. Danach sollte sie auf "true" gesetzt werden. Ansonsten gehen die in der Web-Oberfläche konfigurierten Einstellungen wieder verloren. ### Konfiguration Um die mit dem Let's Encrypt *certbot* erstellten Zertifikate dem LDAP-Server verfügbar zu machen, wurde das Skript `renew-certificates` wie erfolgt erweitert: **/etc/cron.monthly/renew-certificates** ```33 #!/bin/bash LDAP_CONTAINER=openldap SRC_PATH=/etc/letsencrypt/live/cloud.lab.starship-factory.ch DST_PATH=/container/service/slapd/assets/certs ... # Copy certificates to openldap docker container docker cp -L ${SRC_PATH}/cert.pem ${LDAP_CONTAINER}:${DST_PATH} docker cp -L ${SRC_PATH}/privkey.pem ${LDAP_CONTAINER}:${DST_PATH} docker cp -L ${SRC_PATH}/chain.pem ${LDAP_CONTAINER}:${DST_PATH} # Restart openldap docker container docker restart ${LDAP_CONTAINER} ``` Weiterhin wurden in der Konfiguration des *OpenLDAP*-Servers der Gruppe *cn=ldap-admins,ou=groups,dc=starship-factory,dc=ch* vollständige Schreibrechte eingeräumt sowie der Gruppe *cn=ldap-auth-users,ou=groups,dc=starship-factory,dc=ch* vollständge Leserechte. **openldap:/etc/ldap/slapd.d/cn=config/olcDatabase=\{1\}mdb.ldif** ... olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage by * break olcAccess: {1}to attrs=userPassword,shadowLastChange,mail,labeledURI by self write by dn="cn=admin,dc=example,dc=org" write by group.exact="cn=ldap-admins,ou=groups,dc=starship-factory,dc=ch" write by anonymous auth by * none olcAccess: {2}to * by dn="cn=admin,dc=example,dc=org" write by group.exact="cn=ldap-admins,ou=groups,dc=starship-factory,dc=ch" write by group.exact="cn=ldap-auth-users,ou=groups,dc=starship-factory,dc=ch" read by self read by * none ... Die erste Gruppe dient zur Verwaltung der Administratoren, die zweite Gruppe zur Anlage von System-Nutzern, welche zur Authentifizierung gegen den LDAP-Server benötigt werden. ***Hinweis:*** Die Datei *olcDatabase=\{1\}mdb.ldif* befindet sich im Docker-Volumen *ldap_conf*, welches im Verzeichnis */srv/dev-disk-by-id-md-name-debian-1/docker/volumes/ldap_conf/* gespeichert ist. Die Modifikation der *OpenLDAP*-Konfiguration sollte im Normalfall mittels des Befehls `ldapmodify` erfolgen. Da alle Versuche, die Zugriffsrechte mittels `ldapmodify` zu manipulieren scheiterten, wurde letztendlich der Weg der direkten Manipulation der Konfigurationsdatei gewählt. Die Konfiguration von *phpldapadmin* wurde mit den folgenden Einträgen ergänzt, um sicherzustellen, dass der sichere Hash-Algorithmus *SSHA* verwendet wird und die Nummerierung der Benztzer und Gruppen im Bereich >10000 liegt. **phpldapadmin:/var/www/phpldapadmin/config/config.php** ... /* Default password hashing algorithm. One of md5, ssha, sha, md5crpyt, smd5, blowfish, crypt or leave blank for now default algorithm. */ $servers->setValue('appearance','pla_password_hash','ssha'); /* This feature allows phpLDAPadmin to automatically determine the next available uidNumber for a new entry. */ $servers->setValue('auto_number','enable',true); /* The minimum number to use when searching for the next available number (only when 'search' is used for auto_number. */ $servers->setValue('auto_number','min',array('uidNumber'=>10000,'gidNumber'=>10000)); Die erweiterte Konfiguration des *LDAP Account Manager* wurde mittels der Web-Oberfläche durchgeführt und ist im Folgenden nicht weiter beschrieben. ## NextCloud Zum Austausch von Dateien und Informationen zwischen den Mitgliedern der Starship Factory wurde auf dem Cloud-Server eine *NextCloud*-Intanz installiert. Die *NextCloud* ist über den Reverse Proxy unter der Adresse https://cloud.lab.starship-factory.ch/ zu erreichen. ### Docker Die *NextCloud* wurde mittels *Docker* eingerichtet. Konkret wurden hierfür die folgenden Abbilder von *hub.docker.com* mittels `docker pull` bezogen: | Repository | Tag | Image ID | Size | | ---------- | ------ | ------------ | ----- | | nextcloud | latest | a7a0780a23a7 | 835MB | | mariadb | latest | e27cf5bc24fe | 401MB | Die Container wurden mittels `docker-compose` anhand der folgenden Datei erstellt: **docker-compose.yml** version: '3' networks: nextcloud: volumes: nextcloud: db: services: db: image: mariadb container_name: database restart: always command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW volumes: - db:/var/lib/mysql networks: - nextcloud environment: - MYSQL_ROOT_PASSWORD= - MYSQL_PASSWORD= - MYSQL_DATABASE=nextcloud - MYSQL_USER= app: image: nextcloud container_name: nextcloud restart: always ports: - 8080:80 links: - db volumes: - nextcloud:/var/www/html networks: - nextcloud environment: - MYSQL_PASSWORD= - MYSQL_DATABASE=nextcloud - MYSQL_USER=nextcloud - MYSQL_HOST=db - NEXTCLOUD_TRUSTED_DOMAINS=cloud.lab.starship-factory.ch ### Konfiguration Damit integrierte Apps, insbesondere *OnlyOffice* in Kombination mit dem inversen Proxy und der Weiterleitung von *http* auf *https* funktionieren, wurde in der Datei *config.php* der Eintrag *overwrite.cli.url* auf '' und die Einstellung *overwriteprotocol* auf 'https' gesetzt. Außerdem wurde der vollständige Name des Hosts unter *trusted_domains* eingetragen. **nextcloud:/var/www/html/config/config.php** ... 'trusted_domains' => array ( 0 => 'cloud.lab.starship-factory.ch', ), 'overwrite.cli.url' => '', 'overwriteprotocol' => 'https', ... ***Hinweis:*** Die Datei *config.php* befindet sich im Docker-Volumen *nextcloud_nextcloud*, welches im Verzeichnis */srv/dev-disk-by-id-md-name-debian-1/docker/volumes/nextcloud_nextcloud/* gespeichert ist. Das *crontab* wurde um den folgenden Eintrag erweitert, damit Hintegrundaufgaben in der *NextCloud* zuverlässig ausgeführt werden: **/etc/crontab** ... # Execute NextCloud background jobs in docker container */5 * * * * root /usr/bin/docker exec nextcloud runuser -u www-data -- php -f /var/www/html/cron.php >/dev/null 2>&1 ... ### Authenitifizierung via LDAP In den Einstellungen unter "LDAP / AD Integration" wurde die Authentifizierung gegen den lokal installierten *LDAP*-Server aktiviert: [[!img ldap-config.png align="left" width="800" alt="LDAP configuration screenshot"]] Der System-Benutzer *nextcloud-ldap-user* wurde zuvor im LDAP-Verzeichnis angelegt und in die Gruppe *ldap-admins* aufgenommen, um ihm Schreibrechte auf das LDAP-Verzeichnis zu gewähren. ***Hinweis***: Auf Grund einer Beschränkung in der LDAP-Implementierung in Nextcloud ist es aktuell notwendig, dass der LDAP-Benutzer Schreibrechte auf das Verzeichnis hat, um Benutzern das Ändern ihrer Passwörter zu ermöglichen. ***Warnung:*** Eine inkorrekte LDAP-Konfiguration - insbesondere die unsachgemäße Manipulation einer existierenden Konfiguration - kann dazu führen, dass die NextCloud-Instanz nicht mehr startet. ### Apps Die folgenden Apps wurden in NextCloud deaktiviert, da sie mit der Anwendung OnlyOffice kollidieren: * Collabora Online - Built-in CODE Server * Collabora Online Die folgenden Anwendungen wurden zusätzlich installiert und aktiviert: * Community Document Server * ONLYOFFICE * Group Folders * Decks * Tasks * Circles * Announcements * Notes ## Portainer Um die Verwaltung und Pflege der installierten Docker-Container zu erleichtern, wurde zusätzlich ein Portainer-Server in der Community Edition installiert. Die Portainer-Web-Oberfläche ist unter der Adresse https://portainer.lab.starship-factory.ch/ zu erreichen. Aus Sicherheitsgründen wurde der Zugriff auf das lokale Netzwerk beschränkt. ### Docker Der Portainer-Server wurde ebenfalls als Docker-Container gemäß der offiziellen Installationsanleitung installiert. Zuerst wurde ein Volumen zur permanenten Datenspeicherung erstellt: sudo docker volume create portainer_data Im Anschluss wurde der Container selbst gestartet: sudo docker run -d -p 9000:9000 --name portainer \ --restart=always \ -v /var/run/docker.sock:/var/run/docker.sock \ -v portainer_data:/data \ portainer/portainer-ce:latest Abweichend von der offiziellen Installationsanleitung wurde lediglich der unverschlüsselte *http*-Port 9000 weitergeleitet. Der Zugriff via *https* wird duch den Reverse Proxy ermöglicht. ### Reverse Proxy Der Zugriff auf die Portainer-Web-Oberfläche wird wie bei der NextCloud durch den Nginx-Web-Server vermittelt, der als Reverse Proxy konfiguriert wude. Über diesen werden externe http-Anfragen an die Docker-Container weitergeleitet und gegebenenfalls verschlüsselt (*https*). Es werden die selben SSL-Zertifikate wie für den Cloud-Server verwendet. Aus Sicherheitsgründen wurde der Zugriff auf Portainer auf das lokale Netzwerk begrenzt. Die Konfiguration ist in der Datei */etc/nginx/sites-available/portainer* hinterlegt. Die Konfiguration wurde durch Verlinkung in das Verzeichnis */etc/nginx/sites-enabled* aktiviert. **/etc/nginx/sites-available/portainer** server { listen 80; server_name portainer.lab.starship-factory.ch; if ($host = portainer.lab.starship-factory.ch) { return 301 https://$host$request_uri; } # managed by Certbot return 404; # managed by Certbot } server { listen 443 ssl; server_name portainer.lab.starship-factory.ch; # Apply letsencrypt nginx ssl configuration include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot # If you use Lets Encrypt, you should just need to change the domain. # Otherwise, change this to the path to full path to your domains public certificate file. ssl_certificate /etc/letsencrypt/live/cloud.lab.starship-factory.ch/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/cloud.lab.starship-factory.ch/privkey.pem; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot # Log Location. the Nginx User must have R/W permissions. Usually by ownership. access_log /var/log/nginx/access.log; # Forward to NextCloud server location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://cloud.lab.starship-factory.ch:9000/; proxy_read_timeout 30; } ### Authenifizierung via LDAP Um die Authentifizierung mitels LDAP zu ermöglichen, wurde ein dedizierter System-Benutzer *portainer-ldap-user* erstellt. Der System-Benutzer wurde in die Gruppe *ldap-auth-users* aufgenommen, um ihm Suchrechte auf das LDAP-Verzeichnis zu gewähren. Die LDAP-Authentifierzung in Portainer wurde entsprechend dem folgenden Bildschirmfoto in Portainer eingerichtet. [[!img portainer-ldap-config1.png align="left" alt="Portainer LDAP configuration screenshot 1"]] [[!img portainer-ldap-config2.png align="left" alt="Portainer LDAP configuration screenshot 2"]] ***Hinweis:*** Neue Benutzer erscheinen erst nach dem ersten erfolgreichen Login in der Portainer-Nutzerverwaltung. Sie haben zu Beginn noch keine Rechte. Diese müssen ihnen im Anschluss explizit durch einen Administrator hinzugefügt werden.