*: Move modules-enabled files to /usr/share

- This will leave /etc/{plinth,freedombox} empty by default making service more
robust to run across various environments and situations. See systemd's
explanation for more details.

- Use Debian maintainer scripts remove all the existing files in
/etc/plinth/modules-enabled.

- Read from /usr/share/freedombox/modules-enabled then from
/etc/plinth/modules-enabled and finally from /etc/freedombox/modules-enabled.
Later read ones override previously read files. Any file pointing to /dev/null
will mean the module must be ignored.

Tests:

- Clean up /etc/plinth, /etc/freedombox and
/usr/share/freedombox/modules-enabled. Run service and notice that files are
getting loaded from development folder using a debug message.

- Run setup.py and notice that files get installed in
/usr/share/freedombox/modules-enabled/ and in the next run they get loaded from
there.

- Create a override file in /etc/plinth/modules-enabled/transmission and notice
that overriden file gets priority over the one in
/usr/share/freedombox/modules-enabled.

- Link the file /etc/plinth/modules-enabled/transmission to /dev/null and notice
that is not loaded.

- Create another file in /etc/freedombox/modules-enabled/transmission and notice
that it overrides the previous two files.

- All affected modules are loaded.

- Build a new Debian package and ensure that upgrading 23.8 to new version
removes are all configuration files.

- Build developer documentation and test that Tutorial -> Full Code and Tutorial
-> Skeleton sections have been updated with references to
-.../modules-enabled/... paths.

- Install quassel and notice that certificates were copied to /var/lib/quassel
directory. Change domain to another domain and notice that certificates were
copied again to that directory.

Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Sunil Mohan Adapa 2023-05-04 17:56:17 -07:00 committed by James Valleroy
parent 88d7e1c934
commit 40eecb6446
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
70 changed files with 153 additions and 50 deletions

View File

@ -3,6 +3,7 @@ usr/bin
usr/lib
usr/share/augeas
usr/share/dbus-1
usr/share/freedombox/modules-enabled
usr/share/man
usr/share/mediawiki
usr/share/pam-configs

View File

@ -25,3 +25,65 @@ rm_conffile /etc/fail2ban/jail.d/wordpress-auth-freedombox.conf 22.22~
rm_conffile /etc/fail2ban/filter.d/wordpress-auth-freedombox.conf 22.22~
rm_conffile /etc/security/access.d/10freedombox-performance.conf 22.25~
rm_conffile /etc/security/access.d/10freedombox-security.conf 22.25~
rm_conffile /etc/plinth/modules-enabled/apache 23.10~
rm_conffile /etc/plinth/modules-enabled/api 23.10~
rm_conffile /etc/plinth/modules-enabled/avahi 23.10~
rm_conffile /etc/plinth/modules-enabled/backups 23.10~
rm_conffile /etc/plinth/modules-enabled/bepasty 23.10~
rm_conffile /etc/plinth/modules-enabled/bind 23.10~
rm_conffile /etc/plinth/modules-enabled/calibre 23.10~
rm_conffile /etc/plinth/modules-enabled/cockpit 23.10~
rm_conffile /etc/plinth/modules-enabled/config 23.10~
rm_conffile /etc/plinth/modules-enabled/coturn 23.10~
rm_conffile /etc/plinth/modules-enabled/datetime 23.10~
rm_conffile /etc/plinth/modules-enabled/deluge 23.10~
rm_conffile /etc/plinth/modules-enabled/diagnostics 23.10~
rm_conffile /etc/plinth/modules-enabled/dynamicdns 23.10~
rm_conffile /etc/plinth/modules-enabled/ejabberd 23.10~
rm_conffile /etc/plinth/modules-enabled/email 23.10~
rm_conffile /etc/plinth/modules-enabled/firewall 23.10~
rm_conffile /etc/plinth/modules-enabled/first_boot 23.10~
rm_conffile /etc/plinth/modules-enabled/gitweb 23.10~
rm_conffile /etc/plinth/modules-enabled/help 23.10~
rm_conffile /etc/plinth/modules-enabled/i2p 23.10~
rm_conffile /etc/plinth/modules-enabled/ikiwiki 23.10~
rm_conffile /etc/plinth/modules-enabled/infinoted 23.10~
rm_conffile /etc/plinth/modules-enabled/janus 23.10~
rm_conffile /etc/plinth/modules-enabled/jsxc 23.10~
rm_conffile /etc/plinth/modules-enabled/letsencrypt 23.10~
rm_conffile /etc/plinth/modules-enabled/matrixsynapse 23.10~
rm_conffile /etc/plinth/modules-enabled/mediawiki 23.10~
rm_conffile /etc/plinth/modules-enabled/minetest 23.10~
rm_conffile /etc/plinth/modules-enabled/minidlna 23.10~
rm_conffile /etc/plinth/modules-enabled/mumble 23.10~
rm_conffile /etc/plinth/modules-enabled/names 23.10~
rm_conffile /etc/plinth/modules-enabled/networks 23.10~
rm_conffile /etc/plinth/modules-enabled/openvpn 23.10~
rm_conffile /etc/plinth/modules-enabled/pagekite 23.10~
rm_conffile /etc/plinth/modules-enabled/performance 23.10~
rm_conffile /etc/plinth/modules-enabled/power 23.10~
rm_conffile /etc/plinth/modules-enabled/privacy 23.10~
rm_conffile /etc/plinth/modules-enabled/privoxy 23.10~
rm_conffile /etc/plinth/modules-enabled/quassel 23.10~
rm_conffile /etc/plinth/modules-enabled/radicale 23.10~
rm_conffile /etc/plinth/modules-enabled/roundcube 23.10~
rm_conffile /etc/plinth/modules-enabled/rssbridge 23.10~
rm_conffile /etc/plinth/modules-enabled/samba 23.10~
rm_conffile /etc/plinth/modules-enabled/searx 23.10~
rm_conffile /etc/plinth/modules-enabled/security 23.10~
rm_conffile /etc/plinth/modules-enabled/shaarli 23.10~
rm_conffile /etc/plinth/modules-enabled/shadowsocks 23.10~
rm_conffile /etc/plinth/modules-enabled/sharing 23.10~
rm_conffile /etc/plinth/modules-enabled/snapshot 23.10~
rm_conffile /etc/plinth/modules-enabled/ssh 23.10~
rm_conffile /etc/plinth/modules-enabled/sso 23.10~
rm_conffile /etc/plinth/modules-enabled/storage 23.10~
rm_conffile /etc/plinth/modules-enabled/syncthing 23.10~
rm_conffile /etc/plinth/modules-enabled/tor 23.10~
rm_conffile /etc/plinth/modules-enabled/transmission 23.10~
rm_conffile /etc/plinth/modules-enabled/ttrss 23.10~
rm_conffile /etc/plinth/modules-enabled/upgrades 23.10~
rm_conffile /etc/plinth/modules-enabled/users 23.10~
rm_conffile /etc/plinth/modules-enabled/wireguard 23.10~
rm_conffile /etc/plinth/modules-enabled/wordpress 23.10~
rm_conffile /etc/plinth/modules-enabled/zoph 23.10~

