Add compose/nginx/env changes for Talk HPB + notify_push integration, and document deployment + hardening commands in README. Co-Authored-By: Oz <oz-agent@warp.dev>
298 lines
10 KiB
Markdown
298 lines
10 KiB
Markdown
# Nextcloud on Ubuntu via Docker for nxt.bhatfamily.in
|
|
This repository deploys Nextcloud behind Nginx using Docker Compose.
|
|
|
|
Exposed ports:
|
|
- HTTP: `8082`
|
|
- HTTPS: `8446`
|
|
|
|
Target hostname:
|
|
- `nxt.bhatfamily.in`
|
|
|
|
## What changed
|
|
The stack now includes:
|
|
- Fixed Nginx mount path (`nginx/nginx.conf` mapped correctly)
|
|
- Fixed MariaDB command (`mariadbd`)
|
|
- Nginx reverse proxy mode for `nextcloud:apache` (no FastCGI mismatch)
|
|
- Production TLS provisioning using Let's Encrypt DNS-01 with Cloudflare
|
|
- Automated TLS renewal job support (cron)
|
|
- Nextcloud app startup fixes for Apache `ServerName` and writable Fontconfig cache
|
|
- Persistent web-updater enablement (`upgrade-disable-web.config.php` forced to `false`)
|
|
- Reverse-proxy trust configuration in Nextcloud (`trusted_proxies`, `forwarded_for_headers`)
|
|
- Nginx hardening (`server_tokens off`, stronger HSTS, hide `X-Powered-By`, TLS session hardening)
|
|
- Brute-force protection explicitly enabled and maintenance window configured
|
|
- Scripted Nextcloud Hub upgrade workflow: `scripts/update-nextcloud-hub.sh`
|
|
- Automated Hub update scheduler: `scripts/setup-hub-update-cron.sh`
|
|
- Redis service for transactional file locking and distributed cache
|
|
- Floating app image tag enabled: `nextcloud:apache` (major upgrades supported with staged path)
|
|
- Setup warning remediation integrated (missing indices, mimetype migrations, log-noise cleanup)
|
|
- Nextcloud Talk high-performance backend service (`talk-hpb`) with signaling endpoint
|
|
- Nextcloud desktop client push via `notify_push` app and `notify-push` service
|
|
|
|
## Current baseline (Apr 2026)
|
|
- App image: `nextcloud:apache`
|
|
- DB image: `mariadb:11.4`
|
|
- Cache/locking: `redis:7-alpine`
|
|
- Nextcloud version at last validation: `33.0.2`
|
|
- Talk HPB: `ghcr.io/nextcloud-releases/aio-talk:latest` via `/standalone-signaling/`
|
|
- Client push: `notify_push` app + `nextcloud-notify-push` service via `/push/`
|
|
|
|
## Prerequisites
|
|
- Ubuntu host with Docker + Docker Compose plugin (or `docker-compose`)
|
|
- Domain `nxt.bhatfamily.in` in Cloudflare DNS
|
|
- DNS A record for `nxt` pointing to your server public IP (DNS-only)
|
|
- Router/firewall forwarding for ports `8082` and `8446`
|
|
|
|
## Initial setup
|
|
1. Create runtime env file:
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
2. Edit `.env` with strong values.
|
|
3. Start stack with bootstrap TLS:
|
|
```bash
|
|
./scripts/install.sh
|
|
```
|
|
4. Validate:
|
|
```bash
|
|
./scripts/test.sh
|
|
```
|
|
|
|
## Enable web updater (one-time verification)
|
|
Web updater is enabled by design for this deployment.
|
|
|
|
Check values:
|
|
```bash
|
|
docker exec --user www-data nextcloud-app php occ config:list system | grep -E "upgrade.disable-web|updater.release.channel"
|
|
```
|
|
|
|
Expected:
|
|
- `upgrade.disable-web: false`
|
|
- `updater.release.channel: stable`
|
|
|
|
## Update Nextcloud Hub (scripted)
|
|
Use the upgrade helper script to pull images, apply upgrades, run repairs, and validate endpoints.
|
|
|
|
Run update:
|
|
```bash
|
|
./scripts/update-nextcloud-hub.sh
|
|
```
|
|
|
|
Optional flags:
|
|
- Skip app marketplace updates:
|
|
```bash
|
|
RUN_APP_UPDATES=0 ./scripts/update-nextcloud-hub.sh
|
|
```
|
|
- Skip expensive repairs/mimetype migration pass:
|
|
```bash
|
|
RUN_EXPENSIVE_REPAIR=0 ./scripts/update-nextcloud-hub.sh
|
|
```
|
|
- Require strict TLS validation during smoke tests (no `-k`):
|
|
```bash
|
|
STRICT_TLS=1 ./scripts/update-nextcloud-hub.sh
|
|
```
|
|
|
|
What the script does:
|
|
- pulls latest `db`, `app`, and `web` images
|
|
- recreates services and restarts `web` to refresh upstream resolution
|
|
- ensures web updater is enabled and release channel is configured
|
|
- ensures maintenance mode is off before `occ upgrade`
|
|
- runs `occ upgrade`
|
|
- runs `occ app:update --all` (unless disabled)
|
|
- runs schema and repair commands (`db:add-missing-*`, `maintenance:repair`)
|
|
- optionally runs `maintenance:repair --include-expensive`
|
|
- runs `occ status`, `occ setupchecks`, and `scripts/test.sh`
|
|
|
|
### Important: major upgrades are one-at-a-time
|
|
Nextcloud only supports upgrading one major version at a time.
|
|
|
|
If the floating `nextcloud:apache` tag is more than one major ahead of your installed version, do staged upgrades first, for example:
|
|
1. `nextcloud:31-apache` → run updater script
|
|
2. `nextcloud:32-apache` → run updater script
|
|
3. `nextcloud:33-apache` → run updater script
|
|
4. switch back to `nextcloud:apache`
|
|
|
|
## Automate Hub updates (cron)
|
|
Install/update a weekly cron job (default: Sunday 02:30):
|
|
```bash
|
|
./scripts/setup-hub-update-cron.sh
|
|
```
|
|
|
|
Optional custom schedule:
|
|
```bash
|
|
HUB_UPDATE_CRON_SCHEDULE="15 2 * * 6" ./scripts/setup-hub-update-cron.sh
|
|
```
|
|
|
|
This setup script will:
|
|
- create/update `.hub-update.env` (local only, not committed)
|
|
- install/refresh cron entry for `scripts/update-nextcloud-hub.sh`
|
|
- write logs to `logs/hub-update.log`
|
|
|
|
Defaults tracked in `.hub-update.env.example`:
|
|
- `RUN_APP_UPDATES=1`
|
|
- `RUN_EXPENSIVE_REPAIR=1`
|
|
- `STRICT_TLS=0`
|
|
- `ENABLE_WEB_UPDATER=1`
|
|
- `UPDATER_RELEASE_CHANNEL=stable`
|
|
|
|
## Setup warning remediation notes
|
|
The following warning-focused fixes are now part of the deployed configuration:
|
|
- **Transactional File Locking**: Redis-backed locking enabled (`memcache.locking=Redis`)
|
|
- **Mimetype migrations**: addressed via `maintenance:repair --include-expensive`
|
|
- **Missing optional indices**: addressed via `occ db:add-missing-indices`
|
|
- **AppAPI deploy daemon errors**: `app_api` disabled (not used in this deployment)
|
|
- **Internet connectivity check log spam**: `has_internet_connection=false` set intentionally for this environment
|
|
|
|
If you want AppAPI external apps later:
|
|
- re-enable app: `docker exec --user www-data nextcloud-app php occ app:enable app_api`
|
|
- configure a reachable deploy daemon from Settings > AppAPI
|
|
|
|
## Deploy Talk HPB and client push
|
|
This deployment includes Talk HPB and desktop client push support in Docker Compose.
|
|
|
|
Required secrets in `.env` (already templated in `.env.example`):
|
|
- `TALK_TURN_SECRET`
|
|
- `TALK_SIGNALING_SECRET`
|
|
- `TALK_INTERNAL_SECRET`
|
|
|
|
1. Start/update services:
|
|
```bash
|
|
docker compose up -d app talk-hpb notify-push web
|
|
```
|
|
|
|
2. Configure Talk signaling/STUN/TURN in Nextcloud:
|
|
```bash
|
|
set -a; source .env; set +a
|
|
docker exec --user www-data nextcloud-app php occ talk:signaling:add --verify https://nxt.bhatfamily.in:8446/standalone-signaling "$TALK_SIGNALING_SECRET"
|
|
docker exec --user www-data nextcloud-app php occ talk:stun:add nxt.bhatfamily.in:3478
|
|
docker exec --user www-data nextcloud-app php occ talk:turn:add --secret="$TALK_TURN_SECRET" turn nxt.bhatfamily.in:3478 udp,tcp
|
|
```
|
|
|
|
3. Configure Client Push (`notify_push`):
|
|
```bash
|
|
docker exec --user www-data nextcloud-app php occ app:install notify_push
|
|
docker exec --user www-data nextcloud-app php occ notify_push:setup https://nxt.bhatfamily.in:8446/push
|
|
docker exec --user www-data nextcloud-app php occ notify_push:self-test
|
|
```
|
|
If `notify_push` is already installed, skip `app:install` and run `notify_push:setup` + `self-test`.
|
|
|
|
4. Verify endpoints and setup checks:
|
|
```bash
|
|
curl -k https://nxt.bhatfamily.in:8446/standalone-signaling/api/v1/welcome
|
|
docker exec --user www-data nextcloud-app php occ setupchecks
|
|
```
|
|
|
|
## One-time setup/security hardening commands
|
|
These commands were used to clear remaining setup/security notices in this deployment:
|
|
|
|
```bash
|
|
docker exec --user www-data nextcloud-app php occ twofactorauth:enforce --on
|
|
docker exec --user www-data nextcloud-app php occ config:system:set default_phone_region --value=IN
|
|
docker exec --user www-data nextcloud-app php occ config:system:set serverid --type=integer --value=1
|
|
docker exec --user www-data nextcloud-app php occ config:system:set mail_smtpmode --value=null
|
|
```
|
|
Adjust `default_phone_region` to your country code as needed.
|
|
|
|
## Move Nextcloud data directory to external storage
|
|
Use the migration helper to move existing data to a host path and switch the app to a bind mount.
|
|
|
|
Default target:
|
|
- `/media/rbhat/DATA/nextcloud/NextCloudData`
|
|
|
|
Run migration:
|
|
```bash
|
|
./scripts/migrate-data-directory.sh /media/rbhat/DATA/nextcloud/NextCloudData
|
|
```
|
|
|
|
What the script does:
|
|
- enables maintenance mode
|
|
- copies current `/var/www/html/data` content to target directory
|
|
- applies owner/group and permissions for Nextcloud (`www-data`)
|
|
- updates `docker-compose.yml` app volume with `...:/var/www/html/data`
|
|
- recreates `app` and `web` services
|
|
- disables maintenance mode and verifies mount
|
|
|
|
Rollback (if needed):
|
|
1. Remove the `:/var/www/html/data` bind mount line from `app` volumes in `docker-compose.yml`.
|
|
2. `docker compose up -d app web`
|
|
3. Confirm status:
|
|
```bash
|
|
docker exec --user www-data nextcloud-app php occ status
|
|
```
|
|
|
|
## Production TLS (Let's Encrypt + Cloudflare DNS-01)
|
|
1. Export credentials in shell:
|
|
```bash
|
|
export CF_DNS_API_TOKEN={{CF_DNS_API_TOKEN}}
|
|
export LETSENCRYPT_EMAIL={{LETSENCRYPT_EMAIL}}
|
|
```
|
|
2. Issue/renew and install production cert:
|
|
```bash
|
|
./scripts/provision-production-tls.sh
|
|
```
|
|
3. Reload Nginx container:
|
|
```bash
|
|
docker compose restart web
|
|
```
|
|
4. Verify cert:
|
|
```bash
|
|
echo | openssl s_client -connect nxt.bhatfamily.in:8446 -servername nxt.bhatfamily.in 2>/dev/null | openssl x509 -noout -subject -issuer -dates
|
|
```
|
|
|
|
## Automated renewal job (cron)
|
|
1. Ensure your Cloudflare token export script exists (default path used by renewal wrapper):
|
|
- `~/bin/cloudflare-api-usertoken.sh`
|
|
2. Install/update renewal cron entry:
|
|
```bash
|
|
./scripts/setup-renewal-cron.sh
|
|
```
|
|
This script will:
|
|
- create/update `.tls-renewal.env` (local only, not committed)
|
|
- install a daily cron job (`03:17` by default)
|
|
- write logs to `logs/tls-renew.log`
|
|
3. Manual renewal run (same path cron uses):
|
|
```bash
|
|
./scripts/renew-production-tls.sh
|
|
```
|
|
|
|
## Admin password reset
|
|
List existing users:
|
|
```bash
|
|
docker exec --user www-data nextcloud-app php occ user:list
|
|
```
|
|
|
|
Reset password using helper script (interactive prompt):
|
|
```bash
|
|
./scripts/reset-admin-password.sh admin
|
|
```
|
|
|
|
Reset password non-interactively (for automation):
|
|
```bash
|
|
NEW_NEXTCLOUD_PASSWORD={{NEW_NEXTCLOUD_PASSWORD}} ./scripts/reset-admin-password.sh admin
|
|
```
|
|
|
|
You can target a different username by passing it as the first argument.
|
|
|
|
## Useful commands
|
|
Start/update containers:
|
|
```bash
|
|
docker compose up -d
|
|
```
|
|
Restart all services:
|
|
```bash
|
|
docker compose restart
|
|
```
|
|
Restart web only:
|
|
```bash
|
|
docker compose restart web
|
|
```
|
|
Stop and remove containers/volumes:
|
|
```bash
|
|
./scripts/uninstall.sh
|
|
```
|
|
|
|
## Security notes
|
|
- `.env`, `.tls-renewal.env`, `.hub-update.env`, and runtime cert material under `nginx/ssl` are intentionally ignored by Git.
|
|
- `backups/` is ignored and used for local database/log snapshots before risky changes.
|
|
- Keep `.env` mode restricted (`chmod 600 .env`).
|
|
- If secrets were ever committed earlier, rotate them.
|