Compare commits

...

96 Commits

Author SHA1 Message Date
Simon L
853a880c9d Merge pull request #286 from nextcloud/enh/noid/reverse-proxy-docs
add reverse proxy docs
2022-03-01 15:12:58 +01:00
Simon L
0ecd2c8f78 Merge pull request #289 from nextcloud/enh/273/lxc-docs
Add docs on backup container inside LXC containers
2022-03-01 15:12:38 +01:00
Simon L
24d1451325 Merge pull request #294 from nextcloud/automated/noid/psalm-baseline-update-1646132431
[Automated] Update psalm-baseline.xml
2022-03-01 15:12:27 +01:00
Simon L
efde2ab41a Merge pull request #295 from nextcloud/enh/noid/increase-version
increase version to v0.6.0
2022-03-01 12:06:26 +01:00
szaimen
a89c183508 increase version to v0.6.0
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-03-01 12:05:54 +01:00
nextcloud-command
301b6e6297 Update psalm baseline
Signed-off-by: GitHub <noreply@github.com>
2022-03-01 11:00:30 +00:00
Simon L
6e839f5baf Merge pull request #293 from nextcloud/enh/noid/fix-some-psalm-issues
fix some psalm issues
2022-03-01 11:57:24 +01:00
szaimen
edb8bd228b fix some psalm issues
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-03-01 11:44:59 +01:00
Simon L
23429f3e59 Merge pull request #291 from nextcloud/enh/265/upgrade-postgres
update postgres to 14.2
2022-03-01 11:20:19 +01:00
Simon L
f4130a8475 Merge pull request #290 from nextcloud/enh/278/delete-backup-archives
add docs on how to delete backup archives manually
2022-03-01 11:10:30 +01:00
szaimen
e5aa3757d5 add docs on how to delete backup archives manually
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-03-01 11:07:38 +01:00
szaimen
12f1549221 update postgres to 14.2
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-03-01 10:16:32 +01:00
szaimen
d34167b30f Add docs on backup container inside LXC containers
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-03-01 09:38:51 +01:00
Simon L
5e0118a3b5 Merge pull request #287 from nextcloud/automated/noid/psalm-baseline-update-1646108969
[Automated] Update psalm-baseline.xml
2022-03-01 09:11:37 +01:00
nextcloud-command
220194b409 Update psalm baseline
Signed-off-by: GitHub <noreply@github.com>
2022-03-01 04:29:29 +00:00
szaimen
2943c6cf08 add reverse proxy docs
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-03-01 00:25:03 +01:00
szaimen
2040553822 fix the access rights
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-28 19:36:19 +01:00
Simon L
d1656a0fcb Merge pull request #70 from nextcloud/enh/noid/allow-reverse-proxies
allow to run this behind a reverse proxy
2022-02-28 18:55:03 +01:00
szaimen
6e9261f306 allow to run this behind a reverse proxy
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-28 18:44:35 +01:00
szaimen
269f62615f update psalm container regularly
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-28 18:13:26 +01:00
szaimen
704c4ad331 fix sarif upload
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-28 17:49:42 +01:00
Simon L
9afec142f3 Merge pull request #285 from nextcloud/automated/noid/psalm-baseline-update-1646065523
[Automated] Update psalm-baseline.xml
2022-02-28 17:45:16 +01:00
nextcloud-command
9fbcaae567 Update psalm baseline
Signed-off-by: GitHub <noreply@github.com>
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-28 17:42:45 +01:00
szaimen
82c371b519 fix the update-baseline-workflow
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-28 17:30:45 +01:00
Simon L
2afc711983 Merge pull request #283 from nextcloud/enh/noid/update-baseline
add workflow that updates psalm baseline regularly
2022-02-28 17:02:52 +01:00
szaimen
a42f21555a add workflow that updates psalm baseline regularly
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-28 17:01:12 +01:00
Simon L
d6ece6cad8 Merge pull request #210 from nextcloud/enh/207/set-up-psalm
set up psalm
2022-02-28 16:58:21 +01:00
szaimen
6f1da5fc5d set up psalm
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-28 16:55:06 +01:00
szaimen
2024cb8f26 add apcu into the psalm container
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-28 15:45:02 +01:00
Simon L
1c01e9e21f Merge pull request #282 from nextcloud/enh/noid/create-psalm-container
create our own psalm container
2022-02-28 15:30:30 +01:00
szaimen
628e55f076 create our own psalm container
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-28 15:27:02 +01:00
Simon L
5b49faf3b7 Merge pull request #274 from nextcloud/aio-dependency-update
Dependency updates
2022-02-28 14:43:12 +01:00
szaimen
33a73a7b95 dependency updates
Signed-off-by: GitHub <noreply@github.com>
2022-02-27 12:15:24 +00:00
szaimen
e2086ada2b make clear that the external storage app is not covered by the built-in backup solution
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-24 01:27:14 +01:00
szaimen
c15bc86e06 make clear that the external mount point will not be covered by the built-in backup solution
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-24 01:10:25 +01:00
Simon L
ccc80c44cc Merge pull request #255 from nextcloud/enh/76/add-docs
add some docs on how to allow the Nextcloud container to access direc…
2022-02-23 19:32:50 +01:00
Simon L
d12df52864 Merge pull request #269 from nextcloud/increase-to-0.5.0
increase version to v0.5.0
2022-02-23 18:48:24 +01:00
szaimen
5ed19687e2 increase version to v0.5.0
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-23 18:47:29 +01:00
Simon L
af93aeebd7 Merge pull request #254 from nextcloud/enh/76/allow-to-define-a-nextcloud-mountpoint
allow nextcloud to access outside directories
2022-02-23 18:11:35 +01:00
Simon L
aa366556f5 Merge pull request #266 from nextcloud/enh/263/move-trusted-proxies
move trusted_proxies to entrypoint
2022-02-23 18:09:42 +01:00
Simon L
a88000095a Merge pull request #253 from nextcloud/enh/244/enforce-startup-order
enforce startup order
2022-02-23 18:09:27 +01:00
Simon L
15e914e3f4 Merge pull request #267 from nextcloud/aio-dependency-update
Dependency updates
2022-02-23 18:08:38 +01:00
Simon L
472334948c Merge pull request #256 from nextcloud/dependabot/docker/Containers/collabora/collabora/code-21.11.2.2.1
Bump collabora/code from 21.11.1.4.1 to 21.11.2.2.1 in /Containers/collabora
2022-02-23 18:08:02 +01:00
Simon L
663901cacd Merge pull request #260 from nextcloud/dependabot/docker/Containers/mastercontainer/php-8.0.16-apache-bullseye
Bump php from 8.0.15-apache-bullseye to 8.0.16-apache-bullseye in /Containers/mastercontainer
2022-02-23 18:07:49 +01:00
Simon L
6f0e4dc175 Merge pull request #261 from nextcloud/dependabot/docker/Containers/nextcloud/php-8.0.16-fpm-alpine3.15
Bump php from 8.0.15-fpm-alpine3.15 to 8.0.16-fpm-alpine3.15 in /Containers/nextcloud
2022-02-23 18:07:35 +01:00
Simon L
b0894992b4 Merge pull request #262 from nextcloud/dependabot/docker/Containers/postgresql/postgres-13.6-alpine3.15
Bump postgres from 13.5-alpine3.15 to 13.6-alpine3.15 in /Containers/postgresql
2022-02-23 18:07:18 +01:00
Simon L
748dcea39e Merge pull request #246 from nextcloud/enh/219/do-not-disconnect-from-network
Do not disconnect containers from network
2022-02-23 18:05:02 +01:00
Simon L
5b278ca261 Merge pull request #268 from nextcloud/fix/241/validate-ip-address
ip-addresses are not supported as domain
2022-02-23 18:04:10 +01:00
szaimen
d988706ae0 ip-addresses are not supported as domain
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-23 18:01:56 +01:00
szaimen
73193ee2d5 dependency updates
Signed-off-by: GitHub <noreply@github.com>
2022-02-23 12:16:38 +00:00
szaimen
e955b0a96f move trusted_proxies to entrypoint
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-22 13:26:48 +01:00
Simon L
11edcfe142 Merge pull request #250 from nextcloud/enh/234/skeleton-dir-docs
add documentation for skeleton directory
2022-02-22 11:30:07 +01:00
szaimen
c779c91ef6 enforce startup order
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-21 20:00:35 +01:00
dependabot[bot]
3b177a5f55 Bump php in /Containers/nextcloud
Bumps php from 8.0.15-fpm-alpine3.15 to 8.0.16-fpm-alpine3.15.

---
updated-dependencies:
- dependency-name: php
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-21 17:59:20 +00:00
dependabot[bot]
72f7106911 Bump php in /Containers/mastercontainer
Bumps php from 8.0.15-apache-bullseye to 8.0.16-apache-bullseye.

---
updated-dependencies:
- dependency-name: php
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-21 17:59:14 +00:00
dependabot[bot]
cbfe9c1907 Bump postgres in /Containers/postgresql
Bumps postgres from 13.5-alpine3.15 to 13.6-alpine3.15.

---
updated-dependencies:
- dependency-name: postgres
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-21 17:54:31 +00:00
szaimen
db12a9a90b ignore major version updates for specific containers
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-21 18:53:51 +01:00
dependabot[bot]
c777971906 Bump collabora/code in /Containers/collabora
Bumps collabora/code from 21.11.1.4.1 to 21.11.2.2.1.

