Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7abc0bb6 authored by Thomas G.'s avatar Thomas G.
Browse files

feat(docker): modify docker-compose to match dns b2b infra

parent 2f70e646
Loading
Loading
Loading
Loading
Loading

.env

0 → 100644
+29 −0
Original line number Diff line number Diff line
# docker compose
COMPOSE_BAKE=true

# Server
DOMAIN=murenaworkspace.app

# mail
SMTP_NAME=username
SMTP_PASSWORD=123456
SMTP_HOST=smtp.domain.com
MAIL_FROM_ADDRESS=no-reply
MAIL_DOMAIN=domain.com

# database
DB_HOST=db.dev.murenaworkspace.app
DB_USER=nextcloud
DB_PASSWORD=123456
DB_NAME=nextcloud

# redis
REDIS_HOST=redis.dev.murenaworkspace.app
REDIS_HOST_PASSWORD=12456

# nextcloud
NEXTCLOUD_DOCKERFILE=slim.Dockerfile 
NEXTCLOUD_DOCKER_IMG=registry.gitlab.e.foundation/e/infra/ecloud/nextcloud/slim
NEXTCLOUD_ADMIN_USER=admin
NEXTCLOUD_ADMIN_PASSWORD=@dm1n
NEXTCLOUD_TRUSTED_DOMAINS=nginx
+1 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ map $arg_v $asset_immutable {
}

upstream php-handler {
    server nextcloud:9000;
    server ${COMPOSE_PROJECT_NAME}_nextcloud:9000;
}

