Sie sind auf Seite 1von 12

+ Neuen Server einrichten

Unsere Server mieten wir für gewöhnlich bei Netcup und nutzten Debian als Betriebssystem. Basics
Sys-Admins
SSH-Config
Firewall
Basics Docker
Traefik und Portainer
Hier einpaar grundlegende Dinge die die Nutzung und Verwaltung des Server erleichtern. installieren (single node)
Als root auf den Server per SSH einloggen. Traefik eigene Zertifikate
Traefik und Portainer
installieren (multi node)
nano setup.sh
Cluster initialisieren
# Inhalt aus dem Code-Block weiter unten einfügen
NFS einrichten
chmod +x setup.sh
NFS peer
./setup.sh hinzufügen
Traefik einrichten
setup.sh Failover IP configurieren
Impressum und robots.txt
#!/bin/bash Gitlab-Runner
Mail-Server
apt-get update Backup
apt-get upgrade
apt-get dist-upgrade

apt-get install -y sudo qemu-guest-agent htop iotop jnettop nano rsync ufw

apt-get autoremove
apt-get autoclean

fallocate -l 5G /root/bigfile
fallocate -l 5G /root/bigfile2

useradd -m -s /bin/bash -c "k.klockgether@28apps.de" kklockgether


useradd -m -s /bin/bash -c "t.hofer@28apps.de" thofer
useradd -m -s /bin/bash devops28

usermod -aG sudo kklockgether


usermod -aG sudo thofer

mkdir /home/kklockgether/.ssh
touch /home/kklockgether/.ssh/authorized_keys
chown -R kklockgether:kklockgether /home/kklockgether/.ssh/
chmod -R 700 /home/kklockgether/.ssh/

mkdir /home/thofer/.ssh
touch /home/thofer/.ssh/authorized_keys
chown -R thofer:thofer /home/thofer/.ssh/
chmod -R 700 /home/thofer/.ssh/

mkdir /home/devops28/.ssh
touch /home/devops28/.ssh/authorized_keys
chown -R devops28:devops28 /home/devops28/.ssh/
chmod -R 700 /home/devops28/.ssh/

Folgendes manuell ausführen

setup.sh

# User-Passwörter vergeben
passwd kklockgether
passwd thofer
passwd devops28

# Public SSH-Keys hinterlegen


nano /home/kklockgether/.ssh/authorized_keys
nano /home/thofer/.ssh/authorized_keys
nano /home/devops28/.ssh/authorized_keys

# Hostnamen ändern
hostnamectl set-hostname 28backup
# Neuen hostnamen eintragen
nano /etc/hosts
# hinzufügen: 127.0.1.1 28backup
# Falls 127.0.1.1 bereits existiert, einfach den Servernamen hinten dran hängen

# Für Server mit vielen Services; Limit der geöffneten Dateien erhöhen
mkdir /etc/systemd/system.conf.d/
nano /etc/systemd/system.conf.d/limits.conf
# server neu starten um limits zu übernehmen

/etc/systemd/system.conf.d/limits.conf

# https://unix.stackexchange.com/a/443467/470542
# 1048576 ist der maximal mögliche Wert für Linux. https://stackoverflow.com/a/

[Manager]
DefaultLimitNOFILE=1048576:2097152
#DefaultLimitNPROC=262144:524288

Sys-Admins

User Public SSH keys

kklockgether

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDaJV/UIorYEq9mZEjPNTm19R8ylWb

thofer

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQClP5DAm8fl+q1i2YbYPR0wtUS5FIR

SSH-Config
Wichtige Anmerkung: Während der Einrichtung sollte man sich, ohne den Zugang zu testen NIEMALS
ausloggen. Ein zweites Terminal-Fenster sollte zum testen genutzt werden.
Soll der Server Software hosten und deployen, wird dies mit dem Benutzer devops28 Verwaltet.

