Installation ============ To install this software, you can use a container-based setup, or run it directly in a Python environment. As there are many ways (and opinions!) how to configure a web server and deploy a Python WSGI application, only some details are outlined here and the reader is expected to be familiar with at least web server administration. See also the :external+flask:std:doc:`Flask documentation on production deployment `. Container setup (Podman, Kubernetes, …) --------------------------------------- Pull the `container image`_ (or build it yourself using the provided ``Containerfile``): .. code:: shell-session % podman pull registry.git.fsmpi.rwth-aachen.de/schilder/schilder2000:{{TAG}} Config and data is expected in ``/usr/local/var/schilder2000-instance/``. For starters, you can use the ``examples/`` directory in the `source repository`_, which is also included in the container image. To create a volume based on it: .. code:: shell-session % [[ $(id -u) -eq 0 ]] || podman unshare # pushd $(podman image mount registry.git.fsmpi.rwth-aachen.de/schilder/schilder2000:{{TAG}}) # cd usr/local/var/schilder2000-instance # tar cf - . | podman volume import schilder2000-instance # popd # podman image unmount registry.git.fsmpi.rwth-aachen.de/schilder/schilder2000:{{TAG}} You can also use a volume just for ``/usr/local/var/schilder2000-instance/data`` and mount ``/usr/local/var/schilder2000-instance/config/config.py`` separately. Continue with :ref:`configuration` and :ref:`database-migration` before starting the container. Configure your inbound proxy to pass HTTP to port 8080, and your container management to launch the container as required. For example, as plain invocation: .. code:: shell-session % podman run --rm --detach --publish-all \ --volume schilder2000-instance:/usr/local/var/schilder2000-instance \ registry.git.fsmpi.rwth-aachen.de/schilder/schilder2000:{{TAG}} Without container ----------------- You can use our pre-built `Python package`_ (wheel) or build it yourself. Dependencies ~~~~~~~~~~~~ You need Python 3.9 or later and the dependencies specified in ``pyproject.toml``. It is suggested to use a virtualenv, as distribution packages are often missing or outdated. Some optional dependencies need additional native libraries, namely MySQL/MariaDB Connector/C for MySQL/MariaDB support (both should work with either database), and OpenLDAP and Cyrus SASL for LDAP authentication. If binary wheels for those are not available, you need the development versions of those as well as C compiler and Python development infrastructure. Additionally, Git is required to get the sources of some dependencies. .. code:: shell-session # apt-get install python3-dev pkg-config gcc libmariadb-dev libldap-dev libsasl2-dev git # dnf install python3-devel gcc 'pkgconfig(libmariadb)' 'pkgconfig(ldap)' git-core # apk add -t .schilder2000 python3 mariadb-connector-c libldap # Runtime # apk add -t .schilder2000-build build-base git mariadb-connector-c-dev \ openldap-dev python3-dev # Build only, can be removed later To use OS packages as much as possible (note that the versions your distribution provides may be too outdated and you may need to install the development dependencies from above anyway): .. code:: shell-session # apt-get install python3 weasyprint python3-jinja2 python3-flask \ python3-asgiref python3-flask-sqlalchemy python3-flaskext.wtf alembic \ python3-qrcode python3-ldap python3-authlib python3-psycopg \ python3-mysqldb git # dnf install python3 \ python3dist\({weasyprint,jinja2,flask\\[async\\],flask-sqlalchemy,flask-wtf,alembic,qrcode}\) \ python3dist\({python-ldap,python3-saml,authlib,psycopg,mysqlclient}\) # apk add -t .schilder2000 python3 weasyprint py3-jinja2 py3-flask \ py3-asgiref py3-flask-sqlalchemy py3-flask-wtf py3-alembic py3-ldap \ py3-python3-saml py3-authlib py3-psycopg py3-mysqlclient git If you are not using the pre-built `Python package`_ (wheel), you also need Node.js and npm to build the frontend: .. code:: shell-session # apt-get install npm # dnf install nodejs-npm # apk add npm You will also likely want a WSGI server. If in doubt, choose Gunicorn_: .. code:: shell-session (venv) % pip install gunicorn # apt-get install gunicorn # dnf install python3-gunicorn # apk add py3-gunicorn Pre-built package ~~~~~~~~~~~~~~~~~ In your chosen deployment location (e. g., virtualenv), install the package with your desired optional extras. These are ``auth-ldap``, ``auth-saml``, ``auth-oauth``, ``all-auth``, ``db-postgres``, ``db-mysql``, ``all-db``, ``all``. For example, to install with support for SAML login and Postgres database: .. code:: shell-session (venv) % pip install "schilder2000[auth-saml,db-postgres]" \ --index-url https://git.fsmpi.rwth-aachen.de/api/v4/projects/305/packages/pypi/simple Continue with :ref:`configuration`. Building from source ~~~~~~~~~~~~~~~~~~~~ This package follows `PEP 517`_ conventions. You can use `build`_ to generate SDist and wheel packages, or run ``pip install .`` in your local source tree, … if you are at this point, you probably know your choices anyway. The default build process will automatically invoke Node.js/npm to build the frontend. To disable this behaviour, pass ``without-npm`` as build config setting. This requires the files to already exist. For example: .. code:: shell-session % npm run build % python -m build --config-setting without-npm .. _configuration: Configuration ------------- Configuration and runtime data is stored in the instance directory. For container installs, this is ``/usr/local/var/schilder2000-instance/``. For package installs, this defaults to ``{{ python prefix }}/var/schilder2000-instance``; if in doubt, try to run ``flask -A schilder2000``, the error should tell you where it expects the instance directory. To override, specify an *absolute* path in the ``SCHILDER2000_INSTANCE_PATH`` environment variable. Example config and data is located in the ``examples`` directory. The templates there get their footer text and logo from the application config and should also be useful as an example to write your own templates. The main application config is located in ``config/config.py``. Available options: .. py:data:: SQLALCHEMY_DATABASE_URI :type: str **Required**. Database connection URI. See :external:py:data:`Flask-SQLAlchemy documentation ` for details and additional options. Note that the ``db-postgres`` optional dependency install the ``psycopg`` driver (i. e., version 3), not ``psycopg2``. .. py:data:: SECRET_KEY :type: str | bytes **Required**. Secret key for signing cookies and other security related needs. See :external+flask:py:data:`Flask documentation ` for details. .. py:data:: SCHILD_FOOTER :type: str Footer text used by the templates shipped in ``examples/``. .. py:data:: SCHILD_LOGO :type: str Logo used by the templates shipped in ``examples/``. Expects a file relative to ``{{ instance path }}/data/static``. .. py:data:: TEMPLATES_AUTO_RELOAD :type: bool Reload templates when they are changed. See :external+flask:py:data:`Flask documentation ` for details. .. py:data:: PRINTERS :type: dict[str, str] **Required**. Available printers. Maps display names to IPP(S) URLs. .. py:data:: REQUIRE_LOGIN :type: bool **Required**. Whether authentication is required to access the service. If enabled, requires additional configuration for :external+flask_multipass:std:doc:`index`. .. py:data:: MULTIPASS_AUTH_PROVIDERS :type: dict[str, dict] .. py:data:: MULTIPASS_IDENTITY_PROVIDERS :type: dict[str, dict] .. py:data:: MULTIPASS_PROVIDER_MAP :type: dict[str, str] See :external+flask_multipass:std:doc:`Flask-Multipass documentation ` for details. .. py:data:: MULTIPASS_IDENTITY_INFO_KEYS :type: list Required by Flask-Multipass, but can be empty, as identity information is not used. See also :external+flask:std:doc:`Flask documentation ` for additional options and information. .. _database-migration: Database migration ~~~~~~~~~~~~~~~~~~ Unless you use SQLite, create the database in your database server. In all cases, run the migrations: .. code:: shell-session % flask -A schilder2000 alembic upgrade head # without container % podman run --rm --volume <...> flask alembic upgrade head # with container WSGI and webserver setup ~~~~~~~~~~~~~~~~~~~~~~~~ An example config for Gunicorn_ is provided in ``gunicorn.conf.py``. This will listen on ``[::]:8080`` (port 8080, all interfaces), and write the access log to stdout. See :external+flask:std:doc:`Flask documentation on Gunicorn ` and :external+gunicorn:std:doc:`Gunicorn documentation ` for further information. If you want to use another WSGI server, configure it to use ``schilder2000:create_app()`` as application object. Note that this is a factory function that returns the application callable, you have to call it! To use your webserver to directly serve static files, route ``/static`` to ``{{ python packages directory }}/schilder2000/static`` and ``/instance/static`` to ``{{ instance path }}/data/static``. .. _`Python package`: https://git.fsmpi.rwth-aachen.de/schilder/schilder2000/-/packages .. _`container image`: https://git.fsmpi.rwth-aachen.de/schilder/schilder2000/container_registry/33 .. _Gunicorn: https://gunicorn.org/ .. _`source repository`: https://git.fsmpi.rwth-aachen.de/schilder/schilder2000 .. _`PEP 517`: https://peps.python.org/pep-0517/ .. _`build`: https://github.com/pypa/build