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:
James Valleroy 2026-03-15 09:39:26 -04:00 committed by Sunil Mohan Adapa
parent 7cbbc3633b
commit 0e698eb4b4
No known key found for this signature in database
GPG Key ID: 43EA1CFF0AA7C5F2
21 changed files with 107 additions and 231 deletions

View File

@ -8,6 +8,3 @@ Webserver
.. autoclass:: plinth.modules.apache.components.WebserverRoot
:members:
.. autoclass:: plinth.modules.apache.components.Uwsgi
:members:

View File

@ -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()

View File

@ -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)

View File

@ -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,

View File

@ -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."""

View File

@ -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

View File

@ -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()

View File

@ -0,0 +1,5 @@
[Service]
User=bepasty
Group=bepasty
StateDirectory=bepasty
LoadCredential=bepasty-freedombox.conf:/etc/bepasty-freedombox.conf

View File

@ -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>

View File

@ -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

View File

@ -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')]

View File

@ -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)

View File

@ -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."""

View File

@ -0,0 +1,4 @@
[Service]
User=radicale
Group=radicale
StateDirectory=radicale

View File

@ -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>

View File

@ -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')]

View File

@ -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)

View File

@ -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()

View File

@ -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>

View File

@ -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>

View File

@ -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