- Shell 100%
| .gitignore | ||
| chapter_1.yml | ||
| chapter_2.yml | ||
| chapter_3.yml | ||
| chapter_4.yml | ||
| chapter_5_part1.yml | ||
| chapter_5_part2.yml | ||
| chapter_6.yml | ||
| chapter_7.yml | ||
| chapter_8_9.yml | ||
| chapter_10_to_13.yml | ||
| hosts.ini | ||
| README.md | ||
| sync_here.sh | ||
| vars.yml.example | ||
ansible-nextcloud
Ansible playbooks for a fully automated, production-ready Nextcloud installation on Debian 13 Trixie inside an LXC container running on Proxmox. The setup is designed to sit behind an external reverse proxy (I use Caddy) and is split into numbered chapters that are run in sequence. Why don't I just use the Nextcloud AIO? Two reasons: a) Running Nextcloud AIO in a homelab/selfhost situation will "block" ports 80 and 443 so nothing else can be (easily) hosted there. b) Since I do like Proxmox (it does take away many of the complexities of managing containers and VMs), but running Docker (required for Nextcloud AIO) in an LXC container creates networking issues that aren't easily solved, and running Nextcloud AIO in a full blown virtual machine (to avoid the LXC / Deocker networking issue) is much much more resource intensive. That's why I separated the proxy to its own machine. I strongly recommend this as it allows the usual n+1 habit of self-hosters.
With the help of an LLM I have translated these (excellent!) instructions into an Ansible playbook. https://www.c-rieger.de/nextcloud-installationsanleitung/
Still to do
- more storage options (I specifically want to start using some kind of distributed storage system)
- test the playbook on an actual VM to simulate actual bare metal installation, my gut feeling is that it's already there, but I haven't tested it yet.
- mirror this Repo to my public account on my Forgejo instance (meaning learn forgejo automation/runners)
Architecture overview
Internet → Caddy (reverse proxy, TLS) → LXC container (Nginx + PHP-FPM + MariaDB + Redis)
- Nginx handles incoming requests from Caddy on the backend node
- PHP 8.4-FPM runs Nextcloud
- MariaDB 11.8 stores all Nextcloud data
- Redis provides distributed locking and session caching (APCu for local cache)
- Gotify receives SSH login and system alert notifications
- Notify-Push (high-performance push daemon) backs the Nextcloud client sync
Prerequisites
- Ansible installed on your control machine
- A target Debian 13 Trixie LXC container accessible over SSH as
root - A Caddy reverse proxy already running somewhere on your local network
- A Gotify instance for notifications (chapter 7)
Setup
1. Configure the inventory
Edit hosts.ini and replace the hostname, IP, and user with your own:
[nextcloud_servers]
your-host.example.com ansible_host=192.168.x.x ansible_user=root
2. Configure variables
Copy the example vars file and fill in your own values:
cp vars.yml.example vars.yml
Then edit vars.yml:
| Variable | Description |
|---|---|
server_hostname |
Friendly name for the Nextcloud instance |
server_fqdn |
Public FQDN managed by your Caddy proxy |
caddy_proxy_ip |
Local IP of your Caddy server (for trusted proxy config) |
ntp_servers |
List of NTP servers |
php_ver |
PHP version to install (default: 8.4) |
nc_admin_user |
Nextcloud admin username |
nc_admin_pass |
Nextcloud admin password |
nextcloud_db_name |
MariaDB database name |
nextcloud_db_user |
MariaDB database user |
nextcloud_db_pass |
MariaDB database password |
redis_password |
Redis authentication password |
gotify_url |
URL of your Gotify instance |
gotify_token |
API token from your Gotify application |
vars.ymlis listed in.gitignoreand will never be committed.
Running the playbooks
Run each chapter in order. Every chapter builds on the previous one.
Of you're doing this on Proxmox I recommend creating a snapshot after running each playbook.
# Chapter 1 — Base system, Nginx, PHP 8.4
ansible-playbook -i hosts.ini chapter_1.yml
# Chapter 2 — PHP 8.4 extensions and optimizations
ansible-playbook -i hosts.ini chapter_2.yml
# Chapter 3 — MariaDB 11.8 installation and hardening
ansible-playbook -i hosts.ini chapter_3.yml
# Chapter 4 — Redis caching layer
ansible-playbook -i hosts.ini chapter_4.yml
# Chapter 5 — Nextcloud core installation and initial configuration
ansible-playbook -i hosts.ini chapter_5_part1.yml
ansible-playbook -i hosts.ini chapter_5_part2.yml
# Chapter 6 — Reverse proxy alignment layer (no credentials required)
ansible-playbook -i hosts.ini chapter_6.yml
# Chapter 7 — Gotify alerting (SSH login notifications)
ansible-playbook -i hosts.ini chapter_7.yml
# Chapters 8 & 9 — Performance optimizations and push service
ansible-playbook -i hosts.ini chapter_8_9.yml
# Chapters 10–13 — Notify-Push daemon, bash aliases, sysctl network hardening
ansible-playbook -i hosts.ini chapter_10_to_13.yml
Security notes
vars.ymlandnotes.txtare both in.gitignore. Do not remove them from it.- All credentials in the playbooks are referenced via variables — no secrets are hardcoded in the chapter files.
- The target container runs as
root— tighten this if your environment requires it.