diff --git a/bundles/nextcloud/files/nextcloud-cron.service b/bundles/nextcloud/files/nextcloud-cron.service new file mode 100644 index 0000000..6db67ed --- /dev/null +++ b/bundles/nextcloud/files/nextcloud-cron.service @@ -0,0 +1,7 @@ +[Unit] +Description=Nextcloud cron.php job + +[Service] +User=www-data +ExecStart=/usr/bin/php --define apc.enable_cli=1 -f /var/www/nextcloud/cron.php +KillMode=process diff --git a/bundles/nextcloud/files/nextcloud-cron.timer b/bundles/nextcloud/files/nextcloud-cron.timer new file mode 100644 index 0000000..7d205da --- /dev/null +++ b/bundles/nextcloud/files/nextcloud-cron.timer @@ -0,0 +1,8 @@ +[Unit] +Description=Run Nextcloud cron.php every 5 minutes + +[Timer] +OnCalendar=*:0/5 + +[Install] +WantedBy=timers.target diff --git a/bundles/nextcloud/items.py b/bundles/nextcloud/items.py new file mode 100644 index 0000000..d2510aa --- /dev/null +++ b/bundles/nextcloud/items.py @@ -0,0 +1,37 @@ +repo.libs.tools.require_bundle(node, 'nginx') +repo.libs.tools.require_bundle(node, 'php') +repo.libs.tools.require_bundle(node, 'postgresql') +repo.libs.tools.require_bundle(node, 'redis') + +VERSION = node.metadata.get('nextcloud/version') + +directories = { + '/var/lib/nextcloud': { + 'owner': 'www-data', + 'group': 'www-data', + 'mode': '0770', + }, +} + +files = { + '/etc/systemd/system/nextcloud-cron.timer': { + 'triggers': { + 'action:systemd-reload', + 'svc_systemd:nextcloud-cron.timer:restart', + }, + }, + '/etc/systemd/system/nextcloud-cron.service': { + 'triggers': { + 'action:systemd-reload', + }, + }, +} + +svc_systemd = { + 'nextcloud-cron.timer': { + 'needs': { + 'file:/etc/systemd/system/nextcloud-cron.timer', + 'file:/etc/systemd/system/nextcloud-cron.service', + }, + }, +} diff --git a/bundles/nextcloud/metadata.py b/bundles/nextcloud/metadata.py new file mode 100644 index 0000000..72be280 --- /dev/null +++ b/bundles/nextcloud/metadata.py @@ -0,0 +1,83 @@ +defaults = { + 'php': { + 'version': '8.0', + 'packages': { + 'apcu', + 'bcmath', + 'bz2', + 'curl', + 'gd', + 'gmp', + 'imagick', + 'intl', + 'ldap', + 'mbstring', + 'memcached', + 'pgsql', + 'redis', + 'xml', + 'zip', + }, + 'memory_limit': 512, + 'post_max_size': 500, + 'clear_env': False, + }, + 'postgresql': { + 'version': '13', + 'roles': { + 'nextcloud': { + 'password': repo.vault.password_for(f'{node.name} postgresql nextcloud'), + }, + }, + 'databases': { + 'nextcloud': { + 'owner': 'nextcloud', + }, + }, + }, +} + + +@metadata_reactor.provides( + 'nginx/vhosts/nextcloud', +) +def nginx(metadata): + if not node.has_bundle('nginx'): + raise DoNotRunAgain + + return { + 'nginx': { + 'vhosts': { + 'nextcloud': { + 'domain': metadata.get('nextcloud/domain'), + 'webroot_config': { + 'owner': 'www-data', + 'group': 'www-data', + }, + 'max_body_size': '500M', + 'extras': True, + #'website_check_path': '/user/login', + #'website_check_string': 'Sign In', + }, + }, + }, + } + + +@metadata_reactor.provides( + 'icinga2_api/nextcloud/services', +) +def icinga_check_for_new_release(metadata): + return { + 'icinga2_api': { + 'nextcloud': { + 'services': { + 'NEXTCLOUD UPDATE': { + 'command_on_monitored_host': '/usr/local/share/icinga/plugins/check_github_for_new_release nextcloud/server {}'.format(metadata.get('nextcloud/version')), + 'vars.notification.mail': True, + 'check_interval': '60m', + }, + }, + }, + }, + } diff --git a/data/nginx/files/error.html b/data/nginx/files/error.html new file mode 120000 index 0000000..4240cd6 --- /dev/null +++ b/data/nginx/files/error.html @@ -0,0 +1 @@ +../../../../bundlewrap/data/nginx/files/error.html \ No newline at end of file diff --git a/data/nginx/files/extras/qzwi/nextcloud b/data/nginx/files/extras/qzwi/nextcloud new file mode 100644 index 0000000..d470b99 --- /dev/null +++ b/data/nginx/files/extras/qzwi/nextcloud @@ -0,0 +1,105 @@ + add_header X-Download-Options "noopen" always; + add_header X-Permitted-Cross-Domain-Policies "none" always; + add_header X-Robots-Tag "none" always; + + # 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 /remote.php/dav/; } + location = /.well-known/caldav { return 301 /remote.php/dav/; } + + location = /.well-known/webfinger { return 301 /index.php/.well-known/webfinger; } + location = /.well-known/nodeinfo { return 301 /index.php/.well-known/nodeinfo; } + + 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.conf; + fastcgi_pass unix:/run/php/php${php_version}-fpm.sock; + + 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_intercept_errors on; + fastcgi_request_buffering off; + } + + location ~ \.(?:css|js|svg|gif|png|jpg|ico|wasm|tflite)$ { + 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 ~ \.wasm$ { + default_type application/wasm; + } + } + + 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; + } diff --git a/data/nginx/files/not_found.html b/data/nginx/files/not_found.html new file mode 120000 index 0000000..85596d2 --- /dev/null +++ b/data/nginx/files/not_found.html @@ -0,0 +1 @@ +../../../../bundlewrap/data/nginx/files/not_found.html \ No newline at end of file diff --git a/data/nginx/files/ssl b/data/nginx/files/ssl new file mode 120000 index 0000000..a70fa50 --- /dev/null +++ b/data/nginx/files/ssl @@ -0,0 +1 @@ +../../ssl/ \ No newline at end of file diff --git a/nodes/qzwi.toml b/nodes/qzwi.toml index 2c140b8..e9c2e82 100644 --- a/nodes/qzwi.toml +++ b/nodes/qzwi.toml @@ -1,6 +1,12 @@ -hostname = "2a00:f820:528::4" +#hostname = "2a00:f820:528::4" +hostname = "31.47.232.108" bundles = [ + "nginx", + "nextcloud", "openldap", + "php", + "postgresql", + "redis", ] groups = [ "debian-bullseye", @@ -14,6 +20,14 @@ ips = [ gateway4 = "31.47.232.105" gateway6 = "2a00:f820:528::1" +[metadata.nextcloud] +domain = "cloud.qzwi.de" +sha1 = "0d496eb0808c292502479e93cd37fe2daf95786a" +version = "23.0.0" + +[metadata.nginx.vhosts.nextcloud] +ssl = "_.qzwi.de" + [metadata.openldap] my_hostname = "ldap.qzwi.de" ssl = "_.qzwi.de" @@ -23,3 +37,7 @@ backup = [ schemas = [ "openssh-lpk_openldap", ] + +[metadata.vm] +cpu = 4 +ram = 4