View File

@ -42,10 +42,10 @@ plinth/modules/transmission/views.py
.. literalinclude:: ../../../plinth/modules/transmission/views.py
:language: python3
plinth/modules/transmission/data/etc/plinth/modules-enabled/transmission
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
plinth/modules/transmission/data/usr/share/freedombox/modules-enabled/transmission
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
.. literalinclude:: ../../../plinth/modules/transmission/data/etc/plinth/modules-enabled/transmission
.. literalinclude:: ../../../plinth/modules/transmission/data/usr/share/freedombox/modules-enabled/transmission
:language: text
plinth/modules/transmission/data/etc/apache2/conf-available/transmission-plinth.conf

View File

@ -22,13 +22,15 @@ in a step-by-step manner::
├─ urls.py
├─ views.py
├─┬ data/
│ └─┬ etc/
│ ├─┬ plinth/
│ │ └─┬ modules-enabled/
│ │ └─ transmission
│ └─┬ apache2/
│ └─┬ conf-available/
│ └─ transmission-freedombox.conf
│ ├─┬ etc/
│ │ └─┬ apache2/
│ │ └─┬ conf-available/
│ │ └─ transmission-freedombox.conf
│ └─┬ usr/
│ └─┬ share/
│ └─┬ freedombox/
│ └─┬ modules-enabled/
│ └─ transmission
└─┬ tests
└─ __init__.py
@ -50,19 +52,20 @@ Tell FreedomBox that our app exists
The first thing to do is tell FreedomBox that our app exists. This is done by
writing a small file with the Python import path to our app and placing it in
``plinth/modules/transmission/data/etc/plinth/modules-enabled/``. Let us create
this file ``transmission``:
``plinth/modules/transmission/data/usr/share/freedombox/modules-enabled/``. Let
us create this file ``transmission``:
.. code-block:: text
:caption: ``plinth/modules/transmission/data/etc/plinth/modules-enabled/transmission``
:caption: ``plinth/modules/transmission/data/usr/share/freedombox/modules-enabled/transmission``
plinth.modules.transmission
This file is automatically installed to ``/etc/plinth/modules-enabled/`` by
FreedomBox's installation script ``setup.py``. If we are writing a module that
resides independently outside the FreedomBox's source code, the setup script
will need to copy it to the target location. Further, it is not necessary for
the app to be part of the ``plinth.modules`` namespace. It can, for example, be
This file is automatically installed to
``/usr/share/freedombox/modules-enabled/`` by FreedomBox's installation script
``setup.py``. If we are writing a module that resides independently outside the
FreedomBox's source code, the setup script will need to copy it to the target
location. Further, it is not necessary for the app to be part of the
``plinth.modules`` namespace. It can, for example, be
``freedombox_transmission``.
Creating the App class

