cherryd(1)

πŸ“¦
version 18.10.0 Β· 2 versions
  • 18.10.0 Β· debian bookworm, debian trixie, ubuntu noble, ubuntu questing, ubuntu resolute, ubuntu stonking (latest)
  • 18.6.1 Β· ubuntu jammy
, in debian bookworm, debian trixie, ubuntu noble, ubuntu questing, ubuntu resolute, ubuntu stonking

πŸ’– cherryd πŸ’–

okay so bestie, welcome to the cherryd page from the web manual section β€” it's cherryd(1) if you're being all formal at the terminal. buckle up, this one's short but it's got layers πŸ’…


✨ NAME ✨

cherryd β€” starts the CherryPy HTTP server as a daemon πŸ’πŸ‘‘


πŸ¦‹ SYNOPSIS πŸ¦‹

cherryd [-d] [-f | -s] [-e ENV_NAME] [-p PIDFILE_PATH] [-P DIRPATH] [-c
CONFIG_FILE] -i MODULE_NAME

🌸 DESCRIPTION 🌸

cherryd is a Python script, and what it does β€” no cap β€” is start the CherryPy webserver as a daemon. that's the whole vibe. πŸŽ€


πŸ’… OPTIONS πŸ’…

  • -c CONFIG_FILE, --config=CONFIG_FILE β€” points at a config file that gets read and merged into the CherryPy site-wide config dict. you can pass this one multiple times, bestie, it's not a one-and-done situation. for every CONFIG_FILE you hand over, cherryd goes and does cherrypy.config.update(). πŸ”₯
  • -d β€” run the server as a daemon. detached, unbothered, living its truth.
  • -e ENV_NAME, --environment=ENV_NAME β€” names an environment to apply. an environment is basically a canned set of configuration entries β€” like a preset fit already picked out for you. the built-in ones are listed down in ENVIRONMENTS, go look πŸ‘€
  • -f β€” start a fastcgi server instead of the default HTTP server.
  • -s β€” start a scgi server instead of the default HTTP server.
  • -i MODULE_NAME, --import=MODULE_NAME β€” names a module to import. yeah you guessed it, this one can be specified multiple times too, and for each MODULE_NAME given, cherryd imports the module. this is literally how you tell cherryd to run your app's startup code. for all practical purposes, -i is not optional β€” you will always need at least one module. periodt. πŸ’€
  • -p PIDFILE_PATH, --pidfile=PIDFILE_PATH β€” store the process id in PIDFILE_PATH. now you can find it later 🫢
  • -P DIRPATH, --Path DIRPATH β€” names a directory to be inserted at the head of sys.path. DIRPATH should be an absolute path (no shortcuts, bestie). multiple times? yes babe, again. cherryd inserts all the DIRPATHs you gave it into sys.path before it tries to import any modules specified with -i. order matters, that's the tea β˜•

want the terse version of all this? run cherryd --help. iconic behaviour honestly.


🌈 EXAMPLES 🌈

here's a site-wide config file called site.conf:

[global]
server.socket_host = "0.0.0.0"
server.socket_port = 8008
engine.autoreload.on = False

and the application startup code in startup.py:

import cherrypy
import my_controller
cherrypy.log.error_file = '/var/tmp/myapp-error.log'
cherrypy.log.access_file = '/var/tmp/myapp-access.log'
config_root = { 'tools.encode.encoding' : 'utf-8', }
app_conf = { '/' : config_root }
cherrypy.tree.mount(my_controller.Root(), script_name='',
config=app_conf)

and the matching cherryd command line:

cherryd -d -c site.conf -i startup -p /var/log/cherrypy/my_app.pid

see how it all clicks together? chef's kiss πŸ‘¨πŸ³πŸ’‹


πŸ‘‘ DROPPING PRIVILEGES πŸ‘‘

so here's the situation: if you wanna serve your web app on TCP port 80 β€” or literally any port lower than 1024 β€” the CherryPy HTTP server has to start as root so it can bind to that port. but running a web application as root is reckless, full stop, do not do that. the app should drop privileges from root down to some other user and group instead.

and here's the important part: the application must do this itself, because cherryd does not do it for you. it's not gonna hold your hand on this one, bestie πŸ™ˆ

to drop privileges, put these lines into your startup code, swapping in appropriate values for umask, uid and gid:

from cherrypy.process.plugins import DropPrivileges
DropPrivileges(cherrypy.engine, umask=022, uid='nobody',
gid='nogroup').subscribe()

heads up: the values for uid and gid can be either user and group names, or uid and gid integers. both work, pick your fighter. ✨

and another heads up, this one's important β€” you must disable the engine Autoreload plugin. why? because the way Autoreload works is by exec()ing a new instance of the running process, replacing the current instance. and since root privileges are already dropped, that new process instance is gonna fail the second it tries to do a privileged operation, like binding to a low-numbered TCP port. so yeah. turn it off. πŸ”₯


🌈 ENVIRONMENTS 🌈

these are the built-in environment configurations, aka the presets, aka the outfits already hanging in your closet:

staging

'engine.autoreload.on': False,
'checker.on': False,
'tools.log_headers.on': False,
'request.show_tracebacks': False,
'request.show_mismatched_params': False,

production

'engine.autoreload_on': False,
'checker.on': False,
'tools.log_headers.on': False,
'request.show_tracebacks': False,
'request.show_mismatched_params': False,
'log.screen': False,

embedded

# For use with CherryPy embedded in another deployment stack, e.g.
Apache mod_wsgi.
'engine.autoreload_on': False,
'checker.on': False,
'tools.log_headers.on': False,
'request.show_tracebacks': False,
'request.show_mismatched_params': False,
'log.screen': False,
'engine.SIGHUP': None,
'engine.SIGTERM': None,

πŸ’€ BUGS πŸ’€

ngl, cherryd should probably accept command-line options --uid, --gid, and --umask, and handle dropping privileges itself. right now it just... doesn't. and we all noticed. 😭


🫢 AUTHOR 🫢

fumanchu

cherrypy.dev


this man page is placed in the public domain β€” free as a bird, take it, it's yours πŸ’–


and that's the whole page, bestie!! cherryd version 3.2.0, dated 2009-06-15, from the web manual section. go forth and daemonize responsibly πŸ’βœ¨πŸ’