diff --git a/_nextcloud/.docker-compose.yaml.kate-swp b/_nextcloud/.docker-compose.yaml.kate-swp new file mode 100644 index 0000000..0d97897 Binary files /dev/null and b/_nextcloud/.docker-compose.yaml.kate-swp differ diff --git a/_nextcloud/Dockerfile b/_nextcloud/Dockerfile new file mode 100644 index 0000000..fb2afed --- /dev/null +++ b/_nextcloud/Dockerfile @@ -0,0 +1,2 @@ +FROM nextcloud:latest +RUN apt-get update -y --quiet && apt-get install -y --quiet ffmpeg php-imagick imagemagick libmagickcore-6.q16-6-extra diff --git a/_nextcloud/authentik_user_import.py b/_nextcloud/authentik_user_import.py new file mode 100644 index 0000000..f8d38eb --- /dev/null +++ b/_nextcloud/authentik_user_import.py @@ -0,0 +1,101 @@ +import json +import requests + +# Authentik API credentials and endpoints +authentik_url = 'https://auth.delmar.bzh' +authentik_api_key = 'wsH0RN4wHs6cgsTKRrOPUTpZkXXSr8NwDyhBSMDjNFCjSMiyoOXjSfjjRE2t' +authentik_username = 'akadmin' + +# Read the contents of nextcloud_user_info.json +print("Reading nextcloud_user_info.json...") +with open('nextcloud_user_info.json', 'r') as file: + user_info = json.load(file) + +# Extract all groups from user records +all_groups = set() +for user_record in user_info: + all_groups.update(user_record["groups"]) + +# Create a session +session = requests.Session() + +# Define headers +headers = { + 'Accept': 'application/json', + 'Authorization': 'Bearer ' + authentik_api_key, +} + +# Fetch existing groups from Authentik +print("Fetching existing groups from Authentik...") +authentik_groups_url = f'{authentik_url}/api/v3/core/groups/' # Updated API endpoint +response = session.get(authentik_groups_url, headers=headers) +print(f"Groups URL ({authentik_groups_url}") + +# Check for successful response and decode JSON if present +if response.status_code == 200: + try: + authentik_groups = response.json() + print("Existing groups fetched successfully.") + except json.JSONDecodeError as e: + print(f"Failed to decode JSON response: {e}") + authentik_groups = [] +elif response.status_code == 404: + print("The requested resource could not be found. Please check the URL or the resource.") +else: + print(f"Failed to fetch existing groups. Status Code: {response.status_code}") + authentik_groups = [] + +# Check if groups from Nextcloud exist in Authentik, create missing groups +missing_groups = all_groups - set(authentik_groups) +for group in missing_groups: + group_data = {"name": group} + create_group_response = session.post(authentik_groups_url, json=group_data, headers=headers) + if create_group_response.status_code == 201: + print(f"Group '{group}' created successfully.") + else: + print(f"Failed to create group '{group}'. Status Code: {create_group_response.status_code}") + +# Fetch existing groups from Authentik +print("Fetching existing groups from Authentik...") +response = session.get(authentik_groups_url, headers=headers) +authentik_groups = response.json() +#print(authentik_groups) + +# Create a dictionary mapping group names to group UUIDs +group_name_to_uuid = {group['name']: group['pk'] for group in authentik_groups['results']} +print(group_name_to_uuid) + +# Import users to Authentik +print(f"Importing users to Authentik ({authentik_url})...") +for idx, user_record in enumerate(user_info, start=1): + print(f"Processing user {idx}/{len(user_info)} - ID: {user_record['user_id']}") + + # Map Nextcloud groups to Authentik group UUIDs + authentik_group_uuids = [group_name_to_uuid[group] for group in user_record['groups'] if group in group_name_to_uuid] + + + # Format the user record according to Authentik's requirements + formatted_user = { + "username": user_record["user_id"], + "name": user_record["display_name"], + "email": user_record["email"], + "groups": authentik_group_uuids, + "is_active": True, # Assuming all users are active + "type": "internal", # Assuming all users are internal + # Add other fields as required by Authentik's API + # Map or transform data fields according to Authentik's expected format + } + + # Send the formatted user data to Authentik's API endpoint for user import + user_import_url = f"{authentik_url}/api/v3/core/users/" # Updated API endpoint + user_import_response = session.post(user_import_url, json=formatted_user, headers=headers ) + + # Check response status or handle errors based on the API response + if user_import_response.status_code == 201: + print(f"User {formatted_user['username']} imported successfully.") + elif user_import_response.status_code == 400 and user_import_response.json().get('username') == ["This field must be unique."]: + print(f"User {formatted_user['username']} already exists. Skipping.") + else: + print(f"Failed to import user {formatted_user['username']}. Status Code: {user_import_response.status_code}") + # Print response content for debugging (if needed) + print(user_import_response.content) diff --git a/_nextcloud/compose.env b/_nextcloud/compose.env new file mode 100644 index 0000000..d5a350a --- /dev/null +++ b/_nextcloud/compose.env @@ -0,0 +1,13 @@ +NEXTCLOUD_ROOT=/mnt/data/docker/nextcloud +NEXTCLOUD_DATA=/nfs/cloud +NEXTCLOUD_IPADDRESS=192.168.1.14 +NEXTCLOUD_FQDN=cloud.delmar.bzh +MYSQL_ROOT_PASSWORD=transatlantique +MYSQL_PASSWORD=rehire-thrill-curtain +COTURN_SECRET=rehire-thrill-curtain +COLLABORA_FQDN=office.delmar.bzh +COLLABORA_USERNAME=admin +COLLABORA_PASSWORD=rehire-thrill-curtain +TURN_SECRET=eb2bd48deae8d4a0b9c6b72604efe7b13c69205dca8fb1bba4ff0c15aa7efcb3 +SIGNALING_SECRET=ab71e9aa794d39c8eaa3f0e999b216de4262ab2fdf0947ff50848a3c4a21463b +INTERNAL_SECRET=9382487232e79ea3968c3a61ee8bea4bf03b135fc1567797eab7471749ab3b03 diff --git a/_nextcloud/docker-compose.yaml b/_nextcloud/docker-compose.yaml new file mode 100644 index 0000000..5ff6ac9 --- /dev/null +++ b/_nextcloud/docker-compose.yaml @@ -0,0 +1,157 @@ +# sandy (cloud.delmar.bzh) +--- +networks: + nextcloud: + +volumes: + html: + name: nextcloud_html + external: true + mariadb: + name: nextcloud_mariadb + external: true + redis: + name: nextcloud_redis + +services: + app: + container_name: nextcloud + build: + context: . + dockerfile: Dockerfile + depends_on: + - mariadb + - redis + devices: + - /dev/dri:/dev/dri + environment: + NEXTCLOUD_TRUSTED_DOMAINS: cloud.delmar.bzh + NEXTCLOUD_DATA_DIR: /srv/nextcloud/data + MYSQL_DATABASE: nextcloud + MYSQL_USER: nextcloud + MYSQL_PASSWORD: rehire-thrill-curtain + MYSQL_HOST: nextcloud-mariadb + REDIS_HOST: nextcloud-redis + NEXTCLOUD_ENABLE_DRI_DEVICE: true + PHP_MEMORY_LIMIT: 4G + PHP_MAX_EXECUTION_TIME: 7200 + PHP_OPCACHE_MEMORY_CONSUMPTION: 256 + UPLOAD_LIMIT: 10G + PHP_POST_MAX_SIZE: 10G + TZ: Europe/Paris + extra_hosts: + - cloud.delmar.bzh:192.168.1.14 + - office.delmar.bzh:192.168.1.14 + volumes: + - html:/var/www/html + - /nfs/cloud:/srv/nextcloud/data + - type: tmpfs + target: /tmp:exec + ports: + - 35771:80 + networks: + - nextcloud + restart: unless-stopped + labels: + - "dockpeek.link=https://cloud.delmar.bzh" + - "dockpeek.tags=frontend,production" + + nextcloud-cron: + container_name: nextcloud-cron + image: nextcloud + depends_on: + - app + entrypoint: /cron.sh + environment: + NEXTCLOUD_TRUSTED_DOMAINS: cloud.delmar.bzh + NEXTCLOUD_DATA_DIR: /srv/nextcloud/data + MYSQL_DATABASE: nextcloud + MYSQL_USER: nextcloud + MYSQL_PASSWORD: rehire-thrill-curtain + MYSQL_HOST: nextcloud-mariadb + REDIS_HOST: nextcloud-redis + TZ: Europe/Paris + volumes: + - html:/var/www/html + - /nfs/cloud:/srv/nextcloud/data + networks: + - nextcloud + restart: unless-stopped + labels: + - "dockpeek.tags=backend,maintenance,production" + + mariadb: + container_name: nextcloud-mariadb + image: mariadb:11.4-ubi + environment: + MYSQL_ROOT_PASSWORD: transatlantique + MYSQL_PASSWORD: rehire-thrill-curtain + MYSQL_DATABASE: nextcloud + MYSQL_USER: nextcloud + TZ: Europe/Paris + volumes: + - mariadb:/var/lib/mysql + networks: + - nextcloud + restart: unless-stopped + labels: + - "dockpeek.tags=backend,database,production" + + adminer: + container_name: nextcloud-adminer + image: adminer + environment: + ADMINER_DEFAULT_SERVER: mariadb + depends_on: + - mariadb + ports: + - 62764:8080 + networks: + - nextcloud + restart: unless-stopped + labels: + - "dockpeek.tags=backend,database,administration,production" + + redis: + container_name: nextcloud-redis + image: valkey/valkey + volumes: + - redis:/data + networks: + - nextcloud + restart: unless-stopped + labels: + - "dockpeek.tags=backend,broker,production" + + coturn: + container_name: nextcloud-coturn + image: coturn/coturn + command: + - "--realm" + - "cloud.delmar.bzh" + - "--static-auth-secret" + - "rehire-thrill-curtain" + - "--no-stdout-log" + - "--log-file" + - "stdout" + - "--stale-nonce=600" + - "--use-auth-secret" + - "--server-name=nextcloud-coturn " + - "--lt-cred-mech" + - "--fingerprint" + - "--no-software-attribute" + - "--no-multicast-peers" + # - "--listening-ip=0.0.0.0 " + # - "--external-ip=192.168.1.14" + # - "--listening-port=3478" + # - "--min-port=49160" + # - "--max-port=49200" + ports: + - 3478:3478 + - 49160-49200:49160-49200/udp + # network_mode: host + networks: + - nextcloud + restart: unless-stopped + labels: + - "dockpeek.tags=backend,gateway,production" diff --git a/_nextcloud/nextcloud-aio-compose.yaml b/_nextcloud/nextcloud-aio-compose.yaml new file mode 100644 index 0000000..e71c37b --- /dev/null +++ b/_nextcloud/nextcloud-aio-compose.yaml @@ -0,0 +1,53 @@ +# sheldon (cloud.delmar.bzh) +# https://github.com/nextcloud/all-in-one +--- +name: nextcloud-aio + +volumes: # If you want to store the data on a different drive, see https://github.com/nextcloud/all-in-one#how-to-store-the-filesinstallation-on-a-separate-drive + nextcloud_aio_mastercontainer: + name: nextcloud_aio_mastercontainer # This line is not allowed to be changed as otherwise the built-in backup solution will not work + +networks: + nextcloud-aio: + name: nextcloud-aio + driver_opts: + com.docker.network.driver.mtu: 1440 + +services: + nextcloud-aio-mastercontainer: + image: ghcr.io/nextcloud-releases/all-in-one:latest + init: true + restart: always + container_name: nextcloud-aio-mastercontainer + volumes: + - nextcloud_aio_mastercontainer:/mnt/docker-aio-config + - /var/run/docker.sock:/var/run/docker.sock:ro + network_mode: bridge + networks: ["nextcloud-aio"] + ports: + # - 80:80 + - 35771:8080 # This is the AIO interface, served via https and self-signed certificate. See https://github.com/nextcloud/all-in-one#explanation-of-used-ports + # - 8443:8443 # Can be removed when running behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else). See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md + environment: + # AIO_DISABLE_BACKUP_SECTION: false # Setting this to true allows to hide the backup section in the AIO interface. See https://github.com/nextcloud/all-in-one#how-to-disable-the-backup-section + # APACHE_PORT: 11000 # Is needed when running behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else). See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md + # APACHE_IP_BINDING: 127.0.0.1 # Should be set when running behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else) that is running on the same host. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md + # APACHE_ADDITIONAL_NETWORK: frontend_net # (Optional) Connect the apache container to an additional docker network. Needed when behind a web server or reverse proxy (like Apache, Nginx, Caddy, Cloudflare Tunnel and else) running in a different docker network on same server. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md + BORG_RETENTION_POLICY: --keep-within=7d --keep-weekly=4 --keep-monthly=6 + # COLLABORA_SECCOMP_DISABLED: false # Setting this to true allows to disable Collabora's Seccomp feature. See https://github.com/nextcloud/all-in-one#how-to-disable-collaboras-seccomp-feature + # FULLTEXTSEARCH_JAVA_OPTIONS: "-Xms1024M -Xmx1024M" # Allows to adjust the fulltextsearch java options. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-fulltextsearch-java-options + NEXTCLOUD_DATADIR: /mnt/data/ncdata + NEXTCLOUD_MOUNT: /mnt/data/ + NEXTCLOUD_UPLOAD_LIMIT: 16G # Can be adjusted if you need more. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-upload-limit-for-nextcloud + NEXTCLOUD_MAX_TIME: 3600 # Can be adjusted if you need more. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-max-execution-time-for-nextcloud + NEXTCLOUD_MEMORY_LIMIT: 512M # Can be adjusted if you need more. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-php-memory-limit-for-nextcloud + # NEXTCLOUD_TRUSTED_CACERTS_DIR: /path/to/my/cacerts # CA certificates in this directory will be trusted by the OS of the nextcloud container (Useful e.g. for LDAPS) See https://github.com/nextcloud/all-in-one#how-to-trust-user-defined-certification-authorities-ca + # NEXTCLOUD_STARTUP_APPS: deck twofactor_totp tasks calendar contacts notes # Allows to modify the Nextcloud apps that are installed on starting AIO the first time. See https://github.com/nextcloud/all-in-one#how-to-change-the-nextcloud-apps-that-are-installed-on-the-first-startup + NEXTCLOUD_ADDITIONAL_APKS: ffmpeg imagemagick libmagickcore-6.q16-6-extra + NEXTCLOUD_ADDITIONAL_PHP_EXTENSIONS: imagick # php-imagick + NEXTCLOUD_ENABLE_DRI_DEVICE: true + # NEXTCLOUD_ENABLE_NVIDIA_GPU: true # This allows to enable the NVIDIA runtime and GPU access for containers that profit from it. ⚠️⚠️⚠️ Warning: this only works if an NVIDIA gpu is installed on the server. See https://github.com/nextcloud/all-in-one#how-to-enable-hardware-acceleration-for-nextcloud. + NEXTCLOUD_KEEP_DISABLED_APPS: false + # SKIP_DOMAIN_VALIDATION: false # This should only be set to true if things are correctly configured. See https://github.com/nextcloud/all-in-one?tab=readme-ov-file#how-to-skip-the-domain-validation + TALK_PORT: 3478 # This allows to adjust the port that the talk container is using which is exposed on the host. See https://github.com/nextcloud/all-in-one#how-to-adjust-the-talk-port + # WATCHTOWER_DOCKER_SOCKET_PATH: /var/run/docker.sock # Needs to be specified if the docker socket on the host is not located in the default '/var/run/docker.sock'. Otherwise mastercontainer updates will fail. For macos it needs to be '/var/run/docker.sock' diff --git a/_nextcloud/nextcloud_user_export.sh b/_nextcloud/nextcloud_user_export.sh new file mode 100644 index 0000000..1539a87 --- /dev/null +++ b/_nextcloud/nextcloud_user_export.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# Run nextcloud occ command to get user list +user_list=$(docker exec -it nextcloud php occ user:list --output=json) + +# Print the user list content for verification +echo "$user_list" + +# Create an empty array to store user details +user_details=() + +# Extract usernames and nicknames using jq +usernames=$(echo "$user_list" | jq -r 'to_entries[] | "\(.key):\(.value)"') + +# Fetch user information for each username +while IFS= read -r entry; do + username=$(echo "$entry" | cut -d ':' -f1) + + if [ -n "$username" ]; then + echo "Fetching info for user: $username" + # Get user information using user:info for each user + info=$(docker exec -it nextcloud php occ user:info "$username" --output=json) + + # Check if the info is not empty and doesn't contain an error message + if [ -n "$info" ] && ! echo "$info" | grep -q "user not found"; then + user_details+=("$info") + else + echo "Error fetching info for user: $username" + fi + fi +done <<< "$usernames" + +# Convert the user details array to JSON format +user_details_json=$(printf '%s\n' "${user_details[@]}" | jq -s '.') + +# Save the retrieved user details directly to a file +echo "$user_details_json" > nextcloud_user_info.json + +echo "User details exported to nextcloud_user_info.json" + diff --git a/_nextcloud/nextcloud_user_info.json b/_nextcloud/nextcloud_user_info.json new file mode 100644 index 0000000..b4612ff --- /dev/null +++ b/_nextcloud/nextcloud_user_info.json @@ -0,0 +1,115 @@ +[ + { + "user_id": "admin", + "display_name": "admin", + "email": "admin@delmar.bzh", + "cloud_id": "admin@cloud.delmar.bzh", + "enabled": true, + "groups": [ + "Famille", + "admin" + ], + "quota": "none", + "storage": { + "free": 4576955072512, + "used": 17486479, + "total": 4576972558991, + "relative": 0, + "quota": -3 + }, + "first_seen": "unknown", + "last_seen": "2025-05-16T08:15:58+00:00", + "user_directory": "/srv/nextcloud/data/admin", + "backend": "Database" + }, + { + "user_id": "Eliot", + "display_name": "Eliot", + "email": "eliotmarie0@gmail.com", + "cloud_id": "Eliot@cloud.delmar.bzh", + "enabled": true, + "groups": [ + "Famille", + "admin" + ], + "quota": "none", + "storage": { + "free": 4576955072512, + "used": 1177221802, + "total": 4578132294314, + "relative": 0.03, + "quota": -3 + }, + "first_seen": "unknown", + "last_seen": "2025-05-16T08:25:13+00:00", + "user_directory": "/srv/nextcloud/data/Eliot", + "backend": "Database" + }, + { + "user_id": "julien", + "display_name": "Julieñ", + "email": "jme69@delmar.bzh", + "cloud_id": "julien@cloud.delmar.bzh", + "enabled": true, + "groups": [ + "Famille", + "admin" + ], + "quota": "none", + "storage": { + "free": 4576955072512, + "used": 15910061096, + "total": 4592865133608, + "relative": 0.35, + "quota": -3 + }, + "first_seen": "unknown", + "last_seen": "2025-05-16T09:10:12+00:00", + "user_directory": "/srv/nextcloud/data/julien", + "backend": "Database" + }, + { + "user_id": "Sabine", + "display_name": "Sabine", + "email": "sabine.dbm@gmail.com", + "cloud_id": "Sabine@cloud.delmar.bzh", + "enabled": true, + "groups": [ + "Famille" + ], + "quota": "none", + "storage": { + "free": 4576955072512, + "used": 62926115, + "total": 4577017998627, + "relative": 0, + "quota": -3 + }, + "first_seen": "unknown", + "last_seen": "2025-05-16T07:17:06+00:00", + "user_directory": "/srv/nextcloud/data/Sabine", + "backend": "Database" + }, + { + "user_id": "Ugo", + "display_name": "Ugo", + "email": "ugomarie22@gmail.com", + "cloud_id": "Ugo@cloud.delmar.bzh", + "enabled": true, + "groups": [ + "Famille" + ], + "quota": "none", + "storage": { + "free": 4576955072512, + "used": 1019952437, + "total": 4577975024949, + "relative": 0.02, + "quota": -3 + }, + "first_seen": "unknown", + "last_seen": "2025-05-16T08:05:27+00:00", + "user_directory": "/srv/nextcloud/data/Ugo", + "backend": "Database" + } +]