Τι θα λέγατε να φιλοξενήσουμε σε έναν μόνο server, πολλαπλές ιστοσελίδες – web εφαρμογές, το καθένα με το δικό του domain, με SSL χωρίς να μπλέκουμε με ports και αλλαγές σε κάθε apache/nginx conf αλλά μόνο με έναν docker reverse proxy container;

Αν πάμε να στήσουμε σε έναν server όλες τις υπηρεσίες που έχουμε δει μέχρι στιγμής στα «Μαθήματα Docker«, θα ανακαλύψουμε ότι πρέπει να ανοίξουμε πολλές πόρτες στο router μας (ή στον VPS μας), αν θέλουμε να έχουμε πρόσβαση σε αυτές εκτός του τοπικού μας δικτύου. Αυτό από μόνο του είναι ένα τεράστιο πρόβλημα για την ασφάλεια του server μας, το οποίο πρέπει να αποφύγουμε και ένας εξαιρετικός τρόπος για να το κάνουμε αυτό είναι να στήσουμε έναν reverse proxy server. Σήμερα θα δούμε πώς γίνεται αυτό χρησιμοποιώντας το Traefik Proxy.

Πάμε να δούμε πώς λειτουργεί.

Όλη η σειρά οδηγών «Πως χρησιμοποιούμε το Docker βρίσκεται στον σύνδεσμο»:

– cerebrux.net/tag/docker-intro

Τι είναι ο reverse proxy server;

Μια γεύση του τι είναι proxy είχαμε δει όταν κάναμε Εγκατάσταση και ρύθμιση Squid Proxy Server.

Κάθε υπηρεσία που τρέχουμε στο Docker μας δίνει πρόσβαση μέσα από συγκεκριμένες πόρτες, οι οποίες για τις web εφαρμογές είναι συνήθως η 80 (http) και η 443 (https). Για παράδειγμα το Nextcloud χρειάζεται την 80 και την 443, το Home Assistant χρειάζεται την 8123 και το Portainer την 8000 και την 9000. Για να μην ανοίξουμε λοιπόν όλες αυτές τις πόρτες στο δίκτυό μας, μπορούμε να στήσουμε έναν reverse proxy server στην 80 και την 443, ο οποίος θα κατευθύνει τα αιτήματά μας στην υπηρεσία που ζητάμε.

Με απλά λόγια ο reverse proxy είναι ένας πορτιέρης! Στέκεται μπροστά στις ανοιχτές πόρτες, ελέγχει τα αιτήματα σύνδεσης και τα προωθεί στις σωστές υπηρεσίες. Αν για παράδειγμα γράψουμε στον browser ότι θέλουμε να μπούμε στο hass.doctorandoid.gr, ο proxy θα μας στείλει στο Home Assistant, ενώ αν ζητήσουμε το next.doctorandroid.gr, θα μας στείλει αντίστοιχα στο Nextcloud.

Οι σύγχρονοι reverse proxy όπως ο Traefik μπορούν επίσης να φέρουν πιστοποιητικά SSL για τις υπηρεσίες που εξυπηρετούν και να ασφαλίσουν τη σύνδεσή μας, ενώ διαθέτουν και load balancer σε περίπτωση που πολλοί χρήστες ζητήσουν ταυτόχρονα την ίδια υπηρεσία. Το καλύτερο από όλα όμως είναι ότι ειδικά ο Traefik Proxy είναι εύκολος στην εγκατάσταση και τη συντήρηση, κάτι που θα δούμε στην πράξη ευθύς αμέσως.

Προϋποθέσεις

Πριν ξεκινήσουμε όμως θα χρειαστεί να κάνουμε μία προεταοιμασία. Συγκεκριμένα θα πρέπει:

  1. να έχουμε εγκαταστήσει το Docker και το Docker Compose στο server μας,
  2. Αν ο server είναι πίσω από router πρέπει να έχουμε ανοίξει τις πόρτες 80 και 443 στο router και να τις έχουμε προωθήσει στη διεύθυνση IP του server μας,
  3. να έχουμε αποκτήσει το δικό μας domain (π.χ. doctorandroid.gr) και να έχουμε προωθήσει τα subdomain που θα χρησιμοποιήσουμε (π.χ. next.doctorandroid.gr, hass.doctorandroid.gr) στην δημόσια IP που βρίσκεται ο server μας.
  4. Αν το τρέχουμε σε ένα φθηνό server (π.χ. στην DigitalOcean) θα πρέπει να έχουμε κάνει τις ανάλογες ενέργειες για προώθηση στην IP που μας δίνει.