Jeder Sys-Admin der Firma soll einen eigenen Benutzer haben. Der Zugriff wird ausschließlich per SSH-Key
erlaubt. Passwörter müssen für den sudo-Zugriff dennoch stark gewählt werden (Passwortgenerator verwenden).

Server - SSH Config

# SSH Config anpassen. Passwort-Login deaktivieren


nano /etc/ssh/sshd_config

# Folgende Zeilen finden und den Wert auf no setzen


# ChallengeResponseAuthentication
# PasswordAuthentication
# UsePAM
# PermitRootLogin

# Port ändern in eine zufällige Zahl >= 1024 und <= 65353

# SSH-Einstellungen erneuern
systemctl reload ssh

Lokal - SSH Config

# SSH config schreiben


nano ~/.ssh/config

# Beispielhaft:
#Host devops28deploy2
# HOSTNAME 193.30.121.212
# PORT 61122 (Den Port der auf dem Server eingetragen worden ist hier eintrage
# USER devops28

# Zugriff testen
ssh servername

Firewall
Als Firewall nutzten wir ufw Uncomplicated Firewall.
Die Firewall niemals aktivieren ohne den korrekten SSH-Port zu erlauben!

# Adminzugriff
sudo -i

# Firewall installieren
apt-get install ufw

# SSH-Port hinzufügen (Portnummer zu der oben gewählten anpassen)


ufw allow 32859
ufw allow out 32859

# Eingehende Verbindungen Blockieren, Ausgehende erlauben


ufw default deny incoming
ufw default allow outgoing

# Für Webservices
ufw allow http
ufw allow https

# Firewall aktivieren (Sich wirklich sicher sein, dass der korrekte SSH-Port er
ufw enable

Docker
DNS-Eintrag setzten <servername>.28apps-software.de auf die IP vom Server zeigen
Docker installieren
Devops User anlegen und zur Docker-Gruppe hinzufügen

# Devops User anlegen und zur Docker-Gruppe hinzufügen (falls nicht bereits erf
adduser devops28
usermod -aG docker devops28
usermod -aG docker kklockgether
usermod -aG docker thofer

# SSH-Zugriff
mkdir /home/devops28/.ssh
nano /home/devops28/.ssh/authorized_keys
chown -R devops28:devops28 /home/devops28/.ssh
chmod -R 700 /home/devops28/.ssh/

# Docker beim systemstart starten


systemctl enable docker.service
systemctl enable containerd.service

# Docker swarm initialisieren


# (nicht bei cluster installation)
docker swarm init

# Cronjob zum docker aufräumen


crontab -e
# 12 3 * * 1 docker system prune -f
Traefik und Portainer installieren (single node)
Nun als user devops28 fortfahren.

su devops28

# Traefik Netzwerk erstellen


docker network create --driver overlay --scope swarm --subnet=10.10.0.0/16 trae

# Traefik Ordner erstellen


mkdir -p /home/devops28/docker/traefik/certs

Folgenden Inhalt in der Datei /home/devops28/docker/traefik/conf.yml speichern.

conf.yml

tls:
options:
default:
minVersion: VersionTLS12
cipherSuites:
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_AES_128_GCM_SHA256

Folgenden Inhalt in der Datei /home/devops28/docker/traefik/compose.yml speichern.

Dabei sollten einige Dinge angepasst werden


services.traefik.deploy.labels
traefik.http.routers.traefik.rule Url anpassen
traefik.http.middlewares.auth.basicauth.users Neues Passwort generieren und auf dem NAS unter
/Admin Area/Server Zugänge/Server Keepasses speichern

echo $(htpasswd -n 28apps) | sed -e s/\\$/\\$\\$/g

services.portainer.deploy.labels
traefik.http.routers.portainer.rule Url anpassen

compose.yml

version: '3.8'

