mirror of
https://github.com/nextcloud/all-in-one.git
synced 2026-05-22 11:20:13 +00:00
Compare commits
156 Commits
v12.8.0
...
translatio
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ffc810c0b | ||
|
|
b4efbed23f | ||
|
|
021854144b | ||
|
|
228f785987 | ||
|
|
7c8cabdb2d | ||
|
|
7049448541 | ||
|
|
35dd0a2c00 | ||
|
|
fbe60b852c | ||
|
|
5782a01b7f | ||
|
|
46b325f2bd | ||
|
|
05f9fa0e25 | ||
|
|
443f3a4bee | ||
|
|
d280786934 | ||
|
|
253df4ee0c | ||
|
|
8073f3c562 | ||
|
|
a3dac35edb | ||
|
|
b222639bbd | ||
|
|
a5d4f2dd88 | ||
|
|
51c7b270b4 | ||
|
|
754a317fea | ||
|
|
7f35ee5fbb | ||
|
|
b7b6cc8a16 | ||
|
|
7dc489168a | ||
|
|
d71683ff38 | ||
|
|
d4743d9800 | ||
|
|
f1b635c196 | ||
|
|
ecd85281cc | ||
|
|
558e8735b5 | ||
|
|
e0ff3acb3d | ||
|
|
4963558691 | ||
|
|
90d5d6bcf1 | ||
|
|
b19c6dfddb | ||
|
|
904921c815 | ||
|
|
7d63b13a40 | ||
|
|
83102e46b2 | ||
|
|
9e49f81c43 | ||
|
|
25a63abbc8 | ||
|
|
f1eeea9337 | ||
|
|
156e55d0ad | ||
|
|
c5501c885d | ||
|
|
de7b5cd8e4 | ||
|
|
d6981be067 | ||
|
|
0755000456 | ||
|
|
b169790488 | ||
|
|
9a6b74dd16 | ||
|
|
b28572e67f | ||
|
|
8b2a4c057a | ||
|
|
669ea45749 | ||
|
|
1e76d39742 | ||
|
|
c2e7990d33 | ||
|
|
1821e695aa | ||
|
|
d761f22fa1 | ||
|
|
3738890c05 | ||
|
|
726e639f0b | ||
|
|
8bac8f029f | ||
|
|
828b7784f7 | ||
|
|
0cb0d86471 | ||
|
|
1b69fb88ae | ||
|
|
6fd537cd5d | ||
|
|
11dbc4978d | ||
|
|
43de29e071 | ||
|
|
eed853e942 | ||
|
|
bdb8e171f7 | ||
|
|
68c5dc8d60 | ||
|
|
dfe7eb7ec1 | ||
|
|
2016789bea | ||
|
|
b0969d9644 | ||
|
|
6e8c8dab19 | ||
|
|
1e23c1a6dd | ||
|
|
c4f4ff22c9 | ||
|
|
a7703283dc | ||
|
|
9ce33d1d1d | ||
|
|
d86eee5847 | ||
|
|
eda48383b4 | ||
|
|
7302b48fcf | ||
|
|
26c0d6204b | ||
|
|
4ee7f573e6 | ||
|
|
04e424b3a7 | ||
|
|
ba3ee91c35 | ||
|
|
c24f9c1642 | ||
|
|
50b309c5a2 | ||
|
|
1419f29d2b | ||
|
|
9a37170f08 | ||
|
|
1e4e040dad | ||
|
|
ad534c83cc | ||
|
|
26aced2126 | ||
|
|
2ce73190e2 | ||
|
|
585a8ef13b | ||
|
|
a97877ee6b | ||
|
|
203b1a335e | ||
|
|
109f2493af | ||
|
|
9ed23f1952 | ||
|
|
385eeb1621 | ||
|
|
ee4df40708 | ||
|
|
2999fb4413 | ||
|
|
1620f83bf7 | ||
|
|
eccfa8b9d9 | ||
|
|
9b64fff193 | ||
|
|
349443c240 | ||
|
|
49d743c17c | ||
|
|
c45913a6ff | ||
|
|
7f394f5297 | ||
|
|
e561fad2af | ||
|
|
eb9cb26ff1 | ||
|
|
1022b408a7 | ||
|
|
ee137e497a | ||
|
|
71b384be64 | ||
|
|
7922d38aa6 | ||
|
|
dd103fa0f1 | ||
|
|
909ef96748 | ||
|
|
978a4ce282 | ||
|
|
b972c5703f | ||
|
|
8c3b5b2e21 | ||
|
|
6e87758ba9 | ||
|
|
4b1c7286bc | ||
|
|
510032d7a1 | ||
|
|
b248710803 | ||
|
|
9040ccdab8 | ||
|
|
c7041c4f6f | ||
|
|
23f5ae2a10 | ||
|
|
ea326ba723 | ||
|
|
b4db823d9b | ||
|
|
61e6e233f4 | ||
|
|
1abb0e2b94 | ||
|
|
31999ade2e | ||
|
|
744efad0f4 | ||
|
|
11553a3c0f | ||
|
|
0cdbf3aa96 | ||
|
|
2d4903492b | ||
|
|
8cd82a6fb8 | ||
|
|
c5e20e3024 | ||
|
|
b82e34ddef | ||
|
|
e910c0c21a | ||
|
|
d5b334177c | ||
|
|
ea52b11c7b | ||
|
|
825787e228 | ||
|
|
c827221188 | ||
|
|
78cfc91d1e | ||
|
|
0048e46272 | ||
|
|
fc6626918d | ||
|
|
50b89ba7d8 | ||
|
|
7224f659b3 | ||
|
|
d4e753ef84 | ||
|
|
31c30cce9d | ||
|
|
2ef20b2937 | ||
|
|
45bebab55d | ||
|
|
7cd2ac1bbd | ||
|
|
00896009cd | ||
|
|
c1faa785b3 | ||
|
|
004674fada | ||
|
|
a58edd9a64 | ||
|
|
f5810bd601 | ||
|
|
6734ff4c7f | ||
|
|
96de08456d | ||
|
|
ad6b5d4087 | ||
|
|
d11650f798 |
1
.github/workflows/collabora.yml
vendored
1
.github/workflows/collabora.yml
vendored
@@ -20,6 +20,7 @@ jobs:
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: collabora-seccomp-update automated change
|
||||
signoff: true
|
||||
title: collabora seccomp update
|
||||
|
||||
10
.github/workflows/dependency-updates.yml
vendored
10
.github/workflows/dependency-updates.yml
vendored
@@ -43,9 +43,19 @@ jobs:
|
||||
| tail -1
|
||||
)"
|
||||
sed -i "s|pecl install APCu.*\;|pecl install APCu-$apcu_version\;|" ./Containers/mastercontainer/Dockerfile
|
||||
|
||||
# CADDY_REMOTE_HOST_HASH
|
||||
CADDY_REMOTE_HOST_HASH="$(
|
||||
git ls-remote https://github.com/muety/caddy-remote-host master \
|
||||
| cut -f1 \
|
||||
| tail -1
|
||||
)"
|
||||
sed -i "s|^ARG CADDY_REMOTE_HOST_HASH.*$|ARG CADDY_REMOTE_HOST_HASH=$CADDY_REMOTE_HOST_HASH|" ./Containers/mastercontainer/Dockerfile
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: php dependency updates
|
||||
signoff: true
|
||||
title: PHP dependency updates
|
||||
|
||||
1
.github/workflows/imaginary-update.yml
vendored
1
.github/workflows/imaginary-update.yml
vendored
@@ -24,6 +24,7 @@ jobs:
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: imaginary-update automated change
|
||||
signoff: true
|
||||
title: Imaginary update
|
||||
|
||||
2
.github/workflows/lint-yaml.yml
vendored
2
.github/workflows/lint-yaml.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
line-length: warning
|
||||
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
|
||||
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7.3.1
|
||||
|
||||
- name: Check GitHub actions
|
||||
run: uvx zizmor --min-severity medium .github/workflows/*.yml
|
||||
|
||||
1
.github/workflows/nextcloud-update.yml
vendored
1
.github/workflows/nextcloud-update.yml
vendored
@@ -81,6 +81,7 @@ jobs:
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: nextcloud-update automated change
|
||||
signoff: true
|
||||
title: Nextcloud dependency update
|
||||
|
||||
4
.github/workflows/playwright-on-push.yml
vendored
4
.github/workflows/playwright-on-push.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
|
||||
with:
|
||||
node-version: lts/*
|
||||
|
||||
@@ -114,7 +114,7 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
name: playwright-report
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
|
||||
with:
|
||||
node-version: lts/*
|
||||
|
||||
@@ -82,7 +82,7 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
if: ${{ !cancelled() }}
|
||||
with:
|
||||
name: playwright-report
|
||||
|
||||
3
.github/workflows/psalm-update-baseline.yml
vendored
3
.github/workflows/psalm-update-baseline.yml
vendored
@@ -18,6 +18,7 @@ jobs:
|
||||
php-version: 8.5
|
||||
extensions: apcu
|
||||
coverage: none
|
||||
ini-file: development
|
||||
|
||||
- name: Run script
|
||||
run: |
|
||||
@@ -32,7 +33,7 @@ jobs:
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
|
||||
with:
|
||||
token: ${{ secrets.COMMAND_BOT_PAT }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: Update psalm baseline
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: nextcloud-command <nextcloud-command@users.noreply.github.com>
|
||||
|
||||
3
.github/workflows/psalm.yml
vendored
3
.github/workflows/psalm.yml
vendored
@@ -43,8 +43,7 @@ jobs:
|
||||
extensions: apcu
|
||||
coverage: none
|
||||
ini-file: development
|
||||
# Temporary workaround for missing pcntl_* in PHP 8.3
|
||||
ini-values: disable_functions=
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
||||
62
.github/workflows/pull-translations.yml
vendored
Normal file
62
.github/workflows/pull-translations.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
name: Pull Translations from Transifex
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Run every day at 02:00 UTC
|
||||
- cron: '0 2 * * *'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
org:
|
||||
description: 'Transifex organisation slug'
|
||||
required: false
|
||||
default: 'nextcloud'
|
||||
project:
|
||||
description: 'Transifex project slug'
|
||||
required: false
|
||||
default: 'nextcloud-all-in-one'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
pull-translations:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install jq
|
||||
run: sudo apt-get install -y jq
|
||||
|
||||
- name: Make pull script executable
|
||||
run: chmod +x php/translations/pull.sh
|
||||
|
||||
- name: Pull translations from Transifex
|
||||
env:
|
||||
TRANSIFEX_TOKEN: ${{ secrets.TRANSIFEX_TOKEN }}
|
||||
TRANSIFEX_ORG: ${{ inputs.org || 'nextcloud' }}
|
||||
TRANSIFEX_PROJECT: ${{ inputs.project || 'nextcloud-all-in-one' }}
|
||||
run: php/translations/pull.sh
|
||||
|
||||
- name: Check for changes
|
||||
id: changes
|
||||
run: |
|
||||
git diff --quiet php/translations/ && echo "changed=false" >> "$GITHUB_OUTPUT" || echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Create Pull Request
|
||||
if: steps.changes.outputs.changed == 'true'
|
||||
uses: peter-evans/create-pull-request@v7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: 'chore(i18n): update translations from Transifex'
|
||||
branch: chore/update-translations
|
||||
delete-branch: true
|
||||
title: 'chore(i18n): update translations from Transifex'
|
||||
body: |
|
||||
Automated pull of the latest translations from Transifex.
|
||||
|
||||
This PR was created automatically by the **Pull Translations** workflow.
|
||||
Please review the changes and merge when ready.
|
||||
labels: translations
|
||||
1
.github/workflows/talk.yml
vendored
1
.github/workflows/talk.yml
vendored
@@ -47,6 +47,7 @@ jobs:
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: talk-update automated change
|
||||
signoff: true
|
||||
title: talk container update
|
||||
|
||||
1
.github/workflows/watchtower-update.yml
vendored
1
.github/workflows/watchtower-update.yml
vendored
@@ -28,6 +28,7 @@ jobs:
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v7
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: watchtower-update automated change
|
||||
signoff: true
|
||||
title: watchtower container update
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
}
|
||||
|
||||
https://{$ADDITIONAL_TRUSTED_DOMAIN}:443,
|
||||
http://{$APACHE_HOST}:23973, # For Collabora callback and WOPI requests, see containers.json
|
||||
http://{$APACHE_HOST}.nextcloud-aio:23973, # For Collabora callback and WOPI requests, see containers.json
|
||||
{$PROTOCOL}://{$NC_DOMAIN}:{$APACHE_PORT} {
|
||||
header -Server
|
||||
header -X-Powered-By
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM caddy:2.11.1-alpine AS caddy
|
||||
FROM caddy:2.11.2-alpine AS caddy
|
||||
|
||||
# From https://github.com/docker-library/httpd/blob/master/2.4/alpine/Dockerfile
|
||||
FROM httpd:2.4.66-alpine3.23
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
# From a file located probably somewhere here: https://github.com/CollaboraOnline/online/blob/master/docker/from-packages/Dockerfile
|
||||
FROM collabora/code:25.04.8.3.1
|
||||
FROM collabora/code:25.04.9.4.1
|
||||
|
||||
USER root
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM haproxy:3.3.4-alpine
|
||||
FROM haproxy:3.3.6-alpine
|
||||
|
||||
# hadolint ignore=DL3002
|
||||
USER root
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
# Probably from here https://github.com/elastic/elasticsearch/blob/main/distribution/docker/src/docker/Dockerfile
|
||||
FROM elasticsearch:8.19.11
|
||||
FROM elasticsearch:8.19.13
|
||||
|
||||
USER root
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM golang:1.26.0-alpine3.23 AS go
|
||||
FROM golang:1.26.1-alpine3.23 AS go
|
||||
|
||||
ENV IMAGINARY_HASH=6a274b488759a896aff02f52afee6e50b5e3a3ee
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
{
|
||||
# auto_https will create redirects for https://{host}:8443 instead of https://{host}
|
||||
# https redirects are added manually in the http://:80 block
|
||||
auto_https disable_redirects
|
||||
|
||||
storage file_system {
|
||||
root /mnt/docker-aio-config/caddy/
|
||||
}
|
||||
|
||||
log {
|
||||
level ERROR
|
||||
}
|
||||
|
||||
servers {
|
||||
protocols h1 h2 h2c
|
||||
}
|
||||
|
||||
on_demand_tls {
|
||||
ask http://127.0.0.1:9876/
|
||||
}
|
||||
}
|
||||
|
||||
http://:80 {
|
||||
redir https://{host}{uri} permanent
|
||||
}
|
||||
|
||||
https://:8443 {
|
||||
|
||||
reverse_proxy 127.0.0.1:8000
|
||||
|
||||
tls {
|
||||
on_demand
|
||||
issuer acme {
|
||||
disable_tlsalpn_challenge
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,17 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
# Docker CLI is a requirement
|
||||
FROM docker:29.2.1-cli AS docker
|
||||
FROM docker:29.3.0-cli AS docker
|
||||
|
||||
ARG CADDY_REMOTE_HOST_HASH=b21775afa730ffb52a24ddff310c8a6d1fd37276
|
||||
|
||||
# Caddy is a requirement
|
||||
FROM caddy:2.11.1-alpine AS caddy
|
||||
FROM caddy:2.11.2-builder-alpine AS caddy
|
||||
RUN set -ex; \
|
||||
xcaddy build --with github.com/muety/caddy-remote-host@"$CADDY_REMOTE_HOST_HASH"; \
|
||||
/usr/bin/caddy list-modules
|
||||
|
||||
# From https://github.com/docker-library/php/blob/master/8.5/alpine3.23/fpm/Dockerfile
|
||||
FROM php:8.5.3-fpm-alpine3.23
|
||||
FROM php:8.5.4-fpm-alpine3.23
|
||||
|
||||
EXPOSE 80
|
||||
EXPOSE 8080
|
||||
@@ -21,9 +26,8 @@ COPY --from=docker /usr/local/bin/docker /usr/local/bin/docker
|
||||
COPY community-containers /var/www/docker-aio/community-containers
|
||||
COPY php /var/www/docker-aio/php
|
||||
COPY --chmod=775 Containers/mastercontainer/*.sh /
|
||||
COPY --chmod=664 Containers/mastercontainer/Caddyfile /Caddyfile
|
||||
COPY --chmod=664 Containers/mastercontainer/*.Caddyfile /
|
||||
COPY --chmod=664 Containers/mastercontainer/supervisord.conf /supervisord.conf
|
||||
COPY Containers/mastercontainer/mastercontainer.conf /etc/apache2/sites-available/mastercontainer.conf
|
||||
|
||||
WORKDIR /var/www/docker-aio
|
||||
|
||||
@@ -37,13 +41,8 @@ RUN set -ex; \
|
||||
apk add --no-cache \
|
||||
util-linux-misc \
|
||||
ca-certificates \
|
||||
wget \
|
||||
bash \
|
||||
apache2 \
|
||||
apache2-proxy \
|
||||
apache2-ssl \
|
||||
supervisor \
|
||||
openssl \
|
||||
sudo \
|
||||
netcat-openbsd \
|
||||
curl \
|
||||
@@ -67,11 +66,12 @@ RUN set -ex; \
|
||||
sed -i 's/^pm = dynamic/pm = ondemand/' /usr/local/etc/php-fpm.d/www.conf; \
|
||||
sed -i 's/^pm.max_children =.*/pm.max_children = 80/' /usr/local/etc/php-fpm.d/www.conf; \
|
||||
sed -i 's|access.log = /proc/self/fd/2|access.log = /proc/self/fd/1|' /usr/local/etc/php-fpm.d/docker.conf; \
|
||||
grep -q ';listen.allowed_clients' /usr/local/etc/php-fpm.d/www.conf; \
|
||||
sed -i 's|;listen.allowed_clients.*|listen.allowed_clients = 127.0.0.1,::1|' /usr/local/etc/php-fpm.d/www.conf; \
|
||||
grep -q '^listen =' /usr/local/etc/php-fpm.d/docker.conf; \
|
||||
sed -i 's|listen =.*|listen = /run/php.sock|' /usr/local/etc/php-fpm.d/docker.conf; \
|
||||
echo "listen.owner = www-data" | tee -a /usr/local/etc/php-fpm.d/docker.conf; \
|
||||
\
|
||||
apk add --no-cache git; \
|
||||
wget https://getcomposer.org/installer -O - | php -- --install-dir=/usr/local/bin --filename=composer; \
|
||||
curl https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer; \
|
||||
chmod +x /usr/local/bin/composer; \
|
||||
cd /var/www/docker-aio; \
|
||||
rm -r ./php/tests; \
|
||||
@@ -86,42 +86,6 @@ RUN set -ex; \
|
||||
rm -r php/data; \
|
||||
rm -r php/session; \
|
||||
\
|
||||
mkdir -p /etc/apache2/certs; \
|
||||
cd /etc/apache2/certs; \
|
||||
openssl req -new -newkey rsa:4096 -days 3650 -nodes -x509 -subj "/C=DE/ST=BE/L=Local/O=Dev/CN=nextcloud.local" -keyout /etc/apache2/certs/ssl.key -out /etc/apache2/certs/ssl.crt; \
|
||||
\
|
||||
sed -i \
|
||||
-e '/^Listen /d' \
|
||||
-e 's/^LogLevel .*/LogLevel error/' \
|
||||
-e 's|^ErrorLog .*|ErrorLog /proc/self/fd/2|' \
|
||||
-e 's/User apache/User www-data/g' \
|
||||
-e 's/Group apache/Group www-data/g' \
|
||||
-e 's/^#\(LoadModule .*mod_rewrite.so\)/\1/' \
|
||||
-e 's/^#\(LoadModule .*mod_headers.so\)/\1/' \
|
||||
-e 's/^#\(LoadModule .*mod_env.so\)/\1/' \
|
||||
-e 's/^#\(LoadModule .*mod_mime.so\)/\1/' \
|
||||
-e 's/^#\(LoadModule .*mod_dir.so\)/\1/' \
|
||||
-e 's/^#\(LoadModule .*mod_authz_core.so\)/\1/' \
|
||||
-e 's/^#\(LoadModule .*mod_mpm_event.so\)/\1/' \
|
||||
-e 's/\(LoadModule .*mod_mpm_worker.so\)/#\1/' \
|
||||
-e 's/\(LoadModule .*mod_mpm_prefork.so\)/#\1/' \
|
||||
-e 's/\(ScriptAlias \)/#\1/' \
|
||||
/etc/apache2/httpd.conf; \
|
||||
mkdir -p /etc/apache2/logs; \
|
||||
rm /etc/apache2/conf.d/ssl.conf; \
|
||||
echo "ServerName localhost" | tee -a /etc/apache2/httpd.conf; \
|
||||
grep -q '^LoadModule lbmethod_heartbeat_module' /etc/apache2/conf.d/proxy.conf; \
|
||||
sed -i 's|^LoadModule lbmethod_heartbeat_module.*|#LoadModule lbmethod_heartbeat_module|' /etc/apache2/conf.d/proxy.conf; \
|
||||
echo "SSLSessionCache nonenotnull" | tee -a /etc/apache2/httpd.conf; \
|
||||
echo "LoadModule ssl_module modules/mod_ssl.so" | tee -a /etc/apache2/httpd.conf; \
|
||||
echo "LoadModule socache_shmcb_module modules/mod_socache_shmcb.so" | tee -a /etc/apache2/httpd.conf; \
|
||||
echo "Include /etc/apache2/sites-available/mastercontainer.conf" | tee -a /etc/apache2/httpd.conf; \
|
||||
\
|
||||
rm -f /etc/apache2/conf.d/default.conf \
|
||||
/etc/apache2/conf.d/userdir.conf \
|
||||
/etc/apache2/conf.d/info.conf; \
|
||||
\
|
||||
rm -rf /var/www/localhost/cgi-bin/; \
|
||||
mkdir /var/log/supervisord; \
|
||||
mkdir /var/run/supervisord;
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ The mastercontainer acts as the central orchestration service for the deployment
|
||||
of all other containers in the Nextcloud All-in-One stack. It hosts:
|
||||
|
||||
- A dedicated PHP SAPI/backend (php-fpm) for AIO itself (not Nextcloud Server)
|
||||
- An Apache service for accessing the AIO interface via a self-signed HTTPS VirtualHost on 8080/tcp
|
||||
- A Caddy reverse proxy service enabling HTTPS access to the AIO frontend on port 8443/tcp.
|
||||
- A Caddy server enabling self-signed HTTPS access to the AIO frontend on port 8080/tcp.
|
||||
- A Caddy server enabling trusted HTTPS access to the AIO frontend on port 8443/tcp.
|
||||
- Caddy will automatically issue a Let's Encrypt issued certificate if port 80 and 8443
|
||||
is open/forwarded and a domain pointer is in place; then, simply open the Nextcloud AIO interface using the
|
||||
domain (`https://your-domain-that-points-to-this-server.tld:8443`). The Let's Encrypt certificate request will
|
||||
|
||||
52
Containers/mastercontainer/acme.Caddyfile
Normal file
52
Containers/mastercontainer/acme.Caddyfile
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
admin off
|
||||
|
||||
# auto_https will create redirects for https://{host}:8443 instead of https://{host}
|
||||
# https redirects are added manually in the http://:80 block
|
||||
auto_https disable_redirects
|
||||
|
||||
storage file_system {
|
||||
root /mnt/docker-aio-config/caddy/
|
||||
}
|
||||
|
||||
log {
|
||||
level ERROR
|
||||
# We need to exclude the remote-host plugin from logging as it would spam the logs
|
||||
# See https://github.com/nextcloud/all-in-one/pull/7006#issuecomment-4003238239
|
||||
exclude http.matchers.remote_host
|
||||
}
|
||||
|
||||
servers {
|
||||
# Only h1 is allowed as we prevent `ERR_NETWORK_CHANGED` from happening
|
||||
protocols h1
|
||||
}
|
||||
|
||||
on_demand_tls {
|
||||
ask http://127.0.0.1:9876/
|
||||
}
|
||||
|
||||
skip_install_trust
|
||||
}
|
||||
|
||||
http://:80 {
|
||||
redir https://{host}{uri} permanent
|
||||
}
|
||||
|
||||
https://:8443 {
|
||||
@denied {
|
||||
path /api/auth/login /api/auth/getlogin
|
||||
remote_host nextcloud-aio-nextcloud
|
||||
}
|
||||
abort @denied
|
||||
|
||||
root * /var/www/docker-aio/php/public
|
||||
php_fastcgi unix//run/php.sock
|
||||
file_server
|
||||
|
||||
tls {
|
||||
on_demand
|
||||
issuer acme {
|
||||
disable_tlsalpn_challenge
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
if [ -f "/mnt/docker-aio-config/data/configuration.json" ]; then
|
||||
nc -z 127.0.0.1 80 || exit 1
|
||||
nc -z 127.0.0.1 8000 || exit 1
|
||||
nc -z 127.0.0.1 8080 || exit 1
|
||||
nc -z 127.0.0.1 8443 || exit 1
|
||||
nc -z 127.0.0.1 9000 || exit 1
|
||||
test -S /run/php.sock || exit 1
|
||||
nc -z 127.0.0.1 9876 || exit 1
|
||||
fi
|
||||
|
||||
38
Containers/mastercontainer/internal.Caddyfile
Normal file
38
Containers/mastercontainer/internal.Caddyfile
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
admin off
|
||||
|
||||
storage file_system {
|
||||
root /mnt/docker-aio-config/caddy/
|
||||
}
|
||||
|
||||
log {
|
||||
level ERROR
|
||||
# We need to exclude the remote-host plugin from logging as it would spam the logs
|
||||
# See https://github.com/nextcloud/all-in-one/pull/7006#issuecomment-4003238239
|
||||
exclude http.matchers.remote_host
|
||||
}
|
||||
|
||||
servers {
|
||||
# Only h1 is allowed as we prevent `ERR_NETWORK_CHANGED` from happening
|
||||
protocols h1
|
||||
}
|
||||
|
||||
skip_install_trust
|
||||
}
|
||||
|
||||
https://:8080 {
|
||||
@denied {
|
||||
path /api/auth/login /api/auth/getlogin
|
||||
remote_host nextcloud-aio-nextcloud
|
||||
}
|
||||
abort @denied
|
||||
|
||||
root * /var/www/docker-aio/php/public
|
||||
php_fastcgi unix//run/php.sock
|
||||
file_server
|
||||
|
||||
tls {
|
||||
on_demand
|
||||
issuer internal
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
Listen 127.0.0.1:8000
|
||||
Listen 8080 https
|
||||
|
||||
# Deny access to .ht files
|
||||
<Files ".ht*">
|
||||
Require all denied
|
||||
</Files>
|
||||
|
||||
# Http host
|
||||
<VirtualHost 127.0.0.1:8000>
|
||||
ServerName 127.0.0.1
|
||||
|
||||
# Add error log
|
||||
CustomLog /proc/self/fd/1 proxy
|
||||
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" proxy
|
||||
ErrorLog /proc/self/fd/2
|
||||
ErrorLogFormat "[%t] [%l] [%E] [client: %{X-Forwarded-For}i] [%M] [%{User-Agent}i]"
|
||||
LogLevel warn
|
||||
|
||||
# PHP match
|
||||
<FilesMatch "\.php$">
|
||||
SetHandler "proxy:fcgi://127.0.0.1:9000"
|
||||
</FilesMatch>
|
||||
|
||||
# Disable output buffering to enable streaming responses.
|
||||
<Proxy "fcgi://127.0.0.1:9000/" flushpackets=on>
|
||||
</Proxy>
|
||||
|
||||
# Master dir
|
||||
DocumentRoot /var/www/docker-aio/php/public/
|
||||
<Directory /var/www/docker-aio/php/public/>
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^ index.php [QSA,L]
|
||||
Options Indexes FollowSymLinks
|
||||
Require all granted
|
||||
AllowOverride All
|
||||
Options FollowSymLinks MultiViews
|
||||
Satisfy Any
|
||||
<IfModule mod_dav.c>
|
||||
Dav off
|
||||
</IfModule>
|
||||
</Directory>
|
||||
</VirtualHost>
|
||||
|
||||
# Https host
|
||||
<VirtualHost *:8080>
|
||||
# Proxy to https
|
||||
ProxyPass / http://127.0.0.1:8000/
|
||||
ProxyPassReverse / http://127.0.0.1:8000/
|
||||
ProxyPreserveHost On
|
||||
# SSL
|
||||
SSLCertificateKeyFile /etc/apache2/certs/ssl.key
|
||||
SSLCertificateFile /etc/apache2/certs/ssl.crt
|
||||
SSLEngine on
|
||||
SSLProtocol -all +TLSv1.2 +TLSv1.3
|
||||
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305
|
||||
SSLHonorCipherOrder off
|
||||
SSLSessionTickets off
|
||||
</VirtualHost>
|
||||
|
||||
# Increase timeout in case e.g. the initial download takes a long time
|
||||
Timeout 7200
|
||||
ProxyTimeout 7200
|
||||
|
||||
# See https://httpd.apache.org/docs/trunk/mod/core.html#traceenable
|
||||
TraceEnable Off
|
||||
@@ -364,7 +364,6 @@ fi
|
||||
mkdir -p /mnt/docker-aio-config/data/
|
||||
mkdir -p /mnt/docker-aio-config/session/
|
||||
mkdir -p /mnt/docker-aio-config/caddy/
|
||||
mkdir -p /mnt/docker-aio-config/certs/
|
||||
|
||||
# Adjust permissions for all instances
|
||||
chmod 770 -R /mnt/docker-aio-config
|
||||
@@ -372,37 +371,6 @@ chmod 777 /mnt/docker-aio-config
|
||||
chown www-data:www-data -R /mnt/docker-aio-config/data/
|
||||
chown www-data:www-data -R /mnt/docker-aio-config/session/
|
||||
chown www-data:www-data -R /mnt/docker-aio-config/caddy/
|
||||
chown root:root -R /mnt/docker-aio-config/certs/
|
||||
|
||||
# Don't allow access to the AIO interface from the Nextcloud container
|
||||
# Probably more cosmetic than anything but at least an attempt
|
||||
if ! grep -q '# nextcloud-aio-block' /etc/apache2/httpd.conf; then
|
||||
cat << APACHE_CONF >> /etc/apache2/httpd.conf
|
||||
# nextcloud-aio-block-start
|
||||
<Location />
|
||||
order allow,deny
|
||||
deny from nextcloud-aio-nextcloud.nextcloud-aio
|
||||
allow from all
|
||||
</Location>
|
||||
# nextcloud-aio-block-end
|
||||
APACHE_CONF
|
||||
fi
|
||||
|
||||
# Adjust certs
|
||||
GENERATED_CERTS="/mnt/docker-aio-config/certs"
|
||||
TMP_CERTS="/etc/apache2/certs"
|
||||
mkdir -p "$GENERATED_CERTS"
|
||||
cd "$GENERATED_CERTS" || exit 1
|
||||
if ! [ -f ./ssl.crt ] && ! [ -f ./ssl.key ]; then
|
||||
openssl req -new -newkey rsa:4096 -days 3650 -nodes -x509 -subj "/C=DE/ST=BE/L=Local/O=Dev/CN=nextcloud.local" -keyout ./ssl.key -out ./ssl.crt
|
||||
fi
|
||||
if [ -f ./ssl.crt ] && [ -f ./ssl.key ]; then
|
||||
cd "$TMP_CERTS" || exit 1
|
||||
rm ./ssl.crt
|
||||
rm ./ssl.key
|
||||
cp "$GENERATED_CERTS/ssl.crt" ./
|
||||
cp "$GENERATED_CERTS/ssl.key" ./
|
||||
fi
|
||||
|
||||
print_green "Initial startup of Nextcloud All-in-One complete!
|
||||
You should be able to open the Nextcloud AIO Interface now on port 8080 of this server!
|
||||
@@ -415,8 +383,11 @@ https://your-domain-that-points-to-this-server.tld:8443"
|
||||
# Set the timezone to Etc/UTC
|
||||
export TZ=Etc/UTC
|
||||
|
||||
# Fix apache startup
|
||||
rm -f /var/run/apache2/httpd.pid
|
||||
# Remove unused certs
|
||||
rm -vrf /mnt/docker-aio-config/certs
|
||||
|
||||
# Remove the php socket as safeguard
|
||||
rm -vf /run/php.sock
|
||||
|
||||
# Fix caddy startup
|
||||
if [ -d "/mnt/docker-aio-config/caddy/locks" ]; then
|
||||
@@ -424,7 +395,8 @@ if [ -d "/mnt/docker-aio-config/caddy/locks" ]; then
|
||||
fi
|
||||
|
||||
# Fix the Caddyfile format
|
||||
caddy fmt --overwrite /Caddyfile
|
||||
caddy fmt --overwrite /acme.Caddyfile
|
||||
caddy fmt --overwrite /internal.Caddyfile
|
||||
|
||||
# Fix caddy log
|
||||
chmod 777 /root
|
||||
|
||||
@@ -16,20 +16,20 @@ stderr_logfile_maxbytes=0
|
||||
command=php-fpm
|
||||
user=root
|
||||
|
||||
[program:apache]
|
||||
# Stdout logging is disabled as otherwise the logs are spammed
|
||||
stdout_logfile=NONE
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
command=httpd -DFOREGROUND
|
||||
user=root
|
||||
|
||||
[program:caddy]
|
||||
[program:caddy-internal]
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
command=/usr/bin/caddy run --config /Caddyfile
|
||||
command=/usr/bin/caddy run --config /internal.Caddyfile
|
||||
user=www-data
|
||||
|
||||
[program:caddy-acme]
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
command=/usr/bin/caddy run --config /acme.Caddyfile
|
||||
user=www-data
|
||||
|
||||
[program:cron]
|
||||
|
||||
@@ -24,6 +24,10 @@ if (getenv('REDIS_MODE') !== 'rediscluster') {
|
||||
if (getenv('REDIS_USER_AUTH')) {
|
||||
$CONFIG['redis']['user'] = str_replace("&auth[]=", "", getenv('REDIS_USER_AUTH'));
|
||||
}
|
||||
|
||||
if (getenv('NEXTCLOUD_TRUSTED_CERTIFICATES_REDIS')) {
|
||||
$CONFIG['redis']['ssl_context']['cafile'] = '/var/www/html/data/certificates/ca-bundle.crt';
|
||||
}
|
||||
} else {
|
||||
$CONFIG = array(
|
||||
'memcache.distributed' => '\OC\Memcache\Redis',
|
||||
@@ -53,4 +57,8 @@ if (getenv('REDIS_MODE') !== 'rediscluster') {
|
||||
if (getenv('REDIS_USER_AUTH')) {
|
||||
$CONFIG['redis.cluster']['user'] = str_replace("&auth[]=", "", getenv('REDIS_USER_AUTH'));
|
||||
}
|
||||
|
||||
if (getenv('NEXTCLOUD_TRUSTED_CERTIFICATES_REDIS')) {
|
||||
$CONFIG['redis.cluster']['ssl_context']['cafile'] = '/var/www/html/data/certificates/ca-bundle.crt';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,3 +3,4 @@
|
||||
/custom_apps/
|
||||
/themes/
|
||||
/version.php
|
||||
/lost+found
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
# From https://github.com/ONLYOFFICE/Docker-DocumentServer/blob/master/Dockerfile
|
||||
FROM onlyoffice/documentserver:9.3.0.1
|
||||
FROM onlyoffice/documentserver:9.3.1.2
|
||||
|
||||
# USER root is probably used
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
# From https://github.com/docker-library/postgres/blob/master/17/alpine3.23/Dockerfile
|
||||
FROM postgres:17.8-alpine
|
||||
FROM postgres:17.9-alpine
|
||||
|
||||
COPY --chmod=775 start.sh /start.sh
|
||||
COPY --chmod=775 healthcheck.sh /healthcheck.sh
|
||||
|
||||
@@ -20,6 +20,9 @@ RUN set -ex; \
|
||||
xvfb \
|
||||
ffmpeg \
|
||||
firefox \
|
||||
font-noto-all \
|
||||
font-noto-cjk \
|
||||
font-noto-cjk-extra \
|
||||
bind-tools \
|
||||
netcat-openbsd \
|
||||
git \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM nats:2.12.4-scratch AS nats
|
||||
FROM nats:2.12.5-scratch AS nats
|
||||
FROM eturnal/eturnal:1.12.2-alpine AS eturnal
|
||||
FROM strukturag/nextcloud-spreed-signaling:2.1.0 AS signaling
|
||||
FROM strukturag/nextcloud-spreed-signaling:2.1.1 AS signaling
|
||||
FROM alpine:3.23.3 AS janus
|
||||
|
||||
ARG JANUS_VERSION=v1.4.0
|
||||
@@ -70,7 +70,8 @@ RUN set -ex; \
|
||||
libwebsockets \
|
||||
\
|
||||
shadow \
|
||||
grep; \
|
||||
grep \
|
||||
util-linux-misc; \
|
||||
useradd --system -u 1000 eturnal; \
|
||||
apk del --no-cache \
|
||||
shadow; \
|
||||
|
||||
@@ -18,6 +18,22 @@ elif [ -z "$INTERNAL_SECRET" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Trust additional CA certificates, if the user provided NEXTCLOUD_TRUSTED_CACERTS_DIR
|
||||
# The container is read-only, so we build a custom bundle in /tmp (tmpfs) and
|
||||
# point Go's TLS stack to it via SSL_CERT_FILE.
|
||||
if mountpoint -q /usr/local/share/ca-certificates; then
|
||||
echo "Trusting additional CA certificates..."
|
||||
set -x
|
||||
cp /etc/ssl/certs/ca-certificates.crt /tmp/ca-certificates.crt
|
||||
for cert in /usr/local/share/ca-certificates/*; do
|
||||
if [ -f "$cert" ]; then
|
||||
cat "$cert" >> /tmp/ca-certificates.crt
|
||||
fi
|
||||
done
|
||||
export SSL_CERT_FILE=/tmp/ca-certificates.crt
|
||||
set +x
|
||||
fi
|
||||
|
||||
set -x
|
||||
IPv4_ADDRESS_TALK_RELAY="$(hostname -i | grep -oP '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | head -1)"
|
||||
# shellcheck disable=SC2153
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM golang:1.26.0-alpine3.23 AS go
|
||||
FROM golang:1.26.1-alpine3.23 AS go
|
||||
|
||||
ENV WATCHTOWER_COMMIT_HASH=943098a670cb78a620af6499fb94b3ee2c940cf0
|
||||
ENV WATCHTOWER_COMMIT_HASH=5a33e3c0aa3b2770c648a114b4a9d32e0a5b55ba
|
||||
|
||||
RUN set -ex; \
|
||||
apk upgrade --no-cache -a; \
|
||||
apk add --no-cache \
|
||||
build-base; \
|
||||
go install github.com/nicholas-fedor/watchtower@$WATCHTOWER_COMMIT_HASH # v1.14.2
|
||||
go install github.com/nicholas-fedor/watchtower@$WATCHTOWER_COMMIT_HASH # v1.14.4
|
||||
|
||||
FROM alpine:3.23.3
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
# Probably from this file: https://github.com/nextcloud/whiteboard/blob/main/Dockerfile
|
||||
FROM ghcr.io/nextcloud-releases/whiteboard:v1.5.6
|
||||
FROM ghcr.io/nextcloud-releases/whiteboard:v1.5.7
|
||||
|
||||
USER root
|
||||
RUN set -ex; \
|
||||
|
||||
38
community-containers/glances/glances.json
Normal file
38
community-containers/glances/glances.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"aio_services_v1": [
|
||||
{
|
||||
"container_name": "nextcloud-aio-glances",
|
||||
"display_name": "Glances",
|
||||
"documentation": "https://github.com/nextcloud/all-in-one/tree/main/community-containers/glances",
|
||||
"image": "nicolargo/glances",
|
||||
"image_tag": "latest-full",
|
||||
"internal_port": "61208",
|
||||
"restart": "unless-stopped",
|
||||
"ports": [
|
||||
{
|
||||
"ip_binding": "",
|
||||
"port_number": "61208",
|
||||
"protocol": "tcp"
|
||||
}
|
||||
],
|
||||
"volumes": [
|
||||
{
|
||||
"source": "nextcloud_aio_glances",
|
||||
"destination": "/etc/glances",
|
||||
"writeable": true
|
||||
},
|
||||
{
|
||||
"source": "%WATCHTOWER_DOCKER_SOCKET_PATH%",
|
||||
"destination": "/var/run/docker.sock",
|
||||
"writeable": false
|
||||
}
|
||||
],
|
||||
"environment": [
|
||||
"GLANCES_OPT=-w"
|
||||
],
|
||||
"backup_volumes": [
|
||||
"nextcloud_aio_glances"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
18
community-containers/glances/readme.md
Normal file
18
community-containers/glances/readme.md
Normal file
@@ -0,0 +1,18 @@
|
||||
## Glances
|
||||
This container starts Glances, a web-based info-board, and auto-configures it for you.
|
||||
|
||||
> [!CAUTION]
|
||||
> This container mounts the docker-socket from the host-system.
|
||||
|
||||
### Notes
|
||||
- After adding and starting the container, you can directly visit http://ip.address.of.server:61208/ and access your new Glances instance!
|
||||
- It is recommended to start this container only in home networks, because there is no built-in authentication. But you can do a http-auth with your proxy.
|
||||
- In order to access your Glances outside the local network, you have to set up your own reverse proxy. You can set up a reverse proxy following [these instructions](https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md).
|
||||
- The data of Glances will be automatically included in AIO's backup solution!
|
||||
- See [here](https://github.com/nextcloud/all-in-one/tree/main/community-containers#community-containers) how to add it to the AIO stack.
|
||||
|
||||
### Repository
|
||||
https://github.com/nicolargo/glances
|
||||
|
||||
### Maintainer
|
||||
https://github.com/pi-farm
|
||||
@@ -2,6 +2,7 @@
|
||||
This container bundles Seerr and auto-configures it for you.
|
||||
|
||||
### Notes
|
||||
- **Migration from Jellyseerr**: Jellyseer previously ran as the root user. With the migration to Seerr, the container now runs rootless with userid 1000, meaning that if you previously used Jellyseerr, Seerr will not be able to access the config files generated by the old Jellyseerr container. To migrate, execute the following steps: 1. stop all containers using the AIO-interface, 2. run `sudo docker run --rm -v nextcloud_aio_jellyseerr:/data alpine chown -R 1000:1000 /data`
|
||||
- This container is only intended to be used inside home networks as it uses http for its management page by default.
|
||||
- After adding and starting the container, you can directly visit `http://ip.address.of.server:5055` and access your new Seerr instance, which can be used to manage Plex, Jellyfin, and Emby.
|
||||
- In order to access your Seerr outside the local network, you have to set up your own reverse proxy. You can set up a reverse proxy following [these instructions](https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md) and [Seerr's reverse proxy documentation.](https://docs.seerr.dev/extending-Seerr/reverse-proxy), OR use the Caddy community container that will automatically configure requests.$NC_DOMAIN to redirect to your Seerr. Note that it is recommended to [enable CSRF protection in Seerr](https://docs.seerr.dev/using-Seerr/settings/general#enable-csrf-protection) for added security if you plan to use Seerr outside the local network, but make sure to read up on it and understand the caveats first.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
## LanguageTool for Collabora
|
||||
This container bundles a LanguageTool for Collabora which adds spell checking functionality to Collabora.
|
||||
## LanguageTool for Nextcloud Office
|
||||
This container bundles a LanguageTool for Nextcloud Office which adds spell checking functionality to Nextcloud Office.
|
||||
|
||||
### Notes
|
||||
- Make sure to have collabora enabled via the AIO interface
|
||||
- After adding this container via the AIO Interface, while all containers are still stopped, you need to scroll down to the `Additional Collabora options` section and enter `--o:languagetool.enabled=true --o:languagetool.base_url=http://nextcloud-aio-languagetool:8010/v2`.
|
||||
- Make sure to have Nextcloud Office enabled via the AIO interface
|
||||
- After adding this container via the AIO Interface, while all containers are still stopped, you need to scroll down to the `Additional Nextcloud Office options` section and enter `--o:languagetool.enabled=true --o:languagetool.base_url=http://nextcloud-aio-languagetool:8010/v2`.
|
||||
- See https://github.com/nextcloud/all-in-one/tree/main/community-containers#community-containers how to add it to the AIO stack
|
||||
|
||||
### Repository
|
||||
|
||||
@@ -11,9 +11,9 @@ services:
|
||||
network_mode: bridge # This adds the container to the same network as docker run would do. Comment this line and uncomment the line below and the networks section at the end of the file if you want to define a custom MTU size for the docker network
|
||||
# networks: ["nextcloud-aio"]
|
||||
ports:
|
||||
- 80:80 # Can be removed when running behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else). See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
|
||||
- 8080:8080 # This is the AIO interface, served via https and self-signed certificate. See https://github.com/nextcloud/all-in-one#explanation-of-used-ports
|
||||
- 8443:8443 # Can be removed when running behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else). See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
|
||||
- "80:80" # Can be removed when running behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else). See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
|
||||
- "8080:8080" # This is the AIO interface, served via https and self-signed certificate. See https://github.com/nextcloud/all-in-one#explanation-of-used-ports
|
||||
- "8443:8443" # Can be removed when running behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else). See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
|
||||
# security_opt: ["label:disable"] # Is needed when using SELinux. See https://github.com/nextcloud/all-in-one#are-there-known-problems-when-selinux-is-enabled
|
||||
# environment: # Is needed when using any of the options below
|
||||
# AIO_DISABLE_BACKUP_SECTION: false # Setting this to true allows to hide the backup section in the AIO interface. See https://github.com/nextcloud/all-in-one#how-to-disable-the-backup-section
|
||||
|
||||
@@ -45,6 +45,7 @@ services:
|
||||
- APACHE_MAX_TIME=${NEXTCLOUD_MAX_TIME}
|
||||
- NOTIFY_PUSH_HOST=nextcloud-aio-notify-push
|
||||
- WHITEBOARD_HOST=nextcloud-aio-whiteboard
|
||||
- HARP_HOST=nextcloud-aio-harp
|
||||
volumes:
|
||||
- nextcloud_aio_nextcloud:/var/www/html:ro
|
||||
- nextcloud_aio_apache:/mnt/data:rw
|
||||
@@ -202,19 +203,10 @@ services:
|
||||
expose:
|
||||
- "7867"
|
||||
volumes:
|
||||
- nextcloud_aio_nextcloud:/nextcloud:ro
|
||||
- nextcloud_aio_nextcloud:/var/www/html:ro
|
||||
environment:
|
||||
- NC_DOMAIN
|
||||
- NEXTCLOUD_HOST=nextcloud-aio-nextcloud
|
||||
- TZ=${TIMEZONE}
|
||||
- REDIS_HOST=nextcloud-aio-redis
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_HOST_PASSWORD=${REDIS_PASSWORD}
|
||||
- POSTGRES_HOST=nextcloud-aio-database
|
||||
- POSTGRES_PORT=5432
|
||||
- POSTGRES_PASSWORD=${DATABASE_PASSWORD}
|
||||
- POSTGRES_DB=nextcloud_database
|
||||
- POSTGRES_USER=nextcloud
|
||||
restart: unless-stopped
|
||||
read_only: true
|
||||
cap_drop:
|
||||
|
||||
@@ -180,6 +180,7 @@ apt install --no-install-recommends qemu-system qemu-utils libvirt-clients libvi
|
||||
# Virtual machine #1 - "example1-com"
|
||||
https://[DOMAIN_NAME_1]:8443 {
|
||||
reverse_proxy https://[IP_ADDRESS_1]:8080 {
|
||||
header_up Host {host}
|
||||
transport http {
|
||||
tls_insecure_skip_verify
|
||||
}
|
||||
@@ -192,6 +193,7 @@ apt install --no-install-recommends qemu-system qemu-utils libvirt-clients libvi
|
||||
# Virtual machine #2 - "example2-com"
|
||||
https://[DOMAIN_NAME_2]:8443 {
|
||||
reverse_proxy https://[IP_ADDRESS_2]:8080 {
|
||||
header_up Host {host}
|
||||
transport http {
|
||||
tls_insecure_skip_verify
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: nextcloud-aio-helm-chart
|
||||
description: A generated Helm Chart for Nextcloud AIO from Skippbox Kompose
|
||||
version: 12.7.0
|
||||
version: 12.8.0
|
||||
apiVersion: v2
|
||||
keywords:
|
||||
- latest
|
||||
|
||||
@@ -63,7 +63,7 @@ spec:
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
- name: WHITEBOARD_HOST
|
||||
value: nextcloud-aio-whiteboard
|
||||
image: ghcr.io/nextcloud-releases/aio-apache:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-apache:20260306_081319
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -36,7 +36,7 @@ spec:
|
||||
{{- end }}
|
||||
initContainers:
|
||||
- name: init-subpath
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260306_081319
|
||||
command:
|
||||
- mkdir
|
||||
- "-p"
|
||||
@@ -59,7 +59,7 @@ spec:
|
||||
value: "{{ .Values.NEXTCLOUD_UPLOAD_LIMIT }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-clamav:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-clamav:20260306_081319
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -36,9 +36,9 @@ spec:
|
||||
- name: server_name
|
||||
value: "{{ .Values.NC_DOMAIN }}"
|
||||
{{- if contains "--o:support_key=" (join " " (.Values.ADDITIONAL_COLLABORA_OPTIONS | default list)) }}
|
||||
image: ghcr.io/nextcloud-releases/aio-collabora-online:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-collabora-online:20260306_081319
|
||||
{{- else }}
|
||||
image: ghcr.io/nextcloud-releases/aio-collabora:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-collabora:20260306_081319
|
||||
{{- end }}
|
||||
readinessProbe:
|
||||
exec:
|
||||
|
||||
@@ -35,7 +35,7 @@ spec:
|
||||
{{- end }}
|
||||
initContainers:
|
||||
- name: init-subpath
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260306_081319
|
||||
command:
|
||||
- mkdir
|
||||
- "-p"
|
||||
@@ -64,7 +64,7 @@ spec:
|
||||
value: nextcloud
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-postgresql:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-postgresql:20260306_081319
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -24,7 +24,7 @@ spec:
|
||||
spec:
|
||||
initContainers:
|
||||
- name: init-volumes
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260306_081319
|
||||
command:
|
||||
- chmod
|
||||
- "777"
|
||||
@@ -54,7 +54,7 @@ spec:
|
||||
value: basic
|
||||
- name: xpack.security.enabled
|
||||
value: "false"
|
||||
image: ghcr.io/nextcloud-releases/aio-fulltextsearch:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-fulltextsearch:20260306_081319
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -38,7 +38,7 @@ spec:
|
||||
value: "{{ .Values.IMAGINARY_SECRET }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-imaginary:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-imaginary:20260306_081319
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -38,7 +38,7 @@ spec:
|
||||
# AIO settings start # Do not remove or change this line!
|
||||
initContainers:
|
||||
- name: init-volumes
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260306_081319
|
||||
command:
|
||||
- chmod
|
||||
- "777"
|
||||
@@ -190,7 +190,7 @@ spec:
|
||||
value: "{{ .Values.WHITEBOARD_ENABLED }}"
|
||||
- name: WHITEBOARD_SECRET
|
||||
value: "{{ .Values.WHITEBOARD_SECRET }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-nextcloud:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-nextcloud:20260306_081319
|
||||
{{- if eq (.Values.RPSS_ENABLED | default "no") "yes" }} # AIO-config - do not change this comment!
|
||||
securityContext:
|
||||
# The items below only work in container context
|
||||
|
||||
@@ -39,7 +39,7 @@ spec:
|
||||
value: nextcloud-aio-nextcloud
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-notify-push:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-notify-push:20260306_081319
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -24,7 +24,7 @@ spec:
|
||||
spec:
|
||||
initContainers:
|
||||
- name: init-volumes
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-alpine:20260306_081319
|
||||
command:
|
||||
- chmod
|
||||
- "777"
|
||||
@@ -42,7 +42,7 @@ spec:
|
||||
value: "{{ .Values.ONLYOFFICE_SECRET }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-onlyoffice:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-onlyoffice:20260306_081319
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -39,7 +39,7 @@ spec:
|
||||
value: "{{ .Values.REDIS_PASSWORD }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-redis:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-redis:20260306_081319
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -52,7 +52,7 @@ spec:
|
||||
value: "{{ .Values.TURN_SECRET }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-talk:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-talk:20260306_081319
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -44,7 +44,7 @@ spec:
|
||||
value: "{{ .Values.RECORDING_SECRET }}"
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-talk-recording:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-talk-recording:20260306_081319
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
@@ -50,7 +50,7 @@ spec:
|
||||
value: redis
|
||||
- name: TZ
|
||||
value: "{{ .Values.TIMEZONE }}"
|
||||
image: ghcr.io/nextcloud-releases/aio-whiteboard:20260218_123804
|
||||
image: ghcr.io/nextcloud-releases/aio-whiteboard:20260306_081319
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
|
||||
136
php/composer.lock
generated
136
php/composer.lock
generated
@@ -273,16 +273,16 @@
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
"version": "2.8.0",
|
||||
"version": "2.9.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/psr7.git",
|
||||
"reference": "21dc724a0583619cd1652f673303492272778051"
|
||||
"reference": "7d0ed42f28e42d61352a7a79de682e5e67fec884"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051",
|
||||
"reference": "21dc724a0583619cd1652f673303492272778051",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/7d0ed42f28e42d61352a7a79de682e5e67fec884",
|
||||
"reference": "7d0ed42f28e42d61352a7a79de682e5e67fec884",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -298,6 +298,7 @@
|
||||
"require-dev": {
|
||||
"bamarni/composer-bin-plugin": "^1.8.2",
|
||||
"http-interop/http-factory-tests": "0.9.0",
|
||||
"jshttp/mime-db": "1.54.0.1",
|
||||
"phpunit/phpunit": "^8.5.44 || ^9.6.25"
|
||||
},
|
||||
"suggest": {
|
||||
@@ -369,7 +370,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/psr7/issues",
|
||||
"source": "https://github.com/guzzle/psr7/tree/2.8.0"
|
||||
"source": "https://github.com/guzzle/psr7/tree/2.9.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -385,7 +386,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-08-23T21:21:41+00:00"
|
||||
"time": "2026-03-10T16:41:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "http-interop/http-factory-guzzle",
|
||||
@@ -1779,16 +1780,16 @@
|
||||
},
|
||||
{
|
||||
"name": "twig/twig",
|
||||
"version": "v3.23.0",
|
||||
"version": "v3.24.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/Twig.git",
|
||||
"reference": "a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9"
|
||||
"reference": "a6769aefb305efef849dc25c9fd1653358c148f0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9",
|
||||
"reference": "a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/a6769aefb305efef849dc25c9fd1653358c148f0",
|
||||
"reference": "a6769aefb305efef849dc25c9fd1653358c148f0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1798,7 +1799,8 @@
|
||||
"symfony/polyfill-mbstring": "^1.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"php-cs-fixer/shim": "^3.0@stable",
|
||||
"phpstan/phpstan": "^2.0@stable",
|
||||
"psr/container": "^1.0|^2.0",
|
||||
"symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0"
|
||||
},
|
||||
@@ -1842,7 +1844,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/twigphp/Twig/issues",
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.23.0"
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.24.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1854,7 +1856,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-01-23T21:00:41+00:00"
|
||||
"time": "2026-03-17T21:31:11+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
@@ -3246,20 +3248,20 @@
|
||||
},
|
||||
{
|
||||
"name": "league/uri",
|
||||
"version": "7.8.0",
|
||||
"version": "7.8.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/uri.git",
|
||||
"reference": "4436c6ec8d458e4244448b069cc572d088230b76"
|
||||
"reference": "08cf38e3924d4f56238125547b5720496fac8fd4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri/zipball/4436c6ec8d458e4244448b069cc572d088230b76",
|
||||
"reference": "4436c6ec8d458e4244448b069cc572d088230b76",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri/zipball/08cf38e3924d4f56238125547b5720496fac8fd4",
|
||||
"reference": "08cf38e3924d4f56238125547b5720496fac8fd4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"league/uri-interfaces": "^7.8",
|
||||
"league/uri-interfaces": "^7.8.1",
|
||||
"php": "^8.1",
|
||||
"psr/http-factory": "^1"
|
||||
},
|
||||
@@ -3332,7 +3334,7 @@
|
||||
"docs": "https://uri.thephpleague.com",
|
||||
"forum": "https://thephpleague.slack.com",
|
||||
"issues": "https://github.com/thephpleague/uri-src/issues",
|
||||
"source": "https://github.com/thephpleague/uri/tree/7.8.0"
|
||||
"source": "https://github.com/thephpleague/uri/tree/7.8.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3340,20 +3342,20 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-01-14T17:24:56+00:00"
|
||||
"time": "2026-03-15T20:22:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/uri-interfaces",
|
||||
"version": "7.8.0",
|
||||
"version": "7.8.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/uri-interfaces.git",
|
||||
"reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4"
|
||||
"reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/c5c5cd056110fc8afaba29fa6b72a43ced42acd4",
|
||||
"reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4",
|
||||
"url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/85d5c77c5d6d3af6c54db4a78246364908f3c928",
|
||||
"reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3416,7 +3418,7 @@
|
||||
"docs": "https://uri.thephpleague.com",
|
||||
"forum": "https://thephpleague.slack.com",
|
||||
"issues": "https://github.com/thephpleague/uri-src/issues",
|
||||
"source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.0"
|
||||
"source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3424,7 +3426,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-01-15T06:54:53+00:00"
|
||||
"time": "2026-03-08T20:05:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "netresearch/jsonmapper",
|
||||
@@ -3590,16 +3592,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-docblock",
|
||||
"version": "6.0.1",
|
||||
"version": "6.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
|
||||
"reference": "2f5cbed597cb261d1ea458f3da3a9ad32e670b1e"
|
||||
"reference": "7bae67520aa9f5ecc506d646810bd40d9da54582"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/2f5cbed597cb261d1ea458f3da3a9ad32e670b1e",
|
||||
"reference": "2f5cbed597cb261d1ea458f3da3a9ad32e670b1e",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/7bae67520aa9f5ecc506d646810bd40d9da54582",
|
||||
"reference": "7bae67520aa9f5ecc506d646810bd40d9da54582",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3649,9 +3651,9 @@
|
||||
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
|
||||
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/6.0.1"
|
||||
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/6.0.3"
|
||||
},
|
||||
"time": "2026-01-20T15:30:42+00:00"
|
||||
"time": "2026-03-18T20:49:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/type-resolver",
|
||||
@@ -4037,16 +4039,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v6.4.32",
|
||||
"version": "v6.4.35",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "0bc2199c6c1f05276b05956f1ddc63f6d7eb5fc3"
|
||||
"reference": "49257c96304c508223815ee965c251e7c79e614e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/0bc2199c6c1f05276b05956f1ddc63f6d7eb5fc3",
|
||||
"reference": "0bc2199c6c1f05276b05956f1ddc63f6d7eb5fc3",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/49257c96304c508223815ee965c251e7c79e614e",
|
||||
"reference": "49257c96304c508223815ee965c251e7c79e614e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4111,7 +4113,7 @@
|
||||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v6.4.32"
|
||||
"source": "https://github.com/symfony/console/tree/v6.4.35"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4131,20 +4133,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-01-13T08:45:59+00:00"
|
||||
"time": "2026-03-06T13:31:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v8.0.1",
|
||||
"version": "v8.0.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "d937d400b980523dc9ee946bb69972b5e619058d"
|
||||
"reference": "7bf9162d7a0dff98d079b72948508fa48018a770"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/d937d400b980523dc9ee946bb69972b5e619058d",
|
||||
"reference": "d937d400b980523dc9ee946bb69972b5e619058d",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/7bf9162d7a0dff98d079b72948508fa48018a770",
|
||||
"reference": "7bf9162d7a0dff98d079b72948508fa48018a770",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4181,7 +4183,7 @@
|
||||
"description": "Provides basic utilities for the filesystem",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/filesystem/tree/v8.0.1"
|
||||
"source": "https://github.com/symfony/filesystem/tree/v8.0.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4201,20 +4203,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-12-01T09:13:36+00:00"
|
||||
"time": "2026-02-25T16:59:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v6.4.33",
|
||||
"version": "v6.4.34",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/finder.git",
|
||||
"reference": "24965ca011dac87431729640feef8bcf7b5523e0"
|
||||
"reference": "9590e86be1d1c57bfbb16d0dd040345378c20896"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/24965ca011dac87431729640feef8bcf7b5523e0",
|
||||
"reference": "24965ca011dac87431729640feef8bcf7b5523e0",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/9590e86be1d1c57bfbb16d0dd040345378c20896",
|
||||
"reference": "9590e86be1d1c57bfbb16d0dd040345378c20896",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4249,7 +4251,7 @@
|
||||
"description": "Finds files and directories via an intuitive fluent interface",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/finder/tree/v6.4.33"
|
||||
"source": "https://github.com/symfony/finder/tree/v6.4.34"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4269,7 +4271,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-01-26T13:03:48+00:00"
|
||||
"time": "2026-01-28T15:16:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-grapheme",
|
||||
@@ -4607,16 +4609,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
"version": "v7.4.4",
|
||||
"version": "v7.4.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/string.git",
|
||||
"reference": "1c4b10461bf2ec27537b5f36105337262f5f5d6f"
|
||||
"reference": "9f209231affa85aa930a5e46e6eb03381424b30b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/1c4b10461bf2ec27537b5f36105337262f5f5d6f",
|
||||
"reference": "1c4b10461bf2ec27537b5f36105337262f5f5d6f",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/9f209231affa85aa930a5e46e6eb03381424b30b",
|
||||
"reference": "9f209231affa85aa930a5e46e6eb03381424b30b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4674,7 +4676,7 @@
|
||||
"utf8"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/string/tree/v7.4.4"
|
||||
"source": "https://github.com/symfony/string/tree/v7.4.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4694,20 +4696,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-01-12T10:54:30+00:00"
|
||||
"time": "2026-02-09T09:33:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "vimeo/psalm",
|
||||
"version": "6.15.1",
|
||||
"version": "6.16.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vimeo/psalm.git",
|
||||
"reference": "28dc127af1b5aecd52314f6f645bafc10d0e11f9"
|
||||
"reference": "f1f5de594dc76faf8784e02d3dc4716c91c6f6ac"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/vimeo/psalm/zipball/28dc127af1b5aecd52314f6f645bafc10d0e11f9",
|
||||
"reference": "28dc127af1b5aecd52314f6f645bafc10d0e11f9",
|
||||
"url": "https://api.github.com/repos/vimeo/psalm/zipball/f1f5de594dc76faf8784e02d3dc4716c91c6f6ac",
|
||||
"reference": "f1f5de594dc76faf8784e02d3dc4716c91c6f6ac",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4812,7 +4814,7 @@
|
||||
"issues": "https://github.com/vimeo/psalm/issues",
|
||||
"source": "https://github.com/vimeo/psalm"
|
||||
},
|
||||
"time": "2026-02-07T19:27:16+00:00"
|
||||
"time": "2026-03-19T10:56:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "wapmorgan/php-deprecation-detector",
|
||||
@@ -4883,16 +4885,16 @@
|
||||
},
|
||||
{
|
||||
"name": "webmozart/assert",
|
||||
"version": "2.1.5",
|
||||
"version": "2.1.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/webmozarts/assert.git",
|
||||
"reference": "79155f94852fa27e2f73b459f6503f5e87e2c188"
|
||||
"reference": "ff31ad6efc62e66e518fbab1cde3453d389bcdc8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/webmozarts/assert/zipball/79155f94852fa27e2f73b459f6503f5e87e2c188",
|
||||
"reference": "79155f94852fa27e2f73b459f6503f5e87e2c188",
|
||||
"url": "https://api.github.com/repos/webmozarts/assert/zipball/ff31ad6efc62e66e518fbab1cde3453d389bcdc8",
|
||||
"reference": "ff31ad6efc62e66e518fbab1cde3453d389bcdc8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4939,9 +4941,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/webmozarts/assert/issues",
|
||||
"source": "https://github.com/webmozarts/assert/tree/2.1.5"
|
||||
"source": "https://github.com/webmozarts/assert/tree/2.1.6"
|
||||
},
|
||||
"time": "2026-02-18T14:09:36+00:00"
|
||||
"time": "2026-02-27T10:28:38+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
|
||||
@@ -49,6 +49,9 @@
|
||||
"type": "string",
|
||||
"pattern": "^[()A-Za-z &0-9-]+$"
|
||||
},
|
||||
"hide_from_list": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"environment": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
@@ -229,4 +232,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,8 +379,8 @@
|
||||
],
|
||||
"internal_port": "9980",
|
||||
"environment": [
|
||||
"aliasgroup1=https://%NC_DOMAIN%:443,http://nextcloud-aio-apache:23973",
|
||||
"extra_params=--o:ssl.enable=false --o:ssl.termination=true --o:logging.disable_server_audit=true --o:logging.level=warning --o:logging.level_startup=warning --o:welcome.enable=false %COLLABORA_SECCOMP_POLICY% --o:remote_font_config.url=https://%NC_DOMAIN%/apps/richdocuments/settings/fonts.json --o:net.post_allow.host[0]=.+",
|
||||
"aliasgroup1=https://%NC_DOMAIN%:443,http://nextcloud-aio-apache.nextcloud-aio:23973",
|
||||
"extra_params=--o:ssl.enable=false --o:ssl.termination=true --o:logging.disable_server_audit=true --o:logging.level=warning --o:logging.level_startup=warning --o:welcome.enable=false --o:fetch_update_check=0 --o:allow_update_popup=false %COLLABORA_SECCOMP_POLICY% --o:remote_font_config.url=https://%NC_DOMAIN%/apps/richdocuments/settings/fonts.json --o:net.post_allow.host[0]=.+",
|
||||
"dictionaries=%COLLABORA_DICTIONARIES%",
|
||||
"TZ=%TIMEZONE%",
|
||||
"server_name=%NC_DOMAIN%",
|
||||
@@ -389,13 +389,12 @@
|
||||
"restart": "unless-stopped",
|
||||
"nextcloud_exec_commands": [
|
||||
"echo 'Activating Collabora config...'",
|
||||
"php /var/www/html/occ richdocuments:activate-config --wopi-url='http://nextcloud-aio-apache:23973' --callback-url='http://nextcloud-aio-apache:23973'"
|
||||
"php /var/www/html/occ richdocuments:activate-config --wopi-url='http://nextcloud-aio-apache.nextcloud-aio:23973' --callback-url='http://nextcloud-aio-apache.nextcloud-aio:23973'"
|
||||
],
|
||||
"profiles": [
|
||||
"collabora"
|
||||
],
|
||||
"cap_add": [
|
||||
"MKNOD",
|
||||
"SYS_ADMIN",
|
||||
"SYS_CHROOT",
|
||||
"FOWNER",
|
||||
@@ -437,6 +436,13 @@
|
||||
"8081"
|
||||
],
|
||||
"internal_port": "%TALK_PORT%",
|
||||
"volumes": [
|
||||
{
|
||||
"source": "%NEXTCLOUD_TRUSTED_CACERTS_DIR%",
|
||||
"destination": "/usr/local/share/ca-certificates",
|
||||
"writeable": false
|
||||
}
|
||||
],
|
||||
"environment": [
|
||||
"NC_DOMAIN=%NC_DOMAIN%",
|
||||
"TALK_HOST=nextcloud-aio-talk",
|
||||
@@ -523,6 +529,8 @@
|
||||
},
|
||||
{
|
||||
"container_name": "nextcloud-aio-borgbackup",
|
||||
"display_name": "Borgbackup",
|
||||
"hide_from_list": true,
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-borgbackup",
|
||||
"init": true,
|
||||
@@ -591,6 +599,8 @@
|
||||
},
|
||||
{
|
||||
"container_name": "nextcloud-aio-watchtower",
|
||||
"display_name": "Watchtower",
|
||||
"hide_from_list": true,
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-watchtower",
|
||||
"init": true,
|
||||
@@ -611,6 +621,8 @@
|
||||
},
|
||||
{
|
||||
"container_name": "nextcloud-aio-domaincheck",
|
||||
"display_name": "Domaincheck",
|
||||
"hide_from_list": true,
|
||||
"image_tag": "%AIO_CHANNEL%",
|
||||
"image": "ghcr.io/nextcloud-releases/aio-domaincheck",
|
||||
"init": true,
|
||||
|
||||
@@ -7,15 +7,15 @@ if (isset($_GET['domain']) && is_string($_GET['domain'])) {
|
||||
}
|
||||
|
||||
if (!str_contains($domain, '.')) {
|
||||
http_response_code(400);
|
||||
http_response_code(400);
|
||||
} elseif (str_contains($domain, '/')) {
|
||||
http_response_code(400);
|
||||
http_response_code(400);
|
||||
} elseif (str_contains($domain, ':')) {
|
||||
http_response_code(400);
|
||||
http_response_code(400);
|
||||
} elseif (filter_var($domain, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) === false) {
|
||||
http_response_code(400);
|
||||
http_response_code(400);
|
||||
} elseif (filter_var($domain, FILTER_VALIDATE_IP)) {
|
||||
http_response_code(400);
|
||||
http_response_code(400);
|
||||
} else {
|
||||
// Commented because logging is disabled as otherwise all attempts will be logged which spams the logs
|
||||
// error_log($domain . ' was accepted as valid domain.');
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<files psalm-version="6.15.1@28dc127af1b5aecd52314f6f645bafc10d0e11f9"/>
|
||||
<files psalm-version="6.16.1@f1f5de594dc76faf8784e02d3dc4716c91c6f6ac"/>
|
||||
|
||||
@@ -21,9 +21,10 @@ use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$container = \AIO\DependencyInjection::GetContainer();
|
||||
$dataConst = $container->get(\AIO\Data\DataConst::class);
|
||||
ini_set('session.save_path', $dataConst->GetSessionDirectory());
|
||||
// Configure and start the session before building the DI container so that
|
||||
// TranslationManager (instantiated inside the container) can read
|
||||
// $_SESSION['aio_user_language'] from the very first request.
|
||||
ini_set('session.save_path', \AIO\Data\DataConst::GetSessionDirectory());
|
||||
|
||||
// Auto logout on browser close
|
||||
ini_set('session.cookie_lifetime', '0');
|
||||
@@ -31,6 +32,10 @@ ini_set('session.cookie_lifetime', '0');
|
||||
# Keep session for 24h max
|
||||
ini_set('session.gc_maxlifetime', '86400');
|
||||
|
||||
session_start();
|
||||
|
||||
$container = \AIO\DependencyInjection::GetContainer();
|
||||
|
||||
// Create app
|
||||
AppFactory::setContainer($container);
|
||||
$app = AppFactory::create();
|
||||
@@ -44,18 +49,19 @@ $container->set(Guard::class, function () use ($responseFactory) {
|
||||
});
|
||||
|
||||
// Register Middleware To Be Executed On All Routes
|
||||
session_start();
|
||||
$app->add(Guard::class);
|
||||
|
||||
// Create Twig
|
||||
$twig = Twig::create(__DIR__ . '/../templates/', ['cache' => false]);
|
||||
$app->add(TwigMiddleware::create($app, $twig));
|
||||
$twig->addExtension(new \AIO\Twig\CsrfExtension($container->get(Guard::class)));
|
||||
$twig->addExtension(new \AIO\Twig\TranslationExtension($container->get(\AIO\Translation\TranslationManager::class)));
|
||||
|
||||
// Auth Middleware
|
||||
$app->add(new \AIO\Middleware\AuthMiddleware($container->get(\AIO\Auth\AuthManager::class)));
|
||||
|
||||
// API
|
||||
$app->post('/api/language', AIO\Controller\LanguageController::class . ':SetLanguage');
|
||||
$app->post('/api/docker/watchtower', AIO\Controller\DockerController::class . ':StartWatchtowerContainer');
|
||||
$app->get('/api/docker/getwatchtower', AIO\Controller\DockerController::class . ':StartWatchtowerContainer');
|
||||
$app->post('/api/docker/start', AIO\Controller\DockerController::class . ':StartContainer');
|
||||
|
||||
104
php/public/language-switcher.js
Normal file
104
php/public/language-switcher.js
Normal file
@@ -0,0 +1,104 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var STORAGE_KEY = 'aio_language';
|
||||
var API_ENDPOINT = 'api/language';
|
||||
|
||||
/**
|
||||
* Read the CSRF token fields that CsrfExtension injects into every page as
|
||||
* hidden inputs inside the logout form. We reuse them for the JSON POST so
|
||||
* that Slim's CSRF guard accepts our request.
|
||||
*/
|
||||
function getCsrfFields() {
|
||||
var nameInput = document.querySelector('input[name$="__token_name"]') // fallback selector
|
||||
|| document.querySelector('input[name^="csrf_name"]');
|
||||
var valueInput = document.querySelector('input[name$="__token_value"]')
|
||||
|| document.querySelector('input[name^="csrf_value"]');
|
||||
|
||||
// The Slim CSRF guard stores two hidden fields; their *name* attributes
|
||||
// are themselves dynamic (csrf_name / csrf_value carry the key names,
|
||||
// and csrf.name / csrf.value carry the actual token strings).
|
||||
// The simplest reliable approach: grab all hidden inputs from the logout
|
||||
// form and forward them all.
|
||||
var logoutForm = document.querySelector('form[action*="api/auth/logout"]');
|
||||
if (!logoutForm) {
|
||||
return {};
|
||||
}
|
||||
|
||||
var fields = {};
|
||||
var hiddenInputs = logoutForm.querySelectorAll('input[type="hidden"]');
|
||||
hiddenInputs.forEach(function (input) {
|
||||
fields[input.name] = input.value;
|
||||
});
|
||||
return fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* POST the chosen language to the server, then reload on success.
|
||||
* Returns a Promise that resolves to true on success, false on failure.
|
||||
*/
|
||||
function postLanguage(lang) {
|
||||
var csrfFields = getCsrfFields();
|
||||
var body = Object.assign({ language: lang }, csrfFields);
|
||||
|
||||
return fetch(API_ENDPOINT, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: new URLSearchParams(body).toString(),
|
||||
}).then(function (response) {
|
||||
return response.ok || response.status === 204;
|
||||
}).catch(function () {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist the language choice to localStorage and reload the page so the
|
||||
* server can render in the new language.
|
||||
*/
|
||||
function applyLanguage(lang, reload) {
|
||||
localStorage.setItem(STORAGE_KEY, lang);
|
||||
postLanguage(lang).then(function (ok) {
|
||||
if (ok && reload) {
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wire up the <select> drop-down once the DOM is ready.
|
||||
*/
|
||||
function initSwitcher() {
|
||||
var select = document.getElementById('language-switcher');
|
||||
if (!select) {
|
||||
return;
|
||||
}
|
||||
|
||||
select.addEventListener('change', function () {
|
||||
var chosen = select.value;
|
||||
if (chosen) {
|
||||
applyLanguage(chosen, true);
|
||||
}
|
||||
});
|
||||
|
||||
// On page load: if localStorage holds a preference that differs from
|
||||
// the current server-side language, silently sync once and reload.
|
||||
var saved = localStorage.getItem(STORAGE_KEY);
|
||||
var current = select.dataset.current || select.value;
|
||||
|
||||
if (saved && saved !== current) {
|
||||
// Update the select to match the stored preference before posting,
|
||||
// so the UI doesn't flicker if the reload is slow.
|
||||
select.value = saved;
|
||||
applyLanguage(saved, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initSwitcher);
|
||||
} else {
|
||||
initSwitcher();
|
||||
}
|
||||
}());
|
||||
@@ -375,9 +375,38 @@ header {
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
header > form {
|
||||
.header-controls {
|
||||
margin-left: auto;
|
||||
margin-right: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.header-controls > form {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.language-switcher {
|
||||
height: 34px;
|
||||
padding: 0 8px;
|
||||
font-size: var(--default-font-size);
|
||||
font-family: inherit;
|
||||
color: var(--color-main-text);
|
||||
background-color: var(--color-main-background);
|
||||
border: var(--border) solid var(--color-main-border);
|
||||
border-radius: var(--border-radius);
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.language-switcher:hover {
|
||||
border-width: var(--border-hover);
|
||||
border-color: var(--color-main-border-hover);
|
||||
}
|
||||
|
||||
.language-switcher:focus {
|
||||
outline: 2px solid var(--color-main-border);
|
||||
}
|
||||
|
||||
/* Standard styling for enabled checkboxes */
|
||||
@@ -483,8 +512,8 @@ input[type="checkbox"]:disabled:not(:checked) + label {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
align-self: start;
|
||||
width: 20%;
|
||||
height: 7rem;
|
||||
width: 300px;
|
||||
height: 200px;
|
||||
border-radius: var(--border-radius-large);
|
||||
border: solid thin rgb(192, 192, 192);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ readonly class Container {
|
||||
public string $imageTag,
|
||||
public AioVariables $aioVariables,
|
||||
public string $documentation,
|
||||
public bool $hideFromList,
|
||||
private DockerActionManager $dockerActionManager
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -324,6 +324,8 @@ readonly class ContainerDefinitionFetcher {
|
||||
$documentation = $entry['documentation'];
|
||||
}
|
||||
|
||||
$hideFromList = $entry['hide_from_list'] ?? false;
|
||||
|
||||
$containers[] = new Container(
|
||||
$entry['container_name'],
|
||||
$displayName,
|
||||
@@ -349,6 +351,7 @@ readonly class ContainerDefinitionFetcher {
|
||||
$imageTag,
|
||||
$aioVariables,
|
||||
$documentation,
|
||||
$hideFromList,
|
||||
$this->container->get(DockerActionManager::class)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -87,43 +87,64 @@ readonly class DockerController {
|
||||
}
|
||||
|
||||
public function StartBackupContainerBackup(Request $request, Response $response, array $args) : Response {
|
||||
// Get streaming response start and closure
|
||||
$nonbufResp = $this->startStreamingResponse($response);
|
||||
$addToStreamingResponseBody = $this->getAddToStreamingResponseBody($nonbufResp);
|
||||
|
||||
$forceStopNextcloud = true;
|
||||
$this->startBackup($forceStopNextcloud);
|
||||
return $response->withStatus(201)->withHeader('Location', '.');
|
||||
$this->startBackup($forceStopNextcloud, $addToStreamingResponseBody);
|
||||
|
||||
// End streaming response
|
||||
$this->finalizeStreamingResponse($nonbufResp);
|
||||
return $nonbufResp;
|
||||
}
|
||||
|
||||
public function startBackup(bool $forceStopNextcloud = false) : void {
|
||||
public function startBackup(bool $forceStopNextcloud = false, ?\Closure $addToStreamingResponseBody = null) : void {
|
||||
$this->configurationManager->backupMode = 'backup';
|
||||
|
||||
$id = self::TOP_CONTAINER;
|
||||
$this->PerformRecursiveContainerStop($id, $forceStopNextcloud);
|
||||
$this->PerformRecursiveContainerStop($id, $forceStopNextcloud, $addToStreamingResponseBody);
|
||||
|
||||
$id = 'nextcloud-aio-borgbackup';
|
||||
$this->PerformRecursiveContainerStart($id);
|
||||
$this->PerformRecursiveContainerStart($id, true, $addToStreamingResponseBody);
|
||||
}
|
||||
|
||||
public function StartBackupContainerCheck(Request $request, Response $response, array $args) : Response {
|
||||
$this->checkBackup();
|
||||
return $response->withStatus(201)->withHeader('Location', '.');
|
||||
// Get streaming response start and closure
|
||||
$nonbufResp = $this->startStreamingResponse($response);
|
||||
$addToStreamingResponseBody = $this->getAddToStreamingResponseBody($nonbufResp);
|
||||
|
||||
$this->checkBackup($addToStreamingResponseBody);
|
||||
|
||||
// End streaming response
|
||||
$this->finalizeStreamingResponse($nonbufResp);
|
||||
return $nonbufResp;
|
||||
}
|
||||
|
||||
public function StartBackupContainerList(Request $request, Response $response, array $args) : Response {
|
||||
$this->listBackup();
|
||||
return $response->withStatus(201)->withHeader('Location', '.');
|
||||
// Get streaming response start and closure
|
||||
$nonbufResp = $this->startStreamingResponse($response);
|
||||
$addToStreamingResponseBody = $this->getAddToStreamingResponseBody($nonbufResp);
|
||||
|
||||
$this->listBackup($addToStreamingResponseBody);
|
||||
|
||||
// End streaming response
|
||||
$this->finalizeStreamingResponse($nonbufResp);
|
||||
return $nonbufResp;
|
||||
}
|
||||
|
||||
public function checkBackup() : void {
|
||||
public function checkBackup(?\Closure $addToStreamingResponseBody = null) : void {
|
||||
$this->configurationManager->backupMode = 'check';
|
||||
|
||||
$id = 'nextcloud-aio-borgbackup';
|
||||
$this->PerformRecursiveContainerStart($id);
|
||||
$this->PerformRecursiveContainerStart($id, true, $addToStreamingResponseBody);
|
||||
}
|
||||
|
||||
private function listBackup() : void {
|
||||
private function listBackup(?\Closure $addToStreamingResponseBody = null) : void {
|
||||
$this->configurationManager->backupMode = 'list';
|
||||
|
||||
$id = 'nextcloud-aio-borgbackup';
|
||||
$this->PerformRecursiveContainerStart($id);
|
||||
$this->PerformRecursiveContainerStart($id, true, $addToStreamingResponseBody);
|
||||
}
|
||||
|
||||
public function StartBackupContainerRestore(Request $request, Response $response, array $args) : Response {
|
||||
@@ -133,26 +154,38 @@ readonly class DockerController {
|
||||
$this->configurationManager->restoreExcludePreviews = isset($request->getParsedBody()['restore-exclude-previews']);
|
||||
$this->configurationManager->commitTransaction();
|
||||
|
||||
// Get streaming response start and closure
|
||||
$nonbufResp = $this->startStreamingResponse($response);
|
||||
$addToStreamingResponseBody = $this->getAddToStreamingResponseBody($nonbufResp);
|
||||
|
||||
$id = self::TOP_CONTAINER;
|
||||
$forceStopNextcloud = true;
|
||||
$this->PerformRecursiveContainerStop($id, $forceStopNextcloud);
|
||||
$this->PerformRecursiveContainerStop($id, $forceStopNextcloud, $addToStreamingResponseBody);
|
||||
|
||||
$id = 'nextcloud-aio-borgbackup';
|
||||
$this->PerformRecursiveContainerStart($id);
|
||||
$this->PerformRecursiveContainerStart($id, true, $addToStreamingResponseBody);
|
||||
|
||||
return $response->withStatus(201)->withHeader('Location', '.');
|
||||
// End streaming response
|
||||
$this->finalizeStreamingResponse($nonbufResp);
|
||||
return $nonbufResp;
|
||||
}
|
||||
|
||||
public function StartBackupContainerCheckRepair(Request $request, Response $response, array $args) : Response {
|
||||
$this->configurationManager->backupMode = 'check-repair';
|
||||
|
||||
// Get streaming response start and closure
|
||||
$nonbufResp = $this->startStreamingResponse($response);
|
||||
$addToStreamingResponseBody = $this->getAddToStreamingResponseBody($nonbufResp);
|
||||
|
||||
$id = 'nextcloud-aio-borgbackup';
|
||||
$this->PerformRecursiveContainerStart($id);
|
||||
$this->PerformRecursiveContainerStart($id, true, $addToStreamingResponseBody);
|
||||
|
||||
// Restore to backup check which is needed to make the UI logic work correctly
|
||||
$this->configurationManager->backupMode = 'check';
|
||||
|
||||
return $response->withStatus(201)->withHeader('Location', '.');
|
||||
// End streaming response
|
||||
$this->finalizeStreamingResponse($nonbufResp);
|
||||
return $nonbufResp;
|
||||
}
|
||||
|
||||
public function StartBackupContainerTest(Request $request, Response $response, array $args) : Response {
|
||||
@@ -161,13 +194,19 @@ readonly class DockerController {
|
||||
$this->configurationManager->instanceRestoreAttempt = false;
|
||||
$this->configurationManager->commitTransaction();
|
||||
|
||||
// Get streaming response start and closure
|
||||
$nonbufResp = $this->startStreamingResponse($response);
|
||||
$addToStreamingResponseBody = $this->getAddToStreamingResponseBody($nonbufResp);
|
||||
|
||||
$id = self::TOP_CONTAINER;
|
||||
$this->PerformRecursiveContainerStop($id);
|
||||
$this->PerformRecursiveContainerStop($id, true, $addToStreamingResponseBody);
|
||||
|
||||
$id = 'nextcloud-aio-borgbackup';
|
||||
$this->PerformRecursiveContainerStart($id);
|
||||
$this->PerformRecursiveContainerStart($id, true, $addToStreamingResponseBody);
|
||||
|
||||
return $response->withStatus(201)->withHeader('Location', '.');
|
||||
// End streaming response
|
||||
$this->finalizeStreamingResponse($nonbufResp);
|
||||
return $nonbufResp;
|
||||
}
|
||||
|
||||
public function StartContainer(Request $request, Response $response, array $args) : Response
|
||||
@@ -202,23 +241,9 @@ readonly class DockerController {
|
||||
error_log('WARNING: Not pulling container images. Instead, using local ones.');
|
||||
}
|
||||
|
||||
$nonbufResp = $response
|
||||
->withBody(new NonBufferedBody())
|
||||
->withHeader('Content-Type', 'text/html; charset=utf-8')
|
||||
->withHeader('X-Accel-Buffering', 'no')
|
||||
->withHeader('Cache-Control', 'no-cache');
|
||||
|
||||
// Text written into this body is immediately sent to the client, without waiting for later content.
|
||||
$streamingResponseBody = $nonbufResp->getBody();
|
||||
|
||||
$streamingResponseBody->write($this->getStreamingResponseHtmlStart());
|
||||
|
||||
// Create a closure to pass around to the code, which should to the logging (because it e.g. decides
|
||||
// if it'll actually pull an image), but which should not need to know anything about the
|
||||
// wanted markup or formatting.
|
||||
$addToStreamingResponseBody = function (Container $container, string $message) use ($streamingResponseBody) : void {
|
||||
$streamingResponseBody->write("<div>{$container->displayName}: {$message}</div>");
|
||||
};
|
||||
// Get streaming response start and closure
|
||||
$nonbufResp = $this->startStreamingResponse($response);
|
||||
$addToStreamingResponseBody = $this->getAddToStreamingResponseBody($nonbufResp);
|
||||
|
||||
// Start container
|
||||
$this->startTopContainer($pullImage, $addToStreamingResponseBody);
|
||||
@@ -227,7 +252,8 @@ readonly class DockerController {
|
||||
// Temporarily disabled as it leads much faster to docker rate limits
|
||||
// apcu_clear_cache();
|
||||
|
||||
$streamingResponseBody->write($this->getStreamingResponseHtmlEnd());
|
||||
// End streaming response
|
||||
$this->finalizeStreamingResponse($nonbufResp);
|
||||
return $nonbufResp;
|
||||
}
|
||||
|
||||
@@ -243,17 +269,24 @@ readonly class DockerController {
|
||||
}
|
||||
|
||||
public function StartWatchtowerContainer(Request $request, Response $response, array $args) : Response {
|
||||
$this->startWatchtower();
|
||||
return $response->withStatus(201)->withHeader('Location', '.');
|
||||
// Get streaming response start and closure
|
||||
$nonbufResp = $this->startStreamingResponse($response);
|
||||
$addToStreamingResponseBody = $this->getAddToStreamingResponseBody($nonbufResp);
|
||||
|
||||
$this->startWatchtower($addToStreamingResponseBody);
|
||||
|
||||
// End streaming response
|
||||
$this->finalizeStreamingResponse($nonbufResp);
|
||||
return $nonbufResp;
|
||||
}
|
||||
|
||||
public function startWatchtower() : void {
|
||||
public function startWatchtower(?\Closure $addToStreamingResponseBody = null) : void {
|
||||
$id = 'nextcloud-aio-watchtower';
|
||||
|
||||
$this->PerformRecursiveContainerStart($id);
|
||||
$this->PerformRecursiveContainerStart($id, true, $addToStreamingResponseBody);
|
||||
}
|
||||
|
||||
private function PerformRecursiveContainerStop(string $id, bool $forceStopNextcloud = false) : void
|
||||
private function PerformRecursiveContainerStop(string $id, bool $forceStopNextcloud = false, ?\Closure $addToStreamingResponseBody = null) : void
|
||||
{
|
||||
$container = $this->containerDefinitionFetcher->GetContainerById($id);
|
||||
|
||||
@@ -261,7 +294,11 @@ readonly class DockerController {
|
||||
// Stop Collabora first to make sure it force-saves
|
||||
// See https://github.com/nextcloud/richdocuments/issues/3799
|
||||
if ($id === self::TOP_CONTAINER && $this->configurationManager->isCollaboraEnabled) {
|
||||
$this->PerformRecursiveContainerStop('nextcloud-aio-collabora');
|
||||
$this->PerformRecursiveContainerStop('nextcloud-aio-collabora', false, $addToStreamingResponseBody);
|
||||
}
|
||||
|
||||
if ($addToStreamingResponseBody !== null) {
|
||||
$addToStreamingResponseBody($container, "Stopping container");
|
||||
}
|
||||
|
||||
// Stop itself first and then all the dependencies
|
||||
@@ -272,17 +309,23 @@ readonly class DockerController {
|
||||
$this->dockerActionManager->StopContainer($container, $forceStopNextcloud);
|
||||
}
|
||||
foreach($container->dependsOn as $dependency) {
|
||||
$this->PerformRecursiveContainerStop($dependency, $forceStopNextcloud);
|
||||
$this->PerformRecursiveContainerStop($dependency, $forceStopNextcloud, $addToStreamingResponseBody);
|
||||
}
|
||||
}
|
||||
|
||||
public function StopContainer(Request $request, Response $response, array $args) : Response
|
||||
{
|
||||
// Get streaming response start and closure
|
||||
$nonbufResp = $this->startStreamingResponse($response);
|
||||
$addToStreamingResponseBody = $this->getAddToStreamingResponseBody($nonbufResp);
|
||||
|
||||
$id = self::TOP_CONTAINER;
|
||||
$forceStopNextcloud = true;
|
||||
$this->PerformRecursiveContainerStop($id, $forceStopNextcloud);
|
||||
$this->PerformRecursiveContainerStop($id, $forceStopNextcloud, $addToStreamingResponseBody);
|
||||
|
||||
return $response->withStatus(201)->withHeader('Location', '.');
|
||||
// End streaming response
|
||||
$this->finalizeStreamingResponse($nonbufResp);
|
||||
return $nonbufResp;
|
||||
}
|
||||
|
||||
public function stopTopContainer() : void {
|
||||
@@ -354,7 +397,38 @@ readonly class DockerController {
|
||||
|
||||
END;
|
||||
}
|
||||
|
||||
|
||||
private function startStreamingResponse(Response $response) : Response {
|
||||
$nonbufResp = $response
|
||||
->withBody(new NonBufferedBody())
|
||||
->withHeader('Content-Type', 'text/html; charset=utf-8')
|
||||
->withHeader('X-Accel-Buffering', 'no')
|
||||
->withHeader('Content-Length', '-1')
|
||||
->withHeader('Cache-Control', 'no-cache');
|
||||
|
||||
// Text written into this body is immediately sent to the client, without waiting for later content.
|
||||
$streamingResponseBody = $nonbufResp->getBody();
|
||||
|
||||
$streamingResponseBody->write($this->getStreamingResponseHtmlStart());
|
||||
|
||||
return $nonbufResp;
|
||||
}
|
||||
|
||||
private function getAddToStreamingResponseBody(Response $nonbufResp) : ?\Closure {
|
||||
// Create a closure to pass around to the code, which should to the logging (because it e.g. decides
|
||||
// if it'll actually pull an image), but which should not need to know anything about the
|
||||
// wanted markup or formatting.
|
||||
$addToStreamingResponseBody = function (Container $container, string $message) use ($nonbufResp) : void {
|
||||
$nonbufResp->getBody()->write("<div>{$container->displayName}: {$message}</div>");
|
||||
};
|
||||
|
||||
return $addToStreamingResponseBody;
|
||||
}
|
||||
|
||||
private function finalizeStreamingResponse(Response $nonbufResp) : void {
|
||||
$nonbufResp->getBody()->write($this->getStreamingResponseHtmlEnd());
|
||||
}
|
||||
|
||||
private function getStreamingResponseHtmlEnd() : string {
|
||||
return "\n </body>\n</html>";
|
||||
}
|
||||
|
||||
38
php/src/Controller/LanguageController.php
Normal file
38
php/src/Controller/LanguageController.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Controller;
|
||||
|
||||
use AIO\Translation\TranslationManager;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
|
||||
readonly class LanguageController
|
||||
{
|
||||
public function __construct(
|
||||
private TranslationManager $translationManager,
|
||||
) {
|
||||
}
|
||||
|
||||
public function SetLanguage(Request $request, Response $response, array $args): Response
|
||||
{
|
||||
/** @var array<string, mixed>|null $body */
|
||||
$body = $request->getParsedBody();
|
||||
|
||||
$language = '';
|
||||
if (is_array($body) && isset($body['language']) && is_string($body['language'])) {
|
||||
$language = $body['language'];
|
||||
}
|
||||
|
||||
$supported = $this->translationManager->getSupportedLanguages();
|
||||
|
||||
if ($language === '' || !in_array($language, $supported, true)) {
|
||||
$response->getBody()->write('Unsupported language.');
|
||||
return $response->withStatus(422);
|
||||
}
|
||||
|
||||
$_SESSION['aio_user_language'] = $language;
|
||||
|
||||
return $response->withStatus(204);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ namespace AIO;
|
||||
use AIO\Docker\DockerHubManager;
|
||||
use DI\Container;
|
||||
use AIO\Docker\GitHubContainerRegistryManager;
|
||||
use AIO\Translation\TranslationManager;
|
||||
|
||||
class DependencyInjection
|
||||
{
|
||||
@@ -50,6 +51,10 @@ class DependencyInjection
|
||||
$container->get(\AIO\Data\ConfigurationManager::class)
|
||||
)
|
||||
);
|
||||
$container->set(
|
||||
TranslationManager::class,
|
||||
new TranslationManager()
|
||||
);
|
||||
|
||||
return $container;
|
||||
}
|
||||
|
||||
264
php/src/Translation/TranslationManager.php
Normal file
264
php/src/Translation/TranslationManager.php
Normal file
@@ -0,0 +1,264 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Translation;
|
||||
|
||||
/**
|
||||
* Resolves the active language and loads translations from a flat JSON file.
|
||||
*
|
||||
* Language resolution order:
|
||||
* 1. PHP session ($_SESSION['aio_user_language'])
|
||||
* 2. Accept-Language HTTP header (first matching tag that has a JSON file)
|
||||
* 3. Hardcoded fallback: "en"
|
||||
*
|
||||
* English is the implicit source language — the key itself is the English
|
||||
* string, so no en.json is required.
|
||||
*
|
||||
* Translation files live at:
|
||||
* <project-root>/php/translations/{lang}.json
|
||||
* Each file is a flat JSON object: {"some_key": "Translated string", ...}
|
||||
*/
|
||||
final class TranslationManager
|
||||
{
|
||||
private const TRANSLATIONS_DIR = __DIR__ . '/../../translations';
|
||||
private const FALLBACK_LANGUAGE = 'en';
|
||||
private const SESSION_KEY = 'aio_user_language';
|
||||
|
||||
/** @var array<string, string> */
|
||||
private array $strings = [];
|
||||
|
||||
private string $currentLanguage;
|
||||
|
||||
/** @var list<string>|null Lazily populated from the filesystem. */
|
||||
private ?array $supportedLanguages = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->currentLanguage = $this->resolveLanguage();
|
||||
$this->loadStrings($this->currentLanguage);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public API
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Return the translated string for $key, or $key itself when no
|
||||
* translation is available (English pass-through behaviour).
|
||||
*/
|
||||
public function translate(string $key): string
|
||||
{
|
||||
return $this->strings[$key] ?? $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* The language code that is currently active (e.g. "de", "fr", "en").
|
||||
*/
|
||||
public function getCurrentLanguage(): string
|
||||
{
|
||||
return $this->currentLanguage;
|
||||
}
|
||||
|
||||
/**
|
||||
* All language codes for which a translations/*.json file exists.
|
||||
* The list is sorted alphabetically and always includes "en".
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
public function getSupportedLanguages(): array
|
||||
{
|
||||
if ($this->supportedLanguages !== null) {
|
||||
return $this->supportedLanguages;
|
||||
}
|
||||
|
||||
$languages = ['en'];
|
||||
|
||||
$pattern = self::TRANSLATIONS_DIR . '/*.json';
|
||||
$files = glob($pattern);
|
||||
foreach ($files !== false ? $files : [] as $file) {
|
||||
$code = basename($file, '.json');
|
||||
if ($code !== 'en' && $this->isValidLanguageCode($code)) {
|
||||
$languages[] = $code;
|
||||
}
|
||||
}
|
||||
|
||||
sort($languages);
|
||||
$this->supportedLanguages = $languages;
|
||||
|
||||
return $this->supportedLanguages;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Language resolution
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private function resolveLanguage(): string
|
||||
{
|
||||
// 1. Session preference set by the user via the language switcher.
|
||||
if (
|
||||
isset($_SESSION[self::SESSION_KEY])
|
||||
&& is_string($_SESSION[self::SESSION_KEY])
|
||||
&& $this->isValidLanguageCode($_SESSION[self::SESSION_KEY])
|
||||
) {
|
||||
$lang = $this->normalise($_SESSION[self::SESSION_KEY]);
|
||||
if ($this->hasTranslationFile($lang) || $lang === self::FALLBACK_LANGUAGE) {
|
||||
return $lang;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Accept-Language header — try each tag in quality order.
|
||||
$acceptLanguage = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '';
|
||||
if ($acceptLanguage !== '') {
|
||||
$candidate = $this->resolveFromAcceptLanguage($acceptLanguage);
|
||||
if ($candidate !== null) {
|
||||
return $candidate;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Hardcoded fallback.
|
||||
return self::FALLBACK_LANGUAGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an Accept-Language header value and return the best matching
|
||||
* language code for which we have a translation file, or null.
|
||||
*
|
||||
* Example header: "de-AT,de;q=0.9,en-US;q=0.8,en;q=0.7"
|
||||
*/
|
||||
private function resolveFromAcceptLanguage(string $header): ?string
|
||||
{
|
||||
// Split on comma, sort by quality weight (highest first).
|
||||
$tags = [];
|
||||
foreach (explode(',', $header) as $part) {
|
||||
$part = trim($part);
|
||||
if ($part === '') {
|
||||
continue;
|
||||
}
|
||||
$quality = 1.0;
|
||||
if (str_contains($part, ';q=')) {
|
||||
$segments = explode(';q=', $part, 2);
|
||||
$quality = (float) ($segments[1] ?? '1');
|
||||
$part = trim($segments[0]);
|
||||
}
|
||||
$tags[] = ['tag' => $part, 'q' => $quality];
|
||||
}
|
||||
usort($tags, static fn(array $a, array $b): int => $b['q'] <=> $a['q']);
|
||||
|
||||
foreach ($tags as $entry) {
|
||||
$tag = $entry['tag'];
|
||||
|
||||
// Try the exact tag first (e.g. "de-AT"), then the primary subtag
|
||||
// (e.g. "de"), then a case-insensitive match against known files.
|
||||
foreach ($this->candidatesFor($tag) as $candidate) {
|
||||
if ($candidate === self::FALLBACK_LANGUAGE) {
|
||||
return self::FALLBACK_LANGUAGE;
|
||||
}
|
||||
if ($this->hasTranslationFile($candidate)) {
|
||||
return $candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the normalised language code candidates to try for a given
|
||||
* Accept-Language tag, from most specific to least specific.
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
private function candidatesFor(string $tag): array
|
||||
{
|
||||
$candidates = [];
|
||||
|
||||
$normalised = $this->normalise($tag);
|
||||
if ($this->isValidLanguageCode($normalised)) {
|
||||
$candidates[] = $normalised;
|
||||
}
|
||||
|
||||
// If the tag contains a region/script subtag, also try just the
|
||||
// primary language subtag (e.g. "de-AT" → "de").
|
||||
if (str_contains($normalised, '-')) {
|
||||
$primary = explode('-', $normalised, 2)[0];
|
||||
if ($this->isValidLanguageCode($primary)) {
|
||||
$candidates[] = $primary;
|
||||
}
|
||||
}
|
||||
|
||||
return $candidates;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Translation file loading
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private function loadStrings(string $language): void
|
||||
{
|
||||
if ($language === self::FALLBACK_LANGUAGE) {
|
||||
// English: key == translation, nothing to load.
|
||||
$this->strings = [];
|
||||
return;
|
||||
}
|
||||
|
||||
$path = $this->translationFilePath($language);
|
||||
if (!file_exists($path)) {
|
||||
$this->strings = [];
|
||||
return;
|
||||
}
|
||||
|
||||
$contents = file_get_contents($path);
|
||||
if ($contents === false) {
|
||||
$this->strings = [];
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var mixed $decoded */
|
||||
$decoded = json_decode($contents, true);
|
||||
if (!is_array($decoded)) {
|
||||
$this->strings = [];
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var array<string, string> $strings */
|
||||
$strings = [];
|
||||
foreach ($decoded as $key => $value) {
|
||||
if (is_string($key) && is_string($value)) {
|
||||
$strings[$key] = $value;
|
||||
}
|
||||
}
|
||||
$this->strings = $strings;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Helpers
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private function hasTranslationFile(string $language): bool
|
||||
{
|
||||
return file_exists($this->translationFilePath($language));
|
||||
}
|
||||
|
||||
private function translationFilePath(string $language): string
|
||||
{
|
||||
return self::TRANSLATIONS_DIR . '/' . $language . '.json';
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalise a language tag to lowercase with hyphens
|
||||
* (e.g. "de_AT" → "de-at", "ZH-Hans" → "zh-hans").
|
||||
*/
|
||||
private function normalise(string $tag): string
|
||||
{
|
||||
return strtolower(str_replace('_', '-', $tag));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanity-check that the string looks like a BCP-47 language tag and
|
||||
* cannot be used for path traversal.
|
||||
*/
|
||||
private function isValidLanguageCode(string $code): bool
|
||||
{
|
||||
return (bool) preg_match('/^[a-zA-Z]{2,8}(?:-[a-zA-Z0-9]{1,8})*$/', $code);
|
||||
}
|
||||
}
|
||||
48
php/src/Twig/TranslationExtension.php
Normal file
48
php/src/Twig/TranslationExtension.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace AIO\Twig;
|
||||
|
||||
use AIO\Translation\TranslationManager;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\Extension\GlobalsInterface;
|
||||
use Twig\TwigFilter;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
final class TranslationExtension extends AbstractExtension implements GlobalsInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly TranslationManager $translationManager,
|
||||
) {
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('t', $this->translate(...)),
|
||||
];
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [
|
||||
new TwigFilter('t', $this->translate(...)),
|
||||
];
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public function getGlobals(): array
|
||||
{
|
||||
return [
|
||||
'currentLanguage' => $this->translationManager->getCurrentLanguage(),
|
||||
'supportedLanguages' => $this->translationManager->getSupportedLanguages(),
|
||||
];
|
||||
}
|
||||
|
||||
public function translate(string $key): string
|
||||
{
|
||||
return $this->translationManager->translate($key);
|
||||
}
|
||||
}
|
||||
@@ -4,27 +4,27 @@
|
||||
{% if c.GetStartingState().value == 'starting' %}
|
||||
<span class="status running"></span>
|
||||
{{ c.displayName }}
|
||||
(<a href="log?id={{ c.identifier }}" target="_blank">Starting</a>)
|
||||
(<a href="log?id={{ c.identifier }}" target="_blank">{{ t('Starting') }}</a>)
|
||||
{% elseif c.GetRunningState().value == 'running' %}
|
||||
<span class="status success"></span>
|
||||
{{ c.displayName }}
|
||||
(<a href="log?id={{ c.identifier }}" target="_blank">Running</a>)
|
||||
(<a href="log?id={{ c.identifier }}" target="_blank">{{ t('Running') }}</a>)
|
||||
{% else %}
|
||||
<span class="status error"></span>
|
||||
{{ c.displayName }}
|
||||
(<a href="log?id={{ c.identifier }}" target="_blank">Stopped</a>)
|
||||
(<a href="log?id={{ c.identifier }}" target="_blank">{{ t('Stopped') }}</a>)
|
||||
{% endif %}
|
||||
{% if c.documentation != '' %}
|
||||
(<a target="_blank" href="{{ c.documentation }}">docs</a>)
|
||||
(<a target="_blank" href="{{ c.documentation }}">{{ t('docs') }}</a>)
|
||||
{% endif %}
|
||||
{% if c.GetUpdateState().value == 'different' %}
|
||||
⚠️ Update available
|
||||
⚠️ {{ t('Update') }} {{ t('available') }}
|
||||
{% endif %}
|
||||
</span>
|
||||
{% if c.GetUiSecret() != '' %}
|
||||
<details>
|
||||
<summary>Show password for {{ c.displayName }}</summary>
|
||||
<summary>{{ t('Show password for') }} {{ c.displayName }}</summary>
|
||||
<input type="text" value="{{ c.GetUiSecret() }}" readonly>
|
||||
</details>
|
||||
{% endif %}
|
||||
</li>
|
||||
</li>
|
||||
@@ -8,17 +8,27 @@
|
||||
<svg class="logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 142 71" width="62" height="50">
|
||||
<use href="img/nextcloud-logo.svg#logo"></use>
|
||||
</svg>
|
||||
<form method="POST" action="api/auth/logout">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Log out" />
|
||||
</form>
|
||||
<div class="header-controls">
|
||||
{% if supportedLanguages|length > 1 %}
|
||||
<select id="language-switcher" class="language-switcher" data-current="{{ currentLanguage }}" aria-label="{{ t('Select language') }}">
|
||||
{% for lang in supportedLanguages %}
|
||||
<option value="{{ lang }}"{% if lang == currentLanguage %} selected{% endif %}>{{ lang }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% endif %}
|
||||
<form method="POST" action="api/auth/logout">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="{{ t('Log out') }}" />
|
||||
</form>
|
||||
</div>
|
||||
<script type="text/javascript" src="language-switcher.js"></script>
|
||||
</header>
|
||||
|
||||
<div class="container">
|
||||
<main>
|
||||
{% set aio_version = include('includes/aio-version.twig') %}
|
||||
<h1>Nextcloud AIO v{{ aio_version }}</h1>
|
||||
<h1>{{ t('Nextcloud AIO v') }}{{ aio_version }}</h1>
|
||||
|
||||
{# Add 2nd tab warning #}
|
||||
<script type="text/javascript" src="second-tab-warning.js"></script>
|
||||
@@ -47,10 +57,10 @@
|
||||
{% endif %}
|
||||
|
||||
{% for container in containers %}
|
||||
{% if container.displayName != '' and container.GetRunningState().value == 'running' %}
|
||||
{% if container.hideFromList != true and container.GetRunningState().value == 'running' %}
|
||||
{% set isAnyRunning = true %}
|
||||
{% endif %}
|
||||
{% if container.displayName != '' and container.GetRestartingState().value == 'restarting' %}
|
||||
{% if container.hideFromList != true and container.GetRestartingState().value == 'restarting' %}
|
||||
{% set isAnyRestarting = true %}
|
||||
{% endif %}
|
||||
{% if container.identifier == 'nextcloud-aio-watchtower' and container.GetRunningState().value == 'running' %}
|
||||
@@ -65,50 +75,50 @@
|
||||
{% endfor %}
|
||||
|
||||
{% if is_daily_backup_running == true %}
|
||||
<p><span class="status running"></span> Daily backup currently running. (<a href="log?id=nextcloud-aio-mastercontainer" target="_blank">Mastercontainer logs</a>) (<a href="log?id=nextcloud-aio-borgbackup" target="_blank">Borg backup container logs</a>)</p>
|
||||
<p><span class="status running"></span> {{ t('Daily backup currently running.') }} (<a href="log?id=nextcloud-aio-mastercontainer" target="_blank">{{ t('Mastercontainer logs') }}</a>) (<a href="log?id=nextcloud-aio-borgbackup" target="_blank">{{ t('Borg backup container logs') }}</a>)</p>
|
||||
{% if automatic_updates == true %}
|
||||
<p>This will update your containers, the mastercontainer and, on Saturdays, your Nextcloud apps if the backup is successful.</p>
|
||||
<p>{{ t('This will update your containers, the mastercontainer and, on Saturdays, your Nextcloud apps if the backup is successful.') }}</p>
|
||||
{% if is_mastercontainer_update_available == true %}
|
||||
<p>When the mastercontainer is updated it will restart, making it unavailable for a moment. (<a href="log?id=nextcloud-aio-watchtower" target="_blank">Logs</a>)</p>
|
||||
<p>{{ t('When the mastercontainer is updated it will restart, making it unavailable for a moment.') }} (<a href="log?id=nextcloud-aio-watchtower" target="_blank">{{ t('Logs') }}</a>)</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if has_update_available == false %}
|
||||
<p>The whole process should not take more than a few minutes.</p>
|
||||
<p>{{ t('The whole process should not take more than a few minutes.') }}</p>
|
||||
{% elseif automatic_updates == true %}
|
||||
<p>The whole process can take a while as your containers will be updated.</p>
|
||||
<p>{{ t('The whole process can take a while as your containers will be updated.') }}</p>
|
||||
{% endif %}
|
||||
<p><a href="" class="button reload">Reload ↻</a></p>
|
||||
<p>If the daily backup is stuck somehow, you can unstick it by running <strong>sudo docker exec nextcloud-aio-mastercontainer rm /mnt/docker-aio-config/data/daily_backup_running</strong> and afterwards reloading this interface.</p>
|
||||
<p><a href="" class="button reload">{{ t('Reload ↻') }}</a></p>
|
||||
<p>{{ t('If the daily backup is stuck somehow, you can unstick it by running') }} <strong>sudo docker exec nextcloud-aio-mastercontainer rm /mnt/docker-aio-config/data/daily_backup_running</strong> {{ t('and afterwards reloading this interface.') }}</p>
|
||||
{% elseif isWatchtowerRunning == true %}
|
||||
<p><span class="status running"></span> Mastercontainer update currently running. Once the update is complete the mastercontainer will restart, making it unavailable for a moment. Please wait until it's done. (<a href="log?id=nextcloud-aio-watchtower" target="_blank">Logs</a>)</p>
|
||||
<p><a href="" class="button reload">Reload ↻</a></p>
|
||||
<p><span class="status running"></span> {{ t('Mastercontainer update currently running. Once the update is complete the mastercontainer will restart, making it unavailable for a moment. Please wait until it\'s done.') }} (<a href="log?id=nextcloud-aio-watchtower" target="_blank">{{ t('Logs') }}</a>)</p>
|
||||
<p><a href="" class="button reload">{{ t('Reload ↻') }}</a></p>
|
||||
{% else %}
|
||||
{% if is_backup_container_running == false and domain == "" %}
|
||||
{% if isDomaincheckRunning == false %}
|
||||
<h2>Domaincheck container is not running</h2>
|
||||
<p>This is not expected. Most likely this happened because port {{ apache_port }} is already in use on your server. You can check the mastercontainer logs and domaincheck container logs for further clues. You should be able to resolve this by adjusting the APACHE_PORT by following the <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md">reverse proxy documentation</a></strong>. Advice: have a detailed look at the changed docker run command for AIO.</p>
|
||||
<h2>{{ t('Domaincheck container is not running') }}</h2>
|
||||
<p>{{ t('This is not expected. Most likely this happened because port') }} {{ apache_port }} {{ t('is already in use on your server. You can check the mastercontainer logs and domaincheck container logs for further clues. You should be able to resolve this by adjusting the APACHE_PORT by following the') }} <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md">{{ t('reverse proxy documentation') }}</a></strong>. {{ t('Advice: have a detailed look at the changed docker run command for AIO.') }}</p>
|
||||
{% elseif is_mastercontainer_update_available == true %}
|
||||
<h2>Mastercontainer update</h2>
|
||||
<p>⚠️ A mastercontainer update is available. Please click on the button below to update it. Afterwards, you will be able to proceed with the setup.</p>
|
||||
<form method="POST" action="api/docker/watchtower" class="xhr">
|
||||
<h2>{{ t('Mastercontainer update') }}</h2>
|
||||
<p>⚠️ {{ t('A mastercontainer update is available. Please click on the button below to update it. Afterwards, you will be able to proceed with the setup.') }}</p>
|
||||
<form method="POST" action="api/docker/watchtower" target="overlay-log">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Update mastercontainer" />
|
||||
<input type="submit" value="{{ t('Update mastercontainer') }}" />
|
||||
</form>
|
||||
{% else %}
|
||||
{% if not hasBackupLocation %}
|
||||
<p>The official Nextcloud installation method. Nextcloud All-in-One provides easy deployment and maintenance with most features included in this one Nextcloud instance.</p>
|
||||
<p>You can either create a new AIO instance or restore a former AIO instance from backup. See the two sections below.</p>
|
||||
<p>{{ t('The official Nextcloud installation method. Nextcloud All-in-One provides easy deployment and maintenance with most features included in this one Nextcloud instance.') }}</p>
|
||||
<p>{{ t('You can either create a new AIO instance or restore a former AIO instance from backup. See the two sections below.') }}</p>
|
||||
{{ include('includes/aio-config.twig') }}
|
||||
<h2>New AIO instance</h2>
|
||||
<h2>{{ t('New AIO instance') }}</h2>
|
||||
{% if apache_port == '443' %}
|
||||
<p>AIO is currently in "normal mode" which means that it handles the TLS proxying itself. This also means that it cannot be installed behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else). If you want to run AIO behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else), see the <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md">reverse proxy documentation</a></strong>. Advice: have a detailed look at the changed docker run command for AIO.</p>
|
||||
<p>{{ t('AIO is currently in "normal mode" which means that it handles the TLS proxying itself. This also means that it cannot be installed behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else). If you want to run AIO behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else), see the') }} <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md">{{ t('reverse proxy documentation') }}</a></strong>. {{ t('Advice: have a detailed look at the changed docker run command for AIO.') }}</p>
|
||||
{% else %}
|
||||
<p>AIO is currently in "reverse proxy mode" which means that it can be installed behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else) and does not do the TLS proxying itself.</p>
|
||||
<p>{{ t('AIO is currently in "reverse proxy mode" which means that it can be installed behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else) and does not do the TLS proxying itself.') }}</p>
|
||||
{% endif %}
|
||||
<p>Please type in the domain that will be used for Nextcloud and submit it.</p>
|
||||
<p>{{ t('Please type in the domain that will be used for Nextcloud and submit it.') }}</p>
|
||||
{% if skip_domain_validation == true %}
|
||||
<p><strong>Please note:</strong> The domain validation is disabled so any domain will be accepted here! Make sure you do not make a typo here as you will not be able to change it afterwards!</p>
|
||||
<p><strong>{{ t('Please note:') }}</strong> {{ t('The domain validation is disabled so any domain will be accepted here! Make sure you do not make a typo here as you will not be able to change it afterwards!') }}</p>
|
||||
{% endif %}
|
||||
<form method="POST" action="api/configuration" class="xhr">
|
||||
<input type="text" id="domain" name="domain" value="{{ domain }}" placeholder="nextcloud.yourdomain.com"/>
|
||||
@@ -117,59 +127,61 @@
|
||||
{% if skip_domain_validation == true %}
|
||||
<input type="hidden" name="skip_domain_validation" value="{{skip_domain_validation}}">
|
||||
{% endif %}
|
||||
<input type="submit" value="Submit domain" />
|
||||
<input type="submit" value="{{ t('Submit domain') }}" />
|
||||
</form>
|
||||
{% if skip_domain_validation == false %}
|
||||
<p>Make sure that this server is reachable on port 443 (port 443/tcp is open/forwarded in your firewall/router and 443/udp as well if you want to enable http3) and that you've correctly set up the DNS config for the domain that you enter (set the A record to your public ipv4-address and if you need ipv6, set the AAAA record to your public ipv6-address. A CNAME record is, of course, also possible). You should see hints on what went wrong in the top right corner if your domain is not accepted.</p>
|
||||
<p>{{ t('Make sure that this server is reachable on port 443 (port 443/tcp is open/forwarded in your firewall/router and 443/udp as well if you want to enable http3) and that you\'ve correctly set up the DNS config for the domain that you enter (set the A record to your public ipv4-address and if you need ipv6, set the AAAA record to your public ipv6-address. A CNAME record is, of course, also possible). You should see hints on what went wrong in the top right corner if your domain is not accepted.') }}</p>
|
||||
<details>
|
||||
<summary>Click here for further hints</summary>
|
||||
<p>If you do not have a domain yet, you can get one for free e.g. from duckdns.org and others. Recommended is to use <a target="_blank" href="https://github.com/nextcloud/all-in-one/discussions/6817">Tailscale</a></p>
|
||||
<p>If you have a dynamic public IP-address, you can use e.g. <a target="_blank" href="https://ddclient.net/">DDclient</a> with a compatible domain provider for DNS updates.</p>
|
||||
<p>If you only want to install AIO locally without exposing it to the public internet or if you cannot do so, feel free to follow <a target="_blank" href="https://github.com/nextcloud/all-in-one/blob/main/local-instance.md">this documentation</a>.</p>
|
||||
<p>If you should be using Cloudflare Proxy for your domain, make sure to disable the Proxy feature temporarily as it might block the domain validation attempts.</p>
|
||||
<summary>{{ t('Click here for further hints') }}</summary>
|
||||
<p>{{ t('If you do not have a domain yet, you can get one for free e.g. from duckdns.org and others. Recommended is to use') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one/discussions/6817">Tailscale</a></p>
|
||||
<p>{{ t('If you have a dynamic public IP-address, you can use e.g.') }} <a target="_blank" href="https://ddclient.net/">DDclient</a> {{ t('with a compatible domain provider for DNS updates.') }}</p>
|
||||
<p>{{ t('If you only want to install AIO locally without exposing it to the public internet or if you cannot do so, feel free to follow') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one/blob/main/local-instance.md">{{ t('this documentation') }}</a>.</p>
|
||||
<p>{{ t('If you should be using Cloudflare Proxy for your domain, make sure to disable the Proxy feature temporarily as it might block the domain validation attempts.') }}</p>
|
||||
{% if apache_port != '443' %}
|
||||
<p>If you run into issues with your domain being accepted, see <a target="_blank" href="https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md#how-to-debug">these steps</a> for how to debug things.</p>
|
||||
<p>{{ t('If you run into issues with your domain being accepted, see') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md#how-to-debug">{{ t('these steps') }}</a> {{ t('for how to debug things.') }}</p>
|
||||
{% endif %}
|
||||
<p><strong>Hint:</strong> If the domain validation fails but you are completely sure that you've configured everything correctly, you may skip the domain validation by following <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-skip-the-domain-validation">this documentation</a>.</p>
|
||||
<p><strong>{{ t('Hint:') }}</strong> {{ t('If the domain validation fails but you are completely sure that you\'ve configured everything correctly, you may skip the domain validation by following') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-skip-the-domain-validation">{{ t('this documentation') }}</a>.</p>
|
||||
</details>
|
||||
{% endif %}
|
||||
|
||||
<h2>Restore former AIO instance from backup</h2>
|
||||
<p>You can alternatively restore a former AIO instance from backup.</p>
|
||||
<h2>{{ t('Restore former AIO instance from backup') }}</h2>
|
||||
<p>{{ t('You can alternatively restore a former AIO instance from backup.') }}</p>
|
||||
{% endif %}
|
||||
|
||||
{% if is_instance_restore_attempt == false %}
|
||||
{% if hasBackupLocation %}
|
||||
{% if borg_backup_mode in ['test', 'check'] %}
|
||||
{% if backup_exit_code > 0 %}
|
||||
<p><span class="status error"></span> Last {{ borg_backup_mode }} failed! (<a href="log?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
|
||||
<p><span class="status error"></span> {{ t('Last') }} {{ borg_backup_mode }} {{ t('failed!') }} (<a href="log?id=nextcloud-aio-borgbackup" target="_blank">{{ t('Logs') }}</a>)</p>
|
||||
{% if borg_backup_mode == 'test' %}
|
||||
<p>Please adjust the path and/or the encryption password in order to make it work!</p>
|
||||
<p>{{ t('Please adjust the path and/or the encryption password in order to make it work!') }}</p>
|
||||
{% elseif borg_backup_mode == 'check' %}
|
||||
<p>The backup archive seems to be corrupt. Please try to use a different intact backup archive or try to fix it by following <a target="_blank" href="https://borgbackup.readthedocs.io/en/stable/faq.html#i-get-an-integrityerror-or-similar-what-now"><strong>this documentation</strong></a></p>
|
||||
<p>{{ t('The backup archive seems to be corrupt. Please try to use a different intact backup archive or try to fix it by following') }} <a target="_blank" href="https://borgbackup.readthedocs.io/en/stable/faq.html#i-get-an-integrityerror-or-similar-what-now"><strong>{{ t('this documentation') }}</strong></a></p>
|
||||
<details>
|
||||
<summary>Reveal repair option</summary>
|
||||
<p>Below is the option to repair the integrity of your backup. <strong>Please note:</strong> Please only use this after you have read the documentation above! (It will run the command 'borg check --repair' for you.)</p>
|
||||
<form method="POST" action="api/docker/backup-check-repair" class="xhr">
|
||||
<summary>{{ t('Reveal repair option') }}</summary>
|
||||
<p>{{ t('Below is the option to repair the integrity of your backup.') }} <strong>{{ t('Please note:') }}</strong> {{ t('Please only use this after you have read the documentation above! (It will run the command \'borg check --repair\' for you.)') }}</p>
|
||||
{% set confirmRepair = t('Check and repair backup integrity? Are you sure that you want to check and repair the backup integrity? This should only be done after reading the mentioned documentation.') %}
|
||||
<form method="POST" action="api/docker/backup-check-repair" target="overlay-log">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Check and repair backup integrity" onclick="return confirm('Check and repair backup integrity? Are you sure that you want to check and repair the backup integrity? This should only be done after reading the mentioned documentation.')"/>
|
||||
<input type="submit" value="{{ t('Check and repair backup integrity') }}" onclick="return confirm('{{ confirmRepair|e('js') }}')"/>
|
||||
</form>
|
||||
</details>
|
||||
{% endif %}
|
||||
{% elseif backup_exit_code == 0 %}
|
||||
<p><span class="status success"></span> Last {{ borg_backup_mode }} successful! (<a href="log?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
|
||||
<p><span class="status success"></span> {{ t('Last') }} {{ borg_backup_mode }} {{ t('successful!') }} (<a href="log?id=nextcloud-aio-borgbackup" target="_blank">{{ t('Logs') }}</a>)</p>
|
||||
{% if borg_backup_mode == 'test' %}
|
||||
<p>Feel free to check the integrity of the backup archive below before starting the restore process in order to make ensure that the restore will work. This can take a long time though depending on the size of the backup archive and is thus not required.</p>
|
||||
<form method="POST" action="api/docker/backup-check" class="xhr">
|
||||
<p>{{ t('Feel free to check the integrity of the backup archive below before starting the restore process in order to make ensure that the restore will work. This can take a long time though depending on the size of the backup archive and is thus not required.') }}</p>
|
||||
<form method="POST" action="api/docker/backup-check" target="overlay-log">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Check backup integrity"/>
|
||||
<input type="submit" value="{{ t('Check backup integrity') }}"/>
|
||||
</form>
|
||||
{% endif %}
|
||||
<p>Choose the backup that you want to restore and click on the button below to restore the selected backup. This will restore the whole AIO instance. Please note that the current AIO passphrase will be kept and the previous AIO passphrase will not be restored from backup!</p>
|
||||
<p><strong>Important:</strong> If the backup that you want to restore contained any <a target="_blank" href="https://github.com/nextcloud/all-in-one/tree/main/community-containers#community-containers">community container</a>, you need to restore the same backup a second time after this attempt so that the community container data is also correctly restored.</p>
|
||||
<form method="POST" action="api/docker/restore" class="xhr" id="restore_selection">
|
||||
<p>{{ t('Choose the backup that you want to restore and click on the button below to restore the selected backup. This will restore the whole AIO instance. Please note that the current AIO passphrase will be kept and the previous AIO passphrase will not be restored from backup!') }}</p>
|
||||
<p><strong>{{ t('Important:') }}</strong> {{ t('If the backup that you want to restore contained any') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one/tree/main/community-containers#community-containers">{{ t('community container') }}</a>, {{ t('you need to restore the same backup a second time after this attempt so that the community container data is also correctly restored.') }}</p>
|
||||
{% set confirmRestore = t('⚠️ Important: If the backup that you want to restore contained any community container, you need to restore the same backup a second time after this attempt so that the community container data is also correctly restored.') %}
|
||||
<form method="POST" action="api/docker/restore" target="overlay-log" id="restore_selection">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<select id="selected_restore_time" name="selected_restore_time" form="restore_selection">
|
||||
@@ -177,14 +189,14 @@
|
||||
<option value="{{ restore_time }}">{{ restore_time }} UTC</option>
|
||||
{% endfor %}
|
||||
</select><br>
|
||||
<input type="checkbox" id="restore-exclude-previews" name="restore-exclude-previews"><label for="restore-exclude-previews">Exclude previews from restore which will speed up the restore process but will trigger a scan of the preview folder as soon as the Nextcloud container starts the next time</label><br>
|
||||
<input type="submit" value="Restore selected backup" onclick="return confirm('⚠️ Important: If the backup that you want to restore contained any community container, you need to restore the same backup a second time after this attempt so that the community container data is also correctly restored.')"/>
|
||||
<input type="checkbox" id="restore-exclude-previews" name="restore-exclude-previews"><label for="restore-exclude-previews">{{ t('Exclude previews from restore which will speed up the restore process but will trigger a scan of the preview folder as soon as the Nextcloud container starts the next time') }}</label><br>
|
||||
<input type="submit" value="{{ t('Restore selected backup') }}" onclick="return confirm('{{ confirmRestore|e('js') }}')"/>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% elseif borg_backup_mode == 'restore' %}
|
||||
{% if backup_exit_code > 0 %}
|
||||
<p><span class="status error"></span> Last restore failed! (<a href="log?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
|
||||
<p>The restore process has unexpectedly failed! Please adjust the path and encryption password, test it and try to restore again!</p>
|
||||
<p><span class="status error"></span> {{ t('Last restore failed!') }} (<a href="log?id=nextcloud-aio-borgbackup" target="_blank">{{ t('Logs') }}</a>)</p>
|
||||
<p>{{ t('The restore process has unexpectedly failed! Please adjust the path and encryption password, test it and try to restore again!') }}</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -192,51 +204,51 @@
|
||||
{% if not hasBackupLocation or borg_backup_mode not in ['test', 'check', ''] or backup_exit_code > 0 %}
|
||||
{% if borg_remote_repo and backup_exit_code > 0 %}
|
||||
<p>
|
||||
You may still need to authorize this pubkey on your borg remote:<br><strong>{{ borg_public_key }}</strong><br>
|
||||
To try again, resubmit your location and rerun the test.
|
||||
{{ t('You may still need to authorize this pubkey on your borg remote:') }}<br><strong>{{ borg_public_key }}</strong><br>
|
||||
{{ t('To try again, resubmit your location and rerun the test.') }}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
<p>
|
||||
Please enter the location of the backup archive on your host or a
|
||||
<a target="_blank" href="https://borgbackup.readthedocs.io/en/stable/usage/general.html#repository-urls">remote borg repo url</a>
|
||||
if stored remotely; and the encryption password of the backup archive below and submit all values:
|
||||
{{ t('Please enter the location of the backup archive on your host or a') }}
|
||||
<a target="_blank" href="https://borgbackup.readthedocs.io/en/stable/usage/general.html#repository-urls">{{ t('remote borg repo url') }}</a>
|
||||
{{ t('if stored remotely; and the encryption password of the backup archive below and submit all values:') }}
|
||||
</p>
|
||||
<form method="POST" action="api/configuration" class="xhr">
|
||||
<label>Local backup location</label> <input type="text" id="borg_restore_host_location" name="borg_restore_host_location" value="{{borg_backup_host_location}}" placeholder="/mnt/backup"/><br>
|
||||
<label>Remote borg repo</label> <input type="text" name="borg_restore_remote_repo" value="{{borg_remote_repo}}" placeholder="ssh://user@host:port/path/to/repo"/><br>
|
||||
<label>Borg passphrase</label> <input type="text" id="borg_restore_password" name="borg_restore_password" value="{{borg_restore_password}}" placeholder="encryption password"/><br>
|
||||
<label>{{ t('Local backup location') }}</label> <input type="text" id="borg_restore_host_location" name="borg_restore_host_location" value="{{borg_backup_host_location}}" placeholder="/mnt/backup"/><br>
|
||||
<label>{{ t('Remote borg repo') }}</label> <input type="text" name="borg_restore_remote_repo" value="{{borg_remote_repo}}" placeholder="ssh://user@host:port/path/to/repo"/><br>
|
||||
<label>{{ t('Borg passphrase') }}</label> <input type="text" id="borg_restore_password" name="borg_restore_password" value="{{borg_restore_password}}" placeholder="{{ t('encryption password') }}"/><br>
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Submit location and encryption password" />
|
||||
<input type="submit" value="{{ t('Submit location and encryption password') }}" />
|
||||
</form>
|
||||
{{ include('includes/backup-dirs.twig') }}
|
||||
<p>⚠️ Please note that the backup archive must be located in a subfolder of the folder that you enter here and the subfolder which contains the archive must be named 'borg', or the backup container will not be able to find the backup archive!</p>
|
||||
<p>⚠️ {{ t('Please note that the backup archive must be located in a subfolder of the folder that you enter here and the subfolder which contains the archive must be named \'borg\', or the backup container will not be able to find the backup archive!') }}</p>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p><strong>Everything set!</strong> Click on the button below to test the path and encryption password:</p>
|
||||
<form method="POST" action="api/docker/backup-test" class="xhr">
|
||||
<p><strong>{{ t('Everything set!') }}</strong> {{ t('Click on the button below to test the path and encryption password:') }}</p>
|
||||
<form method="POST" action="api/docker/backup-test" target="overlay-log">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Test path and encryption password"/>
|
||||
<input type="submit" value="{{ t('Test path and encryption password') }}"/>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<h2>How to reset the AIO instance?</h2>
|
||||
<p>If something should be going wrong, for example during the initial installation, you can reset the instance by following <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-properly-reset-the-instance">this documentation</a>.</p>
|
||||
<h2>{{ t('How to reset the AIO instance?') }}</h2>
|
||||
<p>{{ t('If something should be going wrong, for example during the initial installation, you can reset the instance by following') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-properly-reset-the-instance">{{ t('this documentation') }}</a>.</p>
|
||||
{% endif %}
|
||||
|
||||
{% if was_start_button_clicked == true %}
|
||||
{% if current_channel starts with 'latest' or current_channel starts with 'beta' or current_channel starts with 'develop' %}
|
||||
<p>You are running the <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-switch-the-channel"><strong>{{ current_channel }}</strong></a> channel. (<a href="log?id=nextcloud-aio-mastercontainer" target="_blank">Logs</a>)</p>
|
||||
<p>{{ t('You are running the') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-switch-the-channel"><strong>{{ current_channel }}</strong></a> {{ t('channel.') }} (<a href="log?id=nextcloud-aio-mastercontainer" target="_blank">{{ t('Logs') }}</a>)</p>
|
||||
{% else %}
|
||||
<p>No channel was found. This means that AIO is not able to update itself and its component and will also not be able to report about updates. Updates need to be done externally.</p>
|
||||
<p>{{ t('No channel was found. This means that AIO is not able to update itself and its component and will also not be able to report about updates. Updates need to be done externally.') }}</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if is_backup_container_running == true %}
|
||||
<p><span class="status running"></span> Backup container is currently running: {{ borg_backup_mode }} (<a href="log?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
|
||||
<p><a href="" class="button reload">Reload ↻</a></p>
|
||||
<p><span class="status running"></span> {{ t('Backup container is currently running:') }} {{ borg_backup_mode }} (<a href="log?id=nextcloud-aio-borgbackup" target="_blank">{{ t('Logs') }}</a>)</p>
|
||||
<p><a href="" class="button reload">{{ t('Reload ↻') }}</a></p>
|
||||
{% endif %}
|
||||
|
||||
{% if domain != "" %}
|
||||
@@ -244,30 +256,30 @@
|
||||
{% if isApacheStarting != true %}
|
||||
{% if hasBackupLocation %}
|
||||
<details>
|
||||
<summary>Click here to reveal the initial Nextcloud credentials</summary>
|
||||
<summary>{{ t('Click here to reveal the initial Nextcloud credentials') }}</summary>
|
||||
{% endif %}
|
||||
<p>Initial Nextcloud username: <strong>admin</strong></p>
|
||||
<p>{{ t('Initial Nextcloud username:') }} <strong>admin</strong></p>
|
||||
{% if hasBackupLocation %}
|
||||
{# nextcloud_password needs to be duplicated due to a bug in Firefox. See https://github.com/nextcloud/all-in-one/issues/638. #}
|
||||
<p>Initial Nextcloud password: <strong id="initial-nextcloud-password">{{ nextcloud_password }}</strong></p></details>
|
||||
<p>{{ t('Initial Nextcloud password:') }} <strong id="initial-nextcloud-password">{{ nextcloud_password }}</strong></p></details>
|
||||
{% else %}
|
||||
<p>Initial Nextcloud password: <strong id="initial-nextcloud-password">{{ nextcloud_password }}</strong></p>
|
||||
<p>{{ t('Initial Nextcloud password:') }} <strong id="initial-nextcloud-password">{{ nextcloud_password }}</strong></p>
|
||||
{% endif %}
|
||||
<p><a href="https://{{ domain }}" class="button" target="_blank">Open your Nextcloud ↗</a></p>
|
||||
<p><a href="https://{{ domain }}" class="button" target="_blank">{{ t('Open your Nextcloud ↗') }}</a></p>
|
||||
{% if not hasBackupLocation %}
|
||||
<p>If your Nextcloud does not open when clicking the button above, see <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one/discussions/2105">this documentation</a></strong></p>
|
||||
<p>{{ t('If your Nextcloud does not open when clicking the button above, see') }} <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one/discussions/2105">{{ t('this documentation') }}</a></strong></p>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if isAnyRestarting == false %}
|
||||
<p><span class="status running"></span> Containers are currently starting. You might inspect the container logs by clicking on <strong>Starting</strong> next to each container for further details.</p>
|
||||
<p><a href="" class="button reload">Reload ↻</a></p>
|
||||
<p><span class="status running"></span> {{ t('Containers are currently starting. You might inspect the container logs by clicking on') }} <strong>{{ t('Starting') }}</strong> {{ t('next to each container for further details.') }}</p>
|
||||
<p><a href="" class="button reload">{{ t('Reload ↻') }}</a></p>
|
||||
{% else %}
|
||||
<p>It seems at least one container was not able to start correctly and is currently restarting.</p>
|
||||
<p>To break this endless loop, you can stop the containers below and investigate the issue in the container logs before starting the containers again.</p>
|
||||
<form method="POST" action="api/docker/stop" class="xhr">
|
||||
<p>{{ t('It seems at least one container was not able to start correctly and is currently restarting.') }}</p>
|
||||
<p>{{ t('To break this endless loop, you can stop the containers below and investigate the issue in the container logs before starting the containers again.') }}</p>
|
||||
<form method="POST" action="api/docker/stop" target="overlay-log">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Stop containers" />
|
||||
<input type="submit" value="{{ t('Stop containers') }}" />
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -278,11 +290,11 @@
|
||||
{% endif %}
|
||||
|
||||
{% if was_start_button_clicked == true %}
|
||||
<h2>Containers</h2>
|
||||
<h2>{{ t('Containers') }}</h2>
|
||||
<ul>
|
||||
{# @var containers \AIO\Container\Container[] #}
|
||||
{% for container in containers %}
|
||||
{% if container.displayName != '' %}
|
||||
{% if container.hideFromList != true %}
|
||||
{% include 'components/container-state.twig' with {'c': container} only %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@@ -290,15 +302,15 @@
|
||||
|
||||
{% if has_update_available == true %}
|
||||
{% if is_mastercontainer_update_available == false %}
|
||||
<p>⚠️ Container updates are available. Click on <strong>Stop containers</strong> and <strong>Start and update containers</strong> to update them. You should consider creating a backup first.</p>
|
||||
<p>⚠️ {{ t('Container updates are available. Click on') }} <strong>{{ t('Stop containers') }}</strong> {{ t('and') }} <strong>{{ t('Start and update containers') }}</strong> {{ t('to update them. You should consider creating a backup first.') }}</p>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if is_mastercontainer_update_available == false %}
|
||||
<p>Your containers are up-to-date.</p>
|
||||
<p>{{ t('Your containers are up-to-date.') }}</p>
|
||||
{% if newMajorVersionString != '' and isAnyRunning == true and isApacheStarting != true %}
|
||||
<details>
|
||||
<summary>Note about <strong>Nextcloud Hub {{ newMajorVersionString }}</strong></summary>
|
||||
<p>If you haven't upgraded to Nextcloud Hub {{ newMajorVersionString }} yet and want to do that now, feel free to follow <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one/discussions/7523">this documentation</a></strong></p>
|
||||
<summary>{{ t('Note about') }} <strong>Nextcloud Hub {{ newMajorVersionString }}</strong></summary>
|
||||
<p>{{ t('If you haven\'t upgraded to Nextcloud Hub') }} {{ newMajorVersionString }} {{ t('yet and want to do that now, feel free to follow') }} <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one/discussions/7523">{{ t('this documentation') }}</a></strong></p>
|
||||
</details>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -308,34 +320,34 @@
|
||||
{% if isAnyRunning == true %}
|
||||
{% if isApacheStarting != true %}
|
||||
{% if is_mastercontainer_update_available == true %}
|
||||
<p>⚠️ A mastercontainer update is available. Please click on the button below to stop your containers in order to update the mastercontainer.</p>
|
||||
<p>⚠️ {{ t('A mastercontainer update is available. Please click on the button below to stop your containers in order to update the mastercontainer.') }}</p>
|
||||
{% if current_channel starts with 'latest' %}
|
||||
<p>You can find the changelog <a target="_blank" href="https://github.com/nextcloud/all-in-one/releases/latest"><strong>here</strong></a></p>
|
||||
<p>{{ t('You can find the changelog') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one/releases/latest"><strong>{{ t('here') }}</strong></a></p>
|
||||
{% elseif current_channel starts with 'beta' %}
|
||||
<p>You can find the changelog <a target="_blank" href="https://github.com/nextcloud/all-in-one/releases"><strong>here</strong></a></p>
|
||||
<p>{{ t('You can find the changelog') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one/releases"><strong>{{ t('here') }}</strong></a></p>
|
||||
{% elseif current_channel starts with 'develop' %}
|
||||
<p>You can find all changes <a target="_blank" href="https://github.com/nextcloud-releases/all-in-one/commits/main"><strong>here</strong></a></p>
|
||||
<p>{{ t('You can find all changes') }} <a target="_blank" href="https://github.com/nextcloud-releases/all-in-one/commits/main"><strong>{{ t('here') }}</strong></a></p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<form method="POST" action="api/docker/stop" class="xhr">
|
||||
<form method="POST" action="api/docker/stop" target="overlay-log">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Stop containers" />
|
||||
<input type="submit" value="{{ t('Stop containers') }}" />
|
||||
</form>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if isBackupOrRestoreRunning == true %}
|
||||
<p>Restore or Backup currently running. Cannot start the containers until Restore or Backup is complete.</p>
|
||||
<p>{{ t('Restore or Backup currently running. Cannot start the containers until Restore or Backup is complete.') }}</p>
|
||||
{% else %}
|
||||
{% if was_start_button_clicked == false %}
|
||||
<p>Clicking on the button below will download all docker containers and start them. This can take a long time depending on your internet connection. Since the overall size is a few GB, this can take around 5-10 min or more. Please be patient!</p>
|
||||
<p>{{ t('Clicking on the button below will download all docker containers and start them. This can take a long time depending on your internet connection. Since the overall size is a few GB, this can take around 5-10 min or more. Please be patient!') }}</p>
|
||||
{% endif %}
|
||||
{% if is_mastercontainer_update_available == true %}
|
||||
<p>⚠️ A mastercontainer update is available. Please click on the button below to update it.</p>
|
||||
<form method="POST" action="api/docker/watchtower" class="xhr">
|
||||
<p>⚠️ {{ t('A mastercontainer update is available. Please click on the button below to update it.') }}</p>
|
||||
<form method="POST" action="api/docker/watchtower" target="overlay-log">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Update mastercontainer" />
|
||||
<input type="submit" value="{{ t('Update mastercontainer') }}" />
|
||||
</form>
|
||||
{% else %}
|
||||
{% if was_start_button_clicked == false %}
|
||||
@@ -344,26 +356,30 @@
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input id="base_path" type="hidden" name="base_path" value="">
|
||||
{% if newMajorVersionString != '' %}
|
||||
<input type="checkbox" id="install_latest_major" name="install_latest_major"><label for="install_latest_major">Install Nextcloud Hub {{ newMajorVersionString }} (if unchecked, Nextcloud Hub {{ oldMajorVersionString }} will get installed)</label><br>
|
||||
<input type="checkbox" id="install_latest_major" name="install_latest_major"><label for="install_latest_major">{{ t('Install Nextcloud Hub') }} {{ newMajorVersionString }} {{ t('(if unchecked, Nextcloud Hub') }} {{ oldMajorVersionString }} {{ t('will get installed)') }}</label><br>
|
||||
{% endif %}
|
||||
<input type="submit" value="Download and start containers" />
|
||||
<input type="submit" value="{{ t('Download and start containers') }}" />
|
||||
</form>
|
||||
{% elseif has_update_available == false %}
|
||||
<form method="POST" action="api/docker/start" target="overlay-log">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input id="base_path" type="hidden" name="base_path" value="">
|
||||
<input type="submit" value="Start containers" />
|
||||
{% if bypass_container_update == true %}
|
||||
<input type="hidden" name="bypass_container_update" value="true">
|
||||
{% endif %}
|
||||
<input type="submit" value="{{ t('Start containers') }}" />
|
||||
</form>
|
||||
{% else %}
|
||||
{% set confirmStartUpdate = t('Start and update containers? You should consider creating a backup first.') %}
|
||||
<form method="POST" action="api/docker/start" target="overlay-log">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input id="base_path" type="hidden" name="base_path" value="">
|
||||
{% if bypass_container_update == true %}
|
||||
<input type="hidden" name="bypass_container_update" value="{{bypass_container_update}}">
|
||||
<input type="hidden" name="bypass_container_update" value="true">
|
||||
{% endif %}
|
||||
<input class="button " type="submit" value="Start and update containers" onclick="return confirm('Start and update containers? You should consider creating a backup first.')" />
|
||||
<input class="button " type="submit" value="{{ t('Start and update containers') }}" onclick="return confirm('{{ confirmStartUpdate|e('js') }}')" />
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -373,23 +389,23 @@
|
||||
{% if was_start_button_clicked == true %}
|
||||
|
||||
{% if is_backup_section_enabled == false %}
|
||||
<h2>Backup and restore</h2>
|
||||
<p>The backup section is disabled via environmental variable.</p>
|
||||
<h2>{{ t('Backup and restore') }}</h2>
|
||||
<p>{{ t('The backup section is disabled via environmental variable.') }}</p>
|
||||
{% else %}
|
||||
{% if is_backup_container_running == false and not hasBackupLocation and isApacheStarting != true %}
|
||||
<h2>Backup and restore</h2>
|
||||
<p>Please enter the directory path below where backups will be created on the host system and submit it. It's best to choose a location on a separate drive and not on your root drive.</p>
|
||||
<h2>{{ t('Backup and restore') }}</h2>
|
||||
<p>{{ t('Please enter the directory path below where backups will be created on the host system and submit it. It\'s best to choose a location on a separate drive and not on your root drive.') }}</p>
|
||||
<p>
|
||||
To store backups remotely instead, fill in the
|
||||
<a target="_blank" href="https://borgbackup.readthedocs.io/en/stable/usage/general.html#repository-urls">remote borg repo url and submit it</a>.
|
||||
You will be provided with an SSH public key for authorization at the remote afterwards.
|
||||
{{ t('To store backups remotely instead, fill in the') }}
|
||||
<a target="_blank" href="https://borgbackup.readthedocs.io/en/stable/usage/general.html#repository-urls">{{ t('remote borg repo url and submit it') }}</a>.
|
||||
{{ t('You will be provided with an SSH public key for authorization at the remote afterwards.') }}
|
||||
</p>
|
||||
<form method="POST" action="api/configuration" class="xhr">
|
||||
<label>Local backup location</label> <input type="text" id="borg_backup_host_location" name="borg_backup_host_location" placeholder="/mnt/backup"/><br>
|
||||
<label>Remote borg repo</label> <input type="text" name="borg_remote_repo" placeholder="ssh://user@host:port/path/to/repo"/><br>
|
||||
<label>{{ t('Local backup location') }}</label> <input type="text" id="borg_backup_host_location" name="borg_backup_host_location" placeholder="/mnt/backup"/><br>
|
||||
<label>{{ t('Remote borg repo') }}</label> <input type="text" name="borg_remote_repo" placeholder="ssh://user@host:port/path/to/repo"/><br>
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Submit backup location" />
|
||||
<input type="submit" value="{{ t('Submit backup location') }}" />
|
||||
</form>
|
||||
{{ include('includes/backup-dirs.twig') }}
|
||||
{% endif %}
|
||||
@@ -399,45 +415,46 @@
|
||||
|
||||
{% if hasBackupLocation %}
|
||||
{% if is_backup_container_running == false %}
|
||||
<h2>Backup and restore</h2>
|
||||
<h2>{{ t('Backup and restore') }}</h2>
|
||||
{% if backup_exit_code > 0 %}
|
||||
<p><span class="status error"></span> Last {{ borg_backup_mode }} failed! (<a href="log?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
|
||||
<p><span class="status error"></span> {{ t('Last') }} {{ borg_backup_mode }} {{ t('failed!') }} (<a href="log?id=nextcloud-aio-borgbackup" target="_blank">{{ t('Logs') }}</a>)</p>
|
||||
{% if borg_backup_mode == "check" %}
|
||||
<p>The backup check was not successful. This might indicate a corrupt archive (look at the logs). If that should be the case, you can try to fix it by following <a target="_blank" href="https://borgbackup.readthedocs.io/en/stable/faq.html#i-get-an-integrityerror-or-similar-what-now"><strong>this documentation</strong></a></p>
|
||||
<p>{{ t('The backup check was not successful. This might indicate a corrupt archive (look at the logs). If that should be the case, you can try to fix it by following') }} <a target="_blank" href="https://borgbackup.readthedocs.io/en/stable/faq.html#i-get-an-integrityerror-or-similar-what-now"><strong>{{ t('this documentation') }}</strong></a></p>
|
||||
<details>
|
||||
<summary>Reveal repair option</summary>
|
||||
<p>Below is the option to repair the integrity of your backup. <strong>Please note:</strong> Please only use this after you have read the documentation above! (It will run the command 'borg check --repair' for you.)</p>
|
||||
<form method="POST" action="api/docker/backup-check-repair" class="xhr">
|
||||
<summary>{{ t('Reveal repair option') }}</summary>
|
||||
<p>{{ t('Below is the option to repair the integrity of your backup.') }} <strong>{{ t('Please note:') }}</strong> {{ t('Please only use this after you have read the documentation above! (It will run the command \'borg check --repair\' for you.)') }}</p>
|
||||
{% set confirmRepair = t('Check and repair backup integrity? Are you sure that you want to check and repair the backup integrity? This should only be done after reading the mentioned documentation.') %}
|
||||
<form method="POST" action="api/docker/backup-check-repair" target="overlay-log">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Check and repair backup integrity" onclick="return confirm('Check and repair backup integrity? Are you sure that you want to check and repair the backup integrity? This should only be done after reading the mentioned documentation.')"/>
|
||||
<input type="submit" value="{{ t('Check and repair backup integrity') }}" onclick="return confirm('{{ confirmRepair|e('js') }}')"/>
|
||||
</form>
|
||||
</details>
|
||||
{% endif %}
|
||||
{% if has_backup_run_once == false %}
|
||||
<p>The initial backup was not successful.</p>
|
||||
<p>{{ t('The initial backup was not successful.') }}</p>
|
||||
|
||||
{% if borg_remote_repo %}
|
||||
<p>
|
||||
You may still need to authorize this pubkey on your borg remote:<br><strong>{{ borg_public_key }}</strong><br>
|
||||
To try again, click <strong>Create backup</strong>.
|
||||
{{ t('You may still need to authorize this pubkey on your borg remote:') }}<br><strong>{{ borg_public_key }}</strong><br>
|
||||
{{ t('To try again, click') }} <strong>{{ t('Create backup') }}</strong>.
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
<p>You may change the backup path again since the initial backup was not successful. After submitting the new value, you need to click on <strong>Create Backup</strong> to test the new value.</p>
|
||||
<p>{{ t('You may change the backup path again since the initial backup was not successful. After submitting the new value, you need to click on') }} <strong>{{ t('Create Backup') }}</strong> {{ t('to test the new value.') }}</p>
|
||||
<form method="POST" action="api/configuration" class="xhr">
|
||||
<label>Local backup location</label> <input type="text" name="borg_backup_host_location" placeholder="/mnt/backup"/><br>
|
||||
<label>Remote borg repo</label> <input type="text" name="borg_remote_repo" placeholder="ssh://user@host:port/path/to/repo"/><br>
|
||||
<label>{{ t('Local backup location') }}</label> <input type="text" name="borg_backup_host_location" placeholder="/mnt/backup"/><br>
|
||||
<label>{{ t('Remote borg repo') }}</label> <input type="text" name="borg_remote_repo" placeholder="ssh://user@host:port/path/to/repo"/><br>
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Set backup location again" />
|
||||
<input type="submit" value="{{ t('Set backup location again') }}" />
|
||||
</form>
|
||||
{% endif %}
|
||||
{% elseif backup_exit_code == 0 %}
|
||||
{% if borg_backup_mode == "backup" %}
|
||||
<p><span class="status success"></span> Last {{ borg_backup_mode }} successful on {{ last_backup_time }} UTC! (<a href="log?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
|
||||
<p><span class="status success"></span> {{ t('Last') }} {{ borg_backup_mode }} {{ t('successful on') }} {{ last_backup_time }} UTC! (<a href="log?id=nextcloud-aio-borgbackup" target="_blank">{{ t('Logs') }}</a>)</p>
|
||||
{% else %}
|
||||
<p><span class="status success"></span> Last {{ borg_backup_mode }} successful! (<a href="log?id=nextcloud-aio-borgbackup" target="_blank">Logs</a>)</p>
|
||||
<p><span class="status success"></span> {{ t('Last') }} {{ borg_backup_mode }} {{ t('successful!') }} (<a href="log?id=nextcloud-aio-borgbackup" target="_blank">{{ t('Logs') }}</a>)</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -445,54 +462,57 @@
|
||||
{% if is_backup_container_running == false and isApacheStarting == false %}
|
||||
{% if has_backup_run_once == true %}
|
||||
<details>
|
||||
<summary>Click here to reveal all backup options (including an option for automatic updates)</summary>
|
||||
<summary>{{ t('Click here to reveal all backup options (including an option for automatic updates)') }}</summary>
|
||||
{% endif %}
|
||||
<h3>Backup information</h3>
|
||||
<p>This is your encryption password for backups: <strong id="borg-backup-password">{{ borgbackup_password }}</strong></p>
|
||||
<p>Please save this password in a safe place. You won't be able to restore from backup if you lose this password!</p>
|
||||
<p>All important data from your Nextcloud AIO instance such as the database, your files and the mastercontainer's configuration files, will be backed up.</p>
|
||||
<p>The backup uses a tool called <a target="_blank" href="https://github.com/borgbackup/borg#what-is-borgbackup"><strong>BorgBackup</strong></a>, a well-known server backup tool that efficiently backs up your files and encrypts them on the fly.</p>
|
||||
<p>By using this tool, backups are incremental, differential, compressed and encrypted – so only the first backup will take a while. Further backups should be fast as only changes are taken into account.</p>
|
||||
<h3>{{ t('Backup information') }}</h3>
|
||||
<p>{{ t('This is your encryption password for backups:') }} <strong id="borg-backup-password">{{ borgbackup_password }}</strong></p>
|
||||
<p>{{ t('Please save this password in a safe place. You won\'t be able to restore from backup if you lose this password!') }}</p>
|
||||
<p>{{ t('All important data from your Nextcloud AIO instance such as the database, your files and the mastercontainer\'s configuration files, will be backed up.') }}</p>
|
||||
<p>{{ t('The backup uses a tool called') }} <a target="_blank" href="https://github.com/borgbackup/borg#what-is-borgbackup"><strong>BorgBackup</strong></a>, {{ t('a well-known server backup tool that efficiently backs up your files and encrypts them on the fly.') }}</p>
|
||||
<p>{{ t('By using this tool, backups are incremental, differential, compressed and encrypted – so only the first backup will take a while. Further backups should be fast as only changes are taken into account.') }}</p>
|
||||
{% if borg_remote_repo != '' %}
|
||||
<p>
|
||||
Backups get created remotely at:<br>
|
||||
{{ t('Backups get created remotely at:') }}<br>
|
||||
<strong>{{ borg_remote_repo }}</strong>
|
||||
{% if has_backup_run_once == true %}
|
||||
<br/>Your borg ssh public key is:<br><strong>{{ borg_public_key }}</strong>
|
||||
<br/>{{ t('Your borg ssh public key is:') }}<br><strong>{{ borg_public_key }}</strong>
|
||||
{% endif %}
|
||||
</p>
|
||||
{% else %}
|
||||
<p>Backups will be created in the following directory on the host: <strong>{{ borg_backup_host_location }}/borg</strong></p>
|
||||
<p>{{ t('Backups will be created in the following directory on the host:') }} <strong>{{ borg_backup_host_location }}/borg</strong></p>
|
||||
{% endif %}
|
||||
<p>Be aware that this solution does not backup files and folders that are mounted into Nextcloud using the external storage app, but you can add further Docker volumes and host paths that you want to back up after the initial backup is done.</p>
|
||||
<p>For information about backup retention, see <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-adjust-borgs-retention-policy">this</a></strong>.</p>
|
||||
<p>Daily backups can be enabled after the initial backup is done. Enabling this also allows you to enable an option to update all containers, Nextcloud, and its apps automatically.</p>
|
||||
<p>For further documentation and options on this backup solution refer to <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one#backup">this section</a></strong> and below.</p>
|
||||
<p>{{ t('Be aware that this solution does not backup files and folders that are mounted into Nextcloud using the external storage app, but you can add further Docker volumes and host paths that you want to back up after the initial backup is done.') }}</p>
|
||||
<p>{{ t('For information about backup retention, see') }} <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-adjust-borgs-retention-policy">{{ t('this') }}</a></strong>.</p>
|
||||
<p>{{ t('Daily backups can be enabled after the initial backup is done. Enabling this also allows you to enable an option to update all containers, Nextcloud, and its apps automatically.') }}</p>
|
||||
<p>{{ t('For further documentation and options on this backup solution refer to') }} <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one#backup">{{ t('this section') }}</a></strong> {{ t('and below.') }}</p>
|
||||
|
||||
{% if isApacheStarting != true %}
|
||||
<h3>Backup creation</h3>
|
||||
<p>Clicking on the button below will create a backup.</p>
|
||||
<form method="POST" action="api/docker/backup" class="xhr">
|
||||
<h3>{{ t('Backup creation') }}</h3>
|
||||
<p>{{ t('Clicking on the button below will create a backup.') }}</p>
|
||||
{% set confirmBackup = t('Create backup? Are you sure that you want to create a backup? This will stop all running containers and create the backup.') %}
|
||||
<form method="POST" action="api/docker/backup" target="overlay-log">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Create backup" onclick="return confirm('Create backup? Are you sure that you want to create a backup? This will stop all running containers and create the backup.')" />
|
||||
<input type="submit" value="{{ t('Create backup') }}" onclick="return confirm('{{ confirmBackup|e('js') }}')" />
|
||||
</form>
|
||||
|
||||
{% if has_backup_run_once == true %}
|
||||
<h3>Backup Viewer</h3>
|
||||
<p>There is now a community container that allows to access your backups in a web session. See <a target="_blank" href="https://github.com/nextcloud/all-in-one/tree/main/community-containers/borgbackup-viewer"><strong>this documentation</strong></a>.</p>
|
||||
<h3>{{ t('Backup Viewer') }}</h3>
|
||||
<p>{{ t('There is now a community container that allows to access your backups in a web session. See') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one/tree/main/community-containers/borgbackup-viewer"><strong>{{ t('this documentation') }}</strong></a>.</p>
|
||||
|
||||
<h3>Backup check</h3>
|
||||
<p>Click on the button below to perform a backup integrity check. This is an option that verifies that your backup is intact. It shouldn't be needed in most situations.</p>
|
||||
<form method="POST" action="api/docker/backup-check" class="xhr">
|
||||
<h3>{{ t('Backup check') }}</h3>
|
||||
<p>{{ t('Click on the button below to perform a backup integrity check. This is an option that verifies that your backup is intact. It shouldn\'t be needed in most situations.') }}</p>
|
||||
{% set confirmCheck = t('Check backup integrity? Are you sure that you want to check the backup? This can take a long time depending on the size of your backup.') %}
|
||||
<form method="POST" action="api/docker/backup-check" target="overlay-log">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Check backup integrity" onclick="return confirm('Check backup integrity? Are you sure that you want to check the backup? This can take a long time depending on the size of your backup.')" />
|
||||
<input type="submit" value="{{ t('Check backup integrity') }}" onclick="return confirm('{{ confirmCheck|e('js') }}')" />
|
||||
</form>
|
||||
|
||||
<h3>Backup restore</h3>
|
||||
<p>Choose the backup that you want to restore and click on the button below to restore the selected backup. This will overwrite all your files with the chosen backup so you should consider creating a backup first. You can run an integrity check before restoring your files but this shouldn't be needed in most situations. Please note that this will not restore additionally chosen backup directories! The restore process should be pretty fast as rsync, which only transfers changed files, is used to restore the chosen backup.</p>
|
||||
<form method="POST" action="api/docker/restore" class="xhr" id="restore_selection">
|
||||
<h3>{{ t('Backup restore') }}</h3>
|
||||
<p>{{ t('Choose the backup that you want to restore and click on the button below to restore the selected backup. This will overwrite all your files with the chosen backup so you should consider creating a backup first. You can run an integrity check before restoring your files but this shouldn\'t be needed in most situations. Please note that this will not restore additionally chosen backup directories! The restore process should be pretty fast as rsync, which only transfers changed files, is used to restore the chosen backup.') }}</p>
|
||||
{% set confirmRestoreSelected = t('Restore the selected backup? Are you sure that you want to restore the selected backup? This will stop all running containers and restore the selected backup. It is recommended to create a backup first. You might also want to check the backup integrity.') %}
|
||||
<form method="POST" action="api/docker/restore" target="overlay-log" id="restore_selection">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<select id="selected_restore_time" name="selected_restore_time" form="restore_selection">
|
||||
@@ -500,74 +520,75 @@
|
||||
<option value="{{ restore_time }}">{{ restore_time }} UTC</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<input type="submit" value="Restore selected backup" onclick="return confirm('Restore the selected backup? Are you sure that you want to restore the selected backup? This will stop all running containers and restore the selected backup. It is recommended to create a backup first. You might also want to check the backup integrity.')" />
|
||||
<input type="submit" value="{{ t('Restore selected backup') }}" onclick="return confirm('{{ confirmRestoreSelected|e('js') }}')" />
|
||||
</form>
|
||||
|
||||
<h3>Update backup list</h3>
|
||||
<h3>{{ t('Update backup list') }}</h3>
|
||||
<details>
|
||||
<summary>Click here to reveal this option</summary>
|
||||
<p>If you use an external snapshot tool to restore the server that runs AIO, you might run into a problem that the above listed available backups are not up-to-date to restore your server from. You can click the button below to update this list.</p>
|
||||
<form method="POST" action="api/docker/backup-list" class="xhr">
|
||||
<summary>{{ t('Click here to reveal this option') }}</summary>
|
||||
<p>{{ t('If you use an external snapshot tool to restore the server that runs AIO, you might run into a problem that the above listed available backups are not up-to-date to restore your server from. You can click the button below to update this list.') }}</p>
|
||||
<form method="POST" action="api/docker/backup-list" target="overlay-log">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Update backup list" />
|
||||
<input type="submit" value="{{ t('Update backup list') }}" />
|
||||
</form>
|
||||
</details>
|
||||
|
||||
<h3>Daily backup and automatic updates</h3>
|
||||
<h3>{{ t('Daily backup and automatic updates') }}</h3>
|
||||
{% if daily_backup_time == "" %}
|
||||
<p>By entering a time below and submitting it, you can enable daily backups. It will create them at the entered time in 24h format. E.g. <strong>04:00</strong> will create backups at 4 am UTC and <strong>16:00</strong> at 4 pm UTC. When creating the backup, containers will be stopped and restarted after the backup is complete.</p>
|
||||
<p>{{ t('By entering a time below and submitting it, you can enable daily backups. It will create them at the entered time in 24h format. E.g.') }} <strong>04:00</strong> {{ t('will create backups at 4 am UTC and') }} <strong>16:00</strong> {{ t('at 4 pm UTC. When creating the backup, containers will be stopped and restarted after the backup is complete.') }}</p>
|
||||
<form method="POST" action="api/configuration" class="xhr">
|
||||
<input type="text" name="daily_backup_time" placeholder="04:00"/>
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Submit daily backup time and settings" /><br>
|
||||
<input type="checkbox" id="automatic_updates" name="automatic_updates" checked="checked"><label for="automatic_updates">Automatically update all containers, the mastercontainer and on saturdays your Nextcloud apps</label><br>
|
||||
<input type="checkbox" id="success_notification" name="success_notification" checked="checked"><label for="success_notification">Send notifications about successful backups (notifications about unsuccessful backups will always be sent)</label>
|
||||
<input type="submit" value="{{ t('Submit daily backup time and settings') }}" /><br>
|
||||
<input type="checkbox" id="automatic_updates" name="automatic_updates" checked="checked"><label for="automatic_updates">{{ t('Automatically update all containers, the mastercontainer and on saturdays your Nextcloud apps') }}</label><br>
|
||||
<input type="checkbox" id="success_notification" name="success_notification" checked="checked"><label for="success_notification">{{ t('Send notifications about successful backups (notifications about unsuccessful backups will always be sent)') }}</label>
|
||||
</form>
|
||||
{% else %}
|
||||
<p>Daily backups will be created at <strong>{{ daily_backup_time }} UTC</strong>. A notification about the result of the backup will be sent.</p>
|
||||
<p>{{ t('Daily backups will be created at') }} <strong>{{ daily_backup_time }} UTC</strong>. {{ t('A notification about the result of the backup will be sent.') }}</p>
|
||||
{% if automatic_updates == true %}
|
||||
Also your containers, the mastercontainer and, on Saturdays, your Nextcloud apps will be automatically updated.
|
||||
{{ t('Also your containers, the mastercontainer and, on Saturdays, your Nextcloud apps will be automatically updated.') }}
|
||||
{% endif %}
|
||||
<p>To change your backup time first disable Daily Backups, then enter your new backup time, and then re-enable them.</p>
|
||||
<p>{{ t('To change your backup time first disable Daily Backups, then enter your new backup time, and then re-enable them.') }}</p>
|
||||
<form method="POST" action="api/configuration" class="xhr">
|
||||
<input type="hidden" name="delete_daily_backup_time" value="yes"/>
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Disable or change daily backup settings" />
|
||||
<input type="submit" value="{{ t('Disable or change daily backup settings') }}" />
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
<h3>Back up additional directories and docker volumes of your host</h3>
|
||||
<p>Below you can enter directories and docker volumes of your host that will be backed up into the same borg backup archive. Make sure to press the submit button after changing anything.</p>
|
||||
<h3>{{ t('Back up additional directories and docker volumes of your host') }}</h3>
|
||||
<p>{{ t('Below you can enter directories and docker volumes of your host that will be backed up into the same borg backup archive. Make sure to press the submit button after changing anything.') }}</p>
|
||||
<form method="POST" action="api/configuration" class="xhr">
|
||||
<textarea id="additional_backup_directories" name="additional_backup_directories" rows="4" cols="50" placeholder="/directory/on/the/host my_custom_docker_volume">{{ additional_backup_directories }}</textarea>
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Submit additional backup locations" />
|
||||
<input type="submit" value="{{ t('Submit additional backup locations') }}" />
|
||||
</form>
|
||||
<p>Each line and entry needs to start with a slash or letter/digit. Only <strong>a-z</strong>, <strong>A-Z</strong>, <strong>.</strong>, <strong>0-9</strong>, <strong>_</strong>, <strong>-</strong>, and <strong>/</strong> are allowed. If the entry begins with a letter/digit slashes are not supported. Two valid entries are <strong>/directory/on/the/host</strong> and <strong>my_custom_docker_volume</strong>. You need to make sure that all given directories exist or the backup container will fail to start!</p>
|
||||
<p>Be sure to individually specify all storage that you want to back up as storage will not be mounted recursively. E.g. providing <strong>/</strong> as additional backup directory will only back up files and folders that are stored on the root partition and not on the EFI partition or any other. Excluded by the backup will be caches and a few other directories. If you want to back up the root partition you should make sure to stop all services before the backup so it can run correctly. For automating this see <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-stopstartupdate-containers-or-trigger-the-daily-backup-from-a-script-externally">this documentation</a></p>
|
||||
<p>Please note that the chosen directories/volumes will not be restored when you restore your instance, so this would need to be done manually.</p>
|
||||
<p>{{ t('Each line and entry needs to start with a slash or letter/digit. Only') }} <strong>a-z</strong>, <strong>A-Z</strong>, <strong>.</strong>, <strong>0-9</strong>, <strong>_</strong>, <strong>-</strong>, {{ t('and') }} <strong>/</strong> {{ t('are allowed. If the entry begins with a letter/digit slashes are not supported. Two valid entries are') }} <strong>/directory/on/the/host</strong> {{ t('and') }} <strong>my_custom_docker_volume</strong>. {{ t('You need to make sure that all given directories exist or the backup container will fail to start!') }}</p>
|
||||
<p>{{ t('Be sure to individually specify all storage that you want to back up as storage will not be mounted recursively. E.g. providing') }} <strong>/</strong> {{ t('as additional backup directory will only back up files and folders that are stored on the root partition and not on the EFI partition or any other. Excluded by the backup will be caches and a few other directories. If you want to back up the root partition you should make sure to stop all services before the backup so it can run correctly. For automating this see') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-stopstartupdate-containers-or-trigger-the-daily-backup-from-a-script-externally">{{ t('this documentation') }}</a></p>
|
||||
<p>{{ t('Please note that the chosen directories/volumes will not be restored when you restore your instance, so this would need to be done manually.') }}</p>
|
||||
{% if additional_backup_directories != "" %}
|
||||
<p>This option is currently set. You can disable it again by clearing the field and submitting your changes.</p>
|
||||
<p>{{ t('This option is currently set. You can disable it again by clearing the field and submitting your changes.') }}</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<h3>Reset backup location</h3>
|
||||
<h3>{{ t('Reset backup location') }}</h3>
|
||||
<p>
|
||||
If the configured backup host location <strong>{{ borg_backup_host_location }}</strong>
|
||||
{{ t('If the configured backup host location') }} <strong>{{ borg_backup_host_location }}</strong>
|
||||
{% if borg_remote_repo %}
|
||||
or the remote repo <strong>{{ borg_remote_repo }}</strong>
|
||||
{{ t('or the remote repo') }} <strong>{{ borg_remote_repo }}</strong>
|
||||
{% endif %}
|
||||
is wrong or if you want to reset the backup location due to other reasons, you can do so by clicking on the button below.
|
||||
{{ t('is wrong or if you want to reset the backup location due to other reasons, you can do so by clicking on the button below.') }}
|
||||
</p>
|
||||
{% set confirmResetLocation = t('Are you sure that you want to reset the backup location?') %}
|
||||
<form method="POST" action="api/configuration" class="xhr">
|
||||
<input type="hidden" name="delete_borg_backup_location_vars" value="yes"/>
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Reset backup location" onclick="return confirm('Are you sure that you want to reset the backup location?')" />
|
||||
<input type="submit" value="{{ t('Reset backup location') }}" onclick="return confirm('{{ confirmResetLocation|e('js') }}')" />
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if has_backup_run_once == true %}
|
||||
@@ -579,18 +600,18 @@
|
||||
|
||||
{% if is_backup_container_running == false %}
|
||||
{% if isApacheStarting == false %}
|
||||
<h2>AIO passphrase change</h2>
|
||||
<h2>{{ t('AIO passphrase change') }}</h2>
|
||||
<details>
|
||||
<summary>Click here to change your AIO passphrase</summary>
|
||||
<p>You can change your AIO passphrase below:</p>
|
||||
<summary>{{ t('Click here to change your AIO passphrase') }}</summary>
|
||||
<p>{{ t('You can change your AIO passphrase below:') }}</p>
|
||||
<form method="POST" action="api/configuration" class="xhr">
|
||||
<input type="password" autocomplete="current-password" name="current-master-password" placeholder="Your current AIO passphrase" id="current-master-password" oninput="showPassword('current-master-password')">
|
||||
<input type="password" autocomplete="new-password" name="new-master-password" placeholder="Your new AIO passphrase" id="new-master-password" oninput="showPassword('new-master-password')">
|
||||
<input type="password" autocomplete="current-password" name="current-master-password" placeholder="{{ t('Your current AIO passphrase') }}" id="current-master-password" oninput="showPassword('current-master-password')">
|
||||
<input type="password" autocomplete="new-password" name="new-master-password" placeholder="{{ t('Your new AIO passphrase') }}" id="new-master-password" oninput="showPassword('new-master-password')">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Submit passphrase change" />
|
||||
<input type="submit" value="{{ t('Submit passphrase change') }}" />
|
||||
</form>
|
||||
<p>The new passphrase needs to be at least 24 characters long. Allowed characters are the <a target="_blank" href="https://en.wikipedia.org/wiki/Latin_alphabet#/media/File:Abecedarium.png"><strong>latin characters</strong></a> <strong>a-z</strong>, <strong>A-Z</strong>, <strong>0-9</strong> and <strong>spaces</strong>.</p>
|
||||
<p>{{ t('The new passphrase needs to be at least 24 characters long. Allowed characters are the') }} <a target="_blank" href="https://en.wikipedia.org/wiki/Latin_alphabet#/media/File:Abecedarium.png"><strong>{{ t('latin characters') }}</strong></a> <strong>a-z</strong>, <strong>A-Z</strong>, <strong>0-9</strong> {{ t('and spaces.') }}</p>
|
||||
</details>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -599,30 +620,31 @@
|
||||
|
||||
{{ include('includes/optional-containers.twig') }}
|
||||
|
||||
<h2>Timezone change</h2>
|
||||
<h2>{{ t('Timezone change') }}</h2>
|
||||
{% if isAnyRunning == true %}
|
||||
{% if timezone != "" %}
|
||||
<p>The timezone for Nextcloud is currently set to <strong>{{ timezone }}</strong>.</p>
|
||||
<p>{{ t('The timezone for Nextcloud is currently set to') }} <strong>{{ timezone }}</strong>.</p>
|
||||
{% endif %}
|
||||
<p><strong>Please note:</strong> You can change the timezone when your containers are stopped.</p>
|
||||
<p><strong>{{ t('Please note:') }}</strong> {{ t('You can change the timezone when your containers are stopped.') }}</p>
|
||||
{% else %}
|
||||
{% if timezone == "" %}
|
||||
<p>To get the correct time values for certain Nextcloud features, set the timezone for Nextcloud to the one that your users mainly use. Please note that this setting does not apply to the mastercontainer and any backup option.</p>
|
||||
<p>You can configure the timezone for Nextcloud below (Do not forget to submit the value!):</p>
|
||||
<p>{{ t('To get the correct time values for certain Nextcloud features, set the timezone for Nextcloud to the one that your users mainly use. Please note that this setting does not apply to the mastercontainer and any backup option.') }}</p>
|
||||
<p>{{ t('You can configure the timezone for Nextcloud below (Do not forget to submit the value!):') }}</p>
|
||||
{% set confirmTimezone = t('Are you sure that this is a valid timezone? Please double check by following the wikipedia article and checking the correct column. If the timezone is not valid, it will break the startup since the database will not be correctly initialized and you will end up in a startup loop.') %}
|
||||
<form method="POST" action="api/configuration" class="xhr">
|
||||
<input type="text" id="timezone" name="timezone" placeholder="Europe/Berlin" />
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Submit timezone" onclick="return confirm('Are you sure that this is a valid timezone? Please double check by following the wikipedia article and checking the correct column. If the timezone is not valid, it will break the startup since the database will not be correctly initialized and you will end up in a startup loop.')" />
|
||||
<input type="submit" value="{{ t('Submit timezone') }}" onclick="return confirm('{{ confirmTimezone|e('js') }}')" />
|
||||
</form>
|
||||
<p>You need to make sure that the timezone that you enter is valid. An example is <strong>Europe/Berlin</strong>. You can get valid values by looking at the 'TZ identifier' column of this list: <a target="_blank" href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List"><strong>click here</strong></a>. The default is <strong>Etc/UTC</strong> if nothing is entered.</p>
|
||||
<p>{{ t('You need to make sure that the timezone that you enter is valid. An example is') }} <strong>Europe/Berlin</strong>. {{ t('You can get valid values by looking at the \'TZ identifier\' column of this list:') }} <a target="_blank" href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List"><strong>{{ t('click here') }}</strong></a>. {{ t('The default is') }} <strong>Etc/UTC</strong> {{ t('if nothing is entered.') }}</p>
|
||||
{% else %}
|
||||
<p>The timezone for Nextcloud is currently set to <strong>{{ timezone }}</strong>. You can change the timezone by clicking on the button below.</p>
|
||||
<p>{{ t('The timezone for Nextcloud is currently set to') }} <strong>{{ timezone }}</strong>. {{ t('You can change the timezone by clicking on the button below.') }}</p>
|
||||
<form method="POST" action="api/configuration" class="xhr">
|
||||
<input type="hidden" name="delete_timezone" value="yes"/>
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Reset the timezone" />
|
||||
<input type="submit" value="{{ t('Reset the timezone') }}" />
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
<details>
|
||||
<summary>Click here to view the current AIO config and documentation links</summary>
|
||||
<summary>{{ t('Click here to view the current AIO config and documentation links') }}</summary>
|
||||
{% if was_start_button_clicked == true %}
|
||||
<p>Nextcloud's config.php file is stored in the nextcloud_aio_nextcloud Docker volume and can be edited by following the <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-edit-nextclouds-configphp-file-with-a-texteditor">config.php documentation</a>.</p>
|
||||
<p>You can run Nextcloud's usual occ commands by following the <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-run-occ-commands">occ documentation</a></strong>.</p>
|
||||
<p>{{ t('Nextcloud\'s config.php file is stored in the nextcloud_aio_nextcloud Docker volume and can be edited by following the') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-edit-nextclouds-configphp-file-with-a-texteditor">{{ t('config.php documentation') }}</a>.</p>
|
||||
<p>{{ t('You can run Nextcloud\'s usual occ commands by following the') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-run-occ-commands">{{ t('occ documentation') }}</a>.</p>
|
||||
{% endif %}
|
||||
|
||||
<p>
|
||||
{% if nextcloud_datadir starts with '/' %}
|
||||
Nextcloud's datadir is getting stored in the {{ nextcloud_datadir }} directory.
|
||||
{{ t('Nextcloud\'s datadir is getting stored in the') }} {{ nextcloud_datadir }} {{ t('directory.') }}
|
||||
{% else %}
|
||||
Nextcloud's datadir is getting stored in the {{ nextcloud_datadir }} Docker volume.
|
||||
{{ t('Nextcloud\'s datadir is getting stored in the') }} {{ nextcloud_datadir }} {{ t('Docker volume.') }}
|
||||
{% endif %}
|
||||
See the <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-change-the-default-location-of-nextclouds-datadir">NEXTCLOUD_DATADIR documentation</a> on how to change this.
|
||||
{{ t('See the') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-change-the-default-location-of-nextclouds-datadir">{{ t('NEXTCLOUD_DATADIR documentation') }}</a> {{ t('on how to change this.') }}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{% if nextcloud_mount == '' %}
|
||||
The Nextcloud container is confined and local external storage in Nextcloud is disabled.
|
||||
{{ t('The Nextcloud container is confined and local external storage in Nextcloud is disabled.') }}
|
||||
{% else %}
|
||||
The Nextcloud container is getting access to the {{ nextcloud_mount }} directory and local external storage in Nextcloud is enabled.
|
||||
{{ t('The Nextcloud container is getting access to the') }} {{ nextcloud_mount }} {{ t('directory and local external storage in Nextcloud is enabled.') }}
|
||||
{% endif %}
|
||||
See the <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-allow-the-nextcloud-container-to-access-directories-on-the-host">NEXTCLOUD_MOUNT documentation</a> on how to change this.</p>
|
||||
{{ t('See the') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-allow-the-nextcloud-container-to-access-directories-on-the-host">{{ t('NEXTCLOUD_MOUNT documentation') }}</a> {{ t('on how to change this.') }}</p>
|
||||
|
||||
<p>Nextcloud has an upload limit of {{ nextcloud_upload_limit }} configured (for public link uploads. Bigger uploads are always possible when users are logged in). See the <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-adjust-the-upload-limit-for-nextcloud">NEXTCLOUD_UPLOAD_LIMIT documentation</a> on how to change this.</p>
|
||||
<p>{{ t('Nextcloud has an upload limit of') }} {{ nextcloud_upload_limit }} {{ t('configured (for public link uploads. Bigger uploads are always possible when users are logged in). See the') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-adjust-the-upload-limit-for-nextcloud">{{ t('NEXTCLOUD_UPLOAD_LIMIT documentation') }}</a> {{ t('on how to change this.') }}</p>
|
||||
|
||||
<p>For Nextcloud, a memory limit of {{ nextcloud_memory_limit }} per PHP process is configured. See the <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-adjust-the-php-memory-limit-for-nextcloud">NEXTCLOUD_MEMORY_LIMIT documentation</a> on how to change this.</p>
|
||||
<p>{{ t('For Nextcloud, a memory limit of') }} {{ nextcloud_memory_limit }} {{ t('per PHP process is configured. See the') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-adjust-the-php-memory-limit-for-nextcloud">{{ t('NEXTCLOUD_MEMORY_LIMIT documentation') }}</a> {{ t('on how to change this.') }}</p>
|
||||
|
||||
<p>Nextcloud has a timeout of {{ nextcloud_max_time }} seconds configured (important for big file uploads). See the <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-adjust-the-max-execution-time-for-nextcloud">NEXTCLOUD_MAX_TIME documentation</a> on how to change this.</p>
|
||||
<p>{{ t('Nextcloud has a timeout of') }} {{ nextcloud_max_time }} {{ t('seconds configured (important for big file uploads). See the') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-adjust-the-max-execution-time-for-nextcloud">{{ t('NEXTCLOUD_MAX_TIME documentation') }}</a> {{ t('on how to change this.') }}</p>
|
||||
|
||||
<p>
|
||||
{% if is_dri_device_enabled == true and is_nvidia_gpu_enabled == true %}
|
||||
Hardware acceleration is enabled with the /dev/dri device and the Nvidia runtime.
|
||||
{{ t('Hardware acceleration is enabled with the /dev/dri device and the Nvidia runtime.') }}
|
||||
{% elseif is_dri_device_enabled == true %}
|
||||
Hardware acceleration is enabled with the /dev/dri device.
|
||||
{{ t('Hardware acceleration is enabled with the /dev/dri device.') }}
|
||||
{% elseif is_nvidia_gpu_enabled == true %}
|
||||
Hardware acceleration is enabled with the Nvidia runtime.
|
||||
{{ t('Hardware acceleration is enabled with the Nvidia runtime.') }}
|
||||
{% else %}
|
||||
Hardware acceleration is not enabled. It's recommended to enable hardware transcoding for better performance.
|
||||
{{ t('Hardware acceleration is not enabled. It\'s recommended to enable hardware transcoding for better performance.') }}
|
||||
{% endif %}
|
||||
See the <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-enable-hardware-acceleration-for-nextcloud">hardware acceleration documentation</a> on how to change this.</p>
|
||||
{{ t('See the') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-enable-hardware-acceleration-for-nextcloud">{{ t('hardware acceleration documentation') }}</a> {{ t('on how to change this.') }}</p>
|
||||
|
||||
<p>For further documentation on AIO, refer to <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one#nextcloud-all-in-one">this page</a></strong>. You can use the browser search [CTRL]+[F] to search through the documentation. Additional documentation can be found <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one/discussions/categories/wiki">here</a></strong>.</p>
|
||||
</details>
|
||||
<p>{{ t('For further documentation on AIO, refer to') }} <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one#nextcloud-all-in-one">{{ t('this page') }}</a></strong>. {{ t('You can use the browser search [CTRL]+[F] to search through the documentation. Additional documentation can be found') }} <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one/discussions/categories/wiki">{{ t('here') }}</a></strong>.</p>
|
||||
</details>
|
||||
@@ -1 +1 @@
|
||||
12.8.0
|
||||
12.9.0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<p>The folder path that you enter must start with <strong>/</strong> and must <strong>not</strong> end with <strong>/</strong>.</p>
|
||||
<p>An example for Linux is <strong>/mnt/backup</strong>.</p>
|
||||
<p>On Synology it could be <strong>/volume1/docker/nextcloud/backup</strong>.</p>
|
||||
<p>For macOS it may be <strong>/var/backup</strong>.</p>
|
||||
<p>On Windows it might be <strong>/run/desktop/mnt/host/c/backup</strong>. (This path is equivalent to 'C:\backup' on your Windows host so you need to translate the path accordingly. Hint: the path that you enter needs to start with '/run/desktop/mnt/host/'. Append to that the exact location on your windows host, e.g. 'c/backup' which is equivalent to 'C:\backup'.) ⚠️ <strong>Please note</strong>: This does not work with external drives like USB or network drives and only with internal drives like SATA or NVME drives.</p>
|
||||
<p>Another option is to enter a specific volume name here: <strong>nextcloud_aio_backupdir</strong>. This volume needs to be created beforehand manually by you in order to be able to use it. See <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-create-the-backup-volume-on-windows">this documentation</a> for an example.</p>
|
||||
<p>{{ t('The folder path that you enter must start with') }} <strong>/</strong> {{ t('and must') }} <strong>{{ t('not') }}</strong> {{ t('end with') }} <strong>/</strong>.</p>
|
||||
<p>{{ t('An example for Linux is') }} <strong>/mnt/backup</strong>.</p>
|
||||
<p>{{ t('On Synology it could be') }} <strong>/volume1/docker/nextcloud/backup</strong>.</p>
|
||||
<p>{{ t('For macOS it may be') }} <strong>/var/backup</strong>.</p>
|
||||
<p>{{ t('On Windows it might be') }} <strong>/run/desktop/mnt/host/c/backup</strong>. ({{ t('This path is equivalent to \'C:\\backup\' on your Windows host so you need to translate the path accordingly. Hint: the path that you enter needs to start with \'/run/desktop/mnt/host/\'. Append to that the exact location on your windows host, e.g. \'c/backup\' which is equivalent to \'C:\\backup\'.') }}) ⚠️ <strong>{{ t('Please note') }}</strong>: {{ t('This does not work with external drives like USB or network drives and only with internal drives like SATA or NVME drives.') }}</p>
|
||||
<p>{{ t('Another option is to enter a specific volume name here:') }} <strong>nextcloud_aio_backupdir</strong>. {{ t('This volume needs to be created beforehand manually by you in order to be able to use it. See') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one#how-to-create-the-backup-volume-on-windows">{{ t('this documentation') }}</a> {{ t('for an example.') }}</p>
|
||||
@@ -1,13 +1,13 @@
|
||||
<h2>Community Containers</h2>
|
||||
<p>In this section you can enable or disable optional Community Containers that are not included by default in the main installation. These containers are provided by the community and can be useful for various purposes and are automatically integrated in AIOs backup solution and update mechanisms.</p>
|
||||
<p><strong>⚠️ Caution: </strong>Community Containers are maintained by the community and not officially by Nextcloud. Some containers may not be compatible with your system, may not work as expected or may discontinue. Use them at your own risk. Please read the documentation for each container first before adding any as some are also incompatible between each other! Never add all of them at the same time!</p>
|
||||
<h2>{{ t('Community Containers') }}</h2>
|
||||
<p>{{ t('In this section you can enable or disable optional Community Containers that are not included by default in the main installation. These containers are provided by the community and can be useful for various purposes and are automatically integrated in AIOs backup solution and update mechanisms.') }}</p>
|
||||
<p><strong>⚠️ {{ t('Caution:') }} </strong>{{ t('Community Containers are maintained by the community and not officially by Nextcloud. Some containers may not be compatible with your system, may not work as expected or may discontinue. Use them at your own risk. Please read the documentation for each container first before adding any as some are also incompatible between each other! Never add all of them at the same time!') }}</p>
|
||||
{% if isAnyRunning == true %}
|
||||
<p><strong>Please note:</strong> You can enable or disable the options below only when your containers are stopped.</p>
|
||||
<p><strong>{{ t('Please note:') }}</strong> {{ t('You can enable or disable the options below only when your containers are stopped.') }}</p>
|
||||
{% else %}
|
||||
<p><strong>Please note:</strong> Make sure to save your changes by clicking <strong>Save changes</strong> below the list of Community Containers. The changes will not be auto-saved.</p>
|
||||
<p><strong>{{ t('Please note:') }}</strong> {{ t('Make sure to save your changes by clicking') }} <strong>{{ t('Save changes') }}</strong> {{ t('below the list of Community Containers. The changes will not be auto-saved.') }}</p>
|
||||
{% endif %}
|
||||
<details>
|
||||
<summary>Show/Hide available Community Containers</summary>
|
||||
<summary>{{ t('Show/Hide available Community Containers') }}</summary>
|
||||
<form id="community-form" method="POST" action="api/configuration" class="xhr">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
@@ -31,12 +31,13 @@
|
||||
>
|
||||
<label for="{{ cc.id }}">{{ cc.name }}
|
||||
{% if cc.documentation != '' %}
|
||||
<a href="{{ cc.documentation }}" target="_blank">(Documentation)</a>
|
||||
<a href="{{ cc.documentation }}" target="_blank">({{ t('Documentation') }})</a>
|
||||
{% endif %}
|
||||
</label>
|
||||
</p>
|
||||
{% endfor %}
|
||||
|
||||
<input id="community-form-submit" type="submit" value="Save changes" onclick="return confirm('Are you sure that you read the documentation of all community containers that you enabled? If no, please do not continue as this might break your instance!')" />
|
||||
{% set confirmCommunity = t('Are you sure that you read the documentation of all community containers that you enabled? If no, please do not continue as this might break your instance!') %}
|
||||
<input id="community-form-submit" type="submit" value="{{ t('Save changes') }}" onclick="return confirm('{{ confirmCommunity|e('js') }}')" />
|
||||
</form>
|
||||
</details>
|
||||
</details>
|
||||
@@ -1,17 +1,17 @@
|
||||
<h2>Optional containers</h2>
|
||||
<p>In this section you can enable or disable optional containers.</p>
|
||||
<h2>{{ t('Optional containers') }}</h2>
|
||||
<p>{{ t('In this section you can enable or disable optional containers.') }}</p>
|
||||
{% if isAnyRunning == true %}
|
||||
<p><strong>Please note:</strong> You can enable or disable the options below only when your containers are stopped.</p>
|
||||
<p><strong>{{ t('Please note:') }}</strong> {{ t('You can enable or disable the options below only when your containers are stopped.') }}</p>
|
||||
{% else %}
|
||||
<p><strong>Please note:</strong> Make sure to save your changes by clicking <strong>Save changes</strong> below the list of optional containers. The changes will not be auto-saved.</p>
|
||||
<p><strong>{{ t('Please note:') }}</strong> {{ t('Make sure to save your changes by clicking') }} <strong>{{ t('Save changes') }}</strong> {{ t('below the list of optional containers. The changes will not be auto-saved.') }}</p>
|
||||
{% endif %}
|
||||
<form id="options-form" method="POST" action="api/configuration" class="xhr">
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="hidden" name="options-form" value="options-form">
|
||||
<h3>Office Suite</h3>
|
||||
<h3>{{ t('Office Suite') }}</h3>
|
||||
{% if isAnyRunning == false %}
|
||||
<p>Choose your preferred office suite. Only one can be enabled at a time.</p>
|
||||
<p>{{ t('Choose your preferred office suite. Only one can be enabled at a time.') }}</p>
|
||||
{% endif %}
|
||||
<div class="office-suite-cards">
|
||||
<input
|
||||
@@ -26,23 +26,23 @@
|
||||
>
|
||||
<label class="office-card{{ isAnyRunning ? ' office-card-disabled' : '' }}" for="office-collabora">
|
||||
<div class="office-card-header">
|
||||
<h4>Nextcloud Office</h4>
|
||||
<h4>{{ t('Nextcloud Office') }}</h4>
|
||||
<svg class="office-checkmark" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="12" r="10" fill="var(--color-nextcloud-blue)"/>
|
||||
<path d="M7 12L10.5 15.5L17 9" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
<ul class="office-features">
|
||||
<li>Best Nextcloud integration</li>
|
||||
<li>Open source</li>
|
||||
<li>Good performance</li>
|
||||
<li>Best security: documents never leave your server</li>
|
||||
<li>Best ODF compatibility</li>
|
||||
<li>Best support for legacy files</li>
|
||||
<li>{{ t('Best Nextcloud integration') }}</li>
|
||||
<li>{{ t('Open source') }}</li>
|
||||
<li>{{ t('Good performance') }}</li>
|
||||
<li>{{ t('Best security: documents never leave your server') }}</li>
|
||||
<li>{{ t('Best ODF compatibility') }}</li>
|
||||
<li>{{ t('Best support for legacy files') }}</li>
|
||||
</ul>
|
||||
{% if isAnyRunning == false %}
|
||||
<a href="https://www.collaboraoffice.com/code/" target="_blank" class="office-learn-more" onclick="event.stopPropagation();">
|
||||
Learn more
|
||||
{{ t('Learn more') }}
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" style="vertical-align: middle; margin-left: 4px;">
|
||||
<path d="M6 12L10 8L6 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
@@ -62,22 +62,22 @@
|
||||
>
|
||||
<label class="office-card{{ isAnyRunning ? ' office-card-disabled' : '' }}" for="office-onlyoffice">
|
||||
<div class="office-card-header">
|
||||
<h4>OnlyOffice</h4>
|
||||
<h4>{{ t('OnlyOffice') }}</h4>
|
||||
<svg class="office-checkmark" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="12" cy="12" r="10" fill="var(--color-nextcloud-blue)"/>
|
||||
<path d="M7 12L10.5 15.5L17 9" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
<ul class="office-features">
|
||||
<li>Good Nextcloud integration</li>
|
||||
<li>Open core</li>
|
||||
<li>Best performance</li>
|
||||
<li>Best Microsoft compatibility</li>
|
||||
<li>Limited ODF compatibility</li>
|
||||
<li>{{ t('Good Nextcloud integration') }}</li>
|
||||
<li>{{ t('Open core') }}</li>
|
||||
<li>{{ t('Best performance') }}</li>
|
||||
<li>{{ t('Best Microsoft compatibility') }}</li>
|
||||
<li>{{ t('Limited ODF compatibility') }}</li>
|
||||
</ul>
|
||||
{% if isAnyRunning == false %}
|
||||
<a href="https://www.onlyoffice.com/" target="_blank" class="office-learn-more" onclick="event.stopPropagation();">
|
||||
Learn more
|
||||
{{ t('Learn more') }}
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" style="vertical-align: middle; margin-left: 4px;">
|
||||
<path d="M6 12L10 8L6 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
@@ -102,12 +102,12 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" style="vertical-align: middle; margin-right: 6px;">
|
||||
<path d="M2 2L14 14M2 14L14 2" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
Disable office suite
|
||||
{{ t('Disable office suite') }}
|
||||
</label>
|
||||
</div>
|
||||
{% endif %}
|
||||
<input class="options-form-submit" type="submit" value="Save changes" />
|
||||
<h3>Additional Optional Containers</h3>
|
||||
<input class="options-form-submit" type="submit" value="{{ t('Save changes') }}" />
|
||||
<h3>{{ t('Additional Optional Containers') }}</h3>
|
||||
<p>
|
||||
<input
|
||||
type="checkbox"
|
||||
@@ -120,7 +120,7 @@
|
||||
data-initial-state="false"
|
||||
{% endif %}
|
||||
>
|
||||
<label for="clamav">ClamAV (Antivirus backend for Nextcloud, needs ~1GB additional RAM)</label>
|
||||
<label for="clamav">{{ t('ClamAV (Antivirus backend for Nextcloud, needs ~1GB additional RAM)') }}</label>
|
||||
</p>
|
||||
<p>
|
||||
<input
|
||||
@@ -135,9 +135,9 @@
|
||||
{% endif %}
|
||||
>
|
||||
<label for="fulltextsearch">
|
||||
Fulltextsearch (needs ~1GB additional RAM, <a target="_blank" href="https://github.com/nextcloud/all-in-one/discussions/5768">does not work on Kernels without Seccomp</a>)
|
||||
{{ t('Fulltextsearch (needs ~1GB additional RAM,') }} <a target="_blank" href="https://github.com/nextcloud/all-in-one/discussions/5768">{{ t('does not work on Kernels without Seccomp') }}</a>)
|
||||
{% if is_fulltextsearch_enabled == false %}
|
||||
. <strong>Please note:</strong> the initial indexing can take a long time during which Nextcloud will be unavailable
|
||||
. <strong>{{ t('Please note:') }}</strong> {{ t('the initial indexing can take a long time during which Nextcloud will be unavailable') }}
|
||||
{% endif %}
|
||||
</label>
|
||||
</p>
|
||||
@@ -153,7 +153,7 @@
|
||||
data-initial-state="false"
|
||||
{% endif %}
|
||||
>
|
||||
<label for="imaginary">Imaginary (for previews of heic, heif, illustrator, pdf, svg, tiff and webp. Imaginary is currently <a target="_blank" href="https://github.com/nextcloud/server/issues/34262">incompatible with server-side-encryption</a>)</label>
|
||||
<label for="imaginary">{{ t('Imaginary (for previews of heic, heif, illustrator, pdf, svg, tiff and webp. Imaginary is currently') }} <a target="_blank" href="https://github.com/nextcloud/server/issues/34262">{{ t('incompatible with server-side-encryption') }}</a>)</label>
|
||||
</p>
|
||||
<p>
|
||||
<input
|
||||
@@ -167,7 +167,7 @@
|
||||
data-initial-state="false"
|
||||
{% endif %}
|
||||
>
|
||||
<label for="talk">Nextcloud Talk (needs ports {{ talk_port }}/TCP and {{ talk_port }}/UDP open/forwarded in your firewall/router)</label>
|
||||
<label for="talk">{{ t('Nextcloud Talk (needs ports') }} {{ talk_port }}/TCP {{ t('and') }} {{ talk_port }}/UDP {{ t('open/forwarded in your firewall/router)') }}</label>
|
||||
</p>
|
||||
<p>
|
||||
<input
|
||||
@@ -181,7 +181,7 @@
|
||||
data-initial-state="false"
|
||||
{% endif %}
|
||||
>
|
||||
<label for="talk-recording">Nextcloud Talk Recording-server (needs Nextcloud Talk being enabled and ~1GB additional RAM and ~2 additional vCPUs)</label>
|
||||
<label for="talk-recording">{{ t('Nextcloud Talk Recording-server (needs Nextcloud Talk being enabled and ~1GB additional RAM and ~2 additional vCPUs)') }}</label>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -196,7 +196,7 @@
|
||||
data-initial-state="false"
|
||||
{% endif %}
|
||||
>
|
||||
<label for="docker-socket-proxy">Docker Socket Proxy (needed for <a target="_blank" href="https://github.com/cloud-py-api/app_api#nextcloud-appapi">Nextcloud App API</a>) ⚠️ The docker socket proxy container is deprecated. Please use the HaRP (High-availability Reverse Proxy for Nextcloud ExApps) instead!</label>
|
||||
<label for="docker-socket-proxy">{{ t('Docker Socket Proxy (needed for') }} <a target="_blank" href="https://github.com/cloud-py-api/app_api#nextcloud-appapi">{{ t('Nextcloud App API') }}</a>) ⚠️ {{ t('The docker socket proxy container is deprecated. Please use the HaRP (High-availability Reverse Proxy for Nextcloud ExApps) instead!') }}</label>
|
||||
</p>
|
||||
{#
|
||||
<p>
|
||||
@@ -226,11 +226,11 @@
|
||||
data-initial-state="false"
|
||||
{% endif %}
|
||||
>
|
||||
<label for="whiteboard">Whiteboard</label>
|
||||
<label for="whiteboard">{{ t('Whiteboard') }}</label>
|
||||
</p>
|
||||
<input class="options-form-submit" type="submit" value="Save changes" />
|
||||
<input class="options-form-submit" type="submit" value="{{ t('Save changes') }}" />
|
||||
</form>
|
||||
<p><strong>Minimal system requirements:</strong> When any optional container is enabled, at least 2GB RAM, a dual-core CPU and 40GB system storage are required. When enabling ClamAV, Nextcloud Talk Recording-server or Fulltextsearch, at least 3GB RAM are required. For Talk Recording-server additional 2 vCPUs are required. When enabling everything, at least 5GB RAM and a quad-core CPU are required. Recommended are at least 1GB more RAM than the minimal requirement. For further advice and recommendations see <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one/discussions/1335">this documentation</a></strong></p>
|
||||
<p><strong>{{ t('Minimal system requirements:') }}</strong> {{ t('When any optional container is enabled, at least 2GB RAM, a dual-core CPU and 40GB system storage are required. When enabling ClamAV, Nextcloud Talk Recording-server or Fulltextsearch, at least 3GB RAM are required. For Talk Recording-server additional 2 vCPUs are required. When enabling everything, at least 5GB RAM and a quad-core CPU are required. Recommended are at least 1GB more RAM than the minimal requirement. For further advice and recommendations see') }} <strong><a target="_blank" href="https://github.com/nextcloud/all-in-one/discussions/1335">{{ t('this documentation') }}</a></strong></p>
|
||||
{% if isAnyRunning == true %}
|
||||
<script type="text/javascript" src="disable-clamav.js"></script>
|
||||
<script type="text/javascript" src="disable-docker-socket-proxy.js"></script>
|
||||
@@ -245,46 +245,46 @@
|
||||
{% endif %}
|
||||
|
||||
{% if is_collabora_enabled == true and isAnyRunning == false and was_start_button_clicked == true %}
|
||||
<h3>Nextcloud Office dictionaries</h3>
|
||||
<h3>{{ t('Nextcloud Office dictionaries') }}</h3>
|
||||
|
||||
{% if collabora_dictionaries == "" %}
|
||||
<p>In order to get the correct dictionaries in Nextcloud Office, you may configure the dictionaries below:</p>
|
||||
<p>{{ t('In order to get the correct dictionaries in Nextcloud Office, you may configure the dictionaries below:') }}</p>
|
||||
<form method="POST" action="api/configuration" class="xhr">
|
||||
<input type="text" name="collabora_dictionaries" placeholder="de_DE en_GB en_US es_ES fr_FR it nl pt_BR pt_PT ru" />
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Submit Nextcloud Office dictionaries" />
|
||||
<input type="submit" value="{{ t('Submit Nextcloud Office dictionaries') }}" />
|
||||
</form>
|
||||
<p>You need to make sure that the dictionaries that you enter are valid. An example is <strong>de_DE en_GB en_US es_ES fr_FR it nl pt_BR pt_PT ru</strong>.</p>
|
||||
<p>{{ t('You need to make sure that the dictionaries that you enter are valid. An example is') }} <strong>de_DE en_GB en_US es_ES fr_FR it nl pt_BR pt_PT ru</strong>.</p>
|
||||
{% else %}
|
||||
<p>The dictionaries for Nextcloud Office are currently set to <strong>{{ collabora_dictionaries }}</strong>. You can reset them again by clicking on the button below.</p>
|
||||
<p>{{ t('The dictionaries for Nextcloud Office are currently set to') }} <strong>{{ collabora_dictionaries }}</strong>. {{ t('You can reset them again by clicking on the button below.') }}</p>
|
||||
<form method="POST" action="api/configuration" class="xhr">
|
||||
<input type="hidden" name="delete_collabora_dictionaries" value="yes"/>
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Reset Nextcloud Office dictionaries" />
|
||||
<input type="submit" value="{{ t('Reset Nextcloud Office dictionaries') }}" />
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
<h3>Additional Nextcloud Office options</h3>
|
||||
<h3>{{ t('Additional Nextcloud Office options') }}</h3>
|
||||
|
||||
{% if collabora_additional_options == "" %}
|
||||
<p>You can configure additional options for Nextcloud Office below.</p>
|
||||
<p>(This can be used for configuring the net.content_security_policy and more. Make sure to submit the value!)</p>
|
||||
<p>{{ t('You can configure additional options for Nextcloud Office below.') }}</p>
|
||||
<p>({{ t('This can be used for configuring the net.content_security_policy and more. Make sure to submit the value!') }})</p>
|
||||
<form method="POST" action="api/configuration" class="xhr">
|
||||
<input type="text" name="collabora_additional_options" />
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Submit additional Nextcloud Office options" />
|
||||
<input type="submit" value="{{ t('Submit additional Nextcloud Office options') }}" />
|
||||
</form>
|
||||
<p>You need to make sure that the options that you enter are valid. An example is <strong>--o:net.content_security_policy=frame-ancestors *.example.com:*;</strong>.</p>
|
||||
<p>{{ t('You need to make sure that the options that you enter are valid. An example is') }} <strong>--o:net.content_security_policy=frame-ancestors *.example.com:*;</strong>.</p>
|
||||
{% else %}
|
||||
<p>The additioinal options for Nextcloud Office are currently set to <strong>{{ collabora_additional_options }}</strong>. You can reset them again by clicking on the button below.</p>
|
||||
<p>{{ t('The additional options for Nextcloud Office are currently set to') }} <strong>{{ collabora_additional_options }}</strong>. {{ t('You can reset them again by clicking on the button below.') }}</p>
|
||||
<form method="POST" action="api/configuration" class="xhr">
|
||||
<input type="hidden" name="delete_collabora_additional_options" value="yes"/>
|
||||
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
|
||||
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
|
||||
<input type="submit" value="Reset additional Nextcloud Office options" />
|
||||
<input type="submit" value="{{ t('Reset additional Nextcloud Office options') }}" />
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -1,7 +1,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>AIO</title>
|
||||
<link rel="stylesheet" href="style.css?v8" media="all" />
|
||||
<link rel="stylesheet" href="style.css?v9" media="all" />
|
||||
<link rel="icon" href="img/favicon.png">
|
||||
<script type="text/javascript" src="forms.js?v1"></script>
|
||||
<script type="text/javascript" src="toggle-dark-mode.js?v1"></script>
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<style>
|
||||
body {
|
||||
padding: 1rem;
|
||||
}
|
||||
#floating-box {
|
||||
position: fixed;
|
||||
position: sticky;
|
||||
top: 1rem;
|
||||
float: right;
|
||||
right: 1rem;
|
||||
width: 20rem;
|
||||
display: flex;
|
||||
|
||||
0
php/tests/tests/initial-setup.spec.js
Normal file → Executable file
0
php/tests/tests/initial-setup.spec.js
Normal file → Executable file
0
php/tests/tests/restore-instance.spec.js
Normal file → Executable file
0
php/tests/tests/restore-instance.spec.js
Normal file → Executable file
0
php/translations/.gitkeep
Normal file
0
php/translations/.gitkeep
Normal file
324
php/translations/de.json
Normal file
324
php/translations/de.json
Normal file
@@ -0,0 +1,324 @@
|
||||
{
|
||||
"⚠️ Important: If the backup that you want to restore contained any community container, you need to restore the same backup a second time after this attempt so that the community container data is also correctly restored.": "⚠️ Wichtig: Falls das Backup, das du wiederherstellen möchtest, Community-Container enthielt, musst du dasselbe Backup nach diesem Versuch ein zweites Mal wiederherstellen, damit die Community-Container-Daten ebenfalls korrekt wiederhergestellt werden.",
|
||||
"(if unchecked, Nextcloud Hub": "(wenn nicht ausgewählt, wird Nextcloud Hub",
|
||||
"A mastercontainer update is available. Please click on the button below to stop your containers in order to update the mastercontainer.": "Ein Mastercontainer-Update ist verfügbar. Bitte klicke auf die Schaltfläche unten, um deine Container zu stoppen und den Mastercontainer zu aktualisieren.",
|
||||
"A mastercontainer update is available. Please click on the button below to update it.": "Ein Mastercontainer-Update ist verfügbar. Bitte klicke auf die Schaltfläche unten, um ihn zu aktualisieren.",
|
||||
"A mastercontainer update is available. Please click on the button below to update it. Afterwards, you will be able to proceed with the setup.": "Ein Mastercontainer-Update ist verfügbar. Bitte klicke auf die Schaltfläche unten, um ihn zu aktualisieren. Danach kannst du mit der Einrichtung fortfahren.",
|
||||
"A notification about the result of the backup will be sent.": "Eine Benachrichtigung über das Ergebnis des Backups wird gesendet.",
|
||||
"a well-known server backup tool that efficiently backs up your files and encrypts them on the fly.": "ein bekanntes Server-Backup-Tool, das deine Dateien effizient sichert und dabei verschlüsselt.",
|
||||
"Additional Nextcloud Office options": "Weitere Nextcloud Office-Optionen",
|
||||
"Additional Optional Containers": "Weitere optionale Container",
|
||||
"Advice: have a detailed look at the changed docker run command for AIO.": "Hinweis: Schau dir den geänderten Docker-Run-Befehl für AIO genau an.",
|
||||
"AIO is currently in \"normal mode\" which means that it handles the TLS proxying itself. This also means that it cannot be installed behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else). If you want to run AIO behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else), see the": "AIO befindet sich derzeit im \"Normalmodus\", d. h. es übernimmt das TLS-Proxying selbst. Das bedeutet auch, dass es nicht hinter einem Webserver oder Reverse-Proxy (wie Apache, Nginx, Caddy, Cloudflare Tunnel usw.) installiert werden kann. Wenn du AIO hinter einem Webserver oder Reverse-Proxy betreiben möchtest, siehe die",
|
||||
"AIO is currently in \"reverse proxy mode\" which means that it can be installed behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else) and does not do the TLS proxying itself.": "AIO befindet sich derzeit im \"Reverse-Proxy-Modus\", d. h. es kann hinter einem Webserver oder Reverse-Proxy (wie Apache, Nginx, Caddy, Cloudflare Tunnel usw.) installiert werden und übernimmt das TLS-Proxying nicht selbst.",
|
||||
"AIO passphrase change": "AIO-Passphrase ändern",
|
||||
"All important data from your Nextcloud AIO instance such as the database, your files and the mastercontainer's configuration files, will be backed up.": "Alle wichtigen Daten deiner Nextcloud-AIO-Instanz, wie die Datenbank, deine Dateien und die Konfigurationsdateien des Mastercontainers, werden gesichert.",
|
||||
"Also your containers, the mastercontainer and, on Saturdays, your Nextcloud apps will be automatically updated.": "Außerdem werden deine Container, der Mastercontainer und samstags deine Nextcloud-Apps automatisch aktualisiert.",
|
||||
"An example for Linux is": "Ein Beispiel für Linux ist",
|
||||
"and": "und",
|
||||
"and afterwards reloading this interface.": "und lade danach diese Oberfläche neu.",
|
||||
"and below.": "und unten.",
|
||||
"and must": "und darf",
|
||||
"and spaces.": "und Leerzeichen.",
|
||||
"Another option is to enter a specific volume name here:": "Eine weitere Möglichkeit ist, hier einen bestimmten Volume-Namen einzugeben:",
|
||||
"are allowed. If the entry begins with a letter/digit slashes are not supported. Two valid entries are": "sind erlaubt. Wenn der Eintrag mit einem Buchstaben oder einer Ziffer beginnt, werden Schrägstriche nicht unterstützt. Zwei gültige Einträge sind",
|
||||
"Are you sure that this is a valid timezone? Please double check by following the wikipedia article and checking the correct column. If the timezone is not valid, it will break the startup since the database will not be correctly initialized and you will end up in a startup loop.": "Bist du sicher, dass dies eine gültige Zeitzone ist? Bitte überprüfe dies anhand des Wikipedia-Artikels und der richtigen Spalte. Wenn die Zeitzone ungültig ist, schlägt der Start fehl, da die Datenbank nicht korrekt initialisiert wird und du in einer Startschleife landen wirst.",
|
||||
"Are you sure that you read the documentation of all community containers that you enabled? If no, please do not continue as this might break your instance!": "Hast du die Dokumentation aller aktivierten Community-Container gelesen? Falls nicht, fahre bitte nicht fort, da dies deine Instanz beschädigen könnte!",
|
||||
"Are you sure that you want to reset the backup location?": "Bist du sicher, dass du den Backup-Speicherort zurücksetzen möchtest?",
|
||||
"as additional backup directory will only back up files and folders that are stored on the root partition and not on the EFI partition or any other. Excluded by the backup will be caches and a few other directories. If you want to back up the root partition you should make sure to stop all services before the backup so it can run correctly. For automating this see": "als zusätzliches Backup-Verzeichnis sichert nur Dateien und Ordner, die auf der Root-Partition gespeichert sind, nicht auf der EFI-Partition oder anderen. Vom Backup ausgeschlossen sind Caches und einige andere Verzeichnisse. Wenn du die Root-Partition sichern möchtest, stelle sicher, dass alle Dienste vor dem Backup gestoppt werden, damit es korrekt ablaufen kann. Zur Automatisierung siehe",
|
||||
"at 4 pm UTC. When creating the backup, containers will be stopped and restarted after the backup is complete.": "um 16 Uhr UTC. Beim Erstellen des Backups werden die Container gestoppt und nach Abschluss des Backups neu gestartet.",
|
||||
"Automatically update all containers, the mastercontainer and on saturdays your Nextcloud apps": "Alle Container, den Mastercontainer und samstags deine Nextcloud-Apps automatisch aktualisieren",
|
||||
"available": "verfügbar",
|
||||
"Back up additional directories and docker volumes of your host": "Weitere Verzeichnisse und Docker-Volumes des Hosts sichern",
|
||||
"Backup and restore": "Backup und Wiederherstellung",
|
||||
"Backup check": "Backup-Prüfung",
|
||||
"Backup container is currently running:": "Backup-Container läuft derzeit:",
|
||||
"Backup creation": "Backup erstellen",
|
||||
"Backup information": "Backup-Informationen",
|
||||
"Backup restore": "Backup wiederherstellen",
|
||||
"Backup Viewer": "Backup-Viewer",
|
||||
"Backups get created remotely at:": "Backups werden remote erstellt unter:",
|
||||
"Backups will be created in the following directory on the host:": "Backups werden im folgenden Verzeichnis auf dem Host erstellt:",
|
||||
"Be aware that this solution does not backup files and folders that are mounted into Nextcloud using the external storage app, but you can add further Docker volumes and host paths that you want to back up after the initial backup is done.": "Beachte, dass diese Lösung keine Dateien und Ordner sichert, die über die externe Speicher-App in Nextcloud eingebunden sind. Du kannst jedoch nach dem ersten Backup weitere Docker-Volumes und Host-Pfade hinzufügen, die gesichert werden sollen.",
|
||||
"Be sure to individually specify all storage that you want to back up as storage will not be mounted recursively. E.g. providing": "Gib alle Speicherorte, die du sichern möchtest, einzeln an, da Speicher nicht rekursiv eingebunden wird. Wenn du z. B.",
|
||||
"Below is the option to repair the integrity of your backup.": "Unten findest du die Option zur Reparatur der Backup-Integrität.",
|
||||
"below the list of Community Containers. The changes will not be auto-saved.": "unterhalb der Liste der Community-Container. Die Änderungen werden nicht automatisch gespeichert.",
|
||||
"below the list of optional containers. The changes will not be auto-saved.": "unterhalb der Liste der optionalen Container. Die Änderungen werden nicht automatisch gespeichert.",
|
||||
"Below you can enter directories and docker volumes of your host that will be backed up into the same borg backup archive. Make sure to press the submit button after changing anything.": "Unten kannst du Verzeichnisse und Docker-Volumes deines Hosts eingeben, die in dasselbe Borg-Backup-Archiv gesichert werden. Stelle sicher, dass du nach jeder Änderung die Senden-Schaltfläche drückst.",
|
||||
"Best Microsoft compatibility": "Beste Microsoft-Kompatibilität",
|
||||
"Best Nextcloud integration": "Beste Nextcloud-Integration",
|
||||
"Best ODF compatibility": "Beste ODF-Kompatibilität",
|
||||
"Best performance": "Beste Leistung",
|
||||
"Best security: documents never leave your server": "Beste Sicherheit: Dokumente verlassen deinen Server nie",
|
||||
"Best support for legacy files": "Beste Unterstützung für ältere Dateiformate",
|
||||
"Borg backup container logs": "Borg-Backup-Container-Protokolle",
|
||||
"Borg passphrase": "Borg-Passphrase",
|
||||
"By entering a time below and submitting it, you can enable daily backups. It will create them at the entered time in 24h format. E.g.": "Durch Eingabe einer Zeit unten und Absenden kannst du tägliche Backups aktivieren. Diese werden zur eingegebenen Zeit im 24-Stunden-Format erstellt. Z. B.",
|
||||
"By using this tool, backups are incremental, differential, compressed and encrypted – so only the first backup will take a while. Further backups should be fast as only changes are taken into account.": "Mit diesem Tool sind Backups inkrementell, differenziell, komprimiert und verschlüsselt – daher dauert nur das erste Backup länger. Weitere Backups sollten schnell sein, da nur Änderungen berücksichtigt werden.",
|
||||
"Caution:": "Achtung:",
|
||||
"channel.": "Kanal.",
|
||||
"Check and repair backup integrity": "Backup-Integrität prüfen und reparieren",
|
||||
"Check and repair backup integrity? Are you sure that you want to check and repair the backup integrity? This should only be done after reading the mentioned documentation.": "Backup-Integrität prüfen und reparieren? Bist du sicher, dass du die Backup-Integrität prüfen und reparieren möchtest? Dies sollte nur nach dem Lesen der genannten Dokumentation durchgeführt werden.",
|
||||
"Check backup integrity": "Backup-Integrität prüfen",
|
||||
"Check backup integrity? Are you sure that you want to check the backup? This can take a long time depending on the size of your backup.": "Backup-Integrität prüfen? Bist du sicher, dass du das Backup prüfen möchtest? Dies kann je nach Größe deines Backups lange dauern.",
|
||||
"Choose the backup that you want to restore and click on the button below to restore the selected backup. This will restore the whole AIO instance. Please note that the current AIO passphrase will be kept and the previous AIO passphrase will not be restored from backup!": "Wähle das Backup aus, das du wiederherstellen möchtest, und klicke auf die Schaltfläche unten, um das ausgewählte Backup wiederherzustellen. Dadurch wird die gesamte AIO-Instanz wiederhergestellt. Bitte beachte, dass die aktuelle AIO-Passphrase beibehalten wird und die vorherige AIO-Passphrase nicht aus dem Backup wiederhergestellt wird!",
|
||||
"Choose your preferred office suite. Only one can be enabled at a time.": "Wähle deine bevorzugte Office-Suite. Es kann jeweils nur eine aktiviert sein.",
|
||||
"ClamAV (Antivirus backend for Nextcloud, needs ~1GB additional RAM)": "ClamAV (Antivirus-Backend für Nextcloud, benötigt ~1 GB zusätzlichen RAM)",
|
||||
"click here": "hier klicken",
|
||||
"Click here for further hints": "Hier für weitere Hinweise klicken",
|
||||
"Click here to change your AIO passphrase": "Hier klicken, um deine AIO-Passphrase zu ändern",
|
||||
"Click here to reveal all backup options (including an option for automatic updates)": "Hier klicken, um alle Backup-Optionen anzuzeigen (einschließlich einer Option für automatische Updates)",
|
||||
"Click here to reveal the initial Nextcloud credentials": "Hier klicken, um die anfänglichen Nextcloud-Zugangsdaten anzuzeigen",
|
||||
"Click here to reveal this option": "Hier klicken, um diese Option anzuzeigen",
|
||||
"Click here to view the current AIO config and documentation links": "Hier klicken, um die aktuelle AIO-Konfiguration und Dokumentationslinks anzuzeigen",
|
||||
"Click on the button below to test the path and encryption password:": "Klicke auf die Schaltfläche unten, um den Pfad und das Verschlüsselungspasswort zu testen:",
|
||||
"Clicking on the button below will create a backup.": "Ein Klick auf die Schaltfläche unten erstellt ein Backup.",
|
||||
"Clicking on the button below will download all docker containers and start them. This can take a long time depending on your internet connection. Since the overall size is a few GB, this can take around 5-10 min or more. Please be patient!": "Ein Klick auf die Schaltfläche unten lädt alle Docker-Container herunter und startet sie. Je nach Internetverbindung kann dies lange dauern. Da die Gesamtgröße einige GB beträgt, kann dies ca. 5–10 Minuten oder länger dauern. Bitte hab Geduld!",
|
||||
"community container": "Community-Container",
|
||||
"Community Containers": "Community-Container",
|
||||
"Community Containers are maintained by the community and not officially by Nextcloud. Some containers may not be compatible with your system, may not work as expected or may discontinue. Use them at your own risk. Please read the documentation for each container first before adding any as some are also incompatible between each other! Never add all of them at the same time!": "Community-Container werden von der Community gepflegt und nicht offiziell von Nextcloud. Einige Container sind möglicherweise nicht mit deinem System kompatibel, funktionieren möglicherweise nicht wie erwartet oder werden eingestellt. Nutzung auf eigenes Risiko. Bitte lies zuerst die Dokumentation zu jedem Container, bevor du ihn hinzufügst, da einige auch untereinander inkompatibel sind! Füge niemals alle gleichzeitig hinzu!",
|
||||
"config.php documentation": "config.php-Dokumentation",
|
||||
"configured (for public link uploads. Bigger uploads are always possible when users are logged in). See the": "konfiguriert (für Uploads über öffentliche Links. Größere Uploads sind immer möglich, wenn Benutzer angemeldet sind). Siehe die",
|
||||
"Container updates are available. Click on": "Container-Updates sind verfügbar. Klicke auf",
|
||||
"Containers": "Container",
|
||||
"Containers are currently starting. You might inspect the container logs by clicking on": "Container werden derzeit gestartet. Du kannst die Container-Protokolle einsehen, indem du auf",
|
||||
"Create backup": "Backup erstellen",
|
||||
"Create Backup": "Backup erstellen",
|
||||
"Create backup? Are you sure that you want to create a backup? This will stop all running containers and create the backup.": "Backup erstellen? Bist du sicher, dass du ein Backup erstellen möchtest? Dadurch werden alle laufenden Container gestoppt und das Backup erstellt.",
|
||||
"Daily backup and automatic updates": "Tägliches Backup und automatische Updates",
|
||||
"Daily backup currently running.": "Tägliches Backup wird derzeit ausgeführt.",
|
||||
"Daily backups can be enabled after the initial backup is done. Enabling this also allows you to enable an option to update all containers, Nextcloud, and its apps automatically.": "Tägliche Backups können nach dem ersten Backup aktiviert werden. Durch die Aktivierung kannst du auch eine Option aktivieren, um alle Container, Nextcloud und seine Apps automatisch zu aktualisieren.",
|
||||
"Daily backups will be created at": "Tägliche Backups werden erstellt um",
|
||||
"directory and local external storage in Nextcloud is enabled.": "Verzeichnis zugegriffen und lokaler externer Speicher in Nextcloud ist aktiviert.",
|
||||
"directory.": "Verzeichnis gespeichert.",
|
||||
"Disable office suite": "Office-Suite deaktivieren",
|
||||
"Disable or change daily backup settings": "Tägliche Backup-Einstellungen deaktivieren oder ändern",
|
||||
"Docker Socket Proxy (needed for": "Docker-Socket-Proxy (benötigt für",
|
||||
"Docker volume.": "Docker-Volume gespeichert.",
|
||||
"docs": "Doku",
|
||||
"Documentation": "Dokumentation",
|
||||
"does not work on Kernels without Seccomp": "funktioniert nicht auf Kerneln ohne Seccomp",
|
||||
"Domaincheck container is not running": "Domaincheck-Container läuft nicht",
|
||||
"Download and start containers": "Container herunterladen und starten",
|
||||
"Each line and entry needs to start with a slash or letter/digit. Only": "Jede Zeile und jeder Eintrag muss mit einem Schrägstrich oder einem Buchstaben/einer Ziffer beginnen. Nur",
|
||||
"encryption password": "Verschlüsselungspasswort",
|
||||
"end with": "enden mit",
|
||||
"Everything set!": "Alles bereit!",
|
||||
"Exclude previews from restore which will speed up the restore process but will trigger a scan of the preview folder as soon as the Nextcloud container starts the next time": "Vorschauen von der Wiederherstellung ausschließen, was den Wiederherstellungsprozess beschleunigt, aber beim nächsten Start des Nextcloud-Containers einen Scan des Vorschauordners auslöst",
|
||||
"failed!": "fehlgeschlagen!",
|
||||
"Feel free to check the integrity of the backup archive below before starting the restore process in order to make ensure that the restore will work. This can take a long time though depending on the size of the backup archive and is thus not required.": "Du kannst die Integrität des Backup-Archivs unten prüfen, bevor du den Wiederherstellungsprozess startest, um sicherzustellen, dass die Wiederherstellung funktioniert. Dies kann jedoch je nach Größe des Backup-Archivs lange dauern und ist daher nicht erforderlich.",
|
||||
"for an example.": "als Beispiel.",
|
||||
"For further documentation and options on this backup solution refer to": "Weitere Dokumentation und Optionen zu dieser Backup-Lösung findest du unter",
|
||||
"For further documentation on AIO, refer to": "Weitere Dokumentation zu AIO findest du auf",
|
||||
"for how to debug things.": "für Hinweise zur Fehlersuche.",
|
||||
"For information about backup retention, see": "Informationen zur Backup-Aufbewahrung findest du unter",
|
||||
"For macOS it may be": "Für macOS könnte es",
|
||||
"For Nextcloud, a memory limit of": "Für Nextcloud ist ein Speicherlimit von",
|
||||
"Fulltextsearch (needs ~1GB additional RAM,": "Volltextsuche (benötigt ~1 GB zusätzlichen RAM,",
|
||||
"Good Nextcloud integration": "Gute Nextcloud-Integration",
|
||||
"Good performance": "Gute Leistung",
|
||||
"hardware acceleration documentation": "Dokumentation zur Hardwarebeschleunigung",
|
||||
"Hardware acceleration is enabled with the /dev/dri device and the Nvidia runtime.": "Hardwarebeschleunigung ist mit dem /dev/dri-Gerät und der Nvidia-Laufzeitumgebung aktiviert.",
|
||||
"Hardware acceleration is enabled with the /dev/dri device.": "Hardwarebeschleunigung ist mit dem /dev/dri-Gerät aktiviert.",
|
||||
"Hardware acceleration is enabled with the Nvidia runtime.": "Hardwarebeschleunigung ist mit der Nvidia-Laufzeitumgebung aktiviert.",
|
||||
"here": "hier",
|
||||
"Hint:": "Hinweis:",
|
||||
"How to reset the AIO instance?": "Wie setzt man die AIO-Instanz zurück?",
|
||||
"if nothing is entered.": "wenn nichts eingegeben wird.",
|
||||
"If something should be going wrong, for example during the initial installation, you can reset the instance by following": "Falls etwas schief geht, zum Beispiel während der Erstinstallation, kannst du die Instanz zurücksetzen, indem du",
|
||||
"if stored remotely; and the encryption password of the backup archive below and submit all values:": "wenn es remote gespeichert ist; sowie das Verschlüsselungspasswort des Backup-Archivs unten eingibst und alle Werte absendest:",
|
||||
"If the backup that you want to restore contained any": "Wenn das Backup, das du wiederherstellen möchtest,",
|
||||
"If the configured backup host location": "Wenn der konfigurierte Backup-Host-Speicherort",
|
||||
"If the daily backup is stuck somehow, you can unstick it by running": "Wenn das tägliche Backup irgendwie feststeckt, kannst du es durch Ausführen von",
|
||||
"If you do not have a domain yet, you can get one for free e.g. from duckdns.org and others. Recommended is to use": "Wenn du noch keine Domain hast, kannst du eine kostenlos z. B. bei duckdns.org und anderen erhalten. Empfohlen wird",
|
||||
"If you have a dynamic public IP-address, you can use e.g.": "Wenn du eine dynamische öffentliche IP-Adresse hast, kannst du z. B.",
|
||||
"If you only want to install AIO locally without exposing it to the public internet or if you cannot do so, feel free to follow": "Wenn du AIO nur lokal installieren möchtest, ohne es dem öffentlichen Internet zugänglich zu machen, oder wenn du dies nicht kannst, folge gerne",
|
||||
"If you run into issues with your domain being accepted, see": "Wenn es Probleme damit gibt, dass deine Domain akzeptiert wird, siehe",
|
||||
"If you should be using Cloudflare Proxy for your domain, make sure to disable the Proxy feature temporarily as it might block the domain validation attempts.": "Wenn du Cloudflare-Proxy für deine Domain verwendest, deaktiviere die Proxy-Funktion vorübergehend, da sie die Domain-Validierungsversuche blockieren könnte.",
|
||||
"If you use an external snapshot tool to restore the server that runs AIO, you might run into a problem that the above listed available backups are not up-to-date to restore your server from. You can click the button below to update this list.": "Wenn du ein externes Snapshot-Tool verwendest, um den Server mit AIO wiederherzustellen, kann es vorkommen, dass die oben aufgelisteten verfügbaren Backups nicht aktuell sind. Du kannst auf die Schaltfläche unten klicken, um diese Liste zu aktualisieren.",
|
||||
"If your Nextcloud does not open when clicking the button above, see": "Wenn sich dein Nextcloud beim Klicken auf die Schaltfläche oben nicht öffnet, siehe",
|
||||
"Imaginary (for previews of heic, heif, illustrator, pdf, svg, tiff and webp. Imaginary is currently": "Imaginary (für Vorschauen von heic, heif, illustrator, pdf, svg, tiff und webp. Imaginary ist derzeit",
|
||||
"Important:": "Wichtig:",
|
||||
"In order to get the correct dictionaries in Nextcloud Office, you may configure the dictionaries below:": "Um die richtigen Wörterbücher in Nextcloud Office zu erhalten, kannst du die Wörterbücher unten konfigurieren:",
|
||||
"In this section you can enable or disable optional Community Containers that are not included by default in the main installation. These containers are provided by the community and can be useful for various purposes and are automatically integrated in AIOs backup solution and update mechanisms.": "In diesem Abschnitt kannst du optionale Community-Container aktivieren oder deaktivieren, die standardmäßig nicht in der Hauptinstallation enthalten sind. Diese Container werden von der Community bereitgestellt, können für verschiedene Zwecke nützlich sein und sind automatisch in AIOs Backup- und Update-Mechanismen integriert.",
|
||||
"In this section you can enable or disable optional containers.": "In diesem Abschnitt kannst du optionale Container aktivieren oder deaktivieren.",
|
||||
"incompatible with server-side-encryption": "inkompatibel mit serverseitiger Verschlüsselung",
|
||||
"Initial Nextcloud password:": "Initiales Nextcloud-Passwort:",
|
||||
"Initial Nextcloud username:": "Initialer Nextcloud-Benutzername:",
|
||||
"Install Nextcloud Hub": "Nextcloud Hub installieren",
|
||||
"is already in use on your server. You can check the mastercontainer logs and domaincheck container logs for further clues. You should be able to resolve this by adjusting the APACHE_PORT by following the": "wird bereits auf deinem Server verwendet. Du kannst die Mastercontainer-Protokolle und die Domaincheck-Container-Protokolle auf weitere Hinweise prüfen. Du solltest dies beheben können, indem du den APACHE_PORT anpasst und dabei die",
|
||||
"is wrong or if you want to reset the backup location due to other reasons, you can do so by clicking on the button below.": "falsch ist oder du den Backup-Speicherort aus anderen Gründen zurücksetzen möchtest, kannst du dies tun, indem du auf die Schaltfläche unten klickst.",
|
||||
"It seems at least one container was not able to start correctly and is currently restarting.": "Es scheint, dass mindestens ein Container nicht korrekt starten konnte und derzeit neu startet.",
|
||||
"Last": "Letztes",
|
||||
"Last restore failed!": "Letzte Wiederherstellung fehlgeschlagen!",
|
||||
"latin characters": "lateinischen Zeichen",
|
||||
"Learn more": "Mehr erfahren",
|
||||
"Limited ODF compatibility": "Eingeschränkte ODF-Kompatibilität",
|
||||
"Local backup location": "Lokaler Backup-Speicherort",
|
||||
"Log out": "Abmelden",
|
||||
"Logs": "Protokolle",
|
||||
"Make sure to save your changes by clicking": "Stelle sicher, dass du deine Änderungen speicherst, indem du auf",
|
||||
"Mastercontainer logs": "Mastercontainer-Protokolle",
|
||||
"Mastercontainer update": "Mastercontainer-Update",
|
||||
"Mastercontainer update currently running. Once the update is complete the mastercontainer will restart, making it unavailable for a moment. Please wait until it's done.": "Mastercontainer-Update wird derzeit ausgeführt. Nach Abschluss des Updates wird der Mastercontainer neu gestartet und ist kurzzeitig nicht verfügbar. Bitte warte, bis es abgeschlossen ist.",
|
||||
"Minimal system requirements:": "Minimale Systemanforderungen:",
|
||||
"New AIO instance": "Neue AIO-Instanz",
|
||||
"next to each container for further details.": "neben jedem Container klickst, um weitere Details zu erhalten.",
|
||||
"Nextcloud AIO v": "Nextcloud AIO v",
|
||||
"Nextcloud App API": "Nextcloud App API",
|
||||
"Nextcloud has a timeout of": "Nextcloud hat ein Timeout von",
|
||||
"Nextcloud has an upload limit of": "Nextcloud hat ein Upload-Limit von",
|
||||
"Nextcloud Office": "Nextcloud Office",
|
||||
"Nextcloud Office dictionaries": "Nextcloud Office-Wörterbücher",
|
||||
"Nextcloud Talk (needs ports": "Nextcloud Talk (benötigt Ports",
|
||||
"Nextcloud Talk Recording-server (needs Nextcloud Talk being enabled and ~1GB additional RAM and ~2 additional vCPUs)": "Nextcloud Talk-Aufnahmeserver (benötigt aktiviertes Nextcloud Talk sowie ~1 GB zusätzlichen RAM und ~2 zusätzliche vCPUs)",
|
||||
"Nextcloud's config.php file is stored in the nextcloud_aio_nextcloud Docker volume and can be edited by following the": "Die config.php-Datei von Nextcloud wird im Docker-Volume nextcloud_aio_nextcloud gespeichert und kann gemäß der",
|
||||
"Nextcloud's datadir is getting stored in the": "Das Datenverzeichnis von Nextcloud wird im",
|
||||
"NEXTCLOUD_DATADIR documentation": "NEXTCLOUD_DATADIR-Dokumentation",
|
||||
"NEXTCLOUD_MAX_TIME documentation": "NEXTCLOUD_MAX_TIME-Dokumentation",
|
||||
"NEXTCLOUD_MEMORY_LIMIT documentation": "NEXTCLOUD_MEMORY_LIMIT-Dokumentation",
|
||||
"NEXTCLOUD_MOUNT documentation": "NEXTCLOUD_MOUNT-Dokumentation",
|
||||
"NEXTCLOUD_UPLOAD_LIMIT documentation": "NEXTCLOUD_UPLOAD_LIMIT-Dokumentation",
|
||||
"No channel was found. This means that AIO is not able to update itself and its component and will also not be able to report about updates. Updates need to be done externally.": "Kein Kanal gefunden. Das bedeutet, dass AIO sich und seine Komponenten nicht selbst aktualisieren kann und auch keine Updates melden kann. Updates müssen extern durchgeführt werden.",
|
||||
"not": "nicht",
|
||||
"Note about": "Hinweis zu",
|
||||
"occ documentation": "occ-Dokumentation",
|
||||
"Office Suite": "Office-Suite",
|
||||
"on how to change this.": "für Details, wie dies geändert werden kann.",
|
||||
"On Synology it could be": "Auf Synology könnte es",
|
||||
"On Windows it might be": "Unter Windows könnte es",
|
||||
"OnlyOffice": "OnlyOffice",
|
||||
"Open core": "Open Core",
|
||||
"Open source": "Open Source",
|
||||
"Open your Nextcloud ↗": "Nextcloud öffnen ↗",
|
||||
"open/forwarded in your firewall/router)": "in deiner Firewall/deinem Router geöffnet/weitergeleitet sein)",
|
||||
"Optional containers": "Optionale Container",
|
||||
"or the remote repo": "oder das Remote-Repository",
|
||||
"per PHP process is configured. See the": "pro PHP-Prozess konfiguriert. Siehe die",
|
||||
"Please adjust the path and/or the encryption password in order to make it work!": "Bitte passe den Pfad und/oder das Verschlüsselungspasswort an, damit es funktioniert!",
|
||||
"Please enter the location of the backup archive on your host or a": "Bitte gib den Speicherort des Backup-Archivs auf deinem Host oder eine",
|
||||
"Please note": "Bitte beachten",
|
||||
"Please note that the chosen directories/volumes will not be restored when you restore your instance, so this would need to be done manually.": "Bitte beachte, dass die ausgewählten Verzeichnisse/Volumes bei der Wiederherstellung deiner Instanz nicht wiederhergestellt werden und dies manuell erledigt werden müsste.",
|
||||
"Please note:": "Bitte beachten:",
|
||||
"Please type in the domain that will be used for Nextcloud and submit it.": "Bitte gib die Domain ein, die für Nextcloud verwendet werden soll, und sende sie ab.",
|
||||
"Please save this password in a safe place. You won't be able to restore from backup if you lose this password!": "Bitte speichere dieses Passwort an einem sicheren Ort. Du kannst das Backup nicht wiederherstellen, wenn du dieses Passwort verlierst!",
|
||||
"Reload ↻": "Neu laden ↻",
|
||||
"Remote borg repo": "Remote-Borg-Repository",
|
||||
"remote borg repo url": "Remote-Borg-Repository-URL",
|
||||
"remote borg repo url and submit it": "Remote-Borg-Repository-URL eingeben und absenden",
|
||||
"Reset additional Nextcloud Office options": "Weitere Nextcloud Office-Optionen zurücksetzen",
|
||||
"Reset backup location": "Backup-Speicherort zurücksetzen",
|
||||
"Reset Nextcloud Office dictionaries": "Nextcloud Office-Wörterbücher zurücksetzen",
|
||||
"Reset the timezone": "Zeitzone zurücksetzen",
|
||||
"Restore former AIO instance from backup": "Frühere AIO-Instanz aus Backup wiederherstellen",
|
||||
"Restore or Backup currently running. Cannot start the containers until Restore or Backup is complete.": "Wiederherstellung oder Backup wird derzeit ausgeführt. Container können erst gestartet werden, wenn die Wiederherstellung oder das Backup abgeschlossen ist.",
|
||||
"Restore selected backup": "Ausgewähltes Backup wiederherstellen",
|
||||
"Restore the selected backup? Are you sure that you want to restore the selected backup? This will stop all running containers and restore the selected backup. It is recommended to create a backup first. You might also want to check the backup integrity.": "Ausgewähltes Backup wiederherstellen? Bist du sicher, dass du das ausgewählte Backup wiederherstellen möchtest? Dadurch werden alle laufenden Container gestoppt und das ausgewählte Backup wiederhergestellt. Es wird empfohlen, zuerst ein Backup zu erstellen. Du solltest auch die Backup-Integrität prüfen.",
|
||||
"Reveal repair option": "Reparaturoption anzeigen",
|
||||
"reverse proxy documentation": "Reverse-Proxy-Dokumentation",
|
||||
"Running": "Läuft",
|
||||
"Save changes": "Änderungen speichern",
|
||||
"seconds configured (important for big file uploads). See the": "Sekunden konfiguriert (wichtig für große Datei-Uploads). Siehe die",
|
||||
"See the": "Siehe die",
|
||||
"Select language": "Sprache auswählen",
|
||||
"Send notifications about successful backups (notifications about unsuccessful backups will always be sent)": "Benachrichtigungen über erfolgreiche Backups senden (Benachrichtigungen über fehlgeschlagene Backups werden immer gesendet)",
|
||||
"Set backup location again": "Backup-Speicherort erneut festlegen",
|
||||
"Show password for": "Passwort anzeigen für",
|
||||
"Show/Hide available Community Containers": "Verfügbare Community-Container ein-/ausblenden",
|
||||
"Start and update containers": "Container starten und aktualisieren",
|
||||
"Start and update containers? You should consider creating a backup first.": "Container starten und aktualisieren? Du solltest zunächst ein Backup erstellen.",
|
||||
"Start containers": "Container starten",
|
||||
"Starting": "Wird gestartet",
|
||||
"Stop containers": "Container stoppen",
|
||||
"Stopped": "Gestoppt",
|
||||
"Submit additional backup locations": "Weitere Backup-Speicherorte speichern",
|
||||
"Submit additional Nextcloud Office options": "Weitere Nextcloud Office-Optionen speichern",
|
||||
"Submit backup location": "Backup-Speicherort speichern",
|
||||
"Submit daily backup time and settings": "Tägliche Backup-Zeit und Einstellungen speichern",
|
||||
"Submit domain": "Domain speichern",
|
||||
"Submit location and encryption password": "Speicherort und Verschlüsselungspasswort speichern",
|
||||
"Submit Nextcloud Office dictionaries": "Nextcloud Office-Wörterbücher speichern",
|
||||
"Submit passphrase change": "Passphrasenänderung speichern",
|
||||
"Submit timezone": "Zeitzone speichern",
|
||||
"successful on": "erfolgreich am",
|
||||
"successful!": "erfolgreich!",
|
||||
"Test path and encryption password": "Pfad und Verschlüsselungspasswort testen",
|
||||
"The additional options for Nextcloud Office are currently set to": "Die zusätzlichen Optionen für Nextcloud Office sind derzeit auf",
|
||||
"The backup archive seems to be corrupt. Please try to use a different intact backup archive or try to fix it by following": "Das Backup-Archiv scheint beschädigt zu sein. Bitte versuche ein anderes intaktes Backup-Archiv zu verwenden oder repariere es gemäß",
|
||||
"The backup check was not successful. This might indicate a corrupt archive (look at the logs). If that should be the case, you can try to fix it by following": "Die Backup-Prüfung war nicht erfolgreich. Dies könnte auf ein beschädigtes Archiv hinweisen (sieh die Protokolle). Falls das der Fall ist, kannst du versuchen, es gemäß",
|
||||
"The backup section is disabled via environmental variable.": "Der Backup-Bereich ist über eine Umgebungsvariable deaktiviert.",
|
||||
"The backup uses a tool called": "Das Backup verwendet ein Tool namens",
|
||||
"The default is": "Der Standardwert ist",
|
||||
"The dictionaries for Nextcloud Office are currently set to": "Die Wörterbücher für Nextcloud Office sind derzeit auf",
|
||||
"The docker socket proxy container is deprecated. Please use the HaRP (High-availability Reverse Proxy for Nextcloud ExApps) instead!": "Der Docker-Socket-Proxy-Container ist veraltet. Bitte verwende stattdessen HaRP (High-availability Reverse Proxy for Nextcloud ExApps)!",
|
||||
"The domain validation is disabled so any domain will be accepted here! Make sure you do not make a typo here as you will not be able to change it afterwards!": "Die Domain-Validierung ist deaktiviert, daher wird hier jede Domain akzeptiert! Stelle sicher, dass du keinen Tippfehler machst, da du sie danach nicht mehr ändern kannst!",
|
||||
"The folder path that you enter must start with": "Der eingegebene Ordnerpfad muss mit",
|
||||
"The initial backup was not successful.": "Das erste Backup war nicht erfolgreich.",
|
||||
"the initial indexing can take a long time during which Nextcloud will be unavailable": "die anfängliche Indizierung kann lange dauern, während der Nextcloud nicht verfügbar ist",
|
||||
"The new passphrase needs to be at least 24 characters long. Allowed characters are the": "Die neue Passphrase muss mindestens 24 Zeichen lang sein. Erlaubte Zeichen sind die",
|
||||
"The Nextcloud container is confined and local external storage in Nextcloud is disabled.": "Der Nextcloud-Container ist eingeschränkt und lokaler externer Speicher in Nextcloud ist deaktiviert.",
|
||||
"The Nextcloud container is getting access to the": "Der Nextcloud-Container erhält Zugriff auf das",
|
||||
"The official Nextcloud installation method. Nextcloud All-in-One provides easy deployment and maintenance with most features included in this one Nextcloud instance.": "Die offizielle Nextcloud-Installationsmethode. Nextcloud All-in-One bietet einfache Bereitstellung und Wartung mit den meisten Funktionen in dieser einen Nextcloud-Instanz.",
|
||||
"The restore process has unexpectedly failed! Please adjust the path and encryption password, test it and try to restore again!": "Der Wiederherstellungsprozess ist unerwartet fehlgeschlagen! Bitte passe den Pfad und das Verschlüsselungspasswort an, teste es und versuche die Wiederherstellung erneut!",
|
||||
"The timezone for Nextcloud is currently set to": "Die Zeitzone für Nextcloud ist derzeit auf",
|
||||
"The whole process can take a while as your containers will be updated.": "Der gesamte Vorgang kann eine Weile dauern, da deine Container aktualisiert werden.",
|
||||
"The whole process should not take more than a few minutes.": "Der gesamte Vorgang sollte nicht mehr als ein paar Minuten dauern.",
|
||||
"There is now a community container that allows to access your backups in a web session. See": "Es gibt jetzt einen Community-Container, der den Zugriff auf deine Backups in einer Websitzung ermöglicht. Siehe",
|
||||
"these steps": "diese Schritte",
|
||||
"this": "diese",
|
||||
"This can be used for configuring the net.content_security_policy and more. Make sure to submit the value!": "Dies kann zur Konfiguration der net.content_security_policy und mehr verwendet werden. Stelle sicher, dass du den Wert absendest!",
|
||||
"this documentation": "diese Dokumentation",
|
||||
"This does not work with external drives like USB or network drives and only with internal drives like SATA or NVME drives.": "Dies funktioniert nicht mit externen Laufwerken wie USB- oder Netzwerklaufwerken, sondern nur mit internen Laufwerken wie SATA- oder NVME-Laufwerken.",
|
||||
"This is not expected. Most likely this happened because port": "Dies ist nicht erwartet. Höchstwahrscheinlich ist dies passiert, weil Port",
|
||||
"This is your encryption password for backups:": "Dies ist dein Verschlüsselungspasswort für Backups:",
|
||||
"This option is currently set. You can disable it again by clearing the field and submitting your changes.": "Diese Option ist derzeit gesetzt. Du kannst sie wieder deaktivieren, indem du das Feld leerst und deine Änderungen absendest.",
|
||||
"this page": "dieser Seite",
|
||||
"this section": "diesem Abschnitt",
|
||||
"This volume needs to be created beforehand manually by you in order to be able to use it. See": "Dieses Volume muss vorher manuell von dir erstellt werden, um es verwenden zu können. Siehe",
|
||||
"This will update your containers, the mastercontainer and, on Saturdays, your Nextcloud apps if the backup is successful.": "Dadurch werden deine Container, der Mastercontainer und samstags deine Nextcloud-Apps aktualisiert, wenn das Backup erfolgreich ist.",
|
||||
"Timezone change": "Zeitzone ändern",
|
||||
"To break this endless loop, you can stop the containers below and investigate the issue in the container logs before starting the containers again.": "Um diese Endlosschleife zu unterbrechen, kannst du die Container unten stoppen und das Problem in den Container-Protokollen untersuchen, bevor du die Container erneut startest.",
|
||||
"To change your backup time first disable Daily Backups, then enter your new backup time, and then re-enable them.": "Um deine Backup-Zeit zu ändern, deaktiviere zuerst tägliche Backups, gib dann deine neue Backup-Zeit ein und aktiviere sie anschließend wieder.",
|
||||
"To get the correct time values for certain Nextcloud features, set the timezone for Nextcloud to the one that your users mainly use. Please note that this setting does not apply to the mastercontainer and any backup option.": "Um die richtigen Zeitwerte für bestimmte Nextcloud-Funktionen zu erhalten, setze die Zeitzone für Nextcloud auf die, die deine Benutzer hauptsächlich verwenden. Bitte beachte, dass diese Einstellung nicht für den Mastercontainer und Backup-Optionen gilt.",
|
||||
"To store backups remotely instead, fill in the": "Um Backups stattdessen remote zu speichern, gib die",
|
||||
"to test the new value.": "um den neuen Wert zu testen.",
|
||||
"To try again, click": "Um es erneut zu versuchen, klicke auf",
|
||||
"To try again, resubmit your location and rerun the test.": "Um es erneut zu versuchen, sende deinen Speicherort erneut und führe den Test erneut aus.",
|
||||
"to update them. You should consider creating a backup first.": "um sie zu aktualisieren. Du solltest zunächst ein Backup erstellen.",
|
||||
"Update": "Aktualisierung",
|
||||
"Update backup list": "Backup-Liste aktualisieren",
|
||||
"Update mastercontainer": "Mastercontainer aktualisieren",
|
||||
"When any optional container is enabled, at least 2GB RAM, a dual-core CPU and 40GB system storage are required. When enabling ClamAV, Nextcloud Talk Recording-server or Fulltextsearch, at least 3GB RAM are required. For Talk Recording-server additional 2 vCPUs are required. When enabling everything, at least 5GB RAM and a quad-core CPU are required. Recommended are at least 1GB more RAM than the minimal requirement. For further advice and recommendations see": "Wenn ein optionaler Container aktiviert ist, sind mindestens 2 GB RAM, eine Dual-Core-CPU und 40 GB Systemspeicher erforderlich. Bei Aktivierung von ClamAV, dem Nextcloud Talk-Aufnahmeserver oder der Volltextsuche sind mindestens 3 GB RAM erforderlich. Für den Talk-Aufnahmeserver sind zusätzlich 2 vCPUs erforderlich. Bei Aktivierung aller Optionen sind mindestens 5 GB RAM und eine Quad-Core-CPU erforderlich. Empfohlen werden mindestens 1 GB mehr RAM als die Mindestanforderung. Weitere Ratschläge und Empfehlungen findest du unter",
|
||||
"When the mastercontainer is updated it will restart, making it unavailable for a moment.": "Wenn der Mastercontainer aktualisiert wird, startet er neu und ist kurzzeitig nicht verfügbar.",
|
||||
"Whiteboard": "Whiteboard",
|
||||
"will create backups at 4 am UTC and": "erstellt Backups um 4 Uhr UTC und",
|
||||
"will get installed)": "wird installiert)",
|
||||
"with a compatible domain provider for DNS updates.": "mit einem kompatiblen Domain-Anbieter für DNS-Updates verwenden.",
|
||||
"yet and want to do that now, feel free to follow": "noch nicht aktualisiert hast und dies jetzt tun möchtest, folge gerne",
|
||||
"You are running the": "Du verwendest den",
|
||||
"You can alternatively restore a former AIO instance from backup.": "Du kannst alternativ eine frühere AIO-Instanz aus einem Backup wiederherstellen.",
|
||||
"You can change the timezone by clicking on the button below.": "Du kannst die Zeitzone ändern, indem du auf die Schaltfläche unten klickst.",
|
||||
"You can change the timezone when your containers are stopped.": "Du kannst die Zeitzone ändern, wenn deine Container gestoppt sind.",
|
||||
"You can change your AIO passphrase below:": "Du kannst deine AIO-Passphrase unten ändern:",
|
||||
"You can configure additional options for Nextcloud Office below.": "Du kannst unten weitere Optionen für Nextcloud Office konfigurieren.",
|
||||
"You can configure the timezone for Nextcloud below (Do not forget to submit the value!):": "Du kannst die Zeitzone für Nextcloud unten konfigurieren (Vergiss nicht, den Wert abzusenden!):",
|
||||
"You can either create a new AIO instance or restore a former AIO instance from backup. See the two sections below.": "Du kannst entweder eine neue AIO-Instanz erstellen oder eine frühere AIO-Instanz aus einem Backup wiederherstellen. Siehe die beiden Abschnitte unten.",
|
||||
"You can enable or disable the options below only when your containers are stopped.": "Du kannst die folgenden Optionen nur aktivieren oder deaktivieren, wenn deine Container gestoppt sind.",
|
||||
"You can find all changes": "Alle Änderungen findest du",
|
||||
"You can find the changelog": "Das Änderungsprotokoll findest du",
|
||||
"You can reset them again by clicking on the button below.": "Du kannst sie zurücksetzen, indem du auf die Schaltfläche unten klickst.",
|
||||
"You can run Nextcloud's usual occ commands by following the": "Du kannst die üblichen occ-Befehle von Nextcloud gemäß der",
|
||||
"You can use the browser search [CTRL]+[F] to search through the documentation. Additional documentation can be found": "Du kannst die Browser-Suche [STRG]+[F] verwenden, um die Dokumentation zu durchsuchen. Weitere Dokumentation findest du",
|
||||
"You may change the backup path again since the initial backup was not successful. After submitting the new value, you need to click on": "Du kannst den Backup-Pfad erneut ändern, da das erste Backup nicht erfolgreich war. Nach dem Absenden des neuen Werts musst du auf",
|
||||
"You may still need to authorize this pubkey on your borg remote:": "Möglicherweise musst du diesen öffentlichen Schlüssel noch auf deinem Borg-Remote autorisieren:",
|
||||
"You need to make sure that all given directories exist or the backup container will fail to start!": "Du musst sicherstellen, dass alle angegebenen Verzeichnisse vorhanden sind, da der Backup-Container sonst nicht starten kann!",
|
||||
"You need to make sure that the dictionaries that you enter are valid. An example is": "Du musst sicherstellen, dass die eingegebenen Wörterbücher gültig sind. Ein Beispiel ist",
|
||||
"You need to make sure that the options that you enter are valid. An example is": "Du musst sicherstellen, dass die eingegebenen Optionen gültig sind. Ein Beispiel ist",
|
||||
"You need to make sure that the timezone that you enter is valid. An example is": "Du musst sicherstellen, dass die eingegebene Zeitzone gültig ist. Ein Beispiel ist",
|
||||
"you need to restore the same backup a second time after this attempt so that the community container data is also correctly restored.": "musst du dasselbe Backup nach diesem Versuch ein zweites Mal wiederherstellen, damit die Community-Container-Daten ebenfalls korrekt wiederhergestellt werden.",
|
||||
"You will be provided with an SSH public key for authorization at the remote afterwards.": "Du erhältst danach einen öffentlichen SSH-Schlüssel zur Autorisierung am Remote.",
|
||||
"Your borg ssh public key is:": "Dein öffentlicher Borg-SSH-Schlüssel lautet:",
|
||||
"Your containers are up-to-date.": "Deine Container sind auf dem neuesten Stand.",
|
||||
"Your current AIO passphrase": "Deine aktuelle AIO-Passphrase",
|
||||
"Your new AIO passphrase": "Deine neue AIO-Passphrase"
|
||||
}
|
||||
223
php/translations/pull.sh
Executable file
223
php/translations/pull.sh
Executable file
@@ -0,0 +1,223 @@
|
||||
#!/usr/bin/env bash
|
||||
# pull.sh — Fetch all translations from Transifex API v3 and write them to
|
||||
# php/translations/{lang}.json.
|
||||
#
|
||||
# Usage:
|
||||
# TRANSIFEX_TOKEN=your_token ./pull.sh
|
||||
#
|
||||
# Optional env vars:
|
||||
# TRANSIFEX_ORG — Transifex organisation slug (default: nextcloud)
|
||||
# TRANSIFEX_PROJECT — Transifex project slug (default: nextcloud-all-in-one)
|
||||
#
|
||||
# Requirements: bash, curl, jq
|
||||
#
|
||||
# Never called at runtime — run manually or from CI before a release.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Configuration
|
||||
# ---------------------------------------------------------------------------
|
||||
TOKEN="${TRANSIFEX_TOKEN:?'TRANSIFEX_TOKEN env var must be set'}"
|
||||
ORG="${TRANSIFEX_ORG:-nextcloud}"
|
||||
PROJECT="${TRANSIFEX_PROJECT:-nextcloud-all-in-one}"
|
||||
|
||||
API="https://rest.api.transifex.com"
|
||||
AUTH_HEADER="Authorization: Bearer ${TOKEN}"
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
require_cmd() {
|
||||
if ! command -v "$1" &>/dev/null; then
|
||||
echo "ERROR: required command '$1' not found." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
require_cmd curl
|
||||
require_cmd jq
|
||||
|
||||
log() { echo "[pull.sh] $*"; }
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 1. Fetch the list of languages for the project
|
||||
# ---------------------------------------------------------------------------
|
||||
log "Fetching language list for ${ORG}/${PROJECT} …"
|
||||
|
||||
languages_response=$(curl --silent --fail --show-error \
|
||||
-H "${AUTH_HEADER}" \
|
||||
-H "Content-Type: application/vnd.api+json" \
|
||||
"${API}/projects/o:${ORG}:p:${PROJECT}/languages")
|
||||
|
||||
mapfile -t lang_codes < <(echo "${languages_response}" \
|
||||
| jq -r '.data[].attributes.code')
|
||||
|
||||
if [[ ${#lang_codes[@]} -eq 0 ]]; then
|
||||
log "No languages found — nothing to do."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log "Found ${#lang_codes[@]} language(s): ${lang_codes[*]}"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 2. Fetch the list of resources for the project (we need the resource slug)
|
||||
# ---------------------------------------------------------------------------
|
||||
log "Fetching resource list …"
|
||||
|
||||
resources_response=$(curl --silent --fail --show-error \
|
||||
-H "${AUTH_HEADER}" \
|
||||
-H "Content-Type: application/vnd.api+json" \
|
||||
"${API}/resources?filter[project]=o:${ORG}:p:${PROJECT}")
|
||||
|
||||
mapfile -t resource_slugs < <(echo "${resources_response}" \
|
||||
| jq -r '.data[].attributes.slug')
|
||||
|
||||
if [[ ${#resource_slugs[@]} -eq 0 ]]; then
|
||||
log "No resources found — nothing to do."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log "Found ${#resource_slugs[@]} resource(s): ${resource_slugs[*]}"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 3. For each language, merge translations from all resources and write JSON
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# poll_until_ready <url> — keeps polling an async download URL until the
|
||||
# Transifex job finishes, then prints the redirect/content URL.
|
||||
poll_until_ready() {
|
||||
local url="$1"
|
||||
local max_attempts=30
|
||||
local attempt=0
|
||||
local delay=2
|
||||
|
||||
while (( attempt < max_attempts )); do
|
||||
response=$(curl --silent --fail --show-error \
|
||||
-H "${AUTH_HEADER}" \
|
||||
-H "Content-Type: application/vnd.api+json" \
|
||||
"${url}")
|
||||
|
||||
status=$(echo "${response}" | jq -r '.data.attributes.status // empty')
|
||||
|
||||
case "${status}" in
|
||||
succeeded)
|
||||
echo "${response}" | jq -r '.data.attributes.download_url'
|
||||
return 0
|
||||
;;
|
||||
failed)
|
||||
echo "ERROR: Transifex async job failed: $(echo "${response}" | jq -r '.data.attributes.errors // empty')" >&2
|
||||
return 1
|
||||
;;
|
||||
*)
|
||||
# pending / processing — wait and retry
|
||||
sleep "${delay}"
|
||||
(( attempt++ )) || true
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "ERROR: Timed out waiting for Transifex download." >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
for lang in "${lang_codes[@]}"; do
|
||||
# Skip English — the key itself IS the English string.
|
||||
if [[ "${lang}" == "en" ]]; then
|
||||
log "Skipping English (source language)."
|
||||
continue
|
||||
fi
|
||||
|
||||
log "Processing language: ${lang}"
|
||||
|
||||
# Collect merged translations from all resources into one flat map.
|
||||
declare -A merged_translations=()
|
||||
|
||||
for resource in "${resource_slugs[@]}"; do
|
||||
log " Requesting download for resource '${resource}' / language '${lang}' …"
|
||||
|
||||
# Request an async resource translation download (KEYVALUEJSON format).
|
||||
job_response=$(curl --silent --fail --show-error \
|
||||
-X POST \
|
||||
-H "${AUTH_HEADER}" \
|
||||
-H "Content-Type: application/vnd.api+json" \
|
||||
-d "{
|
||||
\"data\": {
|
||||
\"attributes\": {
|
||||
\"callback_url\": null,
|
||||
\"content_encoding\": \"text\",
|
||||
\"file_type\": \"default\",
|
||||
\"language\": \"l:${lang}\",
|
||||
\"mode\": \"translator\"
|
||||
},
|
||||
\"relationships\": {
|
||||
\"resource\": {
|
||||
\"data\": {
|
||||
\"id\": \"o:${ORG}:p:${PROJECT}:r:${resource}\",
|
||||
\"type\": \"resources\"
|
||||
}
|
||||
}
|
||||
},
|
||||
\"type\": \"resource_translations_async_downloads\"
|
||||
}
|
||||
}" \
|
||||
"${API}/resource_translations_async_downloads")
|
||||
|
||||
job_id=$(echo "${job_response}" | jq -r '.data.id')
|
||||
if [[ -z "${job_id}" || "${job_id}" == "null" ]]; then
|
||||
log " WARNING: Could not start async download for ${resource}/${lang} — skipping."
|
||||
continue
|
||||
fi
|
||||
|
||||
# Poll until ready and get the download URL.
|
||||
download_url=$(poll_until_ready "${API}/resource_translations_async_downloads/${job_id}")
|
||||
|
||||
# Download the raw file content (KEYVALUEJSON = flat JSON object).
|
||||
raw=$(curl --silent --fail --show-error -L \
|
||||
-H "${AUTH_HEADER}" \
|
||||
"${download_url}")
|
||||
|
||||
# Merge the flat key-value pairs from this resource.
|
||||
while IFS= read -r line; do
|
||||
key=$(echo "${line}" | jq -r '.key')
|
||||
value=$(echo "${line}" | jq -r '.value')
|
||||
if [[ -n "${key}" && -n "${value}" && "${value}" != "null" ]]; then
|
||||
merged_translations["${key}"]="${value}"
|
||||
fi
|
||||
done < <(echo "${raw}" | jq -c 'to_entries[] | {key: .key, value: .value}')
|
||||
done
|
||||
|
||||
# Build the output JSON object from the merged map.
|
||||
output_file="${SCRIPT_DIR}/${lang}.json"
|
||||
tmp_file="${output_file}.tmp"
|
||||
|
||||
{
|
||||
echo "{"
|
||||
first=true
|
||||
for key in "${!merged_translations[@]}"; do
|
||||
value="${merged_translations[${key}]}"
|
||||
if [[ "${first}" == true ]]; then
|
||||
first=false
|
||||
else
|
||||
echo ","
|
||||
fi
|
||||
# Use jq to safely encode both key and value as JSON strings.
|
||||
printf '%s: %s' \
|
||||
"$(echo -n "${key}" | jq -Rs '.')" \
|
||||
"$(echo -n "${value}" | jq -Rs '.')"
|
||||
done
|
||||
echo ""
|
||||
echo "}"
|
||||
} > "${tmp_file}"
|
||||
|
||||
# Validate & pretty-print the JSON before writing it out.
|
||||
jq '.' "${tmp_file}" > "${output_file}"
|
||||
rm -f "${tmp_file}"
|
||||
|
||||
log " Written ${output_file}"
|
||||
unset merged_translations
|
||||
done
|
||||
|
||||
log "Done."
|
||||
29
readme.md
29
readme.md
@@ -221,6 +221,7 @@ https://your-domain-that-points-to-this-server.tld:8443
|
||||
- [How to adjust the internally used docker api version?](#how-to-adjust-the-internally-used-docker-api-version)
|
||||
- [How to change the default location of Nextcloud's Datadir?](#how-to-change-the-default-location-of-nextclouds-datadir)
|
||||
- [How to configure custom UID/GID?](#how-to-configure-custom-uidgid)
|
||||
- [How to move the appdata folder from the datadir to an ssd to improve the performance?](#how-to-move-the-appdata-folder-from-the-datadir-to-an-ssd-to-improve-the-performance)
|
||||
- [How to store the files/installation on a separate drive?](#how-to-store-the-filesinstallation-on-a-separate-drive)
|
||||
- [How to limit the resource usage of AIO?](#how-to-limit-the-resource-usage-of-aio)
|
||||
- [How to allow the Nextcloud container to access directories on the host?](#how-to-allow-the-nextcloud-container-to-access-directories-on-the-host)
|
||||
@@ -475,7 +476,26 @@ Another solution if you really need to use host mounts is to use a bind mount to
|
||||
/source/path /target/path/where/the/source/directory/will/be/mounted/on/the/server fuse.bindfs force-user=33,force-group=33,allow_other 0 0
|
||||
```
|
||||
|
||||
You can then use `--env NEXTCLOUD_DATADIR="/target/path/where/the/source/directory/will/be/mounted/on/the/server"` as described in the section above.
|
||||
Then use `sudo mount /target/path/where/the/source/directory/will/be/mounted/on/the/server` to mount it directly.
|
||||
|
||||
You can afterwards use `--env NEXTCLOUD_DATADIR="/target/path/where/the/source/directory/will/be/mounted/on/the/server"` as described in the section above.
|
||||
|
||||
### How to move the appdata folder from the datadir to an ssd to improve the performance?
|
||||
If the datadir in your setup is configured to be placed on an HDD or network FS like SMB or NFS, you can follow the steps below to change the location of the appdata folder to be located on an SSD in order to improve the performance of the setup.
|
||||
|
||||
> [!NOTE]
|
||||
> The following steps only work if you already configured and used NEXTCLOUD_DATADIR as mentioned [two sections above](#how-to-change-the-default-location-of-nextclouds-datadir).
|
||||
> In this example here, we assume that you used `NEXTCLOUD_DATADIR="/target/path/`.
|
||||
|
||||
After the initial installation is done and all datadir files of Nextcloud are stored inside the configured `/target/path` directory, you will also see an `appdata_*` folder in there that stores app-related data. You can now move that folder to a faster SSD if the target dir is not already positioned on an SSD by first using `rsync` to sync the files a location on an SSD. Afterwards rename the appdata folder in the datadir to something like `appdata_*-backup`. Afterwards add the following line to `/etc/fstab`:
|
||||
```
|
||||
/source/path/on/ssd /target/path/<appdata-path> fuse.bindfs force-user=33,force-group=33,allow_other 0 0
|
||||
```
|
||||
Do not forget to adjust `<appdata-path>` to the correct `appdata_*` name that your installation initially created automatically.
|
||||
|
||||
Then use `sudo mount /target/path/<appdata-path>` to mount it directly.
|
||||
|
||||
Afterwards things should be speed up.
|
||||
|
||||
### How to store the files/installation on a separate drive?
|
||||
You can move the whole docker library and all its files including all Nextcloud AIO files and folders to a separate drive by first mounting the drive in the host OS (NTFS is not supported and ext4 is recommended as FS) and then following this tutorial: https://www.guguweb.com/2019/02/07/how-to-move-docker-data-directory-to-another-location-on-ubuntu/<br>
|
||||
@@ -634,7 +654,7 @@ Additionally, you might need to create a custom user script to start all sibling
|
||||
sleep 120
|
||||
|
||||
# Execute the actual command
|
||||
docker exec --env START_CONTAINERS=1 nextcloud-aio-mastercontainer /daily-backup.sh`
|
||||
docker exec --env START_CONTAINERS=1 nextcloud-aio-mastercontainer /daily-backup.sh
|
||||
```
|
||||
|
||||
Apart from that, the installation of AIO should work like on "normal" Linux. So refer to the Linux instructions for installation.
|
||||
@@ -748,7 +768,10 @@ password=<password>
|
||||
```
|
||||
(Of course you need to modify `<smb/cifs username>` and `<password>` for your specific case.)
|
||||
|
||||
Now you can use `/mnt/storagebox` as Nextcloud's datadir like described in the section above this one.
|
||||
Now you can use `/mnt/storagebox` as Nextcloud's datadir like described in the section [here](#how-to-change-the-default-location-of-nextclouds-datadir).
|
||||
|
||||
> [!NOTE]
|
||||
> You also might want to move the appdata dir after the initial installation is done to improve the performance. See [this section](#how-to-move-the-appdata-folder-from-the-datadir-to-an-ssd-to-improve-the-performance)
|
||||
|
||||
### Can I run this with Docker swarm?
|
||||
Yes. For that to work, you need to use and follow the [manual-install documentation](./manual-install/).
|
||||
|
||||
@@ -169,8 +169,8 @@ The process to run Nextcloud AIO behind a reverse proxy has three required steps
|
||||
|
||||
The reverse-proxy container needs to be connected to the nextcloud containers. This can be achieved one of these 3 ways:
|
||||
1. Utilize host networking instead of docker bridge networking: Specify `--network host` option (or `network_mode: host` for docker-compose) as setting for the reverse proxy container to connect it to the host network. If you are using a firewall on the server, you need to open ports 80 and 443 for the reverse proxy manually. With this setup, the default sample configurations with reverse-proxy pointing to `localhost:$APACHE_PORT` should work directly.
|
||||
1. Connect nextcloud's external-facing containers to the reverse-proxy's docker network by specifying env variable APACHE_ADDITIONAL_NETWORK. With this setup, the reverse proxy can utilize Docker bridge network's DNS name resolution to access nextcloud at `http://nextcloud-aio-apache:$APACHE_PORT`. ⚠️⚠️⚠️ Note, the specified network must already exist before Nextcloud AIO is started. Otherwise it will fail to start the container because the network is not existing.
|
||||
1. Connect the reverse-proxy container to the `nextcloud-aio` network by specifying it as a secondary (external) network for the reverse proxy container. With this setup also, the reverse proxy can utilize Docker bridge network's DNS name resolution to access nextcloud at `http://nextcloud-aio-apache:$APACHE_PORT` .
|
||||
1. Connect nextcloud's external-facing containers to the reverse-proxy's docker network by specifying env variable APACHE_ADDITIONAL_NETWORK. With this setup, the reverse proxy can utilize Docker bridge network's DNS name resolution to access nextcloud at `http://nextcloud-aio-apache.nextcloud-aio:$APACHE_PORT`. ⚠️⚠️⚠️ Note, the specified network must already exist before Nextcloud AIO is started. Otherwise it will fail to start the container because the network is not existing.
|
||||
1. Connect the reverse-proxy container to the `nextcloud-aio` network by specifying it as a secondary (external) network for the reverse proxy container. With this setup also, the reverse proxy can utilize Docker bridge network's DNS name resolution to access nextcloud at `http://nextcloud-aio-apache.nextcloud-aio:$APACHE_PORT` .
|
||||
|
||||
</details>
|
||||
|
||||
@@ -1106,12 +1106,9 @@ After starting AIO, you should be able to access the AIO Interface via `https://
|
||||
⚠️ **Important:** do always use an ip-address if you access this port and not a domain as HSTS might block access to it later! (It is also expected that this port uses a self-signed certificate due to security concerns which you need to accept in your browser)<br>
|
||||
Enter your domain in the AIO interface that you've used in the reverse proxy config and you should be done. Please do not forget to open/forward port `3478/TCP` and `3478/UDP` in your firewall/router for the Talk container!
|
||||
|
||||
### 5. Optional: Configure AIO for reverse proxies that connect to nextcloud using an ip-address and not localhost nor 127.0.0.1
|
||||
If your reverse proxy connects to nextcloud using an ip-address and not localhost or 127.0.0.1<sup>*</sup> you must make the following configuration changes
|
||||
### 5. Optional: Configure AIO for reverse proxies that connect to nextcloud not using localhost nor 127.0.0.1
|
||||
If your reverse proxy connects to nextcloud not using localhost or 127.0.0.1, you must add said IP as trusted proxy to the installation. See the step below:
|
||||
|
||||
<small>*: The IP address it uses to connect to AIO is not in a private IP range such as these: `127.0.0.0/8,192.168.0.0/16,172.16.0.0/12,10.0.0.0/8,100.64.0.0/10,fd00::/8,::1/128`</small>
|
||||
|
||||
#### Nextcloud trusted proxies
|
||||
Add the IP it uses connect to AIO to the Nextcloud trusted_proxies like this:
|
||||
|
||||
```
|
||||
@@ -1134,6 +1131,7 @@ If you want to also access your AIO interface publicly with a valid certificate,
|
||||
```
|
||||
https://<your-nc-domain>:8443 {
|
||||
reverse_proxy https://localhost:8080 {
|
||||
header_up Host {host}
|
||||
transport http {
|
||||
tls_insecure_skip_verify
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Initial setup
|
||||
|
||||
- [ ] Verify that after starting the test container, you can access the AIO interface using https://internal.ip.address:8080
|
||||
- [ ] After clicking the self-signed-certificate warning away, it should show the setup page with an explanation what AIO is and the initial password and a button that contains a link to the AIO login page
|
||||
- [ ] After copying the password and clicking on this button, it should open a new tab with the login page
|
||||
- [ ] The login page should show an input field that allows to enter the AIO password and a `Log in` button
|
||||
- [ ] After pasting the new password into the input field and clicking on this button button, you should be logged in
|
||||
- [ ] After clicking the self-signed-certificate warning away, it should show the setup page with an explanation what AIO is and the initial passphrase and a button that contains a link to the AIO login page
|
||||
- [ ] After copying the passphrase and clicking on this button, it should open a new tab with the login page
|
||||
- [ ] The login page should show an input field that allows to enter the AIO passphrase and a `Log in` button
|
||||
- [ ] After pasting the passphrase into the input field and clicking on this button, you should be logged in
|
||||
- [ ] You should now see the containers page and you should see three sections: one general section which explains what AIO is, one `New AIO instance` section and one section that allows to restore the whole AIO instance from backup.
|
||||
|
||||
You can now continue with [002-new-instance.md](./002-new-instance.md) or [010-restore-instance.md](./010-restore-instance.md).
|
||||
|
||||
@@ -11,7 +11,7 @@ For the below to work, it is important that you have a domain that you point ont
|
||||
- [ ] Entering the domain that does point to your server e.g. `yourdomain.com` should finally redirect you to the next screen (if you did not configure your domain yet or did not open port 443, it should report that to you)
|
||||
- [ ] Now you should see a button `Start containers` and an explanation which points out that clicking on the button will start the containers and that this can take a long time.
|
||||
- [ ] Below that you should see a section `Optional addons` which shows a checkbox list with addons that can be enabled or disabled.
|
||||
- [ ] Collabora and Nextcloud Talk should be enabled, the rest disabled
|
||||
- [ ] Collabora, Imaginary, Talk and Whiteboard should be enabled, the rest disabled
|
||||
- [ ] Unchecking/Checking any of these should insert a button that allows to save the set config
|
||||
- [ ] Checking OnlyOffice and Collabora at the same time should show a warning that this is not supported and should not saving the new config
|
||||
- [ ] Recommended is to uncheck all options now
|
||||
|
||||
@@ -1,18 +1,32 @@
|
||||
# Initial backup
|
||||
|
||||
- [ ] In the Backup and restore section, you should now see and input box where you should type in the path where the backup should get created and some explanation below
|
||||
- [ ] In the Backup and restore section, you should now see two input boxes where for one you should type in the path where the backup should get created and some explanation below or the other type in a remote ssh location
|
||||
- [ ] First, check a local backup:
|
||||
- [ ] Enter `/` which should send an error
|
||||
- [ ] Enter `/mnt/` or `/media/` or `/host_mnt/` or `/var/backups/` should send an error as well
|
||||
- [ ] Accepted should be `/mnt/backup`, `/media/backup`, `/host_mnt/c/backup` and `/var/backups`.
|
||||
- [ ] The side should now reload
|
||||
- [ ] In the Backup restore section you should now see a Backup information section with important info like the encryption password, the backup location and more.
|
||||
- [ ] Also you should see a Backup creation section that contains a `Create backup` button.
|
||||
- [ ] Clicking on the `Create backup` button should open a window prompt that allows to cancel the operation.
|
||||
- [ ] Canceling should return to the website, confirming should reveal the big spinner again which should block the website again.
|
||||
- [ ] After a while you should see the information that Backup container is currently running
|
||||
- [ ] another option are remote backups via SSH using borgbackup. The remote borg repo URL must contain both `@` and `:`. The process works as follows:
|
||||
1. You enter a remote borg repo URL (e.g. `ssh://user@host:port/path/to/repo` or `user@host:/path/to/repo`).
|
||||
2. On the first connection attempt, a SSH key pair is generated automatically and the public key is displayed.
|
||||
3. You add the public key to the `~/.ssh/authorized_keys` file on the remote server so that AIO can connect to it.
|
||||
4. Once authorized, AIO can create and restore backups on the remote server.
|
||||
- [ ] Enter `user` (no `@` and no `:`) which should send an error
|
||||
- [ ] Enter `user@host` (no `:`) which should send an error
|
||||
- [ ] Enter `userhost:/path` (no `@`) which should send an error
|
||||
- [ ] Accepted should be `ssh://user@host:22/path/to/repo` or `user@host:/path/to/repo`
|
||||
- [ ] Both a local backup location and a remote repo URL should not be accepted at the same time
|
||||
- [ ] The page should now reload
|
||||
- [ ] Now click on `Create backup`
|
||||
- [ ] After the first failed backup attempt with a remote repo, the SSH public key for borg should be shown so it can be authorized on the remote server
|
||||
- [ ] After authorizing the server on the remote, scroll down and click on `Create backup` again to create another backup. This time it should succeed.
|
||||
- [ ] The initial Nextcloud credentials on top of the page that are visible when the containers are running should now be hidden in a details tag
|
||||
- [ ] In the Backup restore section you should now see a Backup information section with important info like the encryption password, the backup location and more.
|
||||
- [ ] Also you should see a Backup cretion section that contains a `Create backup` button.
|
||||
- [ ] Clicking on the `Create backup` button should open a window prompt that allows to cancel the operation.
|
||||
- [ ] Canceling should return to the website, confirming should reveal the big spinner again which should block the website again.
|
||||
- [ ] After a while you should see the information that Backup container is currently running
|
||||
- [ ] Below the Containers section you should see the option to `Start containers` again.
|
||||
- [ ] After a while and a few automatic reloads (as long as the side is focused), you should be redirected to the usual page and seen in the Backup and restore section that the last backup was successful.
|
||||
- [ ] Below thhat you should see a details tag that allows to reveal all backup options
|
||||
- [ ] Below that you should see a details tag that allows to reveal all backup options
|
||||
|
||||
You can now continue with [020-backup-and-restore.md](.//020-backup-and-restore.md)
|
||||
@@ -2,17 +2,34 @@
|
||||
|
||||
For the below to work, you need a backup archive of an AIO instance and the location on the test machine and the password for the backup archive. You can get one here: [backup-archive](./assets/backup-archive/)
|
||||
|
||||
- [ ] The section that allows to restore the whole AIO instance from backup should show two input fields: one that allows to enter a location where the backup archive is located and one that allows to enter password of the archive. It should also show a short explanation regarding the path requirements
|
||||
- [ ] Entering an incorrect path and/or password should let you continue and test your settings in the next step
|
||||
- [ ] Clicking on the test button should after a reload bring you back to the initial screen where it should say that the test was unsuccessful. Also you should be able to have a look at the backup container logs for investigation what exactly failed.
|
||||
- [ ] You should also now see the input boxes again where you can change the path and password, confirm it and bring you again to the screen where you can test your settings.
|
||||
- [ ] Entering the correct path to the backup archive and the correct password here should:
|
||||
- [ ] Should reload and should hide all options except the option to test the path and password
|
||||
- [ ] After the test you should see the options to check the integrity of the backup and a list of backup archives that you can choose from to restore your instance
|
||||
- [ ] Clicking on either option should show a window prompt that lets you cancel the operation
|
||||
- [ ] Clicking on the integrity check option should check the integrity and report that the backup integrity is good after a while which should then only show the option to choose the backup archive that should be restored
|
||||
- [ ] Choosing the restore option should finally restore your files.
|
||||
- [ ] After waiting a while it should reload the page and should show the usual container interface again with the state of your containers (stopped) and the option to start and update the containers again.
|
||||
- [ ] The section that allows to restore the whole AIO instance from backup should show three input fields: one that allows to enter a location where the backup archive is located and one that allows to enter a remote ssh path and one that allows to enter password of the archive. It should also show a short explanation regarding the path requirements
|
||||
- [ ] First, check restoring from a local backup location:
|
||||
- [ ] Entering an incorrect path and/or password should let you continue and test your settings in the next step
|
||||
- [ ] Clicking on the test button should after a reload bring you back to the initial screen where it should say that the test was unsuccessful. Also you should be able to have a look at the backup container logs for investigation what exactly failed.
|
||||
- [ ] You should also now see the input boxes again where you can change the path and password, confirm it and bring you again to the screen where you can test your settings.
|
||||
- [ ] Entering the correct path to the backup archive and the correct password here should:
|
||||
- [ ] Should reload and should hide all options except the option to test the path and password
|
||||
- [ ] After the test you should see the options to check the integrity of the backup and a list of backup archives that you can choose from to restore your instance
|
||||
- [ ] Clicking on either option should show a window prompt that lets you cancel the operation
|
||||
- [ ] Clicking on the integrity check option should check the integrity and report that the backup integrity is good after a while which should then only show the option to choose the backup archive that should be restored
|
||||
- [ ] Choosing the restore option should finally restore your files.
|
||||
- [ ] After waiting a while it should reload the page and should show the usual container interface again with the state of your containers (stopped) and the option to start and update the containers again.
|
||||
- [ ] Next, check restoring from a remote backup location via SSH. The remote borg repo URL must contain both `@` and `:`. The restore process works as follows:
|
||||
1. You enter a remote borg repo URL (e.g. `ssh://user@host:port/path/to/repo` or `user@host:/path/to/repo`) and the backup password.
|
||||
2. On the first connection attempt, a SSH key pair is generated automatically and the public key is displayed.
|
||||
3. You add the public key to the `~/.ssh/authorized_keys` file on the remote server so that AIO can connect to it.
|
||||
4. Once authorized, AIO can list and restore backups from the remote server.
|
||||
- [ ] Enter an invalid remote repo URL (e.g. `user` without `@` and `:`) which should send an error
|
||||
- [ ] Enter a valid remote borg repo URL and the correct backup password:
|
||||
- [ ] Should reload and should hide all options except the option to test the path and password
|
||||
- [ ] After the first failed connection attempt, the SSH public key for borg should be shown so it can be authorized on the remote server
|
||||
- [ ] After authorizing the key on the remote server, scroll down and click on the test button again. This time it should succeed and show the options to check the integrity and list backup archives
|
||||
- [ ] After the test you should see the options to check the integrity of the backup and a list of backup archives that you can choose from to restore your instance
|
||||
- [ ] Clicking on either option should show a window prompt that lets you cancel the operation
|
||||
- [ ] Clicking on the integrity check option should check the integrity and report that the backup integrity is good after a while which should then only show the option to choose the backup archive that should be restored
|
||||
- [ ] Choosing the restore option should finally restore your files.
|
||||
- [ ] After waiting a while it should reload the page and should show the usual container interface again with the state of your containers (stopped) and the option to start and update the containers again.
|
||||
|
||||
- [ ] Clicking on `Start and update containers` should show a window prompt that you should create a backup. Canceling should cancel the operation, confirming should reveal the big spinner again.
|
||||
- [ ] After waiting a bit, all containers should be green and your instance should be fully functional again
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Backup and restore
|
||||
|
||||
- [ ] Expanding all backup options in the Backup and restore sectioin should reveal a Backup information section, Backup creation section, Backup check section, Backup restore section and a Daily backup section.
|
||||
- [ ] Expanding all backup options in the Backup and restore sectioin should reveal a Backup information section, Backup creation section, Backup check section, Backup restore section and a Daily backup section as well as a additional backup location section
|
||||
- [ ] The backup restore section should list all available backup archives and list them from most recent to least recent.
|
||||
- [ ] Clicking on either option of Create backup, Check backup integrity or Restore selected backup should run the corresponding action and report after a while in the last check, backup or restore was successful.
|
||||
- [ ] Daily backup creatio should allow to enter a time in 24h format e.g. `04:00` should be accepted, `24:00` or `dfjlk` not.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# AIO password change
|
||||
# AIO passphrase change
|
||||
|
||||
- [ ] In the AIO password change section you should see two input fields. And below the requirements for a new password
|
||||
- [ ] When entering nothing it should report that you need to enter your current aio password
|
||||
- [ ] When entering a false password, it should report that to you
|
||||
- [ ] After entering your current password and leaving the new password empty it should report that you need to enter a new password
|
||||
- [ ] After entering a new passwort shorter than 24 characters or not allowed characters, it should report that the password requirements are not met.
|
||||
- [ ] In the AIO passphrase change section you should see two input fields. And below the requirements for a new passphrase
|
||||
- [ ] When entering nothing it should report that you need to enter your current AIO passphrase
|
||||
- [ ] When entering a false passphrase, it should report that to you
|
||||
- [ ] After entering your current passphrase and leaving the new passphrase empty it should report that you need to enter a new passphrase
|
||||
- [ ] After entering a new passphrase shorter than 24 characters or not allowed characters, it should report that the passphrase requirements are not met.
|
||||
- [ ] `sdfjlksj` should not be accepted
|
||||
- [ ] `jdsfklöjiroewoäsadjkfölk` should not be accepted
|
||||
- [ ] `sdjlfj SDJFLK 32489 sdjklf` should which should reload the page
|
||||
- [ ] `sdjlfj SDJFLK 32489 sdjklf` should be accepted, which should reload the page
|
||||
|
||||
You can now continue with [040-login-behavior.md](./040-login-behavior.md)
|
||||
@@ -1,7 +1,7 @@
|
||||
# Login behavior
|
||||
|
||||
- [ ] When opening the AIO interface in a new tab while the apache container is running, it should report on the login page that Nextcloud is running and you should use the automatic login
|
||||
- [ ] When the apache container is stopped, you should see here an input field that allows you to enter the AIO password which should log you in
|
||||
- [ ] When the apache container is stopped, you should see here an input field that allows you to enter the AIO passphrase which should log you in
|
||||
- [ ] Starting and stopping the containers multiple times should every time produce a new token that is used in the admin overview in Nextcloud as link in the button to log you into the AIO interface. (see [003-automatic-login.md](./003-automatic-login.md))
|
||||
|
||||
You can now continue with [050-optional-addons.md](./050-optional-addons.md)
|
||||
@@ -10,6 +10,8 @@
|
||||
- [ ] Imaginary by having a look if when uploading a new picture in Nextcloud, it adds some log entries to the container
|
||||
- [ ] Fulltextsearch by trying to search for a heading inside a file in Nextcloud
|
||||
- [ ] Talk-recording by starting a call and trying to record something
|
||||
- [ ] When Collabora is enabled, it should show below the Optional Addons section a section where you can change the dictionaries for collabora. `de_DE en_GB en_US es_ES fr_FR it nl pt_BR pt_PT ru` should be a valid setting. E.g. `de.De` not. If already set, it should show a button that allows to remove the setting again.
|
||||
- [ ] When Collabora is enabled
|
||||
- [ ] It should show below the Optional Addons section a section where you can change the dictionaries for collabora. `de_DE en_GB en_US es_ES fr_FR it nl pt_BR pt_PT ru` should be a valid setting. E.g. `de.De` not. If already set, it should show a button that allows to remove the setting again.
|
||||
- [ ] Also, you should see an input field that allows to enter additional collabora options. E.g. `net.content_security_policy=false` should not be accepted, but `--o:net.content_security_policy="frame-ancestors *.example.com:*;"` should.
|
||||
|
||||
You can now continue with [060-environmental-variables.md](./060-environmental-variables.md)
|
||||
You can now continue with [055-community-containers.md](./055-community-containers.md)
|
||||
13
tests/QA/055-community-containers.md
Normal file
13
tests/QA/055-community-containers.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Community Containers
|
||||
|
||||
- [ ] At the very bottom of the page, there should be a Community Containers section
|
||||
- [ ] The section should show a details element that allows to reveal the list of available community containers
|
||||
- [ ] When containers are running, the checkboxes should be disabled and a notice should inform the user that changes can only be made when containers are stopped
|
||||
- [ ] When containers are stopped, checkboxes should be enabled
|
||||
- [ ] Enabling a community container and clicking `Save changes` should show a confirmation dialog
|
||||
- [ ] Canceling the confirmation dialog should not save the changes
|
||||
- [ ] Confirming should save the changes and reload the page
|
||||
- [ ] After saving, the enabled community container should appear in the containers section and start along with the other containers when `Start containers` is clicked
|
||||
- [ ] Disabling a previously enabled community container and saving should remove it from the containers section after stopping and starting containers
|
||||
|
||||
You can now continue with [060-environmental-variables.md](./060-environmental-variables.md)
|
||||
@@ -6,3 +6,9 @@ rules:
|
||||
- build_images.yml
|
||||
artipacked:
|
||||
disable: true
|
||||
secrets-outside-env:
|
||||
ignore:
|
||||
- promote-to-beta.yml
|
||||
- promote-to-latest.yml
|
||||
- publish-to-aws.yml
|
||||
- publish-to-digitalocean.yml
|
||||
|
||||
Reference in New Issue
Block a user