Pro tip:Όσον αφορά την προώθηση των subdomain στο δίκτυό μας, μπορούμε να τα κάνουμε όλα με μία καταχώρηση και να μην ασχοληθούμε ξανά μαζί τους. Μπαίνουμε στη σελίδα του registrar από τον οποίο αγοράσαμε το domain (π.χ. namecheap) και δημιουργούμε ένα «catch all» A record δίνοντας ως Host την διεύθυνση που θέλουμε με το αστεράκι μπροστά π.χ. *.doctorandroid.gr. Με αυτόν τον τρόπο, όποιο subdomain και αν χρειάζεστε δεν θα ασχολείστε με την προώθησή του.

Ρυθμίζουμε το Traefik Proxy

Ο Traefik Proxy χρειάζεται δύο αρχεία ρυθμίσεων για να λειτουργήσει. Το «traefik.toml» διαθέτει τις στατικές ρυθμίσεις της υπηρεσίας και το «traefik_dynamic.toml» τις δυναμικές. Δημιουργούμε και ανοίγουμε το πρώτο με τον αγαπημένο μας editor (π.χ. VIM):

vim traefik.toml

Κάνουμε αντιγραφή και επικόλληση τα ακόλουθα και αποθηκεύουμε το αρχείο μας:

[entryPoints]
  [entryPoints.web]
    address = ":80"
    [entryPoints.web.http.redirections.entryPoint]
      to = "websecure"
      scheme = "https"

  [entryPoints.websecure]
    address = ":443"

[api]
  dashboard = true

[certificatesResolvers.lets-encrypt.acme]
  email = "to-email-mas@gmail.gr"
  storage = "acme.json"
  [certificatesResolvers.lets-encrypt.acme.tlsChallenge]

[providers.docker]
  watch = true
  network = "web"

[providers.file]
  filename = "traefik_dynamic.toml"

Με λίγα λόγια αυτό που κάναμε με το συγκεκριμένο αρχείο είναι το εξής:

  • [entrypoints]: Δηλώσαμε ότι ο proxy μας θα παρακολουθεί την πόρτα 80 (web) και την 443 (websecure) για νέα αιτήματα, ενώ ρυθμίσαμε επίσης τα αιτήματα «http» να προωθούνται αυτόματα σε «https» ().
  • [api]: Ενεργοποιήσαμε το «Dashboard» (γραφικό περιβάλλον) του Traefik.
  • [certificatesResolvers.lets-encrypt.acme]: Ορίσαμε το αρχείο «acme.json» στο οποίο θα αποθηκεύονται οι πληροφορίες των πιστοποιητικών SSL που θα λαμβάνουν οι υπηρεσίες μας από το «Let’s Encrypt». Εκεί δηλώσαμε επίσης και το email μας (π.χ. «to-email-mas@gmail.gr») για τυχόν μελλοντικές ειδοποιήσεις σχετικά με τα SSL μας.
  • [providers.docker]: Ενημερώσαμε τον proxy μας να εξυπηρετεί τα Docker container που είναι συνδεδεμένα στο δίκτυο «web», το οποίο θα δημιουργήσουμε στη συνέχεια.
  • [providers.file]: Δηλώσαμε ότι οι δυναμικές ρυθμίσεις του Traefik βρίσκονται στο αρχείο «traefik_dynamic.toml».

Πάμε τώρα να δημιουργήσουμε το αρχείο «traefik_dynamic.toml». Εκεί περιέχονται και οι ρυθμίσεις για το «Dashboard» του Traefik, μέσα από το οποίο μπορούμε να βλέπουμε με μια ματιά την υγεία των υπηρεσιών μας. Θα χρειαστούμε ένα username (π.χ. «doctor») και ένα password για να το ασφαλίσουμε, αλλά θα πρέπει πρώτα να το κρυπτογραφήσουμε, κάτι που γίνεται ως εξής:

sudo apt install apache2-utils
htpasswd -nb doctor to-password-mas

Το τερματικό θα μας απαντήσει με τον κρυπτογραφημένο κωδικό ως εξής:

doctor:$apr1$q9cQzs5M$VsAyJGznYd1HTNY8qiI7C.

Δημιουργούμε και ανοίγουμε το traefik_dynamic.toml με τον αγαπημένο μας editor (π.χ. VIM):

vim traefik_dynamic.toml

Κάνουμε αντιγραφή και επικόλληση τα ακόλουθα και το αποθηκεύουμε:

