cherryd(1)
π 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 everyCONFIG_FILEyou hand over,cherrydgoes and doescherrypy.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 eachMODULE_NAMEgiven,cherrydimports the module. this is literally how you tellcherrydto run your app's startup code. for all practical purposes,-iis not optional β you will always need at least one module. periodt. π-p PIDFILE_PATH,--pidfile=PIDFILE_PATHβ store the process id inPIDFILE_PATH. now you can find it later π«Ά-P DIRPATH,--Path DIRPATHβ names a directory to be inserted at the head ofsys.path.DIRPATHshould be an absolute path (no shortcuts, bestie). multiple times? yes babe, again.cherrydinserts all theDIRPATHs you gave it intosys.pathbefore 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
π COPYRIGHT π
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 πβ¨π
π¦ where this page comes from
- debian bookworm: python3-cherrypy3 18.8.0-2 Β· BSD-3-Clause
- debian trixie: python3-cherrypy3 18.10.0-1 Β· BSD-3-Clause
- ubuntu noble: python3-cherrypy3 18.9.0-2 Β· BSD-3-Clause
- ubuntu questing: python3-cherrypy3 18.10.0-1
- ubuntu resolute: python3-cherrypy3 18.10.0-2 Β· BSD-3-Clause
- ubuntu stonking: python3-cherrypy3 18.10.0-3 Β· BSD-3-Clause
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms