Files
truenas-apps/ix-dev/stable/nextcloud/templates/docker-compose.yaml
Tyson bb3c43bf3d Added Imaginary as an optional container alongside NextCloud (#1351)
* Added imaginary as an optional container

* chore(deps): update alexta69/metube docker tag to v2025 (#1346)

Co-authored-by: bugclerk <bugclerk@ixsystems.com>

* chore(deps): update updates-patch-minor (#1345)

Co-authored-by: bugclerk <bugclerk@ixsystems.com>

* Publish new changes in catalog [skip ci]

* Update catalog changes [skip ci]

* chore(deps): update updates-patch-minor (#1352)

Co-authored-by: bugclerk <bugclerk@ixsystems.com>

* Publish new changes in catalog [skip ci]

* Update catalog changes [skip ci]

* lib-v2: handle validation of ports for both v6 and v4 (#1332)

* better handling of ipv6 and wildcard addresses

* update version

* cleanup tests

* greatly improve readability

* update hashes

* better check

* flake

* regen hashes

* PR comments

* Removed redunant line from description

* dont nuke if users already have setup imaginary manually

* fix metadata

* simplify

* use correct hash

* fix rest of the tests

* Update .gitignore

* fix rendering

* Update app.yaml

---------

Co-authored-by: truenasbot <113129203+truenasbot@users.noreply.github.com>
Co-authored-by: bugclerk <bugclerk@ixsystems.com>
Co-authored-by: sonicaj <waqarsonic1@gmail.com>
Co-authored-by: Stavros Kois <47820033+stavros-k@users.noreply.github.com>
Co-authored-by: Stavros Kois <s.kois@outlook.com>
2025-01-27 19:04:31 +02:00

220 lines
12 KiB
YAML

{% from "macros/nc.jinja.sh" import occ, hosts_update, trusted_domains_update, imaginary_url %}
{% from "macros/nc.jinja.conf" import opcache, php, limit_request_body, nginx_conf %}
{% set tpl = ix_lib.base.render.Render(values) %}
{% set nc_custom_image = namespace(x=[]) %}
{% if values.nextcloud.apt_packages %}
{% do nc_custom_image.x.append("RUN apt update || { echo 'Failed to update apt cache. Exiting...'; exit 1; }") %}
{# Main packages #}
{% for pkg in values.nextcloud.apt_packages %}
{% do nc_custom_image.x.append("RUN apt install -y --no-install-recommends %s || { echo 'Failed to install [%s]. Exiting...'; exit 1; }"|format(pkg, pkg)) %}
{% endfor %}
{# Additional Dependencies #}
{% for pkg in values.nextcloud.apt_packages if values.consts.packages[pkg] %}
{% for dep in values.consts.packages[pkg].additional_apt %}
{% do nc_custom_image.x.append("RUN apt install -y --no-install-recommends %s || { echo 'Failed to install [%s]. Exiting...'; exit 1; }"|format(dep, dep)) %}
{% endfor %}
{% for dep in values.consts.packages[pkg].pecl %}
{% do nc_custom_image.x.append("RUN pecl install %s || { echo 'Failed to install [%s]. Exiting...'; exit 1; }"|format(dep, dep)) %}
{% endfor %}
{% for dep in values.consts.packages[pkg].docker_php_ext %}
{% do nc_custom_image.x.append("RUN docker-php-ext-enable %s || { echo 'Failed to install [%s]. Exiting...'; exit 1; }"|format(dep, dep)) %}
{% endfor %}
{% for dep in values.consts.packages[pkg].ldd %}
{% do nc_custom_image.x.append("RUN ldd \"$(php -r 'echo ini_get(\"extension_dir\");')\"/%s || { echo 'Failed to install [%s]. Exiting...'; exit 1; }"|format(dep, dep)) %}
{% endfor %}
{# Tesseract OCR #}
{% for lang in values.nextcloud.tesseract_languages if "ocrmypdf" in values.nextcloud.apt_packages %}
{% set lang_pack = "tesseract-ocr-%s" | format(lang|replace("_", "-")) %}
{% do nc_custom_image.x.append("RUN apt install -y --no-install-recommends %s || { echo 'Failed to install [%s]. Exiting...'; exit 1; }"|format(lang_pack, lang_pack)) %}
{% endfor %}
{% endfor %}
{% endif %}
{% set perm_container = tpl.deps.perms(values.consts.perms_container_name) %}
{% set nc_container = tpl.add_container(values.consts.nextcloud_container_name, "image") %}
{% set pg_config = {
"user": values.nextcloud.db_user,
"password": values.nextcloud.db_password,
"database": values.consts.db_name,
"volume": values.storage.postgres_data,
} %}
{% set postgres = tpl.deps.postgres(
values.consts.postgres_container_name,
values.nextcloud.postgres_image_selector,
pg_config, perm_container
) %}
{% do tpl.funcs.disallow_chars(values.nextcloud.redis_password, ["&", "@", "#", "%"], "redis_password") %}
{% set redis_config = {
"password": values.nextcloud.redis_password,
"volume": {"type": "temporary", "volume_config": {"volume_name": "redis-data"}},
} %}
{% set redis = tpl.deps.redis(values.consts.redis_container_name, "redis_image", redis_config, perm_container) %}
{% set nc_caps = ["CHOWN", "FOWNER", "DAC_OVERRIDE", "SETGID", "SETUID", "NET_BIND_SERVICE", "NET_RAW"] %}
{# https://github.com/nextcloud/docker/issues/1796 #}
{% set nc_confs = [
("occ", occ(values), "/usr/local/bin/occ", "0755"),
("opcache.ini", opcache(values), "/usr/local/etc/php/conf.d/opcache-z-99.ini", ""),
("php.ini", php(values), "/usr/local/etc/php/conf.d/nextcloud-z-99.ini", ""),
("limitrequestbody.conf", limit_request_body(values), "/etc/apache2/conf-enabled/limitrequestbody.conf", ""),
] %}
{% set nc_storage = namespace(x=[
("/tmp", {"type": "anonymous", "volume_config": {}}),
]) %}
{% if values.storage.is_data_in_the_same_volume %}
{% do tpl.notes.add_warning(values.consts.deprecation_warning) %}
{% set data_host_path = tpl.funcs.get_host_path(values.storage.data) %}
{% set data_create_host_path = values.storage.data.get("host_path_config", {}).get("create_host_path", False) %}
{% set html_host_path = tpl.funcs.get_host_path(values.storage.html) %}
{% set html_create_host_path = values.storage.html.get("host_path_config", {}).get("create_host_path", False) %}
{% do nc_storage.x.append((values.nextcloud.data_dir_path, dict(values.storage.data, **{"type": "host_path", "host_path_config": {"path": "%s/data"|format(data_host_path), "create_host_path": data_create_host_path, "allow_unsafe_ix_volume": true}} ))) %}
{% do nc_storage.x.append(("/var/www/html", dict(values.storage.html, **{"type": "host_path", "host_path_config": {"path": "%s/html"|format(html_host_path), "create_host_path": html_create_host_path, "allow_unsafe_ix_volume": true}} ))) %}
{% do nc_storage.x.append(("/var/www/html/config", dict(values.storage.html, **{"type": "host_path", "host_path_config": {"path": "%s/config"|format(html_host_path), "create_host_path": html_create_host_path, "allow_unsafe_ix_volume": true}} ))) %}
{% do nc_storage.x.append(("/var/www/html/custom_apps", dict(values.storage.html, **{"type": "host_path", "host_path_config": {"path": "%s/custom_apps"|format(html_host_path), "create_host_path": html_create_host_path, "allow_unsafe_ix_volume": true}} ))) %}
{% do nc_storage.x.append(("/var/www/html/themes", dict(values.storage.html, **{"type": "host_path", "host_path_config": {"path": "%s/themes"|format(html_host_path), "create_host_path": html_create_host_path, "allow_unsafe_ix_volume": true}} ))) %}
{% else %}
{% do nc_storage.x.append(("/var/www/html", values.storage.html)) %}
{% do nc_storage.x.append((values.nextcloud.data_dir_path, values.storage.data)) %}
{% endif %}
{% for store in values.storage.additional_storage %}
{% do nc_storage.x.append((store.mount_path, store)) %}
{% endfor %}
{% set nc_env = namespace(x=[
("NEXTCLOUD_DATA_DIR", values.nextcloud.data_dir_path),
("PHP_UPLOAD_LIMIT", "%dG"|format(values.nextcloud.php_upload_limit)),
("PHP_MEMORY_LIMIT", "%dM"|format(values.nextcloud.php_memory_limit)),
("NEXTCLOUD_ADMIN_USER", values.nextcloud.admin_user),
("NEXTCLOUD_ADMIN_PASSWORD", values.nextcloud.admin_password),
("REDIS_HOST_PORT", 6379),
("REDIS_HOST", values.consts.redis_container_name),
("REDIS_HOST_PASSWORD", values.nextcloud.redis_password),
("POSTGRES_PASSWORD", values.nextcloud.db_password),
("POSTGRES_HOST", postgres.get_url("host_port")),
("POSTGRES_DB", values.consts.db_name),
("POSTGRES_USER", values.nextcloud.db_user),
]) %}
{% set trusted_domains = namespace(x=["127.0.0.1", "localhost", values.consts.nextcloud_container_name]) %}
{% set host = namespace(x="") %}
{% if values.nextcloud.host %}
{% set host.x = values.nextcloud.host if ":" in values.nextcloud.host else "%s:%d"|format(values.nextcloud.host, values.network.web_port) %}
{% set host.x = host.x.replace("https://", "") %}
{% set host.x = host.x.replace("http://", "") %}
{% endif %}
{% if values.network.certificate_id %}
{% do nc_env.x.append(("APACHE_DISABLE_REWRITE_IP", 1)) %}
{% do nc_env.x.append(("OVERWRITEPROTOCOL", "https")) %}
{% do nc_env.x.append(("TRUSTED_PROXIES", ["127.0.0.1", "192.168.0.0/16", "172.16.0.0/12", "10.0.0.0/8"] | join(" "))) %}
{% if values.nextcloud.host and values.network.nginx.use_different_port %}
{% set host.x = "%s:%d"|format(values.nextcloud.host, values.network.nginx.external_port) %}
{% do nc_env.x.append(("OVERWRITEHOST", host.x)) %}
{% endif %}
{% endif %}
{% if host.x %}
{% set clean_host = host.x.split(":")[0] if ":" in host.x else host.x %}
{% do trusted_domains.x.append(clean_host) %}
{% endif %}
{% do nc_env.x.append(("NEXTCLOUD_TRUSTED_DOMAINS", trusted_domains.x|unique|list|join(" "))) %}
{% do nc_container.build_image(nc_custom_image.x) %}
{% do nc_container.set_user(0,0) %}
{% do nc_container.add_caps(nc_caps) %}
{% do nc_container.healthcheck.set_test("curl", {"port": 80, "path": "/status.php", "headers": [("Host", "localhost")]}) %}
{% do nc_container.depends.add_dependency(values.consts.postgres_container_name, "service_healthy") %}
{% do nc_container.depends.add_dependency(values.consts.redis_container_name, "service_healthy") %}
{% do nc_container.configs.add("ix-update-hosts-script.sh", hosts_update(values), "/docker-entrypoint-hooks.d/before-starting/ix-update-hosts-script.sh", "0755") %}
{% do nc_container.configs.add("ix-update-trusted-domains-script.sh", trusted_domains_update(), "/docker-entrypoint-hooks.d/before-starting/ix-update-trusted-domains-script.sh", "0755") %}
{% for c in nc_confs %}
{% do nc_container.configs.add(c[0], c[1], c[2], c[3]) %}
{% endfor %}
{% for e in nc_env.x %}
{% do nc_container.environment.add_env(e[0], e[1]) %}
{% endfor %}
{% for s in nc_storage.x %}
{% do nc_container.add_storage(s[0], s[1]) %}
{% endfor %}
{% if not values.network.certificate_id %}
{% do nc_container.ports.add_port(values.network.web_port, 80) %}
{% endif %}
{% if values.nextcloud.imaginary.enabled %}
{% do nc_container.configs.add(
"ix-imaginary-url.sh",
imaginary_url(values.consts.imaginary_container_name, values.consts.imaginary_port),
"/docker-entrypoint-hooks.d/before-starting/ix-imaginary-url.sh", "0755",
) %}
{% endif %}
{% do nc_container.environment.add_user_envs(values.nextcloud.additional_envs) %}
{% if values.nextcloud.cron.enabled %}
{% set cron_container = tpl.add_container(values.consts.cron_container_name, "image") %}
{% do cron_container.build_image(nc_custom_image.x) %}
{% do cron_container.set_user(0,0) %}
{% do cron_container.add_caps(nc_caps) %}
{% do cron_container.healthcheck.set_custom_test("pidof busybox > /dev/null") %}
{% do cron_container.set_entrypoint(["/bin/sh", "-c"]) %}
{% set cmd = [
"echo '%s php -f /var/www/html/cron.php' > /var/spool/cron/crontabs/www-data || { echo 'Failed to create crontab'; exit 1; }"|format(values.nextcloud.cron.schedule),
"/cron.sh || { echo 'Failed to run cron'; exit 1; }"
]|join("\n") %}
{% do cron_container.set_command([cmd]) %}
{% do cron_container.depends.add_dependency(values.consts.nextcloud_container_name, "service_healthy") %}
{% for c in nc_confs %}
{% do cron_container.configs.add(c[0], c[1], c[2], c[3]) %}
{% endfor %}
{% for e in nc_env.x %}
{% do cron_container.environment.add_env(e[0], e[1]) %}
{% endfor %}
{% for s in nc_storage.x %}
{% do cron_container.add_storage(s[0], s[1]) %}
{% endfor %}
{% do cron_container.environment.add_user_envs(values.nextcloud.additional_envs) %}
{% endif %}
{% if values.nextcloud.imaginary.enabled %}
{% set imaginary_container = tpl.add_container(values.consts.imaginary_container_name, "imaginary_image") %}
{% do imaginary_container.add_caps(["SYS_NICE"]) %}
{% do imaginary_container.set_user(568, 568) %}
{% do imaginary_container.depends.add_dependency(values.consts.nextcloud_container_name, "service_healthy") %}
{% do imaginary_container.healthcheck.set_test("wget", {"port": 9000, "path": "/health"}) %}
{% endif %}
{% if values.network.certificate_id %}
{% set nginx_container = tpl.add_container(values.consts.nginx_container_name, "nginx_image") %}
{% do nginx_container.deploy.resources.remove_devices() %}
{% do nginx_container.add_caps(["NET_BIND_SERVICE", "CHOWN", "FOWNER", "DAC_OVERRIDE", "SETGID", "SETUID", "NET_RAW"]) %}
{% do nginx_container.depends.add_dependency(values.consts.nextcloud_container_name, "service_healthy") %}
{% do nginx_container.configs.add("private", values.ix_certificates[values.network.certificate_id].privatekey, values.consts.ssl_key_path) %}
{% do nginx_container.configs.add("public", values.ix_certificates[values.network.certificate_id].certificate, values.consts.ssl_cert_path) %}
{% do nginx_container.configs.add("nginx.conf", nginx_conf(values), "/etc/nginx/nginx.conf", "0600") %}
{% do nginx_container.add_storage("/tmp", {"type": "anonymous", "volume_config": {}}) %}
{% do nginx_container.healthcheck.set_test("curl", {
"port": values.network.web_port, "path": "/status.php",
"headers": [("Host", "localhost")], "scheme": "https"
}) %}
{% do nginx_container.ports.add_port(values.network.web_port, values.network.web_port) %}
{% endif %}
{% if perm_container.has_actions() %}
{% do perm_container.activate() %}
{% do nc_container.depends.add_dependency(values.consts.perms_container_name, "service_completed_successfully") %}
{% do redis.container.depends.add_dependency(values.consts.perms_container_name, "service_completed_successfully") %}
{% do postgres.container.depends.add_dependency(values.consts.perms_container_name, "service_completed_successfully") %}
{% endif %}
{% do tpl.portals.add_portal({"port": values.network.web_port, "scheme": "https" if values.network.certificate_id else "http"}) %}
{{ tpl.render() | tojson }}