# Migrazione delle Piattaforma Geonode SDI di Techfem
La seguente documentazione descrive le opertazioni di base per predisporre un ambiente di esecuzione per la piattaforma **Techfem SDI** per la condivisione di dati geospazioani aziendale.
La piattaforma è basata sul progetto [GeoNode](https://geonode.org/), soluzione Open Source per implemenetare sistemi GIS (Geospatial Information Systems) e SDI (Spatial Data Infrastructures) ed è stata inizialmente sviluppata e personalizzata da [Geodatalab S.r.l](https://www.geodatalab.it/).
Di seguito vengono riportate le operazioni principali per migrare o reinstallare il sistema da zero, su un host dedicato on-premises o su infrastruttura cloud proprietaria, partendo dal codice sorgente del progetto. Per informazioni dettagliate sull'utilizzo e sulle funzionalità della piattaforma si rimanda invece alla documentazione ufficiale.
Le istruzioni fornite sono relative a sistemi in ambiente GNU/Linux, architettura x86_64 (64 bit) e sistema operativo Ubuntu 18.04 LTS o successivo con Linux kernel dalla versione 5.10 in poi e supporto ai sistemi di containerizzazione basati su [Docker](https://www.docker.com/). Tuttavia, le procedure di configurazione dovrebbero essere facilmente adattabili anche ad altri sistemi Debian-based o sistemi basati su CentOS a patto di predisporre i pacchetti con le dipendenze minime di Geonode (vedi [documentazione](https://docs.geonode.org/en/master/install/basic/index.html)).
## Accesso SSH all'istanza
Ipotizzando di aver già avviato l'host di destinazione della piattaforma dalla console di gestione della propria area personale sul provider cloud, è necessario instaurare la prima connessione alla macchina. In base al servizio scelto, è possibile che sia disponibile una applicazione web di amministrazione remota dell'host per gestire ogni aspetto del sistema. Le più comuni sono:
* [CPanel](https://cpanel.net/)
* [Webmin](https://webmin.com/)
* [Plesk](https://www.plesk.com/)
Ad ogni modo, anche in presenza di quesi strumenti, si consiglia di procedere all'accesso utilizzando il protocollo SSH (Secure Shell) a riga di comando.
Per farlo è necessario disporre di un client SSH sul proprio pc per connettersi all'host remoto in cloud. Sui sistemi GNU/Linux è quasi sempre presente il client SSH di OpenSSH già preinstallato. Lo stesso avviene per MacOs. Aprire il proprio terminale e verificare la presenza del client digitando il seguente comando:
```shell
ssh -V
```
I sistemi Windows dalla versione 10 intetrano un client nella *PowerShell*. Per quelli meno recenti si pu usare [PuTTY](https://www.putty.org/)
Se il client è disponibile, per instaurare la connessione all'host, la sintassi è la seguente:
```shell
ssh user@host
```
*User e Host sono forniti dal provider*
Confermare digitando `yes` (solo la prima volta) e quindi la password di accesso per l'utente, di solito fornita dal provider del cloud. Se la connessione ha successo, il terminale visualizza il prompt dell'host remoto ed è possibile procedere con la guida.
### Configurazione dell'accesso tramite chiave pubblica/privata
L'autenticazione dell'utente tramite SSH può avvenire in diversi modi. Per connessioni sporadiche o per i primi accessi è facile ricorrere all'autenticazione tramite password. Tuttavia, questa modalità è sconsigliata per diversi ragioni: se non viene disabilitata, espone l'host remoto e il server SSH ad attacchi di tipo Brute force; La richiesta interattiva di inserimento password ad ogni accesso impedisce anche le automazioni più semplici.
Per superare queste limitazioni, configurare l'accesso per l'utilizzo di una chiave pubblico/privata e disabilitare l'autenticazione basata su username/password.
*Le istruzioni seguenti presuppongono l'uso del client OpenSSH su GNU/Linux o su MacOS*
Generare una coppia di chiavi sul proprio host digitando il comando seguente e accettando i valori di predefiniti:
```shell
ssh-keygen -t RSA
```
il comando genera due file nella home utente
| Path | Key |
| --------------------- | ------------ |
| `~/.ssh/id_rsa` | Private key |
| `~/.ssh/id_rsa.pub` | Public key |
La chiave pubblica (e solo la chiave pubblica) deve essere trasferita anche sull'host remoto con il comando:
```shell
ssh-copy-id -i ~/.ssh/id_rsa.pub user@host
```
Ciò aggiunge la chiave all'elenco delle chiavi accettate dal server SSH cui ci si vuole loggare (`~/.ssh/authorized_keys`)
A questo punto dovrebbe essere possibile loggarsi senza che venga richiesta la password e a patto che la chiave privata sia nella directory `~/.ssh`.
Se il login funziona, disabilitare l'autenticazione tramite password sul server SSH sull'host (si veda la documentazione ufficiale `man ssh`).
### Usare il file Config di SSH
Se ci si collega di frequente o si devono gestire molti server è possibile configurare i propri host preferiti per l'accesso rapido e richiamarli con un nome mnemonico, aggiungendo una sezione al file `~/.ssh/config`.
Aprire il file con un qualunque editor di testo ed appendere le seguenti righe:
```shell=
Host mycloud ## assegnare un nome corto e semplice
HostName <host-ip-address>
User <user>
```
Come `host-ip-address` si può usare sia l'indirizzo IP pubblico o il nome host dns pubblico, entrambi reperibili dalla console del provider.
A questo punto è possibile accedere al proprio server in modo rapido e senza password
```shell
ssh mycloud
```
### Disabilitare l'accesso SSH per Superuser (root)
Alcuni provider forniscono al primo accesso solo sistemi in cui esiste il solo utente **root**, che quindi è l'unico a poter essere utilizzato per accedere all'host in SSH almeno nelle prime connessioni.
Per questioni di sicurezza, è fortemente sconsigliato usare l'utente root per le normali operazioni di gestione. La cosa migliore da fare, già al primo accesso, è quella di aggiungere un utente convenzionale al sistema, eventualmente concedere a quest'ultimo i privilegi di amministratore (vedi il seguito) e usare queste credenziali per le sessioni successive. La possibilità di loggarsi come root direttamente in SSH potrebbe poi essere disabilitata sul server (vedi `man ssh` per ulteriori dettagli). Così facendo si ha un margine di sicurezza migliore ed una futura separazione dei privilegi gestibile, nel caso si debba condividere le credenziali a terzi.
## Creazione di un utente con login dedicata alla piattaforma
Come anticipato, è consigliabile creare un utente dedicato per la gestione della piattaforma ed eseguire le sucessive operazioni tramite un sessione apposita.
Ipotizzando di essere loggati come `root` sull'host remoto, creare un nuovo utente:
```shell=
adduser sdiadmin
```
creare una password per il login
```shell=
passwd sdiadmin
```
quindi aggiungerlo al grupopo dei *sudoers* per concedere i dirutti di superutente:
```shell=
usermod -a -G sudo sdiadmin
```
È ora possibile disconnette la sessione corrente e ricollegardi con l'utente appena creato:
```shell=
ssh sdiadmin@host
```
Configurare il proprio file `~/.ssh/config` per un accesso agevolato come indicato [precedentemente](#Usare-il-file-Config-di-SSH) e seguire anche per questo utente il [paragrafo per l'accesso con chiave pubblico/privata](#Configurazione-dellaccesso-tramite-chiave-pubblicaprivata).
Mettere quindi in sicurezza il server SSH secondo le proprie preferenze anche seguendo i consigli riportati [qui](#Disabilitare-laccesso-SSH-per-Superuser-root).
## Istallazione e configurazione di Docker
Questa parte riprende la documentazione ufficiale per l'installazione di Docker in Ubuntu Linux, disponibile al seguente [link](https://docs.docker.com/engine/install/ubuntu/)
Per il deploy della piattaforma sono necessari almeno i seguenti componenti dell'ecosistema Docker:
1. Docker Engine - ambiente di containerizzazione
2. Docker Compose - strumento per la gestione di immagini e container e riga di comando
Le istruzioni si riferiscono ad Ubuntu 22.04 LTS, ma dovrebbero funzionare anche per versioni adiacenti.
Prima di installare per la prima volta su un nuovo host, effettuare il set up dei repository Docker
```shell=
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
```
Istallare i pacchetti dell'ultima versione
```shell=
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```
e verificare che tutto sia andato istallato correttamente, lanciando un container di prova
```shell=
sudo docker run hello-world
```
### Docker Engine Post-installation steps
Le seguenti operazioni sono necessarie per configurare al meglio Docker in ambiente Linux.
#### Gestire Docker da un utente non-root
Per consentire ad un utente non-root di gestire le operazioni di containerizzazione creare un gruppo `docker` digitando:
```shell=
sudo groupadd docker # il group potrebbe essere già presente
```
quindi aggiungere gli utenti desiderati:
```shell=
sudo usermod -a -G docker sdiadmin
```
Gli utenti coinvolti devono eseguire riloggarsi per consentire al sistema di aggiornare la membership. Verificare quindi con il comando:
```shell=
docker run hello-world
```
#### Avviare Docker al boot con Systemd
Molte distribuzioni Linux moderne usano [systemd](https://systemd.io/) per gestire quali servizi debbano avviarsi in automatico al boot del sistema. Su Debian e Ubuntu, Docker si avvia al boot di default. Per ottenere lo stesso comportamento su altre distribuzioni usando systemd, eseguire i seguenti comandi:
```shell=
sudo systemctl enable docker.service
sudo systemctl enable containerd.service
```
mentre per ottenere l'opposto usare:
```shell=
sudo systemctl disable docker.service
sudo systemctl disable containerd.service
```
#### Configurare il comportamento dei logs
Docker produce diversi file di log e salva sull'host il logs di tutti i container in formato json. Queste funzioni spesso comportano un consumo eccessivo di spazio su disco, soprattutto nei casi in cui lo spazio assegnato ai servizi in cloud non è sufficiente. Per risolvere il problema si può consuare la seguente [guida ufficiale](https://docs.docker.com/engine/install/linux-postinstall/#configure-default-logging-driver) che offre una soluzione per ogni esigenza.
## Codice sorgente
Se l'istallazione di Docker è andata a buon fine è possibile procedere con la fase di setup e deploy della piattaforma.
Copiare il progetto sull'host tramite Git o spostando il paccketto dei sorgenti dalla propria postazione.
### SCP
SCP è un semplice strumento per il trasporto di file e directory tramite SSH. Generalmente il comando è già presente nel terminale perché incluso nel client OpenSSH. Verificare digitando
```shell!
scp -v
```
Per copiare l'archivio con i sorgenti (es. `j` dal proprio host all'host remoto digitare
```shell!
scp geonode-sdi-dev.zip sdiadmin@host:/tmp
```
quindi collegarsi all'host e scompattare l'archivio in una direcotry adeguata all'istallazione (es. `/opt`)
```shell=
sudo unzip -d /opt /tmp/geonode-sdi-dev.zip
cd /opt
mv geonode-sdi-dev geonode-sdi # opzionale
```
### GIT Clone
Verificare che il client di Git sia istallato:
```shell=
git --version
```
spostarsi nella directory prescelta e clonare
```shell=
cd /opt
git clone git@github.com:Techfem-spa/geonode-sdi.git
```
### Re-init e migrazione del repository
Ipotizzando di avere la piattaforma ben configurata e qualora si dovesse re-inizializzare il repository e/o spostarlo su una nuova sorgente remota (ad esempio un nuovo account Github) è possibile procedere nel seguente modo:
```shell=
cd /opt/geonode-sdi
rm -rf .git # rimuove l'attuale configurazione di git
```
assicurarsi che la folder adesso non sia più vista da Git come un repo
```shell=
git status # deve restiruire un FATAL error
```
quindi procedere con una nuova *init* e aggiungere tutti i file
```shell=
git init
git add . # da eseguire in /opt/geonode-sdi
git status # verificare che il tracking sia attivo
```
eseguire il primo commit e rinominare il branch principale in `main`
```shell=
git commit -m "First commit"
git branch -M main
git status # verificare che il working tree sia pulito
```
settare l'url del repo `origin` per upstream e downstream e pushare il commit verso di esso
```shell=
git remote add origin https://github.com/Techfem/geonode-sdi
git push origin main
```
Si noti che, se il repo è gestito sulla piattaforma Github, in caso di repository privato non sarà possibile utilizzare http/https come protocollo di trasporto per le operazioni di `push`, `pull`, ecc. Consulatere la [documentazione ufficiale di Github](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent) LINK per configurare le chiavi di sicurezza tra il server ed un account account Github che possa agire sull'organizzazione.
---
## Deploy di Geonode
### 1. Customizzazione del file .env
Modificare le variabili del file `.env` puntando all'ip o al dominio corretto:
```shell=
GEONODE_LB_HOST_IP=sdi.techfem.it
SITEURL=https://sdi.techfem.it/
#aggiungere l’host in allowed_hosts
ALLOWED_HOSTS=['django', 'localhost', 'sdi.techfem.it', ...]
HTTP_HOST=sdi.techfem.it
HTTPS_HOST=sdi.techfem.it
GEOSERVER_WEB_UI_LOCATION=https://sdi.techfem.it/geoserver/
GEOSERVER_PUBLIC_LOCATION=https://sdi.techfem.it/geoserver/
```
### 2. Docker start
Lanciare il build delle immagini docker e far partire l'istanza di Geonode.
```shell=
docker-compose -f docker-compose.yml up --build -d
```
### 3. Docker rebuild
In caso di cambiamenti nei parametri (ad esempio nei file .env), è necessario fermare e container e effettuare il rebuild. Il comando 'down' rimuove i container dopo averli fermati.
```shell=
docker-compose -f docker-compose.yml -f docker-compose-bckup.yml down
```
Per il rebuild lanciare il seguente comando, dove `-d` lancia in *detached-mode*
```shell=
docker-compose -f docker-compose.yml -f docker-compose-bckup.yml up -d
```
## Setup "GeoNode Mapstore Client" (Non utilizzato nel deploy attuale)
E' innanzitutto necessario avere un'istanza di Geonode avviata.
#### 1. Struttura cartelle
La struttura delle cartelle potrebbe essere.
```
+ opt/
- geonode
- mapstore-client
```
#### 2. Clone del Repository
Fare il clone del repository nel proprio workspace.
`git clone --recursuve git@gitlab.com:geodatalab-geonode/techfem/geomapstore-client.git mapstore-client`
#### 3. Far puntare l'installazione di Geonode al fork del mapstore-client
Per fare questo è necessario modificare il 'requirements.txt' sotto `/opt/geonode`.
In particolare, questo requisito:
```
#GeoNode org maintained apps.
django-geonode-mapstore-client==3.2.1
```
diventa:
```
#GeoNode org maintained apps.
-e git+https://pmimapstore:kdmLnLp3x1nw9ZLUvHJH@gitlab.com/geodatalab-geonode/techfem/geomapstore-client.git@master#egg=django_geonode_mapstore_client
```
Dove l'url del repo è proceduto da un token generato appositamente.
## BACKUP-RESTORE (DA VERIFICARE)
### 1. BACKUP (Daily)
#### SETUP
The backup use two containers that are defined as docker-compose overwrite `docker-compose-bckup.yml`:
- schedular : `mcuadros/ofelia:latest`
- uploader : based on alpine with aws cli
The change on the env
```
AWS_ACCESS_KEY_ID=b90ebf6e3d024c8786230a142436272d
AWS_SECRET_ACCESS_KEY=ad54b90089d31329ac953af3fed8df73
AWS_BUCKET_NAME=backup
AWS_PATH=techfem
```
**AWS_PATH** should be the name of the directory
more detail about the upload script can be seen [uploadtos3.sh](script-backups/uploadtos3.sh)
#### RUN THE PROJECT IN PRODUCTION
```docker-compose -f docker-compose.yml -f docker-compose-bckup.yml up -d```
### 2. RESTORE
a. Download tar from s3
b. Extract
```
data
datadir
geolib
geonode_data.sql
geonode.sql
uploaded
```
c. restore db
```bash
docker-compose -f docker-compose.yml up -d db
```
```
docker cp geonode.sql db4geonode:/tmp/
docker cp geonode_data.sql db4geonode:/tmp/
docker exec -it db4geonode psql -U postgres -d geonode -f /tmp/geonode.sql
docker exec -it db4geonode psql -U postgres -d geonode_data -f /tmp/geonode_data.sql
```
d. Copy volumes
```
datadir -> /var/lib/docker/volumes/geonode-gsdatadir/_data
data -> /var/lib/docker/volumes/geonode-data/_data
uploaded -> /var/lib/docker/volumes/geonode-statics/_data (the folder not the content)
geolib -> /var/lib/docker/volumes/geonode-glib/_data
```
e.
The above backup does copy the followings:
| Container | File | Type |
|-------------------|---------------------|-----------|
| db4geonode | geonode.sql | sql |
| db4geonode | geonode_data.sql | sql |
| django4geonode | uploaded | directory |
| geoserver4geonode | geoserver_data/data | directory |
| geoserver4geonode | data | directory |
| geoserver4geonode | lib | directory |
#### NOTE (per migrazione originale)
- Before restoring the database as only for this project we need to create a new ROLE called *qgis_data*
- Be sure this user has all the privileges on schemas qgis_data and public.
```sql
GRANT ALL PRIVILEGES ON SCHEMA qgis_data TO qgis_data;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA qgis_data TO qgis_data;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA qgis_data TO qgis_data;
GRANT ALL PRIVILEGES ON SCHEMA public TO qgis_data;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO qgis_data;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO qgis_data;
```
A procedure calculates, given a layer, the list of permissions needed for that area. Set the following role to make this procedure fully work.
```sql
SET ROLE geonode_data;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO qgis_data;
```
- For "Direzione Lavori", a new ROLE called *dlproc* should be created and it should have access to dlproc schema.
```sql
GRANT USAGE ON SCHEMA dlproc TO dlproc;
GRANT SELECT ON ALL TABLES IN SCHEMA dlproc TO dlproc;
```
## Installazione PIMGIS PLUGIN
Aggiungere le info per scaricare l'ultima versione del zip contente il plugin