Sunil Mohan Adapa 7bdf47eea2
apache: Use cgid module instead of cgi
Trying to enable cgi module results in cgid being enabled. Checking for cgi
being enabled always results in failure.

Your MPM seems to be threaded. Selecting cgid instead of cgi.
Module cgid already enabled

No module matches cgi (disabled by site administrator)

This is the reason why installing ikiwiki was causing Apache restart even though
the modules required by ikiwiki are already enabled.

Closes: #1448.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
2019-02-28 20:13:45 -05:00

190 lines
6.5 KiB
Python
Executable File

#!/usr/bin/python3
# -*- mode: python -*-
#
# This file is part of FreedomBox.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Configuration helper for Apache web server.
"""
import argparse
import glob
import re
import subprocess
from plinth import action_utils
def parse_arguments():
"""Return parsed command line arguments as dictionary"""
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
subparser = subparsers.add_parser('setup', help='Setup for Apache')
subparser.add_argument(
'--old-version', type=int, required=True,
help='Earlier version of the app that is already setup.')
subparser = subparsers.add_parser(
'enable', help='Enable a site/config/module in apache')
subparser.add_argument('--name',
help='Name of the site/config/module to enable')
subparser.add_argument('--kind', choices=['site', 'config', 'module'])
subparser = subparsers.add_parser(
'disable', help='Disable a site/config/module in apache')
subparser.add_argument('--name',
help='Name of the site/config/module to disable')
subparser.add_argument('--kind', choices=['site', 'config', 'module'])
subparsers.required = True
return parser.parse_args()
def _get_sort_key_of_version(version):
"""Return the sort key for a given version string.
Simple implementation hoping that PHP Apache module version numbers will be
simple.
"""
parts = []
for part in version.split('.'):
try:
parts.append(int(part))
except ValueError:
parts.append(part)
return parts
def _sort_versions(versions):
"""Return a list of sorted version strings."""
return sorted(versions, key=_get_sort_key_of_version, reverse=True)
def _disable_mod_php(webserver):
"""Disable all mod_php versions.
Idempotent and harmless if all or no PHP modules are identified.
Problematic if only some modules are found.
"""
paths = glob.glob('/etc/apache2/mods-available/php*.conf')
versions = []
for path in paths:
match = re.search(r'\/php(.*)\.conf$', path)
if match:
versions.append(match[1])
versions = _sort_versions(versions)
for version in versions:
webserver.disable('php' + version, kind='module')
def subcommand_setup(arguments):
"""Setup Apache configuration."""
# Regenerate the snakeoil self-signed SSL certificate. This is so that
# FreedomBox images don't all have the same certificate. When FreedomBox
# package is installed via apt, don't regenerate. When upgrading to newer
# version of Apache FreedomBox app and setting up for the first time don't
# regenerate.
if action_utils.is_disk_image() and arguments.old_version == 0:
subprocess.run([
'make-ssl-cert', 'generate-default-snakeoil', '--force-overwrite'
], check=True)
with action_utils.WebserverChange() as webserver:
# Disable mod_php as we have switched to mod_fcgi + php-fpm. Disable
# before switching away from mpm_prefork otherwise switching fails due
# dependency.
_disable_mod_php(webserver)
# set the prefork worker model
webserver.disable('mpm_worker', kind='module')
webserver.disable('mpm_prefork', kind='module')
webserver.enable('mpm_event', kind='module')
# enable miscellaneous modules.
webserver.enable('proxy', kind='module')
webserver.enable('proxy_http', kind='module')
webserver.enable('proxy_fcgi', kind='module')
webserver.enable('rewrite', kind='module')
webserver.enable('macro', kind='module')
# switch to mod_ssl from mod_gnutls
webserver.disable('gnutls', kind='module')
webserver.enable('ssl', kind='module')
# enable mod_alias for RedirectMatch
webserver.enable('alias', kind='module')
# enable mod_headers for HSTS
webserver.enable('headers', kind='module')
# Various modules for authentication/authorization
webserver.enable('authnz_ldap', kind='module')
webserver.enable('auth_pubtkt', kind='module')
# enable some critical modules to avoid restart while installing
# FreedomBox applications.
webserver.disable('cgi', kind='module') # For process MPMs
webserver.enable('cgid', kind='module') # For threaded MPMs
webserver.enable('proxy_uwsgi', kind='module')
webserver.enable('proxy_wstunnel', kind='module')
# enable configuration for PHP-FPM
webserver.enable('php-fpm-freedombox', kind='config')
# enable users to share files uploaded to ~/public_html
webserver.enable('userdir', kind='module')
# setup freedombox site
webserver.enable('freedombox', kind='config')
# enable serving Debian javascript libraries
webserver.enable('javascript-common', kind='config')
# default sites
webserver.enable('000-default', kind='site')
webserver.disable('default-tls', kind='site')
webserver.enable('default-ssl', kind='site')
webserver.enable('plinth', kind='site')
webserver.enable('plinth-ssl', kind='site')
# TODO: Check that the (name, kind) is a managed by FreedomBox before
# performing operation.
def subcommand_enable(arguments):
"""Enable an Apache site/config/module."""
action_utils.webserver_enable(arguments.name, arguments.kind)
def subcommand_disable(arguments):
"""Disable an Apache site/config/module."""
action_utils.webserver_disable(arguments.name, arguments.kind)
def main():
"""Parse arguments and perform all duties"""
arguments = parse_arguments()
subcommand = arguments.subcommand.replace('-', '_')
subcommand_method = globals()['subcommand_' + subcommand]
subcommand_method(arguments)
if __name__ == '__main__':
main()