[http.middlewares.simpleAuth.basicAuth]
  users = [
    "doctor:$apr1$q9cQzs5M$VsAyJGznYd1HTNY8qiI7C."
  ]

[http.routers.api]
  rule = "Host(`monitor.doctorandroid.gr`)"
  entrypoints = ["websecure"]
  middlewares = ["simpleAuth"]
  service = "api@internal"
  [http.routers.api.tls]
    certResolver = "lets-encrypt"

Αυτό που κάναμε με το συγκεκριμένο αρχείο είναι το εξής:

  • [http.middlewares.simpleAuth.basicAuth]: Ορίσαμε ένα username και ένα password για το «Dashboard» του Traefik (είναι αυτό που δημιουργήσαμε πριν με το «htpasswd»).
  • [http.routers.api]: Ορίσαμε τη διεύθυνση από την οποία θα μπαίνουμε στο «Dashboard» (monitor.doctorandroid.gr). Κάναμε επίσης αυτόματη προώθηση όλων των αιτημάτων από την πόρτα 80 στην ασφαλή 443 (websecure). 
  • [http.routers.api.tls]: Τέλος ενημερώσαμε τον proxy μας ότι τα πιστοποιητικά SSL θα έρχονται από την υπηρεσία «Let’s Encrypt».

Δημιουργούμε το Docker container του Traefik Proxy

Είπαμε πριν ότι τα container μας θα τρέχουν στο δίκτυο «web» του Docker. Ας το δημιουργήσουμε με την εντολή:

docker network create web

Δημιουργούμε επίσης το αρχείο «acme.json» και του δίνουμε τα σωστά δικαιώματα στο σύστημα με τις εντολές:

touch acme.jsonchmod 600 acme.json

Η εντολή για σηκώσουμε το container του Traefik Proxy στο Docker είναι η εξής:

docker run -d 
  -v /var/run/docker.sock:/var/run/docker.sock 
  -v ./traefik.toml:/traefik.toml 
  -v ./traefik_dynamic.toml:/traefik_dynamic.toml 
  -v ./acme.json:/acme.json 
  -p 80:80 
  -p 443:443 
  --network web 
  --name traefik 
  traefik:v2.2

Δε χρειάζεται να εξηγήσουμε τι κάνει η συγκεκριμένη εντολή, καθώς είμαστε πλέον έμπειροι από τα προηγούμενα «Μαθήματα Docker«. Τώρα που το Traefik είναι έτοιμο, μπορούμε να μπούμε στην υπηρεσία από τη διεύθυνση (είχαμε δηλώσει το domain στο [http.routers.api]):

https://monitor.doctorandroid.gr/dashboard/

Συνδέουμε το Heimdall στο Traefik Proxy 

Αφού τελειώσαμε με τον proxy server μας, ήρθε επιτέλους η στιγμή να συνδέσουμε τις υπηρεσίες μας επάνω του. Το μόνο που θα χρειαστεί να κάνουμε είναι να προσθέσουμε κάποιες ετικέτες και κάποια δίκτυα στο αρχείο Docker Compose της κάθε υπηρεσίας.

Θα δούμε μία απλή υπηρεσία όπως το Heimdall, αλλά και μία εξαρτώμενη από βάση δεδομένων όπως το Nextcloud για να καλύψουμε όλες τις περιπτώσεις.

Ξεκινάμε με το Heimdall και δημιουργούμε το αρχείο «docker-compose.yml» με την εντολή:

vim docker-compose.yml

Κάνουμε αντιγραφή και επικόλληση τα εξής:

version: '3'

services:
  heimdall:
    container_name: heimdall
      environment:
        - PUID=1000
        - PGID=1000
        - TZ=europe/athens
      volumes:
        - ./heimdall:/config
      labels:
        - traefik.http.routers.heimdall.rule=Host(`heimdall.doctorandroid.gr`)
        - traefik.http.routers.heimdall.tls=true
        - traefik.http.routers.heimdall.tls.certresolver=lets-encrypt
        - traefik.port=80
      networks:
        - internal
        - web
      restart: unless-stopped
      image: linuxserver/heimdall

networks:
  web:
    external: true
  internal:
    external: false

