# Nextcloud files and collaboration

Source: https://docs.quake.ai/resources/iac-templates/nextcloud-files
Markdown: https://docs.quake.ai/resources/iac-templates/nextcloud-files.md

---

# Nextcloud files and collaboration

This pattern composes Compute, Network, and Block Storage into a self-hosted file-sync and collaboration platform for a team, on infrastructure you control.

## What this template does

Provisions a single instance running [Nextcloud](https://nextcloud.com), an open-source file-sync and collaboration platform (a self-hosted alternative to Dropbox or the file layer of Google Workspace). Your team stores, syncs, and shares files on infrastructure you own:

- Compute instance that runs Nextcloud's `app` container in Docker alongside a bundled MariaDB and Redis (4 vCPU and 4 GiB RAM)
- Private network, subnet, router, port, and security group; a floating IP for public access
- A block volume mounted at `/var/lib/docker`, so the MariaDB data and the Nextcloud html/data directory live on a volume you can grow; the default volume size (40 GiB) is larger than the lighter ops-tools templates in this library because Nextcloud's entire purpose is storing user files and its footprint grows with usage
- cloud-init installs Docker Engine, brings up MariaDB and Redis, and prepares Nextcloud to start once you finish configuration

The MariaDB root/app passwords and the Redis password are generated on first boot and written to `/opt/nextcloud/.env`; no credential ships with this template.

## Nextcloud needs a trusted domain before it accepts requests

Like [Infisical](/resources/iac-templates/infisical-secrets), [Plane](/resources/iac-templates/plane-project-management), and [Mattermost](/resources/iac-templates/mattermost-team-chat), Nextcloud requires configuration tied to your public domain before it is fully usable: it rejects requests for hosts not on `NEXTCLOUD_TRUSTED_DOMAINS`. This template holds the Nextcloud app container until you finish that configuration; MariaDB and Redis start immediately.

## Parameters

| Parameter | Description | Default |
| --- | --- | --- |
| `key_name` | SSH keypair name (must already exist) | No default |
| `flavor_name` | Instance size (Nextcloud plus MariaDB and Redis runs on 4 vCPU / 4 GiB for a small team) | `s1a.medium` |
| `image_name` | Operating system image | `Ubuntu-24.04` |
| `app_name` | Display name prefix for resources | `nextcloud` |
| `volume_size` | Block volume size in GiB, mounted at `/var/lib/docker`; grows with file storage usage | `40` |
| `external_network` | External network for floating IP allocation | `PublicStatic` |
| `private_cidr` | CIDR for the private subnet | `10.57.0.0/24` |
| `app_allowed_cidr` | CIDR allowed to reach Nextcloud on port 8080 | `10.57.0.0/24` |

## Finish setup after apply

cloud-init starts MariaDB and Redis and writes the generated passwords to `/opt/nextcloud/.env`. Complete the setup over SSH:

1. Point a domain's DNS A record at the floating IP and put a reverse proxy (Caddy or Nginx) in front for HTTPS on 443.
2. Edit `/opt/nextcloud/.env`: uncomment and set `NEXTCLOUD_ADMIN_USER`, `NEXTCLOUD_ADMIN_PASSWORD`, `NEXTCLOUD_TRUSTED_DOMAINS` (your public hostname), `OVERWRITEPROTOCOL=https`, and `OVERWRITECLIURL` (your public HTTPS address).
3. Start Nextcloud:

```bash
cd /opt/nextcloud
sudo docker compose up -d
```

4. Open the trusted domain and log in with the admin account you set in step 2.

## Access and security

Nextcloud listens on port 8080 over plain HTTP. The security group restricts 8080 to `app_allowed_cidr`, which defaults to the private network only. Because Nextcloud checks its trusted-domain list, the normal access path is a domain with HTTPS on 443 behind a reverse proxy. Ports 80 and 443 stay open for that proxy; they carry no traffic until you add one.

## When to use this pattern

Run file sync, sharing, and storage for a team on a host you operate. This template's default sizing suits a small team; storage usage grows as your team uploads files, so plan to grow `volume_size` over time. To run MariaDB separately from the start, point `MYSQL_HOST` in `/opt/nextcloud/.env` at a [self-managed PostgreSQL](/resources/iac-templates/self-managed-postgres)-style dedicated database instance and remove the bundled `db` service from the compose file.

## Estimated cost

<PricingCompanion
  components={[
    { kind: "template", slug: "nextcloud-files", required: true },
  ]}
/>

## Template source

<TemplateSource slug="nextcloud-files" />

<TemplateResourceMap template="nextcloud-files" format="opentofu" />

## Customize this pattern

- [Customize a template's image and flavor](/docs/automation/how-to/customize-template-image-flavor)
- [Add a block volume to a template](/docs/automation/how-to/add-volume-to-template)
- [Parameterize a template with a tfvars file](/docs/automation/how-to/parameterize-template-tfvars)

## See also

- [Self-managed PostgreSQL](/resources/iac-templates/self-managed-postgres)
- [Mattermost team chat](/resources/iac-templates/mattermost-team-chat)
- [Infisical secrets management](/resources/iac-templates/infisical-secrets)
