diff --git a/docs/source/3_dev/2_structure/1_backend/index.rst b/docs/source/3_dev/2_structure/1_backend/index.rst index 10a8d9a..fe5cc80 100644 --- a/docs/source/3_dev/2_structure/1_backend/index.rst +++ b/docs/source/3_dev/2_structure/1_backend/index.rst @@ -19,6 +19,8 @@ Inoltre, effettua le seguenti operazioni in risposta a determinate richieste eff - *configurazione*, *avvio* e *arresto* di container Docker basati sulle immagini specificate dai notebook; - *configurazione*, *attivazione* e *disattivazione* del servizio di proxying effettuato dal :ref:`modulo proxy`. +È collocato all'interno del repository in ``/backend``. + Librerie e tecnologie utilizzate -------------------------------- diff --git a/docs/source/3_dev/2_structure/2_frontend/index.rst b/docs/source/3_dev/2_structure/2_frontend/index.rst index 6de68d3..1d8aedd 100644 --- a/docs/source/3_dev/2_structure/2_frontend/index.rst +++ b/docs/source/3_dev/2_structure/2_frontend/index.rst @@ -6,6 +6,8 @@ Il *modulo frontend* consiste in una interfaccia web che consente agli utenti di Si è cercato di renderla più user-friendly possibile, cercando di comunicare più informazioni possibili all'utente attraverso colori e icone, rendendo possibile apprendere ad utilizzare l'interfaccia intuitivamente. +È collocato all'interno del repository in ``/frontend``. + Librerie e tecnologie utilizzate -------------------------------- diff --git a/docs/source/3_dev/2_structure/3_proxy/index.rst b/docs/source/3_dev/2_structure/3_proxy/index.rst index fb2652a..0a15e51 100644 --- a/docs/source/3_dev/2_structure/3_proxy/index.rst +++ b/docs/source/3_dev/2_structure/3_proxy/index.rst @@ -3,17 +3,109 @@ Modulo proxy Il *modulo proxy* consiste in un webserver che riceve tutte le richieste HTTP dirette ad uno degli altri moduli e le smista in base a regole statiche e dinamiche. +È collocato all'interno del repository in ``/proxy``. + Tecnologie utilizzate --------------------- -- Il server web `Apache HTTPd `_ - - Il modulo `mod_rewrite `_ - - Il modulo `mod_proxy `_ - - Il modulo `mod_proxy_http `_ - - Il modulo `mod_proxy_wstunnel `_ +- Il server web `Apache HTTPd`_ + - Il modulo `rewrite`_ + - Il modulo `proxy`_ + - Il modulo `proxy_http`_ + - Il modulo `proxy_wstunnel`_ + +.. _Apache HTTPd: https://httpd.apache.org/ +.. _rewrite: https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html +.. _proxy: https://httpd.apache.org/docs/2.4/mod/mod_proxy.html +.. _proxy_http: https://httpd.apache.org/docs/2.4/mod/mod_proxy_http.html +.. _proxy_wstunnel: https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html Funzionamento del modulo ------------------------ +Il modulo proxy è composto da un file di configurazione di `Apache HTTPd`_ e di un ``Dockerfile`` che lo copia all'interno dell'immagine Docker ufficiale ``httpd:2.4``. + +Il file di configurazione abilita i moduli `rewrite`_, `proxy`_, `proxy_wstunnel`_ e `proxy_http`_, impostando quest'ultimo per inoltrare l'header `Host `_ alle pagine verso cui viene effettuato reverse proxying. + +Inoltre, nel file di configurazione viene abilitato il ``RewriteEngine``, che viene utilizzato per effettuare reverse proxying secondo le seguenti regole: + +#. Tutte le richieste verso ``static.`` prefisso ad :ref:`\`\`APACHE_PROXY_BASE_DOMAIN\`\`` vengono processate direttamente dal webserver, utilizzando i file disponibili nella cartella ``/var/www/html/django-static`` che gli vengono forniti dal volume ``django-static`` del :ref:`modulo backend`. + + .. code-block:: apacheconf + + # If ENV:APACHE_PROXY_BASE_DOMAIN equals HTTP_HOST + RewriteCond "static.%{ENV:APACHE_PROXY_BASE_DOMAIN} %{HTTP_HOST}" "^([^ ]+) \1$" [NC] + # Process the request yourself + RewriteRule ".?" - [L] + +#. Tutte le richieste verso :ref:`\`\`APACHE_PROXY_BASE_DOMAIN\`\`` senza nessun sottodominio vengono inoltrate al container Docker del :ref:`modulo frontend` utilizzando la risoluzione dei nomi di dominio di Docker Compose. + + .. code-block:: apacheconf + + # If ENV:APACHE_PROXY_BASE_DOMAIN equals HTTP_HOST + RewriteCond "%{ENV:APACHE_PROXY_BASE_DOMAIN} %{HTTP_HOST}" "^([^ ]+) \1$" [NC] + # Capture ENV:SOPHON_FRONTEND_NAME for substitution in the rewriterule + RewriteCond "%{ENV:SOPHON_FRONTEND_NAME}" "^(.+)$" [NC] + # Forward to the frontend + RewriteRule "/(.*)" "http://%1/$1" [P,L] + +#. Tutte le richieste verso ``api.`` prefisso ad :ref:`\`\`APACHE_PROXY_BASE_DOMAIN\`\`` vengono inoltrate al container Docker del :ref:`modulo backend` utilizzando la risoluzione dei nomi di dominio di Docker Compose. + + .. code-block:: apacheconf + + # If api. prefixed to ENV:APACHE_PROXY_BASE_DOMAIN equals HTTP_HOST + RewriteCond "api.%{ENV:APACHE_PROXY_BASE_DOMAIN} %{HTTP_HOST}" "^([^ ]+) \1$" [NC] + # Capture ENV:SOPHON_BACKEND_NAME for substitution in the rewriterule + RewriteCond "%{ENV:SOPHON_BACKEND_NAME}" "^(.+)$" [NC] + # Forward to the backend + RewriteRule "/(.*)" "http://%1/$1" [P,L] + +#. Carica in memoria la rubrica dei notebook generata dal :ref:`modulo backend` e disponibile in ``/run/sophon/proxy/proxy.dbm`` attraverso il volume ``proxy-data``, assegnandogli il nome di ``sophonproxy``. + + .. code-block:: apacheconf + + # Create a map between the proxy file generated by Sophon and Apache + RewriteMap "sophonproxy" "dbm=gdbm:/run/sophon/proxy/proxy.dbm" + +#. Effettua il proxying dei websocket verso i notebook mappati dalla rubrica ``sophonproxy``. + + .. code-block:: apacheconf + + # If this is any other subdomain of ENV:APACHE_PROXY_BASE_DOMAIN + RewriteCond ".%{ENV:APACHE_PROXY_BASE_DOMAIN} %{HTTP_HOST}" "^([^ ]+) [^ ]+\1$" [NC] + # If this is a websocket connection + RewriteCond "%{HTTP:Connection}" "Upgrade" [NC] + RewriteCond "%{HTTP:Upgrade}" "websocket" [NC] + # Forward to the notebook + RewriteRule "/(.*)" "ws://${sophonproxy:%{HTTP_HOST}}/$1" [P,L] + +#. Effettua il proxying delle richieste "normali" verso i notebook mappati dalla rubrica ``sophonproxy``. + + .. code-block:: apacheconf + + # If this is any other subdomain of ENV:APACHE_PROXY_BASE_DOMAIN + RewriteCond ".%{ENV:APACHE_PROXY_BASE_DOMAIN} %{HTTP_HOST}" "^([^ ]+) [^ ]+\1$" [NC] + # Forward to the notebook + RewriteRule "/(.*)" "http://${sophonproxy:%{HTTP_HOST}}/$1" [P,L] + +Tutte le regole usano il flag ``L`` di ``RewriteRule``, che porta il motore di rewriting a ignorare tutte le regole successive, come il ``return`` di una funzione di un linguaggio di programmazione imperativo. + +.. note:: + + I blocchi di codice all'interno di questa sezione sono stati inseriti manualmente e potrebbero non essere interamente aggiornati alla versione più recente del file. + + Si consiglia di consultare il file ``httpd.conf`` in caso si necessiti di informazioni aggiornate. + + +Continuous Deployment +--------------------- + +L'immagine del modulo viene automaticamente ricompilata da GitHub Actions e pubblicata su GitHub Containers ogni volta che un file all'interno della cartella del modulo viene modificato. + +Questo workflow è definito all'interno del file ``.github/workflows/build-docker-proxy.yml``. + +.. seealso:: + + `La pagina del container `_ su GitHub Containers. diff --git a/docs/source/3_dev/2_structure/4_jupyter/index.rst b/docs/source/3_dev/2_structure/4_jupyter/index.rst index 4e9806f..632fbff 100644 --- a/docs/source/3_dev/2_structure/4_jupyter/index.rst +++ b/docs/source/3_dev/2_structure/4_jupyter/index.rst @@ -1,16 +1,89 @@ Modulo Jupyter ============== -Il *modulo Jupyter* consiste in un ambiente `Jupyter `_ e `JupyterLab `_ modificato per una migliore integrazione con Sophon. +Il *modulo Jupyter* consiste in un ambiente `Jupyter `_ e `JupyterLab `_ modificato per una migliore integrazione con Sophon, in particolare con il :ref:`modulo frontend` e il :ref:`modulo backend`. +È collocato all'interno del repository in ``/jupyter``. Progetti utilizzati ------------------- - Le immagini Docker ufficiali di Jupyter `jupyter/docker-stacks `_ -- Il tema `jupyterlab-theme-sophon `_ (realizzato durante il tirocinio) +- Il tema `JupyterLab Sophon `_ (realizzato durante il tirocinio) - Il tool per il trasferimento dati `curl `_ Funzionamento del modulo ------------------------ + +Il modulo è composto da un singolo ``Dockerfile`` che crea un immagine Docker in quattro fasi: + +#. **Base**: Parte dall'immagine base ``jupyter/scipy-notebook`` ed altera i label dell'immagine; + + .. code-block:: docker + + FROM jupyter/scipy-notebook AS base + # Set the maintainer label + LABEL maintainer="Stefano Pigozzi " + +#. **Env**: Configura le variabili di ambiente dell'immagine, dando il nome "sophon" all'utente non-privilegiato, attivando JupyterLab, configurando il riavvio automatico di Jupyter e permettendo all'utente non-privilegiato di acquisire i privilegi di root attraverso il comando ``sudo``; + + .. code-block:: docker + + FROM base AS env + # Override the default "jovyan" user + ARG NB_USER="sophon" + # Set useful envvars for Sophon notebooks + ENV JUPYTER_ENABLE_LAB=yes + ENV RESTARTABLE=yes + ENV GRANT_SUDO=yes + +#. **Extensions**: Installa, abilita e configura le estensioni necessarie all'integrazione con Sophon (attualmente, soltanto il tema JupyterLab Sophon); + + .. code-block:: docker + + FROM env AS extensions + # As the default user... + USER ${NB_UID} + WORKDIR "${HOME}" + # Install the JupyterLab Sophon theme + RUN jupyter labextension install "jupyterlab_theme_sophon" + # Enable the JupyterLab Sophon theme + RUN jupyter labextension enable "jupyterlab_theme_sophon" + # Set the JupyterLab Sophon theme as default + RUN mkdir -p '.jupyter/lab/user-settings/@jupyterlab/apputils-extension/' + RUN echo '{"theme": "JupyterLab Sophon"}' > ".jupyter/lab/user-settings/@jupyterlab/apputils-extension/themes.jupyterlab-settings" + +#. **Healthcheck**: Installa ``curl``, e aggiunge all'immagine un controllo per verificarne lo stato di avvio, permettendo al :ref:`modulo backend` di comunicare una richiesta di avvio riuscita solo quando l'intera immagine è avviata + + .. code-block:: docker + + FROM extensions AS healthcheck + # As root... + USER root + # Install curl + RUN apt-get update + RUN apt-get install -y curl + # Use curl to check the health status + HEALTHCHECK --start-period=5s --timeout=5s --interval=10s CMD ["curl", "--output", "/dev/null", "http://localhost:8888"] + + # We probably should go back to the default user + USER ${NB_UID} + +.. note:: + + I blocchi di codice all'interno di questa sezione sono stati inseriti manualmente e potrebbero non essere interamente aggiornati alla versione più recente del file. + + Si consiglia di consultare il ``Dockerfile`` in caso si necessiti di informazioni aggiornate. + + +Continuous Deployment +--------------------- + +L'immagine del modulo viene automaticamente ricompilata da GitHub Actions e pubblicata su GitHub Containers ogni volta che un file all'interno della cartella del modulo viene modificato. + +Questo workflow è definito all'interno del file ``.github/workflows/build-docker-jupyter.yml``. + +.. seealso:: + + `La pagina del container `_ su GitHub Containers. diff --git a/docs/source/3_dev/3_differences/index.rst b/docs/source/3_dev/3_differences/index.rst new file mode 100644 index 0000000..1bcceb2 --- /dev/null +++ b/docs/source/3_dev/3_differences/index.rst @@ -0,0 +1,27 @@ +Differenze da altri progetti simili +*********************************** + +Sophon a prima vista può sembrare simile ad altri progetti già esistenti, ma si differenzia in alcune particolarità del suo funzionamento. + + +Differenze da JupyterHub +======================== + +`JupyterHub`_ è un progetto con scopi molto simili a quelli di Sophon, ovvero di permettere a tanti utenti di utilizzare `Jupyter`_ su un server remoto, ma ha funzionalità di autorizzazione molto semplici e non ha supporto per :ref:`collaborazione` in tempo reale, in quanto i server `Jupyter`_ che istanzia sono single-user. + +È però più facile da scalare per grandi numeri di utenti, e ha più opzioni di deployment, a differenza di Sophon, che ne supporta una sola. + +.. _JupyterHub: https://jupyter.org/hub +.. _Jupyter: https://jupyter.org/ + + +Differenze da Google Colab +========================== + +`Google Colab`_ è un progetto che permette di effettuare ricerca su server `Jupyter`_ utilizzando le risorse della `Google Cloud Platform`_. + +A differenza di Sophon, è disponibile esclusivamente come `software-as-a-service`_, il che costringe agli utenti a trasmettere le loro informazioni ai server di Google, e non ha alcun tipo di supporto alla :ref:`collaborazione` in tempo reale. + +.. _Google Colab: https://colab.research.google.com/# +.. _Google Cloud Platform: https://cloud.google.com/ +.. _software-as-a-service: https://it.wikipedia.org/wiki/Software_as_a_service diff --git a/docs/source/3_dev/4_license/index.rst b/docs/source/3_dev/4_license/index.rst new file mode 100644 index 0000000..a7eb7e4 --- /dev/null +++ b/docs/source/3_dev/4_license/index.rst @@ -0,0 +1,12 @@ +Licenza +******* + +Sophon è rilasciato sotto la `GNU Affero General Public License 3`_ (o successiva). + +Il testo completo della licenza è disponibile all'interno del file `LICENSE.txt`_ allegato al codice sorgente del software. + +Si specifica che la licenza copre tutti i file all'interno del repository ``Steffo99/sophon``, anche se essi non contengono un header che indica che sono protetti da copyright. + + +.. _GNU Affero General Public License 3: https://www.gnu.org/licenses/agpl-3.0.html +.. _LICENSE.txt: https://github.com/Steffo99/sophon/blob/main/LICENSE.txt diff --git a/jupyter/Dockerfile b/jupyter/Dockerfile index 551dcc1..d3c8d1b 100644 --- a/jupyter/Dockerfile +++ b/jupyter/Dockerfile @@ -30,7 +30,7 @@ RUN echo '{"theme": "JupyterLab Sophon"}' > ".jupyter/lab/user-settings/@jupyter FROM extensions AS healthcheck # As root... USER root -# Install cURL +# Install curl RUN apt-get update RUN apt-get install -y curl # Use curl to check the health status diff --git a/proxy/httpd.conf b/proxy/httpd.conf index 47e9cc2..f2b8ba9 100644 --- a/proxy/httpd.conf +++ b/proxy/httpd.conf @@ -571,13 +571,13 @@ RewriteRule ".?" - [L] # Process the request yourself # sophon.steffo.eu → frontend RewriteCond "%{ENV:APACHE_PROXY_BASE_DOMAIN} %{HTTP_HOST}" "^([^ ]+) \1$" [NC] # If ENV:APACHE_PROXY_BASE_DOMAIN equals HTTP_HOST RewriteCond "%{ENV:SOPHON_FRONTEND_NAME}" "^(.+)$" [NC] # Capture ENV:SOPHON_FRONTEND_NAME for substitution in the rewriterule -RewriteRule "/(.*)" "http://%1/$1" [P,L] # Rewrite as a SPA and set the matched flag +RewriteRule "/(.*)" "http://%1/$1" [P,L] # Forward to the frontend # Proxy api requests to the backend # api.sophon.steffo.eu → backend RewriteCond "api.%{ENV:APACHE_PROXY_BASE_DOMAIN} %{HTTP_HOST}" "^([^ ]+) \1$" [NC] # If api. prefixed to ENV:APACHE_PROXY_BASE_DOMAIN equals HTTP_HOST RewriteCond "%{ENV:SOPHON_BACKEND_NAME}" "^(.+)$" [NC] # Capture ENV:SOPHON_BACKEND_NAME for substitution in the rewriterule -RewriteRule "/(.*)" "http://%1/$1" [P,L] # Rewrite and set the matched flag +RewriteRule "/(.*)" "http://%1/$1" [P,L] # Forward to the backend # Create a map between the proxy file generated by Sophon and Apache RewriteMap "sophonproxy" "dbm=gdbm:/run/sophon/proxy/proxy.dbm" @@ -587,9 +587,9 @@ RewriteMap "sophonproxy" "dbm=gdbm:/run/sophon/proxy/proxy.dbm" RewriteCond ".%{ENV:APACHE_PROXY_BASE_DOMAIN} %{HTTP_HOST}" "^([^ ]+) [^ ]+\1$" [NC] # If this is any other subdomain of ENV:APACHE_PROXY_BASE_DOMAIN RewriteCond "%{HTTP:Connection}" "Upgrade" [NC] # If this is a websocket connection RewriteCond "%{HTTP:Upgrade}" "websocket" [NC] # If this is a websocket connection -RewriteRule "/(.*)" "ws://${sophonproxy:%{HTTP_HOST}}/$1" [P,L] # Rewrite and set the matched flag +RewriteRule "/(.*)" "ws://${sophonproxy:%{HTTP_HOST}}/$1" [P,L] # Forward to the notebook # Proxy regular requests to the notebooks # *.sophon.steffo.eu → notebook RewriteCond ".%{ENV:APACHE_PROXY_BASE_DOMAIN} %{HTTP_HOST}" "^([^ ]+) [^ ]+\1$" [NC] # If this is any other subdomain of ENV:APACHE_PROXY_BASE_DOMAIN -RewriteRule "/(.*)" "http://${sophonproxy:%{HTTP_HOST}}/$1" [P,L] +RewriteRule "/(.*)" "http://${sophonproxy:%{HTTP_HOST}}/$1" [P,L] # Forward to the notebook