diff --git a/nixos/modules/services/mail/mailman.nix b/nixos/modules/services/mail/mailman.nix index 82dedaf9b29..6142fd11b0b 100644 --- a/nixos/modules/services/mail/mailman.nix +++ b/nixos/modules/services/mail/mailman.nix @@ -6,24 +6,18 @@ let cfg = config.services.mailman; - mailmanWeb = pkgs.python3Packages.mailman-web.override { - serverEMail = cfg.siteOwner; - archiverKey = cfg.hyperkittyApiKey; - allowedHosts = cfg.webHosts; - }; + # This deliberately doesn't use recursiveUpdate so users can + # override the defaults. + settings = { + DEFAULT_FROM_EMAIL = cfg.siteOwner; + SERVER_EMAIL = cfg.siteOwner; + ALLOWED_HOSTS = [ "localhost" "127.0.0.1" ] ++ cfg.webHosts; + COMPRESS_OFFLINE = true; + STATIC_ROOT = "/var/lib/mailman-web/static"; + MEDIA_ROOT = "/var/lib/mailman-web/media"; + } // cfg.webSettings; - mailmanWebPyEnv = pkgs.python3.withPackages (x: with x; [mailman-web]); - - mailmanWebExe = with pkgs; stdenv.mkDerivation { - inherit (mailmanWeb) name; - buildInputs = [makeWrapper]; - unpackPhase = ":"; - installPhase = '' - mkdir -p $out/bin - makeWrapper ${mailmanWebPyEnv}/bin/django-admin $out/bin/mailman-web \ - --set DJANGO_SETTINGS_MODULE settings - ''; - }; + settingsJSON = pkgs.writeText "settings.json" (builtins.toJSON settings); mailmanCfg = '' [mailman] @@ -98,8 +92,8 @@ in { webRoot = mkOption { type = types.path; - default = "${mailmanWeb}/${pkgs.python3.sitePackages}"; - defaultText = "pkgs.python3Packages.mailman-web"; + default = "${pkgs.mailman-web}/${pkgs.python3.sitePackages}"; + defaultText = "\${pkgs.mailman-web}/\${pkgs.python3.sitePackages}"; description = '' The web root for the Hyperkity + Postorius apps provided by Mailman. This variable can be set, of course, but it mainly exists so that site @@ -128,6 +122,14 @@ in { ''; }; + webSettings = mkOption { + type = types.attrs; + default = {}; + description = '' + Overrides for the default mailman-web Django settings. + ''; + }; + hyperkitty = { enable = mkEnableOption "the Hyperkitty archiver for Mailman"; @@ -175,10 +177,27 @@ in { users.users.mailman = { description = "GNU Mailman"; isSystemUser = true; }; - environment = { - systemPackages = [ pkgs.mailman mailmanWebExe pkgs.sassc ]; - etc."mailman.cfg".text = mailmanCfg; - }; + environment.etc."mailman.cfg".text = mailmanCfg; + + environment.etc."mailman3/settings.py".text = '' + import os + + # Required by mailman_web.settings, but will be overridden when + # settings_local.json is loaded. + os.environ["SECRET_KEY"] = "" + + from mailman_web.settings import * + + import json + + with open('${settingsJSON}') as f: + globals().update(json.load(f)) + + with open('/var/lib/mailman-web/settings_local.json') as f: + globals().update(json.load(f)) + ''; + + environment.systemPackages = [ cfg.package ] ++ (with pkgs; [ mailman-web ]); services.postfix = { recipientDelimiter = "+"; # bake recipient addresses in mail envelopes via VERP @@ -201,36 +220,39 @@ in { }; }; - systemd.services.mailman-secrets = { - description = "Generate Hyperkitty API key"; + systemd.services.mailman-settings = { + description = "Generate settings files (including secrets) for Mailman"; before = [ "mailman.service" "mailman-web.service" "hyperkitty.service" "httpd.service" "uwsgi.service" ]; requiredBy = [ "mailman.service" "mailman-web.service" "hyperkitty.service" "httpd.service" "uwsgi.service" ]; + path = with pkgs; [ jq ]; script = '' mailmanDir=/var/lib/mailman mailmanWebDir=/var/lib/mailman-web mailmanCfg=$mailmanDir/mailman-hyperkitty.cfg - hyperkittyCfg=$mailmanWebDir/settings_local.py - - [ -e $mailmanCfg -o -e $hyperkittyCfg ] && exit 0 + mailmanWebCfg=$mailmanWebDir/settings_local.json install -m 0700 -o mailman -g nogroup -d $mailmanDir install -m 0700 -o ${cfg.webUser} -g nogroup -d $mailmanWebDir - hyperkittyApiKey=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64) - secretKey=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64) + if [ ! -e $mailmanWebCfg ]; then + hyperkittyApiKey=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64) + secretKey=$(tr -dc A-Za-z0-9 < /dev/urandom | head -c 64) - hyperkittyCfgTmp=$(mktemp) - echo "MAILMAN_ARCHIVER_KEY='$hyperkittyApiKey'" >>"$hyperkittyCfgTmp" - echo "SECRET_KEY='$secretKey'" >>"$hyperkittyCfgTmp" - chown ${cfg.webUser} "$hyperkittyCfgTmp" + mailmanWebCfgTmp=$(mktemp) + jq -n '.MAILMAN_ARCHIVER_KEY=$archiver_key | .SECRET_KEY=$secret_key' \ + --arg archiver_key "$hyperkittyApiKey" \ + --arg secret_key "$secretKey" \ + >"$mailmanWebCfgTmp" + chown ${cfg.webUser} "$mailmanWebCfgTmp" + mv -n "$mailmanWebCfgTmp" $mailmanWebCfg + fi + hyperkittyApiKey="$(jq -r .MAILMAN_ARCHIVER_KEY $mailmanWebCfg)" mailmanCfgTmp=$(mktemp) sed "s/@API_KEY@/$hyperkittyApiKey/g" ${mailmanHyperkittyCfg} >"$mailmanCfgTmp" chown mailman "$mailmanCfgTmp" - - mv -n "$hyperkittyCfgTmp" $hyperkittyCfg - mv -n "$mailmanCfgTmp" $mailmanCfg + mv "$mailmanCfgTmp" $mailmanCfg ''; serviceConfig = { Type = "oneshot"; @@ -241,11 +263,12 @@ in { description = "Init Postorius DB"; before = [ "httpd.service" "uwsgi.service" ]; requiredBy = [ "httpd.service" "uwsgi.service" ]; + restartTriggers = [ config.environment.etc."mailman3/settings.py".source ]; script = '' - ${mailmanWebExe}/bin/mailman-web migrate + ${pkgs.mailman-web}/bin/mailman-web migrate rm -rf static - ${mailmanWebExe}/bin/mailman-web collectstatic - ${mailmanWebExe}/bin/mailman-web compress + ${pkgs.mailman-web}/bin/mailman-web collectstatic + ${pkgs.mailman-web}/bin/mailman-web compress ''; serviceConfig = { User = cfg.webUser; @@ -267,9 +290,10 @@ in { inherit (cfg.hyperkitty) enable; description = "GNU Hyperkitty QCluster Process"; after = [ "network.target" ]; + restartTriggers = [ config.environment.etc."mailman3/settings.py".source ]; wantedBy = [ "mailman.service" "multi-user.target" ]; serviceConfig = { - ExecStart = "${mailmanWebExe}/bin/mailman-web qcluster"; + ExecStart = "${pkgs.mailman-web}/bin/mailman-web qcluster"; User = cfg.webUser; WorkingDirectory = "/var/lib/mailman-web"; }; @@ -279,8 +303,9 @@ in { inherit (cfg.hyperkitty) enable; description = "Trigger minutely Hyperkitty events"; startAt = "minutely"; + restartTriggers = [ config.environment.etc."mailman3/settings.py".source ]; serviceConfig = { - ExecStart = "${mailmanWebExe}/bin/mailman-web runjobs minutely"; + ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs minutely"; User = cfg.webUser; WorkingDirectory = "/var/lib/mailman-web"; }; @@ -290,8 +315,9 @@ in { inherit (cfg.hyperkitty) enable; description = "Trigger quarter-hourly Hyperkitty events"; startAt = "*:00/15"; + restartTriggers = [ config.environment.etc."mailman3/settings.py".source ]; serviceConfig = { - ExecStart = "${mailmanWebExe}/bin/mailman-web runjobs quarter_hourly"; + ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs quarter_hourly"; User = cfg.webUser; WorkingDirectory = "/var/lib/mailman-web"; }; @@ -301,8 +327,9 @@ in { inherit (cfg.hyperkitty) enable; description = "Trigger hourly Hyperkitty events"; startAt = "hourly"; + restartTriggers = [ config.environment.etc."mailman3/settings.py".source ]; serviceConfig = { - ExecStart = "${mailmanWebExe}/bin/mailman-web runjobs hourly"; + ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs hourly"; User = cfg.webUser; WorkingDirectory = "/var/lib/mailman-web"; }; @@ -312,8 +339,9 @@ in { inherit (cfg.hyperkitty) enable; description = "Trigger daily Hyperkitty events"; startAt = "daily"; + restartTriggers = [ config.environment.etc."mailman3/settings.py".source ]; serviceConfig = { - ExecStart = "${mailmanWebExe}/bin/mailman-web runjobs daily"; + ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs daily"; User = cfg.webUser; WorkingDirectory = "/var/lib/mailman-web"; }; @@ -323,8 +351,9 @@ in { inherit (cfg.hyperkitty) enable; description = "Trigger weekly Hyperkitty events"; startAt = "weekly"; + restartTriggers = [ config.environment.etc."mailman3/settings.py".source ]; serviceConfig = { - ExecStart = "${mailmanWebExe}/bin/mailman-web runjobs weekly"; + ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs weekly"; User = cfg.webUser; WorkingDirectory = "/var/lib/mailman-web"; }; @@ -334,8 +363,9 @@ in { inherit (cfg.hyperkitty) enable; description = "Trigger yearly Hyperkitty events"; startAt = "yearly"; + restartTriggers = [ config.environment.etc."mailman3/settings.py".source ]; serviceConfig = { - ExecStart = "${mailmanWebExe}/bin/mailman-web runjobs yearly"; + ExecStart = "${pkgs.mailman-web}/bin/mailman-web runjobs yearly"; User = cfg.webUser; WorkingDirectory = "/var/lib/mailman-web"; }; diff --git a/pkgs/servers/mail/mailman/settings.py b/pkgs/servers/mail/mailman/settings.py deleted file mode 100644 index 7c3cec92002..00000000000 --- a/pkgs/servers/mail/mailman/settings.py +++ /dev/null @@ -1,508 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (C) 1998-2019 by the Free Software Foundation, Inc. -# -# This file is part of Postorius. -# -# Postorius is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation, either version 3 of the License, or (at your option) -# any later version. -# -# Postorius 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 General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# Postorius. If not, see . - -""" -Django settings for postorius project. - -For more information on this file, see -https://docs.djangoproject.com/en/1.9/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/1.9/ref/settings/ -""" - -# Build paths inside the project like this: os.path.join(BASE_DIR, ...) -import os - -# Compatibility with Bootstrap 3 -from django.contrib.messages import constants as messages - - -BASE_DIR = os.path.dirname(os.path.abspath(__file__)) - - -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/ - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = False - -ADMINS = ( - #('Admin', 'webmaster@example.com'), -) - -SITE_ID = 1 - -# Hosts/domain names that are valid for this site; required if DEBUG is False -# See https://docs.djangoproject.com/en/1.8/ref/settings/#allowed-hosts -ALLOWED_HOSTS = [ - "localhost", # Archiving API from Mailman, keep it. - "127.0.0.1", - # Add here all production URLs you may have. - @ALLOWED_HOSTS@ -] - -# Mailman API credentials -MAILMAN_REST_API_URL = 'http://localhost:8001' -MAILMAN_REST_API_USER = 'restadmin' -MAILMAN_REST_API_PASS = 'restpass' -MAILMAN_ARCHIVER_FROM = ('127.0.0.1', '::1') - -# Application definition - -INSTALLED_APPS = ( - 'hyperkitty', - 'postorius', - 'django_mailman3', - # Uncomment the next line to enable the admin: - 'django.contrib.admin', - # Uncomment the next line to enable admin documentation: - # 'django.contrib.admindocs', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'rest_framework', - 'django_gravatar', - 'compressor', - 'haystack', - 'django_extensions', - 'django_q', - 'allauth', - 'allauth.account', - 'allauth.socialaccount', - 'django_mailman3.lib.auth.fedora', - 'allauth.socialaccount.providers.openid', - 'allauth.socialaccount.providers.github', - 'allauth.socialaccount.providers.gitlab', - 'allauth.socialaccount.providers.google', - #'allauth.socialaccount.providers.facebook', - #'allauth.socialaccount.providers.twitter', - 'allauth.socialaccount.providers.stackexchange', -) - - -MIDDLEWARE = ( - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'django_mailman3.middleware.TimezoneMiddleware', -) - -ROOT_URLCONF = 'urls' - - -TEMPLATES = [ - { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.i18n', - 'django.template.context_processors.media', - 'django.template.context_processors.static', - 'django.template.context_processors.tz', - 'django.template.context_processors.csrf', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - 'django_mailman3.context_processors.common', - 'hyperkitty.context_processors.common', - ], - }, - }, -] - -WSGI_APPLICATION = 'wsgi.application' - - -# Database -# https://docs.djangoproject.com/en/1.9/ref/settings/#databases - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': '/var/lib/mailman-web/mailman-web.db' - } -} - -# Password validation -# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators - -AUTH_PASSWORD_VALIDATORS = [ - { - 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', - }, -] - - -# If you're behind a proxy, use the X-Forwarded-Host header -# See https://docs.djangoproject.com/en/1.8/ref/settings/#use-x-forwarded-host -# USE_X_FORWARDED_HOST = True - -# And if your proxy does your SSL encoding for you, set SECURE_PROXY_SSL_HEADER -# https://docs.djangoproject.com/en/1.8/ref/settings/#secure-proxy-ssl-header -# SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') -# SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_SCHEME', 'https') - -# Other security settings -# SECURE_SSL_REDIRECT = True -# If you set SECURE_SSL_REDIRECT to True, make sure the SECURE_REDIRECT_EXEMPT -# contains at least this line: -# SECURE_REDIRECT_EXEMPT = [ -# "archives/api/mailman/.*", # Request from Mailman. -# ] -# SESSION_COOKIE_SECURE = True -# SECURE_CONTENT_TYPE_NOSNIFF = True -# SECURE_BROWSER_XSS_FILTER = True -# CSRF_COOKIE_SECURE = True -# CSRF_COOKIE_HTTPONLY = True -# X_FRAME_OPTIONS = 'DENY' - - -# Internationalization -# https://docs.djangoproject.com/en/1.9/topics/i18n/ - -LANGUAGE_CODE = 'en-us' - -TIME_ZONE = 'UTC' - -USE_I18N = True - -USE_L10N = True - -USE_TZ = True - - -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/1.9/howto/static-files/ - - -# Absolute path to the directory static files should be collected to. -# Don't put anything in this directory yourself; store your static files -# in apps' "static/" subdirectories and in STATICFILES_DIRS. -# Example: "/var/www/example.com/static/" -STATIC_ROOT = 'static' - -# URL prefix for static files. -# Example: "http://example.com/static/", "http://static.example.com/" -STATIC_URL = '/static/' - -# Additional locations of static files -STATICFILES_DIRS = ( - # Put strings here, like "/home/html/static" or "C:/www/django/static". - # Always use forward slashes, even on Windows. - # Don't forget to use absolute paths, not relative paths. - # BASE_DIR + '/static/', -) - -# List of finder classes that know how to find static files in -# various locations. -STATICFILES_FINDERS = ( - 'django.contrib.staticfiles.finders.FileSystemFinder', - 'django.contrib.staticfiles.finders.AppDirectoriesFinder', - # 'django.contrib.staticfiles.finders.DefaultStorageFinder', - 'compressor.finders.CompressorFinder', -) - -# Django 1.6+ defaults to a JSON serializer, but it won't work with -# django-openid, see -# https://bugs.launchpad.net/django-openid-auth/+bug/1252826 -SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer' - - -LOGIN_URL = 'account_login' -LOGIN_REDIRECT_URL = 'hk_root' -LOGOUT_URL = 'account_logout' - - -# If you enable internal authentication, this is the address that the emails -# will appear to be coming from. Make sure you set a valid domain name, -# otherwise the emails may get rejected. -# https://docs.djangoproject.com/en/1.8/ref/settings/#default-from-email -DEFAULT_FROM_EMAIL = "@SERVER_EMAIL@" - -# If you enable email reporting for error messages, this is where those emails -# will appear to be coming from. Make sure you set a valid domain name, -# otherwise the emails may get rejected. -# https://docs.djangoproject.com/en/1.8/ref/settings/#std:setting-SERVER_EMAIL -SERVER_EMAIL = "@SERVER_EMAIL@" - - -MESSAGE_TAGS = { - messages.ERROR: 'danger' -} - - -# -# Social auth -# -AUTHENTICATION_BACKENDS = ( - 'django.contrib.auth.backends.ModelBackend', - 'allauth.account.auth_backends.AuthenticationBackend', -) - -# Django Allauth -ACCOUNT_AUTHENTICATION_METHOD = "username_email" -ACCOUNT_EMAIL_REQUIRED = True -ACCOUNT_EMAIL_VERIFICATION = "mandatory" -ACCOUNT_DEFAULT_HTTP_PROTOCOL = "https" -ACCOUNT_UNIQUE_EMAIL = True - -SOCIALACCOUNT_PROVIDERS = { - 'openid': { - 'SERVERS': [ - dict(id='yahoo', - name='Yahoo', - openid_url='http://me.yahoo.com'), - ], - }, - 'google': { - 'SCOPE': ['profile', 'email'], - 'AUTH_PARAMS': {'access_type': 'online'}, - }, - 'facebook': { - 'METHOD': 'oauth2', - 'SCOPE': ['email'], - 'FIELDS': [ - 'email', - 'name', - 'first_name', - 'last_name', - 'locale', - 'timezone', - ], - 'VERSION': 'v2.4', - }, - 'gitlab': { - 'GITLAB_URL': 'https://gitlab.com', - 'SCOPE': ['read_user'], - }, -} - - -# -# Gravatar -# https://github.com/twaddington/django-gravatar -# -# Gravatar base url. -# GRAVATAR_URL = 'http://cdn.libravatar.org/' -# Gravatar base secure https url. -# GRAVATAR_SECURE_URL = 'https://seccdn.libravatar.org/' -# Gravatar size in pixels. -# GRAVATAR_DEFAULT_SIZE = '80' -# An image url or one of the following: 'mm', 'identicon', 'monsterid', -# 'wavatar', 'retro'. -# GRAVATAR_DEFAULT_IMAGE = 'mm' -# One of the following: 'g', 'pg', 'r', 'x'. -# GRAVATAR_DEFAULT_RATING = 'g' -# True to use https by default, False for plain http. -# GRAVATAR_DEFAULT_SECURE = True - -# These can be set to override the defaults but are not mandatory: -# EMAIL_CONFIRMATION_TEMPLATE = 'postorius/address_confirmation_message.txt' -# EMAIL_CONFIRMATION_SUBJECT = 'Confirmation needed' - -# -# django-compressor -# https://pypi.python.org/pypi/django_compressor -# -COMPRESS_PRECOMPILERS = ( - ('text/x-scss', '/run/current-system/sw/bin/sassc -t compressed {infile} {outfile}'), - ('text/x-sass', '/run/current-system/sw/bin/sassc -t compressed {infile} {outfile}'), -) -# On a production setup, setting COMPRESS_OFFLINE to True will bring a -# significant performance improvement, as CSS files will not need to be -# recompiled on each requests. It means running an additional "compress" -# management command after each code upgrade. -# http://django-compressor.readthedocs.io/en/latest/usage/#offline-compression -COMPRESS_ENABLED = True -COMPRESS_OFFLINE = True - -# Needed for debug mode -# INTERNAL_IPS = ('127.0.0.1',) - - -# -# Full-text search engine -# -HAYSTACK_CONNECTIONS = { - 'default': { - 'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine', - 'PATH': "/var/lib/mailman-web/fulltext_index", - # You can also use the Xapian engine, it's faster and more accurate, - # but requires another library. - # http://django-haystack.readthedocs.io/en/v2.4.1/installing_search_engines.html#xapian - # Example configuration for Xapian: - #'ENGINE': 'xapian_backend.XapianEngine' - }, -} - - -# -# REST framework -# -REST_FRAMEWORK = { - 'PAGE_SIZE': 10, - 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', - 'DEFAULT_FILTER_BACKENDS': ( - 'rest_framework.filters.OrderingFilter', - ), -} - - -# -# Asynchronous tasks -# -Q_CLUSTER = { - 'timeout': 300, - 'save_limit': 100, - 'orm': 'default', -} - - -# A sample logging configuration. The only tangible logging -# performed by this configuration is to send an email to -# the site admins on every HTTP 500 error when DEBUG=False. -# See http://docs.djangoproject.com/en/dev/topics/logging for -# more details on how to customize your logging configuration. -LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'filters': { - 'require_debug_false': { - '()': 'django.utils.log.RequireDebugFalse' - } - }, - 'handlers': { - 'console': { - 'class': 'logging.StreamHandler', - 'formatter': 'simple', - }, - 'mail_admins': { - 'level': 'ERROR', - 'filters': ['require_debug_false'], - 'class': 'django.utils.log.AdminEmailHandler' - }, - 'file':{ - 'level': 'INFO', - #'class': 'logging.handlers.RotatingFileHandler', - 'class': 'logging.handlers.WatchedFileHandler', - 'filename': 'mailman-web.log', - 'formatter': 'verbose', - }, - }, - 'loggers': { - 'django': { - 'handlers': ['console', 'file'], - 'level': 'INFO', - }, - 'django.request': { - 'handlers': ['console', 'mail_admins', 'file'], - 'level': 'ERROR', - 'propagate': True, - }, - 'postorius': { - 'handlers': ['console', 'file'], - 'level': 'INFO', - }, - 'django': { - 'handlers': ['file'], - 'level': 'ERROR', - 'propagate': True, - }, - 'hyperkitty': { - 'handlers': ['file'], - 'level': 'DEBUG', - 'propagate': True, - }, - }, - 'formatters': { - 'simple': { - 'format': '%(levelname)s: %(message)s' - }, - 'verbose': { - 'format': '%(levelname)s %(asctime)s %(process)d %(name)s %(message)s' - }, - 'simple': { - 'format': '%(levelname)s %(message)s' - }, - }, - #'root': { - # 'handlers': ['file'], - # 'level': 'INFO', - #}, -} - - -POSTORIUS_TEMPLATE_BASE_URL = "http://localhost:8000" - - -# Using the cache infrastructure can significantly improve performance on a -# production setup. This is an example with a local Memcached server. -#CACHES = { -# 'default': { -# 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache', -# 'LOCATION': '127.0.0.1:11211', -# } -#} - - -# When DEBUG is True, don't actually send emails to the SMTP server, just store -# them in a directory. This way you won't accidentally spam your mailing-lists -# while you're fiddling with the code. -if DEBUG == True: - EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend' - EMAIL_FILE_PATH = '/tmp/hyperkitty-emails' - - -# -# HyperKitty-specific -# -# Only display mailing-lists from the same virtual host as the webserver -FILTER_VHOST = False -# Disable singleton locking for Django-Q tasks. -HYPERKITTY_DISABLE_SINGLETON_TASKS = False -# Maximum time between two task runs with same function and arguments. -# This setting is mostly meant for Mailman Developers and should be used -# with caution. -# Default set to 10mins. -HYPERKITTY_TASK_LOCK_TIMEOUT = 10 * 60 - - -try: - from settings_local import * -except ImportError: - pass diff --git a/pkgs/servers/mail/mailman/urls.py b/pkgs/servers/mail/mailman/urls.py deleted file mode 100644 index 9e18da2a218..00000000000 --- a/pkgs/servers/mail/mailman/urls.py +++ /dev/null @@ -1,34 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (C) 1998-2019 by the Free Software Foundation, Inc. -# -# This file is part of Postorius. -# -# Postorius is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation, either version 3 of the License, or (at your option) -# any later version. -# -# Postorius 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 General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# Postorius. If not, see . - - -from django.conf.urls import include, url -from django.contrib import admin -from django.urls import reverse_lazy -from django.views.generic import RedirectView - - -urlpatterns = [ - url(r'^$', RedirectView.as_view(url=reverse_lazy('hk_root'))), - url(r'^hyperkitty/', include('hyperkitty.urls')), - url(r'^postorius/', include('postorius.urls')), - url(r'', include('django_mailman3.urls')), - url(r'^accounts/', include('allauth.urls')), - # Django admin - url(r'^admin/', admin.site.urls), -] diff --git a/pkgs/servers/mail/mailman/web.nix b/pkgs/servers/mail/mailman/web.nix index ec16775b1d4..408840c3f93 100644 --- a/pkgs/servers/mail/mailman/web.nix +++ b/pkgs/servers/mail/mailman/web.nix @@ -1,38 +1,39 @@ -{ stdenv, python, hyperkitty, postorius, buildPythonPackage, isPy3k -, serverEMail ? "postmaster@example.org" -, archiverKey ? "SecretArchiverAPIKey" -, allowedHosts ? [] +{ buildPythonPackage, lib, fetchgit, isPy3k +, git, makeWrapper, sassc, hyperkitty, postorius, whoosh }: -let - - allowedHostsString = stdenv.lib.concatMapStringsSep ", " (x: "\""+x+"\"") allowedHosts; - -in - -# We turn those Djando configuration files into a make-shift Python library so -# that Nix users can use this package as a part of their buildInputs to import -# the code. Also, this package implicitly provides an environment in which the -# Django app can be run. - -buildPythonPackage { - name = "mailman-web-0"; +buildPythonPackage rec { + pname = "mailman-web-unstable"; + version = "2019-09-29"; disabled = !isPy3k; - propagatedBuildInputs = [ hyperkitty postorius ]; + src = fetchgit { + url = "https://gitlab.com/mailman/mailman-web"; + rev = "d17203b4d6bdc71c2b40891757f57a32f3de53d5"; + sha256 = "124cxr4vfi1ibgxygk4l74q4fysx0a6pga1kk9p5wq2yvzwg9z3n"; + leaveDotGit = true; + }; - unpackPhase = ":"; - buildPhase = ":"; - setuptoolsCheckPhase = ":"; - - installPhase = '' - d=$out/${python.sitePackages} - install -D -m 444 ${./urls.py} $d/urls.py - install -D -m 444 ${./wsgi.py} $d/wsgi.py - substitute ${./settings.py} $d/settings.py \ - --subst-var-by SERVER_EMAIL '${serverEMail}' \ - --subst-var-by ARCHIVER_KEY '${archiverKey}' \ - --subst-var-by ALLOWED_HOSTS '${allowedHostsString}' - chmod 444 $d/settings.py + # This is just so people installing from pip also get uwsgi + # installed, AFAICT. + postPatch = '' + sed -i '/^ uwsgi$/d' setup.cfg ''; + + nativeBuildInputs = [ git makeWrapper ]; + propagatedBuildInputs = [ hyperkitty postorius whoosh ]; + + # Tries to check runtime configuration. + doCheck = false; + + postInstall = '' + wrapProgram $out/bin/mailman-web \ + --suffix PATH : ${lib.makeBinPath [ sassc ]} + ''; + + meta = with lib; { + description = "Django project for Mailman 3 web interface"; + license = licenses.gpl3; + maintainers = with maintainers; [ qyliss ]; + }; } diff --git a/pkgs/servers/mail/mailman/wsgi.py b/pkgs/servers/mail/mailman/wsgi.py deleted file mode 100644 index 5bdbc511473..00000000000 --- a/pkgs/servers/mail/mailman/wsgi.py +++ /dev/null @@ -1,17 +0,0 @@ -""" -WSGI config for meh project. - -It exposes the WSGI callable as a module-level variable named ``application``. - -For more information on this file, see -https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/ -""" - -import os - -from django.core.wsgi import get_wsgi_application - - -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings") - -application = get_wsgi_application() diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 255b5dfd90b..92d90410ee1 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -15325,6 +15325,8 @@ in mailman-rss = callPackage ../development/python-modules/mailman-rss { }; + mailman-web = with python3.pkgs; toPythonApplication mailman-web; + mattermost = callPackage ../servers/mattermost { }; matterircd = callPackage ../servers/mattermost/matterircd.nix { }; matterbridge = callPackage ../servers/matterbridge { };