Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions ix-dev/stable/nextcloud/app.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@ annotations:
min_scale_version: 24.10.2.2
app_version: 33.0.2
capabilities:
- description: Cron, Nextcloud, Nginx are able to change file ownership arbitrarily
- description: Cron, Harp, Nextcloud, Nginx are able to change file ownership arbitrarily
name: CHOWN
- description: Cron, Nextcloud, Nginx are able to bypass file permission checks
- description: Cron, Harp, Nextcloud, Nginx are able to bypass file permission checks
name: DAC_OVERRIDE
- description: Cron, Nextcloud, Nginx are able to bypass permission checks for file
operations
- description: Cron, Harp, Nextcloud, Nginx are able to bypass permission checks for
file operations
name: FOWNER
- description: Cron, Nextcloud, Nginx are able to bind to privileged ports (< 1024)
- description: Harp is able to send signals to any process
name: KILL
- description: Cron, Harp, Nextcloud, Nginx are able to bind to privileged ports (<
1024)
name: NET_BIND_SERVICE
- description: Cron, Nextcloud, Nginx are able to use raw and packet sockets
name: NET_RAW
- description: Cron, Nextcloud, Nginx are able to change group ID of processes
- description: Cron, Harp, Nextcloud, Nginx are able to change group ID of processes
name: SETGID
- description: Cron, Nextcloud, Nginx are able to change user ID of processes
- description: Cron, Harp, Nextcloud, Nginx are able to change user ID of processes
name: SETUID
- description: Imaginary is able to modify process scheduling priority
name: SYS_NICE
Expand Down Expand Up @@ -48,6 +51,11 @@ run_as_context:
group_name: Host group is [root]
uid: 0
user_name: Host user is [root]
- description: Container [harp] runs as root user and group.
gid: 0
group_name: Host group is [root]
uid: 0
user_name: Host user is [root]
- description: Container [imaginary] can run as any non-root user and group.
gid: 568
group_name: Host group is [apps]
Expand Down Expand Up @@ -81,4 +89,4 @@ sources:
- https://github.com/nextcloud/docker
title: Nextcloud
train: stable
version: 2.3.16
version: 2.4.0
5 changes: 5 additions & 0 deletions ix-dev/stable/nextcloud/ix_values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ images:
postgres_upgrade_image:
repository: ixsystems/postgres-upgrade
tag: 1.2.4
harp_image:
repository: ghcr.io/nextcloud/nextcloud-appapi-harp
tag: v0.3.2

consts:
nextcloud_container_name: nextcloud
Expand All @@ -33,6 +36,8 @@ consts:
nginx_container_name: nginx
imaginary_container_name: imaginary
imaginary_port: 9000
harp_container_name: harp
harp_port: 8780
db_name: nextcloud
ssl_key_path: /etc/nginx-certs/private.key
ssl_cert_path: /etc/nginx-certs/public.crt
Expand Down
61 changes: 61 additions & 0 deletions ix-dev/stable/nextcloud/questions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,63 @@ questions:
schema:
type: boolean
default: false
- variable: harp
label: HaRP (AppAPI)
description: |
HaRP (HAProxy Reverse Proxy) enables Nextcloud AppAPI for External Apps (ExApps).</br>
Requires Docker socket access (/var/run/docker.sock).</br>
See https://github.com/nextcloud/HaRP for more information.</br>
schema:
type: dict
attrs:
- variable: enabled
label: Enabled
description: Enable HaRP for Nextcloud AppAPI
schema:
type: boolean
default: false
- variable: shared_key
label: Shared Key
description: |
Secret key shared between HaRP and Nextcloud AppAPI.</br>
Set the same value in Nextcloud Admin > AppAPI > Deploy Daemons.</br>
schema:
type: string
private: true
required: true
show_if: [["enabled", "=", true]]
- variable: port
label: HaRP Port
description: The port HaRP exposes for ExApps.
schema:
type: dict
show_if: [["enabled", "=", true]]
attrs:
- variable: bind_mode
label: Port Bind Mode
description: |
The port bind mode.</br>
- Publish: The port will be published on the host for external access.</br>
- Expose: The port will be exposed for inter-container communication.</br>
- None: The port will not be exposed or published.
schema:
type: string
default: "published"
enum:
- value: "published"
description: Publish port on the host for external access
- value: "exposed"
description: Expose port for inter-container communication
- value: ""
description: None
- variable: port_number
label: Port Number
schema:
type: int
default: 8780
min: 1
max: 65535
required: true
- variable: host
label: Host
description: |
Expand Down Expand Up @@ -429,6 +486,8 @@ questions:
description: postgres
- value: redis
description: redis
- value: harp
description: harp
- variable: config
label: Container Network Configuration
schema:
Expand Down Expand Up @@ -927,6 +986,8 @@ questions:
description: postgres
- value: redis
description: redis
- value: harp
description: harp

- variable: resources
label: ""
Expand Down
32 changes: 31 additions & 1 deletion ix-dev/stable/nextcloud/templates/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% from "macros/nc.jinja.sh" import occ, hosts_update, trusted_domains_update, imaginary_url %}
{% from "macros/nc.jinja.sh" import occ, hosts_update, trusted_domains_update, imaginary_url, harp_daemon_register %}
{% from "macros/nc.jinja.conf" import opcache, php, limit_request_body, use_x_real_ip_in_logs, nginx_conf %}