View File

@ -61,30 +61,51 @@ def _include_module_urls(module_import_path, module_name):
raise
def _get_modules_enabled_paths():
"""Return list of paths from which enabled modules list must be read."""
return [
pathlib.Path('/usr/share/freedombox/modules-enabled/'),
pathlib.Path('/etc/plinth/modules-enabled/'), # For compatibility
pathlib.Path('/etc/freedombox/modules-enabled/'),
]
def _get_modules_enabled_files_to_read():
"""Return the list of files containing modules import paths."""
module_files = {}
for path in _get_modules_enabled_paths():
directory = pathlib.Path(path)
files = list(directory.glob('*'))
for file_ in files:
# Omit hidden or backup files
if file_.name.startswith('.') or '.dpkg' in file_.name:
continue
if file_.is_symlink() and str(file_.resolve()) == '/dev/null':
module_files.pop(file_.name, None)
continue
module_files[file_.name] = file_
if module_files:
return module_files.values()
# './setup.py install' has not been executed yet. Pickup files to load
# from local module directories.
directory = pathlib.Path(__file__).parent
glob_pattern = 'modules/*/data/usr/share/freedombox/modules-enabled/*'
return list(directory.glob(glob_pattern))
def get_modules_to_load():
"""Get the list of modules to be loaded"""
global _modules_to_load
if _modules_to_load is not None:
return _modules_to_load
directory = pathlib.Path(cfg.config_dir) / 'modules-enabled'
files = list(directory.glob('*'))
if not files:
# './setup.py install' has not been executed yet. Pickup files to load
# from local module directories.
directory = pathlib.Path(__file__).parent
files = list(
directory.glob('modules/*/data/etc/plinth/modules-enabled/*'))
# Omit hidden files
files = [
file_ for file_ in files
if not file_.name.startswith('.') and '.dpkg' not in file_.name
]
modules = []
for file_ in files:
module = _get_module_import_paths_from_file(file_)
for file_ in _get_modules_enabled_files_to_read():
module = _read_module_import_paths_from_file(file_)
if module:
modules.append(module)
@ -94,11 +115,35 @@ def get_modules_to_load():
def get_module_import_path(module_name: str) -> str:
"""Return the import path for a module."""
file_path = pathlib.Path(cfg.config_dir) / 'modules-enabled' / module_name
return _get_module_import_paths_from_file(file_path)
import_path_file = None
for path in _get_modules_enabled_paths():
file_ = path / module_name
if file_.exists():
import_path_file = file_
if file_.is_symlink() and str(file_.resolve()) == '/dev/null':
import_path_file = None
if not import_path_file:
# './setup.py install' has not been executed yet. Pickup files to load
# from local module directories.
directory = pathlib.Path(__file__).parent
import_path_file = (directory /
f'modules/{module_name}/data/usr/share/'
f'freedombox/modules-enabled/{module_name}')
if not import_path_file:
raise ValueError('Unknown module')
import_path = _read_module_import_paths_from_file(import_path_file)
if not import_path:
raise ValueError('Module disabled')
return import_path
def _get_module_import_paths_from_file(file_path: str) -> Optional[str]:
def _read_module_import_paths_from_file(
file_path: pathlib.Path) -> Optional[str]:
"""Read a module's import path from a file."""
with file_path.open() as file_handle:
for line in file_handle:

View File

@ -17,7 +17,7 @@ import configobj
from plinth import action_utils
from plinth import app as app_module
from plinth import cfg
from plinth import module_loader
from plinth.actions import privileged
from plinth.modules import letsencrypt as le
@ -302,10 +302,7 @@ def _get_managed_path(path):
def _assert_managed_path(module, path):
"""Check that path is in fact managed by module."""
cfg.read()
module_file = pathlib.Path(cfg.config_dir) / 'modules-enabled' / module
module_path = module_file.read_text().strip()
module_path = module_loader.get_module_import_path(module)
module = importlib.import_module(module_path)
module_classes = inspect.getmembers(module, inspect.isclass)
app_classes = [

View File

@ -1,17 +1,12 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
"""List and handle system services."""
import os
from plinth import action_utils
from plinth import app as app_module
from plinth import cfg, module_loader
from plinth import module_loader
from plinth.actions import privileged
from plinth.daemon import Daemon, RelatedDaemon
cfg.read()
module_config_path = os.path.join(cfg.config_dir, 'modules-enabled')
@privileged
def start(service: str):

View File

@ -35,7 +35,7 @@ DIRECTORIES_TO_COPY = [
('/usr/share/plinth/static', 'static'),
]
ENABLED_APPS_PATH = "/etc/plinth/modules-enabled/"
ENABLED_APPS_PATH = "/usr/share/freedombox/modules-enabled/"
DISABLED_APPS_TO_REMOVE = [
'apps',