#!/bin/bash
# ==== CONFIGURATION ====
NEXTCLOUD_PATH="/var/www/html"
DATA_PATH="/var/www/html/data"
BACKUP_PATH="/var/backups/nextcloud"
DB_USER="nextcloud"
DB_PASS="dbpassword"
DB_NAME="nextcloud"
FTP_HOST="yourftphost.com"
FTP_USER="yourftpuser"
FTP_PASS="yourftppassword"
FTP_DIR="/path/to/save/file"
DATE=$(date +"%Y-%m-%d_%H-%M")
ARCHIVE_NAME="nextcloud-backup-$DATE.tar.gz"
MAX_LOCAL_BACKUPS=3
# ==== START BACKUP ====
echo "Starting streamed Nextcloud backup..."
mkdir -p "$BACKUP_PATH"
# Export database (small file)
DB_DUMP="/tmp/db_$DATE.sql"
mysqldump --no-tablespaces -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" > "$DB_DUMP"
# === Stream tar directly to FTP ===
echo "Creating and streaming archive directly to FTP..."
tar -czf - \
--exclude="$DATA_PATH/appdata_*/preview" \
--exclude="$NEXTCLOUD_PATH/updater-*" \
--exclude="$NEXTCLOUD_PATH/data/tmp" \
-C / \
"${NEXTCLOUD_PATH#/}" \
"${DATA_PATH#/}" \
"$DB_DUMP" \
| curl --ftp-pasv -T - "ftp://$FTP_HOST$FTP_DIR/$ARCHIVE_NAME" --user "$FTP_USER:$FTP_PASS"
# Remove temp database dump
rm -f "$DB_DUMP"
# Optional: keep a few local backups (not needed for streamed uploads)
echo "Cleaning up old local backups..."
cd "$BACKUP_PATH" || exit
ls -1t nextcloud-backup-*.tar.gz 2>/dev/null | tail -n +$((MAX_LOCAL_BACKUPS + 1)) | xargs -r rm -f --
echo "Backup complete: streamed directly to FTP as $ARCHIVE_NAME"Author Archives: Unique Technologies
Setting up a NAS on a Raspberry Pi 5
# nano /boot/firmware/config.txt
kernel=kernel8.img
# sudo apt update
# sudo apt install snapd
# sudo snap install snapd
# sudo snap install nextcloud
# sudo /snap/bin/nextcloud.enable-https lets-encrypt
# sudo /snap/bin/nextcloud.occ maintenance:repair --include-expensive
# sudo /snap/bin/nextcloud.occ background:cron
# apt install syncthing
# systemctl enable syncthing@pi-nas.service
# systemctl start syncthing@pi-nas.service
# nano /usr/lib/systemd/system/syncthing@.service
Group=users
UMask=0002
# apt install proftpd
# nano /etc/proftpd/proftpd.conf
# Force all uploads to be owned by pi-nas user
<IfModule mod_ifsession.c>
<IfUser user1>
<Directory /volume1/user1>
Umask 022
AllowOverwrite on
UserOwner pi-nas
GroupOwner users
</Directory>
</IfUser>
<IfUser user2>
<Directory /volume1/user2>
Umask 022
AllowOverwrite on
UserOwner pi-nas
GroupOwner users
</Directory>
</IfUser>
</IfModule>Setting Up Radicale and Infcloud in Debian 13 (Trixie)
# apt update # apt install git python3-pip python3-venv # useradd -r -m -d /var/lib/radicale -s /bin/bash radicale # mkdir /etc/radicale # nano /etc/radicale/radicale.conf [server] # Bind to all IP addresses (0.0.0.0) instead of just localhost hosts = 0.0.0.0:5232 [auth] type = htpasswd htpasswd_filename = /etc/radicale/users htpasswd_encryption = bcrypt [storage] filesystem_folder = /var/lib/radicale/collections [web] type = radicale_infcloud # htpasswd -c -B /etc/radicale/users yourusername # htpasswd -B /etc/radicale/users anotheruser # ufw allow 5232/tcp # ufw reload # su radicale $ cd ~ $ python3 -m venv venv $ source venv/bin/activate $ pip install radicale bcrypt git+https://github.com/Unrud/RadicaleInfCloud.git $ radicale --config /etc/radicale/radicale.conf http://your-server-ip:5232/ $ exit # nano /etc/systemd/system/radicale.service [Unit] Description=Radicale CalDAV and CardDAV Server After=network.target [Service] User=radicale Group=radicale ExecStart=/var/lib/radicale/venv/bin/radicale --config /etc/radicale/radicale.conf WorkingDirectory=/var/lib/radicale Restart=on-failure LimitNOFILE=4096 [Install] WantedBy=multi-user.target # systemctl daemon-reload # systemctl enable radicale # systemctl start radicale # systemctl status radicale # apt install apache2 certbot python3-certbot-apache # nano /etc/apache2/sites-available/radicale.conf <VirtualHost *:80> ServerName your_domain.com ProxyPass / http://localhost:5232/ ProxyPassReverse / http://localhost:5232/ </VirtualHost> # ufw allow 80/tcp # ufw allow 443/tcp # ufw reload # certbot --apache -d your_domain.com https://your_domain.com # sudo systemctl status certbot.timer # sudo certbot renew --dry-run
Setting Up Webmin/Fail2ban/Freeswitch in Debian
Webmin Setup
The simplest and best way to get Webmin is to use automatic webmin-setup-repo.sh script to configure repositories on your RHEL or Debian derivative systems. It can be done in two easy steps:
$curl -o webmin-setup-repo.sh https://raw.githubusercontent.com/webmin/webmin/master/webmin-setup-repo.sh
sudo sh webmin-setup-repo.sh
This script will automatically setup our repository and install our GPG keys on your system, and provide webmin package for installation and easy upgrades in the future.
Install
If Webmin repository was setup using our webmin-setup-repo.sh as described above then Webmin can be installed as easy as:
$ sudo apt-get install webmin --install-recommendsAccess
Open ports for both Webmin and Freeswitch.
$ ufw allow 10000/tcp
$ ufw allow 3478:3479/udp
$ ufw allow 5060
$ ufw allow 5080
$ ufw allow 8021/tcp
$ ufw allow 16384:32768/udpAfter successful Webmin installation, you can access its interface by entering https://<Your-Server-IP>:10000 in your browser..
Freeswitch Setup
$curl -sSL https://freeswitch.org/fsget | bash -s [Personal Access Token] release install
$ sudo apt install freeswitch-mod-flite fail2banFail2ban Setup
Fail2ban’s jail.conf file contains a standard configuration for FreeSWITCH.
From Standard jail.conf
[shd] <-- Make sure that this section is empty.
[freeswitch]
enabled = true
port = 5060,5061
action_ = %(default/action_)s[name=%(__name__)s-tcp, protocol="tcp"]
%(default/action_)s[name=%(__name__)s-udp, protocol="udp"]
logpath = /var/log/freeswitch/freeswitch.log
filter = freeswitch-ip/etc/fail2ban/filter.d/freeswitch-ip.conf
# Fail2Ban configuration file
[Definition]
failregex = \[WARNING\] sofia_reg.c:\d+ Can't find user \[.*@\d+.\d+.\d+.\d+\] from <HOST>
ignoreregex =
Add the following line to the [DEFAULT] section of /etc/fail2ban/paths-debian.conf:
sshd_backend = systemdIn Webmin, go to Networking > Fail2ban Intrusion Detector and click on Filter Action Jails. Click on Freeswitch in the list and change ‘Check for log file updates using‘ to systemd and click on the ‘Save’ button.
Usage
To check the status of fail2ban:
$ systemctl status fail2ban.serviceTo check the IP addresses that were blocked:
$ fail2ban-client bannedResources
https://developer.signalwire.com/freeswitch/FreeSWITCH-Explained/Security/Fail2Ban_1049236/
https://github.com/fail2ban/fail2ban/issues/3567
https://stackoverflow.com/questions/3561289/what-ports-does-freeswitch-need-open
Setting Up a Syncthing System Service
Create the user who should run the service, or choose an existing one.(Skip if your distribution package already installs these files, see above.) From git location copy the syncthing@.service file into the load path of the system instance. On Debian 12, the path of the file is ‘/usr/lib/systemd/system’. I also added the following lines to the [Service] section of the file:
Group=users
UMask=0002The umask only works when ‘Ignore Permissions’ is enabled for the folder. Enable and start the service. Replace “myuser” with the actual Syncthing user after the @:
$ sudo systemctl enable syncthing@myuser.service
$ sudo systemctl start syncthing@myuser.serviceReference
Setting Up IMAPdump in Debian
IMAPdump, requires OpenSSL to be installed. Install it using the following command:
$ sudo apt install opensslThe IO::Socket::SSL Perl module is also required. First, install using the following command:
$ sudo perl -MCPAN -e shellThen enter the following command from within the cpan shell:
cpan[1]> install IO::Socket::SSLNow IMAPdump should run without errors. You can download it from https://github.com/andrewnimmo/rick-sanders-imap-tools.
Install Nextcloud on a Raspberry Pi 5 using Snap
This article assumes that you have all of your files in the /volume1 folder. In order to be able to access these files from within Nextcloud’s External Storage app, you will need to add the following line in /etc/fstab:
/volume1 /mnt/volume1 none bindAlso, until Redis packages are made to take advantage of the larger page size of the Raspberry Pi 5, we will have to add the following line to /boot/firmware/config.txt:
kernel=kernel8.imgNow install nextcloud using the following commands:
$ sudo apt install snapd
$ sudo snap install snapd
$ sudo snap install nextcloudYou should now be able to access the Nextcloud installer by entering the Pi’s IP address in a browser on the same network. If you want to install an SSL certificate then use the following command:
$ sudo /snap/bin/nextcloud.enable-https lets-encryptYou will be asked to provide an email address and the domain name to be used. You will need to add the following lines to the config.php file for Nextcloud. This file should be located in /var/snap/nextcloud/current/nextcloud/config/config.php.
'overwritehost' => 'example.com',
'overwriteprotocol' => 'https',
'trusted_domains' =>
array (
0 => 'example.com',
),Now you should be able to access Nextcloud using your domain name. If you need to run the OCC command, use the following:
$ sudo /snap/bin/nextcloud.occ COMMANDReferences
https://help.nextcloud.com/t/redis-crashing-on-startup-after-swapping-rpi4-8gb-with-rpi5-8gb/182242
Adding external storage in Nextcloud fails with “wrong password”
If you are having trouble with adding external storage mounts in Nextcloud, you can do this:
$ sudo -u www-data php occ files_external:list
You can see the bad external mounts and delete it with:
$ sudo -u www-data php occ files_external:delete X
Then, you can re-create good ones by using this command:
$ sudo -u www-data php occ files_external:create Blabla ‘smb’ password::password -c host=X.X.X.X -c share=X -c root=/X -c domain=workgroup -c user=X -c password=X
You can add applicable users to the mount using this command:
$ sudo -u www-data php occ files_external:applicable --add-user=X
Replace: X with Yours.
Reference
Setting Up Nextcloud in a Docker Container
Use the following to set up Nextcloud in a Docker Container:
version: '3.9'
services:
mariadb:
image: mariadb:latest
container_name: Nextcloud-DB
security_opt:
- no-new-privileges:true
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW --innodb-read-only-compressed=OFF
environment:
- PUID=1000
- PGID=1000
- MYSQL_ROOT_PASSWORD=[PASSWORD]
- MYSQL_PASSWORD=[PASSWORD]
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- TZ=America/Los_Angeles
volumes:
- /volume1/docker/nextcloud/mariadb:/config
restart: on-failure:5
redis:
image: redis:latest
container_name: Nextcloud-REDIS
hostname: nextcloudredis
healthcheck:
test: ["CMD-SHELL", "redis-cli ping || exit 1"]
environment:
- PUID=1000
- PGID=1000
- TZ=America/Los_Angeles
volumes:
- /volume1/docker/nextcloud/redis:/data:rw
restart: on-failure:5
nextcloud:
image: nextcloud:latest
container_name: Nextcloud
ports:
- 9333:80
depends_on:
mariadb:
condition: service_started
redis:
condition: service_healthy
healthcheck:
test: curl -f http://localhost:80/ || exit 1
environment:
- REDIS_HOST=nextcloudredis
- NEXTCLOUD_TRUSTED_DOMAINS=[DOMAIN] 10.0.1.9
- TRUSTED_PROXIES=[DOMAIN] 10.0.1.9
- OVERWRITEHOST=[DOMAIN]
- OVERWRITEPROTOCOL=https
- MYSQL_PASSWORD=[PASSWORD]
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_HOST=mariadb
volumes:
- /volume1/docker/nextcloud/html:/var/www/html:rw
- /volume1/docker/nextcloud/custom_apps:/var/www/html/custom_apps:rw
- /volume1/docker/nextcloud/config:/var/www/html/config:rw
- /volume1/docker/nextcloud/data:/var/www/html/data:rw
- /volume1/docker/nextcloud/themes:/var/www/html/themes:rw
restart: on-failure:5
cron:
image: nextcloud:apache
container_name: Nextcloud-CRON
restart: always
volumes:
- /volume1/docker/nextcloud/config:/var/www/html/config:rw
- /volume1/docker/nextcloud/html:/var/www/html:rw
- /volume1/docker/nextcloud/custom_apps:/var/www/html/custom_apps:rw
- /volume1/docker/nextcloud/data:/var/www/html/data:rw
entrypoint: /cron.sh
depends_on:
mariadb:
condition: service_started
redis:
condition: service_started
proxy:
image: 'jc21/nginx-proxy-manager:latest'
container_name: Nextcloud-PROXY
restart: unless-stopped
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- /volume1/docker/nextcloud/proxy/data:/data
- /volume1/docker/nextcloud/proxy/letsencrypt:/etc/letsencryptSource
https://github.com/docker/awesome-compose/tree/master/nextcloud-redis-mariadb
Change Boot Order to USB Raspberry Pi 5 (w/NVME)
I have my raspberry pi 5 hooked up to an nvme via pcie. When I pull up raspi-config the only options are to boot nvme first or sd first. However I need an option to boot usb first followed by nvme. The case I’m using doesn’t provide access to the micro sd card slot.
I’ve tried finding the setting in raspi-config, but no luck.
I’ve tried changing the boot order manually by editing eeprom and this worked:
$ sudo rpi-eeprom-config --edit
BOOT_UART=1 POWER_OFF_ON_HALT=0 BOOT_ORDER=0xf164
Reference