{% set tpl = ix_lib.base.render.Render(values) %}
Expand Down Expand Up @@ -162,6 +162,17 @@
"/docker-entrypoint-hooks.d/before-starting/ix-imaginary-url.sh", "0755",
) %}
{% endif %}
{% if values.nextcloud.harp.enabled %}
{% set nc_scheme = "https" if values.network.certificate_id else "http" %}
{% set nc_url = "%s://%s"|format(nc_scheme, host.x) if host.x else "%s://localhost:%d"|format(nc_scheme, values.network.web_port.port_number) %}
{% set app_name = values.get("ix_context", {}).get("app_name", "") or "nextcloud" %}
{% set docker_network = "%s_%s"|format(app_name, nc_net) %}
{% do nc_container.configs.add(
"ix-harp-daemon.sh",
harp_daemon_register(values, nc_url, docker_network),
"/docker-entrypoint-hooks.d/before-starting/ix-harp-daemon.sh", "0755",
) %}
{% endif %}

{% do nc_container.environment.add_user_envs(values.nextcloud.additional_envs) %}

Expand Down Expand Up @@ -199,6 +210,25 @@
{% do imaginary_container.healthcheck.set_test("wget", {"port": 9000, "path": "/health"}) %}
{% endif %}

{% if values.nextcloud.harp.enabled %}
{% do tpl.notes.add_warning("HaRP requires access to /var/run/docker.sock, which gives it full control over the Docker daemon. Enable only if you trust the implications.") %}
{% set nc_scheme = "https" if values.network.certificate_id else "http" %}
{% set nc_url = "%s://%s"|format(nc_scheme, host.x) if host.x else "%s://localhost:%d"|format(nc_scheme, values.network.web_port.port_number) %}

{% set harp_container = tpl.add_container(values.consts.harp_container_name, "harp_image") %}
{% do harp_container.add_network(nc_net) %}
{% do harp_container.set_user(0, 0) %}
{% do harp_container.add_caps(["CHOWN", "DAC_OVERRIDE", "FOWNER", "KILL", "SETGID", "SETUID", "NET_BIND_SERVICE"]) %}
{% do harp_container.healthcheck.disable() %}
{% do harp_container.add_docker_socket(read_only=true) %}
{% do harp_container.environment.add_env("HP_SHARED_KEY", values.nextcloud.harp.shared_key) %}
{% do harp_container.environment.add_env("NC_INSTANCE_URL", nc_url) %}
{% do harp_container.add_port(values.nextcloud.harp.port) %}
{% if not values.network.certificate_id %}
{% do tpl.notes.add_info("HaRP is enabled but nginx is not. You must configure your external reverse proxy to route /exapps/* to HaRP on port %d."|format(values.nextcloud.harp.port.port_number)) %}
{% endif %}
{% endif %}

{% if values.network.certificate_id %}
{% set nginx_container = tpl.add_container(values.consts.nginx_container_name, "nginx_image") %}
{% do nginx_container.add_network(nc_net) %}
Expand Down
24 changes: 24 additions & 0 deletions ix-dev/stable/nextcloud/templates/macros/nc.jinja.conf
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,30 @@ http {
return 301 /index.php$request_uri;
}

{%- if values.nextcloud.harp.enabled %}
location /exapps/ {
proxy_pass http://{{ values.consts.harp_container_name }}:{{ values.consts.harp_port }}/;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_request_buffering off;

# Proxy headers
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port {{ port.x | default("443", true) | replace(":", "") }};

# Proxy timeouts
proxy_connect_timeout {{ values.network.nginx.proxy_timeout }}s;
proxy_send_timeout {{ values.network.nginx.proxy_timeout }}s;
proxy_read_timeout {{ values.network.nginx.proxy_timeout }}s;
}
{%- endif %}

location / {
proxy_pass http://{{ values.consts.nextcloud_container_name }}:80;
proxy_http_version 1.1;
Expand Down
26 changes: 26 additions & 0 deletions ix-dev/stable/nextcloud/templates/macros/nc.jinja.sh
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,29 @@ set_list "trusted_domains" "${NEXTCLOUD_TRUSTED_DOMAINS}" || { echo "Failed to u
echo '## Configuring Imaginary...'
occ config:system:set preview_imaginary_url --value={{ "http://%s:%d"|format(host, port) }}
{%- endmacro -%}

{% macro harp_daemon_register(values, nc_url, docker_network) -%}
#!/bin/bash
echo '## Configuring HaRP (AppAPI)...'

echo 'Installing and enabling app_api...'
occ app:install app_api 2>/dev/null || true
occ app:enable app_api 2>/dev/null || true

echo 'Registering HaRP deploy daemon...'
occ app_api:daemon:register \
harp \
"HaRP (TrueNAS)" \
"docker-install" \
"http" \
"{{ values.consts.harp_container_name }}:{{ values.consts.harp_port }}" \
"{{ nc_url }}" \
--net "{{ docker_network }}" \
--harp \
--harp_frp_address "{{ values.consts.harp_container_name }}:8782" \
--harp_shared_key "{{ values.nextcloud.harp.shared_key }}" \
--set-default \
|| echo 'Daemon already registered or registration failed. You can register manually via Nextcloud Admin > AppAPI.'

echo 'HaRP daemon registration complete.'
{%- endmacro -%}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ nextcloud:
max_execution_time: 30
imaginary:
enabled: false
harp:
enabled: false
cron:
enabled: true
schedule: "*/5 * * * *"
Expand Down
Loading
Loading