diff --git a/doc/backends.rst b/doc/backends.rst index c3e19a9b..0c2a673f 100644 --- a/doc/backends.rst +++ b/doc/backends.rst @@ -1,11 +1,12 @@ Backends ############# +Canaille can read and save data in different databases. +This page presents the different database backends and their specificities: + .. contents:: :local: -Canaille can read and save data in different databases: - Memory ====== diff --git a/doc/conf.py b/doc/conf.py index 0da72a15..f26af869 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -27,6 +27,7 @@ sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES) extensions = [ "sphinx.ext.autodoc", + "sphinx.ext.autosectionlabel", "sphinx.ext.doctest", "sphinx.ext.graphviz", "sphinx.ext.intersphinx", @@ -52,6 +53,10 @@ todo_include_todos = False intersphinx_mapping = { "python": ("https://docs.python.org/3", None), + "authlib": ("https://docs.authlib.org/en/latest", None), + "flask": ("https://flask.palletsprojects.com", None), + "flask-babel": ("https://python-babel.github.io/flask-babel", None), + "flask-wtf": ("https://flask-wtf.readthedocs.io", None), } issues_uri = "https://gitlab.com/yaal/canaille/-/issues/{issue}" @@ -94,3 +99,8 @@ texinfo_documents = [ "Miscellaneous", ) ] + +# -- Options for autosectionlabel ----------------------------------------- + +autosectionlabel_prefix_document = True +autosectionlabel_maxdepth = 2 diff --git a/doc/deployment.rst b/doc/deployment.rst new file mode 100644 index 00000000..60bb8a2d --- /dev/null +++ b/doc/deployment.rst @@ -0,0 +1,165 @@ +Deployment +########## + +Application service +=================== + +After having finished Canaille installation you have to run it in a WSGI application server. +Here are some WSGI server configuration examples you can pick. Do not forget to update the paths. + +gunicorn +-------- + +TBD + +uwsgi +----- + +.. code-block:: ini + + [uwsgi] + virtualenv=/opt/canaille/env + socket=/etc/canaille/uwsgi.sock + plugin=python3 + module=canaille:create_app() + lazy-apps=true + master=true + processes=1 + threads=10 + need-app=true + thunder-lock=true + touch-chain-reload=/etc/canaille/uwsgi-reload.fifo + enable-threads=true + reload-on-rss=1024 + worker-reload-mercy=600 + buffer-size=65535 + disable-write-exception = true + env = CONFIG=/etc/canaille/config.toml + +Webserver +========= + +Now you have to plug your WSGI application server to your webserver so it is accessible on the internet. +Here are some webserver configuration examples you can pick: + +Nginx +----- + +.. code-block:: nginx + + server { + listen 80; + listen [::]:80; + server_name auth.mydomain.tld; + return 301 https://$server_name$request_uri; + } + + server { + server_name auth.mydomain.tld; + + listen 443 ssl http2; + listen [::]:443 ssl http2; + + ssl_certificate /etc/letsencrypt/live/moncompte.nubla.fr/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/moncompte.nubla.fr/privkey.pem; + ssl_session_timeout 1d; + ssl_session_cache shared:MozSSL:10m; # about 40000 sessions + ssl_session_tickets off; + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; + ssl_prefer_server_ciphers off; + ssl_stapling on; + ssl_stapling_verify on; + + index index.html index.php; + charset utf-8; + client_max_body_size 10M; + + access_log /opt/canaille/logs/nginx.access.log; + error_log /opt/canaille/logs/nginx.error.log; + + gzip on; + gzip_vary on; + gzip_comp_level 4; + gzip_min_length 256; + gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; + gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; + + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "same-origin" always; + + location /static { + root /opt/canaille/src/canaille; + + location ~* ^.+\.(?:css|cur|js|jpe?g|gif|htc|ico|png|html|xml|otf|ttf|eot|woff|woff2|svg)$ { + access_log off; + expires 30d; + add_header Cache-Control public; + } + } + + location / { + include uwsgi_params; + uwsgi_pass unix:/etc/canaille/uwsgi.sock; + } + } + +Apache +------ + +TBD + +Recurrent jobs +============== + +You might want to clean up your database to avoid it growing too much. You can regularly delete +expired tokens and authorization codes with: + +.. code-block:: bash + + env CONFIG="$CANAILLE_CONF_DIR/config.toml" FLASK_APP=canaille "$CANAILLE_INSTALL_DIR/env/bin/canaille" clean + + +Webfinger +========= + +You may want to configure a `WebFinger`_ endpoint on your main website to allow the automatic discovery of your Canaille installation based on the account name of one of your users. For instance, suppose your domain is ``mydomain.tld`` and your Canaille domain is ``auth.mydomain.tld`` and there is a user ``john.doe``. A third-party application could require to authenticate the user and ask them for a user account. The user would give their account ``john.doe@mydomain.tld``, then the application would perform a WebFinger request at ``https://mydomain.tld/.well-known/webfinger`` and the response would contain the address of the authentication server ``https://auth.mydomain.tld``. With this information the third party application can redirect the user to the Canaille authentication page. + +The difficulty here is that the WebFinger endpoint must be hosted at the top-level domain (i.e. ``mydomain.tld``) while the authentication server might be hosted on a sublevel (i.e. ``auth.mydomain.tld``). Canaille provides a WebFinger endpoint, but if it is not hosted at the top-level domain, a web redirection is required on the ``/.well-known/webfinger`` path. + +Nginx +----- + +.. code-block:: nginx + + server { + listen 443; + server_name mydomain.tld; + rewrite ^/.well-known/webfinger https://auth.mydomain.tld/.well-known/webfinger permanent; + } + +Apache +------ + +.. code-block:: apache + + + ServerName mydomain.tld + RewriteEngine on + RewriteRule "^/.well-know/webfinger" "https://auth.mydomain.tld/.well-known/webfinger" [R,L] + + +Create your first user +====================== + +Once canaille is installed, you have several ways to populate the database. The obvious one is by adding +directly users and group into your LDAP directory. You might also want to temporarily enable then +``ENABLE_REGISTRATION`` configuration parameter to allow you to create your first users. Then, if you +have configured your ACLs properly then you will be able to manage users and groups through the Canaille +interface. + +.. _WebFinger: https://www.rfc-editor.org/rfc/rfc7033.html diff --git a/doc/index.rst b/doc/index.rst index a321db79..3c63a717 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -35,6 +35,7 @@ Table of contents :maxdepth: 2 install + deployment backends configuration troubleshooting diff --git a/doc/install.rst b/doc/install.rst index a8fa22e2..50ccd7e4 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -45,10 +45,10 @@ Choose a path where to store your configuration file. You can pass any configura sudo mkdir --parents "$CANAILLE_CONF_DIR" sudo cp $CANAILLE_INSTALL_DIR/env/lib/python*/site-packages/canaille/config.sample.toml "$CANAILLE_CONF_DIR/config.toml" -You should then edit your configuration file to adapt the values to your needs. +You should then edit your configuration file to adapt the values to your needs. Look at the configuration details in the :doc:`configuration` page. -Installation -============ +Install and check +================= Automatic schemas installation ------------------------------ @@ -112,166 +112,3 @@ After a manual installation, you can check your configuration file with the foll .. code-block:: bash env CONFIG="$CANAILLE_CONF_DIR/config.toml" "$CANAILLE_INSTALL_DIR/env/bin/canaille" check - -Application service -=================== - -Finally you have to run canaille in a WSGI application server. -Here are some WSGI server configuration examples you can pick. Do not forget to update the paths. - -gunicorn --------- - -TBD - -uwsgi ------ - -.. code-block:: ini - - [uwsgi] - virtualenv=/opt/canaille/env - socket=/etc/canaille/uwsgi.sock - plugin=python3 - module=canaille:create_app() - lazy-apps=true - master=true - processes=1 - threads=10 - need-app=true - thunder-lock=true - touch-chain-reload=/etc/canaille/uwsgi-reload.fifo - enable-threads=true - reload-on-rss=1024 - worker-reload-mercy=600 - buffer-size=65535 - disable-write-exception = true - env = CONFIG=/etc/canaille/config.toml - -Webserver -========= - -Now you have to plug your WSGI application server to your webserver so it is accessible on the internet. -Here are some webserver configuration examples you can pick: - -Nginx ------ - -.. code-block:: nginx - - server { - listen 80; - listen [::]:80; - server_name auth.mydomain.tld; - return 301 https://$server_name$request_uri; - } - - server { - server_name auth.mydomain.tld; - - listen 443 ssl http2; - listen [::]:443 ssl http2; - - ssl_certificate /etc/letsencrypt/live/moncompte.nubla.fr/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/moncompte.nubla.fr/privkey.pem; - ssl_session_timeout 1d; - ssl_session_cache shared:MozSSL:10m; # about 40000 sessions - ssl_session_tickets off; - ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; - ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; - ssl_prefer_server_ciphers off; - ssl_stapling on; - ssl_stapling_verify on; - - index index.html index.php; - charset utf-8; - client_max_body_size 10M; - - access_log /opt/canaille/logs/nginx.access.log; - error_log /opt/canaille/logs/nginx.error.log; - - gzip on; - gzip_vary on; - gzip_comp_level 4; - gzip_min_length 256; - gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; - gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; - - add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; - add_header X-Frame-Options "SAMEORIGIN" always; - add_header X-XSS-Protection "1; mode=block" always; - add_header X-Content-Type-Options "nosniff" always; - add_header Referrer-Policy "same-origin" always; - - location /static { - root /opt/canaille/src/canaille; - - location ~* ^.+\.(?:css|cur|js|jpe?g|gif|htc|ico|png|html|xml|otf|ttf|eot|woff|woff2|svg)$ { - access_log off; - expires 30d; - add_header Cache-Control public; - } - } - - location / { - include uwsgi_params; - uwsgi_pass unix:/etc/canaille/uwsgi.sock; - } - } - -Apache ------- - -TBD - -Recurrent jobs -============== - -You might want to clean up your database to avoid it growing too much. You can regularly delete -expired tokens and authorization codes with: - -.. code-block:: bash - - env CONFIG="$CANAILLE_CONF_DIR/config.toml" FLASK_APP=canaille "$CANAILLE_INSTALL_DIR/env/bin/canaille" clean - - -Webfinger -========= - -You may want to configure a `WebFinger`_ endpoint on your main website to allow the automatic discovery of your Canaille installation based on the account name of one of your users. For instance, suppose your domain is ``mydomain.tld`` and your Canaille domain is ``auth.mydomain.tld`` and there is a user ``john.doe``. A third-party application could require to authenticate the user and ask them for a user account. The user would give their account ``john.doe@mydomain.tld``, then the application would perform a WebFinger request at ``https://mydomain.tld/.well-known/webfinger`` and the response would contain the address of the authentication server ``https://auth.mydomain.tld``. With this information the third party application can redirect the user to the Canaille authentication page. - -The difficulty here is that the WebFinger endpoint must be hosted at the top-level domain (i.e. ``mydomain.tld``) while the authentication server might be hosted on a sublevel (i.e. ``auth.mydomain.tld``). Canaille provides a WebFinger endpoint, but if it is not hosted at the top-level domain, a web redirection is required on the ``/.well-known/webfinger`` path. - -Nginx ------ - -.. code-block:: nginx - - server { - listen 443; - server_name mydomain.tld; - rewrite ^/.well-known/webfinger https://auth.mydomain.tld/.well-known/webfinger permanent; - } - -Apache ------- - -.. code-block:: apache - - - ServerName mydomain.tld - RewriteEngine on - RewriteRule "^/.well-know/webfinger" "https://auth.mydomain.tld/.well-known/webfinger" [R,L] - - -Create your first user -====================== - -Once canaille is installed, you have several ways to populate the database. The obvious one is by adding -directly users and group into your LDAP directory. You might also want to temporarily enable then -``ENABLE_REGISTRATION`` configuration parameter to allow you to create your first users. Then, if you -have configured your ACLs properly then you will be able to manage users and groups through the Canaille -interface. - -.. _WebFinger: https://www.rfc-editor.org/rfc/rfc7033.html