mirror of
https://github.com/nextcloud/all-in-one.git
synced 2026-05-22 03:10:16 +00:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
853a880c9d | ||
|
|
0ecd2c8f78 | ||
|
|
24d1451325 | ||
|
|
efde2ab41a | ||
|
|
a89c183508 | ||
|
|
301b6e6297 | ||
|
|
6e839f5baf | ||
|
|
edb8bd228b | ||
|
|
23429f3e59 | ||
|
|
f4130a8475 | ||
|
|
e5aa3757d5 | ||
|
|
12f1549221 | ||
|
|
d34167b30f | ||
|
|
5e0118a3b5 | ||
|
|
220194b409 | ||
|
|
2943c6cf08 | ||
|
|
2040553822 | ||
|
|
d1656a0fcb | ||
|
|
6e9261f306 | ||
|
|
269f62615f | ||
|
|
704c4ad331 | ||
|
|
9afec142f3 | ||
|
|
9fbcaae567 | ||
|
|
82c371b519 | ||
|
|
2afc711983 | ||
|
|
a42f21555a | ||
|
|
d6ece6cad8 | ||
|
|
6f1da5fc5d | ||
|
|
2024cb8f26 | ||
|
|
1c01e9e21f | ||
|
|
628e55f076 | ||
|
|
5b49faf3b7 | ||
|
|
33a73a7b95 | ||
|
|
e2086ada2b | ||
|
|
c15bc86e06 |
54
.github/workflows/create-psalm-container.yml
vendored
Normal file
54
.github/workflows/create-psalm-container.yml
vendored
Normal 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
18
.github/workflows/psalm-analysis.yml
vendored
Normal 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
25
.github/workflows/psalm-security.yml
vendored
Normal 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
|
||||
48
.github/workflows/psalm-update-baseline.yml
vendored
Normal file
48
.github/workflows/psalm-update-baseline.yml
vendored
Normal 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
|
||||
@@ -6,7 +6,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
https://{$NC_DOMAIN}:443 {
|
||||
{$PROTOCOL}://{$NC_DOMAIN}:{$APACHE_PORT} {
|
||||
|
||||
# Notify Push
|
||||
route /push/* {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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/
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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."
|
||||
@@ -68,6 +76,15 @@ The string must be equal to/start with '/mnt/' or '/media/' or be equal to '/var
|
||||
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/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# From https://github.com/docker-library/postgres/blob/master/13/alpine/Dockerfile
|
||||
FROM postgres:13.6-alpine3.15
|
||||
FROM postgres:14.2-alpine3.15
|
||||
|
||||
RUN apk add --update --no-cache bash openssl shadow netcat-openbsd
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
16
php/composer.lock
generated
16
php/composer.lock
generated
@@ -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": [
|
||||
@@ -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": [
|
||||
|
||||
@@ -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": [
|
||||
{
|
||||
@@ -276,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
113
php/psalm-baseline.xml
Normal 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->getParsedBody()['borg_backup_host_location']</code>
|
||||
<code>$request->getParsedBody()['domain']</code>
|
||||
</PossiblyInvalidArrayAccess>
|
||||
<PossiblyNullArgument occurrences="2">
|
||||
<code>$request->getParsedBody()['borg_backup_host_location']</code>
|
||||
<code>$request->getParsedBody()['domain']</code>
|
||||
</PossiblyNullArgument>
|
||||
<PossiblyNullArrayAccess occurrences="2">
|
||||
<code>$request->getParsedBody()['borg_backup_host_location']</code>
|
||||
<code>$request->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->getParsedBody()['selected_restore_time']</code>
|
||||
</PossiblyInvalidArrayAccess>
|
||||
<PossiblyNullArgument occurrences="1">
|
||||
<code>$container</code>
|
||||
</PossiblyNullArgument>
|
||||
<PossiblyNullArrayAccess occurrences="1">
|
||||
<code>$request->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->getParsedBody()['password']</code>
|
||||
</PossiblyInvalidArrayAccess>
|
||||
<PossiblyNullArgument occurrences="1">
|
||||
<code>$password</code>
|
||||
</PossiblyNullArgument>
|
||||
<PossiblyNullArrayAccess occurrences="1">
|
||||
<code>$request->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->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
15
php/psalm.xml
Normal 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>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
@@ -126,7 +126,7 @@ 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) {
|
||||
@@ -146,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() != '') {
|
||||
@@ -167,7 +167,7 @@ class DockerController
|
||||
$this->PerformRecursiveContainerStart($id);
|
||||
}
|
||||
|
||||
private function StopDomaincheckContainer()
|
||||
private function StopDomaincheckContainer() : void
|
||||
{
|
||||
$id = 'nextcloud-aio-domaincheck';
|
||||
$this->PerformRecursiveContainerStop($id);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -101,10 +101,6 @@ class ConfigurationManager
|
||||
$backupTimes[] = $backupTimesTemp[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_array($backupTimes)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $backupTimes;
|
||||
}
|
||||
@@ -148,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);
|
||||
|
||||
@@ -232,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
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
@@ -214,6 +214,8 @@ class DockerActionManager
|
||||
$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]);
|
||||
}
|
||||
@@ -257,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 {
|
||||
@@ -281,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 {
|
||||
@@ -352,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) {
|
||||
|
||||
@@ -398,7 +399,7 @@ class DockerActionManager
|
||||
}
|
||||
}
|
||||
|
||||
public function DisconnectContainerFromNetwork(Container $container)
|
||||
public function DisconnectContainerFromNetwork(Container $container) : void
|
||||
{
|
||||
|
||||
$url = $this->BuildApiUrl(
|
||||
@@ -419,7 +420,7 @@ class DockerActionManager
|
||||
}
|
||||
}
|
||||
|
||||
private function ConnectContainerIdToNetwork(string $id)
|
||||
private function ConnectContainerIdToNetwork(string $id) : void
|
||||
{
|
||||
$url = $this->BuildApiUrl('networks/create');
|
||||
try {
|
||||
@@ -462,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);
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
</header>
|
||||
|
||||
<div class="content">
|
||||
<h1>Nextcloud AIO Beta v0.5.0</h1>
|
||||
<h1>Nextcloud AIO Beta v0.6.0</h1>
|
||||
This is beta software and not production ready.<br><br>
|
||||
|
||||
{% set isAnyRunning = false %}
|
||||
@@ -210,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">
|
||||
|
||||
45
readme.md
45
readme.md
@@ -66,28 +66,28 @@ 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
|
||||
- `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
|
||||
- `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?
|
||||
@@ -117,11 +117,19 @@ Backups can be created and restored in the AIO interface using the buttons `Crea
|
||||
|
||||
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.
|
||||
|
||||
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).
|
||||
|
||||
---
|
||||
|
||||
**Pro-tip**: you can open the BorgBackup archives on your host by following these steps:<br>
|
||||
#### 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
|
||||
@@ -139,8 +147,29 @@ xhost +si:localuser:root && sudo nautilus /tmp/borg
|
||||
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.
|
||||
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/
|
||||
|
||||
68
reverse-proxy.md
Normal file
68
reverse-proxy.md
Normal 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`.
|
||||
Reference in New Issue
Block a user