Costruire una Rete di Siti web/Server web con LXD, per Principianti¶
Introduzione¶
Ok, abbiamo già una guida sull'installazione di LXD/LXC su Rocky Linux, ma è stata scritta da qualcuno che sa cosa stava facendo e che voleva costruire una rete containerizzata di server e/o applicazioni su una macchina fisica della sua rete locale. È fantastico, e ne ruberò subito dei pezzi per non dover scrivere tanto.
Ma se avete appena sentito parlare di Linux Containers e non avete ancora capito bene come funzionano, ma volete ospitare qualche sito web, questa è la guida che fa per voi. Questo tutorial vi insegnerà come ospitare siti web di base con LXD e LXC su qualsiasi sistema, compresi i server privati virtuali e il cloud hosting.
Quindi, in primo luogo, che cos'è un Container Linux? Per i principianti, si tratta di un modo per far sì che un computer finga di essere in realtà molti altri computer. Questi " container " ospitano ciascuno una versione di base, solitamente ridotta, di un sistema operativo scelto dall'utente. È possibile usare ogni contenitore come un server individuale; mettere nginx su uno, Apache su un altro e persino usare un terzo come server di database.
Il vantaggio fondamentale è che se un'applicazione o un sito web all'interno del proprio contenitore presenta gravi bug, un hack o altri problemi, è improbabile che si ripercuotano sul resto del server o sulle altre applicazioni e siti web. Inoltre, i container sono facilissimi da visualizzare in snapshot, eseguire il backup e ripristinare.
In questo caso, eseguiremo Rocky Linux nei nostri container, sopra il nostro sistema "host", che è anch'esso Rocky Linux.
Concettualmente, è qualcosa di simile:
Se avete mai giocato con VirtualBox per eseguire alcune applicazioni Windows, è come questo, ma non è così. A differenza delle macchine virtuali, i container Linux non emulano un intero ambiente hardware per ogni container. Piuttosto, tutti condividono alcuni dispositivi virtuali per impostazione predefinita per la rete e lo storage, anche se è possibile aggiungere altri dispositivi virtuali. Di conseguenza, richiedono molto meno overhead (potenza di elaborazione e RAM) di una macchina virtuale.
Per gli amici di Docker (Docker è un altro sistema basato su container, non un sistema di macchine virtuali), i container Linux sono meno effimeri di quelli a cui siete abituati. Tutti i dati in ogni istanza del container sono persistenti e qualsiasi modifica apportata è permanente, a meno che non si ripristini un backup. In breve, lo spegnimento del container non cancellerà gli eventuali problemi introdotti.
LXD, in particolare, è un'applicazione a riga di comando che aiuta a configurare e gestire i container Linux. Questo è ciò che installeremo oggi sul nostro server host Rocky Linux. Scriverò parecchio su LXC/LXD, perché c'è molta documentazione vecchia che si riferisce solo a LXC e sto cercando di rendere più facile per le persone il reperimento di guide aggiornate come questa.
Note
Esisteva un'applicazione precursore di LXD che si chiamava anche "LXC". Oggi LXC è la tecnologia e LXD è l'applicazione.
Li useremo entrambi per creare un ambiente che funzioni in questo modo:
In particolare, vi mostrerò come configurare semplici server web Nginx e Apache all'interno dei vostri container server e come utilizzare un altro container con Nginx come reverse proxy. Anche in questo caso, questa configurazione dovrebbe funzionare in qualsiasi ambiente: dalle reti locali ai server privati virtuali.
Note
Un reverse proxy è un programma che prende le connessioni in entrata da Internet (o dalla rete locale) e le indirizza al server, al container o all'applicazione appropriata. Esistono anche strumenti dedicati a questo lavoro, come HaProxy... ma trovo che Nginx sia molto più facile da usare.
Prerequisiti E Presupposti¶
- Conoscenza di base dell'interfaccia a riga di comando Linux. È necessario sapere come usare SSH se si installa LXC/LXD su un server remoto.
- Un server connesso a Internet, fisico o virtuale, su cui è già in esecuzione Rocky Linux.
- Due nomi di dominio puntati correttamente sul vostro server con un record A.
- Anche due sottodomini andrebbero bene. Un dominio con un record di sottodominio wildcard può andare bene, oppure un dominio LAN personalizzato.
- Un editor di testo a riga di comando. nano va bene, micro è il mio preferito, ma si può usare quello che si preferisce.
- Potete seguire l'intero tutorial come utente root, ma non è una buona idea. Dopo l'installazione iniziale di LXC/LXD, vi guideremo nella creazione di un utente non privilegiato specifico per i comandi LXD.
- Le immagini di Rocky Linux su cui basare i container sono ora disponibili.
- Se non avete molta familiarità con Nginx o Apache, allora dovrete consultare alcune delle nostre altre guide se volete ottenere un server di produzione completo e funzionante. Non preoccupatevi, le inserirò nei link qui sotto.
Impostazione dell'Ambiente del Server Host¶
Installa il repository EPEL¶
LXD richiede il repository EPEL (Extra Packages for Enterprise Linux), facile da installare con:
dnf install epel-release
Una volta installato, controllate gli aggiornamenti:
dnf update
Se sono stati eseguiti aggiornamenti del kernel durante il processo di aggiornamento di cui sopra, riavviare il server
Installazione di snapd¶
LXD deve essere installato da un pacchetto snap* per Rocky Linux. Per questo motivo, è necessario installare snapd con:
dnf install snapd
Ora abilitate il servizio snapd per l'avvio automatico al riavvio del server e avviatelo direttamente:
systemctl enable snapd
E poi eseguire:
systemctl start snapd
Riavviare il server prima di continuare. È possibile farlo con il comando reboot
o dal pannello di amministrazione del VPS/cloud hosting.
* snap è un metodo per impacchettare le applicazioni in modo che siano dotate di tutte le dipendenze necessarie e possano essere eseguite su quasi tutti i sistemi Linux.
Installare LXD¶
L'installazione di LXD richiede l'uso del comando snap. A questo punto, stiamo solo installando, non stiamo facendo alcuna configurazione:
snap install lxd
Se state eseguendo LXD su un server fisico (AKA "bare metal"), probabilmente dovreste tornare all'altra guida e leggere la sezione "Impostazione dell'ambiente". C'è un sacco di materiale interessante su kernel e file system, e molto altro ancora.
Se state eseguendo LXD in un ambiente virtuale, riavviate e continuate a leggere.
Inizializzazione LXD¶
Ora che l'ambiente è stato configurato, siamo pronti a inizializzare LXD. Si tratta di uno script automatico che pone una serie di domande per rendere operativa l'istanza LXD:
lxd init
Ecco le domande e le nostre risposte per lo script, con una piccola spiegazione dove necessario:
Would you like to use LXD clustering? (yes/no) [default=no]:
Se siete interessati al clustering, fate ulteriori ricerche al riguardo qui. Altrimenti, basta premere "Invio" per accettare l'opzione predefinita.
Do you want to configure a new storage pool? (yes/no) [default=yes]:
Accettare l'impostazione predefinita.
Name of the new storage pool [default=default]: server-storage
Scegliere un nome per il pool di archiviazione. Mi piace chiamarlo come il server su cui gira LXD. (Un pool di archiviazione è in pratica una quantità prestabilita di spazio su disco rigido messa da parte per i vostri container)
Name of the storage backend to use (btrfs, dir, lvm, zfs, ceph) [default=zfs]: lvm
La domanda precedente riguarda il tipo di file system che si desidera utilizzare per l'archiviazione e l'impostazione predefinita può variare a seconda di ciò che è disponibile sul sistema. Se siete su un server bare metal e volete usare ZFS, fate riferimento alla guida di cui sopra.
In un ambiente virtuale, ho scoperto che "LVM" funziona bene e di solito è quello che uso. È possibile accettare l'impostazione predefinita alla domanda successiva.
Create a new LVM pool? (yes/no) [default=yes]:
Se si dispone di un disco rigido o di una partizione specifica che si desidera utilizzare per l'intero pool di archiviazione, scrivere " yes". Se state facendo tutto questo su un VPS, probabilmente dovrete scegliere "no".
`Would you like to use an existing empty block device (e.g. a disk or partition)? (yes/no) [default=no]:`
Il Metal As A Service (MAAS) non rientra nell'ambito di questo documento. Accettare le impostazioni predefinite.
Would you like to connect to a MAAS server? (yes/no) [default=no]:
E ancora altri default. È tutto a posto.
Would you like to create a new local network bridge? (yes/no) [default=yes]:
What should the new bridge be called? [default=lxdbr0]: `
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
Se si desidera utilizzare IPv6 sui propri contenitori LXD, è possibile attivare la prossima opzione. Questo dipende da voi, ma per lo più non dovrebbe essere necessario.
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]:
Questo è necessario per eseguire facilmente il backup del server e può consentire di gestire l'installazione di LXD da altri computer. Se tutto questo vi sembra buono, rispondete " yes"
Would you like the LXD server to be available over the network? (yes/no) [default=no]: yes
Se avete risposto sì alle ultime domande, scegliete i valori predefiniti:
Address to bind LXD to (not including port) [default=all]:
Port to bind LXD to [default=8443]:
Ora vi verrà chiesta una password di fiducia. È il modo in cui ci si connette al server host LXC da altri computer e server, quindi è necessario impostare qualcosa che abbia senso nel proprio ambiente. Salvate la password in un luogo sicuro, ad esempio in un gestore di password.
Trust password for new clients:
Again:
E poi continuare a utilizzare i valori predefiniti da qui in avanti:
Would you like stale cached images to be updated automatically? (yes/no) [default=yes]
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]:
Impostazione dei Privilegi degli Utenti¶
Prima di continuare, dobbiamo creare l'utente "lxdadmin" e assicurarci che abbia i privilegi necessari. L'utente "lxdadmin" deve poter usare sudo per accedere ai comandi di root e deve essere membro del gruppo "lxd". Per aggiungere l'utente e assicurarsi che sia membro di entrambi i gruppi, eseguire:
useradd -G wheel,lxd lxdadmin
Quindi impostare la password:
passwd lxdadmin
Come per le altre password, salvatela in un luogo sicuro.
Impostare il vostro Firewall¶
Prima di fare qualsiasi altra cosa con i container, è necessario poter accedere al server proxy dall'esterno. Se il firewall blocca la porta 80 (la porta predefinita utilizzata per il traffico HTTP/web) o la porta 443 (utilizzata per il traffico web HTTPS/sicuro), non si potrà fare molto a livello di server.
L'altra guida di LXD mostra come farlo con il firewall iptables, se è questo che si vuole fare. Tendo a utilizzare il firewall predefinito di CentOS: firewalld. Ecco cosa faremo questa volta.
firewalld
è configurato tramite il comando firewall-cmd
. La prima cosa da fare, prima di aprire qualsiasi porta, è assicurarsi che ai container possano essere assegnati automaticamente gli indirizzi IP:
firewall-cmd --zone=trusted --permanent --change-interface=lxdbr0
Attenzione
Se non si esegue quest'ultimo passaggio, i contenitori non saranno in grado di accedere correttamente a Internet o tra loro. Si tratta di un elemento pazzescamente essenziale, e conoscerlo vi risparmierà anni di frustrazione.
Ora, per aggiungere una nuova porta, basta eseguire questa istruzione:
firewall-cmd --permanent --zone=public --add-port=80/tcp
Vediamo di analizzare il tutto:
- La flag
--permanent
dice al firewall di assicurarsi che questa configurazione sia usata ogni volta che il firewall viene riavviato, e quando il server stesso viene riavviato. --zone=public
indica al firewall di accettare le connessioni in entrata a questa porta da chiunque.- Infine,
–-add-port=80/tcp
dice al firewall di accettare connessioni in entrata sulla porta 80, fintanto che stanno utilizzando il Transmission Control Protocol, che è quello che si desidera in questo caso.
Per ripetere il processo per il traffico HTTPS, basta eseguire nuovamente il comando e cambiare il numero.
firewall-cmd --permanent --zone=public --add-port=443/tcp
Queste configurazioni non avranno effetto finché non si forzerà il problema. Per farlo, dite a firewalld di ricaricare le sue configurazioni, in questo modo:
firewall-cmd --reload
Ora, c'è una piccolissima possibilità che questo non funzioni. In questi rari casi, fate in modo che firewalld esegua i vostri ordini con il vecchio "spegni e riaccendi".
systemctl restart firewalld
Per verificare che le porte siano state aggiunte correttamente, eseguire firewall-cmd --list-all
. Un firewall correttamente configurato avrà un aspetto simile a questo (ho alcune porte extra aperte sul mio server locale, ignoratele):
public (active)
target: default
icmp-block-inversion: no
interfaces: enp9s0
sources:
services: cockpit dhcpv6-client ssh
ports: 81/tcp 444/tcp 15151/tcp 80/tcp 443/tcp
protocols:
forward: no
masquerade: no
forward-ports:
source-ports:
icmp-blocks:
rich rules:
E questo dovrebbe essere tutto ciò di cui avete bisogno, a livello di firewall.
Impostazione dei Container¶
In realtà la gestione dei container è piuttosto semplice. Pensate che è come poter evocare un intero computer a comando e avviarlo o fermarlo a piacimento. È inoltre possibile accedere a tale "computer" ed eseguire qualsiasi comando, proprio come si farebbe con il server host.
Nota
Da questo momento in poi, ogni comando deve essere eseguito come utente lxdadmin
, o come avete deciso di chiamarlo, anche se alcuni richiederanno l'uso di sudo per ottenere temporaneamente i privilegi di root.
Per questa esercitazione sono necessari tre container: il server reverse proxy, un server Nginx di prova e un server Apache di prova, tutti eseguiti su container basati su Rocky.
Se per qualche motivo si ha bisogno di un container completamente riservato (e per lo più non dovrebbe), si possono eseguire tutti questi comandi come root.
Per questa esercitazione sono necessari tre container:
Li chiameremo "proxy-server" (per il container che dirigerà il traffico web agli altri due container), "nginx-server" e "apache-server". Sì, vi mostrerò come effettuare il reverse proxy sia verso i server basati su nginx che su apache.
Cominciamo con lo stabilire su quale immagine vogliamo basare i nostri container. Per questa esercitazione, utilizzeremo solo Rocky Linux. L'uso di Alpine Linux, ad esempio, può portare a container molto più piccoli (se l'archiviazione è un problema), ma questo va oltre lo scopo di questo documento.
Trovare l'immagine desiderata¶
Ecco il metodo rapido per avviare un container con Rocky Linux:
lxc launch images:rockylinux/8/amd64 my-container
Naturalmente, quel "my-container" alla fine deve essere rinominato con il nome del container che si desidera, ad es. “proxy-server”. La parte "/amd64" dovrebbe essere cambiata in "arm64" se si sta facendo tutto questo su qualcosa come un Raspberry Pi.
Ecco la versione lunga: per trovare le immagini desiderate, si può usare questo comando per elencare tutte le immagini disponibili nei repository LXC principali:
lxc image list images: | more
Poi basta premere "Invio" per scorrere un enorme elenco di immagini e premere "Control-C" per uscire dalla modalità di visualizzazione dell'elenco.
Oppure, ci si può semplificare la vita e specificare il tipo di Linux che si desidera, in questo modo:
lxc image list images: | grep rockylinux
Dovrebbe essere visualizzato un elenco molto più breve, simile a questo:
| rockylinux/8 (3 more) | 4e6beda70200 | yes | Rockylinux 8 amd64 (20220129_03:44) | x86_64 | VIRTUAL-MACHINE | 612.19MB | Jan 29, 2022 at 12:00am (UTC) |
| rockylinux/8 (3 more) | c04dd2bcf20b | yes | Rockylinux 8 amd64 (20220129_03:44) | x86_64 | CONTAINER | 127.34MB | Jan 29, 2022 at 12:00am (UTC) |
| rockylinux/8/arm64 (1 more) | adc0561d6330 | yes | Rockylinux 8 arm64 (20220129_03:44) | aarch64 | CONTAINER | 124.03MB | Jan 29, 2022 at 12:00am (UTC) |
| rockylinux/8/cloud (1 more) | 2591d9716b04 | yes | Rockylinux 8 amd64 (20220129_03:43) | x86_64 | CONTAINER | 147.04MB | Jan 29, 2022 at 12:00am (UTC) |
| rockylinux/8/cloud (1 more) | c963253fcea9 | yes | Rockylinux 8 amd64 (20220129_03:43) | x86_64 | VIRTUAL-MACHINE | 630.56MB | Jan 29, 2022 at 12:00am (UTC) |
| rockylinux/8/cloud/arm64 | 9f49e80afa5b | yes | Rockylinux 8 arm64 (20220129_03:44) | aarch64 | CONTAINER | 143.15MB | Jan 29, 2022 at 12:00am (UTC) |
Creazione dei Container¶
Nota
Di seguito viene illustrato un modo rapido per creare tutti questi contenitori. Si consiglia di aspettare prima di creare il container proxy-server. C'è un trucco che vi mostrerò di seguito e che potrebbe farvi risparmiare tempo.
Una volta trovata l'immagine desiderata, utilizzate il comando lxc launch
come mostrato sopra. Per creare i container desiderati per questa esercitazione, eseguire questi comandi (modificandoli se necessario) in successione:
lxc launch images:rockylinux/8/amd64 proxy-server
lxc launch images:rockylinux/8/amd64 nginx-server
lxc launch images:rockylinux/8/amd64 apache-server
Dopo aver eseguito ogni comando, si dovrebbe ricevere una notifica che indica che i container sono stati creati e persino avviati. Quindi, è necessario controllarli tutti.
Eseguite questo comando per verificare che siano tutti attivi e funzionanti:
lxc list
Il risultato dovrebbe essere simile a questo (anche se, se si è scelto di usare IPv6, ci sarà molto più testo):
+---------------+---------+-----------------------+------+-----------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+---------------+---------+-----------------------+------+-----------+-----------+
| proxy-server | RUNNING | 10.199.182.231 (eth0) | | CONTAINER | 0 |
+---------------+---------+-----------------------+------+-----------+-----------+
| nginx-server | RUNNING | 10.199.182.232 (eth0) | | CONTAINER | 0 |
+---------------+---------+-----------------------+------+-----------+-----------+
| apache-server | RUNNING | 10.199.182.233 (eth0) | | CONTAINER | 0 |
+---------------+---------+-----------------------+------+-----------+-----------+
Una parola sulla Rete di Container¶
Quindi l'altra guida riportata all'inizio di questa ha un intero tutorial su come impostare LXC/LXD per lavorare con Macvlan. Questo è particolarmente utile se si gestisce un server locale e si vuole che ogni container abbia un indirizzo IP visibile sulla rete locale.
Quando si lavora su un VPS, spesso non si ha questa possibilità. In effetti, potreste avere un solo indirizzo IP con cui siete autorizzati a lavorare. La configurazione di rete predefinita è progettata per soddisfare questo tipo di limitazioni; rispondendo alle richieste lxd init
come ho specificato sopra dovrebbe occuparsi di tutto.
Fondamentalmente, LXD crea un dispositivo di rete virtuale chiamato bridge (di solito chiamato "lxdbr0") e tutti i container vengono connessi a quel bridge per impostazione predefinita. Attraverso di esso, possono connettersi a Internet tramite il dispositivo di rete predefinito dell'host (Ethernet, wi-fi o un dispositivo di rete virtuale fornito dal VPS). Cosa ancora più importante, tutti i container possono connettersi tra loro.
Per garantire questa connessione tra i container, ogni container ottiene un nome di dominio interno. Per impostazione predefinita, è solo il nome del contenitore più ".lxd". Quindi il container "proxy-server" è disponibile per tutti gli altri container in "proxy-server.lxd". Ma ecco la cosa davvero importante da sapere: per default i domini ".lxd" sono disponibili solo all'interno dei container stessi.
Se si esegue ping proxy-server.lxd
sul sistema operativo host (o altrove), non si otterrà nulla. Questi domini interni, però, ci torneranno molto utili in seguito.
Tecnicamente si può cambiare e rendere disponibili i domini interni del container sull'host... ma non l'ho mai capito. Probabilmente è meglio mettere il server reverse proxy in un container, in modo da poter eseguire snapshot e backup con facilità.
Gestione dei container¶
Alcune cose da sapere prima di procedere:
Avviamento & Arresto¶
Tutti i container possono essere avviati, fermati e riavviati a seconda delle necessità con i seguenti comandi:
lxc start mycontainer
lxc stop mycontainer
lxc restart mycontainer
Anche Linux ha bisogno di riavviarsi a volte. È possibile avviare, arrestare e riavviare tutti i container contemporaneamente con i seguenti comandi.
lxc start --all
lxc stop --all
lxc restart --all
L'opzione restart --all
è molto utile per alcuni dei bug temporanei più oscuri.
Eseguire operazioni all'interno dei container¶
È possibile controllare il sistema operativo all'interno del container in due modi: si possono semplicemente eseguire comandi al suo interno dal sistema operativo host, oppure si può aprire una shell.
Ecco cosa voglio dire. Per eseguire un comando all'interno di un container, ad esempio per installare Apache, basta usare lxc exec
, in questo modo:
lxc exec my-container dnf install httpd -y
Questo permetterà a Apache di installarsi da solo e di vedere l'output del comando sul terminale dell'host.
Per aprire una shell (in cui è possibile eseguire tutti i comandi desiderati come root), utilizzare questa procedura:
lxc exec my-container bash
Se, come me, preferite la comodità allo spazio di archiviazione e avete installato una shell alternativa come fish in tutti i vostri container, cambiate semplicemente il comando in questo modo:
lxc exec my-container fish
In quasi tutti i casi, verrete automaticamente assegnati all'account di root e alla directory /root
.
Infine, se si è aperta una shell in un container, la si abbandona nello stesso modo in cui si abbandona qualsiasi shell: semplicemente con il comando exit
.
Copia dei Container¶
Ora, se si dispone di un container che si desidera replicare con il minimo sforzo, non è necessario avviarne uno nuovo e installare nuovamente tutte le applicazioni di base. Questo richiede un lavoro supplementare che non è necessario. Basta eseguire:
lxc copy my-container my-other-container
Verrà creata una copia esatta di "my-container" con il nome "my-other-container". Tuttavia, potrebbe non avviarsi automaticamente, quindi si dovranno apportare le eventuali modifiche alla configurazione del nuovo container e poi avviarlo:
lxc start my-other-container
A questo punto, si potrebbero apportare alcune modifiche, come cambiare l'hostname interno del container o altro.
Configurazione dello Storage & Limiti della CPU¶
LXC/LXD di solito definisce la quantità di spazio di archiviazione di un container e in generale gestisce le risorse, ma è possibile che si voglia avere il controllo su questo aspetto. Se si desidera mantenere i contenitori di dimensioni ridotte, si può usare il comando lxc config
per rimpicciolirli e allargarli secondo le necessità.
Il comando seguente imposta un limite "soft" di 2GB su un container. Un limite soft è in realtà più che altro una "memoria minima" e il container utilizzerà più memoria se è disponibile. Come sempre, cambiate "my-container" con il nome del container vero e proprio.
lxc config set my-container limits.memory 2GB
È possibile impostare un limite hard in questo modo:
lxc config set my-container limits.memory.enforce 2GB
Se si desidera evitare che un determinato container possa occupare tutta la potenza di elaborazione disponibile sul server, è possibile limitare i core della CPU a cui ha accesso con questo comando. Basta modificare il numero di core della CPU alla fine, a seconda delle esigenze.
lxc config set my-container limits.cpu 2
Eliminare i Container (e Come Evitare Che Ciò Accada)¶
Infine, è possibile eliminare i container eseguendo questo comando:
lxc delete my-container
Non sarà possibile eliminare il container se è in esecuzione, quindi lo si può fermare prima o usare la flag --force
per saltare questa parte.
lxc delete my-container --force
Ora, grazie al completamento del comando Tab, all'errore dell'utente e al fatto che la "d" si trova accanto alla "s" sulla maggior parte delle tastiere, è possibile cancellare accidentalmente i container.
Per evitare che ciò accada, è possibile impostare qualsiasi container come "protetto" (facendo in modo che il processo di cancellazione richieda un passo in più) con questo comando:
lxc config set my-container security.protection.delete true
Per togliere la protezione al contenitore, basta eseguire nuovamente il comando, cambiando "true" in "false".
Impostazione dei Server¶
Ok, ora che i container sono attivi e funzionanti, è il momento di installare ciò che serve. Per prima cosa, assicurarsi che tutti siano aggiornati con i seguenti comandi (saltare il contenitore "proxy-server" se non è stato ancora creato):
lxc exec proxy-server dnf update -y
lxc exec nginx-server dnf update -y
lxc exec apache-server dnf update -y
Poi, entrare in ogni container e iniziare a lavorare.
È inoltre necessario un editor di testo per ogni container. Per impostazione predefinita, Rocky Linux viene fornito con vi, ma se volete semplificarvi la vita, nano andrà bene. È necessario installarlo in ogni contenitore prima di aprirlo.
lxc exec proxy-server dnf install nano -y
lxc exec nginx-server dnf install nano -y
lxc exec apache-server dnf install nano -y
In seguito userò nano in tutti i comandi relativi all'editor di testo, ma fate voi.
Il Server del Sito Web Apache¶
La faremo breve, a scopo di apprendimento e di verifica. Di seguito trovate il link alle guide complete di Apache.
Per prima cosa, aprite una shell nel vostro container. Si noti che, per impostazione predefinita, i container vi porteranno nell'account di root. Per i nostri scopi, questo va bene, anche se si potrebbe voler creare un utente del server web specifico per la produzione effettiva.
lxc exec apache-server bash
Una volta effettuato l'accesso, basta installare Apache nel modo più semplice:
dnf install httpd
Ora, si potrebbe seguire la nostra guida Apache Web Server Multi-Site Setup da qui in avanti, ma in realtà è un po' eccessivo per i nostri scopi. Di solito non si vuole configurare Apache per più siti web in un ambiente containerizzato come questo. Il punto centrale dei container è la separazione delle problematiche, dopotutto.
Inoltre, i certificati SSL andranno sul server proxy, quindi manterremo le cose semplici.
Una volta installato Apache, assicurarsi che sia in funzione e che possa continuare a funzionare al riavvio:
systemctl enable --now httpd
La flag --now
consente di saltare il comando di avvio del server vero e proprio. Per riferimento, sarebbe:
systemctl start httpd
Se avete installato curl
sul vostro host server, potete assicurarvi che la pagina web predefinita sia attiva e funzionante con:
curl [container-ip-address]
Ricordare che è possibile vedere tutti gli IP del contenitore con lxc list
. E se si installa curl su tutti i container, si potrebbe eseguire semplicemente:
curl localhost
Ottenere gli IP degli utenti reali dal server proxy¶
Ora c'è un passo da fare per preparare Apache all'uso del reverse proxy. Per impostazione predefinita, gli indirizzi IP effettivi degli utenti non vengono registrati dai server nei container del server web. Si desidera che questi indirizzi IP attraversino la rete, perché alcune applicazioni web hanno bisogno degli IP degli utenti per operazioni come la moderazione, l'interdizione e la risoluzione dei problemi.
Per far sì che gli indirizzi IP dei visitatori superino il server proxy, sono necessarie due parti: le giuste impostazioni del server proxy (di cui parleremo più avanti) e un semplice file di configurazione per il server Apache.
Un grosso ringraziamento va a Linode e alla loro guida LXD per i modelli di questi file di configurazione.
Creare un nuovo file di configurazione:
nano /etc/httpd/conf.d/real-ip.conf
E aggiungere questo testo:
RemoteIPHeader X-Real-IP
RemoteIPTrustedProxy proxy-server.lxd
Ricordarsi di cambiare proxy-server.lxd
con il nome del container proxy effettivo, se necessario. Ora non riavviate ancora il server Apache. Il file di configurazione che abbiamo aggiunto potrebbe causare problemi fino a quando non avremo il server proxy attivo e funzionante.
Uscire dalla shell per ora e iniziare con il server Nginx.
Nota
Anche se questa tecnica funziona (le applicazioni web e i siti web otterranno gli IP reali degli utenti), i log di accesso di Apache non mostreranno gli IP giusti e di solito mostreranno l'IP del container in cui si trova il reverse proxy. A quanto pare si tratta di un problema nel modo in cui Apache registra i log.
È possibile controllare i registri di accesso del server proxy se si desidera vedere gli indirizzi IP, oppure controllare i registri dell'applicazione web che si sta installando.
Il server web Nginx¶
Anche in questo caso, la faremo breve. Se volete usare la versione più recente (e consigliata) di Nginx in produzione, consultate la nostra guida per principianti all'installazione di Nginx. Questo contiene la guida completa all'installazione e alcune buone pratiche per la configurazione del server.
Per i test e l'apprendimento, potreste installare Nginx normalmente, ma vi consiglio di installare l'ultima versione, che è chiamata ramo "mainline".
Per prima cosa, accedere alla shell del container:
lxc exec nginx-server bash
Quindi, installare il repository epel-release
in modo da poter installare l'ultima versione di Nginx:
dnf install epel-release
Una volta fatto questo, cercare l'ultima versione di Nginx con:
dnf module list nginx
Si dovrebbe ottenere un elenco simile a questo:
Rocky Linux 8 - AppStream
Name Stream Profiles Summary
nginx 1.14 [d] common [d] nginx webserver
nginx 1.16 common [d] nginx webserver
nginx 1.18 common [d] nginx webserver
nginx 1.20 common [d] nginx webserver
nginx mainline common [d] nginx webserver
Quella desiderata è, avete indovinato, il ramo mainline. Abilitare il modulo con questo comando:
dnf enable module nginx:mainline
Ti verrà chiesto se sei sicuro di volerlo fare, quindi scegli Y
come al solito. Quindi, utilizzare il comando predefinito per installare Nginx:
dnf install nginx
Quindi, abilitare e avviare Nginx:
dnf enable --now nginx
Nota
Ricordate quando vi ho detto di aspettare prima di creare il contenitore proxy? Ecco perché: a questo punto, si può risparmiare tempo lasciando il container "nginx-server" e copiandolo per creare il container "proxy-server":
lxc copy nginx-server proxy-server
Assicurarsi di avviare il container proxy con lxc start proxy-server
e di aggiungere le porte proxy al container come descritto di seguito.
Anche in questo caso, si può verificare che il container funzioni dall'host con:
curl [your-container-ip]
Ottenere gli IP utente reali dal server proxy (nuovamente)¶
I log dovrebbero funzionare questa volta. Dovrebbero. Per farlo, inseriamo un file simile in /etc/nginx/conf.d
:
nano /etc/nginx/conf.d/real-ip.conf
Poi inserite questo testo:
real_ip_header X-Real-IP;
set_real_ip_from proxy-server.lxd;
Infine, non riavviare ancora il server. Anche in questo caso, il file di configurazione potrebbe causare problemi finché non viene impostato il server proxy.
Il Server Reverse Proxy¶
Ricordate quando vi ho detto che vi servono due domini o sottodomini? È qui che servono. I sottodomini che sto utilizzando per questo tutorial sono:
- apache.server.test
- nginx.server.test
Modificateli in tutti i file e le istruzioni, se necessario.
Se si è copiato il container "proxy-server" dal container "nginx-server" e vi si sono aggiunti i dispositivi proxy, basta entrare nella shell. Se il container è stato creato in precedenza, è necessario ripetere tutti i passaggi per l'installazione di Nginx nel container "proxy-server".
Una volta installato e verificato che funziona correttamente, è sufficiente impostare un paio di file di configurazione per indirizzare il traffico dai domini scelti ai server del sito web vero e proprio.
Prima di farlo, assicuratevi di poter accedere a entrambi i server tramite i loro domini interni:
curl apache-server.lxd
curl nginx-server.lxd
Se questi due comandi caricano nel terminale l'HTML delle pagine di benvenuto del server predefinito, allora tutto è stato configurato correttamente.
Passo essenziale: Configurare il Container "proxy-server" per Accettare Tutto il Traffico Server in Entrata¶
Anche in questo caso, si consiglia di farlo in un secondo momento, quando si creerà effettivamente il server proxy, ma ecco le istruzioni necessarie:
Ricordate quando abbiamo aperto le porte 80 e 443 nel firewall? Qui si fa in modo che il container "proxy-server" ascolti queste porte e riceva tutto il traffico diretto verso di esse.
Basta eseguire questi due comandi in successione:
lxc config device add proxy-server myproxy80 proxy listen=tcp:0.0.0.0:80 connect=tcp:127.0.0.1:80
lxc config device add proxy-server myproxy443 proxy listen=tcp:0.0.0.0:443 connect=tcp:127.0.0.1:443
Vediamo di analizzare la situazione. Ogni comando aggiunge un "device" virtuale al container proxy-server. Questi dispositivi sono impostati per ascoltare la porta 80 e la porta 443 del sistema operativo host e sono collegati alla porta 80 e alla porta 443 del container. Ogni dispositivo ha bisogno di un nome, quindi ho scelto "myproxy80" e "myproxy443".
L'opzione "listen" è la porta del sistema operativo host e, se non sbaglio, 0.0.0.0 è l'indirizzo IP dell'host sul bridge "lxdbr0". L'opzione "connect" indica l'indirizzo IP locale e le porte a cui ci si connette.
Nota
Una volta impostati questi dispositivi, è necessario riavviare tutti i container, per sicurezza.
Questi dispositivi virtuali dovrebbero essere idealmente unici. Di solito è meglio non aggiungere un dispositivo "myport80" a un altro container in esecuzione; dovrà essere chiamato in un altro modo.
Allo stesso modo, solo un container alla volta può ascoltare su una specifica porta del sistema operativo host.
Direzione del traffico al server Apache¶
Nel container "proxy-server", creare un file di configurazione chiamato apache-server.conf
in /etc/nginx/conf.d/
:
nano /etc/nginx/conf.d/apache-server.conf
Quindi incollate questo test, modificate il nome del dominio secondo necessità e salvatelo:
upstream apache-server {
server apache-server.lxd:80;
}
server {
listen 80 proxy_protocol;
listen [::]:80 proxy_protocol;
server_name apache.server.test; #< Your domain goes here
location / {
proxy_pass http://apache-server;
proxy_redirect off;
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;
}
}
Vediamo di scomporlo un po':
- La sezione
upstream
definisce esattamente dove il reverse proxy invierà tutto il suo traffico. In particolare, invia il traffico al nome di dominio interno del container "apache-server":apache-server.lxd
. - Le due righe che iniziano con
listen
indicano al server di ascoltare il traffico in arrivo sulla porta 80 con il protocollo proxy. La prima via IPv4 e la seconda via IPv6. - La funzione
server_name
prende tutto il traffico che arriva specificamente da "apache.server.test" e lo instrada attraverso il reverse proxy. - La funzione
proxy-pass
è la parte che dirige effettivamente tutto il traffico catturato dalla variabileserver_name
e lo invia al server definito nella sezioneupstream
. - La funzione
proxy_redirect
può apparentemente interferire con i reverse proxy, quindi ci assicuriamo che sia disattivata. - Tutte le opzioni
proxy-set-header
inviano al server web informazioni come l'IP dell'utente e altro.
Attenzione
Il valore proxy_protocol
nelle variabili listen
è essenziale per il funzionamento del server proxy. Non lasciarlo mai fuori.
Per ogni file di configurazione di LXD/sito web, è necessario modificare le impostazioni di upstream
, server
, server_name
e proxy_pass
. Il testo dopo "http://" in proxy-pass
deve corrispondere al testo che viene dopo il testo upstream
.
Ricaricare il server con systemctl restart nginx
, quindi puntare il browser sul dominio che si sta usando al posto di apache.server.test
. Se la pagina ha questo aspetto, il successo è assicurato:
Nota
È possibile assegnare ai file di configurazione il nome che si preferisce. Per le esercitazioni sto usando nomi semplificati, ma alcuni sysadmin raccomandano nomi basati sul dominio attuale, ma al contrario. È un'organizzazione basata sull'ordine alfabetico.
es. "apache.server.test" otterrebbe un file di configurazione chiamato test.server.apache.conf
.
Direzione del traffico al server Nginx¶
Ripetere il procedimento. Creare un file come in precedenza:
nano /etc/nginx/conf.d/nginx-server.conf
Aggiungere il testo appropriato:
upstream nginx-server {
server rocky-nginx.lxd:80;
}
server {
listen 80 proxy_protocol;
listen [::]:80 proxy_protocol;
server_name nginx.server.test; #< Your domain goes here
location / {
proxy_pass http://nginx-server;
proxy_redirect off;
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;
}
}
Di nuovo, ricaricate il server proxy, puntate il browser all'indirizzo appropriato e auguratevi di vedere questo:
Riavviare i server nei container che ospitano il server web¶
Uscire dal container "proxy-server" e riavviare i server negli altri due container con un semplice comando:
lxc exec apache-server systemctl restart httpd && lxc exec nginx-server restart nginx
Questo applicherà i file "real-ip.conf" che abbiamo creato nelle rispettive configurazioni dei server.
Ottenere i certificati SSL per i tuoi siti web¶
Ottenere certificati SSL ufficiali e corretti è più facile con Let's Encrypt e una piccola applicazione chiamata certbot. certbot rileva automaticamente i vostri siti web, ottiene i certificati SSL e configura i siti stessi. Rinnova anche i certificati per voi ogni 30 giorni circa, senza alcun intervento da parte vostra o cron job.
Tutto questo deve essere fatto dal container "proxy-server", quindi si deve accedere a quella shell. Una volta lì, installare i repository EPEL, proprio come si è fatto sull'host. Assicurarsi che il container sia stato prima aggiornato:
dnf update
Quindi, aggiungere il repository EPEL:
dnf install epel-release
Quindi è sufficiente installare certbot e il suo modulo Nginx:
dnf install certbot python3-certbot-nginx
Una volta installato, se si dispone già di un paio di siti web configurati, è sufficiente eseguirlo:
certbot --nginx
Certbot leggerà la configurazione di Nginx e capirà quanti siti web avete e se hanno bisogno di certificati SSL. A questo punto, vi saranno poste alcune domande. Accettate i termini di servizio, volete ricevere e-mail, ecc?
Le domande più importanti sono le seguenti. Inserite il vostro indirizzo e-mail quando vedete questo:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
(Enter 'c' to cancel):
Qui è possibile scegliere per quali siti web ottenere i certificati. Basta premere invio per ottenere i certificati per tutti quanti.
Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: apache.server.test
2: nginx.server.test
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel):
Verrà visualizzato un testo di conferma e la procedura sarà conclusa. Ma se andate sui vostri siti web, potreste scoprire che non funzionano. Questo perché quando certbot crea la configurazione aggiornata, dimentica una cosa molto importante.
Andate nei file apache-server.conf
e nginx-server.conf
e trovate le due righe seguenti:
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
Sì, manca l'impostazione proxy_protocol
e questo non va bene. Aggiungetelo voi stessi.
listen proxy_protocol [::]:443 ssl ipv6only=on; # managed by Certbot
listen proxy_protocol 443 ssl; # managed by Certbot
Salvate il file, riavviate il server e i vostri siti web si caricheranno senza problemi.
Note¶
- In questa guida non ho parlato molto della configurazione dei server web. Il minimo che si dovrebbe fare, in produzione, è cambiare i nomi dei domini nei file di configurazione del server nei container del server web vero e proprio, e non solo nel container proxy. E magari impostare un utente del server web in ciascuno di essi.
- Se volete saperne di più sulla gestione manuale dei certificati SSL e delle configurazioni dei server SSL, consultate la nostra guida all'installazione di certbot e alla generazione dei certificati SSL.
- Applicazioni come Nextcloud richiedono una configurazione aggiuntiva (per motivi di sicurezza) se vengono inserite in un contenitore LXD dietro un proxy.
Conclusione¶
C'è molto altro da imparare su LXC/LXD, sulla containerizzazione, sui server web e sull'esecuzione dei siti web, ma questo dovrebbe essere un buon inizio. Una volta appreso come deve essere impostato tutto e come configurare le cose nel modo desiderato, si può anche iniziare ad automatizzare il processo.
Potreste usare Ansible, oppure essere come me e avere una serie di script scritti su misura da eseguire per rendere tutto più veloce. È anche possibile creare piccoli "container modello" con tutti i software preferiti preinstallati, per poi copiarli ed espanderne la capacità di archiviazione in base alle esigenze.
Va Bene. Questo è fatto. Io sono fuori per giocare a videogiochi. Buon divertimento!
Author: Ezequiel Bruni
Contributors: Steven Spencer, Ganna Zhyrnova