Αυτό που αλλάξει εδώ σε σχέση με το επίσημο Docker Compose αρχείο του Heimdall είναι το εξής:

  • Αφαιρέσαμε τα «ports» καθώς τη διαχείρισή τους θα την κάνει πλέον ο proxy.
  • Προσθέσαμε τα «networks» στα οποία θα συνδεθεί το container μας. Το «web» είναι το βασικό δίκτυο του proxy, ενώ με το «internal» το container μας μπορεί να επικοινωνεί με άλλα container (δε χρειάζεται στην συγκεκριμένη περίπτωση). 
  • Προσθέσαμε τα απαραίτητα «labels» στα οποία δηλώσαμε τη διεύθυνση μέσα από την οποία θα έχουμε πρόσβαση (heimdall.doctorandroid.gr), καθώς και ότι θέλουμε ένα SSL πιστοποιητικό από το «Let’s Encrypt» για αυτήν.

Το αποθηκεύουμε και το τρέχουμε με την εντολή:

docker-compse up -d

Πλέον μπορούμε να μπούμε στην υπηρεσία του Heimdall από τη διεύθυνση:

https://heimdall.doctorandroid.gr

Συνδέουμε το Nextcloud στο Traefik proxy 

Πάμε να ρίξουμε και μια ματιά στην περίπτωση του Nextcloud, το οποίο χρειάζεται και μία βάση δεδομένων για να λειτουργήσει. Στην περίπτωση αυτή θέλουμε να στείλουμε στον proxy μόνο την υπηρεσία του Nextcloud και όχι τη βάση δεδομένων, η οποία θέλουμε να λειτουργεί τοπικά.

Δημιουργούμε το αρχείο «docker-compose.yml» με την εντολή:

vim docker-compose.yml

Κάνουμε αντιγραφή και επικόλληση τα εξής:

version: '3'

services:
  db:
    image: mariadb
    container_name: nextcloud_db
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    restart: always
    volumes:
      - ./database:/var/lib/mysql

    environment:
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_PASSWORD=password
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=doctor
    networks:
      - internal
    labels:
      - traefik.enable=false

  app:
    image: nextcloud
    container_name: nextcloud_app
    restart: always
    labels:
      - traefik.http.routers.cloud.rule=Host(`cloud.doctorandroid.gr`)
      - traefik.http.routers.cloud.tls=true
      - traefik.http.routers.cloud.tls.certresolver=lets-encrypt
      - traefik.port=80
    networks:
      - internal
      - web
    volumes:
      - ./html:/var/www/html
    depends_on:
      - db

networks:
  web:
    external: true
  internal:
    external: false

Σε αυτό το αρχείο βλέπουμε δύο υπηρεσίες, το db που είναι η βάση δεδομένων και το app το οποίο είναι η εφαρμογή του Nextcloud. Το db λοιπόν δε θέλουμε να έχει πρόσβαση στο ίντερνετ οπότε το προσθέσαμε μόνο στο internal network και όχι στο web. Με το labels: traefik.enable=false λέμε επίσης στο Traefik να μην το λαμβάνει υπ’ όψη.

Αντίθετα στο app προσθέσαμε τα labels και networks που χρησιμοποιήσαμε και στο Heimdall (εδώ το «internal» είναι απαραίτητο για να επικοινωνεί το app με το db). Η διαφορά εδώ είναι ότι προσθέσαμε επίσης και το depends_on: db, το οποίο σημαίνει ότι το app δεν μπορεί να λειτουργήσει χωρίς το db, κάτι το οποίο είναι λογικό.

Το αποθηκεύουμε και το τρέχουμε με την εντολή:

docker-compse up -d

Πλέον μπορούμε να μπούμε στην υπηρεσία του nextcloud από τη διεύθυνση:

https://cloud.doctorandroid.gr

Εν κατακλείδι

Η πρώτη προτεραιότητα σε έναν server είναι πάντα η ασφάλεια. Όσο βολικό και να είναι το self-hosting με το Docker, δεν μπορείς να ανοίγεις πόρτες στο δίκτυό σου για κάθε υπηρεσία. Αργά ή γρήγορα λοιπόν ένας reverse proxy server θα σου χρειαστεί και αυτός που μας προσφέρει η Traefik Labs είναι εξαιρετικά εύκολος στην εγκατάσταση, ενώ δε χρειάζεται σχεδόν καθόλου συντήρηση.

Προσθέστε σε αυτά το γεγονός ότι είναι ανοιχτού κώδικα και ότι διαθέτει ένα πλήρες documentation, σε περίπτωση που θέλουμε να κάνουμε κάτι πιο εξεζητημένο στο μέλλον. Περισσότερα για τον Traefik Proxy θα βρείτε στην επίσημη σελίδα του.

crosspost doctorandroid.gr



Source link

Αφήστε μια απάντηση

Η ηλ. διεύθυνση σας δεν δημοσιεύεται. Τα υποχρεωτικά πεδία σημειώνονται με *