server {

create-cname.sh

0 → 100755
+37 −0
Original line number Diff line number Diff line
#!/bin/bash

# Script simple pour créer des CNAME via l'API Gandi
# Usage: ./create-cname.sh <subdomain> <domain> <target>
# Exemple: ./create-cname.sh test example.com target.example.com

SUBDOMAIN=$1
DOMAIN=$2
TARGET=$3
GANDI_API_KEY=${GANDI_API_KEY}

if [[ -z "$SUBDOMAIN" || -z "$DOMAIN" || -z "$TARGET" || -z "$GANDI_API_KEY" ]]; then
    echo "Usage: $0 <subdomain> <domain> <target>"
    echo "Exemple: $0 test example.com target.example.com"
    echo "GANDI_API_KEY doit être définie en variable d'environnement"
    exit 1
fi

# Créer le record CNAME via l'API Gandi
response=$(curl -s -X POST \
    "https://api.gandi.net/v5/livedns/domains/$DOMAIN/records" \
    -H "Authorization: Apikey $GANDI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
        "rrset_name": "'$SUBDOMAIN'",
        "rrset_type": "CNAME",
        "rrset_values": ["'$TARGET'"],
        "rrset_ttl": 300
    }')

if echo "$response" | grep -q "rrset_name"; then
    echo "✅ CNAME créé avec succès: $SUBDOMAIN.$DOMAIN -> $TARGET"
else
    echo "❌ Erreur lors de la création du CNAME:"
    echo "$response"
    exit 1
fi
 No newline at end of file

deploy-crud.sh

0 → 100755
+444 −0
Original line number Diff line number Diff line
#!/bin/bash

# CRUD script for intelligent Nextcloud deployment
# Usage: ./deploy-crud.sh <action> <instance_name> <docker_context>
# Actions: create, read, update, delete, list
# Example: ./deploy-crud.sh create nc1 remote

ACTION=$1
INSTANCE_NAME=$2
DOCKER_CONTEXT=${3:-"default"}

show_help() {
    echo "Usage: $0 <action> <instance_name> [docker_context]"
    echo ""
    echo "Actions:"
    echo "  create   - Create a new instance"
    echo "  read     - View instance status"
    echo "  update   - Update an instance"
    echo "  delete   - Delete an instance"
    echo "  list     - List all instances"
    echo ""
    echo "Examples:"
    echo "  $0 create nc1 remote"
    echo "  $0 read nc1 remote"
    echo "  $0 delete nc1 remote"
    echo "  $0 list remote"
    exit 1
}

if [[ -z "$ACTION" ]]; then
    show_help
fi

# Fonctions utilitaires
get_docker_info() {
    DOCKER_ENDPOINT=$(docker context inspect $DOCKER_CONTEXT --format '{{.Endpoints.docker.Host}}' 2>/dev/null)

    if [[ -z "$DOCKER_ENDPOINT" ]]; then
        echo "❌ Docker context '$DOCKER_CONTEXT' not found"
        exit 1
    fi

    if [[ "$DOCKER_ENDPOINT" =~ ssh://.*@(.+) ]]; then
        DOCKER_HOST="${BASH_REMATCH[1]}"

        if [[ "$DOCKER_HOST" == *".dev."* ]]; then
            ENV="dev"
            BASE_DOMAIN=$(echo "$DOCKER_HOST" | sed 's/^docker\.//')
            TARGET_HOST="$DOCKER_HOST"
        elif [[ "$DOCKER_HOST" == *".staging."* ]]; then
            ENV="staging"
            BASE_DOMAIN=$(echo "$DOCKER_HOST" | sed 's/^docker\.//')
            TARGET_HOST="$DOCKER_HOST"
        elif [[ "$DOCKER_HOST" == *"murenaworkspace.com"* ]]; then
            ENV="prod"
            BASE_DOMAIN="murenaworkspace.com"
            TARGET_HOST="$DOCKER_HOST"
        else
            ENV="custom"
            BASE_DOMAIN=$(echo "$DOCKER_HOST" | sed 's/^[^.]*\.//')
            TARGET_HOST="$DOCKER_HOST"
        fi
    else
        ENV="local"
        BASE_DOMAIN="localhost"
        TARGET_HOST="nginx"
    fi

    FULL_DOMAIN="${INSTANCE_NAME}.${BASE_DOMAIN}"
}

create_cname() {
    if [[ "$ENV" != "local" && -n "$GANDI_API_KEY" ]]; then
        echo "📡 Creating CNAME $FULL_DOMAIN -> $TARGET_HOST..."

        if [[ "$BASE_DOMAIN" == "dev.murenaworkspace.app" ]]; then
            API_DOMAIN="murenaworkspace.app"
            RECORD_NAME="${INSTANCE_NAME}.dev"
        else
            API_DOMAIN="$BASE_DOMAIN"
            RECORD_NAME="$INSTANCE_NAME"
        fi

        response=$(curl -s -X POST \
            "https://api.gandi.net/v5/livedns/domains/$API_DOMAIN/records" \
            -H "Authorization: Bearer $GANDI_API_KEY" \
            -H "Content-Type: application/json" \
            -d '{
                "rrset_name": "'$RECORD_NAME'",
                "rrset_type": "CNAME",
                "rrset_values": ["'$TARGET_HOST'."],
                "rrset_ttl": 300
            }')

        if echo "$response" | grep -q -E "(rrset_name|DNS Record Created)"; then
            echo "✅ CNAME created successfully"
        else
            echo "⚠️  CNAME error: $response"
        fi
    else
        echo "⚠️  CNAME ignored (local or no GANDI_API_KEY)"
    fi
}

delete_cname() {
    if [[ "$ENV" != "local" && -n "$GANDI_API_KEY" ]]; then
        echo "🗑️  Deleting CNAME $FULL_DOMAIN..."

        if [[ "$BASE_DOMAIN" == "dev.murenaworkspace.app" ]]; then
            API_DOMAIN="murenaworkspace.app"
            RECORD_NAME="${INSTANCE_NAME}.dev"
        else
            API_DOMAIN="$BASE_DOMAIN"
            RECORD_NAME="$INSTANCE_NAME"
        fi

        response=$(curl -s -X DELETE \
            "https://api.gandi.net/v5/livedns/domains/$API_DOMAIN/records/$RECORD_NAME/CNAME" \
            -H "Authorization: Bearer $GANDI_API_KEY")

        if [[ "$response" == "" ]]; then
            echo "✅ CNAME deleted successfully"
        else
            echo "⚠️  CNAME deletion error: $response"
        fi
    fi
}

find_project_by_instance() {
    get_docker_info
    local project_file=".env.${INSTANCE_NAME}-${ENV}"
    if [[ -f "$project_file" ]]; then
        PROJECT_NAME="${INSTANCE_NAME}-${ENV}"
        echo "$PROJECT_NAME"
    else
        echo ""
    fi
}

# Actions CRUD

action_create() {
    if [[ -z "$INSTANCE_NAME" ]]; then
        echo "❌ Instance name required for CREATE"
        show_help
    fi

    get_docker_info

    # Generate unique UID for this project
    PROJECT_UID=$(echo "$INSTANCE_NAME-$ENV" | md5sum | cut -c1-8)
    PROJECT_NAME="${INSTANCE_NAME}-${ENV}"

    # Vérifier la connectivité à l'infrastructure distante
    echo "🔍 Checking remote infrastructure..."

    # Tester la connectivité à la base de données
    if ! docker --context $DOCKER_CONTEXT run --rm alpine/curl -f --connect-timeout 5 http://db.${BASE_DOMAIN}:3306 2>/dev/null; then
        echo "⚠️  Database not accessible at db.${BASE_DOMAIN}:3306"
        echo "   Continuing anyway, check that Terraform infrastructure is deployed"
    else
        echo "✅ Database accessible"
    fi

    echo "🚀 Creating Nextcloud instance:"
    echo "   - Instance: $INSTANCE_NAME"
    echo "   - Contexte: $DOCKER_CONTEXT"
    echo "   - Project: $PROJECT_NAME"
    echo "   - Environment: $ENV"
    echo "   - Domain: $FULL_DOMAIN"
    echo "   - Target: $TARGET_HOST"
    echo ""
    echo "🔌 Remote infrastructure:"
    echo "   - Database: db.${BASE_DOMAIN}:3306"
    echo "   - Redis: redis.${BASE_DOMAIN}:6379"
    echo "   - Docker: docker.${BASE_DOMAIN}:22"

    create_cname

    # Générer port numérique basé sur le hash du nom
    PORT_SUFFIX=$(echo "$PROJECT_NAME" | md5sum | tr -d 'a-f' | head -c 3)

    # Créer le .env
    cat > .env.${PROJECT_NAME} << EOF
# Instance: $INSTANCE_NAME
# Environment: $ENV
# Created: $(date)

DOMAIN=${FULL_DOMAIN}
NGINX_PORT=8${PORT_SUFFIX:-000}

# Database (uses infrastructure deployed via DNS)
DB_HOST=db.${BASE_DOMAIN}
DB_USER=nextcloud
DB_PASSWORD=0aVa8l87PfDtrUlg5hIvK3SH1SnfB1
DB_NAME=nextcloud

# Redis (uses infrastructure deployed via DNS)
REDIS_HOST=redis.${BASE_DOMAIN}
REDIS_PASSWORD=123456

# Nextcloud
NEXTCLOUD_DOCKERFILE=slim.Dockerfile
NEXTCLOUD_DOCKER_IMG=registry.gitlab.e.foundation/e/infra/ecloud/nextcloud/slim
NEXTCLOUD_ADMIN_USER=admin
NEXTCLOUD_ADMIN_PASSWORD=@dm1n
NEXTCLOUD_TRUSTED_DOMAINS=${FULL_DOMAIN}

# Mail
SMTP_NAME=${SMTP_NAME:-fd0af045-04cd-471d-b405-3e978bb0b313}
SMTP_PASSWORD=${SMTP_PASSWORD:-d3d51629-f9dd-4d1b-bbb4-8998f5b9bd50}
SMTP_HOST=${SMTP_HOST:-smtp.tem.scaleway.com}
MAIL_FROM_ADDRESS=${MAIL_FROM_ADDRESS:-no-reply}
MAIL_DOMAIN=${MAIL_DOMAIN:-${BASE_DOMAIN}}

# Traefik / ACME
ACME_EMAIL=${ACME_EMAIL:-dev@e.email}
EOF

    echo "📄 Configuration: .env.${PROJECT_NAME}"

    # Déployer
    export COMPOSE_PROJECT_NAME=$PROJECT_NAME
    echo "🐳 Deploying on context '$DOCKER_CONTEXT'..."

    if docker --context $DOCKER_CONTEXT info --format '{{.Swarm.LocalNodeState}}' 2>/dev/null | grep -q "active"; then
        echo "🐝 Docker Swarm mode detected"

        # Créer le volume avec nom explicite
        VOLUME_NAME="nc_data_${INSTANCE_NAME}_${PROJECT_UID}"
        echo "📦 Creating volume: $VOLUME_NAME"
        docker --context $DOCKER_CONTEXT volume create $VOLUME_NAME

        set -a
        source .env.${PROJECT_NAME}
        export INSTANCE_NAME=$INSTANCE_NAME
        export PROJECT_UID=$PROJECT_UID
        set +a
        docker --context $DOCKER_CONTEXT stack deploy -c docker-compose.yml $PROJECT_NAME
    else
        echo "🐳 Docker Compose mode detected"
        DOCKER_CONTEXT=$DOCKER_CONTEXT docker-compose -f docker-compose.yml --env-file .env.${PROJECT_NAME} up -d
    fi

    echo ""
    echo "✅ Instance '$INSTANCE_NAME' created successfully!"
    echo "   🌍 URL: https://$FULL_DOMAIN"
    echo "   📋 Project: $PROJECT_NAME"
    echo "   ⚙️  Config: .env.${PROJECT_NAME}"
    echo ""
    echo "🔑 Admin login:"
    echo "   👤 User: $(grep NEXTCLOUD_ADMIN_USER .env.${PROJECT_NAME} | cut -d'=' -f2)"
    echo "   🔒 Pass: $(grep NEXTCLOUD_ADMIN_PASSWORD .env.${PROJECT_NAME} | cut -d'=' -f2)"
}

action_read() {
    if [[ -z "$INSTANCE_NAME" ]]; then
        echo "❌ Instance name required for READ"
        show_help
    fi

    PROJECT_NAME=$(find_project_by_instance)
    if [[ -z "$PROJECT_NAME" ]]; then
        echo "❌ Instance '$INSTANCE_NAME' not found"
        exit 1
    fi

    get_docker_info

    echo "📋 Instance '$INSTANCE_NAME' status:"
    echo "   - Project: $PROJECT_NAME"
    echo "   - Domain: $FULL_DOMAIN"
    echo "   - Config: .env.${PROJECT_NAME}"

    # État des services
    if docker --context $DOCKER_CONTEXT info --format '{{.Swarm.LocalNodeState}}' 2>/dev/null | grep -q "active"; then
        echo ""
        echo "🐝 Docker Swarm services:"
        docker --context $DOCKER_CONTEXT stack services $PROJECT_NAME
        echo ""
        echo "📊 Detailed status:"
        docker --context $DOCKER_CONTEXT stack ps $PROJECT_NAME
    else
        echo ""
        echo "🐳 Docker Compose services:"
        DOCKER_CONTEXT=$DOCKER_CONTEXT docker-compose -f docker-compose.yml -p $PROJECT_NAME ps
    fi
}

action_delete() {
    if [[ -z "$INSTANCE_NAME" ]]; then
        echo "❌ Instance name required for DELETE"
        show_help
    fi

    PROJECT_NAME=$(find_project_by_instance)
    if [[ -z "$PROJECT_NAME" ]]; then
        echo "❌ Instance '$INSTANCE_NAME' not found"
        exit 1
    fi

    get_docker_info

    echo "🗑️  Deleting instance '$INSTANCE_NAME':"
    echo "   - Project: $PROJECT_NAME"
    echo "   - Domain: $FULL_DOMAIN"

    # Confirmer la suppression
    read -p "⚠️  Confirm deletion of '$INSTANCE_NAME'? (yes/no): " confirm
    if [[ "$confirm" != "yes" ]]; then
        echo "❌ Deletion cancelled"
        exit 1
    fi

    # Supprimer les services
    if docker --context $DOCKER_CONTEXT info --format '{{.Swarm.LocalNodeState}}' 2>/dev/null | grep -q "active"; then
        echo "🐝 Deleting Docker Swarm stack..."
        docker --context $DOCKER_CONTEXT stack rm $PROJECT_NAME

        # Wait for stack to be completely deleted
        sleep 10

        # Delete explicit volume
        VOLUME_NAME="nc_data_${INSTANCE_NAME}_${PROJECT_UID}"
        echo "🗑️  Deleting volume: $VOLUME_NAME"
        docker --context $DOCKER_CONTEXT volume rm $VOLUME_NAME 2>/dev/null || echo "Volume already deleted"
    else
        echo "🐳 Deleting Docker Compose services..."
        DOCKER_CONTEXT=$DOCKER_CONTEXT docker-compose -f docker-compose.yml -p $PROJECT_NAME down -v
    fi

    # Supprimer le CNAME
    delete_cname


    # Supprimer la config
    if [[ -f ".env.${PROJECT_NAME}" ]]; then
        rm ".env.${PROJECT_NAME}"
        echo "📄 Configuration deleted: .env.${PROJECT_NAME}"
    fi

    echo "✅ Instance '$INSTANCE_NAME' deleted successfully!"
}

action_list() {
    get_docker_info

    echo "📋 Instances deployed on '$DOCKER_CONTEXT' ($ENV):"
    echo ""

    # Lister depuis les fichiers .env
    local configs=($(ls .env.*-* 2>/dev/null))
    if [[ ${#configs[@]} -eq 0 ]]; then
        echo "   No instances found"
        return
    fi

    for config in "${configs[@]}"; do
        PROJECT_NAME=$(basename "$config" | sed 's/^\.env\.//')
        INSTANCE_NAME=$(echo "$PROJECT_NAME" | sed 's/-[^-]*$//')

        # Extraire le domaine du fichier
        if [[ -f "$config" ]]; then
            DOMAIN=$(grep "^DOMAIN=" "$config" | cut -d'=' -f2)
            CREATED=$(grep "# Created:" "$config" | sed 's/# Created: //')
        fi

        echo "   🔹 $INSTANCE_NAME"
        echo "      Projet: $PROJECT_NAME"
        echo "      Domaine: $DOMAIN"
        echo "      Created: ${CREATED:-'N/A'}"
        echo "      Config: $config"
        echo ""
    done

    # Stack/services status
    if docker --context $DOCKER_CONTEXT info --format '{{.Swarm.LocalNodeState}}' 2>/dev/null | grep -q "active"; then
        echo "🐝 Active Docker Swarm stacks:"
        docker --context $DOCKER_CONTEXT stack ls
    else
        echo "🐳 Active Docker Compose services:"
        docker --context $DOCKER_CONTEXT ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
    fi
}

action_update() {
    if [[ -z "$INSTANCE_NAME" ]]; then
        echo "❌ Instance name required for UPDATE"
        show_help
    fi

    PROJECT_NAME=$(find_project_by_instance)
    if [[ -z "$PROJECT_NAME" ]]; then
        echo "❌ Instance '$INSTANCE_NAME' not found"
        exit 1
    fi

    echo "🔄 Updating instance '$INSTANCE_NAME':"
    echo "   - Project: $PROJECT_NAME"

    # Redeploy with existing config
    export COMPOSE_PROJECT_NAME=$PROJECT_NAME

    if docker --context $DOCKER_CONTEXT info --format '{{.Swarm.LocalNodeState}}' 2>/dev/null | grep -q "active"; then
        echo "🐝 Updating Docker Swarm stack..."
        set -a
        source .env.${PROJECT_NAME}
        export INSTANCE_NAME=$INSTANCE_NAME
        export PROJECT_UID=$PROJECT_UID
        set +a
        docker --context $DOCKER_CONTEXT stack deploy -c docker-compose.yml $PROJECT_NAME
    else
        echo "🐳 Updating Docker Compose services..."
        DOCKER_CONTEXT=$DOCKER_CONTEXT docker-compose -f docker-compose.yml --env-file .env.${PROJECT_NAME} up -d
    fi

    echo "✅ Instance '$INSTANCE_NAME' updated successfully!"
}

# Router vers la bonne action
case "$ACTION" in
    create|c)
        action_create
        ;;
    read|r|status)
        action_read
        ;;
    update|u)
        action_update
        ;;
    delete|d|remove)
        action_delete
        ;;
    list|l|ls)
        action_list
        ;;
    help|h|--help|-h)
        show_help
        ;;
    *)
        echo "❌ Unknown action: $ACTION"
        show_help
        ;;
