diff --git a/README.md b/README.md index e247bda7..515b3df8 100644 --- a/README.md +++ b/README.md @@ -52,10 +52,14 @@ (For production-grade installations, visit the [Install Docs](https://netmaker.readthedocs.io/en/master/install.html).) -1. Get a cloud VM with Ubuntu 20.04 and a public IP. -2. Open ports 443 and 51821-51830/udp on the VM firewall and in cloud security settings. -3. Run the script: `wget -qO - https://raw.githubusercontent.com/gravitl/netmaker/master/scripts/nm-quick.sh | sudo bash` -3.a. (with custom domain + email): `wget -qO - https://raw.githubusercontent.com/gravitl/netmaker/master/scripts/nm-quick.sh | sudo bash -s -- -d mynetmaker.domain.com -e example@email.com` +1. Get a cloud VM with Ubuntu 22.04 and a public IP. +2. Open ports 443, 80, and 51821-51830/udp on the VM firewall and in cloud security settings. +3. (optional) Prepare DNS - Set a wildcard subdomain in your DNS for Netmaker, e.g. *.netmaker.example.com +4. Run the script: + +`sudo wget -qO /root/nm-quick-interactive.sh https://raw.githubusercontent.com/gravitl/netmaker/test_v0.17.0_compose/scripts/nm-quick-interactive.sh && sudo chmod +x /root/nm-quick-interactive.sh && sudo /root/nm-quick-interactive.sh` + +This script gives you the option to deploy the Community or Enterprise version of Netmaker. If deploying Enterprise, you get a free account with a 50 node limit by default. It also gives you the option to use your own domain (recommended) or an auto-generated domain.

diff --git a/compose/docker-compose.ee.yml b/compose/docker-compose.ee.yml index fc8bf8fb..5e0ae3ed 100644 --- a/compose/docker-compose.ee.yml +++ b/compose/docker-compose.ee.yml @@ -3,7 +3,7 @@ version: "3.4" services: netmaker: container_name: netmaker - image: gravitl/netmaker:v0.16.3-ee + image: gravitl/netmaker:0.17.0-ee cap_add: - NET_ADMIN - NET_RAW @@ -45,17 +45,9 @@ services: MQ_ADMIN_PASSWORD: "REPLACE_MQ_ADMIN_PASSWORD" ports: - "51821-51830:51821-51830/udp" - expose: - - "8081" - labels: - - traefik.enable=true - - traefik.http.routers.netmaker-api.entrypoints=websecure - - traefik.http.routers.netmaker-api.rule=Host(`api.NETMAKER_BASE_DOMAIN`) - - traefik.http.routers.netmaker-api.service=netmaker-api - - traefik.http.services.netmaker-api.loadbalancer.server.port=8081 netmaker-ui: container_name: netmaker-ui - image: gravitl/netmaker-ui:v0.16.3 + image: gravitl/netmaker-ui:0.17.0 depends_on: - netmaker links: @@ -63,21 +55,17 @@ services: restart: always environment: BACKEND_URL: "https://api.NETMAKER_BASE_DOMAIN" - expose: - - "80" - labels: - - traefik.enable=true - - traefik.http.middlewares.nmui-security.headers.accessControlAllowOriginList=*.NETMAKER_BASE_DOMAIN - - traefik.http.middlewares.nmui-security.headers.stsSeconds=31536000 - - traefik.http.middlewares.nmui-security.headers.browserXssFilter=true - - traefik.http.middlewares.nmui-security.headers.customFrameOptionsValue=SAMEORIGIN - - traefik.http.middlewares.nmui-security.headers.customResponseHeaders.X-Robots-Tag=none - - traefik.http.middlewares.nmui-security.headers.customResponseHeaders.Server= # Remove the server name - - traefik.http.routers.netmaker-ui.entrypoints=websecure - - traefik.http.routers.netmaker-ui.middlewares=nmui-security@docker - - traefik.http.routers.netmaker-ui.rule=Host(`dashboard.NETMAKER_BASE_DOMAIN`) - - traefik.http.routers.netmaker-ui.service=netmaker-ui - - traefik.http.services.netmaker-ui.loadbalancer.server.port=80 + caddy: + image: caddy:2.6.2 + container_name: caddy + restart: unless-stopped + volumes: + - /root/Caddyfile:/etc/caddy/Caddyfile + - caddy_data:/data + - caddy_conf:/config + ports: + - "80:80" + - "443:443" coredns: container_name: coredns image: coredns/coredns @@ -87,26 +75,6 @@ services: restart: always volumes: - dnsconfig:/root/dnsconfig - traefik: - image: traefik:v2.9 - container_name: traefik - command: - - "--certificatesresolvers.http.acme.email=YOUR_EMAIL" - - "--certificatesresolvers.http.acme.storage=/letsencrypt/acme.json" - - "--certificatesresolvers.http.acme.tlschallenge=true" - - "--entrypoints.websecure.address=:443" - - "--entrypoints.websecure.http.tls=true" - - "--entrypoints.websecure.http.tls.certResolver=http" - - "--log.level=INFO" - - "--providers.docker=true" - - "--providers.docker.exposedByDefault=false" - - "--serverstransport.insecureskipverify=true" - restart: always - volumes: - - /var/run/docker.sock:/var/run/docker.sock:ro - - traefik_certs:/letsencrypt - ports: - - "443:443" mq: container_name: mq image: eclipse-mosquitto:2.0.15-openssl @@ -121,50 +89,29 @@ services: - /root/wait.sh:/mosquitto/config/wait.sh - mosquitto_data:/mosquitto/data - mosquitto_logs:/mosquitto/log - expose: - - "8883" - labels: - - traefik.enable=true - - traefik.http.routers.mqtt_websocket.rule=Host(`broker.NETMAKER_BASE_DOMAIN`) - - traefik.http.routers.mqtt_websocket.entrypoints=websecure - - traefik.http.routers.mqtt_websocket.tls.certresolver=http - - traefik.http.services.mqtt_websocket.loadbalancer.server.port=8883 + ports: + - "1883:1883" + - "8883:8883" prometheus: container_name: prometheus image: gravitl/netmaker-prometheus:latest environment: NETMAKER_METRICS_TARGET: "netmaker-exporter.NETMAKER_BASE_DOMAIN" LICENSE_KEY: "YOUR_LICENSE_KEY" - labels: - - traefik.enable=true - - traefik.http.routers.prometheus.entrypoints=websecure - - traefik.http.routers.prometheus.rule=Host(`prometheus.NETMAKER_BASE_DOMAIN`) - - traefik.http.services.prometheus.loadbalancer.server.port=9090 - - traefik.http.routers.prometheus.service=prometheus restart: always volumes: - prometheus_data:/prometheus depends_on: - netmaker - ports: - - 9090:9090 grafana: container_name: grafana image: gravitl/netmaker-grafana:latest - labels: - - traefik.enable=true - - traefik.http.routers.grafana.entrypoints=websecure - - traefik.http.routers.grafana.rule=Host(`grafana.NETMAKER_BASE_DOMAIN`) - - traefik.http.services.grafana.loadbalancer.server.port=3000 - - traefik.http.routers.grafana.service=grafana environment: PROMETHEUS_HOST: "prometheus.NETMAKER_BASE_DOMAIN" NETMAKER_METRICS_TARGET: "netmaker-exporter.NETMAKER_BASE_DOMAIN" LICENSE_KEY: "YOUR_LICENSE_KEY" volumes: - grafana_data:/var/lib/grafana - ports: - - 3000:3000 restart: always links: - prometheus @@ -174,12 +121,6 @@ services: netmaker-exporter: container_name: netmaker-exporter image: gravitl/netmaker-exporter:latest - labels: - - traefik.enable=true - - traefik.http.routers.netmaker-exporter.entrypoints=websecure - - traefik.http.routers.netmaker-exporter.rule=Host(`netmaker-exporter.NETMAKER_BASE_DOMAIN`) - - traefik.http.services.netmaker-exporter.loadbalancer.server.port=8085 - - traefik.http.routers.netmaker-exporter.service=netmaker-exporter restart: always depends_on: - netmaker @@ -192,10 +133,9 @@ services: API_PORT: "8085" LICENSE_KEY: "YOUR_LICENSE_KEY" PROMETHEUS_HOST: https://prometheus.NETMAKER_BASE_DOMAIN - expose: - - "8085" volumes: - traefik_certs: {} + caddy_data: {} + caddy_conf: {} sqldata: {} dnsconfig: {} mosquitto_data: {} diff --git a/compose/docker-compose.reference.yml b/compose/docker-compose.reference.yml index aaf793cb..0093446c 100644 --- a/compose/docker-compose.reference.yml +++ b/compose/docker-compose.reference.yml @@ -3,7 +3,7 @@ version: "3.4" services: netmaker: # The Primary Server for running Netmaker container_name: netmaker - image: gravitl/netmaker:v0.16.3 + image: gravitl/netmaker:v0.17.0 cap_add: - NET_ADMIN - NET_RAW @@ -52,17 +52,9 @@ services: OIDC_ISSUER: "" # https://oidc.yourprovider.com - URL of oidc provider ports: - "51821-51830:51821-51830/udp" # wireguard ports - expose: - - "8081" # api port - labels: # only for use with traefik proxy (default) - - traefik.enable=true - - traefik.http.routers.netmaker-api.entrypoints=websecure - - traefik.http.routers.netmaker-api.rule=Host(`api.NETMAKER_BASE_DOMAIN`) - - traefik.http.routers.netmaker-api.service=netmaker-api - - traefik.http.services.netmaker-api.loadbalancer.server.port=8081 netmaker-ui: # The Netmaker UI Component container_name: netmaker-ui - image: gravitl/netmaker-ui:v0.16.3 + image: gravitl/netmaker-ui:v0.17.0 depends_on: - netmaker links: @@ -70,21 +62,17 @@ services: restart: always environment: BACKEND_URL: "https://api.NETMAKER_BASE_DOMAIN" # URL where UI will send API requests. Change based on SERVER_HOST, SERVER_HTTP_HOST, and API_PORT - expose: - - "80" - labels: - - traefik.enable=true - - traefik.http.middlewares.nmui-security.headers.accessControlAllowOriginList=*.NETMAKER_BASE_DOMAIN - - traefik.http.middlewares.nmui-security.headers.stsSeconds=31536000 - - traefik.http.middlewares.nmui-security.headers.browserXssFilter=true - - traefik.http.middlewares.nmui-security.headers.customFrameOptionsValue=SAMEORIGIN - - traefik.http.middlewares.nmui-security.headers.customResponseHeaders.X-Robots-Tag=none - - traefik.http.middlewares.nmui-security.headers.customResponseHeaders.Server= # Remove the server name - - traefik.http.routers.netmaker-ui.entrypoints=websecure - - traefik.http.routers.netmaker-ui.middlewares=nmui-security@docker - - traefik.http.routers.netmaker-ui.rule=Host(`dashboard.NETMAKER_BASE_DOMAIN`) - - traefik.http.routers.netmaker-ui.service=netmaker-ui - - traefik.http.services.netmaker-ui.loadbalancer.server.port=80 + caddy: # The reverse proxy that manages traffic for Netmaker + image: caddy:2.6.2 + container_name: caddy + restart: unless-stopped + volumes: + - /root/Caddyfile:/etc/caddy/Caddyfile # Config file for Caddy + - caddy_data:/data + - caddy_conf:/config + ports: + - "80:80" + - "443:443" coredns: # The DNS Server. CoreDNS can be removed unless doing special advanced use cases container_name: coredns image: coredns/coredns @@ -94,26 +82,6 @@ services: restart: always volumes: - dnsconfig:/root/dnsconfig - traefik: # the default proxy - can be replaced with caddy or nginx, but requires careful configuration - image: traefik:v2.9 - container_name: traefik - command: - - "--certificatesresolvers.http.acme.email=YOUR_EMAIL" - - "--certificatesresolvers.http.acme.storage=/letsencrypt/acme.json" - - "--certificatesresolvers.http.acme.tlschallenge=true" - - "--entrypoints.websecure.address=:443" - - "--entrypoints.websecure.http.tls=true" - - "--entrypoints.websecure.http.tls.certResolver=http" - - "--log.level=INFO" - - "--providers.docker=true" - - "--providers.docker.exposedByDefault=false" - - "--serverstransport.insecureskipverify=true" - restart: always - volumes: - - /var/run/docker.sock:/var/run/docker.sock:ro - - traefik_certs:/letsencrypt - ports: - - "443:443" mq: # the MQTT broker for netmaker container_name: mq image: eclipse-mosquitto:2.0.15-openssl @@ -125,17 +93,12 @@ services: - mosquitto_data:/mosquitto/data - mosquitto_logs:/mosquitto/log - shared_certs:/mosquitto/certs - expose: - - "8883" - labels: - - traefik.enable=true - - traefik.http.routers.mqtt_websocket.rule=Host(`broker.NETMAKER_BASE_DOMAIN`) - - traefik.http.routers.mqtt_websocket.entrypoints=websecure - - traefik.http.routers.mqtt_websocket.tls.passthrough=true - - traefik.http.services.mqtts-svc.loadbalancer.server.port=8883 - - traefik.http.routers.mqtt_websocket.service=mqtts-svc + ports: + - "1883:1883" + - "8883:8883" volumes: - traefik_certs: {} # ssl certificates - auto generated + caddy_data: {} # runtime data for caddy + caddy_conf: {} # configuration file for Caddy shared_certs: {} # netmaker certs generated for MQ comms - used by nodes/servers sqldata: {} # storage for embedded sqlite dnsconfig: {} # storage for coredns diff --git a/compose/docker-compose.yml b/compose/docker-compose.yml index 2fe91030..9529d567 100644 --- a/compose/docker-compose.yml +++ b/compose/docker-compose.yml @@ -3,7 +3,7 @@ version: "3.4" services: netmaker: container_name: netmaker - image: gravitl/netmaker:v0.16.3 + image: gravitl/netmaker:v0.17.0 cap_add: - NET_ADMIN - NET_RAW @@ -42,17 +42,9 @@ services: MQ_ADMIN_PASSWORD: "REPLACE_MQ_ADMIN_PASSWORD" ports: - "51821-51830:51821-51830/udp" - expose: - - "8081" - labels: - - traefik.enable=true - - traefik.http.routers.netmaker-api.entrypoints=websecure - - traefik.http.routers.netmaker-api.rule=Host(`api.NETMAKER_BASE_DOMAIN`) - - traefik.http.routers.netmaker-api.service=netmaker-api - - traefik.http.services.netmaker-api.loadbalancer.server.port=8081 netmaker-ui: container_name: netmaker-ui - image: gravitl/netmaker-ui:v0.16.3 + image: gravitl/netmaker-ui:v0.17.0 depends_on: - netmaker links: @@ -60,21 +52,17 @@ services: restart: always environment: BACKEND_URL: "https://api.NETMAKER_BASE_DOMAIN" - expose: - - "80" - labels: - - traefik.enable=true - - traefik.http.middlewares.nmui-security.headers.accessControlAllowOriginList=*.NETMAKER_BASE_DOMAIN - - traefik.http.middlewares.nmui-security.headers.stsSeconds=31536000 - - traefik.http.middlewares.nmui-security.headers.browserXssFilter=true - - traefik.http.middlewares.nmui-security.headers.customFrameOptionsValue=SAMEORIGIN - - traefik.http.middlewares.nmui-security.headers.customResponseHeaders.X-Robots-Tag=none - - traefik.http.middlewares.nmui-security.headers.customResponseHeaders.Server= # Remove the server name - - traefik.http.routers.netmaker-ui.entrypoints=websecure - - traefik.http.routers.netmaker-ui.middlewares=nmui-security@docker - - traefik.http.routers.netmaker-ui.rule=Host(`dashboard.NETMAKER_BASE_DOMAIN`) - - traefik.http.routers.netmaker-ui.service=netmaker-ui - - traefik.http.services.netmaker-ui.loadbalancer.server.port=80 + caddy: + image: caddy:2.6.2 + container_name: caddy + restart: unless-stopped + volumes: + - /root/Caddyfile:/etc/caddy/Caddyfile + - caddy_data:/data + - caddy_conf:/config + ports: + - "80:80" + - "443:443" coredns: container_name: coredns image: coredns/coredns @@ -84,26 +72,6 @@ services: restart: always volumes: - dnsconfig:/root/dnsconfig - traefik: - image: traefik:v2.9 - container_name: traefik - command: - - "--certificatesresolvers.http.acme.email=YOUR_EMAIL" - - "--certificatesresolvers.http.acme.storage=/letsencrypt/acme.json" - - "--certificatesresolvers.http.acme.tlschallenge=true" - - "--entrypoints.websecure.address=:443" - - "--entrypoints.websecure.http.tls=true" - - "--entrypoints.websecure.http.tls.certResolver=http" - - "--log.level=INFO" - - "--providers.docker=true" - - "--providers.docker.exposedByDefault=false" - - "--serverstransport.insecureskipverify=true" - restart: always - volumes: - - /var/run/docker.sock:/var/run/docker.sock:ro - - traefik_certs:/letsencrypt - ports: - - "443:443" mq: container_name: mq image: eclipse-mosquitto:2.0.15-openssl @@ -118,17 +86,13 @@ services: - /root/wait.sh:/mosquitto/config/wait.sh - mosquitto_data:/mosquitto/data - mosquitto_logs:/mosquitto/log - expose: - - "8883" - labels: - - traefik.enable=true - - traefik.http.routers.mqtt_websocket.rule=Host(`broker.NETMAKER_BASE_DOMAIN`) - - traefik.http.routers.mqtt_websocket.entrypoints=websecure - - traefik.http.routers.mqtt_websocket.tls.certresolver=http - - traefik.http.services.mqtt_websocket.loadbalancer.server.port=8883 + ports: + - "1883:1883" + - "8883:8883" volumes: - traefik_certs: {} + caddy_data: {} + caddy_conf: {} sqldata: {} dnsconfig: {} mosquitto_data: {} - mosquitto_logs: {} + mosquitto_logs: {} \ No newline at end of file diff --git a/docker/Caddyfile b/docker/Caddyfile index 98e74b87..a5b09f1d 100644 --- a/docker/Caddyfile +++ b/docker/Caddyfile @@ -28,3 +28,8 @@ https://dashboard.NETMAKER_BASE_DOMAIN { https://api.NETMAKER_BASE_DOMAIN { reverse_proxy http://netmaker:8081 } + +# MQ +wss://broker.NETMAKER_BASE_DOMAIN { + reverse_proxy ws://mq:8883 +} diff --git a/docker/Caddyfile-EE b/docker/Caddyfile-EE new file mode 100644 index 00000000..6555977e --- /dev/null +++ b/docker/Caddyfile-EE @@ -0,0 +1,50 @@ +{ + # LetsEncrypt account + email YOUR_EMAIL +} + +# Dashboard +https://dashboard.NETMAKER_BASE_DOMAIN { + # Apply basic security headers + header { + # Enable cross origin access to *.NETMAKER_BASE_DOMAIN + Access-Control-Allow-Origin *.NETMAKER_BASE_DOMAIN + # Enable HTTP Strict Transport Security (HSTS) + Strict-Transport-Security "max-age=31536000;" + # Enable cross-site filter (XSS) and tell browser to block detected attacks + X-XSS-Protection "1; mode=block" + # Disallow the site to be rendered within a frame on a foreign domain (clickjacking protection) + X-Frame-Options "SAMEORIGIN" + # Prevent search engines from indexing + X-Robots-Tag "none" + # Remove the server name + -Server + } + + reverse_proxy http://netmaker-ui +} + +# Netmaker Exporter +https://netmaker-exporter.NETMAKER_BASE_DOMAIN { + reverse_proxy http://netmaker-exporter:8085 +} + +# Prometheus +https://prometheus.NETMAKER_BASE_DOMAIN { + reverse_proxy http://prometheus:9090 +} + +# Grafana +https://grafana.NETMAKER_BASE_DOMAIN { + reverse_proxy http://grafana:3000 +} + +# API +https://api.NETMAKER_BASE_DOMAIN { + reverse_proxy http://netmaker:8081 +} + +# MQ +wss://broker.NETMAKER_BASE_DOMAIN { + reverse_proxy ws://mq:8883 +} diff --git a/scripts/nm-quick-interactive.sh b/scripts/nm-quick-interactive.sh index 7842a3f3..4f942683 100644 --- a/scripts/nm-quick-interactive.sh +++ b/scripts/nm-quick-interactive.sh @@ -17,6 +17,11 @@ cat << "EOF" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - EOF +if [ $(id -u) -ne 0 ]; then + echo "This script must be run as root" + exit 1 +fi + if [ -z "$1" ]; then echo "-----------------------------------------------------" echo "Would you like to install Netmaker Community Edition (CE), or Netmaker Enterprise Edition (EE)?" @@ -61,17 +66,12 @@ confirm() {( read -p 'Does everything look right? [y/n]: ' yn case $yn in [Yy]* ) override="true"; break;; - [Nn]* ) echo "exiting..."; exit;; + [Nn]* ) echo "exiting..."; exit 1;; * ) echo "Please answer yes or no.";; esac done )} -if [ $(id -u) -ne 0 ]; then - echo "This script must be run as root" - exit 1 -fi - echo "checking dependencies..." OS=$(uname) @@ -124,6 +124,9 @@ if [ -z "${install_cmd}" ]; then fi set -- $dependencies + +${update_cmd} + while [ -n "$1" ]; do if [ "${OS}" = "FreeBSD" ]; then is_installed=$(pkg check -d $1 | grep "Checking" | grep "done") @@ -186,7 +189,6 @@ COREDNS_IP=$(ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p') SERVER_PUBLIC_IP=$(curl -s ifconfig.me) MASTER_KEY=$(tr -dc A-Za-z0-9 &1) if [[ "$i" == 6 ]]; then - echo " Traefik is having an issue setting up certificates, please investigate (docker logs traefik)" + echo " Caddy is having an issue setting up certificates, please investigate (docker logs caddy)" echo " Exiting..." exit 1 elif [[ "$curlresponse" == *"failed to verify the legitimacy of the server"* ]]; then @@ -357,12 +368,22 @@ wait_seconds 3 echo "Configuring netmaker server as ingress gateway" - -while [ -z "$SERVER_ID" ]; do - echo "waiting for server node to become available" - wait_seconds 2 +for i in 1 2 3 4 5 6 +do + echo " waiting for server node to become available" + wait_seconds 5 curlresponse=$(curl -s -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/nodes/netmaker) SERVER_ID=$(jq -r '.[0].id' <<< ${curlresponse}) + if [[ "$i" == 6 && -z "$SERVER_ID" ]]; then + echo " Netmaker is having issues configuring itself, please investigate (docker logs netmaker)" + echo " Exiting..." + exit 1 + elif [ -z "$SERVER_ID" ]; then + echo " server node not yet configured, retrying..." + else + echo " server node is now availble, continuing" + break + fi done curl -o /dev/null -s -X POST -H "Authorization: Bearer $MASTER_KEY" -H 'Content-Type: application/json' https://api.${NETMAKER_BASE_DOMAIN}/api/nodes/netmaker/$SERVER_ID/createingress diff --git a/scripts/nm-quick.sh b/scripts/nm-quick.sh index d08afe2d..7ee33a66 100755 --- a/scripts/nm-quick.sh +++ b/scripts/nm-quick.sh @@ -128,6 +128,7 @@ sleep 5 echo "setting mosquitto.conf..." wget -q -O /root/mosquitto.conf https://raw.githubusercontent.com/gravitl/netmaker/master/docker/mosquitto.conf +wget -q -O /root/Caddyfile https://raw.githubusercontent.com/gravitl/netmaker/master/docker/Caddyfile wget -q -O /root/wait.sh https://raw.githubusercontent.com/gravitl/netmaker/master/docker/wait.sh chmod +x /root/wait.sh echo "setting docker-compose..." @@ -136,10 +137,11 @@ mkdir -p /etc/netmaker wget -q -O /root/docker-compose.yml https://raw.githubusercontent.com/gravitl/netmaker/master/compose/docker-compose.yml sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/docker-compose.yml +sed -i "s/NETMAKER_BASE_DOMAIN/$NETMAKER_BASE_DOMAIN/g" /root/Caddyfile sed -i "s/SERVER_PUBLIC_IP/$SERVER_PUBLIC_IP/g" /root/docker-compose.yml sed -i "s/COREDNS_IP/$COREDNS_IP/g" /root/docker-compose.yml sed -i "s/REPLACE_MASTER_KEY/$MASTER_KEY/g" /root/docker-compose.yml -sed -i "s/YOUR_EMAIL/$EMAIL/g" /root/docker-compose.yml +sed -i "s/YOUR_EMAIL/$EMAIL/g" /root/Caddyfile sed -i "s/REPLACE_MQ_ADMIN_PASSWORD/$MQ_ADMIN_PASSWORD/g" /root/docker-compose.yml echo "starting containers..."