From 3fd2e3efa9078593ff19a209fcd72743d4d91490 Mon Sep 17 00:00:00 2001 From: Steve Hay Date: Sat, 17 Sep 2022 08:03:16 -0400 Subject: [PATCH] Replace Flask built-in WSGI server with gunicorn (#2158) --- conf/mailinabox.service | 1 + management/auth.py | 16 ++-------------- management/wsgi.py | 7 +++++++ setup/management.sh | 10 ++++++++-- 4 files changed, 18 insertions(+), 16 deletions(-) create mode 100644 management/wsgi.py diff --git a/conf/mailinabox.service b/conf/mailinabox.service index b4cfa6c..c1d98a0 100644 --- a/conf/mailinabox.service +++ b/conf/mailinabox.service @@ -4,6 +4,7 @@ After=multi-user.target [Service] Type=idle +IgnoreSIGPIPE=False ExecStart=/usr/local/lib/mailinabox/start [Install] diff --git a/management/auth.py b/management/auth.py index 0a88c45..c576d01 100644 --- a/management/auth.py +++ b/management/auth.py @@ -22,20 +22,8 @@ class AuthService: def init_system_api_key(self): """Write an API key to a local file so local processes can use the API""" - def create_file_with_mode(path, mode): - # Based on answer by A-B-B: http://stackoverflow.com/a/15015748 - old_umask = os.umask(0) - try: - return os.fdopen(os.open(path, os.O_WRONLY | os.O_CREAT, mode), 'w') - finally: - os.umask(old_umask) - - self.key = secrets.token_hex(32) - - os.makedirs(os.path.dirname(self.key_path), exist_ok=True) - - with create_file_with_mode(self.key_path, 0o640) as key_file: - key_file.write(self.key + '\n') + with open(self.key_path, 'r') as file: + self.key = file.read() def authenticate(self, request, env, login_only=False, logout=False): """Test if the HTTP Authorization header's username matches the system key, a session key, diff --git a/management/wsgi.py b/management/wsgi.py new file mode 100644 index 0000000..86cf3af --- /dev/null +++ b/management/wsgi.py @@ -0,0 +1,7 @@ +from daemon import app +import auth, utils + +app.logger.addHandler(utils.create_syslog_handler()) + +if __name__ == "__main__": + app.run(port=10222) \ No newline at end of file diff --git a/setup/management.sh b/setup/management.sh index cfac5db..cebed8d 100755 --- a/setup/management.sh +++ b/setup/management.sh @@ -50,7 +50,7 @@ hide_output $venv/bin/pip install --upgrade pip # NOTE: email_validator is repeated in setup/questions.sh, so please keep the versions synced. hide_output $venv/bin/pip install --upgrade \ rtyaml "email_validator>=1.0.0" "exclusiveprocess" \ - flask dnspython python-dateutil expiringdict \ + flask dnspython python-dateutil expiringdict gunicorn \ qrcode[pil] pyotp \ "idna>=2.0.0" "cryptography==37.0.2" psutil postfix-mta-sts-resolver \ b2sdk boto3 @@ -90,6 +90,7 @@ rm -f /tmp/bootstrap.zip # Create an init script to start the management daemon and keep it # running after a reboot. +# Note: Authentication currently breaks with more than 1 gunicorn worker. cat > $inst_dir/start < /var/lib/mailinabox/api.key +chmod 640 /var/lib/mailinabox/api.key + source $venv/bin/activate -exec python $(pwd)/management/daemon.py +export PYTHONPATH=$(pwd)/management +exec gunicorn -b localhost:10222 -w 1 wsgi:app EOF chmod +x $inst_dir/start cp --remove-destination conf/mailinabox.service /lib/systemd/system/mailinabox.service # target was previously a symlink so remove it first