services:
traefik:
image: traefik
command:
- --api=true
- --api.dashboard=true
- --providers.docker.endpoint=unix:///var/run/docker.sock
- --providers.docker.swarmMode=true
- --providers.docker.exposedbydefault=false
- --providers.docker.network=traefik-public
- --providers.file.filename=/conf.yml
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --entrypoints.websecure.http.tls.options=default@file
- --certificatesresolvers.letsencryptresolver.acme.httpchallenge=true
- --certificatesresolvers.letsencryptresolver.acme.httpchallenge.entrypoi
- --certificatesresolvers.letsencryptresolver.acme.email=srvadmin@28apps.
- --certificatesresolvers.letsencryptresolver.acme.storage=/letsencrypt/a
# - --log.level=DEBUG
ports:
- 80:80
- 443:443
volumes:
- ./certs:/letsencrypt
- ./conf.yml:/conf.yml
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- traefik-public
deploy:
placement:
constraints:
- node.role == manager
labels:
- traefik.enable=true
- traefik.http.routers.traefik.rule=Host(`traefik.dev.28apps-software.d
- traefik.http.routers.traefik.service=api@internal
- traefik.http.routers.traefik.entrypoints=websecure
- traefik.http.routers.traefik.tls.certresolver=letsencryptresolver
- traefik.http.services.traefik.loadbalancer.server.port=1337
# basic auth
- traefik.http.routers.traefik.middlewares=traefik-auth
- traefik.http.middlewares.traefik-auth.basicauth.users=28apps:$$apr1$$
# Redirect http to https
- traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)
- traefik.http.routers.http-catchall.priority=10
- traefik.http.routers.http-catchall.entrypoints=web
- traefik.http.routers.http-catchall.middlewares=redirect-to-https@dock
- traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=http

portainer-agent:
image: portainer/agent
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /var/lib/docker/volumes:/var/lib/docker/volumes
networks:
- agent_network
deploy:
mode: global
placement:
constraints: [node.platform.os == linux]

portainer:
image: portainer/portainer-ce
command: -H tcp://tasks.portainer-agent:9001 --tlsskipverify
volumes:
- portainer_data:/data
networks:
- traefik-public
- agent_network
deploy:
mode: replicated
replicas: 1
placement:
constraints: [node.role == manager]
labels:
- traefik.enable=true
- traefik.http.routers.portainer.rule=Host(`portainer.dev.28apps-softwa
- traefik.http.routers.portainer.entrypoints=websecure
- traefik.http.routers.portainer.tls.certresolver=letsencryptresolver
- traefik.http.services.portainer.loadbalancer.server.port=9000

volumes:
portainer_data:

networks:
traefik-public:
external: true
agent_network:

Deploy-Script hinzufügen

cd /home/devops28/docker/traefik
echo "docker stack deploy --prune -c compose.yml traefik" > deploy.sh
chmod +x deploy.sh
./deploy.sh

Traefik-Seite aufsuchen und Zugangsdaten testen.


Portainer-Seite aufuchen und Zugangsdaten setzten. Ebenfalls in der Keypass-Datei auf dem NAS speichern.

Traefik eigene Zertifikate


compose.yml

services:
traefik:
image: traefik
command:
- --api=true
- --api.dashboard=true
- --providers.docker
- --providers.docker.endpoint=unix:///var/run/docker.sock
- --providers.docker.swarmMode=true
- --providers.docker.exposedbydefault=false
- --providers.docker.network=traefik-public
- --providers.file.directory=/etc/traefik/dynamic
- --entrypoints.websecure.address=:443
# - --log.level=DEBUG
ports:
- 443:443
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./certs-traefik.yml:/etc/traefik/dynamic/certs-traefik.yaml:ro
- /etc/apache2/ssl/wildcard-dallmann-bau.de-mit-chain.crt:/certs/server.c
- /etc/apache2/ssl/wildcard-dallmann-bau.de.key:/certs/server.key:ro
networks:
- traefik-public
deploy:
placement:
constraints:
- node.role == manager
labels:
- traefik.enable=true
- traefik.http.routers.traefik.rule=Host(`traefik.dallmann-bau.de`)
- traefik.http.routers.traefik.service=api@internal
- traefik.http.routers.traefik.entrypoints=websecure
- traefik.http.routers.traefik.tls=true
# Basic Auth
- traefik.http.routers.traefik.middlewares=auth
- traefik.http.middlewares.auth.basicauth.users=28apps:$$2y$$05$$flzEg2

certs-traefik.yml

tls:
certificates:
- certFile: /certs/server.crt
keyFile: /certs/server.key

Traefik und Portainer installieren (multi node)


Tutorial: https://www.rockyourcode.com/traefik-2-docker-swarm-setup-with-docker-socket-proxy-and-more/

Cluster initialisieren

#manager
docker swarm init
sudo ufw allow from <ips aller server im cluster>
# Traefik Netzwerk erstellen
docker network create --driver overlay --subnet=10.10.0.0/16 --ingress --opt en

#alle
sudo ufw allow from <ips aller server im cluster>
#worker
docker swarm join --token <token> <ip>:2377

#manager
docker node promote <worker>
docker node ls

NFS einrichten

# all
nano /etc/hosts
# ips und hostsnames von allen servern im cluster hinzufügen

apt-get install glusterfs-server glusterfs-client


systemctl start glusterd
systemctl enable glusterd
ssh-keygen

gluster peer probe <alle anderen hosts im cluster>


gluster pool list

mkdir -p /gluster/traefik
mkdir -p /gluster/gitlab-runner

chown -R root:docker /mnt


chmod -R 775 /mnt
chmod g+s /mnt
mkdir -p /mnt/traefik/{certbot,portainer}

# manager
gluster volume create traefik replica 3 peaked1:/gluster/traefik peaked2:/glust
gluster volume start traefik
gluster volume create gitlab-runner replica 3 peaked1:/gluster/gitlab-runner pe
gluster volume start gitlab-runner

# all
# /etc/fstab ergänzen
localhost:/traefik /mnt/traefik glusterfs defaults,_netdev,noauto,x-systemd
localhost:/portainer /mnt/portainer glusterfs defaults,_netdev,noauto,x-sy

systemctl daemon-reload
systemctl restart remote-fs.target

NFS peer hinzufügen

# neuer node
apt-get install glusterfs-server glusterfs-client
systemctl start glusterd
systemctl enable glusterd
ssh-keygen

# alle nodes
# /etc/hosts ergänzen
# firewall ergänzen

# bestehender node
gluster peer probe <neuer node>
gluster pool list
gluster volume add-brick traefik replica 3 peaked3:/gluster/traefik force

# neuer node
mkdir -p /gluster/traefik
chown -R root:docker /mnt
chmod -R 775 /mnt
chmod g+s /mnt
mkdir -p /mnt/traefik/
# /etc/fstab ergänzen
localhost:/traefik /mnt/traefik glusterfs defaults,_n
localhost:/gitlab-runner /mnt/gitlab-runner glusterfs defaults,_n

systemctl daemon-reload
systemctl restart remote-fs.target

Traefik einrichten

manager

su devops28

# Traefik Netzwerk erstellen (weiter oben schon erstellt)


docker network create --driver overlay --subnet=10.10.0.0/16 --ingress --opt en

# network hosting the services that are routed by traefik


docker network create --subnet 10.13.0.0/16 --driver overlay --scope swarm --op

# Traefik Ordner erstellen


mkdir -p /home/devops28/docker/traefik
cd /home/devops28/docker/traefik

# Nachfolgende Dateien kopieren und anpassen

./deploy.sh

crontab -e
# einfügen
# 0 10 * * 1 /home/devops28/docker/traefik/renew-certs.sh

/home/devops28/docker/traefik/deploy.sh

docker stack deploy --prune -c compose.yml traefik

/home/devops28/docker/traefik/compose.yml

version: '3.8'

networks:
traefik-public:
external: true
portainer-agent:

services:

### TRAEFIK ###

traefik:
image: traefik:2.6
command:
- --api=true
- --api.dashboard=true
- --providers.docker
- --providers.docker.swarmMode=true
- --providers.docker.watch=true
- --providers.docker.endpoint=unix:///var/run/docker.sock
- --providers.docker.exposedbydefault=false
- --providers.docker.network=traefik-public
- --providers.file.directory=/conf
- --providers.file.watch=true
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
# - --log.level=DEBUG
deploy:
mode: global
restart_policy:
condition: on-failure
labels:
- traefik.enable=true
- traefik.http.routers.traefik.rule=Host(`traefik.peaked.me`)
- traefik.http.routers.traefik.service=api@internal
- traefik.http.routers.traefik.entrypoints=websecure
- traefik.http.routers.traefik.tls=true
- traefik.http.services.traefik.loadbalancer.server.port=80
# Basic Auth
- traefik.http.routers.traefik.middlewares=auth
- traefik.http.middlewares.auth.basicauth.users=28apps:$$apr1$$6rr5scst
# Redirect http to https
- traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)
- traefik.http.routers.http-catchall.entrypoints=web
- traefik.http.routers.http-catchall.middlewares=traefik-ratelimit,redi
- traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=http
# low priority to be able to be overwriten
- traefik.http.routers.http-catchall.priority=10
# rate limits
- traefik.http.middlewares.traefik-ratelimit.ratelimit.average=100
- traefik.http.middlewares.traefik-ratelimit.ratelimit.burst=50
ports:
- 80:80
- 443:443
volumes:
- /mnt/traefik/conf:/conf:ro
- /mnt/traefik/certbot:/certs:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- traefik-public

