RA4 — Pràctica 1: Nextcloud amb Docker Compose

Durada: ~90 minuts
Nivell: ASIX 2n curs
Prerequisits: Docker instal·lat, coneixement bàsic de docker run i volums


Pas 0 — Verificació de l'entorn (feu-ho PRIMER, ~5 min)

Abans de començar, executeu el script de verificació. Si alguna comprovació falla, seguiu la miniguia d'instal·lació que trobareu al final d'aquest document.

Descarregueu i executeu el script:

mkdir -p ~/ra4 && cd ~/ra4

Creeu el fitxer check_tools.sh amb el contingut següent:

#!/bin/bash
# check_tools.sh - Verificació de l'entorn per al RA4
# Debian 13 (Trixie)

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

OK=0
FAIL=0

check() {
    local desc="$1"
    local cmd="$2"
    if eval "$cmd" &>/dev/null; then
        echo -e "${GREEN}[OK]${NC}  $desc"
        ((OK++))
    else
        echo -e "${RED}[FAIL]${NC} $desc"
        ((FAIL++))
    fi
}

echo "========================================"
echo " Verificació de l'entorn — RA4"
echo "========================================"
echo ""

echo "--- Docker ---"
check "docker instal·lat" "command -v docker"
check "docker en execució" "docker info"
check "usuari pot executar docker (sense sudo)" "docker ps"
check "docker compose disponible" "docker compose version"

echo ""
echo "--- Python i curl ---"
check "python3 instal·lat" "command -v python3"
check "pip3 instal·lat" "command -v pip3"
check "curl instal·lat" "command -v curl"
check "jq instal·lat (útil per a JSON)" "command -v jq"

echo ""
echo "--- Ports disponibles ---"
for port in 8080 8181 3000; do
    if ! ss -tlnp 2>/dev/null | grep -q ":$port "; then
        echo -e "${GREEN}[OK]${NC}  Port $port lliure"
        ((OK++))
    else
        echo -e "${RED}[FAIL]${NC} Port $port ocupat!"
        ((FAIL++))
    fi
done

echo ""
echo "--- Memòria disponible ---"
MEM_FREE=$(awk '/MemAvailable/ {print int($2/1024)}' /proc/meminfo)
if [ "$MEM_FREE" -ge 1800 ]; then
    echo -e "${GREEN}[OK]${NC}  Memòria disponible: ${MEM_FREE} MB (mínim recomanat: 1800 MB)"
    ((OK++))
else
    echo -e "${YELLOW}[WARN]${NC} Memòria disponible: ${MEM_FREE} MB — pot anar just. Tanqueu aplicacions innecessàries."
fi

echo ""
echo "--- Connectivitat ---"
check "accés a Docker Hub" "curl -s --max-time 5 https://hub.docker.com > /dev/null"
check "accés a ghcr.io (GitHub Container Registry)" "curl -s --max-time 5 https://ghcr.io > /dev/null"

echo ""
echo "========================================"
if [ $FAIL -eq 0 ]; then
    echo -e "${GREEN}Tot correcte! Podeu continuar amb la pràctica.${NC}"
else
    echo -e "${RED}Hi ha $FAIL comprovació/ons fallides.${NC}"
    echo "Consulteu la secció 'Miniguia d'instal·lació' al final d'aquest document."
fi
echo "========================================"

Executeu-lo:

chmod +x check_tools.sh
./check_tools.sh

Tots els [OK]? Continueu. Si hi ha [FAIL], aneu a la miniguia al final d'aquest document.


Part 1 — Instal·lació de Nextcloud amb Docker Compose (~25 min)

1.1 Estructura de directoris

mkdir -p ~/ra4/nextcloud
cd ~/ra4/nextcloud

1.2 Fitxer de variables d'entorn

Creeu el fitxer .env (les contrasenyes es centralitzen aquí):

cat > .env << 'EOF'
# Base de dades
MYSQL_ROOT_PASSWORD=rootpassword_canvia
MYSQL_DATABASE=nextcloud
MYSQL_USER=nextclouduser
MYSQL_PASSWORD=nextcloudpass_canvia

# Nextcloud admin
NEXTCLOUD_ADMIN_USER=admin
NEXTCLOUD_ADMIN_PASSWORD=adminpassword_canvia

# URL de confiança (localhost o IP de la VM)
NEXTCLOUD_TRUSTED_DOMAINS=localhost 127.0.0.1
EOF

Nota de seguretat: en producció, mai poseu contrasenyes reals en un fitxer .env sense protecció. Per a pràctiques, és acceptable.

1.3 Fitxer compose.yaml

Creeu el fitxer compose.yaml:

# compose.yaml — Nextcloud + MariaDB per a pràctiques RA4
# Debian 13 (Trixie) · Docker Compose v2

