Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions 03_container_layer/docker/admin/nextcloud/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Prevent secrets and editor artifacts from leaking into the build context.
.env
*.env
*.key
*.pem
*.p12
*.pfx
README.md
21 changes: 21 additions & 0 deletions 03_container_layer/docker/admin/nextcloud/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#
# ISSUE 146
#
# Copy to .env and fill in values before running: cp .env.example .env
# .env is gitignored — never commit real secrets.
#

# ── Nextcloud ──────────────────────────────────────────────────────────────
NC_DOMAIN=localhost

# ── Initial admin (auto-created by Nextcloud on first boot) ───────────────
NC_ADMIN_USER=nc-admin
NC_ADMIN_PASS=Admin1234!

# ── PostgreSQL ──────────────────────────────────────────────────────────────
POSTGRES_USER=nextcloud
POSTGRES_PASSWORD=CHANGEME_replace_before_deploying
POSTGRES_DB=nextcloud

# ── Host ports ──────────────────────────────────────────────────────────────
HTTP_PORT=8080
32 changes: 32 additions & 0 deletions 03_container_layer/docker/admin/nextcloud/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#
# ISSUE 146
#

#
# BUILDER — php:8.3-apache-bookworm (same base as official Nextcloud Dockerfile)
# Installs yq and jq as static binaries; copies and pre-validates provisioning scripts.
#
FROM php:8.3-apache-bookworm AS builder

RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates && \
rm -rf /var/lib/apt/lists/* && \
curl -sL https://github.com/mikefarah/yq/releases/download/v4.44.1/yq_linux_amd64 \
-o /usr/local/bin/yq && chmod +x /usr/local/bin/yq && \
curl -sL https://github.com/jqlang/jq/releases/download/jq-1.7.1/jq-linux-amd64 \
-o /usr/local/bin/jq && chmod +x /usr/local/bin/jq

COPY provisioning/ /provisioning/
RUN chmod +x /provisioning/init.sh

#
# RUNTIME — nextcloud:latest (PHP/Apache/Debian, provisioner via OCS API)
# Copies tooling and provisioning scripts from builder.
# Acts as the provisioner sidecar: creates users and app passwords via OCS API.
#
FROM nextcloud:latest AS runtime

COPY --from=builder /usr/local/bin/yq /usr/local/bin/yq
COPY --from=builder /usr/local/bin/jq /usr/local/bin/jq
COPY --from=builder /provisioning/ /provisioning/

ENTRYPOINT ["/provisioning/init.sh"]
92 changes: 92 additions & 0 deletions 03_container_layer/docker/admin/nextcloud/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#
# ISSUE 146
#

SERVICE = nextcloud
PROVISIONER = nextcloud-provisioner
DEBUG_SERVICE = $(SERVICE)-debug

.PHONY: help up down stop build rebuild build-up rebuild-up reprovision logs-provisioner tokens term term-debug-build clean print

help:
@echo ""
@echo ""
@echo " Available : "
@echo ""
@echo " make up - run the full stack (db + redis + nextcloud + provisioner) in background"
@echo " make down - stop and remove all containers"
@echo " make stop - stop $(SERVICE) only"
@echo ""
@echo " make build - build the provisioner image"
@echo " make build-up - build provisioner image then start the full stack"
@echo ""
@echo " make rebuild - full rebuild without cache"
@echo " make rebuild-up - full rebuild without cache then start"
@echo ""
@echo " make reprovision - remove the provisioning stamp and restart provisioner"
@echo " make logs-provisioner - tail provisioner output"
@echo " make tokens - print generated app passwords"
@echo ""
@echo " make term - open shell in $(SERVICE) container"
@echo " make term-debug-build - build and open shell in $(DEBUG_SERVICE)"
@echo " make clean - delete all containers, images, volumes and unused network"
@echo " make print - print this help"
@echo ""
@echo ""

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

up:
docker compose up -d
down:
docker compose down
stop:
docker compose stop $(SERVICE)

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

build:
docker compose build

rebuild:
docker compose down
docker compose build --no-cache

# # # # # # # # # # # #

build-up:
docker compose build
docker compose up -d

rebuild-up:
docker compose down
docker compose build --no-cache
docker compose up -d

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

reprovision:
docker volume rm -f nextcloud_nextcloud-tokens 2>/dev/null || true
docker compose up -d $(PROVISIONER)

logs-provisioner:
docker compose logs -f $(PROVISIONER)

tokens:
docker run --rm -v nextcloud_nextcloud-tokens:/tokens alpine cat /tokens/tokens.txt

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

clean:
docker compose down -v --rmi all

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

term:
docker exec -it $(SERVICE) /bin/bash

term-debug-build:
docker compose up --build -d debug
docker exec -it $(DEBUG_SERVICE) /bin/bash

print: help
169 changes: 169 additions & 0 deletions 03_container_layer/docker/admin/nextcloud/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# Nextcloud — Standalone Docker Deployment

Issue: [#146](https://github.com/range42/range42-catalog/issues/146)

Standalone Nextcloud instance with automated user provisioning and app-password generation.
The initial admin is created automatically by Nextcloud on first boot; additional users and app
passwords are provisioned via the OCS API sidecar.

---

## Prerequisites

- Docker 24+ with Compose v2
- `make`

---

## Quick Start

```bash
cp .env.example .env # edit secrets before deploying
make build-up # build provisioner image, start full stack
make logs-provisioner # watch bootstrap output
make tokens # print generated app passwords
```

Nextcloud will be available at `http://localhost:8080` (or `HTTP_PORT`).
WebDAV: `http://localhost:8080/remote.php/dav/files/<USERNAME>/`

---

## Build & Push

```bash
# Build only the provisioner image
make build

# Full rebuild (no cache)
make rebuild

# Push to a registry (replace tag as needed)
docker tag nextcloud-provisioner registry.example.com/range42/nextcloud-provisioner:latest
docker push registry.example.com/range42/nextcloud-provisioner:latest
```

---

## Declaring Users

Edit `provisioning/users.yml` before the first `make up`:

```yaml
admins:
- username: nc-admin2
email: admin2@range42.local
password: "Admin1234!"
display_name: "NC Admin 2"

users:
- username: trainee01
email: trainee01@range42.local
password: "Trainee1234!"
display_name: "Trainee 01"
```

- `admins[]` entries are created and added to the Nextcloud `admin` group.
- `users[]` entries are regular accounts.
- `nc-admin` (set via `NC_ADMIN_USER`) is created automatically by Nextcloud — do not repeat it here.
- An app password is auto-generated for every user and written to `/tokens/tokens.txt`.

**The provisioner runs only once** (guarded by `/tokens/.provisioned`).
To re-provision after changes, run:

```bash
make reprovision
```

---

## App Password Retrieval

App passwords are written to the `nextcloud-tokens` volume during provisioning.
Retrieve them at any time:

```bash
make tokens
```

Example output:

```
nc-admin2: <app-password-string>
trainee01: <app-password-string>
trainee02: <app-password-string>
trainee03: <app-password-string>
```

---

## WebDAV Usage

Mount a user's files via WebDAV using the generated app password:

```
davs://localhost:8080/remote.php/dav/files/<USERNAME>/
```

Example with `curl`:

```bash
curl -u trainee01:<app-password> \
https://localhost:8080/remote.php/dav/files/trainee01/
```

---

## API Usage Examples

```bash
# List files (WebDAV PROPFIND)
curl -X PROPFIND \
-u trainee01:<app-password> \
http://localhost:8080/remote.php/dav/files/trainee01/

# Upload a file
curl -T local_file.txt \
-u trainee01:<app-password> \
http://localhost:8080/remote.php/dav/files/trainee01/remote_file.txt

# OCS user list (admin only)
curl -H "OCS-APIRequest: true" -H "Accept: application/json" \
-u nc-admin:Admin1234! \
http://localhost:8080/ocs/v1.php/cloud/users
```

---

## Environment Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `NC_DOMAIN` | `localhost` | Trusted domain for Nextcloud |
| `NC_ADMIN_USER` | `nc-admin` | Initial admin username (auto-created by Nextcloud) |
| `NC_ADMIN_PASS` | `Admin1234!` | Initial admin password |
| `POSTGRES_USER` | `nextcloud` | DB user |
| `POSTGRES_PASSWORD` | `nextcloud` | DB password — **change before deploying** |
| `POSTGRES_DB` | `nextcloud` | DB name |
| `HTTP_PORT` | `8080` | Host port for HTTP |

---

## Troubleshooting

**Provisioner exits immediately with "Already provisioned"**
Remove the tokens volume and re-run: `make reprovision`

**Provisioner fails with "Nextcloud did not become healthy after 180 s"**
Nextcloud first-boot can take several minutes. Increase `start_period` in `compose.yml`
or check `docker logs nextcloud` for errors.

**User creation returns a 403 or 401**
Verify `NC_ADMIN_USER` and `NC_ADMIN_PASS` in `.env` match the actual admin credentials.

**App password generation fails (ERROR in tokens.txt)**
The OCS v2 endpoint requires the user to exist and be enabled.
Check `make logs-provisioner` for the exact error.

**Port 8080 already in use**
Set `HTTP_PORT=8081` (or any free port) in `.env`.
Loading