From ad8a3da0e5babfec4352823d8ef65393d0874326 Mon Sep 17 00:00:00 2001 From: fadmin Date: Thu, 11 Jun 2026 11:08:50 -0400 Subject: [PATCH] install.sh --- install.sh | 242 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 install.sh diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..f7fd99f --- /dev/null +++ b/install.sh @@ -0,0 +1,242 @@ +#!/bin/bash + +# Exit on any error +set -e + +echo "=====================================" +echo " Stack Configuration Script " +echo "=====================================" + +# 1. Gather User Inputs +read -p "Enter your Let's Encrypt Email: " USER_EMAIL +if [ -z "$USER_EMAIL" ]; then echo "Error: Email cannot be empty."; exit 1; fi + +read -p "Enter base storage path (e.g., /opt/stack): " BASE_PATH +if [ -z "$BASE_PATH" ]; then echo "Error: Storage path cannot be empty."; exit 1; fi + +read -p "Enter your root domain (e.g., example.com): " ROOT_DOMAIN +if [ -z "$ROOT_DOMAIN" ]; then echo "Error: Domain cannot be empty."; exit 1; fi + +echo "-------------------------------------" +echo " Database & Admin Configuration " +echo "-------------------------------------" + +read -p "Enter MySQL Root Password: " MYSQL_ROOT_PASS +if [ -z "$MYSQL_ROOT_PASS" ]; then echo "Error: Password cannot be empty."; exit 1; fi + +read -p "Enter MySQL Nextcloud User Name [nc_user]: " MYSQL_USER +MYSQL_USER=${MYSQL_USER:-nc_user} + +read -p "Enter MySQL Nextcloud User Password: " MYSQL_PASS +if [ -z "$MYSQL_PASS" ]; then echo "Error: Password cannot be empty."; exit 1; fi + +read -p "Enter Nextcloud Admin Username [admin]: " NC_ADMIN +NC_ADMIN=${NC_ADMIN:-admin} + +read -p "Enter Nextcloud Admin Password: " NC_ADMIN_PASS +if [ -z "$NC_ADMIN_PASS" ]; then echo "Error: Password cannot be empty."; exit 1; fi + +# Clean trailing slashes if any from path +BASE_PATH=$(echo "$BASE_PATH" | sed 's:/*$::') + +echo "" +echo "Configuring environment..." +echo "-> Email: $USER_EMAIL" +echo "-> Base Location: $BASE_PATH" +echo "-> Database Name: mysql" +echo "-> Portainer Domain: portainer.$ROOT_DOMAIN" +echo "-> Nextcloud Domain: nextcloud.$ROOT_DOMAIN" +echo "=====================================" + +# 2. Setup local directory structures & required Traefik files +echo "Creating local directories..." +mkdir -p "$BASE_PATH/Traefik/files" +mkdir -p "$BASE_PATH/Portainer" +mkdir -p "$BASE_PATH/phpmyadmin/theme" +mkdir -p "$BASE_PATH/Nextcloud/data" +mkdir -p "$BASE_PATH/mysql/data" + +# Traefik requires acme.json to exist and have strict 600 permissions +if [ ! -f "$BASE_PATH/Traefik/acme.json" ]; then + echo "Creating empty acme.json with correct permissions..." + touch "$BASE_PATH/Traefik/acme.json" + chmod 600 "$BASE_PATH/Traefik/acme.json" +fi + +# Create a blank traefik.yml config file if it doesn't exist +if [ ! -f "$BASE_PATH/Traefik/files/traefik.yml" ]; then + touch "$BASE_PATH/Traefik/files/traefik.yml" +fi + +# Create a blank phpmyadmin config if it doesn't exist +if [ ! -f "$BASE_PATH/phpmyadmin/config.user.inc.php" ]; then + touch "$BASE_PATH/phpmyadmin/config.user.inc.php" +fi + +# 3. Ensure the external Docker network exists +echo "Checking Docker network 'web'..." +docker network inspect web >/dev/null 2>&1 || docker network create web + +# 4. Write the final docker-compose.yml file +echo "Generating docker-compose.yml..." +cat << EOF > docker-compose.yml +volumes: + redis_data: + driver: local + redis: + driver: local + letsencrypt: + driver: local + phpmyadmin: + driver: local + mysql_data: + driver: local + +services: + + traefik: + image: traefik:latest + container_name: Proxy + restart: unless-stopped + command: + - "--log.level=DEBUG" + - "--accesslog=true" + - "--api.insecure=true" + - "--providers.docker=true" + - "--providers.docker.exposedbydefault=true" + - "--entrypoints.web.address=:80" + - "--entrypoints.websecure.address=:443" + - "--entrypoints.web.http.redirections.entryPoint.to=websecure" + - "--entrypoints.web.http.redirections.entryPoint.scheme=https" + - "--certificatesresolvers.myresolver.acme.httpchallenge=true" + - "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web" + - "--certificatesresolvers.myresolver.acme.email=${USER_EMAIL}" + - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json" + ports: + - 80:80 + - 443:443 + - 8081:8080 + networks: + - web + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - letsencrypt:/letsencrypt + - ${BASE_PATH}/Traefik/acme.json:/acme.json + - ${BASE_PATH}/Traefik/files/:/etc/traefik/traefik.yml + + redis: + image: redis:latest + container_name: Redis + restart: unless-stopped + networks: + - web + volumes: + - redis:/var/lib/redis + - redis_data:/data + labels: + - traefik.enable=true + - traefik.backend=redis + + mysql: + image: mysql:8.0 + container_name: mysql + restart: unless-stopped + networks: + - web + environment: + - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASS} + - MYSQL_DATABASE=mysql + - MYSQL_USER=${MYSQL_USER} + - MYSQL_PASSWORD=${MYSQL_PASS} + volumes: + - ${BASE_PATH}/mysql/data:/var/lib/mysql + + NextCloud: + image: nextcloud:latest + container_name: NameOfYourContainer + restart: unless-stopped + depends_on: + - mysql + - redis + networks: + - web + labels: + - traefik.protocol=http + - traefik.port=80 + - traefik.http.routers.nextcloud.middlewares=nextcloud,nextcloud_redirect + - traefik.http.routers.nextcloud.tls=true + - traefik.http.routers.nextcloud.entrypoints=websecure + - traefik.http.routers.nextcloud.tls.certresolver=myresolver + - traefik.http.routers.nextcloud.rule=Host(\`nextcloud.${ROOT_DOMAIN}\`) + - traefik.http.middlewares.nextcloud.headers.customFrameOptionsValue=ALLOW-FR> + - traefik.http.middlewares.nextcloud.headers.stsSeconds=155520011 + - traefik.http.middlewares.nextcloud.headers.stsIncludeSubdomains=true + - traefik.http.middlewares.nextcloud.headers.stsPreload=true + - traefik.http.middlewares.nextcloud.redirectregex.regex=/.well-know> + - traefik.http.middlewares.nextcloud_redirect.redirectregex.replacement=/remo> + environment: + - MYSQL_HOST=mysql + - MYSQL_DATABASE=mysql + - MYSQL_USER=${MYSQL_USER} + - MYSQL_PASSWORD=${MYSQL_PASS} + - NEXTCLOUD_ADMIN_USER=${NC_ADMIN} + - NEXTCLOUD_ADMIN_PASSWORD=${NC_ADMIN_PASS} + - REDIS_HOST=redis + - NEXTCLOUD_TRUSTED_DOMAINS=nextcloud.${ROOT_DOMAIN} + - TRUSTED_PROXIES=172.18.0.0/16 + volumes: + - ${BASE_PATH}/Nextcloud/data/:/var/www/html + + portainer: + image: portainer/portainer-ce:latest + container_name: Container-WebUI + command: -H unix:///var/run/docker.sock + restart: always + labels: + - "traefik.enable=true" + - "traefik.http.routers.portainer.entrypoints=web" + - "traefik.http.routers.portainer.rule=Host(\`portainer.${ROOT_DOMAIN}\`)" + - "traefik.http.middlewares.portainer-https-redirect.redirectscheme.scheme=https" + - "traefik.http.routers.portainer.middlewares=portainer-https-redirect" + - "traefik.http.routers.portainer-secure.entrypoints=websecure" + - "traefik.http.routers.portainer-secure.rule=Host(\`portainer.${ROOT_DOMAIN}\`)" + - "traefik.http.routers.portainer-secure.tls=true" + - "traefik.http.routers.portainer-secure.tls.certresolver=myresolver" + - "traefik.http.routers.portainer-secure.service=portainer" + - "traefik.http.services.portainer.loadbalancer.server.port=9000" + - "traefik.docker.network=traefik-proxy" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ${BASE_PATH}/Portainer:/data + ports: + - 9001:9001 + - 8081:9000 + networks: + - web + + phpmyadmin: + image: phpmyadmin/phpmyadmin + container_name: Database-WebUI + restart: unless-stopped + networks: + - web + environment: + - PMA_ARBITRARY=1 + labels: + - traefik.backend=phpmyadmin + - traefik.http.routers.phpmyadmin.tls.certresolver=myresolver + - traefik.http.routers.phpmyadmin.rule=Host(\`phpmyadmin.${ROOT_DOMAIN}\`) + - traefik.docker.network=web + - traefik.port=80 + volumes: + - phpmyadmin:/sessions + - ${BASE_PATH}/phpmyadmin/config.user.inc.php:/etc/phpmyadmin/config.user.inc.php + - ${BASE_PATH}/phpmyadmin/theme/:/www/themes/theme/ + +networks: + web: + external: true +EOF + +echo "Done! 'docker-compose.yml' has been created successfully." +echo "You can now run: docker compose up -d" \ No newline at end of file