docker-compose.yaml 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. {% from "macros/nginx.conf" import nginx_conf, nginx_headers %}
  2. {% from "macros/crontasks" import crontasks %}
  3. {% from "macros/tune.ini" import php_tune_ini, redis_session, opcache_recommended %}
  4. {% from "macros/builder.jinja" import builder %}
  5. {% set tpl = ix_lib.base.render.Render(values) %}
  6. {% set nc_custom_image = namespace(x=[]) %}
  7. {% do builder(values.nextcloud.build, nc_custom_image) %}
  8. {% set perm_container = tpl.deps.perms(values.consts.perms_container_name) %}
  9. {% set perm_config = {"uid": values.run_as.user, "gid": values.run_as.group, "mode": "check"} %}
  10. {# -- Postgres -- #}
  11. {% set pg_config = {
  12. "user": values.consts.db_user,
  13. "password": values.nextcloud.db_password,
  14. "database": values.consts.db_name,
  15. "volume": values.storage.postgres_data,
  16. } %}
  17. {% set postgres = tpl.deps.postgres(
  18. values.consts.postgres_container_name,
  19. values.nextcloud.postgres_image_selector,
  20. pg_config, perm_container
  21. ) %}
  22. {# -- Redis -- #}
  23. {% do tpl.funcs.disallow_chars(values.nextcloud.redis_password, ["&", "@", "#", "%"], "redis_password") %}
  24. {% set redis_config = {
  25. "password": values.nextcloud.redis_password,
  26. "volume": {"type": "temporary", "volume_config": {"volume_name": "redis-data"}},
  27. } %}
  28. {% set redis = tpl.deps.redis(values.consts.redis_container_name, "redis_image", redis_config, perm_container) %}
  29. {# -- Nextcloud -- #}
  30. {% set nc_container = tpl.add_container(values.consts.nextcloud_container_name, "image") %}
  31. {% if nc_custom_image.x %}
  32. {% do nc_container.build_image(nc_custom_image.x) %}
  33. {% endif %}
  34. {% do nc_container.set_user(values.run_as.user, values.run_as.group) %}
  35. {% do nc_container.healthcheck.set_custom_test("/healthcheck.sh") %}
  36. {% do nc_container.add_extra_host("host.docker.internal", "host-gateway") %}
  37. {% do nc_container.depends.add_dependency(values.consts.postgres_container_name, "service_healthy") %}
  38. {% do nc_container.depends.add_dependency(values.consts.redis_container_name, "service_healthy") %}
  39. {% do nc_container.configs.add("php_tune", php_tune_ini(values), "/usr/local/etc/php-fpm.d/zz-tune.conf") %}
  40. {% do nc_container.configs.add("redis_session", redis_session(values), "/usr/local/etc/php/conf.d/redis-session.ini") %}
  41. {% do nc_container.configs.add("opcache_recommended", opcache_recommended(values), "/usr/local/etc/php/conf.d/opcache-recommended.ini") %}
  42. {% do nc_container.environment.add_user_envs(values.nextcloud.additional_envs) %}
  43. {# Only on initial startup #}
  44. {% do nc_container.environment.add_env("NEXTCLOUD_ADMIN_USER", values.nextcloud.admin_user) %}
  45. {% do nc_container.environment.add_env("NEXTCLOUD_ADMIN_PASSWORD", values.nextcloud.admin_password) %}
  46. {% do nc_container.environment.add_env("POSTGRES_HOST", values.consts.postgres_container_name) %}
  47. {% do nc_container.environment.add_env("POSTGRES_DB", values.consts.db_name) %}
  48. {% do nc_container.environment.add_env("POSTGRES_USER", values.consts.db_user) %}
  49. {% do nc_container.environment.add_env("POSTGRES_PASSWORD", values.nextcloud.db_password) %}
  50. {% do nc_container.environment.add_env("NEXTCLOUD_DATA_DIR", values.consts.data_path) %}
  51. {# On every startup #}
  52. {% do nc_container.environment.add_env("PHP_MEMORY_LIMIT", "%dM" | format(values.nextcloud.performance.php_memory_limit_mb)) %}
  53. {% do nc_container.environment.add_env("PHP_UPLOAD_LIMIT", "%dG" | format(values.nextcloud.performance.php_upload_limit_gb)) %}
  54. {% do nc_container.environment.add_env("IX_MAINTENANCE_WINDOW_START", values.nextcloud.general.maintenance_window_start) %}
  55. {% do nc_container.environment.add_env("IX_DEFAULT_PHONE_REGION", values.nextcloud.general.default_phone_region) %}
  56. {% do nc_container.environment.add_env("IX_RUN_OPTIMIZE", values.nextcloud.performance.run_optimize) %}
  57. {% do nc_container.environment.add_env("IX_MAX_CHUNKSIZE", values.nextcloud.performance.max_chunksize_mb * 1024 * 1024) %}
  58. {% do nc_container.environment.add_env("IX_LOG_LEVEL", 2) %}
  59. {% do nc_container.environment.add_env("IX_LOG_FILE", "/var/www/html/data/logs/nextcloud.log") %}
  60. {% do nc_container.environment.add_env("IX_LOG_FILE_AUDIT", "/var/www/html/data/logs/audit.log") %}
  61. {% do nc_container.environment.add_env("IX_LOG_DATE_FORMAT", "d/m/Y H:i:s") %}
  62. {% do nc_container.environment.add_env("IX_LOG_TIMEZONE", values.TZ) %}
  63. {% do nc_container.environment.add_env("IX_POSTGRES_HOST", values.consts.postgres_container_name) %}
  64. {% do nc_container.environment.add_env("IX_POSTGRES_NAME", values.consts.db_name) %}
  65. {% do nc_container.environment.add_env("IX_POSTGRES_USER", values.consts.db_user) %}
  66. {% do nc_container.environment.add_env("IX_POSTGRES_PASSWORD", values.nextcloud.db_password) %}
  67. {% do nc_container.environment.add_env("IX_REDIS", true) %}
  68. {% do nc_container.environment.add_env("IX_REDIS_HOST", values.consts.redis_container_name) %}
  69. {% do nc_container.environment.add_env("IX_REDIS_PORT", 6379) %}
  70. {% do nc_container.environment.add_env("IX_REDIS_PASS", values.nextcloud.redis_password) %}
  71. {% do nc_container.environment.add_env("IX_PREVIEWS", values.nextcloud.previews.enabled) %}
  72. {% if values.nextcloud.previews.enabled %}
  73. {% do nc_container.environment.add_env("IX_PREVIEW_MAX_X", values.nextcloud.previews.max_x) %}
  74. {% do nc_container.environment.add_env("IX_PREVIEW_MAX_Y", values.nextcloud.previews.max_y) %}
  75. {% do nc_container.environment.add_env("IX_PREVIEW_MAX_MEMORY", values.nextcloud.previews.max_memory_mb) %}
  76. {% do nc_container.environment.add_env("IX_PREVIEW_MAX_FILESIZE_IMAGE", values.nextcloud.previews.max_filesize_image_mb) %}
  77. {% do nc_container.environment.add_env("IX_PREVIEW_JPEG_QUALITY", values.nextcloud.previews.jpeg_quality) %}
  78. {% do nc_container.environment.add_env("IX_PREVIEW_SQUARE_SIZES", values.nextcloud.previews.square_sizes | join(" ")) %}
  79. {% do nc_container.environment.add_env("IX_PREVIEW_WIDTH_SIZES", values.nextcloud.previews.width_sizes | join(" ")) %}
  80. {% do nc_container.environment.add_env("IX_PREVIEW_HEIGHT_SIZES", values.nextcloud.previews.height_sizes | join(" ")) %}
  81. {% do nc_container.environment.add_env("IX_PREVIEW_PROVIDERS", values.nextcloud.previews.providers | unique | list | join(" ")) %}
  82. {% endif %}
  83. {% do nc_container.environment.add_env("IX_ACTIVITY_EXPIRE_DAYS", values.nextcloud.expirations.activity_expire_days) %}
  84. {% do nc_container.environment.add_env("IX_TRASH_RETENTION", values.nextcloud.expirations.trash_retention) %}
  85. {% do nc_container.environment.add_env("IX_VERSIONS_RETENTION", values.nextcloud.expirations.versions_retention) %}
  86. {% set ext_protocol = "https" if values.network.certificate_id else values.nextcloud.urls.protocol %}
  87. {% set ext_port = values.nextcloud.urls.external_port or values.network.web_port.port_number %}
  88. {% set parsed_url = tpl.funcs.url_to_dict(values.nextcloud.urls.host, true) %}
  89. {% if values.nextcloud.urls.host.endswith("/") %}{% do tpl.funcs.fail("Host must not end with a trailing slash.") %}{% endif %}
  90. {% if parsed_url.port %}{% do tpl.funcs.fail("Host must not contain a port number") %}{% endif %}
  91. {% set port_host = "%s:%d" | format(values.nextcloud.urls.host, ext_port) %}
  92. {% set ext_host_port = namespace(x=port_host) %}
  93. {% if ext_port == 443 or ext_port == 80 %}
  94. {% set ext_host_port.x = tpl.funcs.url_to_dict(port_host).host %}
  95. {% endif %}
  96. {% do nc_container.environment.add_env("IX_OVERWRITE_PROTOCOL", ext_protocol) %}
  97. {% do nc_container.environment.add_env("IX_OVERWRITE_HOST", ext_host_port.x) %}
  98. {% do nc_container.environment.add_env("IX_OVERWRITE_CLI_URL", "%s://%s" | format(ext_protocol, ext_host_port.x)) %}
  99. {% do nc_container.environment.add_env("IX_TRUSTED_DOMAINS", ([
  100. "localhost",
  101. "docker.internal.healthcheck",
  102. parsed_url.host,
  103. ] + values.nextcloud.urls.trusted_domains) | unique | list | join(" ")) %}
  104. {% do nc_container.environment.add_env("IX_TRUSTED_PROXIES", values.nextcloud.urls.trusted_proxies | join(" ")) %}
  105. {% do nc_container.environment.add_env("IX_COLLABORA", values.nextcloud.collabora.enabled) %}
  106. {% if values.nextcloud.collabora.enabled %}
  107. {% do nc_container.environment.add_env("IX_COLLABORA_URL", values.nextcloud.collabora.url) %}
  108. {% do nc_container.environment.add_env("IX_COLLABORA_INTERNAL_URL", values.nextcloud.collabora.internal_url) %}
  109. {% do nc_container.environment.add_env("IX_COLLABORA_ALLOWLIST", values.nextcloud.collabora.allowlist | join(" ")) %}
  110. {% endif %}
  111. {% do nc_container.environment.add_env("IX_CLAMAV", values.nextcloud.clamav.enabled) %}
  112. {% if values.nextcloud.clamav.enabled %}
  113. {% do nc_container.environment.add_env("IX_CLAMAV_HOST", values.nextcloud.clamav.host) %}
  114. {% do nc_container.environment.add_env("IX_CLAMAV_PORT", values.nextcloud.clamav.port) %}
  115. {% do nc_container.environment.add_env("IX_CLAMAV_FILE_MAX_SIZE", values.nextcloud.clamav.file_max_size) %}
  116. {% do nc_container.environment.add_env("IX_CLAMAV_INFECTED_ACTION", values.nextcloud.clamav.infected_action) %}
  117. {% do nc_container.environment.add_env("IX_CLAMAV_STREAM_MAX_LENGTH", values.nextcloud.clamav.stream_max_length) %}
  118. {% endif %}
  119. {% do nc_container.environment.add_env("IX_ONLYOFFICE", values.nextcloud.onlyoffice.enabled) %}
  120. {% if values.nextcloud.onlyoffice.enabled %}
  121. {% do nc_container.environment.add_env("IX_ONLYOFFICE_URL", values.nextcloud.onlyoffice.url) %}
  122. {% do nc_container.environment.add_env("IX_ONLYOFFICE_JWT_SECRET", values.nextcloud.onlyoffice.jwt_secret) %}
  123. {% do nc_container.environment.add_env("IX_ONLYOFFICE_JWT_HEADER", values.nextcloud.onlyoffice.jwt_header) %}
  124. {% endif %}
  125. {% do nc_container.add_storage(values.consts.html_path, values.storage.html) %}
  126. {% do perm_container.add_or_skip_action("html", values.storage.html, perm_config) %}
  127. {% do nc_container.add_storage(values.consts.data_path, values.storage.data) %}
  128. {% do perm_container.add_or_skip_action("data", values.storage.data, perm_config) %}
  129. {% for store in values.storage.additional_storage %}
  130. {% do nc_container.add_storage(store.mount_path, store) %}
  131. {% do perm_container.add_or_skip_action(store.mount_path, store, perm_config) %}
  132. {% endfor %}
  133. {# -- Nginx -- #}
  134. {% set nginx_container = tpl.add_container(values.consts.nginx_container_name, "nginx_image") %}
  135. {% do nginx_container.set_user(values.run_as.user, values.run_as.group) %}
  136. {% do nginx_container.healthcheck.set_test("curl", {
  137. "port": values.network.web_port.port_number, "path": "/status.php",
  138. "scheme": "https" if values.network.certificate_id else "http",
  139. "headers": [("Host", "docker.internal.healthcheck")]
  140. }) %}
  141. {% do nginx_container.configs.add("nginx.conf", nginx_conf(values), "/etc/nginx/nginx.conf") %}
  142. {% do nginx_container.configs.add("nginx_headers.conf", nginx_headers(values), "/etc/nginx/nginx-headers.conf") %}
  143. {% do nginx_container.depends.add_dependency(values.consts.nextcloud_container_name, "service_healthy") %}
  144. {% if values.network.certificate_id %}
  145. {% set cert = values.ix_certificates[values.network.certificate_id] %}
  146. {% do nginx_container.configs.add("private", cert.privatekey, values.consts.ssl_key_path) %}
  147. {% do nginx_container.configs.add("public", cert.certificate, values.consts.ssl_cert_path) %}
  148. {% endif %}
  149. {% do nginx_container.add_port(values.network.web_port) %}
  150. {% do nginx_container.add_storage(values.consts.html_path, dict(values.storage.html, **{"read_only": true})) %}
  151. {# -- Cron -- #}
  152. {% set cron_container = tpl.add_container(values.consts.cron_container_name, "image") %}
  153. {% do cron_container.set_user(values.run_as.user, values.run_as.group) %}
  154. {% do cron_container.healthcheck.disable() %}
  155. {% do cron_container.set_entrypoint(["/cron.sh"]) %}
  156. {% do cron_container.depends.add_dependency(values.consts.nginx_container_name, "service_healthy") %}
  157. {% do cron_container.configs.add("crontasks", crontasks(values.nextcloud.cron.tasks), "/crontasks") %}
  158. {% do cron_container.add_storage(values.consts.html_path, values.storage.html) %}
  159. {% do cron_container.add_storage(values.consts.data_path, values.storage.data) %}
  160. {% for store in values.storage.additional_storage %}
  161. {% do cron_container.add_storage(store.mount_path, store) %}
  162. {% endfor %}
  163. {# -- Imaginary -- #}
  164. {% do nc_container.environment.add_env("IX_IMAGINARY", values.nextcloud.previews.enabled and values.nextcloud.previews.imaginary.enabled) %}
  165. {% if values.nextcloud.previews.enabled and values.nextcloud.previews.imaginary.enabled %}
  166. {% set imaginary_container = tpl.add_container(values.consts.imaginary_container_name, "imaginary_image") %}
  167. {% do imaginary_container.set_user(values.run_as.user, values.run_as.group) %}
  168. {% do imaginary_container.healthcheck.set_test("wget", {"port": values.consts.internal_imaginary_port, "path": "/health"}) %}
  169. {% do imaginary_container.set_entrypoint([
  170. "imaginary",
  171. "-p", "9000",
  172. "-concurrency", "20",
  173. "-max-allowed-resolution", "222.2",
  174. "-enable-url-source",
  175. "-return-size",
  176. ])%}
  177. {% do nc_container.environment.add_env("IX_IMAGINARY_URL", "http://%s:%s" | format(values.consts.imaginary_container_name, values.consts.internal_imaginary_port)) %}
  178. {% endif %}
  179. {# -- Notify Push -- #}
  180. {% do nc_container.environment.add_env("IX_NOTIFY_PUSH", values.nextcloud.notify_push.enabled) %}
  181. {% if values.nextcloud.notify_push.enabled %}
  182. {% set notify_push_container = tpl.add_container(values.consts.notify_push_container_name, "notify_push_image") %}
  183. {% do notify_push_container.set_user(values.run_as.user, values.run_as.group) %}
  184. {% do notify_push_container.healthcheck.set_test("curl", {
  185. "port": values.consts.internal_notify_push_port, "path": "/push/test/cookie",
  186. "headers": [("Host", "docker.internal.healthcheck")]
  187. }) %}
  188. {% do notify_push_container.environment.add_env("NEXTCLOUD_URL", "%s://%s:%s" | format(
  189. "https" if values.network.certificate_id else "http",
  190. values.consts.nginx_container_name, values.network.web_port.port_number
  191. )) %}
  192. {% do notify_push_container.environment.add_env("CONFIG_FILE", "%s/config/config.php" | format(values.consts.html_path)) %}
  193. {% do notify_push_container.depends.add_dependency(values.consts.nextcloud_container_name, "service_healthy") %}
  194. {% do notify_push_container.add_storage(values.consts.html_path, dict(values.storage.html, **{"read_only": true})) %}
  195. {% do nc_container.environment.add_env("IX_NOTIFY_PUSH_ENDPOINT", "%s://%s/push" | format(ext_protocol, ext_host_port.x)) %}
  196. {% endif %}
  197. {% if perm_container.has_actions() %}
  198. {% do perm_container.activate() %}
  199. {% do nc_container.depends.add_dependency(values.consts.perms_container_name, "service_completed_successfully") %}
  200. {% do redis.container.depends.add_dependency(values.consts.perms_container_name, "service_completed_successfully") %}
  201. {% do postgres.add_dependency(values.consts.perms_container_name, "service_completed_successfully") %}
  202. {% endif %}
  203. {% do tpl.portals.add(values.network.web_port, {"port": ext_port, "scheme": ext_protocol, "host": parsed_url.host}) %}
  204. {% do tpl.notes.set_body(values.consts.notes) %}
  205. {{ tpl.render() | tojson }}