services:

  db:
    image: mariadb:lts
    container_name: nc_db
    restart: unless-stopped
    command: >
      --transaction-isolation=READ-COMMITTED
      --log-bin=binlog
      --binlog-format=ROW
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE:      ${MYSQL_DATABASE}
      MYSQL_USER:          ${MYSQL_USER}
      MYSQL_PASSWORD:      ${MYSQL_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - nc_net
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 10
      start_period: 30s

  app:
    image: nextcloud:apache
    container_name: nc_app
    restart: unless-stopped
    ports:
      - "8080:80"
    environment:
      MYSQL_HOST:     db
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER:     ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      NEXTCLOUD_ADMIN_USER:     ${NEXTCLOUD_ADMIN_USER}
      NEXTCLOUD_ADMIN_PASSWORD: ${NEXTCLOUD_ADMIN_PASSWORD}
      NEXTCLOUD_TRUSTED_DOMAINS: ${NEXTCLOUD_TRUSTED_DOMAINS}
    volumes:
      - nc_data:/var/www/html
    networks:
      - nc_net
    depends_on:
      db:
        condition: service_healthy

networks:
  nc_net:
    driver: bridge

volumes:
  db_data:
  nc_data:

1.4 Llançar els serveis

# Baixar imatges i engegar en segon pla
docker compose up -d

# Seguir els logs d'arrencada (Ctrl+C per sortir, els contenidors continuen)
docker compose logs -f app

Espereu fins que vegeu alguna cosa com:

nc_app  | [core:notice] [...] AH00094: Command line: 'apache2 -D FOREGROUND'

Pot trigar entre 1 i 3 minuts en la primera arrencada (Nextcloud inicialitza la base de dades).

1.5 Verificar l'estat

docker compose ps

Heu de veure tots dos serveis amb estat running (i healthy per a db).

1.6 Accedir a Nextcloud

Obriu el navegador: http://localhost:8080

Heu de veure el dashboard de Nextcloud amb l'usuari admin ja connectat (la configuració automàtica hauria d'haver creat la sessió).

Si demana login: usuari admin, contrasenya la que heu posat a .env.


Part 2 — Gestió d'usuaris des de la interfície web (~20 min)

2.1 Crear grups

  1. Aneu a la icona d'usuari (dalt a la dreta) → AdministracióUsuaris
  2. A la barra lateral esquerra, clicar "+ Nou grup"
  3. Crear els grups: Professors i Alumnes

2.2 Crear usuaris

Crear els usuaris següents (botó "Nou usuari" dalt a la dreta):

Usuari Nom complet Contrasenya Grup Quota
alice Alice Martínez Alice2025! Professors 2 GB
bob Bob García Bob2025! Alumnes 500 MB
carol Carol López Carol2025! Alumnes 500 MB

2.3 Crear carpetes compartides

  1. Tanqueu la sessió d'admin i entreu com alice
  2. Aneu a Fitxers → botó "+"Nova carpeta → Nom: Materials del curs
  3. Cliceu els tres punts (...) al costat de la carpeta → Compartir
  4. Al camp de cerca, escriviu Alumnes (el grup)
  5. Seleccioneu el grup Alumnes, permisos: només lectura (desmarqueu "Pot editar")
  6. Cliqueu "Compartir"

2.4 Verificar la compartició

  1. Tanqueu sessió d'alice
  2. Entreu com bob
  3. Aneu a FitxersCompartit amb tu
  4. Heu de veure la carpeta "Materials del curs"
  5. Intenteu crear una subcarpeta dins → hauria de donar error de permisos

2.5 Activitat cooperativa

Mentre esteu com bob:

  1. Aneu als vostres Fitxers personals
  2. Pugeu qualsevol fitxer (una imatge, un document)
  3. Compartiu-lo amb carol (usuari específic, no grup) amb permisos d'edició

Verifiqueu com a carol que el fitxer apareix a "Compartit amb tu".


Part 3 — Gestió d'usuaris per línia de comandes amb occ (~20 min)

3.1 Explorar occ

Des del directori ~/ra4/nextcloud:

# Llistar totes les comandes disponibles
docker compose exec -u www-data app php occ list

# Veure les comandes relacionades amb usuaris
docker compose exec -u www-data app php occ list user

# Veure l'estat general de Nextcloud
docker compose exec -u www-data app php occ status

3.2 Crear un usuari per CLI

# Crear l'usuari 'david' del grup Professors
OC_PASS="David2025!" docker compose exec -u www-data -e OC_PASS app \
  php occ user:add \
    --password-from-env \
    --display-name "David Puig" \
    --group "Professors" \
    david

Verificar que s'ha creat:

docker compose exec -u www-data app php occ user:info david

3.3 Gestionar grups per CLI

# Llistar grups i els seus membres
docker compose exec -u www-data app php occ group:list

# Afegir bob al grup Professors (ara pertany a dos grups)
docker compose exec -u www-data app php occ group:adduser Professors bob

# Verificar
docker compose exec -u www-data app php occ user:info bob

3.4 Canviar quota i configuració

# Canviar la quota de david
docker compose exec -u www-data app php occ user:setting david files quota 1GB

# Verificar totes les quotes
docker compose exec -u www-data app php occ user:list --output=json | \
  python3 -c "import sys,json; d=json.load(sys.stdin); [print(f'{k}: {v.get(\"displayName\",k)}') for k,v in d.items()]"

