Files
upstream-zulip/puppet/zulip/manifests/app_frontend_base.pp
upstream-mirror 64898b2c79
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
2026-09-15 15:05:30 +05:00

319 lines
11 KiB
Puppet

# Minimal configuration to run a Zulip application server.
# Default nginx configuration is included in extension app_frontend.pp.
class zulip::app_frontend_base {
include zulip::nginx
include zulip::tusd
include zulip::sasl_modules
include zulip::supervisor
include zulip::tornado_sharding
include zulip::hooks::base
if $facts['os']['family'] == 'Debian' {
# Upgrade and other tooling wants to be able to get a database
# shell. This is not necessary on CentOS because the PostgreSQL
# package already includes the client.
include zulip::postgresql_client
}
zulip::safepackage {
[
# For `manage.py compilemessages` when upgrading from Git.
'gettext',
# For Slack import.
'unzip',
# Ensures `/etc/ldap/ldap.conf` exists; the default
# `TLS_CACERTDIR` specified there is necessary for LDAP
# authentication to work. This package is "Recommended" by
# `libldap` where is required by postgres, so has been on most
# Zulip servers by default; adding it here explicitly ensures it
# is available on those that don't include the database server.
'libldap-common',
]:
ensure => installed,
}
file { '/etc/nginx/zulip-include/app':
require => Package[$zulip::common::nginx],
owner => 'root',
group => 'root',
mode => '0644',
source => 'puppet:///modules/zulip/nginx/zulip-include-frontend/app',
notify => Service['nginx'],
}
file { '/etc/nginx/zulip-include/uploads.types':
require => Package[$zulip::common::nginx],
owner => 'root',
group => 'root',
mode => '0644',
source => 'puppet:///modules/zulip/nginx/zulip-include-frontend/uploads.types',
notify => Service['nginx'],
}
file { '/etc/nginx/zulip-include/app.d/':
ensure => directory,
owner => 'root',
group => 'root',
mode => '0755',
}
file { '/etc/nginx/zulip-include/localhost.d/':
ensure => directory,
owner => 'root',
group => 'root',
mode => '0755',
}
$loadbalancers = split(zulipconf('loadbalancer', 'ips', ''), ',')
if $loadbalancers != [] {
file { '/etc/nginx/zulip-include/app.d/keepalive-loadbalancer.conf':
require => File['/etc/nginx/zulip-include/app.d'],
owner => 'root',
group => 'root',
mode => '0644',
source => 'puppet:///modules/zulip/nginx/zulip-include-app.d/keepalive-loadbalancer.conf',
notify => Service['nginx'],
}
} else {
file { '/etc/nginx/zulip-include/app.d/keepalive-loadbalancer.conf':
ensure => absent,
notify => Service['nginx'],
}
}
file { '/etc/nginx/zulip-include/app.d/accept-loadbalancer.conf':
# This moved to /etc/nginx/zulip-include/trusted-ip, via
# nginx.pp. This block can be removed once direct Zulip upgrades
# from Zulip 11 are no longer supported.
ensure => absent,
notify => Service['nginx'],
}
file { '/etc/nginx/zulip-include/app.d/healthcheck.conf':
require => File['/etc/nginx/zulip-include/app.d'],
owner => 'root',
group => 'root',
mode => '0644',
content => template('zulip/nginx/healthcheck.conf.template.erb'),
notify => Service['nginx'],
}
file { '/etc/nginx/zulip-include/upstreams':
require => Package[$zulip::common::nginx],
owner => 'root',
group => 'root',
mode => '0644',
source => 'puppet:///modules/zulip/nginx/zulip-include-frontend/upstreams',
notify => Service['nginx'],
}
$s3_memory_cache_size = zulipconf('application_server', 's3_memory_cache_size', '1M')
$s3_disk_cache_size = zulipconf('application_server', 's3_disk_cache_size', '200M')
$s3_cache_inactive_time = zulipconf('application_server', 's3_cache_inactive_time', '30d')
$configured_nginx_resolver = zulipconf('application_server', 'nameserver', '')
if $configured_nginx_resolver == '' {
# This may fail in the unlikely change that there is no configured
# resolver in /etc/resolv.conf, so only call it is unset in zulip.conf
$nginx_resolver_ip = resolver_ip()
} elsif (':' in $configured_nginx_resolver) and ! ('.' in $configured_nginx_resolver) and ! ('[' in $configured_nginx_resolver) {
# Assume this is IPv6, which needs square brackets.
$nginx_resolver_ip = "[${configured_nginx_resolver}]"
} else {
$nginx_resolver_ip = $configured_nginx_resolver
}
file { '/etc/nginx/zulip-include/s3-cache':
require => [
Package[$zulip::common::nginx],
File['/srv/zulip-uploaded-files-cache'],
],
owner => 'root',
group => 'root',
mode => '0644',
content => template('zulip/nginx/s3-cache.template.erb'),
notify => Service['nginx'],
}
file { '/etc/nginx/zulip-include/app.d/uploads-internal.conf':
ensure => file,
require => Package[$zulip::common::nginx],
owner => 'root',
group => 'root',
mode => '0644',
notify => Service['nginx'],
source => 'puppet:///modules/zulip/nginx/zulip-include-frontend/uploads-internal.conf',
}
# This determines whether we run queue processors multithreaded or
# multiprocess. Multiprocess scales much better, but requires more
# RAM; we just auto-detect based on available system RAM.
#
# Because Zulip can run in the multiprocess mode with 4GB of memory,
# and it's a common instance size, we aim for that to be the cutoff
# for this higher-performance mode.
#
# We use a cutoff less than 4000 here to detect systems advertised
# as "4GB"; some may have as little as 4 x 1000^3 / 1024^2 ≈ 3815 MiB
# of memory.
$queues_multiprocess_default = $zulip::common::total_memory_mb > 3800
$queues_multiprocess = zulipconf('application_server', 'queue_workers_multiprocess', $queues_multiprocess_default)
$base_queues = [
'deferred_work',
'digest_emails',
'email_mirror',
'embed_links',
'embedded_bots',
'email_senders',
'deferred_email_senders',
'missedmessage_emails',
'missedmessage_mobile_notifications',
'outgoing_webhooks',
'thumbnail',
'user_activity',
'user_activity_interval',
]
# Soft reactivations normally share the deferred_work queue; larger
# servers can opt into a dedicated queue (and worker process) for them.
$queues = zulipconf('application_server', 'dedicated_soft_reactivation_queue', false) ? {
true => $base_queues + ['soft_reactivation'],
default => $base_queues,
}
if $zulip::common::total_memory_mb > 24000 {
$uwsgi_default_processes = 16
} elsif $zulip::common::total_memory_mb > 12000 {
$uwsgi_default_processes = 8
} elsif $zulip::common::total_memory_mb > 6000 {
$uwsgi_default_processes = 6
} elsif $zulip::common::total_memory_mb > 3000 {
$uwsgi_default_processes = 4
} else {
$uwsgi_default_processes = 3
}
# Not the different naming scheme for sharded workers, where each gets its own queue,
# vs when multiple workers service the same queue.
$worker_counts = Hash(zulipconf_keys('application_server').filter |$key| {
$key =~ /_workers$/
}.map |$key| {
[regsubst($key, '_workers$', ''), Integer(zulipconf('application_server', $key, 1))]
})
$mobile_notification_shards = Integer(zulipconf('application_server', 'mobile_notification_shards', 1))
$user_activity_shards = Integer(zulipconf('application_server', 'user_activity_shards', 1))
$tornado_ports = $zulip::tornado_sharding::tornado_ports
$proxy_host = zulipconf('http_proxy', 'host', 'localhost')
$proxy_port = zulipconf('http_proxy', 'port', '4750')
if ($proxy_host in ['localhost', '127.0.0.1', '::1']) and ($proxy_port == '4750') {
include zulip::smokescreen
}
$katex_server = zulipconf('application_server', 'katex_server', true)
$katex_server_port = zulipconf('application_server', 'katex_server_port', '9700')
$tusd_server_listen = zulipconf('application_server', 'tusd_server_listen', '127.0.0.1')
# Supervisor sets this as HTTP_proxy/HTTPS_proxy in every process's
# environment, so that all outgoing requests go through Smokescreen;
# including those made directly by libraries rather than through
# OutgoingSession.
if $proxy_host != '' and $proxy_port != '' {
$proxy = "http://${proxy_host}:${proxy_port}"
} else {
$proxy = ''
}
$custom_ca_path = zulipconf('application_server','custom_ca_path', '')
if $custom_ca_path != '' {
file { '/usr/local/share/ca-certificates/custom-zulip-ca.crt':
ensure => file,
source => $custom_ca_path,
owner => 'root',
group => 'root',
mode => '0644',
notify => Exec['update-ca-certificates'],
}
exec { 'update-ca-certificates':
command => '/usr/sbin/update-ca-certificates',
require => Package['ca-certificates'],
before => File["${zulip::common::supervisor_conf_dir}/zulip.conf"],
refreshonly => true,
}
$ca_bundle=',REQUESTS_CA_BUNDLE="/etc/ssl/certs/ca-certificates.crt"'
} else {
$ca_bundle=''
}
file { "${zulip::common::supervisor_conf_dir}/zulip.conf":
ensure => file,
require => [Package[supervisor], Exec['stage_updated_sharding']],
owner => 'root',
group => 'root',
mode => '0644',
content => template('zulip/supervisor/zulip.conf.template.erb'),
notify => Service[$zulip::common::supervisor_service],
}
$uwsgi_rolling_restart = zulipconf('application_server', 'rolling_restart', false)
$uwsgi_listen_backlog_limit = zulipconf('application_server', 'uwsgi_listen_backlog_limit', 128)
$uwsgi_processes = zulipconf('application_server', 'uwsgi_processes', $uwsgi_default_processes)
$somaxconn = 2 * Integer($uwsgi_listen_backlog_limit)
file { '/etc/zulip/uwsgi.ini':
ensure => file,
require => Package[supervisor],
owner => 'root',
group => 'root',
mode => '0644',
content => template('zulip/uwsgi.ini.template.erb'),
notify => Service[$zulip::common::supervisor_service],
}
zulip::sysctl { 'uwsgi':
comment => 'Allow larger listen backlog',
key => 'net.core.somaxconn',
value => $somaxconn,
}
file { [
'/home/zulip/tornado',
'/home/zulip/prod-static',
'/home/zulip/deployments',
'/srv/zulip-locks',
'/srv/zulip-emoji-cache',
'/srv/zulip-uploaded-files-cache',
]:
ensure => directory,
owner => 'zulip',
group => 'zulip',
mode => '0755',
}
# /home/zulip/uploads is documented as something administrators may
# replace with a symlink to a different storage location, so we use
# an exec with a `test -d` guard (which follows symlinks) rather
# than a file resource that would replace the symlink.
exec { 'create-uploads-dir':
command => 'install -d -o zulip -g zulip -m 0755 /home/zulip/uploads',
unless => 'test -d /home/zulip/uploads',
path => '/usr/bin:/bin',
}
file { [
'/var/log/zulip/queue_error',
'/var/log/zulip/queue_stats',
]:
ensure => directory,
owner => 'zulip',
group => 'zulip',
mode => '0750',
}
$access_log_retention_days = zulipconf('application_server','access_log_retention_days', 14)
file { '/etc/logrotate.d/zulip':
ensure => file,
owner => 'root',
group => 'root',
mode => '0644',
content => template('zulip/logrotate/zulip.template.erb'),
}
zulip::nagios_plugins {'zulip_app_frontend': }
# This cron job does nothing unless RATE_LIMIT_TOR_TOGETHER is enabled.
zulip::cron { 'fetch-tor-exit-nodes':
minute => '17',
}
# This was originally added with a typo in the name.
file { '/etc/cron.d/fetch-for-exit-nodes':
ensure => absent,
}
}