Nextcloud
Contents
Nextcloud#
All configurations presented here use docker-compose. Read the Docker instructions first.
At the moment of writing the production Nextcloud version is 24.
Nextcloud on Docker setups#
Some variables are obvious while others needs an explanation
Variable name |
Description |
---|---|
|
directory containing user files, Nextcloud logs and application data |
|
Elasticsearch data directory |
|
Elasticsearch plugins directory |
|
domain name |
|
directory containing Nextcloud’s HTML code and configurations. You can mount this directory on a SSD |
|
a username of the Nextcloud instance |
|
a password corresponding to |
MariaDB hosted on a Docker container#
See also
follow the Docker instructions
create the jobs directories. See reference
mkdir -p /home/jobs/scripts/by-user/root/docker/nextcloud cd /home/jobs/scripts/by-user/root/docker/nextcloud
create a
Docker compose file
/home/jobs/scripts/by-user/root/docker/nextcloud/docker-compose.yml#version: '2' volumes: nextcloud: db: redis: services: # See # https://help.nextcloud.com/t/mariadb-upgrade-from-10-5-11-to-10-6-causes-internal-server-error/120585 db: hostname: db image: mariadb:10.5.11 restart: always command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW volumes: - ./db:/var/lib/mysql environment: - MYSQL_ROOT_PASSWORD=${DATABASE_ROOT_PASSWORD} - MYSQL_PASSWORD=${DATABASE_PASSWORD} - MYSQL_DATABASE=nextcloud - MYSQL_USER=nextcloud app: image: nextcloud:production restart: always ports: - 4005:80 links: - db - redis volumes: - ${DATA_PATH}:/var/www/html/data - ${HTML_DATA_PATH}:/var/www/html environment: - REDIS_HOST=redis - REDIS_HOST_PORT=6379 - MYSQL_PASSWORD=${DATABASE_PASSWORD} - MYSQL_DATABASE=nextcloud - MYSQL_USER=nextcloud - MYSQL_HOST=db - APACHE_DISABLE_REWRITE_IP=1 - TRUSTED_PROXIES=127.0.0.1 - OVERWRITEHOST=${FQDN} - OVERWRITEPROTOCOL=https - OVERWRITECLIURL=https://${FQDN} redis: image: redis:6.2.5 restart: always
Note
Replace
DATABASE_ROOT_PASSWORD
,DATABASE_PASSWORD
,DATA_PATH
,HTML_DATA_PATH
andFQDN
with appropriate values.create a
Systemd unit file
. See also the Docker compose services section/home/jobs/services/by-user/root/docker-compose.nextcloud.service#[Unit] Requires=docker.service Requires=network-online.target After=docker.service After=network-online.target # Enable these for the "scalable" variant. # Requires=redis.service # Requires=redis-socket.service # After=redis.service # After=redis-socket.service [Service] Type=simple WorkingDirectory=/home/jobs/scripts/by-user/root/docker/nextcloud ExecStart=/usr/bin/docker-compose up --remove-orphans ExecStop=/usr/bin/docker-compose down --remove-orphans Restart=always [Install] WantedBy=multi-user.target
fix the permissions
chmod 700 /home/jobs/scripts/by-user/root/docker/nextcloud chmod 700 -R /home/jobs/services/by-user/root
run the deploy script
modify the reverse proxy port of your webserver configuration with
4005
Migration from MariaDB on a container container to PostgreSQL in host#
check that your PostgreSQL setup is fully configured and running
add an entry in the
pg_hba.conf
file/etc/postgresql/13/main/pg_hba.conf#host nextclouddb nextcloud 172.16.0.0/16 scram-sha-256
change this setting in
postgresql.conf
/etc/postgresql/13/main/postgresql.conf#listen_addresses = '*'
restart Postgres
systemctl restart postgresql.service
stop the Nextcloud container
systemctl stop docker-compose.nextcloud.service
convert the database type. You will be prompted for the database password
docker-compose exec --user www-data app php occ db:convert-type --all-apps pgsql ${DATABASE_USER} ${DATABASE_HOST} ${DATABASE_NAME}
The Docker container must now comunicate with the PostgreSQL instance running on bare metal. The variables used here refer to the PostgreSQL instance.
use this
Docker compose file
instead. See also the Docker compose services section/home/jobs/scripts/by-user/root/docker/nextcloud/docker-compose.yml## PostgreSQL in host. version: '2' volumes: nextcloud: redis: services: app: image: nextcloud:production restart: always ports: - 4005:80 links: - redis volumes: - ${DATA_PATH}:/var/www/html/data - ${HTML_DATA_PATH}:/var/www/html environment: - REDIS_HOST=redis - REDIS_HOST_PORT=6379 - POSTGRES_DB=${DATABASE_NAME} - POSTGRES_USER=${DATABASE_USER} - POSTGRES_HOST=${DATABASE_HOST} - POSTGRES_PASSWORD=${DATABASE_PASSWORD} - APACHE_DISABLE_REWRITE_IP=1 - TRUSTED_PROXIES=127.0.0.1 - OVERWRITEHOST=${FQDN} - OVERWRITEPROTOCOL=https - OVERWRITECLIURL=https://${FQDN} redis: image: redis:6.2.5 restart: always hostname: redis volumes: - redis:/var/lib/redis
Note
Replace
DATABASE_NAME
,DATABASE_USER
,DATABASE_PASSWORD
,DATABASE_HOST
,DATA_PATH
,HTML_DATA_PATH
andFQDN
with appropriate values.DATABASE_HOST
may be different fromFQDN
if PostgreSQL is not reachable through Internet or is running on a different machine.run the deploy script
A more scalable setup#
To have a more serious setup you must separate some of the components. In this example Nextcloud’s FPM image, the NGINX webserver and ClamAV (optional) will be run in Docker. Redis will accessed by Docker containers from the host machine.
See also
Access host socket from container - socat - IT Playground Blog 6
follow the Docker instructions
create the jobs directories. See reference
mkdir -p /home/jobs/scripts/by-user/root/docker/nextcloud cd /home/jobs/scripts/by-user/root/docker/nextcloud
create a
Docker compose file
/home/jobs/scripts/by-user/root/docker/nextcloud/docker-compose.yml#version: '2' volumes: app: web: services: web: image: nginx:1.23.1 restart: always ports: - 127.0.0.1:4005:80 links: - app volumes: - ./nginx.conf:/etc/nginx/nginx.conf volumes_from: - app networks: - mynetwork app: image: nextcloud:24.0.5-fpm restart: always links: - clamav volumes: - ${DATA_PATH}:/var/www/html/data - ${HTML_DATA_PATH}:/var/www/html - ${PHP_CONFIG_DATA_PATH}:/usr/local/etc/php/conf.d - /var/run/redis.sock:/var/run/redis.sock environment: - TZ=Europe/Rome - REDIS_HOST=/var/run/redis.sock - REDIS_HOST_PORT=0 - POSTGRES_DB=${DATABASE_NAME} - POSTGRES_USER=${DATABASE_USER} - POSTGRES_HOST=${DATABASE_HOST} - POSTGRES_PASSWORD=${DATABASE_PASSWORD} - APACHE_DISABLE_REWRITE_IP=1 - TRUSTED_PROXIES=127.0.0.1 - OVERWRITEHOST=${FQDN} - OVERWRITEPROTOCOL=https - OVERWRITECLIURL=https://${FQDN} - PHP_UPLOAD_LIMIT=8G
Note
Replace
DATABASE_ROOT_PASSWORD
,DATABASE_PASSWORD
,DATA_PATH
,HTML_DATA_PATH
,PHP_CONFIG_DATA_PATH
andFQDN
with appropriate values.create a
Systemd unit file
. See also the Docker compose services section/home/jobs/services/by-user/root/docker-compose.nextcloud.service#[Unit] Requires=docker.service Requires=network-online.target After=docker.service After=network-online.target # Enable these for the "scalable" variant. # Requires=redis.service # Requires=redis-socket.service # After=redis.service # After=redis-socket.service [Service] Type=simple WorkingDirectory=/home/jobs/scripts/by-user/root/docker/nextcloud ExecStart=/usr/bin/docker-compose up --remove-orphans ExecStop=/usr/bin/docker-compose down --remove-orphans Restart=always [Install] WantedBy=multi-user.target
follow the Redis instructions
create a copy of the Redis socket with specific permissions. Use this
Systemd service
. The Redis docket must have the same user id (in this case33
) of the nextcloud files in the Docker image./home/jobs/services/by-user/root/redis-socket.service#[Unit] Requires=network-online.target Requires=redis.service After=network-online.target After=redis.service [Service] Type=simple ExecStart=/usr/bin/socat UNIX-LISTEN:/var/run/redis.sock,user=33,group=33,mode=0660,fork UNIX-CLIENT:/var/run/redis/redis-server.sock Restart=always [Install] WantedBy=multi-user.target
copy the php data from the image to the
PHP_CONFIG_DATA_PATH
. First of all comment thePHP_CONFIG_DATA_PATH
volume from the docker-compose file then rundocker-compose up --remove orphans docker cp $(docker container ls | grep nextcloud:24.0.5-fpm | awk '{print $1}'):/usr/local/etc/php/conf.d "${PHP_CONFIG_DATA_PATH}" docker-compose down
use this
NGINX configuration file
as example./home/jobs/scripts/by-user/root/docker/nextcloud/nginx.conf#worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; # Prevent nginx HTTP Server Detection server_tokens off; keepalive_timeout 65; #gzip on; upstream php-handler { server app:9000; } server { server_name ${FQDN} listen 80; # HSTS settings # WARNING: Only add the preload option once you read about # the consequences in https://hstspreload.org/. This option # will add the domain to a hardcoded list that is shipped # in all major browsers and getting removed from this list # could take several months. add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always; # set max upload size client_max_body_size 512M; fastcgi_buffers 64 4K; # Enable gzip but do not remove ETag headers gzip on; gzip_vary on; gzip_comp_level 4; gzip_min_length 256; gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; # Pagespeed is not supported by Nextcloud, so if your server is built # with the `ngx_pagespeed` module, uncomment this line to disable it. #pagespeed off; # HTTP response headers borrowed from Nextcloud `.htaccess` add_header Referrer-Policy "no-referrer" always; add_header X-Content-Type-Options "nosniff" always; add_header X-Download-Options "noopen" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Permitted-Cross-Domain-Policies "none" always; add_header X-Robots-Tag "none" always; add_header X-XSS-Protection "1; mode=block" always; # Remove X-Powered-By, which is an information leak fastcgi_hide_header X-Powered-By; # Path to the root of your installation root /var/www/html; # Specify how to handle directories -- specifying `/index.php$request_uri` # here as the fallback means that Nginx always exhibits the desired behaviour # when a client requests a path that corresponds to a directory that exists # on the server. In particular, if that directory contains an index.php file, # that file is correctly served; if it doesn't, then the request is passed to # the front-end controller. This consistent behaviour means that we don't need # to specify custom rules for certain paths (e.g. images and other assets, # `/updater`, `/ocm-provider`, `/ocs-provider`), and thus # `try_files $uri $uri/ /index.php$request_uri` # always provides the desired behaviour. index index.php index.html /index.php$request_uri; # Rule borrowed from `.htaccess` to handle Microsoft DAV clients location = / { if ( $http_user_agent ~ ^DavClnt ) { return 302 /remote.php/webdav/$is_args$args; } } location = /robots.txt { allow all; log_not_found off; access_log off; } # Make a regex exception for `/.well-known` so that clients can still # access it despite the existence of the regex rule # `location ~ /(\.|autotest|...)` which would otherwise handle requests # for `/.well-known`. location ^~ /.well-known { # The rules in this block are an adaptation of the rules # in `.htaccess` that concern `/.well-known`. location = /.well-known/carddav { return 301 https://${FQDN}/remote.php/dav/; } location = /.well-known/caldav { return 301 https://${FQDN}/remote.php/dav/; } location = /.well-known/webfinger { return 301 https://${FQDN}/index.php/.well-known/webfinger; } location = /.well-known/nodeinfo { return 301 https://${FQDN}/index.php/.well-known/nodeinfo; } location /.well-known/acme-challenge { try_files $uri $uri/ =404; } location /.well-known/pki-validation { try_files $uri $uri/ =404; } # Let Nextcloud's API for `/.well-known` URIs handle all other # requests by passing them to the front-end controller. return 301 /index.php$request_uri; } # Rules borrowed from `.htaccess` to hide certain paths from clients location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; } location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; } # Ensure this block, which passes PHP files to the PHP process, is above the blocks # which handle static assets (as seen below). If this block is not declared first, # then Nginx will encounter an infinite rewriting loop when it prepends `/index.php` # to the URI, resulting in a HTTP 500 error response. location ~ \.php(?:$|/) { # Required for legacy support rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy) /index.php$request_uri; fastcgi_split_path_info ^(.+?\.php)(/.*)$; set $path_info $fastcgi_path_info; try_files $fastcgi_script_name =404; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $path_info; #fastcgi_param HTTPS on; fastcgi_param modHeadersAvailable true; # Avoid sending the security headers twice fastcgi_param front_controller_active true; # Enable pretty urls fastcgi_pass php-handler; fastcgi_intercept_errors on; fastcgi_request_buffering off; } location ~ \.(?:css|js|svg|gif)$ { try_files $uri /index.php$request_uri; expires 6M; # Cache-Control policy borrowed from `.htaccess` access_log off; # Optional: Don't log access to assets } location ~ \.woff2?$ { try_files $uri /index.php$request_uri; expires 7d; # Cache-Control policy borrowed from `.htaccess` access_log off; # Optional: Don't log access to assets } # Rule borrowed from `.htaccess` location /remote { return 301 /remote.php$request_uri; } location / { try_files $uri $uri/ /index.php$request_uri; } } }
Note
Replace
FQDN
with appropriate value.edit the redis configuration in the PHP config (
${HTML_DATA_PATH}/config/config.php
) like this# [ ... ] 'redis' => array ( 'host' => '/var/run/redis.sock', 'password' => '', ), # [ ... ]
run the deploy script
modify the reverse proxy port of your webserver configuration with
4005
connect to your Nextcloud instance as admin and configure the antivirus app from the settings. Go to Settings -> Security -> Antivirus for Files
Mode:
ClamAV Daemon
Host:
clamav
Port:
3310
When infected files are found during a background scan:
Delete file
Apache configuration#
serve the files via HTTP by creating a new
Apache virtual host
. ReplaceFQDN
with the appropriate domain and include this file from the Apache configuration/etc/apache2/nextcloud.apache.conf############### # Nextcloud # ############## <IfModule mod_ssl.c> <VirtualHost *:80> ServerName ${FQDN} # Force https. UseCanonicalName on RewriteEngine on RewriteCond %{SERVER_NAME} =${FQDN} # Ignore rewrite rules for 127.0.0.1 RewriteCond %{HTTP_HOST} !=127.0.0.1 RewriteCond %{REMOTE_ADDR} !=127.0.0.1 RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent] </VirtualHost> </IfModule> <IfModule mod_ssl.c> <VirtualHost *:443> UseCanonicalName on Keepalive On ServerName ${FQDN} SSLCompression off # HSTS <IfModule mod_headers.c> Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains" </IfModule> RequestHeader set X-Forwarded-Proto "https" RequestHeader set X-Forwarded-For "app" RequestHeader set X-Forwarded-Port "443" RequestHeader set X-Forwarded-Host "${FQDN}" ProxyPass / http://127.0.0.1:4005/ ProxyPassReverse / http://127.0.0.1:4005/ Include /etc/letsencrypt/options-ssl-apache.conf SSLCertificateFile /etc/letsencrypt/live/${FQDN}/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/${FQDN}/privkey.pem </VirtualHost> </IfModule>
Apps#
Tips and configurations for some Nextcloud apps
Collabora (cloud office suite)#
To make Collabora interact with Nextcloud without errors you need to deploy a new virtual server in Apache. Collabora must work with the same security protocol as the Nextcloud instance. In all these examples you see that Nextcloud is deployed in SSL mode so Collabora must be in SSL mode as well.
See also
Installation example with Docker — Nextcloud latest Administration Manual latest documentation 15
Nextcloud & Collabora docker installation. Error: Collabora Online should use the same protocol as the server installation - 🚧 Installation - Nextcloud community 16
Socket Error when accessing Collabora - ℹ️ Support / 📄 Collabora - Nextcloud community 17
Can’t connect to OnlyOffice document server after update to NC19 - ℹ️ Support - Nextcloud community 30
follow the Docker instructions
create the jobs directories. See reference
mkdir -p /home/jobs/scripts/by-user/root/docker/collabora cd /home/jobs/scripts/by-user/root/docker/collabora
create a
Docker compose file
/home/jobs/scripts/by-user/root/docker/collabora/docker-compose.yml#version: '2.4' services: collabora: image: collabora/code:latest-amd64 restart: always ports: - 127.0.0.1:9980:9980 environment: - password=${PASSWORD} - username=${USERNAME} - domain=${NEXTCLOUD_FQDN} - server_name=${COLLABORA_FQDN} - dictionaries=de en es it - extra_params=--o:ssl.enable=true --o:ssl.termination=true cap_add: - MKNOD
Note
Replace
PASSWORD
,USERNAME
,NEXTCLOUD_FQDN
andCOLLABORA_FQDN
with appropriate values.create a
Systemd unit file
. See also the Docker compose services section/home/jobs/services/by-user/root/docker-compose.collabora.service#[Unit] Requires=docker.service Requires=network-online.target After=docker.service After=network-online.target ## Run ## docker-compose up --detach --force-recreate ## to reload configuration. [Service] # https://community.hetzner.com/tutorials/docker-compose-as-systemd-service Type=simple WorkingDirectory=/home/jobs/scripts/by-user/root/docker/collabora ExecStart=/usr/bin/docker-compose up --remove-orphans ExecStop=/usr/bin/docker-compose down --remove-orphans Restart=always [Install] WantedBy=multi-user.target
fix the permissions
chmod 700 /home/jobs/scripts/by-user/root/docker/collabora chmod 700 -R /home/jobs/services/by-user/root
serve Collabora via HTTPS by creating a new
Apache virtual host
. ReplaceCOLLABORA_FQDN
with the appropriate domain and include this file from the Apache configuration/etc/apache2/collabora.apache.conf############## # Collabora # ############# <IfModule mod_ssl.c> <VirtualHost *:80> ServerName ${COLLABORA_FQDN} # Force https. UseCanonicalName on RewriteEngine on RewriteCond %{SERVER_NAME} =${COLLABORA_FQDN} # Ignore rewrite rules for 127.0.0.1 RewriteCond %{HTTP_HOST} !=127.0.0.1 RewriteCond %{REMOTE_ADDR} !=127.0.0.1 RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent] </VirtualHost> </IfModule> <IfModule mod_ssl.c> <VirtualHost *:443> ServerName ${COLLABORA_FQDN} SSLEngine on AllowEncodedSlashes NoDecode # Container uses a unique non-signed certificate SSLProxyEngine On SSLProxyVerify None SSLProxyCheckPeerCN Off SSLProxyCheckPeerName Off ProxyPreserveHost On # static html, js, images, etc. served from coolwsd # browser is the client part of LibreOffice Online ProxyPass /browser https://127.0.0.1:9980/browser retry=0 ProxyPassReverse /browser https://127.0.0.1:9980/browser # WOPI discovery URL ProxyPass /hosting/discovery https://127.0.0.1:9980/hosting/discovery retry=0 ProxyPassReverse /hosting/discovery https://127.0.0.1:9980/hosting/discovery # Main websocket ProxyPassMatch "/cool/(.*)/ws$" wss://127.0.0.1:9980/cool/$1/ws nocanon # Admin Console websocket ProxyPass /cool/adminws wss://127.0.0.1:9980/cool/adminws # Download as, Fullscreen presentation and Image upload operations ProxyPass /cool https://127.0.0.1:9980/cool ProxyPassReverse /cool https://127.0.0.1:9980/cool # Compatibility with integrations that use the /lool/convert-to endpoint ProxyPass /lool https://127.0.0.1:9980/cool ProxyPassReverse /lool https://127.0.0.1:9980/cool # Capabilities ProxyPass /hosting/capabilities https://127.0.0.1:9980/hosting/capabilities retry=0 ProxyPassReverse /hosting/capabilities https://127.0.0.1:9980/hosting/capabilities # IMPORTANT: If you use Collabora and Nextcloud outside of your LAN # the following restrictions need to be changed or removed! # Your browser must infact be able to connect to Collabora directly. <Proxy *> # Localhost. Require ip 127.0.0.1 Require ip 192.168.0. # Docker containers. Require ip 172.16. </Proxy> Include /etc/letsencrypt/options-ssl-apache.conf SSLCertificateFile /etc/letsencrypt/live/collabora.franco.net.eu.org/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/collabora.franco.net.eu.org/privkey.pem </VirtualHost> </IfModule>
run the deploy script
restart Apache
systemctl restart apache2
install the Nexcloud Office app from the store. Go to the add apps admin menu, then to the
Search
sectionconfigure the search from the Nextcloud admin settings. Go to the
Office
tab and use these settingsUse your own server
URL (and Port) of Collabora Online-server
:${COLLABORA_FQDN}
click on
Save
create a new office document or open an existing one to check if everything is working
Nextcloud calendar to PDF#
Export a Nextcloud calendar to a PDF file. This is not an app you install from the Nextcloud store but an external script which interacts with the Nextcloud API
![strict digraph content {
rankdir=LR;
nc [label="Nextcloud (HTTP API)", shape="rectangle"];
ical [label="iCalendar", shape="rectangle"];
html [label="HTML", shape="rectangle"];
pdf [label="PDF", shape="rectangle"];
nc -> ical [label="requests"];
ical -> html [label="ical2html"];
html -> pdf [label="Weasyprint"];
}](../../_images/graphviz-1e0b249961b5ac76ac70bca9ac00205ee13287c7.png)
See also
Index of /Tools/Ical2html 11
install the dependencies
apt-get install ical2html pip3 install --user pipenv
create the jobs directories
mkdir -p /home/jobs/scripts/by-user/myuser/nextcloud_calendar_to_pdf cd /home/jobs/scripts/by-user/myuser/nextcloud_calendar_to_pdf
create a new Nextcloud user specifically for this purpose and share the calendar with it
connect to your Nextcloud instance using the new user and go to the calendar app
get the calendar name by opening the calendar options an click on
Copy private link
create the
script
includes/home/jobs/scripts/by-user/myuser/nextcloud_calendar_to_pdf/nextcloud_calendar_to_pdf.py##!/usr/bin/env python3 # -*- coding: utf-8 -*- # # nextcloud_calendar_to_pdf.py # # Copyright (C) 2022 Franco Masotti (franco \D\o\T masotti {-A-T-} tutanota \D\o\T com) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. # # See more copyrights and licenses below. import calendar import datetime import pathlib import shlex import subprocess import sys import urllib.parse import requests import yaml from weasyprint import HTML if __name__ == '__main__': configuration_file = sys.argv[1] config = yaml.load(open(configuration_file, 'r'), Loader=yaml.SafeLoader) input_year: str = input("Year (empty for current) : ").zfill(4) input_month: str = input("Month (empty for current): ").zfill(2) if input_year == '0000': input_year = str(datetime.datetime.now().year).zfill(4) if input_month == '00': input_month = str(datetime.datetime.now().month).zfill(2) input('Are you sure, year=' + input_year + ' month=' + input_month + '? ') # Day is always fixed at 1. input_day: str = '01' input_date: str = input_year + input_month + input_day calendar_error_message: str = 'This is the WebDAV interface. It can only be accessed by WebDAV clients such as the Nextcloud desktop sync client.' try: # Format yyyymmdd ttime = datetime.datetime.strptime(input_date, '%Y%m%d') month_range: tuple = calendar.monthrange(ttime.year, ttime.month) # Pan days = current_month.days - 1 pan_days: str = str(month_range[1] - 1) except ValueError: print('date parse error') sys.exit(1) calendar_api_uri: str = ('https://' + config['nextcloud']['host'] + '/remote.php/dav/calendars/' + config['nextcloud']['user'] + '/' + config['nextcloud']['calendar_name'] + '?export') # Check if the computed string is a valid URL. try: nc_calendar_string = urllib.parse.urlparse(calendar_api_uri) if (nc_calendar_string.scheme == str() or nc_calendar_string.netloc == str()): raise ValueError except ValueError: print('URL parse error') sys.exit(1) # Get the calendar using credentials. r = requests.get(calendar_api_uri, auth=(config['nextcloud']['user'], config['nextcloud']['password'])) if (r.status_code == 200 and not r.text == calendar_error_message): nc_calendar: str = r.text else: print('error getting calendar from the Nextcloud instance') sys.exit(1) # Transform the ical file to HTML. command: str = ('ical2html --footer=' + config['ical2html']['footer'] + ' --timezone=' + config['ical2html']['timezone'] + ' ' + input_date + ' P' + pan_days + 'D ' + config['ical2html']['options']) command: str = shlex.split(command) try: process = subprocess.run(command, input=nc_calendar.encode('UTF-8'), check=True, capture_output=True) except subprocess.CalledProcessError: print('ical2html error') sys.exit(1) # Transform the HTML file to PDF. try: output_file = str( pathlib.Path( config['output_basedir'], config['nextcloud']['calendar_name'] + '_' + input_date + '_dayrange_' + str(month_range[1]))) html = HTML(string=process.stdout) final_file = output_file + '.pdf' html.write_pdf(final_file) print('output file = ' + final_file) except (TypeError, ValueError): print('weasyprint error') sys.exit(1)
create the
configuration
/home/jobs/scripts/by-user/myuser/nextcloud_calendar_to_pdf/nextcloud_calendar_to_pdf.yaml#nextcloud: host: 'my.nextcloud.com' user: 'calendar-user' password: 'my password' # Must already be slugged. calendar_name: 'my-personal-calendar_shared_by_someotheruser' ical2html: # Pass options directly. options: '--monday' timezone: 'Europe/Rome' footer: '"A generic footer message"' output_basedir: '/home/myuser/calendar_outputs'
create a
launcher
includes/home/jobs/scripts/by-user/myuser/nextcloud_calendar_to_pdf_laucher.sh##!/usr/bin/env bash # # nextcloud_calendar_to_pdf_laucher.sh # # Copyright (C) 2022 Franco Masotti (franco \D\o\T masotti {-A-T-} tutanota \D\o\T com) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. # pushd /home/jobs/scripts/by-user/myuser/nextcloud_calendar_to_pdf \ && /home/myuser/.local/bin/pipenv run ./nextcloud_calendar_to_pdf.py \ ./nextcloud_calendar_to_pdf.yaml
create the
Pipfile
includes/home/jobs/scripts/by-user/myuser/nextcloud_calendar_to_pdf/Pipfile## # Pipfile # # Copyright (C) 2022 Franco Masotti (franco \D\o\T masotti {-A-T-} tutanota \D\o\T com) # # This file is part of fpydocs. # # fpydocs is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # fpydocs is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with fpydocs. If not, see <http://www.gnu.org/licenses/>. # [[source]] name = "pypi" url = "https://pypi.org/simple" verify_ssl = true [packages] requests = '>=2,<3' WeasyPrint = '>=52,<53' PyYAML = '>=6,<7'
fix the permissions
chmod 700 /home/jobs/scripts/by-user/myuser chmod 700 -R /home/jobs/services/by-user/myuser
install the development environment witn
myuser
pipenv install
Run the script
/home/jobs/scripts/by-user/myuser/nextcloud_calendar_to_pdf/nextcloud_calendar_to_pdf.sh
Full text search with Elasticsearch#
These apps enable you to search text through all files (no OCR).
See also
Docker-compose fails with ingest-attachment - Elastic Stack / Elasticsearch - Discuss the Elastic Stack 7
How to Run Elasticsearch 8 on Docker for Local Development | by Lynn Kwong | Level Up Coding 8
ingest-attachment and node alive problem · Issue #42 · nextcloud/fulltextsearch_elasticsearch · GitHub 9
elasticsearch - Recommended RAM ratios for ELK with docker-compose - Stack Overflow 10
Plugin was built for Elasticsearch version 7.7.0 but version 7.7.1 is runnin · Issue #10 · opendatasoft/elasticsearch-aggregation-geoclustering · GitHub 33
install these three apps in Nextcloud. Go to the add apps admin menu, then to the
Search
sectionconfigure the search from the Nextcloud admin settings. Go to the
Full text search
tab and use these settings:Nextcloud administration search settings#
add this content to the docker compose file
/home/jobs/scripts/by-user/root/docker/nextcloud/docker-compose.yml#clamav: image: clamav/clamav:latest restart: always hostname: clamav # PostgreSQL in host with elasticsearch. version: '2' volumes: nextcloud: redis: services: app: image: nextcloud:production restart: always ports: - 4005:80 links: - redis - elasticsearch volumes: - ${DATA_PATH}:/var/www/html/data - ${HTML_DATA_PATH}:/var/www/html environment: - REDIS_HOST=redis - REDIS_HOST_PORT=6379 - POSTGRES_DB=${DATABASE_NAME} - POSTGRES_USER=${DATABASE_USER} - POSTGRES_HOST=${DATABASE_HOST} - POSTGRES_PASSWORD=${DATABASE_PASSWORD} - APACHE_DISABLE_REWRITE_IP=1 - TRUSTED_PROXIES=127.0.0.1 - OVERWRITEHOST=${FQDN} - OVERWRITEPROTOCOL=https - OVERWRITECLIURL=https://${FQDN} elasticsearch: image: elasticsearch:7.17.7 environment: - xpack.security.enabled=false - "discovery.type=single-node" networks: - mynetwork hostname: elasticsearch volumes: # NOTE # enable the data volume when insructed! # NOTE # # - ${ES_DATA_PATH}:/usr/share/elasticsearch/data - ${ES_PLUGINS_PATH}:/usr/share/elasticsearch/plugins ports: - 9200:9200 # Very important: elastic search will use all memory available # so you must set an appropriate value here. mem_limit: 16g redis: image: redis:6.2.5 restart: always hostname: redis volumes: - redis:/var/lib/redis
Note
Replace
DATABASE_NAME
,DATABASE_USER
,DATABASE_PASSWORD
,DATABASE_HOST
,DATA_PATH
,HTML_DATA_PATH
,FQDN
,ES_DATA_PATH
andES_PLUGINS_PATH
with appropriate values.Important
At the moment only version 7 of Elasticsearch is supported
go to the Nextcloud docker directory and run the app
pushd /home/jobs/scripts/by-user/root/docker/nextcloud docker-compose up --remove-orphans
install the attachment plugin
/usr/bin/docker-compose exec -T elasticsearch /usr/share/elasticsearch/bin/elasticsearch-plugin install ingest-attachment
check the user id and group id of the data directory in the elasticsearch container
/usr/bin/docker-compose exec -T elasticsearch id elasticsearch /usr/bin/docker-compose exec -T elasticsearch ls -ld /usr/share/elasticsearch/data
stop the app
docker-compose down
change the ownership of the docker volume to the ones resulting from the previous command. In my case the owner user is
1000
while the owner group isroot
chown 1000:root esdata
enable the commented volume,
ES_DATA_PATH
, from the docker-compose filecreate a
Systemd unit file
. See also the Docker compose services section/home/jobs/services/by-user/root/docker-compose.nextcloud.service#[Unit] Requires=docker.service Requires=network-online.target After=docker.service After=network-online.target # Enable these for the "scalable" variant. # Requires=redis.service # Requires=redis-socket.service # After=redis.service # After=redis-socket.service [Service] Type=simple WorkingDirectory=/home/jobs/scripts/by-user/root/docker/nextcloud ExecStart=/usr/bin/docker-compose up --remove-orphans ExecStop=/usr/bin/docker-compose down --remove-orphans Restart=always [Install] WantedBy=multi-user.target
run the deploy script
test if the interaction between the Nextcloud container and Elasticsearch is working. The last command does the actual indexing and it may take a long time to complete
/usr/bin/docker-compose exec -T --user www-data app php occ fulltextsearch:test /usr/bin/docker-compose exec -T --user www-data app php occ fulltextsearch:check /usr/bin/docker-compose exec -T --user www-data app php occ fulltextsearch:index
create a
Systemd unit file
/home/jobs/services/by-user/root/nextcloud-elasticsearch.service#[Unit] Requires=docker-compose.nextcloud.service Requires=network-online.target After=docker-compose.nextcloud.service After=network-online.target [Service] Type=simple WorkingDirectory=/home/jobs/scripts/by-user/root/docker/nextcloud Restart=no ExecStart=/usr/bin/bash -c '/usr/bin/docker-compose exec -T --user www-data app php occ fulltextsearch:index'
create a
Systemd timer unit file
/home/jobs/services/by-user/root/nextcloud-elasticsearch.timer#[Unit] Description=Once every hour run Nextcloud's elasticsearch indexing [Timer] OnCalendar=Hourly Persistent=true [Install] WantedBy=timers.target
run the deploy script
Important
When you update Elasticsearch, for example from version 7.17.7 to 7.17.8, you must recreate the index like this
systemctl stop docker-compose.nextcloud.service
/usr/bin/docker-compose run --rm elasticsearch /usr/share/elasticsearch/bin/elasticsearch-plugin remove ingest-attachment
/usr/bin/docker-compose run --rm elasticsearch /usr/share/elasticsearch/bin/elasticsearch-plugin install ingest-attachment
systemctl restart docker-compose.nextcloud.service
Talk (a.k.a. Spreed)#
You can use metered.ca OpenRelay’s STUN and TURN servers to improve communication between WebRTC P2P clients.
See also
Free WebRTC TURN Server - Open Relay Project | Open Relay Project - Free WebRTC TURN Server 5
Services#
Once you have your Nextcloud container running you may want to integrate these services as well
Required#
Crontab#
See also
Background jobs — Nextcloud latest Administration Manual latest documentation 4
create another
Systemd unit file
that will run tasks periodically/home/jobs/services/by-user/root/nextcloud-cron.service#[Unit] Requires=docker-compose.nextcloud.service Requires=network-online.target After=docker-compose.nextcloud.service After=network-online.target [Service] Type=simple WorkingDirectory=/home/jobs/scripts/by-user/root/docker/nextcloud Restart=no ExecStart=/usr/bin/bash -c '/usr/bin/docker-compose exec -T --user www-data app php cron.php'
create a
Systemd timer file
/home/jobs/services/by-user/root/nextcloud-cron.timer#[Unit] Description=Once every 15 minutes run Nextcloud's cron [Timer] OnCalendar=*:0/15 Persistent=true [Install] WantedBy=timers.target
run the deploy script
Optional#
File scanner#
create another
Systemd unit file
that will enable nextcloud to periodically scan for new files if added by external sources/home/jobs/services/by-user/root/scan-files-nextcloud.service#[Unit] Requires=docker-compose.nextcloud.service Requires=network-online.target After=docker-compose.nextcloud.service After=network-online.target [Service] Type=simple WorkingDirectory=/home/jobs/scripts/by-user/root/docker/nextcloud Restart=no # Scan all new files. ExecStart=/usr/bin/bash -c '/usr/bin/docker-compose exec -T --user www-data app php occ files:scan --all'
create a
Systemd timer file
/home/jobs/services/by-user/root/scan-files-nextcloud.timer#[Unit] Description=Once every week scan-files-nextcloud [Timer] OnCalendar=weekly Persistent=true [Install] WantedBy=timers.target
run the deploy script
Image previews#
To have faster image load time you can use the image preview app.
See also
install the apps in Nextcloud. Go to the add apps admin menu, then to the
Search
sectionAppend these options to the main configuration file
${HTML_DATA_PATH}/config/config.php#'preview_max_x' => '4096', 'preview_max_y' => '4096', 'jpeg_quality' => '40',
restart nextcloud
systemctl restart docker-compose.nextcloud.service
go to the docker-compose directory and run these commands to set the preview sizes
cd /home/jobs/scripts/by-user/root/docker/nextcloud docker-compose exec -T --user www-data app php occ config:app:set --value="32 128" previewgenerator squareSizes docker-compose exec -T --user www-data app php occ config:app:set --value="128 256" previewgenerator widthSizes docker-compose exec -T --user www-data app php occ config:app:set --value="128" previewgenerator heightSizes
generate the previews and wait
docker-compose exec -T --user www-data app php occ preview:generate-all -vvv
Note
You may get an error such as
Could not create folder
. Retry scanning manually later untill it works.create a
Systemd unit file
/home/jobs/services/by-user/root/nextcloud-preview.service#[Unit] Requires=docker-compose.nextcloud.service Requires=network-online.target After=docker-compose.nextcloud.service After=network-online.target [Service] Type=simple WorkingDirectory=/home/jobs/scripts/by-user/root/docker/nextcloud Restart=no ExecStart=/usr/bin/bash -c '/usr/bin/docker-compose exec -T --user www-data app php occ preview:generate-all'
create a
Systemd timer unit file
/home/jobs/services/by-user/root/nextcloud-preview.timer#[Unit] Description=Run Nextcloud's image preview generation daily [Timer] OnCalendar=*-*-* 04:00:00 Persistent=true [Install] WantedBy=timers.target
run the deploy script
Note
If you need to regenerate or delete the previews you must follow the steps reported in the repository’s readme 13.
Export#
You can export all calendars, contacts and news sources using this script. This is useful if your do not have the possibility to make a full backup and in case something goes wrong during an update to your Nextcloud instance.
install the dependencies
apt-get install python3-yaml
create a new user
useradd --system -s /bin/bash -U nextcloud passwd nextcloud usermod -aG jobs nextcloud
create the jobs directories. See reference
mkdir -p /home/jobs/{scripts,services}/by-user/nextcloud
create the
script
/home/jobs/scripts/by-user/nextcloud/nextcloud_export.py##!/usr/bin/env python3 # -*- coding: utf-8 -*- # # nextcloud_export.py # # Copyright (C) 2023 Franco Masotti (franco \D\o\T masotti {-A-T-} tutanota \D\o\T com) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. # import io import pathlib import re import sys import urllib.parse import urllib.request import yaml if __name__ == '__main__': configuration_file = sys.argv[1] config = yaml.load(open(configuration_file, 'r'), Loader=yaml.SafeLoader) total_elements: int = len(config['element']) extension: str element_api_url: str element_error_message: str = 'This is the WebDAV interface. It can only be accessed by WebDAV clients such as the Nextcloud desktop sync client.' for i, c in enumerate(config['element']): print('getting Nextcloud element (' + str(i + 1) + ' of ' + str(total_elements) + ') ' + c) if config['element'][c]['type'] == 'calendar': element_api_url = ('https://' + config['element'][c]['host'] + '/remote.php/dav/calendars/' + config['element'][c]['user'] + '/' + config['element'][c]['name'] + '?export') extension = 'vcs' elif config['element'][c]['type'] == 'address_book': element_api_url = ('https://' + config['element'][c]['host'] + '/remote.php/dav/addressbooks/users/' + config['element'][c]['user'] + '/' + config['element'][c]['name'] + '?export') extension = 'vcf' elif config['element'][c]['type'] == 'news': element_api_url = ('https://' + config['element'][c]['host'] + '/apps/news/export/opml') extension = 'opml' else: print('unsupported element: ' + config['element'][c]['type']) sys.exit(1) # Check if the computed string is a valid URL. try: element_string = urllib.parse.urlparse(element_api_url) if (element_string.scheme == str() or element_string.netloc == str() or not re.match('^http(|s)', element_string.scheme)): raise ValueError except ValueError: print('URL parse error') sys.exit(1) # Get the element using credentials. # Send credentials immediately, do not wait for the 401 error. password_manager = urllib.request.HTTPPasswordMgrWithPriorAuth() password_manager.add_password(None, element_api_url, config['element'][c]['user'], config['element'][c]['password'], is_authenticated=True) handler = urllib.request.HTTPBasicAuthHandler(password_manager) opener = urllib.request.build_opener(handler) urllib.request.install_opener(opener) try: with urllib.request.urlopen(element_api_url) as response: nc_element: io.BytesIO = response.read() if nc_element.decode('UTF-8') == element_error_message: raise ValueError except (urllib.error.URLError, ValueError) as e: print(e) print('error getting element from the Nextcloud instance at ' + element_api_url) sys.exit(1) # Save the element using the directory structure "basedir/username/element". top_directory = pathlib.Path(config['output_basedir'], config['element'][c]['user']) top_directory.mkdir(mode=0o755, parents=True, exist_ok=True) final_path = str( pathlib.Path(top_directory, config['element'][c]['name'] + '.' + extension)) with open(final_path, 'wb') as f: f.write(nc_element)
create a
configuration file
/home/jobs/scripts/by-user/nextcloud/nextcloud_export.yaml#element: my_personal_calendar: # Do not include the http or https scheme. host: '${FQDN}' user: '${NC_USER}' password: '${NC_PASSWORD}' # Must already be slugged. name: 'personal' # valid values: {calendar,address_book,news} type: 'calendar' my_news_subscription: host: '${FQDN}' user: '${NC_USER}' password: '${NC_PASSWORD}' # 'name' for type 'news' can be any arbitrary value. # This will correspond to the file name, excluding the extension. name: 'news-subscription' type: 'news' my_contacts: host: '${FQDN}' user: '${NC_USER}' password: '${NC_PASSWORD}' name: 'contacts' type: 'address_book' output_basedir: '/data/NEXTCLOUD/export'
create the data directory which must be accessible by the
nextcloud
usermkdir /data/NEXTCLOUD/export chmod 700 /data/NEXTCLOUD/export chown nextcloud:nextcloud /data/NEXTCLOUD/export
use this
Systemd service file
/home/jobs/services/by-user/nextcloud/nextcloud-export.service#[Unit] Description=Nextcloud export elements Requires=network-online.target After=network-online.target Requires=data.mount After=data.mount Requires=docker-compose.nextcloud.service After=docker-compose.nextcloud.service [Service] Type=simple ExecStart=/home/jobs/scripts/by-user/nextcloud/nextcloud_export.py /home/jobs/scripts/by-user/nextcloud/nextcloud_export.yaml User=nextcloud Group=nextcloud
use this
Systemd timer file
/home/jobs/services/by-user/nextcloud/nextcloud-export.timer#[Unit] Description=Once a day Nextcloud export elements [Timer] OnCalendar=Daily Persistent=true [Install] WantedBy=timers.target
fix the permissions
chown -R nextcloud:nextcloud /home/jobs/{scripts,services}/by-user/nextcloud chmod 700 -R /home/jobs/{scripts,services}/by-user/nextcloud
Other notes#
PhoneTrack app#
Some mobile phones OSs have a bug in interpeting the correct date sent from GPS satellites. This problem is called GPS week number rollover and sets the date, but not the time, 1024 weeks in the past.
Applications like PhoneTrack should compensate for this problem. A fix was proposed but never merged in the code.
You patach the code manually in
${HTML_DATA_PATH}/custom_apps/phonetrack/lib/Controller/LogController.php
and then restart your Nextcloud instance.
Recognize app#
Important information before using the Recognize for Nextcloud app.
See also
GitHub - nextcloud/recognize: Smart media tagging for Nextcloud: recognizes faces, objects, landscapes, music genres 19
Error when deleting file or folder - General - Nextcloud community 20
[Bug]: Call to undefined method OCPFilesEventsNodeNodeDeletedEvent::getSubject() on deltetion of files · Issue #33865 · nextcloud/server · GitHub 21
[3.2.2] Background scan blocks Nextcloud CRON php job indefinetly with 100% CPU load · Issue #505 · nextcloud/recognize · GitHub 22
Memories app#
Once the Memories app is installed or when you added external files you must run a reindexing operation
See also
GitHub - pulsejet/memories: Fast, modern and advanced photo management suite. Runs as a Nextcloud app. 23
docker-compose exec -T --user www-data app php occ memories:index
News app#
Improve performance#
Opcache#
You can improve caching by changing options in the opcache-recommended.ini
file.
See also
create the directory
mkdir /home/jobs/scripts/by-user/root/docker/nextcloud/phpcfg pushd /home/jobs/scripts/by-user/root/docker/nextcloud/phpcfg
create a
configuration file
/home/jobs/scripts/by-user/root/docker/nextcloud/phpcfg/opcache-recommended.ini#opcache.enable=1 opcache.interned_strings_buffer=512 opcache.max_accelerated_files=65407 opcache.memory_consumption=2048 opcache.save_comments=1 opcache.revalidate_freq=80
add the docker volume in the docker-compose file
/home/jobs/scripts/by-user/root/nextcloud/docker-compose.yml## [ ... ] volumes: # [ ... ] - /home/jobs/scripts/by-user/root/docker/nextcloud/phpcfg/opcache-recommended.ini:/usr/local/etc/php/conf.d/opcache-recommended.ini # [ ... ] # [ ... ]
run the deploy script
Transactional file locking#
See also
Transactional file locking — Nextcloud latest Administration Manual latest documentation 29
Footnotes
- 1
https://docs.nextcloud.com/server/20/admin_manual/configuration_database/linux_database_configuration.html CC BY 3.0, Copyright (c) Nextcloud contributors
- 2
https://faun.pub/deploy-nextcloud-with-docker-compose-traefik-2-postgresql-and-redis-fd1ffc166173 unknown license
- 3
https://techoverflow.net/2020/12/01/how-to-backup-data-from-docker-compose-mariadb-container-using-mysqldump/ unknown license
- 4
https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/background_jobs_configuration.html CC-BY 3.0, Copyright (c) Nextcloud contributors
- 5
https://www.metered.ca/tools/openrelay/#turn-server-for-nextcloud-talk unknown license
- 6
https://blog.it-playground.eu/accessing-host-socket-when-using-namespaces-for-docker-isolation/ unknown license
- 7
https://discuss.elastic.co/t/docker-compose-fails-with-ingest-attachment/173598/5 unknown license
- 8
https://levelup.gitconnected.com/how-to-run-elasticsearch-8-on-docker-for-local-development-401fd3fff829 unknown license
- 9
https://github.com/nextcloud/fulltextsearch_elasticsearch/issues/42 unknown license
- 10
https://stackoverflow.com/questions/51541323/recommended-ram-ratios-for-elk-with-docker-compose CC BY-SA 4.0, Copyright (c) 2018 Stackoverflow contributors
- 11
https://www.w3.org/Tools/Ical2html/ W3C Software Notice and License, Copyright (c) Ical2html contributors
- 12
https://rayagainstthemachine.net/linux%20administration/nextcloud-photos/ unknown license
- 13(1,2)
https://github.com/nextcloud/previewgenerator GNU AGPLv3, Copyright (c) Preview Generator contributors
- 14
https://github.com/nextcloud/previewgenerator/issues/289 GNU AGPLv3, Copyright (c) Preview Generator contributors
- 15
https://docs.nextcloud.com/server/24/admin_manual/office/example-docker.html CC-BY 3.0, Nextcloud contributors
- 16
- 17
https://help.nextcloud.com/t/socket-error-when-accessing-collabora/22486 unknown license
- 18
https://help.nextcloud.com/t/issue-with-federation-and-shares/120917/3 unknown license
- 19
- 20
https://help.nextcloud.com/t/error-when-deleting-file-or-folder/34948 unknown license
- 21
https://github.com/nextcloud/server/issues/33865 unknown license
- 22
https://github.com/nextcloud/recognize/issues/505 unknown license
- 23
https://github.com/pulsejet/memories AGPL-3.0 license, Copyright (c) memories contributors
- 24
https://www.php.net/manual/en/intro.opcache.php unknown license
- 25
https://www.php.net/manual/en/opcache.configuration.php unknown license
- 26
https://gitlab.com/eneiluj/phonetrack-oc/-/merge_requests/934 unknown license
- 27
https://gitlab.com/eneiluj/phonetrack-oc/-/merge_requests/934/diffs unknown license
- 28
https://github.com/nextcloud/server/issues/5044 unknown license
- 29
https://docs.nextcloud.com/server/latest/admin_manual/configuration_files/files_locking_transactional.html CC-BY 3.0, Nextcloud contributors
- 30
https://help.nextcloud.com/t/cant-connect-to-onlyoffice-document-server-after-update-to-nc19/83958 unknown license
- 31
https://help.nextcloud.com/t/how-can-i-remove-all-the-rss-feeds-from-the-news-app/118340/4 unknown license
- 32
https://help.nextcloud.com/t/rss-news-reader-cleanup-before-new-content/33623 unknown license
- 33
https://github.com/opendatasoft/elasticsearch-aggregation-geoclustering/issues/10#issuecomment-1044899338 unknown license