From ed168c342f185cc92b9f4b8ffd2c1277ebd053dc Mon Sep 17 00:00:00 2001
From: Phill Kelley <34226495+Paraphraser@users.noreply.github.com>
Date: Sat, 14 Oct 2023 14:04:15 +1100
Subject: [PATCH 1/6] 2023-10-14 documentation - master branch
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Replaces all example commands in the following format:
```
$ docker-compose rm --force --stop -v «container»
```
with example commands in the this format:
```
$ docker-compose down «container»
```
The Getting Started document includes a note explaining that any error
returned by `docker-compose down` to the effect that it does not support
`«container»` arguments implies that the user's version of
`docker-compose` is obsolete and should be updated.
Where any container's documentation has had `rm` replaced with `down`,
that is followed by a note pointing to the Getting Started explanation.
Also, I took the opportunity to fix the following error returned by
`mkdocs`:
```
INFO - Doc file 'index.md' contains an unrecognized relative link 'Developers/', it was left as is. Did you mean 'Developers/index.md'?
```
Signed-off-by: Phill Kelley <34226495+Paraphraser@users.noreply.github.com>
---
docs/Basic_setup/index.md | 13 +++++++++++--
docs/Containers/Blynk_server.md | 6 ++++--
docs/Containers/Grafana.md | 4 +++-
docs/Containers/InfluxDB2.md | 8 ++++++--
docs/Containers/MariaDB.md | 4 +++-
docs/Containers/MotionEye.md | 4 +++-
docs/Containers/NextCloud.md | 7 +++++--
docs/Containers/Node-RED.md | 4 +++-
docs/Containers/Pi-hole.md | 4 +++-
docs/Containers/PostgreSQL.md | 4 +++-
docs/Containers/Prometheus.md | 4 +++-
docs/Containers/Python.md | 12 ++++++++----
docs/Containers/Scrypted.md | 4 +++-
docs/Containers/Telegraf.md | 10 ++++++----
docs/Containers/WireGuard.md | 8 ++++++--
docs/Containers/ZeroTier.md | 11 ++++++++---
docs/index.md | 2 +-
17 files changed, 79 insertions(+), 30 deletions(-)
mode change 100644 => 100755 docs/Basic_setup/index.md
mode change 100644 => 100755 docs/Containers/Blynk_server.md
mode change 100644 => 100755 docs/Containers/Grafana.md
mode change 100644 => 100755 docs/Containers/InfluxDB2.md
mode change 100644 => 100755 docs/Containers/MariaDB.md
mode change 100644 => 100755 docs/Containers/NextCloud.md
mode change 100644 => 100755 docs/Containers/Node-RED.md
mode change 100644 => 100755 docs/Containers/PostgreSQL.md
mode change 100644 => 100755 docs/Containers/Prometheus.md
mode change 100644 => 100755 docs/Containers/Python.md
mode change 100644 => 100755 docs/Containers/Scrypted.md
mode change 100644 => 100755 docs/Containers/Telegraf.md
mode change 100644 => 100755 docs/Containers/WireGuard.md
mode change 100644 => 100755 docs/Containers/ZeroTier.md
mode change 100644 => 100755 docs/index.md
diff --git a/docs/Basic_setup/index.md b/docs/Basic_setup/index.md
old mode 100644
new mode 100755
index 18cc70a1b..979040ef6
--- a/docs/Basic_setup/index.md
+++ b/docs/Basic_setup/index.md
@@ -409,13 +409,22 @@ $ cd ~/IOTstack
$ docker-compose start «container»
```
-There is no equivalent of `down` for a single container. It needs:
+You can also `down` a container:
``` console
$ cd ~/IOTstack
-$ docker-compose rm --force --stop -v «container»
+$ docker-compose down «container»
```
+Note:
+
+* If the `down` command returns an error suggesting that you can't use it to down a container, it actually means that you have an obsolete version of `docker-compose`. You should upgrade your system. The workaround is to you the old syntax:
+
+ ``` console
+ $ cd ~/IOTstack
+ $ docker-compose rm --force --stop -v «container»
+ ```
+
To reactivate a container which has been stopped and removed:
``` console
diff --git a/docs/Containers/Blynk_server.md b/docs/Containers/Blynk_server.md
old mode 100644
new mode 100755
index a9eeefef0..edb403c43
--- a/docs/Containers/Blynk_server.md
+++ b/docs/Containers/Blynk_server.md
@@ -164,11 +164,11 @@ Erasing Blynk Server's persistent storage area triggers self-healing and restore
```console
$ cd ~/IOTstack
-$ docker-compose rm --force --stop -v blynk_server
+$ docker-compose down blynk_server
$ sudo rm -rf ./volumes/blynk_server
$ docker-compose up -d blynk_server
```
-Note:
+Notes:
* You can also remove individual configuration files and then trigger self-healing. For example, if you decide to edit `server.properties` and make a mess, you can restore the original default version like this:
@@ -177,6 +177,8 @@ Note:
$ rm volumes/blynk_server/config/server.properties
$ docker-compose restart blynk_server
```
+
+* See also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
## Upgrading Blynk Server { #upgradingBlynkServer }
diff --git a/docs/Containers/Grafana.md b/docs/Containers/Grafana.md
old mode 100644
new mode 100755
index bf3009cc0..22793f7bb
--- a/docs/Containers/Grafana.md
+++ b/docs/Containers/Grafana.md
@@ -122,9 +122,11 @@ Begin by stopping Grafana:
``` console
$ cd ~/IOTstack
-$ docker-compose rm --force --stop -v grafana
+$ docker-compose down grafana
```
+> see also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
+
You have two options:
1. Destroy your settings and dashboards but retain any plugins you may have installed:
diff --git a/docs/Containers/InfluxDB2.md b/docs/Containers/InfluxDB2.md
old mode 100644
new mode 100755
index 3b563711c..97e1b7bd5
--- a/docs/Containers/InfluxDB2.md
+++ b/docs/Containers/InfluxDB2.md
@@ -202,11 +202,13 @@ To migrate your InfluxDB 1.8 data:
```bash
$ sudo rm -rf ./volumes/influxdb.migrate
- $ docker-compose rm --force --stop -v influxdb
+ $ docker-compose down influxdb
$ sudo cp -a ./volumes/influxdb ./volumes/influxdb.migrate
$ docker-compose up -d influxdb
$ sudo chown -R 1000:1000 ./volumes/influxdb.migrate/data
```
+
+ > see also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
In words:
@@ -349,8 +351,10 @@ If you need to start over from a clean slate:
2. Terminate the InfluxDB 2 container:
```bash
- $ docker-compose rm --force --stop -v influxdb2
+ $ docker-compose down influxdb2
```
+
+ > see also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
3. Remove the persistent store:
diff --git a/docs/Containers/MariaDB.md b/docs/Containers/MariaDB.md
old mode 100644
new mode 100755
index 4242aef60..cc0ef854c
--- a/docs/Containers/MariaDB.md
+++ b/docs/Containers/MariaDB.md
@@ -38,9 +38,11 @@ You only get the opportunity to change the `MQSL_` prefixed environment variable
``` console
$ cd ~/IOTstack
- $ docker-compose rm --force --stop -v mariadb
+ $ docker-compose down mariadb
$ sudo rm -rf ./volumes/mariadb
```
+
+ > see also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
* Edit `docker-compose.yml` and change the variables.
* Bring up the container:
diff --git a/docs/Containers/MotionEye.md b/docs/Containers/MotionEye.md
index d0387a2ed..e947819f4 100755
--- a/docs/Containers/MotionEye.md
+++ b/docs/Containers/MotionEye.md
@@ -109,8 +109,10 @@ Although it depends on your exact settings, MotionEye's video storage can repres
2. Terminate the motioneye container:
``` bash
- $ docker-compose rm --force --stop -v motioneye
+ $ docker-compose down motioneye
```
+
+ > see also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
3. Move the video storage folder:
diff --git a/docs/Containers/NextCloud.md b/docs/Containers/NextCloud.md
old mode 100644
new mode 100755
index 6ff5db73f..8b4f4eed9
--- a/docs/Containers/NextCloud.md
+++ b/docs/Containers/NextCloud.md
@@ -75,6 +75,8 @@ The passwords need to be set before you bring up the Nextcloud service for the f
```console
$ docker-compose down
```
+
+ > see also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
3. Erase the persistent storage area for Nextcloud (double-check the command *before* you hit return):
@@ -309,7 +311,7 @@ If you want to take a backup, something like the following will get the job done
$ cd ~/IOTstack
$ BACKUP_TAR_GZ=$PWD/backups/$(date +"%Y-%m-%d_%H%M").$HOSTNAME.nextcloud-backup.tar.gz
$ touch "$BACKUP_TAR_GZ"
-$ docker-compose rm --force --stop -v nextcloud nextcloud_db
+$ docker-compose down nextcloud nextcloud_db
$ sudo tar -czf "$BACKUP_TAR_GZ" -C "./volumes/nextcloud" .
$ docker-compose up -d nextcloud
```
@@ -318,13 +320,14 @@ Notes:
* A *baseline* backup takes over 400MB and about 2 minutes. Once you start adding your own data, it will take even more time and storage.
* The `up` of the NextCloud container implies the `up` of the Nextcloud_DB container.
+* See also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
To restore, you first need to identify the name of the backup file by looking in the `backups` directory. Then:
```console
$ cd ~/IOTstack
$ RESTORE_TAR_GZ=$PWD/backups/2021-06-12_1321.sec-dev.nextcloud-backup.tar.gz
-$ docker-compose rm --force --stop -v nextcloud nextcloud_db
+$ docker-compose down nextcloud nextcloud_db
$ sudo rm -rf ./volumes/nextcloud/*
$ sudo tar -x --same-owner -z -f "$RESTORE_TAR_GZ" -C "./volumes/nextcloud"
$ docker-compose up -d nextcloud
diff --git a/docs/Containers/Node-RED.md b/docs/Containers/Node-RED.md
old mode 100644
new mode 100755
index 7d9cd50d6..cbd548d02
--- a/docs/Containers/Node-RED.md
+++ b/docs/Containers/Node-RED.md
@@ -975,9 +975,11 @@ To stop the running container:
``` console
$ cd ~/IOTstack
-$ docker-compose rm --force --stop -v nodered
+$ docker-compose down nodered
```
+> see also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
+
Alternatively, you can stop the entire stack:
``` console
diff --git a/docs/Containers/Pi-hole.md b/docs/Containers/Pi-hole.md
index 764f55e3b..11e77e32b 100755
--- a/docs/Containers/Pi-hole.md
+++ b/docs/Containers/Pi-hole.md
@@ -496,10 +496,12 @@ The recommended approach is:
``` console
$ cd ~/IOTstack
- $ docker-compose rm --force --stop -v pihole
+ $ docker-compose down pihole
$ sudo rm -rf ./volumes/pihole
$ docker-compose up -d pihole
```
+
+ > see also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
5. Login to Pi-hole's web GUI and navigate to Settings » Teleporter.
6. Use the checkboxes to select the settings you wish to restore, and click the Browse and Restore buttons.
diff --git a/docs/Containers/PostgreSQL.md b/docs/Containers/PostgreSQL.md
old mode 100644
new mode 100755
index 2693a72ca..fe6821e89
--- a/docs/Containers/PostgreSQL.md
+++ b/docs/Containers/PostgreSQL.md
@@ -85,7 +85,9 @@ If you need to start over, proceed like this:
``` console
$ cd ~/IOTstack
-$ docker-compose rm --force --stop -v postgres
+$ docker-compose down postgres
$ sudo rm -rf ./volumes/postgres
$ docker-compose up -d postgres
```
+
+> see also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
diff --git a/docs/Containers/Prometheus.md b/docs/Containers/Prometheus.md
old mode 100644
new mode 100755
index 503de1447..4020334ee
--- a/docs/Containers/Prometheus.md
+++ b/docs/Containers/Prometheus.md
@@ -24,8 +24,10 @@
```
$ cd ~/IOTstack
- $ docker-compose rm --force --stop -v prometheus prometheus-cadvisor prometheus-nodeexporter
+ $ docker-compose down prometheus prometheus-cadvisor prometheus-nodeexporter
```
+
+ > see also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
2. Move the existing active configuration out of the way:
diff --git a/docs/Containers/Python.md b/docs/Containers/Python.md
old mode 100644
new mode 100755
index 331c637a2..f66e63850
--- a/docs/Containers/Python.md
+++ b/docs/Containers/Python.md
@@ -154,8 +154,10 @@ To stop the container from running, either:
``` console
$ cd ~/IOTstack
- $ docker-compose rm --force --stop -v python
+ $ docker-compose down python
```
+
+ > see also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
## starting the Python service { #startPython }
@@ -255,11 +257,13 @@ If you make a mess of things and need to start from a clean slate, erase the per
``` console
$ cd ~/IOTstack
-$ docker-compose rm --force --stop -v python
+$ docker-compose down python
$ sudo rm -rf ./volumes/python
$ docker-compose up -d python
```
+> see also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
+
The container will re-initialise the persistent storage area from its defaults.
### adding packages { #addingPackages }
@@ -377,7 +381,7 @@ Suppose the Python script you have been developing reaches a major milestone and
``` console
$ cd ~/IOTstack
- $ docker-compose rm --force --stop -v python
+ $ docker-compose down python
$ sudo rm -rf ./volumes/python
```
@@ -419,7 +423,7 @@ Proceed like this:
``` console
$ cd ~/IOTstack
- $ docker-compose rm --force --stop -v python
+ $ docker-compose down python
```
2. Remove the existing local image:
diff --git a/docs/Containers/Scrypted.md b/docs/Containers/Scrypted.md
old mode 100644
new mode 100755
index ae7171504..255466c15
--- a/docs/Containers/Scrypted.md
+++ b/docs/Containers/Scrypted.md
@@ -72,11 +72,13 @@ If you need to start over from scratch:
``` console
$ cd ~/IOTstack
-$ docker-compose rm --force --stop -v scrypted
+$ docker-compose down scrypted
$ sudo rm -rf ./volumes/scrypted
$ docker-compose up -d scrypted
```
+> see also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
+
## About the service definition
The Scrypted container runs in host mode, which means it binds directly to the Raspberry Pi's ports. The service definition includes:
diff --git a/docs/Containers/Telegraf.md b/docs/Containers/Telegraf.md
old mode 100644
new mode 100755
index d07c3683f..29d2480e4
--- a/docs/Containers/Telegraf.md
+++ b/docs/Containers/Telegraf.md
@@ -252,12 +252,12 @@ Erasing Telegraf's persistent storage area triggers self-healing and restores kn
``` console
$ cd ~/IOTstack
-$ docker-compose rm --force --stop -v telegraf
+$ docker-compose down telegraf
$ sudo rm -rf ./volumes/telegraf
$ docker-compose up -d telegraf
```
-Note:
+Notes:
* You can also remove individual files within the persistent storage area and then trigger self-healing. For example, if you decide to edit `telegraf-reference.conf` and make a mess, you can restore the original version like this:
@@ -267,13 +267,15 @@ Note:
$ docker-compose restart telegraf
```
+* See also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
+
### Resetting the InfluxDB database { #resetDB }
To reset the InfluxDB database that Telegraf writes into, proceed like this:
``` console
$ cd ~/IOTstack
-$ docker-compose rm --force --stop -v telegraf
+$ docker-compose down telegraf
$ docker exec -it influxdb influx -precision=rfc3339
> drop database telegraf
> exit
@@ -283,7 +285,7 @@ $ docker-compose up -d telegraf
In words:
* Be in the right directory.
-* Stop the Telegraf container (while leaving the InfluxDB container running).
+* Stop the Telegraf container (while leaving the InfluxDB container running). See also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer).
* Launch the Influx CLI inside the InfluxDB container.
* Delete the `telegraf` database, and then exit the CLI.
* Start the Telegraf container. This re-creates the database automatically.
diff --git a/docs/Containers/WireGuard.md b/docs/Containers/WireGuard.md
old mode 100644
new mode 100755
index a73418ff2..e9b9c217c
--- a/docs/Containers/WireGuard.md
+++ b/docs/Containers/WireGuard.md
@@ -616,10 +616,12 @@ IOTstack users implementing WireGuard for the first time will get the correct st
``` console
$ cd ~/IOTstack
-$ docker-compose rm --force --stop -v wireguard
+$ docker-compose down wireguard
$ ./scripts/2022-10-01-wireguard-restructure.sh
```
+> see also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
+
In words:
* Be in the correct directory
@@ -665,8 +667,10 @@ The procedure is:
``` console
$ cd ~/IOTstack
- $ docker-compose rm --force --stop -v wireguard
+ $ docker-compose down wireguard
```
+
+ > see also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
2. Erase the persistent storage area (essential):
diff --git a/docs/Containers/ZeroTier.md b/docs/Containers/ZeroTier.md
old mode 100644
new mode 100755
index f39faf264..0b832105f
--- a/docs/Containers/ZeroTier.md
+++ b/docs/Containers/ZeroTier.md
@@ -209,8 +209,10 @@ The ZeroTier-router container is just the ZeroTier-client container with some `i
``` console
$ cd ~/IOTstack
- $ docker-compose rm --force --stop -v zerotier-client
+ $ docker-compose down zerotier-client
```
+
+ > See also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
2. Remove the existing service definition, either by:
@@ -969,11 +971,14 @@ You can erase ZeroTier's persistent storage area like this:
``` console
$ cd ~/IOTstack
-$ docker-compose rm --force --stop -v {zerotier-client | zerotier-router}
+$ docker-compose down {zerotier-client | zerotier-router}
$ sudo rm -rf ./volumes/zerotier-one
```
-> Tip: always double-check `sudo` commands **before** hitting Enter.
+Tips:
+
+1. always double-check `sudo` commands **before** hitting Enter.
+2. see also [if downing a container doesn't work](../Basic_setup/index.md/#downContainer)
Erasing persistent storage destroys the client's authorisation (cryptographic credentials). If you start the container again, it will construct a new identity and you will need to re-authorise the client in ZeroTier Central. You should also delete the obsolete client authorisation.
diff --git a/docs/index.md b/docs/index.md
old mode 100644
new mode 100755
index 8d8e6a79e..bacadc90e
--- a/docs/index.md
+++ b/docs/index.md
@@ -24,7 +24,7 @@ Welcome to IOTstack:
* You're always welcome to ask questions on the [IOTStack Discord](https://discord.gg/ZpKHnks).
-* Fixes and improvements welcome, see [Contributing](Developers/)
+* Fixes and improvements welcome, see [Contributing](./Developers/index.md)
!!! cite inline end "Full site page listing"
From 63e1afd2e7afde2675848790c94ee0009e34fe7d Mon Sep 17 00:00:00 2001
From: Phill Kelley <34226495+Paraphraser@users.noreply.github.com>
Date: Sun, 22 Oct 2023 17:01:24 +1100
Subject: [PATCH 2/6] remove redundant list of videos
I will be making significant updates to list in the main readme and
there is no point in maintaining two lists.
Signed-off-by: Phill Kelley <34226495+Paraphraser@users.noreply.github.com>
---
docs/index.md | 13 -------------
1 file changed, 13 deletions(-)
mode change 100755 => 100644 docs/index.md
diff --git a/docs/index.md b/docs/index.md
old mode 100755
new mode 100644
index bacadc90e..a7708362c
--- a/docs/index.md
+++ b/docs/index.md
@@ -29,16 +29,3 @@ Welcome to IOTstack:
!!! cite inline end "Full site page listing"
{nav}
-
-## introduction to IOTstack - videos
-
-These are from 2019 and 2020. Though IOTstack has changed a bit, they are still
-a great introduction.
-
-Andreas Spiess Video #295: Raspberry Pi Server based on Docker, with VPN, Dropbox backup, Influx, Grafana, etc: IOTstack
-
-[![#295 Raspberry Pi Server based on Docker, with VPN, Dropbox backup, Influx, Grafana, etc: IOTstack](http://img.youtube.com/vi/a6mjt8tWUws/0.jpg)](https://www.youtube.com/watch?v=a6mjt8tWUws)
-
-Andreas Spiess Video #352: Raspberry Pi4 Home Automation Server (incl. Docker, OpenHAB, HASSIO, NextCloud)
-
-[![#352 Raspberry Pi4 Home Automation Server (incl. Docker, OpenHAB, HASSIO, NextCloud)](http://img.youtube.com/vi/KJRMjUzlHI8/0.jpg)](https://www.youtube.com/watch?v=KJRMjUzlHI8)
From 7a287c88277e9caba8b315ef95939d16ed007aee Mon Sep 17 00:00:00 2001
From: Phill Kelley <34226495+Paraphraser@users.noreply.github.com>
Date: Tue, 24 Oct 2023 16:35:21 +1100
Subject: [PATCH 3/6] update main README
1. Remove "significant change to networking" from main readme. This
change occurred in Jan 2022 so the warning is stale.
2. Add links to more recent videos to main readme, and list videos
in reverse chronological order.
Signed-off-by: Phill Kelley <34226495+Paraphraser@users.noreply.github.com>
---
README.md | 48 +++++++++++++++++++++++++++++++-----------------
1 file changed, 31 insertions(+), 17 deletions(-)
diff --git a/README.md b/README.md
index 08dfb01ff..dab194dd6 100644
--- a/README.md
+++ b/README.md
@@ -4,42 +4,56 @@ IOTstack is a builder for docker-compose to easily make and maintain IoT stacks
## introduction to IOTstack - videos
-These are from 2019 and 2020. Though IOTstack has changed quite a bit, they are
-still a great overview
+IOTstack changes a fair bit so YouTube videos only reflect a moment in time and tend to date quickly. These videos contain excellent overviews but you should rely more on the written documentation than anything you see in the videos.
-Andreas Spiess Video #295: Raspberry Pi Server based on Docker, with VPN, Dropbox backup, Influx, Grafana, etc: IOTstack
+Andreas Spiess:
-[![#295 Raspberry Pi Server based on Docker, with VPN, Dropbox backup, Influx, Grafana, etc: IOTstack](http://img.youtube.com/vi/a6mjt8tWUws/0.jpg)](https://www.youtube.com/watch?v=a6mjt8tWUws)
+* 2023-10-01 Upgrade your Raspberry Pi to a Homelab (instead of a Raspberry Pi 5)
-Andreas Spiess Video #352: Raspberry Pi4 Home Automation Server (incl. Docker, OpenHAB, HASSIO, NextCloud)
+ [![20231001](http://img.youtube.com/vi/xVq_5f0aFlw/0.jpg)](https://www.youtube.com/watch?v=xVq_5f0aFlw)
-[![#352 Raspberry Pi4 Home Automation Server (incl. Docker, OpenHAB, HASSIO, NextCloud)](http://img.youtube.com/vi/KJRMjUzlHI8/0.jpg)](https://www.youtube.com/watch?v=KJRMjUzlHI8)
+* 2022-11-20 #443 I found an Excellent Raspberry Pi Replacement for Home Assistant / IOTstack (incl. Proxmox)
+
+ [![#443](http://img.youtube.com/vi/rXc_zGRYhLo/0.jpg)](https://www.youtube.com/watch?v=rXc_zGRYhLo)
+
+* 2020-11-22 #362 Wireguard and NextCloud on a Raspberry Pi = Marvellous (Docker, IOTstack)
+
+ [![#362](http://img.youtube.com/vi/7Pe-Cv0tnLs/0.jpg)](https://www.youtube.com/watch?v=7Pe-Cv0tnLs)
+
+* 2020-09-13 #352 Raspberry Pi4 Home Automation Server (incl. Docker, OpenHAB, HASSIO, NextCloud)
+
+ [![#352](http://img.youtube.com/vi/KJRMjUzlHI8/0.jpg)](https://www.youtube.com/watch?v=KJRMjUzlHI8)
+
+* 2019-10-27 #295 Raspberry Pi Server based on Docker, with VPN, Dropbox backup, Influx, Grafana, etc: IOTstack
+
+ [![#295](http://img.youtube.com/vi/a6mjt8tWUws/0.jpg)](https://www.youtube.com/watch?v=a6mjt8tWUws)
+
+OneMarcFifty:
+
+* 2021-02-02 Raspberry Pi 4 Home Automation Server with IOTstack
+
+ [![20210202](http://img.youtube.com/vi/5a2qhKMetGU/0.jpg)](https://www.youtube.com/watch?v=5a2qhKMetGU)
### getting started
See [Getting Started](https://sensorsiot.github.io/IOTstack/Getting-Started) in the [IOTstack Wiki](https://sensorsiot.github.io/IOTstack/). It includes:
-* A link to Andreas Spiess videos #295 and #352.
* How to download the project (including constraints you need to observe).
* How to migrate from the older gcgarner/IOTstack repository.
* Running the menu to install Docker and set up your containers.
* Useful Docker commands (start \& stop the stack, manage containers).
* Stack maintenance.
-### significant change to networking
-
-After 2022-01-18 the menu has changed to use Docker networks differently. Users from before this need to do [migration](https://sensorsiot.github.io/IOTstack/Updates/migration-network-change/) in order to add new services. In essence, just re-select all your services using the menu. If not done, docker-compose will give you an error like:
+### reporting issues
-```
-ERROR: Service "influxdb" uses an undefined network "iotstack_nw"
-```
+Please use the [issues](https://github.com/SensorsIot/IOTstack/issues) tab to report issues or make suggestions for new features or containers.
-### contributions
+### submitting pull requests
-Please use the [issues](https://github.com/SensorsIot/IOTstack/issues) tab to report issues.
+Pull Requests are always welcome. Your contribution helps improve the project for everyone. Please see [creating Pull Requests](https://gist.github.com/Paraphraser/818bf54faf5d3b3ed08d16281f32297d) for a guide on the process.
-### Need help? Have a feature suggestion? Discovered a bug?
+### community
We have a Discord server setup for discussions: [IOTstack Discord channel](https://discord.gg/ZpKHnks) if you want to comment on features, suggest new container types, or ask the IOTstack community for help.
-If you use some of the tools in the project please consider donating or contributing on their projects. It doesn't have to be monetary. Reporting bugs and [creating Pull Requests](https://gist.github.com/Paraphraser/818bf54faf5d3b3ed08d16281f32297d) helps improve the projects for everyone.
+If you use some of the tools in the project please consider donating or contributing on their projects. It doesn't have to be monetary.
From 02480fb333a286efc92091d6182220dea3e820d5 Mon Sep 17 00:00:00 2001
From: Phill Kelley <34226495+Paraphraser@users.noreply.github.com>
Date: Tue, 24 Oct 2023 16:41:05 +1100
Subject: [PATCH 4/6] update getting started
Companion changes for #740
Signed-off-by: Phill Kelley <34226495+Paraphraser@users.noreply.github.com>
---
docs/Basic_setup/index.md | 258 ++++++++++++--------------------------
1 file changed, 79 insertions(+), 179 deletions(-)
mode change 100755 => 100644 docs/Basic_setup/index.md
diff --git a/docs/Basic_setup/index.md b/docs/Basic_setup/index.md
old mode 100755
new mode 100644
index 979040ef6..323c83cca
--- a/docs/Basic_setup/index.md
+++ b/docs/Basic_setup/index.md
@@ -1,128 +1,103 @@
# Getting Started
-## Requirements
-
-IOTstack makes the following assumptions:
-
-1. Your hardware is a Raspberry Pi (typically a 3B+ or 4B).
+## About IOTstack { #conventions }
- * The Raspberry Pi Zero W2 has been tested with IOTstack. It works but the 512MB RAM means you should not try to run too many containers concurrently.
- * Users have also [reported success](https://github.com/SensorsIot/IOTstack/issues/375) on Orange Pi Win/Plus.
+IOTstack is not a *system.* It is a set of *conventions* for assembling arbitrary collections of containers into something that has a reasonable chance of working out-of-the-box. The three most important conventions are:
-2. Your Raspberry Pi has a reasonably-recent version of 32-bit or 64-bit Raspberry Pi OS (aka "Raspbian") installed. You can download operating-system images:
+1. If a container needs information to persist across restarts (and most containers do) then the container's *persistent store* will be found at:
- * [Current release](https://www.raspberrypi.com/software/operating-systems/)
- : "Raspberry Pi OS with desktop" is recommended.
- * [Prior releases](http://downloads.raspberrypi.org/raspios_armhf/images/)
- : This offers only "Raspberry Pi OS with desktop" images.
-
-3. Your operating system has been updated:
-
- ``` console
- $ sudo apt update
- $ sudo apt upgrade -y
```
+ ~/IOTstack/volumes/«container»
+ ```
+
+ Most *service definitions* examples found on the web have a scattergun approach to this problem. IOTstack imposes order on this chaos.
+
+2. To the maximum extent possible, network port conflicts have been sorted out in advance.
-4. You are logged-in as the user "pi".
-5. User "pi" has the user ID 1000.
-6. The home directory for user "pi" is `/home/pi/`.
-7. IOTstack is installed at `/home/pi/IOTstack` (with that exact spelling).
-
-If the first three assumptions hold, assumptions four through six are Raspberry Pi defaults on a clean installation. The seventh is what you get if you follow these instructions faithfully.
-
-Please don't read these assumptions as saying that IOTstack will not run on other hardware, other operating systems, or as a different user. It is just that IOTstack gets most of its testing under these conditions. The further you get from these implicit assumptions, the more your mileage may vary.
+ Sometimes this is not possible. For example, Pi-hole and AdGuardHome both offer Domain Name System services. The DNS relies on port 53. You can't have two containers claiming port 53 so the only way to avoid this is to pick *either* Pi-hole *or* AdGuardHome.
+3. Where multiple containers are needed to implement a single user-facing service, the IOTstack service definition will include everything needed. A good example is NextCloud which relies on MariaDB. IOTstack implements MariaDB as a private instance which is only available to NextCloud. This strategy ensures that you are able to run your own separate MariaDB container without any risk of interference with your NextCloud service.
-## New installation
+## Requirements
-### automatic (recommended)
+IOTstack makes the following assumptions:
-1. Install `curl`:
+1. Your hardware is capable of running Debian or one of its derivatives. Examples that are known to work include:
- ``` console
- $ sudo apt install -y curl
- ```
+ - a Raspberry Pi (typically a 3B+ or 4B)
-2. Run the following command:
+ > The Raspberry Pi Zero W2 has been tested with IOTstack. It works but the 512MB RAM means you should not try to run too many containers concurrently.
- ``` console
- $ curl -fsSL https://raw.githubusercontent.com/SensorsIot/IOTstack/master/install.sh | bash
- ```
+ - Orange Pi Win/Plus [see also issue 375](https://github.com/SensorsIot/IOTstack/issues/375)
+ - an Intel-based Mac running macOS plus Parallels with a Debian guest.
+ - an Intel-based platform running Proxmox with a Debian guest.
-3. Run the menu and choose your containers:
+2. Your host or guest system is running a reasonably-recent version of Debian or an operating system which is downstream of Debian in the Linux family tree, such as Raspberry Pi OS (aka "Raspbian") or Ubuntu.
- ``` console
- $ cd ~/IOTstack
- $ ./menu.sh
- ```
+ IOTstack is known to work in 32-bit mode but not all containers have images on DockerHub that support 320bit mode. If you are setting up a new system from scratch, you should choose a 64-bit option.
-4. Bring up your stack:
+ IOTstack was known to work with Buster but it has not been tested recently. Bullseye is known to work but if you are setting up a new system from scratch, you should choose Bookworm.
+
+ Please don't waste your own time trying Linux distributions from outside the Debian family tree. They are unlikely to work.
- ``` console
- $ cd ~/IOTstack
- $ docker-compose up -d
- ```
+3. You are logged-in as the default user (ie not root). In most cases, this is the user with ID=1000 and is what you get by default on either a Raspberry Pi OS or Debian installation.
-### manual
+ This assumption is not really an IOTstack requirement as such. However, many containers assume UID=1000 exists and you are less likely to encounter issues if this assumption holds.
-1. Install `git`:
+Please don't read these assumptions as saying that IOTstack will not run on other hardware, other operating systems, or as a different user. It is just that IOTstack gets most of its testing under these conditions. The further you get from these implicit assumptions, the more your mileage may vary.
- ``` console
- $ sudo apt install -y git
- ```
+## New installation
-2. Clone IOTstack:
+You have two choices:
- * If you want "new menu":
+1. If you have an **existing** system and you want to add IOTstack to it, then the [add-on](#addonInstall) method is your best choice.
+2. If you are setting up a **new** system from scratch, then [PiBuilder](#pibuilderInstall) is probably your best choice. You can, however, also use the [add-on](#addonInstall) method in a green-fields installation.
- ``` console
- $ git clone https://github.com/SensorsIot/IOTstack.git ~/IOTstack
- ```
+### add-on method { #addonInstall }
- * If you prefer "old menu":
+This method assumes an **existing** system rather than a green-fields installation. The script uses the principle of least interference. It only installs the bare minimum of prerequisites and, with the exception of adding some boot time options to your Raspberry Pi (but not any other kind of hardware), makes no attempt to tailor your system.
- ``` console
- $ git clone -b old-menu https://github.com/SensorsIot/IOTstack.git ~/IOTstack
- ```
+To use this method:
-3. Run the menu and choose your containers:
+1. Install `curl`:
``` console
- $ cd ~/IOTstack
- $ ./menu.sh
+ $ sudo apt install -y curl
```
- Note:
-
- * If you are running "old menu" for the first time, you will be guided to "Install Docker". That will end in a reboot, after which you should re-enter the menu and choose your containers.
-
-4. Bring up your stack:
+2. Run the following command:
``` console
- $ cd ~/IOTstack
- $ docker-compose up -d
+ $ curl -fsSL https://raw.githubusercontent.com/SensorsIot/IOTstack/master/install.sh | bash
```
-### scripted – PiBuilder { #scripted }
+The `install.sh` script is *designed* to be run multiple times. If the script discovers a problem, it will explain how to fix that problem and, assuming you follow the instructions, you can safely re-run the script. You can repeat this process until the script completes normally.
+
+### PiBuilder method { #pibuilderInstall }
-If you prefer to automate your installations using scripts, see [PiBuilder](https://github.com/Paraphraser/PiBuilder). Beginning with your choice of Raspberry Pi OS starting point (eg Buster or Bullseye), PiBuilder:
+Compared with the [add-on method](#addonInstall), PiBuilder is far more comprehensive. PiBuilder:
-1. Satisfies all dependencies likely to be needed for IOTstack.
+1. Does everything the [add-on method](#addonInstall) does.
+2. Adds support packages and debugging tools that have proven useful in the IOTstack context.
3. Installs all required system patches (see next section).
-3. Installs Docker and docker-compose.
-4. Clones:
+4. In addition to cloning IOTstack (this repository), PiBuilder also clones:
- * IOTstack (this repository);
* [IOTstackBackup](https://github.com/Paraphraser/IOTstackBackup) which is an alternative to the backup script supplied with IOTstack but does not require your stack to be taken down to perform backups; and
* [IOTstackAliases](https://github.com/Paraphraser/IOTstackAliases) which provides shortcuts for common IOTstack operations.
-After PiBuilder has finished, your system is ready to either:
+5. Performs extra tailoring intended to deliver a rock-solid platform for IOTstack.
-* Run the IOTstack menu to build your first stack; or
-* Restore a backup and bring up your stack.
+PiBuilder does, however, assume a **green fields** system rather than an existing installation. Although the PiBuilder scripts will *probably* work on an existing system, that scenario has never been tested so it's entirely at your own risk.
+
+PiBuilder actually has two specific use-cases:
+
+1. A first-time build of a system to run IOTstack; and
+2. The ability to create your own customised version of PiBuilder so that you can quickly rebuild your Raspberry Pi or Proxmox guest after a disaster. Combined with IOTstackBackup, you can go from bare metal to a running system with data restored in about half an hour.
## Required system patches
-Unless you know what you are doing, assume these are needed.
+You can skip this section if you used [PiBuilder](https://github.com/Paraphraser/PiBuilder) to construct your system. That's because PiBuilder installs all necessary patches automatically.
+
+If you used the [add-on method](#addonInstall), you should consider applying these patches by hand. Unless you know that a patch is **not** required, assume that it is needed.
### patch 1 – restrict DHCP
@@ -138,7 +113,7 @@ See [Issue 219](https://github.com/SensorsIot/IOTstack/issues/219) and [Issue 25
### patch 2 – update libseccomp2
-This patch is **ONLY** for Raspbian Buster. Do **NOT** install this patch if you are running Raspbian Bullseye.
+This patch is **ONLY** for Raspbian Buster. Do **NOT** install this patch if you are running Raspbian Bullseye or Bookworm.
1. check your OS release
@@ -180,32 +155,19 @@ $ echo $(cat /boot/cmdline.txt) cgroup_memory=1 cgroup_enable=memory | sudo tee
$ sudo reboot
```
-## the IOTstack menu
+## the IOTstack menu { #iotstackMenu}
-The menu is used to install Docker and then build the `docker-compose.yml` file which is necessary for starting the stack.
-
-> The menu is only an aid. It is a good idea to learn the `docker` and `docker-compose` commands if you plan on using Docker in the long run.
-
-### menu item: Install Docker (old menu only)
-
-Please do **not** try to install `docker` and `docker-compose` via `sudo apt install`. There's more to it than that. Docker needs to be installed by `menu.sh`. The menu will prompt you to install docker if it detects that docker is not already installed. You can manually install it from within the `Native Installs` menu:
-
-``` console
-$ cd ~/IOTstack
-$ ./menu.sh
-Select "Native Installs"
-Select "Install Docker and Docker-Compose"
-```
+The menu is used to construct your `docker-compose.yml` file. That file is read by `docker-compose` which issues the instructions necessary for starting your stack.
-Follow the prompts. The process finishes by asking you to reboot. Do that!
+The menu is a great way to get started quickly but it is only an aid. It is a good idea to learn the various `docker` and `docker-compose` commands so you can use them outside the menu. It is also a good idea to study the `docker-compose.yml` generated by the menu to see how everything is put together. You will gain a lot of flexibility if you learn how to add containers by hand.
-Note:
+In essence, the menu is a concatenation tool which appends *service definitions* that exist inside the hidden `~/IOTstack/.templates` folder to your `docker-compose.yml`.
-* New menu (master branch) automates this step.
+Once you understand what the menu does (and, more importantly, what it doesn't do), you will realise that the real power of IOTstack lies not in its menu system but resides in its [conventions](#conventions).
-### menu item: Build Stack
+### menu item: Build Stack { #buildStack}
-`docker-compose` uses a `docker-compose.yml` file to configure all your services. The `docker-compose.yml` file is created by the menu:
+To create your first `docker-compose.yml`:
``` console
$ cd ~/IOTstack
@@ -233,7 +195,7 @@ The first time you run `up` the stack docker will download all the images from D
Some containers also need to be built locally. Node-RED is an example. Depending on the Node-RED nodes you select, building the image can also take a very long time. This is especially true if you select the SQLite node.
-Be patient (and ignore the huge number of warnings).
+Be patient (and, if you selected the SQLite node, ignore the huge number of warnings).
### menu item: Docker commands
@@ -243,83 +205,6 @@ The commands in this menu execute shell scripts in the root of the project.
The old and new menus differ in the options they offer. You should come back and explore them once your stack is built and running.
-## switching menus
-
-At the time of writing, IOTstack supports three menus:
-
-* "Old Menu" on the `old-menu` branch. This was inherited from [gcgarner/IOTstack](https://github.com/gcgarner/IOTstack).
-* "New Menu" on the `master` branch. This is the current menu.
-* "New New Menu" on the `experimental` branch. This is under development.
-
-With a few precautions, you can switch between git branches as much as you like without breaking anything. The basic check you should perform is:
-
-``` console
-$ cd ~/IOTstack
-$ git status
-```
-
-Check the results to see if any files are marked as "modified". For example:
-
-``` output
-modified: .templates/mosquitto/Dockerfile
-```
-
-Key point:
-
-* Files marked "untracked" do not matter. You only need to check for "modified" files because those have the potential to stop you from switching branches cleanly.
-
-The way to avoid potential problems is to move any modified files to one side and restore the unmodified original. For example:
-
-``` console
-$ mv .templates/mosquitto/Dockerfile .templates/mosquitto/Dockerfile.save
-$ git checkout -- .templates/mosquitto/Dockerfile
-```
-
-When `git status` reports no more "modified" files, it is safe to switch your branch.
-
-### current menu (master branch)
-
-``` console
-$ cd ~/IOTstack/
-$ git pull
-$ git checkout master
-$ ./menu.sh
-```
-
-### old menu (old-menu branch)
-
-``` console
-$ cd ~/IOTstack/
-$ git pull
-$ git checkout old-menu
-$ ./menu.sh
-```
-
-### experimental branch
-
-Switch to the experimental branch to try the latest and greatest features.
-
-``` console
-$ cd ~/IOTstack/
-$ git pull
-$ git checkout experimental
-$ ./menu.sh
-```
-
-Notes:
-
-* Please make sure you have a good backup before you start.
-* The experimental branch may be broken, or may break your setup.
-* Please report any issues.
-* Remember:
-
- * you can switch git branches as much as you like without breaking anything.
- * simply launching the menu (any version) won't change anything providing you exit before letting the menu complete.
- * running the menu *to completion* **will** change your docker-compose.yml and supporting structures in `~/IOTstack/services`.
- * running `docker-compose up -d` will change your running containers.
-
-* The way back is to take down your stack, restore a backup, and bring up your stack again.
-
## useful commands: docker & docker-compose
Handy rules:
@@ -368,6 +253,21 @@ Logging limits were added to prevent Docker using up lots of RAM if log2ram is e
You can also turn logging off or set it to use another option for any service by using the IOTstack `docker-compose-override.yml` file mentioned at [IOTstack/Custom](Custom.md).
+Another approach is to change `daemon.json` to be like this:
+
+``` json
+{
+ "log-driver": "local",
+ "log-opts": {
+ "max-size": "1m"
+ }
+}
+```
+
+The `local` driver is specifically designed to prevent disk exhaustion. Limiting log size to one megabyte also helps, particularly if you only have a limited amount of storage.
+
+If you are familiar with system logging where it is best practice to retain logs spanning days or weeks, you may feel that one megabyte is unreasonably small. However, before you rush to increase the limit, consider that each container is the equivalent of a small computer dedicated to a single task. By their very nature, containers tend to either work as expected or fail outright. That, in turn, means that it is usually only recent container logs showing failures as they happen that are actually useful for diagnosing problems.
+
### starting an individual container
To start a particular container:
From 8371bad67053fffc2a221dfdf7130bfeecc6f685 Mon Sep 17 00:00:00 2001
From: Phill Kelley <34226495+Paraphraser@users.noreply.github.com>
Date: Thu, 26 Oct 2023 17:42:18 +1100
Subject: [PATCH 5/6] doc updates associated with #742 and #743
Signed-off-by: Phill Kelley <34226495+Paraphraser@users.noreply.github.com>
---
docs/Containers/NextCloud.md | 91 +++++-------------
.../images/nextcloud-malformedurl.png | Bin 47284 -> 0 bytes
2 files changed, 22 insertions(+), 69 deletions(-)
delete mode 100644 docs/Containers/images/nextcloud-malformedurl.png
diff --git a/docs/Containers/NextCloud.md b/docs/Containers/NextCloud.md
index 8b4f4eed9..71893ed64 100755
--- a/docs/Containers/NextCloud.md
+++ b/docs/Containers/NextCloud.md
@@ -10,12 +10,14 @@ nextcloud:
image: nextcloud
restart: unless-stopped
environment:
+ - TZ=${TZ:-Etc/UTC}
- MYSQL_HOST=nextcloud_db
- - MYSQL_PASSWORD=«user_password»
+ - MYSQL_PASSWORD=%randomMySqlPassword%
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
ports:
- "9321:80"
+ - "9343:443"
volumes:
- ./volumes/nextcloud/html:/var/www/html
depends_on:
@@ -29,11 +31,11 @@ nextcloud_db:
build: ./.templates/mariadb/.
restart: unless-stopped
environment:
- - TZ=Etc/UTC
+ - TZ=${TZ:-Etc/UTC}
- PUID=1000
- PGID=1000
- - MYSQL_ROOT_PASSWORD=«root_password»
- - MYSQL_PASSWORD=«user_password»
+ - MYSQL_ROOT_PASSWORD=%randomPassword%
+ - MYSQL_PASSWORD=%randomMySqlPassword%
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
volumes:
@@ -106,86 +108,33 @@ The passwords need to be set before you bring up the Nextcloud service for the f
$ docker logs nextcloud
```
-6. If you want to be sure Nextcloud gets set up correctly, it is best to perform the remaining steps from a **different** computer.
+6. On a computer that is **not** the device running Nextcloud, launch a browser and point to the device running Nextcloud using your chosen connection method. Examples:
- That means you need to decide how that **other** computer will refer to your Raspberry Pi running Nextcloud. Your choices are:
-
- * the IP address of your Raspberry Pi – eg `192.168.203.200`
- * your Raspberry Pi's fully-qualified domain name – eg `myrpi.mydomain.com`
- * your Raspberry Pi's host name – eg `myrpi`
-
- Key points:
-
- * You **can't** use a multicast domain name (eg `myrpi.local`). An mDNS name will not work until Nextcloud has been initialised!
- * Once you have picked a connection method, **STICK TO IT**.
- * You are only stuck with this restriction until Nextcloud has been initialised. You **can** (and should) fix it later by completing the steps in ["Access through untrusted domain"](#untrustedDomain).
-
-7. On a computer that is **not** the Raspberry Pi running Nextcloud, launch a browser and point to the Raspberry Pi running Nextcloud using your chosen connection method. Examples:
-
- - If you are using an IP address:
-
- ```
- http://192.168.203.200:9321
- ```
-
- - If you are using a domain name:
-
- ```
- http://myrpi.mydomain.com:9321
- ```
-
- - If you are using a host name in `/etc/hosts`:
-
- ```
- http://myrpi:9321
- ```
+ ```
+ http://192.168.203.200:9321
+ http://myrpi.mydomain.com:9321
+ http://myrpi.local:9321
+ http://myrpi:9321
+ ```
The expected result is:
![Create Administrator Account](./images/nextcloud-createadminaccount.png)
-8. Create an administrator account and then click "Install".
-
-9. There is a long delay. In most cases, the "Recommended apps" screen appears and you can ignore the instructions in this step. However, if your browser returns a "Not Found" error like the following:
-
- ![Mal-formed URL](./images/nextcloud-malformedurl.png)
-
- then you should:
-
- * Examine the contents of your browser's URL bar. If you see this pattern:
-
- ```
- http://localhost/index.php/core/apps/recommended
- ```
-
- * Edit the URL to replace `localhost` with what it *should* be, which will be **one** of the following patterns, depending on which method you chose to access Nextcloud:
-
- * `http://192.168.203.200:9321/index.php/core/apps/recommended`
- * `http://myrpi.mydomain.com:9321/index.php/core/apps/recommended`
- * `http://myrpi:9321/index.php/core/apps/recommended`
-
- Note:
-
- * This seems to be the only time Nextcloud misbehaves and forces `localhost` into a URL.
+7. Create an administrator account and then click "Install" and wait for the loading to complete.
-10. The "Recommended apps" screen appears. Click "Install recommended apps". A spinner moves down the list of apps as they are loaded:
-
- ![Recommended Apps](./images/nextcloud-recommendedapps.png)
-
- Wait for the loading to complete.
-
-11. Eventually, the dashboard will appear. Then the dashboard will be obscured by the "Nextcloud Hub" floating window:
+8. Eventually, the dashboard will appear. Then the dashboard will be obscured by the "Nextcloud Hub" floating window which you can dismiss:
![Post-initialisation](./images/nextcloud-postinitialisation.png)
- Keep clicking on the right-arrow button until you reach the last screen, then click "Start using Nextcloud".
-
-12. Congratulations. Your IOTstack implementation of Nextcloud is ready to roll:
+9. Congratulations. Your IOTstack implementation of Nextcloud is ready to roll:
![Dashboard](./images/nextcloud-dashboard.png)
## "Access through untrusted domain" { #untrustedDomain }
+> The information in this section *may* be out of date. Recent tests suggest it is no longer necessary to edit the `trusted_domains` list in `config.php`. This section is being left here so you will know what to do if you encounter the problem.
+
During Nextcloud initialisation you had to choose between an IP address, a domain name or a host name. Now that Nextcloud is running, you have the opportunity to expand your connection options.
> If you are reading this because you are staring at an "access through untrusted domain" message then you have come to the right place.
@@ -255,6 +204,8 @@ See also:
### Using a DNS alias for your Nextcloud service { #dnsAlias }
+> The information in this section *may* be out of date. Recent tests suggest it is no longer necessary to add a `hostname` clause to your `docker-compose.yml` to silence warnings when using DNS aliases to reach your NextCloud service. This section is being left here so you will know what to do if you encounter the problem.
+
The examples above include using a DNS alias (a CNAME record) for your Nextcloud service. If you decide to do that, you may see this warning in the log:
```
@@ -271,6 +222,8 @@ You can silence the warning by editing the Nextcloud service definition in `dock
Nextcloud traffic is not encrypted. Do **not** expose it to the web by opening a port on your home router. Instead, use a VPN like Wireguard to provide secure access to your home network, and let your remote clients access Nextcloud over the VPN tunnel.
+The IOTstack service definition for NextCloud reserves port 9343 for HTTPS access but leaves it as an exercise for the reader to figure out how to make it work. You may get some guidance [here](https://youtu.be/qlcVx-k-02E?si=qtVNFAvSB8w202Jh).
+
## Container health check { #healthCheck }
A script , or "agent", to assess the health of the MariaDB container has been added to the *local image* via the *Dockerfile*. In other words, the script is specific to IOTstack.
diff --git a/docs/Containers/images/nextcloud-malformedurl.png b/docs/Containers/images/nextcloud-malformedurl.png
deleted file mode 100644
index 61d8e819392934806f83c43f839b9467b3241233..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 47284
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