---
updated-dependencies:
- dependency-name: collabora/code
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-21 17:26:52 +00:00
szaimen
0b8caa8cea fix dependabot formatting
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-21 18:26:00 +01:00
szaimen
eafe011ae9 add some docs on how to allow the Nextcloud container to access directories on the host
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-21 18:08:31 +01:00
szaimen
bc50b0cc4f allow nextcloud to access outside directories
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-21 17:31:05 +01:00
Simon L
a2f60ba765 Merge pull request #248 from nextcloud/fix/2200/fix-dependabot
fix dependabot
2022-02-21 15:54:16 +01:00
szaimen
487688d000 add documentation for skeleton directory
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-21 14:33:14 +01:00
szaimen
30e2c6be25 fix typo in readme
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-21 14:18:46 +01:00
szaimen
777666cf11 fix dependabot
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-21 14:09:22 +01:00
szaimen
221ab2515d Do not disconnect containers from network
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-21 14:01:27 +01:00
Simon L
ac3b8bc963 Merge pull request #238 from nextcloud/enh/noid/add-backup-pro-tip
Add instructions how to open the backup archives on the host
2022-02-21 13:32:53 +01:00
szaimen
1df46bb805 Add instructions how to open the backup archives on the host
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-21 13:32:18 +01:00
Simon L
89830a1b81 Merge pull request #237 from nextcloud/fix/235/fix-database-import
fix database import by waiting for the database to start
2022-02-18 11:44:12 +01:00
szaimen
48e60872b3 fix database import by waiting for the database to start
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-18 11:41:52 +01:00
Simon L
9d9da9e47c Merge pull request #230 from nextcloud/enh/noid/update-version
update version to 0.4.0
2022-02-16 16:30:44 +01:00
szaimen
3a9c305758 update version to 0.4.0
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-16 16:29:47 +01:00
szaimen
8f1fcde006 fix selecting a backup container
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-16 16:26:35 +01:00
Simon L
8a6de8f63c Merge pull request #65 from nextcloud/enh/39/allow-to-select-archive
allow to select the archive to restore from
2022-02-16 14:43:10 +01:00
szaimen
0880aff7ea adress review
Signed-off-by: szaimen <szaimen@e.mail.de>
Co-Authored-By: Carl Schwan <carl@carlschwan.eu>
2022-02-16 14:34:21 +01:00
Simon L
2c3db2fd40 Merge pull request #229 from nextcloud/nextcloud-container-update
Nextcloud update
2022-02-16 13:39:37 +01:00
szaimen
e357fc8bb9 nextcloud-update automated change
Signed-off-by: GitHub <noreply@github.com>
2022-02-16 12:33:48 +00:00
Simon L
a82b86b915 Merge pull request #222 from nextcloud/aio-dependency-update
Dependency updates
2022-02-16 13:28:10 +01:00
szaimen
67705134cf dependency updates
Signed-off-by: GitHub <noreply@github.com>
2022-02-16 12:13:04 +00:00
Simon L
ce15c64cd9 Merge pull request #228 from nextcloud/enh/noid/update-nextcloud
update nextcloud to 23.0.2
2022-02-16 12:19:41 +01:00
szaimen
92492affe4 update nextcloud to 23.0.2
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-16 12:18:46 +01:00
szaimen
63e0849215 allow to select the archive to restore from
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-16 12:00:54 +01:00
szaimen
1515d0c210 another attempt to fix the database import
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-15 18:57:39 +01:00
Simon L
4359792a48 Merge pull request #226 from nextcloud/enh/noid/fix-database-import
fix database import
2022-02-15 17:44:36 +01:00
szaimen
3887275808 fix database import
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-15 17:44:00 +01:00
szaimen
badd8d02a9 update to 0.3.1
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-15 12:56:44 +01:00
Simon L
5bc10a56ed Merge pull request #218 from nextcloud/enh/noid/fix-database-connection
fix the database connection
2022-02-15 12:15:39 +01:00
Simon L
222dcd3317 Merge pull request #221 from nextcloud/aio-dependency-update
Dependency updates
2022-02-13 13:43:13 +01:00
szaimen
cec86aa825 dependency updates
Signed-off-by: GitHub <noreply@github.com>
2022-02-13 12:11:36 +00:00
szaimen
e7dfb2514b fix the database connection
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-13 11:44:59 +01:00
szaimen
b0e570176b fix redis build
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-12 14:24:11 +01:00
szaimen
7756826eb3 revert the removal for now since it would break all instances
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-12 01:02:39 +01:00
szaimen
836552e1a7 verbose output
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-12 00:26:12 +01:00
szaimen
6e22b364ae postgresql - delete the datadir once
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-11 23:53:50 +01:00
Simon L
4979d1d90e Merge pull request #214 from nextcloud/enh/131/use-dependabot-to-update-containers
use dependabot to update containers
2022-02-11 18:42:45 +01:00
szaimen
3029b277f1 use dependabot to update containers
Signed-off-by: szaimen <szaimen@e.mail.de>
2022-02-11 15:47:49 +01:00
41 changed files with 895 additions and 150 deletions

105
.github/dependabot.yml vendored
View File

@@ -3,10 +3,107 @@ updates:
- package-ecosystem: composer
directory: "/php/"
schedule:
interval: weekly
day: saturday
time: "03:00"
timezone: Europe/Paris
interval: daily
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/apache"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/borgbackup"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/collabora"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/domaincheck"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/mastercontainer"
schedule:
interval: "daily"
time: "12:00"
ignore:
- dependency-name: "php"
update-types: ["version-update:semver-major", "version-update:semver-minor"]
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/nextcloud"
schedule:
interval: "daily"
time: "12:00"
ignore:
- dependency-name: "php"
update-types: ["version-update:semver-major", "version-update:semver-minor"]
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/postgresql"
schedule:
interval: "daily"
time: "12:00"
ignore:
- dependency-name: "postgres"
update-types: ["version-update:semver-major"]
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/redis"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/talk"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review
- dependencies
- package-ecosystem: "docker"
directory: "/Containers/watchtower"
schedule:
interval: "daily"
time: "12:00"
open-pull-requests-limit: 10
labels:
- 3. to review

View File

@@ -0,0 +1,54 @@
name: Create Psalm Container
on:
workflow_dispatch:
schedule:
- cron: '5 4 * * *'
jobs:
push_to_registry:
runs-on: ubuntu-latest
name: Create Psalm Container
permissions:
packages: write
contents: read
steps:
- name: Check out the repo
run: |
git clone https://github.com/psalm/psalm-github-actions.git
- name: Modify the Dockerfile
run: |
set -x
sed -i 's|FROM php:7.4-alpine|FROM php:8.0-alpine|' "psalm-github-actions/Dockerfile"
cat << APCU >> "psalm-github-actions/Dockerfile"
RUN mkdir -p /usr/src/php/ext/apcu && \
curl -fsSL https://pecl.php.net/get/apcu | tar xvz -C "/usr/src/php/ext/apcu" --strip 1 && \
docker-php-ext-install apcu
APCU
- name: Log in to GitHub Docker Registry
uses: docker/login-action@v1
with:
registry: docker.pkg.github.com
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build container image
uses: docker/build-push-action@v2
with:
push: true
context: 'psalm-github-actions'
file: 'psalm-github-actions/Dockerfile'
tags: |
ghcr.io/nextcloud/all-in-one-psalm:latest

18
.github/workflows/psalm-analysis.yml vendored Normal file
View File

@@ -0,0 +1,18 @@
name: Psalm Analysis
on:
pull_request:
push:
jobs:
psalm:
name: Psalm
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Psalm
uses: docker://ghcr.io/nextcloud/all-in-one-psalm
with:
composer_ignore_platform_reqs: false
relative_dir: php

25
.github/workflows/psalm-security.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
name: Psalm Security Analysis
on:
push:
branches:
- main
jobs:
psalm:
name: Psalm
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Psalm
uses: docker://ghcr.io/nextcloud/all-in-one-psalm
with:
relative_dir: php
security_analysis: true
composer_ignore_platform_reqs: false
report_file: results.sarif
- name: Upload Security Analysis results to GitHub
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: php/results.sarif

View File

@@ -0,0 +1,48 @@
name: Update Psalm baseline
on:
workflow_dispatch:
schedule:
- cron: '5 4 * * *'
jobs:
update-psalm-baseline:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up php8.0
uses: shivammathur/setup-php@v2
with:
php-version: 8.0
extensions: apcu
coverage: none
- name: Run script
run: |
set -x
cd php
composer global require vimeo/psalm --prefer-dist --no-progress --dev
composer install
composer run psalm -- --monochrome --no-progress --output-format=text --update-baseline
git clean -f lib/composer
git checkout composer.json composer.lock lib/composer
continue-on-error: true
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
token: ${{ secrets.COMMAND_BOT_PAT }}
commit-message: Update psalm baseline
committer: GitHub <noreply@github.com>
author: nextcloud-command <nextcloud-command@users.noreply.github.com>
signoff: true
branch: automated/noid/psalm-baseline-update
# Make sure we can open multiple PRs
branch-suffix: timestamp
title: '[Automated] Update psalm-baseline.xml'
body: |
Auto-generated update psalm-baseline.xml with fixed psalm warnings
labels: |
3. to review

View File

