mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-03-25 09:21:10 +00:00
apache: Use a Uwsgi native socket systemd unit for each app
[Sunil]: - Drop Uwsgi component entirely. After the changes, it mostly looks like Daemon component minus some features. One change that Uwsgi component does is when component is disabled, it also stops and disables the .service unit. Stopping the service is useful and we can add this to Daemon component. - Use /run instead of /var/run/ as 1) /var/run is a symlink to /run 2) /run/ path is what is listed in uwsgi-app@.socket unit file. - Implement upgrade for apps from older version. Disable and mask uwsgi init.d script. Enable the daemon component if the webserver component is enabled. - Update manifest files to deal with .socket units instead of 'uwsgi' service. Backup the /var/lib/private directories as that is actual directory to backup with DynamicUser=yes. - For bepasty load the configuration as a systemd provided credential since DynamicUser=yes. - Remove the /var/lib/private directories during uninstall. - Don't create user/group for bepasty as it is not needed with DynamicUser=yes. Tests: - Radicale - Functional tests pass - Freshly install radicale. - Web interface works. - Create and edit calendars - Path of the storage directory is in /var/lib/private/radicale (after accessing web interface) - Permissions on the storage folder and files inside are set to nobody:nobody. - Uninstall removes the /var/lib/private/radicale directory. - Create a calender and backup the app. Uninstall the app. Re-install the app. The calendar is not available. After restoring the backup, the calendar is available. - Install radicale without patch and create a calendar. Apply patches and start plinth.service. Setup is run. UWSGI is disabled and masked. Service is running. Old calender is visible. - Install radicale without patch. Disable and apply patches and start plinth.service. Setup is run. UWSGI is disabled and masked. Service is not running. Enabling the service works. - After upgrade, data storage path got migrated to /var/lib/private/radicale. Old data is accessible. - After upgrade the directory is still owned by radicale:radicale. - Freshly install radicale with patch and restore an old backup. The data is available in the web interface and data was migrated to /var/lib/private/radicale. - Bepasty - Functional tests pass - Freshly install bepasy. - Enabling and disabling rapidly works. - Uploading files works. - Path of the storage directory is /var/lib/private/bepasty. - Permissions on the storage folder are as expect 755 but on the parent are 700. - Permissions on the stored files are 644 and owned by nobody:nobody. - Uninstall removes the /var/lib/private/bepasty directory. - Upload a picture and backup the app. Uninstall the app. Re-install the app. The uploaded file is not available. After restoring the backup, the uploaded file is available. - Install bepasty without patch and upload a file. Apply patches and start plinth.service. Setup is run. UWSGI is disabled and masked. Service is running. Old uploaded picture is visible. - Install bepasty without patch. Disable app. Apply patches and start plinth.service. Setup is run. UWSGI is disabled and masked. Service is not running. Enabling the service works. - After upgrade, data storage path got migrated to /var/lib/private/bepasty. Old data is accessible. - After upgrade the directory is still owned by bepasty:bepasty. - Freshly install bepasty with patch and restore an old backup. The uploaded file is available in the web interface and data was migrated to /var/lib/private/bepasty. Signed-off-by: James Valleroy <jvalleroy@mailbox.org> Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
7cbbc3633b
commit
0e698eb4b4
@ -8,6 +8,3 @@ Webserver
|
||||
|
||||
.. autoclass:: plinth.modules.apache.components.WebserverRoot
|
||||
:members:
|
||||
|
||||
.. autoclass:: plinth.modules.apache.components.Uwsgi
|
||||
:members:
|
||||
|
||||
@ -18,9 +18,6 @@ from . import actions
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
UWSGI_ENABLED_PATH = '/etc/uwsgi/apps-enabled/{config_name}.ini'
|
||||
UWSGI_AVAILABLE_PATH = '/etc/uwsgi/apps-available/{config_name}.ini'
|
||||
|
||||
# Flag on disk to indicate if freedombox package was held by
|
||||
# plinth. This is a backup in case the process is interrupted and hold
|
||||
# is not released.
|
||||
@ -318,43 +315,6 @@ class WebserverChange:
|
||||
self.actions_required.add(action_required)
|
||||
|
||||
|
||||
def uwsgi_is_enabled(config_name):
|
||||
"""Return whether a uwsgi config is enabled."""
|
||||
enabled_path = UWSGI_ENABLED_PATH.format(config_name=config_name)
|
||||
return os.path.exists(enabled_path)
|
||||
|
||||
|
||||
def uwsgi_enable(config_name):
|
||||
"""Enable a uwsgi configuration that runs under uwsgi."""
|
||||
if uwsgi_is_enabled(config_name):
|
||||
return
|
||||
|
||||
# uwsgi is started/stopped using init script. We don't know if it can
|
||||
# handle some configuration already running against newly enabled
|
||||
# configuration. So, stop first before enabling new configuration.
|
||||
service_stop('uwsgi')
|
||||
|
||||
enabled_path = UWSGI_ENABLED_PATH.format(config_name=config_name)
|
||||
available_path = UWSGI_AVAILABLE_PATH.format(config_name=config_name)
|
||||
os.symlink(available_path, enabled_path)
|
||||
|
||||
service_enable('uwsgi')
|
||||
service_start('uwsgi')
|
||||
|
||||
|
||||
def uwsgi_disable(config_name):
|
||||
"""Disable a uwsgi configuration that runs under uwsgi."""
|
||||
if not uwsgi_is_enabled(config_name):
|
||||
return
|
||||
|
||||
# If uwsgi is restarted later, it won't stop the just disabled
|
||||
# configuration due to how init scripts are written for uwsgi.
|
||||
service_stop('uwsgi')
|
||||
enabled_path = UWSGI_ENABLED_PATH.format(config_name=config_name)
|
||||
os.unlink(enabled_path)
|
||||
service_start('uwsgi')
|
||||
|
||||
|
||||
def get_addresses() -> list[dict[str, str | bool]]:
|
||||
"""Return a list of IP addresses and hostnames."""
|
||||
addresses = get_ip_addresses()
|
||||
|
||||
@ -97,8 +97,8 @@ class ApacheApp(app_module.App):
|
||||
self.add(info)
|
||||
|
||||
packages = Packages('packages-apache', [
|
||||
'apache2', 'php-fpm', 'ssl-cert', 'uwsgi', 'uwsgi-plugin-python3',
|
||||
'libapache2-mod-auth-openidc'
|
||||
'apache2', 'php-fpm', 'ssl-cert', 'uwsgi-core',
|
||||
'uwsgi-plugin-python3', 'libapache2-mod-auth-openidc'
|
||||
])
|
||||
self.add(packages)
|
||||
|
||||
@ -134,6 +134,7 @@ class ApacheApp(app_module.App):
|
||||
daemon = Daemon('daemon-apache', 'apache2')
|
||||
self.add(daemon)
|
||||
|
||||
# To be able to disable the old uwsgi init.d script.
|
||||
related_daemon = RelatedDaemon('related-daemon-apache', 'uwsgi')
|
||||
self.add(related_daemon)
|
||||
|
||||
|
||||
@ -210,42 +210,6 @@ class WebserverRoot(app.FollowerComponent):
|
||||
kvstore.delete(self._key_get(), ignore_missing=True)
|
||||
|
||||
|
||||
class Uwsgi(app.LeaderComponent):
|
||||
"""Component to enable/disable uWSGI configuration."""
|
||||
|
||||
def __init__(self, component_id: str, uwsgi_name: str):
|
||||
"""Initialize the uWSGI component.
|
||||
|
||||
component_id should be a unique ID across all components of an app and
|
||||
across all components.
|
||||
|
||||
uwsgi_name is the primary part of the configuration file path which
|
||||
must be enabled/disabled by this component.
|
||||
|
||||
"""
|
||||
super().__init__(component_id)
|
||||
|
||||
self.uwsgi_name = uwsgi_name
|
||||
|
||||
def is_enabled(self) -> bool:
|
||||
"""Return whether the uWSGI configuration is enabled."""
|
||||
return action_utils.uwsgi_is_enabled(self.uwsgi_name) \
|
||||
and action_utils.service_is_enabled('uwsgi')
|
||||
|
||||
def enable(self) -> None:
|
||||
"""Enable the uWSGI configuration."""
|
||||
privileged.uwsgi_enable(self.uwsgi_name)
|
||||
|
||||
def disable(self) -> None:
|
||||
"""Disable the uWSGI configuration."""
|
||||
privileged.uwsgi_disable(self.uwsgi_name)
|
||||
|
||||
def is_running(self) -> bool:
|
||||
"""Return whether the uWSGI daemon is running with configuration."""
|
||||
return action_utils.uwsgi_is_enabled(self.uwsgi_name) \
|
||||
and action_utils.service_is_running('uwsgi')
|
||||
|
||||
|
||||
def diagnose_url(url: str, kind: str | None = None,
|
||||
env: dict[str, str] | None = None,
|
||||
check_certificate: bool = True,
|
||||
|
||||
@ -362,18 +362,6 @@ def unlink_root(domain: str):
|
||||
action_utils.service_reload('apache2')
|
||||
|
||||
|
||||
@privileged
|
||||
def uwsgi_enable(name: str):
|
||||
"""Enable uWSGI configuration and reload."""
|
||||
action_utils.uwsgi_enable(name)
|
||||
|
||||
|
||||
@privileged
|
||||
def uwsgi_disable(name: str):
|
||||
"""Disable uWSGI configuration and reload."""
|
||||
action_utils.uwsgi_disable(name)
|
||||
|
||||
|
||||
@privileged
|
||||
def domain_setup(domain: str):
|
||||
"""Add site specific configuration for a domain."""
|
||||
|
||||
@ -10,7 +10,7 @@ import pytest
|
||||
|
||||
from plinth import app, kvstore
|
||||
from plinth.diagnostic_check import DiagnosticCheck, Result
|
||||
from plinth.modules.apache.components import (Uwsgi, Webserver, WebserverRoot,
|
||||
from plinth.modules.apache.components import (Webserver, WebserverRoot,
|
||||
check_url, diagnose_url,
|
||||
diagnose_url_on_all)
|
||||
|
||||
@ -326,81 +326,6 @@ def test_webserver_root_uninstall(component_app, enable, disable):
|
||||
assert kvstore.get_default('test-webserver_domain', 'x-value') == 'x-value'
|
||||
|
||||
|
||||
def test_uwsgi_init():
|
||||
"""Test that uWSGI component can be initialized."""
|
||||
with pytest.raises(ValueError):
|
||||
Uwsgi(None, None)
|
||||
|
||||
uwsgi = Uwsgi('test-uwsgi', 'test-config')
|
||||
assert uwsgi.component_id == 'test-uwsgi'
|
||||
assert uwsgi.uwsgi_name == 'test-config'
|
||||
|
||||
|
||||
@patch('plinth.action_utils.service_is_enabled')
|
||||
@patch('plinth.action_utils.uwsgi_is_enabled')
|
||||
def test_uwsgi_is_enabled(uwsgi_is_enabled, service_is_enabled):
|
||||
"""Test that checking uwsgi configuration enabled works."""
|
||||
uwsgi = Uwsgi('test-uwsgi', 'test-config')
|
||||
|
||||
uwsgi_is_enabled.return_value = True
|
||||
service_is_enabled.return_value = True
|
||||
assert uwsgi.is_enabled()
|
||||
uwsgi_is_enabled.assert_has_calls([call('test-config')])
|
||||
service_is_enabled.assert_has_calls([call('uwsgi')])
|
||||
|
||||
service_is_enabled.return_value = False
|
||||
assert not uwsgi.is_enabled()
|
||||
|
||||
uwsgi_is_enabled.return_value = False
|
||||
assert not uwsgi.is_enabled()
|
||||
|
||||
service_is_enabled.return_value = False
|
||||
assert not uwsgi.is_enabled()
|
||||
|
||||
|
||||
@patch('plinth.modules.apache.privileged.uwsgi_enable')
|
||||
def test_uwsgi_enable(enable):
|
||||
"""Test that enabling uwsgi configuration works."""
|
||||
uwsgi = Uwsgi('test-uwsgi', 'test-config')
|
||||
|
||||
uwsgi.enable()
|
||||
enable.assert_has_calls([call('test-config')])
|
||||
|
||||
|
||||
@patch('plinth.modules.apache.privileged.uwsgi_disable')
|
||||
def test_uwsgi_disable(disable):
|
||||
"""Test that disabling uwsgi configuration works."""
|
||||
uwsgi = Uwsgi('test-uwsgi', 'test-config')
|
||||
|
||||
uwsgi.disable()
|
||||
disable.assert_has_calls([call('test-config')])
|
||||
|
||||
|
||||
@patch('plinth.action_utils.service_is_running')
|
||||
@patch('plinth.action_utils.uwsgi_is_enabled')
|
||||
def test_uwsgi_is_running(uwsgi_is_enabled, service_is_running):
|
||||
"""Test checking whether uwsgi is running with a configuration."""
|
||||
uwsgi = Uwsgi('test-uwsgi', 'test-config')
|
||||
|
||||
uwsgi_is_enabled.return_value = True
|
||||
service_is_running.return_value = True
|
||||
assert uwsgi.is_running()
|
||||
uwsgi_is_enabled.assert_has_calls([call('test-config')])
|
||||
service_is_running.assert_has_calls([call('uwsgi')])
|
||||
|
||||
uwsgi_is_enabled.return_value = False
|
||||
service_is_running.return_value = True
|
||||
assert not uwsgi.is_running()
|
||||
|
||||
uwsgi_is_enabled.return_value = True
|
||||
service_is_running.return_value = False
|
||||
assert not uwsgi.is_running()
|
||||
|
||||
uwsgi_is_enabled.return_value = False
|
||||
service_is_running.return_value = False
|
||||
assert not uwsgi.is_running()
|
||||
|
||||
|
||||
@patch('plinth.modules.apache.components.check_url')
|
||||
@patch('plinth.action_utils.get_addresses')
|
||||
def test_diagnose_url(get_addresses, check):
|
||||
@ -473,8 +398,10 @@ def test_diagnose_url(get_addresses, check):
|
||||
def test_check_url(run):
|
||||
"""Test checking whether a URL is accessible."""
|
||||
url = 'http://localhost/test'
|
||||
basic_command = ['curl', '--location', '--cookie', '', '--fail',
|
||||
'--write-out', '%{response_code}']
|
||||
basic_command = [
|
||||
'curl', '--location', '--cookie', '', '--fail', '--write-out',
|
||||
'%{response_code}'
|
||||
]
|
||||
extra_args = {'env': None, 'check': True, 'stdout': -1, 'stderr': -1}
|
||||
|
||||
# Basic
|
||||
|
||||
@ -6,10 +6,12 @@ from django.utils.translation import gettext_lazy as _
|
||||
from plinth import app as app_module
|
||||
from plinth import frontpage, menu
|
||||
from plinth.config import DropinConfigs
|
||||
from plinth.modules.apache.components import Uwsgi, Webserver
|
||||
from plinth.daemon import Daemon
|
||||
from plinth.modules.apache.components import Webserver
|
||||
from plinth.modules.backups.components import BackupRestore
|
||||
from plinth.modules.firewall.components import Firewall
|
||||
from plinth.package import Packages
|
||||
from plinth.privileged import service as service_privileged
|
||||
|
||||
from . import manifest, privileged
|
||||
|
||||
@ -48,7 +50,7 @@ class BepastyApp(app_module.App):
|
||||
|
||||
app_id = 'bepasty'
|
||||
|
||||
_version = 3
|
||||
_version = 4
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Create components for the app."""
|
||||
@ -83,8 +85,9 @@ class BepastyApp(app_module.App):
|
||||
ports=['http', 'https'], is_external=True)
|
||||
self.add(firewall)
|
||||
|
||||
uwsgi = Uwsgi('uwsgi-bepasty', 'bepasty-freedombox')
|
||||
self.add(uwsgi)
|
||||
daemon = Daemon('daemon-bepasty',
|
||||
'uwsgi-app@bepasty-freedombox.socket')
|
||||
self.add(daemon)
|
||||
|
||||
webserver = Webserver('webserver-bepasty', 'bepasty-freedombox',
|
||||
urls=['https://{host}/bepasty/'])
|
||||
@ -107,6 +110,16 @@ class BepastyApp(app_module.App):
|
||||
# value.
|
||||
privileged.set_default(['read'])
|
||||
|
||||
if old_version and old_version <= 3:
|
||||
webserver = self.get_component('webserver-bepasty')
|
||||
daemon = self.get_component('daemon-bepasty')
|
||||
if webserver.is_enabled():
|
||||
daemon.enable()
|
||||
|
||||
# Vanquish the old uwsgi init.d script.
|
||||
service_privileged.disable('uwsgi')
|
||||
service_privileged.mask('uwsgi')
|
||||
|
||||
def uninstall(self):
|
||||
"""De-configure and uninstall the app."""
|
||||
super().uninstall()
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
[Service]
|
||||
User=bepasty
|
||||
Group=bepasty
|
||||
StateDirectory=bepasty
|
||||
LoadCredential=bepasty-freedombox.conf:/etc/bepasty-freedombox.conf
|
||||
@ -12,5 +12,5 @@
|
||||
</Location>
|
||||
|
||||
<Location /bepasty/>
|
||||
ProxyPass unix:/run/uwsgi/app/bepasty-freedombox/socket|uwsgi://bepasty/
|
||||
ProxyPass unix:/run/uwsgi/bepasty-freedombox.socket|uwsgi://bepasty/
|
||||
</Location>
|
||||
|
||||
@ -25,7 +25,7 @@ lazy-apps = true
|
||||
|
||||
# Module to import
|
||||
module = bepasty.wsgi
|
||||
env = BEPASTY_CONFIG=/etc/bepasty-freedombox.conf
|
||||
env = BEPASTY_CONFIG=$(CREDENTIALS_DIRECTORY)/bepasty-freedombox.conf
|
||||
|
||||
pythonpath = /usr/lib/python3/dist-packages/
|
||||
buffer-size = 32768
|
||||
|
||||
@ -15,9 +15,9 @@ backup = {
|
||||
'files': ['/etc/bepasty-freedombox.conf']
|
||||
},
|
||||
'data': {
|
||||
'directories': ['/var/lib/bepasty']
|
||||
'directories': ['/var/lib/bepasty', '/var/lib/private/bepasty']
|
||||
},
|
||||
'services': ['uwsgi'],
|
||||
'services': ['uwsgi-app@bepasty-freedombox.socket'],
|
||||
}
|
||||
|
||||
tags = [_('File sharing'), _('Pastebin')]
|
||||
|
||||
@ -2,11 +2,8 @@
|
||||
"""Configuration helper for bepasty."""
|
||||
|
||||
import collections
|
||||
import grp
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import pwd
|
||||
import secrets
|
||||
import shutil
|
||||
import string
|
||||
@ -17,11 +14,10 @@ from plinth import action_utils
|
||||
from plinth.actions import privileged, secret_str
|
||||
from plinth.modules import bepasty
|
||||
|
||||
DATA_DIR = '/var/lib/bepasty'
|
||||
|
||||
PASSWORD_LENGTH = 20
|
||||
|
||||
CONF_FILE = pathlib.Path('/etc/bepasty-freedombox.conf')
|
||||
DATA_DIR = '/var/lib/private/bepasty'
|
||||
PASSWORD_LENGTH = 20
|
||||
SERVICE_NAME = 'uwsgi-app@bepasty-freedombox.service'
|
||||
|
||||
|
||||
def _augeas_load():
|
||||
@ -66,26 +62,6 @@ def conf_file_write(conf):
|
||||
@privileged
|
||||
def setup(domain_name: str):
|
||||
"""Post installation actions for bepasty."""
|
||||
# Create bepasty group if needed.
|
||||
try:
|
||||
grp.getgrnam('bepasty')
|
||||
except KeyError:
|
||||
action_utils.run(['addgroup', '--system', 'bepasty'], check=True)
|
||||
|
||||
# Create bepasty user if needed.
|
||||
try:
|
||||
pwd.getpwnam('bepasty')
|
||||
except KeyError:
|
||||
action_utils.run([
|
||||
'adduser', '--system', '--ingroup', 'bepasty', '--home',
|
||||
'/var/lib/bepasty', '--gecos', 'bepasty file sharing', 'bepasty'
|
||||
], check=True)
|
||||
|
||||
# Create data directory if needed.
|
||||
if not os.path.exists(DATA_DIR):
|
||||
os.makedirs(DATA_DIR, mode=0o750)
|
||||
shutil.chown(DATA_DIR, user='bepasty', group='bepasty')
|
||||
|
||||
# Create configuration file if needed.
|
||||
if not CONF_FILE.is_file():
|
||||
passwords = [_generate_password() for _ in range(3)]
|
||||
@ -112,7 +88,11 @@ def setup(domain_name: str):
|
||||
}
|
||||
conf_file_write(conf)
|
||||
CONF_FILE.chmod(0o640)
|
||||
shutil.chown(CONF_FILE, user='bepasty', group='bepasty')
|
||||
|
||||
# Migrate from old bepasty:bepasty ownership to root:root
|
||||
shutil.chown(CONF_FILE, user='root', group='root')
|
||||
action_utils.run(['deluser', 'bepasty'], check=False)
|
||||
action_utils.run(['delgroup', 'bepasty'], check=False)
|
||||
|
||||
|
||||
@privileged
|
||||
@ -132,7 +112,8 @@ def add_password(permissions: list[str], comment: str | None = None):
|
||||
conf['PERMISSION_COMMENTS'][password] = comment
|
||||
|
||||
conf_file_write(conf)
|
||||
action_utils.service_try_restart('uwsgi')
|
||||
# Service is started again by socket.
|
||||
action_utils.service_stop(SERVICE_NAME)
|
||||
|
||||
|
||||
@privileged
|
||||
@ -145,7 +126,7 @@ def remove_password(password: secret_str):
|
||||
if password in conf['PERMISSION_COMMENTS']:
|
||||
del conf['PERMISSION_COMMENTS'][password]
|
||||
conf_file_write(conf)
|
||||
action_utils.service_try_restart('uwsgi')
|
||||
action_utils.service_stop(SERVICE_NAME)
|
||||
|
||||
|
||||
@privileged
|
||||
@ -153,7 +134,7 @@ def set_default(permissions: list[str]):
|
||||
"""Set default permissions."""
|
||||
conf = {'DEFAULT_PERMISSIONS': _format_permissions(permissions)}
|
||||
conf_file_write(conf)
|
||||
action_utils.service_try_restart('uwsgi')
|
||||
action_utils.service_stop(SERVICE_NAME)
|
||||
|
||||
|
||||
def _format_permissions(permissions=None):
|
||||
@ -173,5 +154,3 @@ def uninstall():
|
||||
"""Remove bepasty user, group and data."""
|
||||
shutil.rmtree(DATA_DIR, ignore_errors=True)
|
||||
CONF_FILE.unlink(missing_ok=True)
|
||||
action_utils.run(['deluser', 'bepasty'], check=False)
|
||||
action_utils.run(['delgroup', 'bepasty'], check=False)
|
||||
|
||||
@ -11,11 +11,13 @@ from django.utils.translation import gettext_lazy as _
|
||||
from plinth import app as app_module
|
||||
from plinth import cfg, frontpage, menu
|
||||
from plinth.config import DropinConfigs
|
||||
from plinth.modules.apache.components import Uwsgi, Webserver
|
||||
from plinth.daemon import Daemon
|
||||
from plinth.modules.apache.components import Webserver
|
||||
from plinth.modules.backups.components import BackupRestore
|
||||
from plinth.modules.firewall.components import Firewall
|
||||
from plinth.modules.users.components import UsersAndGroups
|
||||
from plinth.package import Packages, install
|
||||
from plinth.privileged import service as service_privileged
|
||||
from plinth.utils import Version, format_lazy
|
||||
|
||||
from . import manifest, privileged
|
||||
@ -43,7 +45,7 @@ class RadicaleApp(app_module.App):
|
||||
|
||||
app_id = 'radicale'
|
||||
|
||||
_version = 4
|
||||
_version = 5
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Create components for the app."""
|
||||
@ -84,8 +86,8 @@ class RadicaleApp(app_module.App):
|
||||
urls=['https://{host}/radicale'])
|
||||
self.add(webserver)
|
||||
|
||||
uwsgi = Uwsgi('uwsgi-radicale', 'radicale')
|
||||
self.add(uwsgi)
|
||||
daemon = Daemon('daemon-radicale', 'uwsgi-app@radicale.socket')
|
||||
self.add(daemon)
|
||||
|
||||
users_and_groups = UsersAndGroups('users-and-groups-radicale',
|
||||
reserved_usernames=['radicale'])
|
||||
@ -107,6 +109,16 @@ class RadicaleApp(app_module.App):
|
||||
if not old_version:
|
||||
self.enable()
|
||||
|
||||
if old_version and old_version <= 4:
|
||||
webserver = self.get_component('webserver-radicale')
|
||||
daemon = self.get_component('daemon-radicale')
|
||||
if webserver.is_enabled():
|
||||
daemon.enable()
|
||||
|
||||
# Vanquish the old uwsgi init.d script.
|
||||
service_privileged.disable('uwsgi')
|
||||
service_privileged.mask('uwsgi')
|
||||
|
||||
def force_upgrade(self, packages):
|
||||
"""Force upgrade radicale to resolve conffile prompt."""
|
||||
if 'radicale' not in packages:
|
||||
@ -124,6 +136,11 @@ class RadicaleApp(app_module.App):
|
||||
|
||||
return True
|
||||
|
||||
def uninstall(self):
|
||||
"""De-configure and uninstall the app."""
|
||||
super().uninstall()
|
||||
privileged.uninstall()
|
||||
|
||||
|
||||
def load_augeas():
|
||||
"""Prepares the augeas."""
|
||||
|
||||
@ -0,0 +1,4 @@
|
||||
[Service]
|
||||
User=radicale
|
||||
Group=radicale
|
||||
StateDirectory=radicale
|
||||
@ -17,8 +17,8 @@ Redirect 301 /.well-known/caldav /radicale/
|
||||
Include includes/freedombox-auth-ldap.conf
|
||||
Require valid-user
|
||||
|
||||
ProxyPass unix:/run/uwsgi/app/radicale/socket|uwsgi://radicale/
|
||||
ProxyPassReverse unix:/run/uwsgi/app/radicale/socket|uwsgi://radicale/
|
||||
ProxyPass unix:/run/uwsgi/radicale.socket|uwsgi://radicale/
|
||||
ProxyPassReverse unix:/run/uwsgi/radicale.socket|uwsgi://radicale/
|
||||
RequestHeader set X-Script-Name /radicale/
|
||||
RequestHeader set X-Remote-User expr=%{REMOTE_USER}
|
||||
</Location>
|
||||
|
||||
@ -83,9 +83,9 @@ backup = {
|
||||
'directories': ['/etc/radicale/']
|
||||
},
|
||||
'data': {
|
||||
'directories': ['/var/lib/radicale/']
|
||||
'directories': ['/var/lib/private/radicale/', '/var/lib/radicale/']
|
||||
},
|
||||
'services': ['uwsgi']
|
||||
'services': ['uwsgi-app@radicale.socket']
|
||||
}
|
||||
|
||||
tags = [_('Calendar'), _('Contacts'), _('Server'), _('CalDAV'), _('CardDAV')]
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
"""Configure Radicale."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
||||
import augeas
|
||||
|
||||
@ -10,6 +11,7 @@ from plinth.actions import privileged
|
||||
|
||||
CONFIG_FILE = '/etc/radicale/config'
|
||||
LOG_PATH = '/var/log/radicale'
|
||||
SERVICE_NAME = 'uwsgi-app@radicale.service'
|
||||
|
||||
|
||||
@privileged
|
||||
@ -23,7 +25,8 @@ def setup():
|
||||
aug = load_augeas()
|
||||
aug.set('auth/type', 'remote_user')
|
||||
aug.save()
|
||||
action_utils.service_try_restart('uwsgi')
|
||||
# Service is started again by socket.
|
||||
action_utils.service_stop(SERVICE_NAME)
|
||||
|
||||
|
||||
@privileged
|
||||
@ -36,8 +39,7 @@ def configure(rights_type: str):
|
||||
aug = load_augeas()
|
||||
aug.set('rights/type', rights_type)
|
||||
aug.save()
|
||||
|
||||
action_utils.service_try_restart('uwsgi')
|
||||
action_utils.service_stop(SERVICE_NAME)
|
||||
|
||||
|
||||
@privileged
|
||||
@ -57,3 +59,9 @@ def load_augeas():
|
||||
aug.set('/augeas/context', '/files' + CONFIG_FILE)
|
||||
aug.load()
|
||||
return aug
|
||||
|
||||
|
||||
@privileged
|
||||
def uninstall():
|
||||
"""Remove all radicale collections."""
|
||||
shutil.rmtree('/var/lib/private/radicale/', ignore_errors=True)
|
||||
|
||||
@ -8,11 +8,13 @@ from django.utils.translation import gettext_lazy as _
|
||||
from plinth import app as app_module
|
||||
from plinth import frontpage, menu
|
||||
from plinth.config import DropinConfigs
|
||||
from plinth.modules.apache.components import Uwsgi, Webserver
|
||||
from plinth.daemon import Daemon
|
||||
from plinth.modules.apache.components import Webserver
|
||||
from plinth.modules.backups.components import BackupRestore
|
||||
from plinth.modules.firewall.components import Firewall
|
||||
from plinth.modules.users.components import UsersAndGroups
|
||||
from plinth.package import Packages
|
||||
from plinth.privileged import service as service_privileged
|
||||
|
||||
from . import manifest, privileged
|
||||
|
||||
@ -29,7 +31,7 @@ class SearxApp(app_module.App):
|
||||
|
||||
app_id = 'searx'
|
||||
|
||||
_version = 6
|
||||
_version = 7
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Create components for the app."""
|
||||
@ -78,8 +80,8 @@ class SearxApp(app_module.App):
|
||||
'searx-freedombox-auth')
|
||||
self.add(webserver)
|
||||
|
||||
uwsgi = Uwsgi('uwsgi-searx', 'searx')
|
||||
self.add(uwsgi)
|
||||
daemon = Daemon('daemon-searx', 'uwsgi-app@searx.socket')
|
||||
self.add(daemon)
|
||||
|
||||
users_and_groups = UsersAndGroups('users-and-groups-searx',
|
||||
groups=groups)
|
||||
@ -102,6 +104,16 @@ class SearxApp(app_module.App):
|
||||
self.enable()
|
||||
self.set_shortcut_login_required(True)
|
||||
|
||||
if old_version and old_version <= 6:
|
||||
webserver = self.get_component('webserver-searx')
|
||||
daemon = self.get_component('daemon-searx')
|
||||
if webserver.is_enabled():
|
||||
daemon.enable()
|
||||
|
||||
# Vanquish the old uwsgi init.d script.
|
||||
service_privileged.disable('uwsgi')
|
||||
service_privileged.mask('uwsgi')
|
||||
|
||||
def uninstall(self):
|
||||
"""De-configure and uninstall the app."""
|
||||
super().uninstall()
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<Location /searx/>
|
||||
ProxyPass unix:/run/uwsgi/app/searx/socket|uwsgi://uwsgi-uds-searx/
|
||||
ProxyPass unix:/run/uwsgi/searx.socket|uwsgi://uwsgi-uds-searx/
|
||||
Use AuthOpenIDConnect
|
||||
Use RequireGroup web-search
|
||||
</Location>
|
||||
|
||||
@ -9,12 +9,12 @@
|
||||
|
||||
|
||||
<Location /searx/>
|
||||
ProxyPass unix:/run/uwsgi/app/searx/socket|uwsgi://uwsgi-uds-searx/
|
||||
ProxyPass unix:/run/uwsgi/searx.socket|uwsgi://uwsgi-uds-searx/
|
||||
</Location>
|
||||
|
||||
|
||||
# This exclusion rule is to allow Searx to be added as a search engine in Firefox.
|
||||
<LocationMatch "^/searx/(opensearch.xml|static/themes/oscar/img/favicon.png)$">
|
||||
Require all granted
|
||||
ProxyPassMatch "unix:/run/uwsgi/app/searx/socket|uwsgi://uwsgi-uds-searx/$1"
|
||||
ProxyPassMatch "unix:/run/uwsgi/searx.socket|uwsgi://uwsgi-uds-searx/$1"
|
||||
</LocationMatch>
|
||||
|
||||
@ -139,7 +139,8 @@ def setup():
|
||||
_update_search_engines(settings)
|
||||
write_settings(settings)
|
||||
|
||||
action_utils.service_restart('uwsgi')
|
||||
# Service is started again by socket.
|
||||
action_utils.service_stop('uwsgi-app@searx.service')
|
||||
|
||||
|
||||
@privileged
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user