3.5 Script d'automatització

Creeu el fitxer crear_usuaris.sh:

#!/bin/bash
# crear_usuaris.sh - Crea múltiples usuaris a Nextcloud via occ
# Execució: ./crear_usuaris.sh

COMPOSE_DIR="$HOME/ra4/nextcloud"
NC_EXEC="docker compose exec -u www-data"

# Format: nomUsuari:NomComplet:Contrasenya:Grup
USUARIS=(
  "elena:Elena Vidal:Elena2025!:Alumnes"
  "ferran:Ferran Costa:Ferran2025!:Alumnes"
  "gina:Gina Roca:Gina2025!:Professors"
)

cd "$COMPOSE_DIR" || exit 1

echo "=== Creació massiva d'usuaris Nextcloud ==="
echo ""

for entrada in "${USUARIS[@]}"; do
  IFS=':' read -r usuari nom_complet contrasenya grup <<< "$entrada"

  echo -n "Creant '$usuari' ($nom_complet, grup: $grup)... "

  OC_PASS="$contrasenya" $NC_EXEC -e OC_PASS app \
    php occ user:add \
      --password-from-env \
      --display-name "$nom_complet" \
      --group "$grup" \
      "$usuari" 2>/dev/null

  if [ $? -eq 0 ]; then
    echo "OK"
  else
    echo "Error (potser ja existeix?)"
  fi
done

echo ""
echo "=== Usuaris creats ==="
$NC_EXEC app php occ user:list

Executeu-lo:

chmod +x ~/ra4/nextcloud/crear_usuaris.sh
~/ra4/nextcloud/crear_usuaris.sh

Part 4 — Exercici de reflexió i documentació (~10 min)

4.1 Preguntes de reflexió

Responeu per escrit (al full de pràctiques o en un fitxer .md):

  1. Quina diferència hi ha entre gestionar usuaris per interfície web i per occ? En quin cas usaríeu cada mètode?

  2. En el compose.yaml, la base de dades no té cap port publicat a l'amfitrió. Per què és correcte així? Quan caldria publicar-lo?

  3. Si l'administrador de l'organització vol que tots els alumnes tinguin exactament 200 MB de quota d'emmagatzematge, com ho faria de manera eficient? (Penseu en occ i en el script.)

  4. Un usuari del grup Alumnes intenta pujar un fitxer a la carpeta compartida "Materials del curs" i no pot. Expliqueu per què i com ho arreglaríeu si volgués permetre-ho.

4.2 Documentació (criteri 4.8)

Creeu un fitxer manual_nextcloud.md amb les seccions:


Miniguia d'instal·lació (si check_tools.sh ha fallat)

Docker no instal·lat o sense permisos

# 1. Eliminar versions antigues/conflictives
sudo apt remove -y docker docker-engine docker.io containerd runc 2>/dev/null || true

# 2. Instal·lar dependències
sudo apt update
sudo apt install -y ca-certificates curl gnupg

# 3. Afegir clau GPG oficial de Docker
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | \
  sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# 4. Afegir repositori (format modern per a Debian 13)
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/debian trixie stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 5. Instal·lar Docker Engine i el plugin Compose
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin

# 6. Afegir l'usuari al grup docker (evitar sudo en cada comanda)
sudo usermod -aG docker $USER

# 7. Activar el grup sense tancar sessió
newgrp docker

# 8. Verificar
docker run hello-world
docker compose version

Eines auxiliars no instal·lades

# python3, pip3, curl, jq
sudo apt install -y python3 python3-pip curl jq

# Instal·lar la llibreria requests per a Python (usada a la Pràctica 2)
pip3 install requests --break-system-packages

Port ocupat

Si un port és ocupat, identifiqueu el procés i atureu-lo:

# Exemple: veure qui usa el port 8080
sudo ss -tlnp | grep :8080

# Si és un contenidor Docker anterior:
docker ps -a
docker stop <nom_contenidor>
docker rm <nom_contenidor>

# Alternativa: canviar el port al compose.yaml
# ports: "8090:80"  ← usar 8090 en lloc de 8080

Memòria insuficient

# Veure memòria disponible
free -m

# Tancar aplicacions pesades (navegador, IDE...)
# En cas extrem, activar swap temporal:
sudo fallocate -l 2G /swapfile_temp
sudo chmod 600 /swapfile_temp
sudo mkswap /swapfile_temp
sudo swapon /swapfile_temp

# Per desactivar-lo quan acabeu:
# sudo swapoff /swapfile_temp && sudo rm /swapfile_temp

Comandes ràpides de referència

# Engegar els serveis
docker compose up -d

# Aturar els serveis (sense esborrar dades)
docker compose stop

# Aturar i esborrar contenidors (les dades als volums es conserven)
docker compose down

# Esborrar-ho tot incloent volums (⚠️ perd totes les dades)
docker compose down -v

# Veure logs en temps real
docker compose logs -f

# Estat dels serveis
docker compose ps

# Executar occ (Nextcloud CLI)
docker compose exec -u www-data app php occ <comanda>