### CERTBOT ###


# Because Traefik is not able to share the acme.json between multiple instanc
certbot:
image: certbot/certbot
# shell with open stdin to keep container running
entrypoint: /bin/sh
stdin_open: true
volumes:
- /mnt/traefik/certbot:/etc/letsencrypt
networks:
- traefik-public
deploy:
replicas: 1
placement:
constraints:
- node.hostname==peaked1
labels:
- traefik.enable=true
# Catch letsencript http-challenge
- traefik.http.routers.certbot.rule=PathPrefix(`/.well-known/acme-chall
# Do not use ssl for this service
- traefik.http.routers.certbot.entrypoints=web
# Overwrite traefiks catchall router
- traefik.http.routers.certbot.priority=1000
- traefik.http.services.certbot.loadbalancer.server.port=80

### PORTAINER ###

portainer-agent:
image: portainer/agent
volumes:
- /var/run/docker.sock:/var/run/docker.sock
networks:
- portainer-agent
deploy:
mode: global
restart_policy:
condition: on-failure

portainer:
image: portainer/portainer-ce
command: -H tcp://tasks.portainer-agent:9001 --tlsskipverify
volumes:
- /mnt/traefik/portainer:/data
networks:
- traefik-public
- portainer-agent
deploy:
replicas: 1
restart_policy:
condition: on-failure
labels:
- traefik.enable=true
- traefik.http.routers.portainer.rule=Host(`portainer.peaked.me`)
- traefik.http.routers.portainer.entrypoints=websecure
- traefik.http.routers.portainer.tls=true
- traefik.http.services.portainer.loadbalancer.server.port=9000

/home/devops28/docker/traefik/renew-certs.sh

# *.peaked.me
containerCertbot=$(docker ps -f name=traefik_certbot --format {{.ID}})
docker exec $containerCertbot /etc/letsencrypt/renew.sh

# Restart traefik to reload certificates


docker service update --force traefik_traefik

/mnt/traefik/conf/traefik.yml
1
2 tls:
3 options:
4 default:
5 minVersion: VersionTLS13
6 tls12:
7 minVersion: VersionTLS12
8 cipherSuites:
9 - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
10 - TLS_AES_256_GCM_SHA384
11 - TLS_CHACHA20_POLY1305_SHA256
12 - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
13 - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
14 - TLS_AES_128_GCM_SHA256
15 stores:
16 default:
17 defaultCertificate:
18 certFile: /certs/live/peaked.me/fullchain.pem
19 keyFile: /certs/live/peaked.me/privkey.pem
20 certificates:
21 - certFile: /certs/live/peaked.me/fullchain.pem
keyFile: /certs/live/peaked.me/privkey.pem

/mnt/traefik/certbot/renew.sh
1
2 #!/bin/sh
3
4 # abort script on error
5 set -e
6 set -o pipefail
7
8 certbot certonly -n --agree-tos --standalone \
9 --max-log-backups 0 \
10 --email srvadmin@28apps.de \
11 --cert-name peaked.me \
12 -d peaked.me \
13 -d portainer.peaked.me \
14 -d traefik.peaked.me \
15 -d api.peaked.me \
-d office.peaked.me
Failover IP configurieren

ip addr add 188.68.44.99/32 dev eth0

Impressum und robots.txt


Mit einem einfach nginx liefern wir eine index.html mit dem 28Apps Impressum und eine robots.txt aus.
Der Traefik router hat eine hohe Priorität, damit der Pfad auf die robots.txt auch für andere router (=Services,
Router) ausgeliefert wird.

compose.yml
1
2 version: '3.8'
3
4 services:
5 nginx:
6 image: nginx:1-alpine
7 volumes:
8 - /home/devops28/docker/imprint/html:/usr/share/nginx/html:ro
9 networks:
10 - traefik-public
11 deploy:
12 mode: replicated
13 replicas: 1
14 labels:
15 - traefik.enable=true
16 - traefik.http.services.imprint-nginx.loadbalancer.server.port=80
17
18 - traefik.http.routers.imprint.rule=Host(`dev2.28apps-software.de
19 - traefik.http.routers.imprint.priority=1
20 - traefik.http.routers.imprint.entrypoints=websecure
21 - traefik.http.routers.imprint.tls.certresolver=letsencryptresolv
22
23 - traefik.http.routers.imprint-robots.rule=Path(`/robots.txt`) &&
24 - traefik.http.routers.imprint-robots.priority=10000
25 - traefik.http.routers.imprint-robots.entrypoints=websecure
26 - traefik.http.routers.imprint-robots.tls.certresolver=letsencryp
27
28 networks:
29 traefik-public:
external: true

deploy.sh

docker stack deploy -c compose.yml imprint

html/index.html

<html lang="de-DE" class="js">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name='robots' content='noindex,follow' />

<title>28dev2 Impressum</title>

<style>
body {
font-family: Arial;
}
</style>
</head>
<body>

<h2>Informationen gemäß § 6 TDG</h2>

<p>Nach der Neufassung des § 6 TDG (Teledienstegesetz) müssen Diensteanbiet


<p>28Apps Software GmbH<br>Martinistraße 43<br>28195 Bremen<br>Telefon:<spa

<p>Vertretungsberechtigte Geschäftsführer:</p>
<p>Emrah Gencer, Thomas Stehr</p>

<p>Amtsgericht Bremen unter HRB 31147 HB<br>Steuernummer: 246010008350<br>U

</body>
</html>

html/robots.txt

User-agent: *
Disallow: /

Gitlab-Runner
https://gitlab.28apps-software.de/28apps-docker/gitlab-runner

Mail-Server
Hier gibt es eine umfassende Anleitung für einen Mail-Server in Docker verpackt: https://gitlab.28apps-
software.de/28server/mail-server

Mail DNS Test: https://www.appmaildev.com/en/dkim


Mail Spam Test: https://www.mail-tester.com/

Backup
Wie man das Backup einrichtet ist im eigenem Abschnitt dokumentiert: 28backup

Das könnte Ihnen auch gefallen