@@ -6,7 +6,7 @@
}
}
https://{$NC_DOMAIN}:443 {
{$PROTOCOL}://{$NC_DOMAIN}:{$APACHE_PORT} {
# Notify Push
route /push/* {

View File

@@ -1,4 +1,4 @@
FROM debian:bullseye-slim
FROM debian:bullseye-20220125-slim
EXPOSE 80
@@ -59,7 +59,8 @@ COPY start.sh /usr/bin/
COPY supervisord.conf /
RUN chmod +x /usr/bin/start.sh; \
chmod +r /supervisord.conf; \
chmod +r /Caddyfile;
chmod a+w /Caddyfile; \
chmod a+w /
# Give root a random password
RUN echo "root:$(openssl rand -base64 12)" | chpasswd

View File

@@ -23,6 +23,19 @@ while ! nc -z "$COLLABORA_HOST" 9980; do
sleep 5
done
if [ -z "$APACHE_PORT" ]; then
export APACHE_PORT="443"
fi
if [ "$APACHE_PORT" != '443' ]; then
export PROTOCOL="http"
export NC_DOMAIN=""
sed -i 's|auto_https.*|auto_https off|' /Caddyfile
else
export PROTOCOL="https"
sed -i 's|auto_https.*|auto_https disable_redirects|' /Caddyfile
fi
# Add caddy path
mkdir -p /mnt/data/caddy/

View File

@@ -1,4 +1,4 @@
FROM debian:bullseye-slim
FROM debian:bullseye-20220125-slim
RUN set -ex; \
\

View File

@@ -1,13 +1,9 @@
#!/bin/bash
# Variables
BORG_BACKUP_DIRECTORY="/mnt/borgbackup/borg"
# Functions
get_start_time(){
START_TIME=$(date +%s)
CURRENT_DATE=$(date --date @"$START_TIME" +"%Y%m%d_%H%M%S")
CURRENT_DATE_READABLE=$(date --date @"$START_TIME" +"%d.%m.%Y - %H:%M:%S")
}
get_expiration_time() {
END_TIME=$(date +%s)
@@ -19,11 +15,6 @@ get_expiration_time() {
DURATION_READABLE=$(printf "%02d hours %02d minutes %02d seconds" $DURATION_HOUR $DURATION_MIN $DURATION_SEC)
}
# Export defaults
export BORG_PASSPHRASE="$BORG_PASSWORD"
export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes
export BORG_RELOCATED_REPO_ACCESS_IS_OK=yes
# Test if all volumes aren't empty
VOLUME_DIRS="$(find /nextcloud_aio_volumes -mindepth 1 -maxdepth 1 -type d)"
mapfile -t VOLUME_DIRS <<< "$VOLUME_DIRS"
@@ -150,9 +141,6 @@ if [ "$BORG_MODE" = backup ]; then
# Remove the update skip file because the backup was successful
rm -f "/nextcloud_aio_volumes/nextcloud_aio_nextcloud_data/skip.update"
echo "$CURRENT_DATE,$CURRENT_DATE_READABLE" >> "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list"
chmod +r "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list"
# Prune options
BORG_PRUNE_OPTS=(--stats --progress --keep-within=7d --keep-weekly=4 --keep-monthly=6 "$BORG_BACKUP_DIRECTORY")
@@ -172,17 +160,20 @@ fi
# Do the restore
if [ "$BORG_MODE" = restore ]; then
get_start_time
echo "Restoring the last backup..."
# Perform the restore
FIRST_ARCHIVE="$(borg list "$BORG_BACKUP_DIRECTORY" | grep "nextcloud-aio" | awk -F " " '{print $1}' | sort -r | head -1)"
if [ -n "$SELECTED_RESTORE_TIME" ]; then
SELECTED_ARCHIVE="$(borg list "$BORG_BACKUP_DIRECTORY" | grep "nextcloud-aio" | grep "$SELECTED_RESTORE_TIME" | awk -F " " '{print $1}' | head -1)"
else
SELECTED_ARCHIVE="$(borg list "$BORG_BACKUP_DIRECTORY" | grep "nextcloud-aio" | awk -F " " '{print $1}' | sort -r | head -1)"
fi
echo "Restoring '$SELECTED_ARCHIVE'..."
mkdir -p /tmp/borg
if ! borg mount "$BORG_BACKUP_DIRECTORY::$FIRST_ARCHIVE" /tmp/borg; then
if ! borg mount "$BORG_BACKUP_DIRECTORY::$SELECTED_ARCHIVE" /tmp/borg; then
echo "Could not mount the backup!"
exit 1
fi
if ! rsync --stats --archive --human-readable -vv --delete \
--exclude "nextcloud_aio_mastercontainer/data/backup_archives.list" \
--exclude "nextcloud_aio_mastercontainer/session/"** \
--exclude "nextcloud_aio_mastercontainer/certs/"** \
/tmp/borg/nextcloud_aio_volumes/ /nextcloud_aio_volumes; then

View File

@@ -1,12 +1,18 @@
#!/bin/bash
# Variables
export BORG_BACKUP_DIRECTORY="/mnt/borgbackup/borg"
# Validate BORG_PASSWORD
if [ -z "$BORG_PASSWORD" ]; then
echo "BORG_PASSWORD is not allowed to be empty."
exit 1
fi
export BORG_PASSWORD
# Export defaults
export BORG_PASSPHRASE="$BORG_PASSWORD"
export BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes
export BORG_RELOCATED_REPO_ACCESS_IS_OK=yes
# Validate BORG_MODE
if [ "$BORG_MODE" != backup ] && [ "$BORG_MODE" != restore ] && [ "$BORG_MODE" != check ]; then
@@ -24,6 +30,12 @@ fi
# Remove lockfile
rm -f "/nextcloud_aio_volumes/nextcloud_aio_database_dump/backup-is-running"
# Get a list of all available borg archives
set -x
borg list "$BORG_BACKUP_DIRECTORY" | grep "nextcloud-aio" | awk -F " " '{print $1","$3,$4}' > "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list"
chmod +r "/nextcloud_aio_volumes/nextcloud_aio_mastercontainer/data/backup_archives.list"
set +x
if [ -n "$FAILED" ]; then
if [ "$BORG_MODE" = backup ]; then
# Add file to Nextcloud container so that it skips any update the next time

View File

@@ -1,2 +1,2 @@
# From a file located probably somewhere here: https://github.com/CollaboraOnline/online/tree/master/docker
FROM collabora/code:latest
FROM collabora/code:21.11.2.2.1

View File

@@ -1,4 +1,4 @@
FROM alpine
FROM alpine:3.15.0
RUN apk add --update --no-cache lighttpd bash
RUN adduser -S www-data -G www-data

View File

@@ -1,6 +1,6 @@
server.document-root = "/var/www/domaincheck/"
server.port = 443
server.port = env.APACHE_PORT
server.username = "www-data"
server.groupname = "www-data"

View File

@@ -7,6 +7,10 @@ fi
echo "$INSTANCE_ID" > /var/www/domaincheck/index.html
if [ -z "$APACHE_PORT" ]; then
export APACHE_PORT="443"
fi
# Check config file
lighttpd -tt -f /etc/lighttpd/lighttpd.conf

View File

@@ -1,5 +1,8 @@
# Docker CLI is a requirement
FROM docker:20.10.12-dind-alpine3.15 as dind
# From https://github.com/docker-library/php/blob/master/8.0/bullseye/apache/Dockerfile
FROM php:8.0-apache-bullseye
FROM php:8.0.16-apache-bullseye
EXPOSE 80
EXPOSE 8080
@@ -28,7 +31,7 @@ RUN set -ex; \
&& chmod +x /usr/bin/caddy \
&& /usr/bin/caddy version
COPY --from=docker:dind /usr/local/bin/docker /usr/local/bin/
COPY --from=dind /usr/local/bin/docker /usr/local/bin/
RUN chmod +x /usr/local/bin/docker
RUN mkdir -p /usr/src/php/ext/apcu && \

View File

@@ -6,6 +6,14 @@ print_green() {
printf "%b%s%b\n" "\e[0;92m" "$TEXT" "\e[0m"
}
# Function to check if number was provided
check_if_number() {
case "${1}" in
''|*[!0-9]*) return 1 ;;
*) return 0 ;;
esac
}
# Check if socket is available and readable
if ! [ -a "/var/run/docker.sock" ]; then
echo "Docker socket is not available. Cannot continue."
@@ -54,6 +62,30 @@ else
sleep 10
fi
# Check for other options
if [ -n "$NEXTCLOUD_MOUNT" ]; then
if ! echo "$NEXTCLOUD_MOUNT" | grep -q "^/mnt/" \
&& ! echo "$NEXTCLOUD_MOUNT" | grep -q "^/media/" \
&& ! echo "$NEXTCLOUD_MOUNT" | grep -q "^/var/backups$"
then
echo "You've set NEXCLOUD_MOUNT but not to an allowed value.
The string must be equal to/start with '/mnt/' or '/media/' or be equal to '/var/backups'."
exit 1
elif [ "$NEXTCLOUD_MOUNT" = "/mnt/ncdata" ] || echo "$NEXTCLOUD_MOUNT" | grep -q "^/mnt/ncdata/"; then
echo "/mnt/ncdata and /mnt/ncdata/ are not allowed for NEXTCLOUD_MOUNT."
exit 1
fi
fi
if [ -n "$APACHE_PORT" ]; then
if ! check_if_number "$APACHE_PORT"; then
echo "You provided an Apache port but did not only use numbers"
exit 1
elif ! [ "$APACHE_PORT" -le 65535 ] || ! [ "$APACHE_PORT" -ge 1 ]; then
echo "The provided Apache port is invalid. It must be between 1 and 65535"
exit 1
fi
fi
# Add important folders
mkdir -p /mnt/docker-aio-config/data/
mkdir -p /mnt/docker-aio-config/session/

View File

@@ -1,5 +1,5 @@
# From https://github.com/nextcloud/docker/blob/master/23/fpm-alpine/Dockerfile
FROM php:8.0-fpm-alpine
FROM php:8.0.16-fpm-alpine3.15
# Custom: change id of www-data user as it needs to be the same like on old installations
RUN set -ex; \
@@ -62,7 +62,7 @@ RUN set -ex; \
# pecl will claim success even if one install fails, so we need to perform each install separately
pecl install APCu-5.1.21; \
pecl install memcached-3.1.5; \
pecl install redis-5.3.6; \
pecl install redis-5.3.7; \
pecl install imagick-3.7.0; \
\
docker-php-ext-enable \
@@ -105,7 +105,7 @@ RUN { \
VOLUME /var/www/html
ENV NEXTCLOUD_VERSION 23.0.1
ENV NEXTCLOUD_VERSION 23.0.2
RUN set -ex; \
apk add --no-cache --virtual .fetch-deps \

View File

@@ -18,8 +18,3 @@ $overwriteCondAddr = getenv('OVERWRITECONDADDR');
if ($overwriteCondAddr) {
$CONFIG['overwritecondaddr'] = $overwriteCondAddr;
}
$trustedProxies = getenv('TRUSTED_PROXIES');
if ($trustedProxies) {
$CONFIG['trusted_proxies'] = array_filter(array_map('trim', explode(' ', $trustedProxies)));
}

View File

@@ -250,6 +250,7 @@ elif [ "$(php /var/www/html/occ config:app:get notify_push enabled)" = "no" ]; t
else
php /var/www/html/occ app:update notify_push
fi
php /var/www/html/occ config:system:set trusted_proxies 0 --value="127.0.0.1"
php /var/www/html/occ config:app:set notify_push base_endpoint --value="https://$NC_DOMAIN/push"
# Collabora

View File

@@ -6,6 +6,16 @@ while ! nc -z "$POSTGRES_HOST" 5432; do
sleep 5
done
# Use the correct Postgres username
POSTGRES_USER="oc_$POSTGRES_USER"
export POSTGRES_USER
# Fix false database connection on old instances
if [ -f "/var/www/html/config/config.php" ] && sleep 2 && psql -d "postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:5432/$POSTGRES_DB" -c "select now()"; then
sed -i "s|'dbuser'.*=>.*$|'dbuser' => '$POSTGRES_USER',|" /var/www/html/config/config.php
sed -i "s|'dbpassword'.*=>.*$|'dbpassword' => '$POSTGRES_PASSWORD',|" /var/www/html/config/config.php
fi
# Run original entrypoint
if ! bash /entrypoint.sh; then
exit 1

View File

@@ -1,7 +1,7 @@
# From https://github.com/docker-library/postgres/blob/master/13/alpine/Dockerfile
FROM postgres:13-alpine
FROM postgres:14.2-alpine3.15
RUN apk add --update --no-cache bash openssl shadow
RUN apk add --update --no-cache bash openssl shadow netcat-openbsd
# We need to use the same gid and uid as on old installations
RUN set -ex; \
@@ -17,7 +17,9 @@ RUN set -ex; \
chown -R postgres:postgres "$PGDATA"
COPY start.sh /usr/bin/
RUN chmod +x /usr/bin/start.sh
COPY init-user-db.sh /docker-entrypoint-initdb.d/
RUN chmod +x /usr/bin/start.sh; \
chmod +xr /docker-entrypoint-initdb.d/init-user-db.sh
RUN mkdir /mnt/data; \
chown postgres:postgres /mnt/data;

View File

@@ -0,0 +1,9 @@
#!/bin/bash
set -ex
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
CREATE USER "oc_$POSTGRES_USER" WITH PASSWORD '$POSTGRES_PASSWORD' CREATEDB;
ALTER DATABASE "$POSTGRES_DB" OWNER TO "oc_$POSTGRES_USER";
EOSQL
set +ex

View File

@@ -18,10 +18,18 @@ if ! [ -w "$DUMP_DIR" ]; then
exit 1
fi
# Delete the datadir once (needed for setting the correct credentials on old instances once)
if ! [ -f "$DUMP_DIR/export.failed" ] && ! [ -f "$DUMP_DIR/initial-cleanup-done" ]; then
set -ex
rm -rf "${DATADIR:?}/"*
touch "$DUMP_DIR/initial-cleanup-done"
set +ex
fi
# Test if some things match
# shellcheck disable=SC2235
if ( [ -f "$DATADIR/PG_VERSION" ] && [ "$PG_MAJOR" != "$(cat "$DATADIR/PG_VERSION")" ] ) \
|| ( ! [ -f "$DATADIR/PG_VERSION" ] && [ -f "$DUMP_FILE" ] ); then
|| ( ! [ -f "$DATADIR/PG_VERSION" ] && ( [ -f "$DUMP_FILE" ] || [ -f "$DUMP_DIR/export.failed" ] ) ); then
# The DUMP_file must be provided
if ! [ -f "$DUMP_FILE" ]; then
echo "Unable to restore the database because the database dump is missing."
@@ -39,7 +47,7 @@ if ( [ -f "$DATADIR/PG_VERSION" ] && [ "$PG_MAJOR" != "$(cat "$DATADIR/PG_VERSIO
echo "Restoring from database dump."
# Exit if any command fails
set -e
set -ex
# Remove old database files
rm -rf "${DATADIR:?}/"*
@@ -50,13 +58,33 @@ if ( [ -f "$DATADIR/PG_VERSION" ] && [ "$PG_MAJOR" != "$(cat "$DATADIR/PG_VERSIO
# Create new database
exec docker-entrypoint.sh postgres &
# Wait 2s for creation
sleep 2s
# Wait for creation
while ! nc -z localhost 11000; do
echo "Waiting for the database to start."
sleep 5
done
# Set correct permissions
if grep -q "Owner: oc_admin" "$DUMP_FILE" && ! grep -q "Owner: oc_$POSTGRES_USER" "$DUMP_FILE"; then
OC_ADMIN_EXISTS=1
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
CREATE USER oc_admin WITH PASSWORD '$POSTGRES_PASSWORD' CREATEDB;
ALTER DATABASE "$POSTGRES_DB" OWNER TO oc_admin;
EOSQL
fi
# Restore database
echo "Restoring the database from database dump"
psql "$POSTGRES_DB" -U "$POSTGRES_USER" < "$DUMP_FILE"
# Correct permissions
if [ -n "$OC_ADMIN_EXISTS" ]; then
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
ALTER DATABASE "$POSTGRES_DB" OWNER TO "oc_$POSTGRES_USER";
REASSIGN OWNED BY oc_admin TO "oc_$POSTGRES_USER";
EOSQL
fi
# Shut down the database to be able to start it again
pg_ctl stop -m fast
@@ -64,7 +92,7 @@ if ( [ -f "$DATADIR/PG_VERSION" ] && [ "$PG_MAJOR" != "$(cat "$DATADIR/PG_VERSIO
export PGPORT=5432
# Don't exit if command fails anymore
set +e
set +ex
fi
# Cover the last case

View File

@@ -1,5 +1,5 @@
# From https://github.com/docker-library/redis/blob/master/6.2/alpine/Dockerfile
FROM redis:6.2-alpine
FROM redis:6.2.6-alpine3.15
RUN apk add --update --no-cache openssl bash

View File

@@ -1,4 +1,4 @@
FROM ubuntu:focal
FROM ubuntu:focal-20220113
EXPOSE 3478

View File

@@ -1,7 +1,7 @@
# From https://github.com/containrrr/watchtower/blob/main/dockerfiles/Dockerfile.self-contained
FROM containrrr/watchtower:latest as watchtower
FROM containrrr/watchtower:1.4.0 as watchtower
FROM alpine:latest
FROM alpine:3.15.0
RUN apk add --update --no-cache bash
COPY --from=watchtower /watchtower /

View File

@@ -17,5 +17,9 @@
"slim/twig-view": "^3.2",
"slim/csrf": "^1.2",
"ext-apcu": "*"
}
},
"scripts": {
"psalm": "psalm --threads=1",
"psalm:update-baseline": "psalm --threads=1 --update-baseline"
}
}

48
php/composer.lock generated
View File

@@ -50,12 +50,12 @@
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\": "src/"
},
"files": [
"src/functions_include.php"
]
],
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -157,12 +157,12 @@
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
},
"files": [
"src/functions_include.php"
]
],
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -465,12 +465,12 @@
}
},
"autoload": {
"psr-4": {
"Opis\\Closure\\": "src/"
},
"files": [
"functions.php"
]
],
"psr-4": {
"Opis\\Closure\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -595,12 +595,12 @@
},
"type": "library",
"autoload": {
"psr-4": {
"DI\\": "src/"
},
"files": [
"src/functions.php"
]
],
"psr-4": {
"DI\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -1469,12 +1469,12 @@
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
},
"files": [
"bootstrap.php"
]
],
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -1551,12 +1551,12 @@
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
},
"files": [
"bootstrap.php"
]
],
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [

View File

@@ -10,17 +10,18 @@
"displayName": "Apache",
"containerName": "nextcloud/aio-apache",
"ports": [
"443/tcp"
"%APACHE_PORT%/tcp"
],
"internalPorts": [
"443"
"%APACHE_PORT%"
],
"secrets": [],
"environmentVariables": [
"NC_DOMAIN=%NC_DOMAIN%",
"NEXTCLOUD_HOST=nextcloud-aio-nextcloud",
"COLLABORA_HOST=nextcloud-aio-collabora",
"TALK_HOST=nextcloud-aio-talk"
"TALK_HOST=nextcloud-aio-talk",
"APACHE_PORT=%APACHE_PORT%"
],
"volumes": [
{
@@ -98,6 +99,11 @@
"name": "nextcloud_aio_nextcloud_data",
"location": "/mnt/ncdata",
"writeable": true
},
{
"name": "%NEXTCLOUD_MOUNT%",
"location": "%NEXTCLOUD_MOUNT%",
"writeable": true
}
],
"environmentVariables": [
@@ -114,7 +120,6 @@
"NEXTCLOUD_DATA_DIR=/mnt/ncdata",
"OVERWRITEHOST=%NC_DOMAIN%",
"OVERWRITEPROTOCOL=https",
"TRUSTED_PROXIES=127.0.0.1",
"TURN_SECRET=%TURN_SECRET%",
"SIGNALING_SECRET=%SIGNALING_SECRET%",
"AIO_URL=%AIO_URL%"
@@ -194,7 +199,8 @@
"internalPorts": [],
"environmentVariables": [
"BORG_PASSWORD=%BORGBACKUP_PASSWORD%",
"BORG_MODE=%BORGBACKUP_MODE%"
"BORG_MODE=%BORGBACKUP_MODE%",
"SELECTED_RESTORE_TIME=%SELECTED_RESTORE_TIME%"
],
"volumes": [
{
@@ -271,11 +277,12 @@
"displayName": "Domaincheck",
"containerName": "nextcloud/aio-domaincheck",
"ports": [
"443/tcp"
"%APACHE_PORT%/tcp"
],
"internalPorts": [],
"environmentVariables": [
"INSTANCE_ID=%INSTANCE_ID%"
"INSTANCE_ID=%INSTANCE_ID%",
"APACHE_PORT=%APACHE_PORT%"
],
"volumes": [],
"secrets": [

113
php/psalm-baseline.xml Normal file
View File

@@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="4.22.0@fc2c6ab4d5fa5d644d8617089f012f3bb84b8703">
<file src="public/index.php">
<MissingClosureParamType occurrences="10">
<code>$args</code>
<code>$args</code>
<code>$args</code>
<code>$args</code>
<code>$request</code>
<code>$request</code>
<code>$request</code>
<code>$response</code>
<code>$response</code>
<code>$response</code>
</MissingClosureParamType>
</file>
<file src="src/Controller/ConfigurationController.php">
<MissingParamType occurrences="1">
<code>$args</code>
</MissingParamType>
<PossiblyInvalidArrayAccess occurrences="2">
<code>$request-&gt;getParsedBody()['borg_backup_host_location']</code>
<code>$request-&gt;getParsedBody()['domain']</code>
</PossiblyInvalidArrayAccess>
<PossiblyNullArgument occurrences="2">
<code>$request-&gt;getParsedBody()['borg_backup_host_location']</code>
<code>$request-&gt;getParsedBody()['domain']</code>
</PossiblyNullArgument>
<PossiblyNullArrayAccess occurrences="2">
<code>$request-&gt;getParsedBody()['borg_backup_host_location']</code>
<code>$request-&gt;getParsedBody()['domain']</code>
</PossiblyNullArrayAccess>
</file>
<file src="src/Controller/DockerController.php">
<MissingParamType occurrences="7">
<code>$args</code>
<code>$args</code>
<code>$args</code>
<code>$args</code>
<code>$args</code>
<code>$args</code>
<code>$args</code>
</MissingParamType>
<PossiblyInvalidArrayAccess occurrences="1">
<code>$request-&gt;getParsedBody()['selected_restore_time']</code>
</PossiblyInvalidArrayAccess>
<PossiblyNullArgument occurrences="1">
<code>$container</code>
</PossiblyNullArgument>
<PossiblyNullArrayAccess occurrences="1">
<code>$request-&gt;getParsedBody()['selected_restore_time']</code>
</PossiblyNullArrayAccess>
<PossiblyNullReference occurrences="5">
<code>GetDependsOn</code>
<code>GetDependsOn</code>
<code>GetIdentifier</code>
<code>GetIdentifier</code>
<code>GetRunningState</code>
</PossiblyNullReference>
</file>
<file src="src/Controller/LoginController.php">
<MissingParamType occurrences="3">
<code>$args</code>
<code>$args</code>
<code>$args</code>
</MissingParamType>
<PossiblyInvalidArrayAccess occurrences="1">
<code>$request-&gt;getParsedBody()['password']</code>
</PossiblyInvalidArrayAccess>
<PossiblyNullArgument occurrences="1">
<code>$password</code>
</PossiblyNullArgument>
<PossiblyNullArrayAccess occurrences="1">
<code>$request-&gt;getParsedBody()['password']</code>
</PossiblyNullArrayAccess>
</file>
<file src="src/Cron/cron.php">
<PossiblyNullArgument occurrences="2">
<code>$nextcloudContainer</code>
<code>$nextcloudContainer</code>
</PossiblyNullArgument>
</file>
<file src="src/Docker/DockerActionManager.php">
<InvalidReturnType occurrences="1">
<code>IContainerState</code>
</InvalidReturnType>
<InvalidScalarArgument occurrences="1">
<code>$internalPort</code>
</InvalidScalarArgument>
<PossiblyFalseOperand occurrences="1">
<code>strpos($fullDigest, "@")</code>
</PossiblyFalseOperand>
<PossiblyNullArgument occurrences="1">
<code>$apacheContainer</code>
</PossiblyNullArgument>
<PossiblyNullReference occurrences="1">
<code>GetUpdateState</code>
</PossiblyNullReference>
<RedundantCondition occurrences="1">
<code>$container-&gt;GetInternalPorts() !== null</code>
</RedundantCondition>
</file>
<file src="src/Middleware/AuthMiddleware.php">
<UndefinedInterfaceMethod occurrences="1">
<code>withStatus</code>
</UndefinedInterfaceMethod>
</file>
<file src="src/Twig/ClassExtension.php">
<MissingParamType occurrences="1">
<code>$object</code>
</MissingParamType>
</file>
</files>

15
php/psalm.xml Normal file
View File

@@ -0,0 +1,15 @@
<?xml version="1.0"?>
<psalm
errorLevel="2"
resolveFromConfigFile="true"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config"
errorBaseline="psalm-baseline.xml"
>
<projectFiles>
<directory name="templates"/>
<directory name="src"/>
<file name="public/index.php"/>
</projectFiles>
</psalm>

View File

@@ -87,6 +87,7 @@ $app->get('/containers', function ($request, $response, $args) use ($container)
'was_start_button_clicked' => $configurationManager->wasStartButtonClicked(),
'has_update_available' => $dockerActionManger->isAnyUpdateAvailable(),
'last_backup_time' => $configurationManager->GetLastBackupTime(),
'backup_times' => $configurationManager->GetBackupTimes(),
]);
})->setName('profile');
$app->get('/login', function ($request, $response, $args) use ($container) {

View File

@@ -6,7 +6,7 @@ class ContainerVolumes {
/** @var ContainerVolume[] */
private array $volumes = [];
public function AddVolume(ContainerVolume $volume) {
public function AddVolume(ContainerVolume $volume) : void {
$this->volumes[] = $volume;
}

View File

@@ -51,11 +51,17 @@ class ContainerDefinitionFetcher
foreach ($data['production'] as $entry) {
$ports = new ContainerPorts();
foreach ($entry['ports'] as $port) {
if($port === '%APACHE_PORT%/tcp') {
$port = $this->configurationManager->GetApachePort() . '/tcp';
}
$ports->AddPort($port);
}
$internalPorts = new ContainerInternalPorts();
foreach ($entry['internalPorts'] as $internalPort) {
if($internalPort === '%APACHE_PORT%') {
$internalPort = $this->configurationManager->GetApachePort();
}
$internalPorts->AddInternalPort($internalPort);
}
@@ -67,6 +73,18 @@ class ContainerDefinitionFetcher
continue;
}
}
if($value['name'] === '%NEXTCLOUD_MOUNT%') {
$value['name'] = $this->configurationManager->GetNextcloudMount();
if($value['name'] === '') {
continue;
}
}
if($value['location'] === '%NEXTCLOUD_MOUNT%') {
$value['location'] = $this->configurationManager->GetNextcloudMount();
if($value['location'] === '') {
continue;
}
}
$volumes->AddVolume(
new ContainerVolume(
$value['name'],

View File

@@ -26,7 +26,7 @@ class DockerController
$this->configurationManager = $configurationManager;
}
private function PerformRecursiveContainerStart(string $id) {
private function PerformRecursiveContainerStart(string $id) : void {
$container = $this->containerDefinitionFetcher->GetContainerById($id);
foreach($container->GetDependsOn() as $dependency) {
@@ -83,6 +83,7 @@ class DockerController
public function StartBackupContainerRestore(Request $request, Response $response, $args) : Response {
$config = $this->configurationManager->GetConfig();
$config['backup-mode'] = 'restore';
$config['selected-restore-time'] = $request->getParsedBody()['selected_restore_time'];
$this->configurationManager->WriteConfig($config);
$id = self::TOP_CONTAINER;
@@ -125,14 +126,15 @@ class DockerController
return $response->withStatus(201)->withHeader('Location', '/');
}
private function PerformRecursiveContainerStop(string $id)
private function PerformRecursiveContainerStop(string $id) : void
{
$container = $this->containerDefinitionFetcher->GetContainerById($id);
foreach($container->GetDependsOn() as $dependency) {
$this->PerformRecursiveContainerStop($dependency);
}
$this->dockerActionManager->DisconnectContainerFromNetwork($container);
// Disconnecting is not needed. This also allows to start the containers manually via docker-cli
//$this->dockerActionManager->DisconnectContainerFromNetwork($container);
$this->dockerActionManager->StopContainer($container);
}
@@ -144,7 +146,7 @@ class DockerController
return $response->withStatus(201)->withHeader('Location', '/');
}
public function StartDomaincheckContainer()
public function StartDomaincheckContainer() : void
{
# Don't start if domain is already set
if ($this->configurationManager->GetDomain() != '') {
@@ -165,7 +167,7 @@ class DockerController
$this->PerformRecursiveContainerStart($id);
}
private function StopDomaincheckContainer()
private function StopDomaincheckContainer() : void
{
$id = 'nextcloud-aio-domaincheck';
$this->PerformRecursiveContainerStop($id);

View File

@@ -46,7 +46,7 @@ class ConfigurationManager
return $config['secrets'][$secretId];
}
private function DoubleSafeBackupSecret(string $borgBackupPassword) {
private function DoubleSafeBackupSecret(string $borgBackupPassword) : void {
file_put_contents(DataConst::GetBackupSecretFile(), $borgBackupPassword);
}
@@ -64,7 +64,7 @@ class ConfigurationManager
}
$content = file_get_contents(DataConst::GetBackupArchivesList());
if ($content === "") {
if ($content === '') {
return '';
}
@@ -83,6 +83,28 @@ class ConfigurationManager
return $lastBackupTime;
}
public function GetBackupTimes() : array {
if (!file_exists(DataConst::GetBackupArchivesList())) {
return [];
}
$content = file_get_contents(DataConst::GetBackupArchivesList());
if ($content === '') {
return [];
}
$backupLines = explode("\n", $content);
$backupTimes = [];
foreach($backupLines as $lines) {
if ($lines !== "") {
$backupTimesTemp = explode(',', $lines);
$backupTimes[] = $backupTimesTemp[1];
}
}
return $backupTimes;
}
public function wasStartButtonClicked() : bool {
if (isset($this->GetConfig()['wasStartButtonClicked'])) {
return true;
@@ -100,6 +122,11 @@ class ConfigurationManager
throw new InvalidSettingConfigurationException("Domain is not in a valid format!");
}
// Validate that it is not an IP-address
if(filter_var($domain, FILTER_VALIDATE_IP)) {
throw new InvalidSettingConfigurationException("Please enter a domain and not an IP-address!");
}
$dnsRecordIP = gethostbyname($domain);
// Validate IP
@@ -117,10 +144,18 @@ class ConfigurationManager
// Get Instance ID
$instanceID = $this->GetSecret('INSTANCE_ID');
// set protocol
$port = $this->GetApachePort();
if ($port !== '443') {
$protocol = 'https://';
} else {
$protocol = 'http://';
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,'http://' . $domain . ':443');
curl_setopt($ch, CURLOPT_URL, $protocol . $domain . ':443');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$response = (string)curl_exec($ch);
# Get rid of trailing \n
$response = str_replace("\n", "", $response);
@@ -152,6 +187,15 @@ class ConfigurationManager
return $config['backup-mode'];
}
public function GetSelectedRestoreTime() : string {
$config = $this->GetConfig();
if(!isset($config['selected-restore-time'])) {
$config['selected-restore-time'] = '';
}
return $config['selected-restore-time'];
}
public function GetAIOURL() : string {
$config = $this->GetConfig();
if(!isset($config['AIO_URL'])) {
@@ -192,6 +236,29 @@ class ConfigurationManager
$this->WriteConfig($config);
}
public function GetApachePort() : string {
$port = getenv('APACHE_PORT');
if ($port === false) {
$config = $this->GetConfig();
if (!isset($config['apache_port']) || $config['apache_port'] === '') {
$config['apache_port'] = '443';
}
return $config['apache_port'];
} else {
if(file_exists(DataConst::GetConfigFile())) {
$config = $this->GetConfig();
if (!isset($config['apache_port'])) {
$config['apache_port'] = '';
}
if ($port !== $config['apache_port']) {
$config['apache_port'] = $port;
$this->WriteConfig($config);
}
}
return $port;
}
}
/**
* @throws InvalidSettingConfigurationException
*/
@@ -219,4 +286,27 @@ class ConfigurationManager
return $config['backup-mode'];
}
public function GetNextcloudMount() : string {
$mount = getenv('NEXTCLOUD_MOUNT');
if ($mount === false) {
$config = $this->GetConfig();
if (!isset($config['nextcloud_mount'])) {
$config['nextcloud_mount'] = '';
}
return $config['nextcloud_mount'];
} else {
if(file_exists(DataConst::GetConfigFile())) {
$config = $this->GetConfig();
if (!isset($config['nextcloud_mount'])) {
$config['nextcloud_mount'] = '';
}
if ($mount !== $config['nextcloud_mount']) {
$config['nextcloud_mount'] = $mount;
$this->WriteConfig($config);
}
}
return $mount;
}
}
}

View File

@@ -109,7 +109,7 @@ class DockerActionManager
}
}
public function DeleteContainer(Container $container) {
public function DeleteContainer(Container $container) : void {
$url = $this->BuildApiUrl(sprintf('containers/%s?v=true', urlencode($container->GetIdentifier())));
try {
$this->guzzleClient->delete($url);
@@ -142,12 +142,12 @@ class DockerActionManager
return $response;
}
public function StartContainer(Container $container) {
public function StartContainer(Container $container) : void {
$url = $this->BuildApiUrl(sprintf('containers/%s/start', urlencode($container->GetIdentifier())));
$this->guzzleClient->post($url);
}
public function CreateVolumes(Container $container)
public function CreateVolumes(Container $container): void
{
$url = $this->BuildApiUrl('volumes/create');
foreach($container->GetVolumes()->GetVolumes() as $volume) {
@@ -170,7 +170,7 @@ class DockerActionManager
}
}
public function CreateContainer(Container $container) {
public function CreateContainer(Container $container) : void {
$volumes = [];
foreach($container->GetVolumes()->GetVolumes() as $volume) {
$volumeEntry = $volume->name . ':' . $volume->mountPoint;
@@ -212,6 +212,10 @@ class DockerActionManager
$replacements[1] = $this->configurationManager->GetBackupMode();
} elseif ($out[1] === 'AIO_URL') {
$replacements[1] = $this->configurationManager->GetAIOURL();
} elseif ($out[1] === 'SELECTED_RESTORE_TIME') {
$replacements[1] = $this->configurationManager->GetSelectedRestoreTime();
} elseif ($out[1] === 'APACHE_PORT') {
$replacements[1] = $this->configurationManager->GetApachePort();
} else {
$replacements[1] = $this->configurationManager->GetSecret($out[1]);
}
@@ -255,7 +259,7 @@ class DockerActionManager
);
}
public function PullContainer(Container $container)
public function PullContainer(Container $container) : void
{
$url = $this->BuildApiUrl(sprintf('images/create?fromImage=%s', urlencode($this->BuildImageName($container))));
try {
@@ -279,10 +283,9 @@ class DockerActionManager
return $updateAvailable;
}
public function isAnyUpdateAvailable() {
public function isAnyUpdateAvailable() : bool {
$id = 'nextcloud-aio-apache';
if ($this->isContainerUpdateAvailable($id) !== "") {
return true;
} else {
@@ -350,7 +353,7 @@ class DockerActionManager
}
}
public function sendNotification(Container $container, string $subject, string $message)
public function sendNotification(Container $container, string $subject, string $message) : void
{
if ($this->GetContainerStartingState($container) instanceof RunningState) {
@@ -396,7 +399,7 @@ class DockerActionManager
}
}
public function DisconnectContainerFromNetwork(Container $container)
public function DisconnectContainerFromNetwork(Container $container) : void
{
$url = $this->BuildApiUrl(
@@ -417,7 +420,7 @@ class DockerActionManager
}
}
private function ConnectContainerIdToNetwork(string $id)
private function ConnectContainerIdToNetwork(string $id) : void
{
$url = $this->BuildApiUrl('networks/create');
try {
@@ -460,17 +463,17 @@ class DockerActionManager
}
}
public function ConnectMasterContainerToNetwork()
public function ConnectMasterContainerToNetwork() : void
{
$this->ConnectContainerIdToNetwork('nextcloud-aio-mastercontainer');
}
public function ConnectContainerToNetwork(Container $container)
public function ConnectContainerToNetwork(Container $container) : void
{
$this->ConnectContainerIdToNetwork($container->GetIdentifier());
}
public function StopContainer(Container $container) {
public function StopContainer(Container $container) : void {
$url = $this->BuildApiUrl(sprintf('containers/%s/stop?t=%s', urlencode($container->GetIdentifier()), $container->GetMaxShutdownTime()));
try {
$this->guzzleClient->post($url);

View File

@@ -16,7 +16,7 @@
</header>
<div class="content">
<h1>Nextcloud AIO Beta v0.3.0</h1>
<h1>Nextcloud AIO Beta v0.6.0</h1>
This is beta software and not production ready.<br><br>
{% set isAnyRunning = false %}
@@ -48,19 +48,29 @@
{% endfor %}
{% if isWatchtowerRunning == true %}
Mastercontainer updpate currently running. It will restart the mastercontainer soon which will make it unavailable for a moment. Please wait until thats done.<br /><br />
Mastercontainer update currently running. It will restart the mastercontainer soon which will make it unavailable for a moment. Please wait until that's done.<br /><br />
<a href="" class="button reload">Reload ↻</a><br/>
{% else %}
{% if isBackupOrRestoreRunning == false and domain == "" %}
Please type in the domain that will be used for Nextcloud:<br><br />
<form method="POST" action="/api/configuration" class="xhr">
<input type="text" name="domain" value="{{ domain }}" placeholder="nextcloud.yourdomain.com"/>
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input class="button" type="submit" value="Submit" />
</form>
Make sure that this server is reachable on Port 443 and you've correctly set up the DNS config for the domain that you enter. <br><br>
If you have a dynamic IP-address, you can use e.g. <a href="https://ddclient.net/">DDclient</a> with a compatible domain provider for DNS updates.
{% if is_mastercontainer_update_available == true %}
<h2>Mastercontainer update</h2>
⚠ A mastercontainer update is available. Please click on the button below to update it. Afterwards, you will be able to proceed with the setup.<br><br>
<form method="POST" action="/api/docker/watchtower" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input class="button" type="submit" value="Update mastercontainer" />
</form>
{% else %}
Please type in the domain that will be used for Nextcloud:<br><br />
<form method="POST" action="/api/configuration" class="xhr">
<input type="text" name="domain" value="{{ domain }}" placeholder="nextcloud.yourdomain.com"/>
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input class="button" type="submit" value="Submit" />
</form>
Make sure that this server is reachable on Port 443 and you've correctly set up the DNS config for the domain that you enter. <br><br>
If you have a dynamic IP-address, you can use e.g. <a href="https://ddclient.net/">DDclient</a> with a compatible domain provider for DNS updates.
{% endif %}
{% endif %}
{% if domain != "" %}
@@ -99,18 +109,21 @@
</ul>
{% if has_update_available == true %}
⚠ Container updates are available. Click on `Stop Containers` and `Start Containers` to update them. You should consider creating a backup first. The mastercontainer gets updated with a different procedure though and has its own update button which is visible if an update is available.<br><br>
{% if is_mastercontainer_update_available == false %}
⚠ Container updates are available. Click on `Stop Containers` and `Start Containers` to update them. You should consider creating a backup first.<br><br>
{% endif %}
{% else %}
{% if is_mastercontainer_update_available == false %}
Your containers are up-to-date.<br><br>
{% else %}
Your containers are up-to-date. (Except the mastercontainer. See the section below.)<br><br>
{% endif %}
{% endif %}
{% endif %}
{% if isAnyRunning == true %}
{% if isApacheStarting != true %}
{% if is_mastercontainer_update_available == true %}
⚠ A mastercontainer update is available. Please click on the button below to stop your containers in order to be able to update the mastercontainer.<br /><br />
{% endif %}
<form method="POST" action="/api/docker/stop" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
@@ -126,18 +139,22 @@
{% if was_start_button_clicked == false %}
Clicking on the button below will download all docker containers and start them. This can take a lot of time depending on your internect connection. Since the overall size is a few GB, this will take around 5-10 min or more. So be aware and patient!<br><br>
{% endif %}
{% if was_start_button_clicked == false or has_update_available == false %}
<form method="POST" action="/api/docker/start" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input class="button" type="submit" value="Start containers" />
</form>
{% if is_mastercontainer_update_available == true %}
⚠ Please update your mastercontainer. Afterwards, you will be able to start your containers again.<br><br>
{% else %}
<form method="POST" action="/api/docker/start" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input class="button " type="submit" value="Start and update containers" onclick="return confirm('Start and update containers? You should consider creating a backup first.')" />
</form>
{% if was_start_button_clicked == false or has_update_available == false %}
<form method="POST" action="/api/docker/start" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input class="button" type="submit" value="Start containers" />
</form>
{% else %}
<form method="POST" action="/api/docker/start" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input class="button " type="submit" value="Start and update containers" onclick="return confirm('Start and update containers? You should consider creating a backup first.')" />
</form>
{% endif %}
{% endif %}
{% endif %}
{% endif %}
@@ -145,13 +162,16 @@
{% if is_mastercontainer_update_available == true %}
{% if isBackupOrRestoreRunning == false %}
<h2>Mastercontainer update</h2>
⚠ A mastercontainer update is available. Please click on the button below to update it. All other containers get updated independently from the mastercontainer by simply clicking on `Stop containers` and clicking on `Start containers` if a new update is available.<br><br>
<form method="POST" action="/api/docker/watchtower" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input class="button" type="submit" value="Update mastercontainer" />
</form>
{% if isAnyRunning == false %}
⚠ A mastercontainer update is available. Please click on the button below to update it.<br><br>
<form method="POST" action="/api/docker/watchtower" class="xhr">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input class="button" type="submit" value="Update mastercontainer" />
</form>
{% else %}
⚠ A mastercontainer update is available. Please stop your containers in order to be able to update the mastercontainer.
{% endif %}
{% endif %}
{% endif %}
@@ -190,6 +210,7 @@
Backed up will get all important data of your Nextcloud AIO instance like the database, your files and configuration files of the mastercontainer and else. <br /><br/>
The backup itself will use a tool that is called <a href="https://github.com/borgbackup/borg#what-is-borgbackup">BorgBackup<a/> which is a well-known server backup tool that efficiently backs up your files and encrypts them on the fly. <br /><br/>
Backups get created in the following directory on the host: {{ borg_backup_host_location }}/borg <br /><br/>
Be aware that this solution does not back up files and folders that are mounted into Nextcloud using the external storage app. <br /><br/>
{% if isApacheStarting != true %}
<form method="POST" action="/api/docker/backup" class="xhr">
@@ -206,11 +227,16 @@
<input class="button" 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.')" /><br/>
</form>
Click on the button below to restore the last backup from {{ last_backup_time }}. This will overwrite all your files with the state of the backup. It makes sense to run an integrity check before restoring your files but is not mandatory since it shouldn't be needed in most situations.<br><br>
<form method="POST" action="/api/docker/restore" class="xhr">
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 state of the backup so you should consider creating a backup first. It also makes sense to run an integrity check before restoring your files but is not mandatory since it shouldn't be needed in most situations.<br><br>
<form method="POST" action="/api/docker/restore" class="xhr" id="restore_selection">
<input type="hidden" name="{{csrf.keys.name}}" value="{{csrf.name}}">
<input type="hidden" name="{{csrf.keys.value}}" value="{{csrf.value}}">
<input class="button" type="submit" value="Restore last backup" onclick="return confirm('Restore last backup? Are you sure that you want to restore the last backup? This will stop all running containers and restore the last backup from {{ last_backup_time }}. You might want to check the backup integrity first.')" />
<select id="selected_restore_time" name="selected_restore_time" form="restore_selection">
{% for restore_time in backup_times %}
<option value="{{ restore_time }}">{{ restore_time }}</option>
{% endfor %}
</select>
<input class="button" 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.')" />
</form>
{% endif %}
{% endif %}

View File

@@ -66,29 +66,29 @@ Included are:
</details>
4. After the initial startup, you should be able to open the Nextcloud AIO Interface now on port 8080 of this server.<br>
E.g. https://internal.ip.of.this.server:8080<br>
E.g. `https://internal.ip.of.this.server:8080`<br>
If your server has port 80 and 8443 open and you point a domain to your server, you can get a valid certificate automatially by opening the Nextcloud AIO Interface via:<br>
https://your-domain-that-points-to-this-server.tld:8443
`https://your-domain-that-points-to-this-server.tld:8443`
5. Please do not forget to open port `3478/TCP` and `3478/UDP` for the Talk container!
## FAQ
### How does it work?
Nextcloud AIO is inspired by projects like Portainer that allow to manage the docker daemon by talking to the docker socket directly. This concept allows to install only one container with a single command that does the heavy lifting of creating and managing all containers that are needed in order to provide a Nextcloud installation with most features included. It also makes updating a breeze and is not bound to the host system (and its slow updates) anymore as everything is in containers. Additionally, it is very easy to handle from a user perspective because a simple interface for managing your Nextcloud AIO installation is provided.
### Are reverse proxies supported?
Reverse proxies are currently because of the above mentioned architecture not supported.<br>
You might investigate yourself though how it could made work behind reverse proxies. If you open a PR with that we might consider it then :)
Yes. Please refer to the following documentation on this: [reverse-proxy.md](https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md)
### Which ports are mandatory to be open?
Only those (if you acces the Mastercontainer Interface internally via port 8080):
- `443/TCP` for the Nextcloud container
- `3478/TCP` and `3478/UPD` for the Talk container
- `443/TCP` for the Apache container
- `3478/TCP` and `3478/UDP` for the Talk container
### Explanation of used ports:
- `8080/TCP`: Mastercontainer Interface with self-signed certificate (works always, also if only access via IP-address is possible, e.g. `https://internal.ip.address:8080/`)
- `80/TCP`: redirects to Nextcloud (is used for getting the certificate via ACME http-challenge for the Mastercontainer)
- `8443/TCP`: Mastercontainer Interface with valid certificate (only works if port 80 and 8443 are open and you point a domain to your server. It generates a valid certificate then automatically and access via e.g. `https://public.domain.com:8443/` is possible.)
- `443/TCP`: will be used by the Nextcloud container later on and needs to be open
- `3478/TCP` and `3478/UPD`: will be used by the Turnserver inside the Talk container and needs to be open
- `443/TCP`: will be used by the Apache container later on and needs to be open
- `3478/TCP` and `3478/UDP`: will be used by the Turnserver inside the Talk container and needs to be open
### How to run `occ` commands?
Simply run the following: `sudo docker exec -it nextcloud-aio-nextcloud php occ your-command`. Of course `your-command` needs to be exchanged with the command that you want to run.
@@ -113,11 +113,63 @@ It is recommended to create a backup before any container update. By doing this,
If you connect an external drive to your host, and choose the backup directory to be on that drive, you are also kind of save against drive failures of the drive where the docker volumes are stored on.
Backups can be created and restored in the AIO interface using the buttons `Create Backup` and `Restore last backup`. Additionally, a backup check is provided that checks the integrity of your backups but it shouldn't be needed in most situations.
Backups can be created and restored in the AIO interface using the buttons `Create Backup` and `Restore selected backup`. Additionally, a backup check is provided that checks the integrity of your backups but it shouldn't be needed in most situations.
The backups itself get encrypted with an encryption key that gets shown to you in the AIO interface. Please save that at a safe place as you will not be able to restore from backup without this key.
Note that this implementation does not provide remote backups, for this you can use the [backup app](https://apps.nextcloud.com/apps/backup).
Be aware that this solution does not back up files and folders that are mounted into Nextcloud using the external storage app.
Note that this implementation does not provide remote backups, for this you can use the [backup app](https://apps.nextcloud.com/apps/backup).
---
#### Failure of the backup container in LXC containers
If you are running AIO in a LXC container, you need to make sure that FUSE is enabled in the LXC container settings. Otherwise the backup container will not be able to start as FUSE is required for it to work.
---
#### Pro-tip: Backup archives access
You can open the BorgBackup archives on your host by following these steps:<br>
(instructions for Ubuntu Desktop)
```bash
# Install borgbackup on the host
sudo apt update && sudo apt install borgbackup
# Mount the archives to /tmp/borg (if you are using the default backup location /mnt/backup/borg)
sudo mkdir -p /tmp/borg && sudo borg mount "/mnt/backup/borg" /tmp/borg
# After entering your repository key successfully, you should be able to access all archives in /tmp/borg
# You can now do whatever you want by syncing them to a different place using rsync or doing other things
# E.g. you can open the file manager on that location by running:
xhost +si:localuser:root && sudo nautilus /tmp/borg
# When you are done, simply close the file manager and run the following command to unmount the backup archives:
sudo umount /tmp/borg
```
---
#### Delete backup archives manually
You can delete BorgBackup archives on your host manually by following these steps:<br>
(instructions for Debian based OS' like Ubuntu)
```bash
# Install borgbackup on the host
sudo apt update && sudo apt install borgbackup
# List all archives (if you are using the default backup location /mnt/backup/borg)
sudo borg list "/mnt/backup/borg"
# After entering your repository key successfully, you should now see a list of all backup archives
# An example backup archive might be called 20220223_174237-nextcloud-aio
# Then you can simply delete the archive with:
sudo borg delete --stats --progress "/mnt/backup/borg::20220223_174237-nextcloud-aio"
```
After doing so, make sure to update the backup archives list in the AIO interface!<br>
You can do so by clicking on the `Check backup integrity` button or `Create backup` button.
### How to allow the Nextcloud container to access directories on the host?
By default, the Nextcloud container is confined and cannot access directories on the host OS. You might want to change this when you are planning to use local external storage in Nextcloud to store some files outside the data directory and can do so by adding the environmental variable `NEXTCLOUD_MOUNT` to the initial startup of the mastercontainer. Allowed values for that variable are strings that are equal to or start with `/mnt/` or `/media/` or are equal to `/var/backups` and unequal to `/mnt/ncdata`. Two examples for this are: `-e NEXTCLOUD_MOUNT="/mnt/"` or `-e NEXTCLOUD_MOUNT="/media/"`. After doing so, please make sure to apply the correct permissions to the directories that you want to use in Nextcloud. E.g. `sudo chown -R 33:0 /mnt/your-drive-mountpoint` should make it work. You can then navigate to the apps management page, activate the external storage app, navigate to `https://your-nc-domain.com/settings/admin/externalstorages` and add a local external storage directory that will be accessible inside the container at the same place that you've entered. E.g. `/mnt/your-drive-mountpoint` will be mounted to `/mnt/your-drive-mountpoint` inside the container, etc. Be aware though that these locations will not be covered by the built-in backup solution!
### Huge docker logs
When your containers run for a few days without a restart, the container logs that you can view from the AIO interface can get really huge. You can limit the loge sizes by enabling logrotate for docker container logs. Feel free to enable this by following those instructions: https://sandro-keil.de/blog/logrotate-for-docker-container/
@@ -134,6 +186,9 @@ You can move the whole docker library and all its files including all Nextcloud
### How to edit Nextclouds config.php file with a texteditor?
You can edit Nextclouds config.php file directly from the host with your favorite text editor. E.g. like this: `sudo nano /var/lib/docker/volumes/nextcloud_aio_nextcloud/_data/config/config.php`. Make sure to not break the file though which might corrupt your Nextcloud instance otherwise. In best case, create a backup using the built-in backup solution before editing the file.
### Custom skeleton directory
If you want to define a custom skeleton directory, you can do so by putting your skeleton files into `/var/lib/docker/volumes/nextcloud_aio_nextcloud_data/_data/skeleton/`, applying the correct permissions with `sudo chown -R 33:0 /var/lib/docker/volumes/nextcloud_aio_nextcloud_data/_data/skeleton` and setting the skeleton directory option with `sudo docker exec -it nextcloud-aio-nextcloud php occ config:system:set skeletondirectory --value="/mnt/ncdata/skeleton"`. You can read further on this option here: [click here](https://docs.nextcloud.com/server/stable/admin_manual/configuration_server/config_sample_php_parameters.html?highlight=skeletondir#:~:text=adding%20%3Fdirect%3D1-,'skeletondirectory',-%3D%3E%20'%2Fpath%2Fto%2Fnextcloud)
### LDAP
It is possible to connect to an existing LDAP server. You need to make sure that the LDAP server is reachable from the Nextcloud container. Then you can enable the LDAP app and configure LDAP in Nextcloud manually. If you don't have a LDAP server yet, recommended is to use this docker container: https://hub.docker.com/r/osixia/openldap/. Make sure here as well that Nextcloud can talk to the LDAP server. The easiest way is by adding the LDAP docker container to the docker network `nextcloud-aio`. Then you can connect to the LDAP container by its name from the Nextcloud container. **Pro-tip**: You will probably find this app useful: https://apps.nextcloud.com/apps/ldap_write_support

68
reverse-proxy.md Normal file
View File

@@ -0,0 +1,68 @@
## Reverse Proxy Config
Basically, you need to specify the port that the apache container shall use and modify the startup command a bit.
All examples below will use port `11000` as example apache port. Also it is supposed that the reverse proxy runs on the same server like AIO, hence `localhost` is used and not an internal ip-address to point to the AIO instance. Modify both to your needings.
### Caddy reverse proxy config example
Add this to your Caddyfile:
```
https://<your-nc-domain>:443 {
header Strict-Transport-Security max-age=31536000;
reverse_proxy localhost:11000
}
```
Of course you need to modify `<your-nc-domain>` to the domain on which you want to run Nextcloud.
### Startup command
```
# For x64 CPUs:
sudo docker run -it \
--name nextcloud-aio-mastercontainer \
--restart always \
-p 8080:8080 \
-e APACHE_PORT=11000 \
--volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
nextcloud/all-in-one:latest
```
<details>
<summary>Command for arm64 CPUs like the Raspberry Pi 4</summary>
```
# For arm64 CPUs:
sudo docker run -it \
--name nextcloud-aio-mastercontainer \
--restart always \
-p 8080:8080 \
-e APACHE_PORT=11000 \
--volume nextcloud_aio_mastercontainer:/mnt/docker-aio-config \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
nextcloud/all-in-one:latest-arm64
```
</details>
After doing so, you should be able to access the AIO Interface via `https://internal.ip.of.this.server:8080`. Enter your domain that you've entered in the reverse proxy config and you should be done. Please do not forget to open port `3478/TCP` and `3478/UDP` for the Talk container!
### Optional
If you want to also access your AIO interface publicly with a valid certificate, you can add e.g. the following config to your Caddyfile:
```
https://<your-nc-domain>:8443 {
reverse_proxy https://localhost:8080 {
transport http {
tls_insecure_skip_verify
}
}
}
```
Of course you also need to modify `<your-nc-domain>` to the domain that you want to use. Afterwards should the AIO interface be accessible via `https://<your-nc-domain>:8443`.