Skip to content

Commit

Permalink
Shift default configuration to production-friendly values
Browse files Browse the repository at this point in the history
The out-of-the-box configuration for the server is now geared toward
production rather than development so that there is less need for
supplemental configuration. This makes the deployment process slightly
easier.

Part of this change involves removing file-based application and
access logs, which were redundant with the logging that is already
happening through systemd and nginx. Additional configuration logic
was added to get CherryPy not to write access logs to stdout.
  • Loading branch information
lovett committed Apr 13, 2019
1 parent 18c2377 commit f17ac20
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 51 deletions.
14 changes: 7 additions & 7 deletions README.md
Expand Up @@ -67,7 +67,7 @@ Sqlite databases. Default: `./db`


**engine.autoreload.on**: Whether the CherryPy webserver should watch **engine.autoreload.on**: Whether the CherryPy webserver should watch
for changes to application files and restart itself. Only useful in for changes to application files and restart itself. Only useful in
development. Default: `True` development. Default: `False`


**local_maintenance**: Whether the server should allow requests **local_maintenance**: Whether the server should allow requests
from localhost that perform cleanup and maintenance operations. These from localhost that perform cleanup and maintenance operations. These
Expand All @@ -77,22 +77,22 @@ when the application is otherwise dormant. Default: `True`
**log.screen**: Whether requests should be written to the stdout of the **log.screen**: Whether requests should be written to the stdout of the
tty running the server process. Default: `True` tty running the server process. Default: `True`


**log_dir**: The path to the directory that should be used for access **log.screen_access**: Whether access logs should be written to stdout
logs. Default: `./logs` when screen logging is enabled. Default: `False`


**memorize_checksums**: Whether the server should keep static asset file **memorize_checksums**: Whether the server should keep static asset file
hashes in memory for use with HTTP cache control. Useful in production hashes in memory for use with HTTP cache control. Useful in production
but counterproductive in development. Default: `False` but counterproductive in development. Default: `True`


**request.show_tracebacks**: Whether CherryPy should display Python **request.show_tracebacks**: Whether CherryPy should display Python
trackebacks when errors occur. Default: `True` trackebacks when errors occur. Default: `False`


**server.daemonize**: Whether the CherryPy server should run as a **server.daemonize**: Whether the CherryPy server should run as a
daemon. Not meaningful in production unless systemd is not being daemon. Not meaningful in production unless systemd is not being
used. Default: `False` used. Default: `False`


**server.socket_host**: The IP the server should listen on. Default: **server.socket_host**: The IP the server should listen on. Default:
`0.0.0.0` `127.0.0.1`


**server.socket_port**: The port the server should listen on. Default: **server.socket_port**: The port the server should listen on. Default:
`8085` `8085`
Expand All @@ -101,7 +101,7 @@ used. Default: `False`
authorization. Default: `False` authorization. Default: `False`


**users**: If using conditional auth, a Python dictionary of usernames **users**: If using conditional auth, a Python dictionary of usernames
and passwords for Basic Auth. Default: `None` and passwords for Basic Auth. Default: `{}`


**tools.conditional_auth.whitelist**: If using conditional auth, a **tools.conditional_auth.whitelist**: If using conditional auth, a
space-separated string of IP addresses or fragments that are allowed space-separated string of IP addresses or fragments that are allowed
Expand Down
1 change: 0 additions & 1 deletion ansible/roles/system/tasks/main.yml
Expand Up @@ -31,7 +31,6 @@
group="{{ project_group }}" group="{{ project_group }}"
mode=0775 mode=0775
with_items: with_items:
- /var/log/{{ project_name }}
- /var/cache/{{ project_name }} - /var/cache/{{ project_name }}
- /var/cache/{{ project_name }}/speak - /var/cache/{{ project_name }}/speak


Expand Down
75 changes: 32 additions & 43 deletions medley.py
Expand Up @@ -11,7 +11,6 @@


