mailman-web: use upstream, improve NixOS module

Previously, some files were copied into the Nixpkgs tree, which meant
we wouldn't easily be able to update them, and was also just messy.

The reason it was done that way before was so that a few NixOS
options could be substituted in.  Some problems with doing it this way
were that the _package_ changed depending on the values of the
settings, which is pretty strange, and also that it only allowed those
few settings to be set.

In the new model, mailman-web is a usable package without needing to
override, and I've implemented the NixOS options in a much more
flexible way.  NixOS' mailman-web config file first reads the
mailman-web settings to use as defaults, but then it loads another
configuration file generated from the new services.mailman.webSettings
option, so _any_ mailman-web Django setting can be customised by the
user, rather than just the three that were supported before.  I've
kept the old options, but there might not really be any good reason to
keep them.
This commit is contained in:
Alyssa Ross 2020-01-09 21:35:56 +00:00
parent a8538a73a7
commit 881dd9963f
6 changed files with 111 additions and 637 deletions

View File

@ -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";
};

View File

@ -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 <http://www.gnu.org/licenses/>.
"""
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

View File

@ -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 <http://www.gnu.org/licenses/>.
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),
]

View File

@ -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 ];
};
}

View File

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

View File

@ -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 { };