esac
 No newline at end of file
+49 −49
Original line number Diff line number Diff line
services:
  db:
    image: postgres:17.4-alpine
    restart: unless-stopped
    environment:
      - POSTGRES_DB=${DB_NAME}
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASSWORD}
    volumes:
      - db:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7.4-alpine
    restart: unless-stopped
    healthcheck:
      test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ]
      interval: 10s
      timeout: 5s
      retries: 5

  nextcloud:
    image: ${NEXTCLOUD_DOCKER_IMG}
    build:
      context: .
      dockerfile: ${NEXTCLOUD_DOCKERFILE}
    restart: unless-stopped
    environment:
      - POSTGRES_HOST=${DB_HOST}
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASSWORD}
      - POSTGRES_DB=${DB_NAME}
      - MYSQL_HOST=${DB_HOST}
      - MYSQL_USER=${DB_USER}
      - MYSQL_PASSWORD=${DB_PASSWORD}
      - MYSQL_DATABASE=${DB_NAME}
      - REDIS_HOST=${REDIS_HOST}
      - REDIS_HOST_PASSWORD=${REDIS_PASSWORD}
      - NEXTCLOUD_ADMIN_USER=${NEXTCLOUD_ADMIN_USER}
      - NEXTCLOUD_ADMIN_PASSWORD=${NEXTCLOUD_ADMIN_PASSWORD}
      - NEXTCLOUD_TRUSTED_DOMAINS=${NEXTCLOUD_TRUSTED_DOMAINS}