import importlib import importlib
import logging import logging
import logging.config
import os import os
import os.path import os.path
import cherrypy import cherrypy
Expand All @@ -31,21 +30,27 @@ def main():
server_root = os.path.dirname(os.path.abspath(__file__)) server_root = os.path.dirname(os.path.abspath(__file__))
app_root = os.path.join(server_root, "apps") app_root = os.path.join(server_root, "apps")


# Configuration - default values # Configuration defaults
#
# These are reasonable values for a production environment.
cherrypy.config.update({ cherrypy.config.update({
"cache_dir": "./cache", "cache_dir": "./cache",
"database_dir": "./db", "database_dir": "./db",
"engine.autoreload.on": True, "engine.autoreload.on": False,
"local_maintenance": True, "local_maintenance": True,
"log.screen": True, "log.screen": True,
"log_dir": "./logs", "log.screen_access": False,
"memorize_checksums": False, "log.access_file": "",
"request.show_tracebacks": True, "log.error_file": "",
"memorize_checksums": True,
"request.show_tracebacks": False,
"server.daemonize": False, "server.daemonize": False,
"server.socket_host": "0.0.0.0", "server.socket_host": "127.0.0.1",
"server.socket_port": 8085, "server.socket_port": 8085,
"server_root": server_root, "server_root": server_root,
"tools.conditional_auth.on": False, "tools.conditional_auth.on": False,
"users": {},
"tools.conditional_auth.whitelist": "",


# Jinja templating won't work unless tools.encode is off # Jinja templating won't work unless tools.encode is off
"tools.encode.on": False, "tools.encode.on": False,
Expand All @@ -69,6 +74,11 @@ def main():
if os.path.isfile(candidate)), if os.path.isfile(candidate)),
) )
cherrypy.config.update(config) cherrypy.config.update(config)

cherrypy.log("Configuration overrides loaded from {}".format(
config
))

except StopIteration: except StopIteration:
pass pass


Expand All @@ -79,8 +89,9 @@ def main():


# Directory creation # Directory creation
# #
# Filesystem paths declared by the config are expected to exist. # Filesystem paths specified in the configuration are expected to
for key in ("database_dir", "cache_dir", "log_dir"): # already exist. Try to create them if they don't.
for key in ("database_dir", "cache_dir"):
value = cherrypy.config.get(key) value = cherrypy.config.get(key)


try: try:
Expand Down Expand Up @@ -184,40 +195,18 @@ def main():
cherrypy.tools.negotiable = tools.negotiable.Tool() cherrypy.tools.negotiable = tools.negotiable.Tool()
cherrypy.tools.capture = tools.capture.Tool() cherrypy.tools.capture = tools.capture.Tool()


# Logging # Disable access logging to the console
error_log_handler = logging.handlers.TimedRotatingFileHandler( #
os.path.join( # This changes CherryPy's default behavior, which is to send
cherrypy.config.get("log_dir"), # access and error logs to the screen when screen logging is
"error.log" # enabled. Turning off one but not the other only works when
), # logging to files.
when="D", #
interval=1, # The log.screen_access config key is unique to this project.
backupCount=14, if not cherrypy.config.get("log.screen_access"):
encoding="utf8" for handler in cherrypy.log.access_log.handlers:
) if isinstance(handler, logging.StreamHandler):
error_log_handler.setLevel(logging.INFO) cherrypy.log.access_log.handlers.remove(handler)

# pylint: disable=protected-access
error_log_handler.setFormatter(cherrypy._cplogging.logfmt)

cherrypy.log.error_log.addHandler(error_log_handler)

access_log_handler = logging.handlers.TimedRotatingFileHandler(
os.path.join(
cherrypy.config.get("log_dir"),
"access.log"
),
when="D",
interval=1,
backupCount=14,
encoding="utf8"
)
access_log_handler.setLevel(logging.INFO)

# pylint: disable=protected-access
access_log_handler.setFormatter(cherrypy._cplogging.logfmt)

cherrypy.log.access_log.addHandler(access_log_handler)


cherrypy.engine.start() cherrypy.engine.start()
cherrypy.engine.publish("scheduler:revive") cherrypy.engine.publish("scheduler:revive")
Expand Down

0 comments on commit f17ac20

Please sign in to comment.