diff --git a/README.md b/README.md new file mode 100644 index 0000000..0379af2 --- /dev/null +++ b/README.md @@ -0,0 +1,179 @@ +# Nextcloud - nc.wittenberger.us + +Self-hosted Nextcloud instance running on a bare metal Ubuntu VM with Apache + PHP 8.3 and a MySQL backend. + +--- + +## Repository Contents + +``` +nextcloud/ +├── configs/ +│ ├── config.php # Nextcloud application config (secrets redacted) +│ ├── nc.wittenberger.us.conf # Apache HTTP vhost (port 80, redirects to HTTPS) +│ ├── nc.wittenberger.us-le-ssl.conf # Apache HTTPS vhost (port 443, SSL + RemoteIP) +│ └── php.ini # PHP 8.3 config (apache2 SAPI) +└── README.md +``` + +--- + +## Stack + +- **Nextcloud** v33.0.3.2 +- **Apache2** - HTTP/HTTPS, mod_ssl, mod_remoteip, mod_rewrite +- **PHP 8.3** - mod_php (apache2 SAPI) +- **MySQL** - database backend (`nextcloud` db, `localhost`) +- **Redis** - distributed locking (`memcache.locking`, localhost:6379) +- **APCu** - local memory cache (`memcache.local`) +- **Let's Encrypt** - SSL via Certbot (`/etc/letsencrypt/live/nc.wittenberger.us/`) + +--- + +## Prerequisites + +- Ubuntu VM with Apache2, PHP 8.3, MySQL, Redis installed +- PHP extensions: `apcu`, `opcache`, `pdo_mysql`, `mbstring`, `intl`, `gd`, `curl`, `zip`, `xml` +- Certbot for SSL certificate management +- Cloudflare in front of the server (NPM on a separate host handles proxying) + +--- + +## Key PHP Settings + +The following values in `configs/php.ini` are tuned specifically for Nextcloud - these differ from PHP defaults: + +| Directive | Value | Reason | +|-----------|-------|--------| +| `memory_limit` | `512M` | Nextcloud recommendation | +| `upload_max_filesize` | `200G` | Large file uploads | +| `post_max_size` | `200G` | Large file uploads | +| `max_execution_time` | `360` | Long-running operations | +| `opcache.enable` | `1` | Performance | +| `opcache.memory_consumption` | `512` | Performance | +| `opcache.interned_strings_buffer` | `16` | Performance | +| `opcache.max_accelerated_files` | `10000` | Performance | +| `date.timezone` | `America/Chicago` | Local timezone | + +--- + +## Apache Configuration + +Two vhost files in `configs/`: + +**`nc.wittenberger.us.conf`** (port 80) - redirects all HTTP traffic to HTTPS via `mod_rewrite`. + +**`nc.wittenberger.us-le-ssl.conf`** (port 443) - main vhost. Notable settings: +- `RemoteIPHeader X-Forwarded-For` with all Cloudflare IP ranges trusted via `RemoteIPTrustedProxy` +- NPM reverse proxy IP (`10.10.14.199`) also trusted +- HSTS header set via `mod_headers`: `max-age=15552000; includeSubDomains` +- SSL via Let's Encrypt; includes `/etc/letsencrypt/options-ssl-apache.conf` + +> The `RemoteIPTrustedProxy` list should be kept in sync with the Cloudflare IP ranges in `config.php`'s `trusted_proxies` array and the NPM host's `http_top.conf`. All three need updating when Cloudflare adds new ranges. + +--- + +## Nextcloud Configuration (`config.php`) + +Key settings (see `configs/config.php` for full file): + +| Setting | Value | +|---------|-------| +| `dbtype` | `mysql` | +| `dbhost` | `localhost` | +| `memcache.local` | `APCu` | +| `memcache.locking` | `Redis` | +| `redis.host` | `localhost:6379` | +| `maintenance_window_start` | `6` (6 AM UTC) | +| `default_phone_region` | `US` | +| `mail_smtpport` | `587` | +| `REVERSE_PROXY_LIMIT` | `2` | + +Secrets to fill in after cloning: + +| Placeholder | Description | +|-------------|-------------| +| `instanceid` | Auto-generated, do not change on restore | +| `passwordsalt` | Auto-generated, do not change on restore | +| `secret` | Auto-generated, do not change on restore | +| `trusted_domains` | Your FQDN and LAN IP | +| `trusted_proxies` | NPM host IP + Cloudflare ranges | +| `dbpassword` | MySQL password for `nextcloud` user | +| `mail_smtphost` / `mail_smtppassword` | SMTP credentials | +| `INTERNAL_TOKEN` / `JWT_SECRET` | Auto-generated, restore from backup | + + +--- + +## Background Jobs (Cron) + +Nextcloud background tasks run via system cron as root every 5 minutes: + +``` +*/5 * * * * php -f /var/www/nc.wittenberger.us/cron.php +``` + +To restore after accidental removal: + +Verify cron mode is set to **Cron** (not Ajax or Webcron) under **Administration → Basic Settings** in the Nextcloud UI. + +--- + +## SSL Certificates + +Managed by Certbot. Certificates live at `/etc/letsencrypt/live/nc.wittenberger.us/`. Auto-renewal is handled by the system `certbot.timer` - verify with: + +```bash +systemctl status certbot.timer +``` + +--- + +## Backups + +| What | Where | +|------|-------| +| Nextcloud files | `/var/www/nc.wittenberger.us/` | +| User data | `/var/www/nc.wittenberger.us/data/` (or custom `datadirectory`) | +| Database | `mysqldump -u nextcloud -p nextcloud > nextcloud_$(date +%F).sql` | +| Config | `config.php` (this repo, secrets stored separately) | +| SSL certs | `/etc/letsencrypt/` | + +--- + +## Updating Nextcloud + +Use the built-in web updater or `occ`: + +```bash +cd /var/www/nc.wittenberger.us +sudo -u www-data php occ upgrade +``` + +After updates, clear opcache and verify background jobs are still running. + +--- + +## Troubleshooting + +**Incorrect IP in logs / Nextcloud security warning about reverse proxy** +Verify `trusted_proxies` in `config.php` matches the `RemoteIPTrustedProxy` entries in the SSL vhost and that `REVERSE_PROXY_LIMIT` is set correctly. + +**Background jobs not running** +Check cron is active: `crontab -l`. Verify mode in Admin → Basic Settings. + +**Redis connection errors** +```bash +systemctl status redis +redis-cli ping +``` + +**Opcache issues after update** +```bash +systemctl restart apache2 +``` + +**Check Nextcloud logs** +```bash +tail -f /var/www/nc.wittenberger.us/data/nextcloud.log +``` \ No newline at end of file