@@ -45,42 +22,65 @@ services:
      - SMTP_HOST=${SMTP_HOST}
      - MAIL_FROM_ADDRESS=${MAIL_FROM_ADDRESS}
      - MAIL_DOMAIN=${MAIL_DOMAIN}
      - SYSLOG_HOST=syslog
      - SYSLOG_HOST=syslog.dev.murenaworkspace.app
    volumes:
      - nextcloud:/var/www/html
    depends_on:
      syslog:
        condition: service_started
      db:
        condition: service_healthy
      redis:
        condition: service_healthy

  syslog:
    image: jumanjiman/rsyslog
    deploy:
      restart_policy:
        condition: any
      placement:
        constraints:
          - node.role == worker

  nextcloud-cron:
    image: ${NEXTCLOUD_DOCKER_IMG}
    restart: unless-stopped
    entrypoint: /cron.sh
    volumes:
      - nextcloud:/var/www/html
    depends_on:
      - nextcloud
    deploy:
      restart_policy:
        condition: any
      placement:
        constraints:
          - node.role == worker

  nginx:
    image: nginx:stable-alpine
    restart: unless-stopped
    environment:
      DOMAIN: ${DOMAIN}
    ports:
      - "8000:80"
      COMPOSE_PROJECT_NAME: ${COMPOSE_PROJECT_NAME:-nextcloud}
    configs:
      - source: nginx_config
        target: /etc/nginx/templates/default.conf.template
    volumes:
      - ${DEPLOYMENT_PATH:-.}/config/nginx/templates:/etc/nginx/templates
      - nextcloud:/var/www/html
    depends_on:
      - nextcloud
    deploy:
      restart_policy:
        condition: any
      placement:
        constraints:
          - node.role == worker
      labels:
        - traefik.enable=true
        - traefik.http.routers.${COMPOSE_PROJECT_NAME:-nextcloud}.rule=Host(`${DOMAIN}`)
        - traefik.http.routers.${COMPOSE_PROJECT_NAME:-nextcloud}.entrypoints=websecure
        - traefik.http.routers.${COMPOSE_PROJECT_NAME:-nextcloud}.tls.certresolver=letsencrypt
        - traefik.http.routers.${COMPOSE_PROJECT_NAME:-nextcloud}-http.rule=Host(`${DOMAIN}`)
        - traefik.http.routers.${COMPOSE_PROJECT_NAME:-nextcloud}-http.entrypoints=web
        - traefik.http.routers.${COMPOSE_PROJECT_NAME:-nextcloud}-http.middlewares=https-redirect
        - traefik.http.middlewares.https-redirect.redirectscheme.scheme=https
        - traefik.http.services.${COMPOSE_PROJECT_NAME:-nextcloud}.loadbalancer.server.port=80

volumes:
  db:
  nextcloud:
    external: true
    name: nc_data_${INSTANCE_NAME}_${PROJECT_UID}

networks:
  default:
    external: true
    name: nextcloud-network

configs:
  nginx_config:
    file: ./config/nginx/templates/default.conf.template
 No newline at end of file