<div dir="ltr"><div>Hi Łukasz,</div><div><br></div><div>Sorry to have given you confusing information.</div><div><br></div><div>The code snippet I had looked at was:</div><div>(kallithea/lib/paster_commands/template.ini.mako)</div><div><br></div><div>%if http_server == 'gearbox':<br><%text>##</%text> Gearbox default web server ##<br>use = egg:gearbox#wsgiref<br><%text>##</%text> nr of worker threads to spawn<br>threadpool_workers = 1<br><%text>##</%text> max request before thread respawn<br>threadpool_max_requests = 100<br><%text>##</%text> option to use threads of process<br>use_threadpool = true<br><br>[..]<br><br>%elif http_server == 'waitress':<br><%text>##</%text> WAITRESS ##<br>use = egg:waitress#main<br><%text>##</%text> number of worker threads<br>threads = 1<br><%text>##</%text> MAX BODY SIZE 100GB<br>max_request_body_size = 107374182400<br><%text>##</%text> use poll instead of select, fixes fd limits, may not work on old<br><%text>##</%text> windows systems.<br>#asyncore_use_poll = True<br><br>[..]<br><br>%endif<br></div><div><br></div><div><br></div><div>The directive 'threadpool_max_requests' that I was referring to is an option to the 'gearbox' http server, not 'waitress'. Also the 'gunicorn' server has a similar option set, but it seems that 'waitress' does not support something directly (<a href="https://docs.pylonsproject.org/projects/waitress/en/stable/arguments.html">https://docs.pylonsproject.org/projects/waitress/en/stable/arguments.html</a>).</div><div><br></div><div>But 'waitress' is the default setting for kallithea-cli config-create.</div><div><br></div><div>You can try another server using:</div><div></div><div>kallithea-cli config-create foo.ini http_server=gearbox</div><div><br></div><div>and replace gearbox by the one you would like to choose. Valid options are: waitress, gearbox, gevent, gunicorn, uwsgi .</div><div><br></div><div>In my own production instance I'm using uwsgi.</div><div><br></div><div><br></div><div>Mads: I wonder if we should do something about the default 'waitress' setting?</div><div><br></div><div>Thanks,</div><div>Thomas<br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">El lun., 31 ago. 2020 a las 13:06, Łukasz Michalski (<<a href="mailto:lm@zork.pl">lm@zork.pl</a>>) escribió:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 29/08/2020 12.26, Thomas De Schampheleire wrote:<br>
> Hi Łukasz,<br>
> <br>
> Apart from some code changes we did to improve/eliminate some caching mechanisms, we also added a note to our documentation to clarify the expectations. See the bottom of the following page:<br>
> <a href="https://kallithea.readthedocs.io/en/stable/overview.html" rel="noreferrer" target="_blank">https://kallithea.readthedocs.io/en/stable/overview.html</a><br>
> <br>
> Basically, we can not avoid certain memory growth in the context of a single process, and the recommended approach is to ensure that the web server process recreates its workers regularly.<br>
> <br>
> For gearbox/waitress, this can be done automatically with the setting threadpool_max_requests, which is set to 100 by default in the ini file produced by 'kallithea-cli config-create'.<br>
> <br>
> Is this setting present in your ini file?<br>
> Could you share the ini file?<br>
> <br>
<br>
No it is not. I generated new config using kallithea-cli and manually moved changes from old one.<br>
I attached it below.<br>
<br>
I just generated new one and I do not see threadpool_max_requests option in there.<br>
<br>
Regards,<br>
Łukasz<br>
<br>
<br>
###################################################################################<br>
###################################################################################<br>
## Kallithea config file generated with kallithea-cli 0.6.1                      ##<br>
##                                                                               ##<br>
## The %(here)s variable will generally be replaced with the parent directory of ##<br>
## this file. Other use of % must be escaped as %% .                             ##<br>
###################################################################################<br>
###################################################################################<br>
<br>
[DEFAULT]<br>
<br>
################################################################################<br>
## Email settings                                                             ##<br>
##                                                                            ##<br>
## Refer to the documentation ("Email settings") for more details.            ##<br>
##                                                                            ##<br>
## It is recommended to use a valid sender address that passes access         ##<br>
## validation and spam filtering in mail servers.                             ##<br>
################################################################################<br>
<br>
## 'From' header for application emails. You can optionally add a name.<br>
## Default:<br>
#app_email_from = Kallithea<br>
## Examples:<br>
#app_email_from = Kallithea <<a href="mailto:kallithea-noreply@example.com" target="_blank">kallithea-noreply@example.com</a>><br>
#app_email_from = <a href="mailto:kallithea-noreply@example.com" target="_blank">kallithea-noreply@example.com</a><br>
app_email_from = CodeReview <<a href="mailto:codereview@domain.pl" target="_blank">codereview@domain.pl</a>><br>
<br>
## Subject prefix for application emails.<br>
## A space between this prefix and the real subject is automatically added.<br>
## Default:<br>
#email_prefix =<br>
## Example:<br>
#email_prefix = [Kallithea]<br>
<br>
## Recipients for error emails and fallback recipients of application mails.<br>
## Multiple addresses can be specified, comma-separated.<br>
## Only addresses are allowed, do not add any name part.<br>
## Default:<br>
#email_to =<br>
## Examples:<br>
#email_to = <a href="mailto:admin@example.com" target="_blank">admin@example.com</a><br>
#email_to = <a href="mailto:admin@example.com" target="_blank">admin@example.com</a>,<a href="mailto:another_admin@example.com" target="_blank">another_admin@example.com</a><br>
email_to = <a href="mailto:root@domain.pl" target="_blank">root@domain.pl</a><br>
<br>
## 'From' header for error emails. You can optionally add a name.<br>
## Default: (none)<br>
## Examples:<br>
#error_email_from = Kallithea Errors <<a href="mailto:kallithea-noreply@example.com" target="_blank">kallithea-noreply@example.com</a>><br>
#error_email_from = <a href="mailto:kallithea_errors@example.com" target="_blank">kallithea_errors@example.com</a><br>
error_email_from = CodeReview <<a href="mailto:codereview@domain.pl" target="_blank">codereview@domain.pl</a>><br>
<br>
## SMTP server settings<br>
## If specifying credentials, make sure to use secure connections.<br>
## Default: Send unencrypted unauthenticated mails to the specified smtp_server.<br>
## For "SSL", use smtp_use_ssl = true and smtp_port = 465.<br>
## For "STARTTLS", use smtp_use_tls = true and smtp_port = 587.<br>
smtp_server = localhost<br>
smtp_username =<br>
smtp_password =<br>
smtp_port = 25<br>
smtp_use_ssl = false<br>
smtp_use_tls = false<br>
<br>
## Entry point for 'gearbox serve'<br>
[server:main]<br>
host = 127.0.0.1<br>
port = 5000<br>
<br>
## WAITRESS ##<br>
use = egg:waitress#main<br>
## number of worker threads<br>
threads = 1<br>
## MAX BODY SIZE 100GB<br>
max_request_body_size = 107374182400<br>
## use poll instead of select, fixes fd limits, may not work on old<br>
## windows systems.<br>
#asyncore_use_poll = True<br>
<br>
## middleware for hosting the WSGI application under a URL prefix<br>
[filter:proxy-prefix]<br>
use = egg:PasteDeploy#prefix<br>
prefix = /codereview<br>
<br>
[app:main]<br>
use = egg:kallithea<br>
## enable proxy prefix middleware<br>
filter-with = proxy-prefix<br>
<br>
full_stack = true<br>
static_files = true<br>
<br>
## Internationalization (see setup documentation for details)<br>
## By default, the languages requested by the browser are used if available, with English as default.<br>
## Set i18n.enabled=false to disable automatic language choice.<br>
i18n.enabled = false<br>
## To Force a language, set i18n.enabled=false and specify the language in i18n.lang.<br>
## Valid values are the names of subdirectories in kallithea/i18n with a LC_MESSAGES/kallithea.mo<br>
i18n.lang = en<br>
<br>
cache_dir = %(here)s/data<br>
index_dir = %(here)s/data/index<br>
<br>
## uncomment and set this path to use archive download cache<br>
archive_cache_dir = %(here)s/tarballcache<br>
<br>
## change this to unique ID for security<br>
app_instance_uuid = 339b99011ca3463a8b4c2b64680cded0<br>
<br>
## cut off limit for large diffs (size in bytes)<br>
cut_off_limit = 256000<br>
<br>
## force https in Kallithea, fixes https redirects, assumes it's always https<br>
force_https = true<br>
<br>
## use Strict-Transport-Security headers<br>
use_htsts = false<br>
<br>
## number of commits stats will parse on each iteration<br>
commit_parse_limit = 25<br>
<br>
## Path to Python executable to be used for git hooks.<br>
## This value will be written inside the git hook scripts as the text<br>
## after '#!' (shebang). When empty or not defined, the value of<br>
## 'sys.executable' at the time of installation of the git hooks is<br>
## used, which is correct in many cases but for example not when using uwsgi.<br>
## If you change this setting, you should reinstall the Git hooks via<br>
## Admin > Settings > Remap and Rescan.<br>
#git_hook_interpreter = /srv/kallithea/venv/bin/python3<br>
git_hook_interpreter = /srv/kallithea/venv/bin/python3<br>
<br>
## path to git executable<br>
git_path = git<br>
<br>
## git rev filter option, --all is the default filter, if you need to<br>
## hide all refs in changelog switch this to --branches --tags<br>
#git_rev_filter = --branches --tags<br>
<br>
## RSS feed options<br>
rss_cut_off_limit = 256000<br>
rss_items_per_page = 10<br>
rss_include_diff = false<br>
<br>
## options for showing and identifying changesets<br>
show_sha_length = 12<br>
show_revision_number = false<br>
<br>
## Canonical URL to use when creating full URLs in UI and texts.<br>
## Useful when the site is available under different names or protocols.<br>
## Defaults to what is provided in the WSGI environment.<br>
#canonical_url = <a href="https://kallithea.example.com/repos" rel="noreferrer" target="_blank">https://kallithea.example.com/repos</a><br>
<br>
## gist URL alias, used to create nicer urls for gist. This should be an<br>
## url that does rewrites to _admin/gists/<gistid>.<br>
## example: <a href="http://gist.example.com/%7Bgistid%7D" rel="noreferrer" target="_blank">http://gist.example.com/{gistid}</a>. Empty means use the internal<br>
## Kallithea url, ie. http[s]://<a href="http://kallithea.example.com/_admin/gists/" rel="noreferrer" target="_blank">kallithea.example.com/_admin/gists/</a><gistid><br>
gist_alias_url =<br>
<br>
## default encoding used to convert from and to unicode<br>
## can be also a comma separated list of encoding in case of mixed encodings<br>
default_encoding = utf-8<br>
<br>
## Set Mercurial encoding, similar to setting HGENCODING before launching Kallithea<br>
hgencoding = utf-8<br>
<br>
## issue tracker for Kallithea (leave blank to disable, absent for default)<br>
#bugtracker = <a href="https://bitbucket.org/conservancy/kallithea/issues" rel="noreferrer" target="_blank">https://bitbucket.org/conservancy/kallithea/issues</a><br>
<br>
## issue tracking mapping for commit messages, comments, PR descriptions, ...<br>
## Refer to the documentation ("Integration with issue trackers") for more details.<br>
<br>
## regular expression to match issue references<br>
## This pattern may/should contain parenthesized groups, that can<br>
## be referred to in issue_server_link or issue_sub using Python backreferences<br>
## (e.g. \1, \2, ...). You can also create named groups with '(?P<groupname>)'.<br>
## To require mandatory whitespace before the issue pattern, use:<br>
## (?:^|(?<=\s)) before the actual pattern, and for mandatory whitespace<br>
## behind the issue pattern, use (?:$|(?=\s)) after the actual pattern.<br>
<br>
#issue_pat = #(\d+)<br>
issue_pat = (Case\s?|#)(\d+)<br>
<br>
## server url to the issue<br>
## This pattern may/should contain backreferences to parenthesized groups in issue_pat.<br>
## A backreference can be \1, \2, ... or \g<groupname> if you specified a named group<br>
## called 'groupname' in issue_pat.<br>
## The special token {repo} is replaced with the full repository name<br>
## including repository groups, while {repo_name} is replaced with just<br>
## the name of the repository.<br>
<br>
#issue_server_link = <a href="https://issues.example.com/%7Brepo%7D/issue/%5C1" rel="noreferrer" target="_blank">https://issues.example.com/{repo}/issue/\1</a><br>
issue_server_link = <a href="https://hq.domain.pl/support/default.asp" rel="noreferrer" target="_blank">https://hq.domain.pl/support/default.asp</a>?\2<br>
<br>
## substitution pattern to use as the link text<br>
## If issue_sub is empty, the text matched by issue_pat is retained verbatim<br>
## for the link text. Otherwise, the link text is that of issue_sub, with any<br>
## backreferences to groups in issue_pat replaced.<br>
<br>
issue_sub =<br>
<br>
## issue_pat, issue_server_link and issue_sub can have suffixes to specify<br>
## multiple patterns, to other issues server, wiki or others<br>
## below an example how to create a wiki pattern<br>
## wiki-some-id -> <a href="https://wiki.example.com/some-id" rel="noreferrer" target="_blank">https://wiki.example.com/some-id</a><br>
<br>
#issue_pat_wiki = wiki-(\S+)<br>
#issue_server_link_wiki = <a href="https://wiki.example.com/%5C1" rel="noreferrer" target="_blank">https://wiki.example.com/\1</a><br>
#issue_sub_wiki = WIKI-\1<br>
<br>
## alternative return HTTP header for failed authentication. Default HTTP<br>
## response is 401 HTTPUnauthorized. Currently Mercurial clients have trouble with<br>
## handling that. Set this variable to 403 to return HTTPForbidden<br>
auth_ret_code =<br>
<br>
## allows to change the repository location in settings page<br>
allow_repo_location_change = True<br>
<br>
## allows to setup custom hooks in settings page<br>
allow_custom_hooks_settings = True<br>
<br>
## extra extensions for indexing, space separated and without the leading '.'.<br>
#index.extensions =<br>
#    gemfile<br>
#    lock<br>
<br>
## extra filenames for indexing, space separated<br>
#index.filenames =<br>
#    .dockerignore<br>
#    .editorconfig<br>
#    INSTALL<br>
#    CHANGELOG<br>
<br>
####################################<br>
##            SSH CONFIG          ##<br>
####################################<br>
<br>
## SSH is disabled by default, until an Administrator decides to enable it.<br>
ssh_enabled = true<br>
<br>
## File where users' SSH keys will be stored *if* ssh_enabled is true.<br>
#ssh_authorized_keys = /home/kallithea/.ssh/authorized_keys<br>
ssh_authorized_keys = /srv/kallithea/.ssh/authorized_keys<br>
<br>
## Path to be used in ssh_authorized_keys file to invoke kallithea-cli with ssh-serve.<br>
#kallithea_cli_path = /srv/kallithea/venv/bin/kallithea-cli<br>
kallithea_cli_path = /srv/kallithea/venv/bin/kallithea-cli<br>
<br>
## Locale to be used in the ssh-serve command.<br>
## This is needed because an SSH client may try to use its own locale<br>
## settings, which may not be available on the server.<br>
## See `locale -a` for valid values on this system.<br>
#ssh_locale = C.UTF-8<br>
ssh_locale = en_US.UTF-8<br>
<br>
####################################<br>
##         CELERY CONFIG          ##<br>
####################################<br>
<br>
## Note: Celery doesn't support Windows.<br>
use_celery = false<br>
<br>
## Celery config settings from <a href="https://docs.celeryproject.org/en/4.4.0/userguide/configuration.html" rel="noreferrer" target="_blank">https://docs.celeryproject.org/en/4.4.0/userguide/configuration.html</a> prefixed with 'celery.'.<br>
<br>
## Example: use the message queue on the local virtual host 'kallitheavhost' as the RabbitMQ user 'kallithea':<br>
celery.broker_url = amqp://kallithea:thepassword@localhost:5672/kallitheavhost<br>
<br>
celery.result.backend = db+sqlite:///celery-results.db<br>
<br>
#celery.amqp.task.result.expires = 18000<br>
<br>
celery.worker_concurrency = 2<br>
celery.worker_max_tasks_per_child = 1<br>
<br>
## If true, tasks will never be sent to the queue, but executed locally instead.<br>
celery.task_always_eager = false<br>
<br>
####################################<br>
##          BEAKER CACHE          ##<br>
####################################<br>
<br>
beaker.cache.data_dir = %(here)s/data/cache/data<br>
beaker.cache.lock_dir = %(here)s/data/cache/lock<br>
<br>
beaker.cache.regions = long_term,long_term_file<br>
<br>
beaker.cache.long_term.type = memory<br>
beaker.cache.long_term.expire = 36000<br>
beaker.cache.long_term.key_length = 256<br>
<br>
beaker.cache.long_term_file.type = file<br>
beaker.cache.long_term_file.expire = 604800<br>
beaker.cache.long_term_file.key_length = 256<br>
<br>
####################################<br>
##        BEAKER SESSION          ##<br>
####################################<br>
<br>
## Name of session cookie. Should be unique for a given host and path, even when running<br>
## on different ports. Otherwise, cookie sessions will be shared and messed up.<br>
session.key = kallithea<br>
## Sessions should always only be accessible by the browser, not directly by JavaScript.<br>
session.httponly = true<br>
## Session lifetime. 2592000 seconds is 30 days.<br>
session.timeout = 2592000<br>
<br>
## Server secret used with HMAC to ensure integrity of cookies.<br>
session.secret = <secret removed><br>
## Further, encrypt the data with AES.<br>
#session.encrypt_key = <key_for_encryption><br>
#session.validate_key = <validation_key><br>
<br>
## Type of storage used for the session, current types are<br>
## dbm, file, memcached, database, and memory.<br>
<br>
## File system storage of session data. (default)<br>
#session.type = file<br>
<br>
## Cookie only, store all session data inside the cookie. Requires secure secrets.<br>
#session.type = cookie<br>
<br>
## Database storage of session data.<br>
#session.type = ext:database<br>
#session.sa.url = postgresql://postgres:qwe@localhost/kallithea<br>
#session.table_name = db_session<br>
<br>
####################################<br>
##        ERROR HANDLING          ##<br>
####################################<br>
<br>
## Show a nice error page for application HTTP errors and exceptions (default true)<br>
#errorpage.enabled = true<br>
<br>
## Enable Backlash client-side interactive debugger (default false)<br>
## WARNING: *THIS MUST BE false IN PRODUCTION ENVIRONMENTS!!!*<br>
## This debug mode will allow all visitors to execute malicious code.<br>
#debug = false<br>
<br>
## Enable Backlash server-side error reporting (unless debug mode handles it client-side) (default true)<br>
#trace_errors.enable = true<br>
## Errors will be reported by mail if trace_errors.error_email is set.<br>
<br>
## Propagate email settings to ErrorReporter of TurboGears2<br>
## You do not normally need to change these lines<br>
get trace_errors.smtp_server = smtp_server<br>
get trace_errors.smtp_port = smtp_port<br>
get trace_errors.from_address = error_email_from<br>
get trace_errors.error_email = email_to<br>
get trace_errors.smtp_username = smtp_username<br>
get trace_errors.smtp_password = smtp_password<br>
get trace_errors.smtp_use_tls = smtp_use_tls<br>
<br>
<br>
##################################<br>
##        LOGVIEW CONFIG        ##<br>
##################################<br>
<br>
logview.sqlalchemy = #faa<br>
logview.pylons.templating = #bfb<br>
logview.pylons.util = #eee<br>
<br>
#########################<br>
##      DB CONFIG      ##<br>
#########################<br>
<br>
## SQLITE [default]<br>
sqlalchemy.url = sqlite:///%(here)s/kallithea.db?timeout=60<br>
<br>
## see sqlalchemy docs for other backends<br>
<br>
sqlalchemy.pool_recycle = 3600<br>
<br>
################################<br>
##   ALEMBIC CONFIGURATION    ##<br>
################################<br>
<br>
[alembic]<br>
script_location = kallithea:alembic<br>
<br>
################################<br>
##   LOGGING CONFIGURATION    ##<br>
################################<br>
<br>
[loggers]<br>
keys = root, routes, kallithea, sqlalchemy, tg, gearbox, beaker, templates, whoosh_indexer, werkzeug, backlash<br>
<br>
[handlers]<br>
keys = console, console_color, console_color_sql, null<br>
<br>
[formatters]<br>
keys = generic, color_formatter, color_formatter_sql<br>
<br>
#############<br>
## LOGGERS ##<br>
#############<br>
<br>
[logger_root]<br>
level = NOTSET<br>
handlers = console<br>
## For coloring based on log level:<br>
#handlers = console_color<br>
<br>
[logger_routes]<br>
level = WARN<br>
handlers =<br>
qualname = routes.middleware<br>
## "level = DEBUG" logs the route matched and routing variables.<br>
<br>
[logger_beaker]<br>
level = WARN<br>
handlers =<br>
qualname = beaker.container<br>
<br>
[logger_templates]<br>
level = WARN<br>
handlers =<br>
qualname = pylons.templating<br>
<br>
[logger_kallithea]<br>
level = WARN<br>
handlers =<br>
qualname = kallithea<br>
<br>
[logger_tg]<br>
level = WARN<br>
handlers =<br>
qualname = tg<br>
<br>
[logger_gearbox]<br>
level = WARN<br>
handlers =<br>
qualname = gearbox<br>
<br>
[logger_sqlalchemy]<br>
level = WARN<br>
handlers =<br>
qualname = sqlalchemy.engine<br>
## For coloring based on log level and pretty printing of SQL:<br>
#level = INFO<br>
#handlers = console_color_sql<br>
#propagate = 0<br>
<br>
[logger_whoosh_indexer]<br>
level = WARN<br>
handlers =<br>
qualname = whoosh_indexer<br>
<br>
[logger_werkzeug]<br>
level = WARN<br>
handlers =<br>
qualname = werkzeug<br>
<br>
[logger_backlash]<br>
level = WARN<br>
handlers =<br>
qualname = backlash<br>
<br>
##############<br>
## HANDLERS ##<br>
##############<br>
<br>
[handler_console]<br>
class = StreamHandler<br>
args = (sys.stderr,)<br>
formatter = generic<br>
<br>
[handler_console_color]<br>
## ANSI color coding based on log level<br>
class = StreamHandler<br>
args = (sys.stderr,)<br>
formatter = color_formatter<br>
<br>
[handler_console_color_sql]<br>
## ANSI color coding and pretty printing of SQL statements<br>
class = StreamHandler<br>
args = (sys.stderr,)<br>
formatter = color_formatter_sql<br>
<br>
[handler_null]<br>
class = NullHandler<br>
args = ()<br>
<br>
################<br>
## FORMATTERS ##<br>
################<br>
<br>
[formatter_generic]<br>
format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s<br>
datefmt = %Y-%m-%d %H:%M:%S<br>
<br>
[formatter_color_formatter]<br>
class = kallithea.lib.colored_formatter.ColorFormatter<br>
format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s<br>
datefmt = %Y-%m-%d %H:%M:%S<br>
<br>
[formatter_color_formatter_sql]<br>
class = kallithea.lib.colored_formatter.ColorFormatterSql<br>
format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s<br>
datefmt = %Y-%m-%d %H:%M:%S<br>
<br>
#################<br>
## SSH LOGGING ##<br>
#################<br>
<br>
## The default loggers use 'handler_console' that uses StreamHandler with<br>
## destination 'sys.stderr'. In the context of the SSH server process, these log<br>
## messages would be sent to the client, which is normally not what you want.<br>
## By default, when running ssh-serve, just use NullHandler and disable logging<br>
## completely. For other logging options, see:<br>
## <a href="https://docs.python.org/2/library/logging.handlers.html" rel="noreferrer" target="_blank">https://docs.python.org/2/library/logging.handlers.html</a><br>
<br>
[ssh_serve:logger_root]<br>
level = CRITICAL<br>
handlers = null<br>
<br>
## Note: If logging is configured with other handlers, they might need similar<br>
## muting for ssh-serve too.<br>
<br>
<br>
_______________________________________________<br>
kallithea-general mailing list<br>
<a href="mailto:kallithea-general@sfconservancy.org" target="_blank">kallithea-general@sfconservancy.org</a><br>
<a href="https://lists.sfconservancy.org/mailman/listinfo/kallithea-general" rel="noreferrer" target="_blank">https://lists.sfconservancy.org/mailman/listinfo/kallithea-general</a><br>
</blockquote></div>