mirror of
https://github.com/absmach/magistrala.git
synced 2026-06-23 04:10:28 +00:00
NOISSUE - Add a fast Certbot startup (#3517)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
This commit is contained in:
@@ -144,7 +144,7 @@ FILTERED_SERVICES = $(filter-out $(RUN_ADDON_ARGS), $(SERVICES))
|
||||
|
||||
all: $(SERVICES)
|
||||
|
||||
.PHONY: all $(SERVICES) dockers dockers_dev latest release run_latest run_stable run_addons grpc_mtls_certs check_mtls check_certs test_api mocks
|
||||
.PHONY: all $(SERVICES) dockers dockers_dev latest release run_latest run_tls run_stable run_addons grpc_mtls_certs check_mtls check_certs test_api mocks
|
||||
|
||||
clean:
|
||||
rm -rf ${BUILD_DIR}
|
||||
@@ -293,6 +293,17 @@ run_latest: check_certs
|
||||
$(SED_INPLACE) 's/^MG_RELEASE_TAG=.*/MG_RELEASE_TAG=latest/' docker/.env
|
||||
$(DOCKER_PLATFORM) docker compose -f docker/docker-compose.yaml --env-file docker/.env -p $(DOCKER_PROJECT) $(DOCKER_COMPOSE_COMMAND) $(args)
|
||||
|
||||
run_tls:
|
||||
@test -n "$(host)" || (echo "Usage: make run_tls host=example.com [email=admin@example.com] [letsencrypt=false] [staging=false] [force=true]" && exit 2)
|
||||
@if [ "$(or $(letsencrypt),true)" != "false" ] && [ -z "$(email)" ]; then echo "Usage: make run_tls host=example.com email=admin@example.com [letsencrypt=false] [staging=false] [force=true]"; exit 2; fi
|
||||
MG_PUBLIC_HOST="$(host)" \
|
||||
MG_LETSENCRYPT_ENABLED="$(or $(letsencrypt),true)" \
|
||||
MG_LETSENCRYPT_EMAIL="$(email)" \
|
||||
MG_LETSENCRYPT_STAGING="$(or $(staging),true)" \
|
||||
MG_LETSENCRYPT_FORCE_RENEWAL="$(or $(force),false)" \
|
||||
DOCKER_PROJECT="$(DOCKER_PROJECT)" \
|
||||
./docker/setup-tls.sh
|
||||
|
||||
run_stable: check_certs
|
||||
$(eval version = $(shell git describe --abbrev=0 --tags))
|
||||
git checkout $(version)
|
||||
|
||||
@@ -7,12 +7,21 @@
|
||||
GRPC_MTLS=
|
||||
|
||||
## NginX
|
||||
MG_PUBLIC_HOST=localhost
|
||||
MG_UI_HOST=ui
|
||||
MG_LETSENCRYPT_ENABLED=false
|
||||
MG_LETSENCRYPT_EMAIL=
|
||||
MG_LETSENCRYPT_STAGING=true
|
||||
MG_LETSENCRYPT_FORCE_RENEWAL=false
|
||||
MG_NGINX_HTTP_PORT=80
|
||||
MG_NGINX_SSL_PORT=443
|
||||
MG_NGINX_MQTT_PORT=1883
|
||||
MG_NGINX_MQTTS_PORT=8883
|
||||
MG_NGINX_AMQP_PORT=5682
|
||||
MG_NGINX_SERVER_NAME=
|
||||
# After issuing a Let's Encrypt certificate, uncomment these paths and restart nginx.
|
||||
# MG_NGINX_SERVER_CERT=./ssl/letsencrypt/live/${MG_PUBLIC_HOST}/fullchain.pem
|
||||
# MG_NGINX_SERVER_KEY=./ssl/letsencrypt/live/${MG_PUBLIC_HOST}/privkey.pem
|
||||
|
||||
## FluxMQ Cluster
|
||||
MG_FLUXMQ_IMAGE_TAG=latest
|
||||
|
||||
+62
-7
@@ -129,16 +129,71 @@ services:
|
||||
Nginx is the entry point for all traffic to Magistrala.
|
||||
By using environment variables file at `docker/.env` you can modify the below given Nginx directive.
|
||||
|
||||
| Environment Variable | Description |
|
||||
|----------------------|-------------|
|
||||
| `MG_NGINX_SERVER_NAME` | `MG_NGINX_SERVER_NAME` environmental variable is used to configure nginx directive `server_name`. If environmental variable `MG_NGINX_SERVER_NAME` is empty then default value `localhost` will set to `server_name`. |
|
||||
| `MG_NGINX_SERVER_CERT` | `MG_NGINX_SERVER_CERT` environmental variable is used to configure nginx directive `ssl_certificate`. If environmental variable `MG_NGINX_SERVER_CERT` is empty then by default server certificate in the path `docker/ssl/certs/magistrala-server.crt` will be assigned. |
|
||||
| `MG_NGINX_SERVER_KEY` | `MG_NGINX_SERVER_KEY` environmental variable is used to configure nginx directive `ssl_certificate_key`. If environmental variable `MG_NGINX_SERVER_KEY` is empty then by default server certificate key in the path `docker/ssl/certs/magistrala-server.key` will be assigned. |
|
||||
| `MG_NGINX_SERVER_CLIENT_CA` | `MG_NGINX_SERVER_CLIENT_CA` environmental variable is used to configure nginx directive `ssl_client_certificate`. If environmental variable `MG_NGINX_SERVER_CLIENT_CA` is empty then by default certificate in the path `docker/ssl/certs/ca.crt` will be assigned. |
|
||||
| `MG_NGINX_SERVER_DHPARAM` | `MG_NGINX_SERVER_DHPARAM` environmental variable is used to configure nginx directive `ssl_dhparam`. If environmental variable `MG_NGINX_SERVER_DHPARAM` is empty then by default file in the path `docker/ssl/dhparam.pem` will be assigned. |
|
||||
| Environment Variable | Description |
|
||||
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `MG_PUBLIC_HOST` | Public DNS name for the Docker host. This value is used by UI URLs and Let's Encrypt certificate requests. |
|
||||
| `MG_UI_HOST` | Internal Compose hostname for the UI service. Defaults to `ui`. |
|
||||
| `MG_LETSENCRYPT_ENABLED` | Set to `true` to request and use a Let's Encrypt certificate. Set to `false` to comment out the Let's Encrypt cert/key paths and use the fallback Nginx certificate. |
|
||||
| `MG_LETSENCRYPT_EMAIL` | Email address used by Let's Encrypt for expiry and account notifications. Required when running the `letsencrypt` profile. |
|
||||
| `MG_LETSENCRYPT_STAGING` | Set to `true` to request staging certificates while testing. Set to `false` for trusted production certificates. |
|
||||
| `MG_LETSENCRYPT_FORCE_RENEWAL` | Set to `true` for one certbot run when replacing a staging certificate with a production certificate. Set it back to `false` after the production certificate is issued. |
|
||||
| `MG_NGINX_SERVER_NAME` | `MG_NGINX_SERVER_NAME` environmental variable is used to configure nginx directive `server_name`. If environmental variable `MG_NGINX_SERVER_NAME` is empty then default value `localhost` will set to `server_name`. |
|
||||
| `MG_NGINX_SERVER_CERT` | `MG_NGINX_SERVER_CERT` environmental variable is used to configure nginx directive `ssl_certificate`. If environmental variable `MG_NGINX_SERVER_CERT` is empty then by default server certificate in the path `docker/ssl/certs/magistrala-server.crt` will be assigned. |
|
||||
| `MG_NGINX_SERVER_KEY` | `MG_NGINX_SERVER_KEY` environmental variable is used to configure nginx directive `ssl_certificate_key`. If environmental variable `MG_NGINX_SERVER_KEY` is empty then by default server certificate key in the path `docker/ssl/certs/magistrala-server.key` will be assigned. |
|
||||
| `MG_NGINX_SERVER_CLIENT_CA` | `MG_NGINX_SERVER_CLIENT_CA` environmental variable is used to configure nginx directive `ssl_client_certificate`. If environmental variable `MG_NGINX_SERVER_CLIENT_CA` is empty then by default certificate in the path `docker/ssl/certs/ca.crt` will be assigned. |
|
||||
| `MG_NGINX_SERVER_DHPARAM` | `MG_NGINX_SERVER_DHPARAM` environmental variable is used to configure nginx directive `ssl_dhparam`. If environmental variable `MG_NGINX_SERVER_DHPARAM` is empty then by default file in the path `docker/ssl/dhparam.pem` will be assigned. |
|
||||
|
||||
Adjust these values in `.env` to configure TLS / SSL behavior for your deployment.
|
||||
|
||||
### HTTPS UI with Let's Encrypt
|
||||
|
||||
The Compose stack can request and renew a Let's Encrypt certificate with the optional `letsencrypt` profile. This secures the public Nginx entrypoint and serves the UI through `https://${MG_PUBLIC_HOST}/`. Plain UI requests to `/` are redirected to HTTPS, while API and messaging routes keep their existing protocol behavior. Certbot stores challenge files and issued certificates under ignored local paths in `docker/ssl/`.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- `MG_PUBLIC_HOST` must resolve to the Docker host.
|
||||
- Ports `80` and `443` must be reachable from the public internet.
|
||||
- Set `MG_LETSENCRYPT_EMAIL` before requesting a certificate.
|
||||
|
||||
For a staging certificate, run one command from the project root:
|
||||
|
||||
```bash
|
||||
make run_tls host=example.com email=admin@example.com
|
||||
```
|
||||
|
||||
For a trusted production certificate, set `staging=false`:
|
||||
|
||||
```bash
|
||||
make run_tls host=example.com email=admin@example.com staging=false
|
||||
```
|
||||
|
||||
The target updates `docker/.env`, starts the Compose stack with the fallback certificate, runs certbot, switches Nginx to the issued certificate, and recreates Nginx. It also sets `MG_UI_DOCKER_ACCEPT_EULA=yes` for the UI container and configures public UI URLs to `https://${MG_PUBLIC_HOST}`.
|
||||
|
||||
To configure the same instance without Let's Encrypt, use:
|
||||
|
||||
```bash
|
||||
make run_tls host=example.com letsencrypt=false
|
||||
```
|
||||
|
||||
That command updates `docker/.env`, comments out `MG_NGINX_SERVER_CERT` and `MG_NGINX_SERVER_KEY`, stops certbot if it exists, and runs the stack with the fallback Nginx certificate.
|
||||
|
||||
If you are replacing an existing valid certificate and want certbot to request a new one immediately, pass `force=true`:
|
||||
|
||||
```bash
|
||||
make run_tls host=example.com email=admin@example.com staging=false force=true
|
||||
```
|
||||
|
||||
The generated certificate paths in `docker/.env` are:
|
||||
|
||||
```env
|
||||
MG_NGINX_SERVER_CERT=./ssl/letsencrypt/live/<host>/fullchain.pem
|
||||
MG_NGINX_SERVER_KEY=./ssl/letsencrypt/live/<host>/privkey.pem
|
||||
```
|
||||
|
||||
The setup script comments or uncomments those values automatically. Operators should not need to edit them by hand.
|
||||
|
||||
The certbot service keeps running and checks renewal twice a day. When a certificate is renewed, it sends a `HUP` signal to the Nginx process so new TLS handshakes use the renewed certificate.
|
||||
|
||||
## Makefile Integration
|
||||
|
||||
The included `Makefile` defines build and Docker‑build targets for all Magistrala services. Key points:
|
||||
|
||||
@@ -525,6 +525,8 @@ services:
|
||||
- type: bind
|
||||
source: ${MG_NGINX_SERVER_DHPARAM:-./ssl/dhparam.pem}
|
||||
target: /etc/ssl/certs/dhparam.pem
|
||||
- ./ssl/letsencrypt:/etc/letsencrypt:ro
|
||||
- ./ssl/certbot-www:/var/www/certbot:ro
|
||||
ports:
|
||||
- ${MG_NGINX_HTTP_PORT}:${MG_NGINX_HTTP_PORT}
|
||||
- ${MG_NGINX_SSL_PORT}:${MG_NGINX_SSL_PORT}
|
||||
@@ -544,6 +546,63 @@ services:
|
||||
soft: 65536
|
||||
hard: 65536
|
||||
|
||||
certbot:
|
||||
image: docker.io/certbot/certbot:v2.11.0
|
||||
container_name: magistrala-certbot
|
||||
profiles:
|
||||
- letsencrypt
|
||||
depends_on:
|
||||
- nginx
|
||||
pid: "service:nginx"
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- .env
|
||||
volumes:
|
||||
- ./ssl/letsencrypt:/etc/letsencrypt
|
||||
- ./ssl/certbot-www:/var/www/certbot
|
||||
entrypoint: /bin/sh
|
||||
command:
|
||||
- -c
|
||||
- |
|
||||
if [ -z "$${MG_PUBLIC_HOST}" ] || [ "$${MG_PUBLIC_HOST}" = "localhost" ]; then
|
||||
echo "Set MG_PUBLIC_HOST to a public DNS name before requesting a Let's Encrypt certificate." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$${MG_LETSENCRYPT_EMAIL}" ]; then
|
||||
echo "Set MG_LETSENCRYPT_EMAIL before requesting a Let's Encrypt certificate." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
staging_arg=""
|
||||
if [ "$${MG_LETSENCRYPT_STAGING}" = "true" ]; then
|
||||
staging_arg="--staging"
|
||||
fi
|
||||
renewal_arg="--keep-until-expiring"
|
||||
if [ "$${MG_LETSENCRYPT_FORCE_RENEWAL}" = "true" ]; then
|
||||
renewal_arg="--force-renewal"
|
||||
fi
|
||||
|
||||
certbot certonly \
|
||||
--webroot \
|
||||
--webroot-path /var/www/certbot \
|
||||
--domain "$${MG_PUBLIC_HOST}" \
|
||||
--email "$${MG_LETSENCRYPT_EMAIL}" \
|
||||
--agree-tos \
|
||||
--no-eff-email \
|
||||
--non-interactive \
|
||||
$${renewal_arg} \
|
||||
$${staging_arg}
|
||||
|
||||
while :; do
|
||||
certbot renew \
|
||||
--webroot \
|
||||
--webroot-path /var/www/certbot \
|
||||
--quiet \
|
||||
--deploy-hook "kill -HUP 1" \
|
||||
$${staging_arg}
|
||||
sleep 12h & wait $$!
|
||||
done
|
||||
|
||||
clients-db:
|
||||
image: docker.io/postgres:18.0-alpine3.22
|
||||
container_name: magistrala-clients-db
|
||||
|
||||
@@ -71,6 +71,12 @@ http {
|
||||
add_header Access-Control-Allow-Methods '*';
|
||||
add_header Access-Control-Allow-Headers '*';
|
||||
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
root /var/www/certbot;
|
||||
default_type text/plain;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
# Proxy pass to auth service
|
||||
location ~ ^/(pats) {
|
||||
include snippets/proxy-headers.conf;
|
||||
@@ -156,6 +162,9 @@ http {
|
||||
include snippets/ws-upgrade.conf;
|
||||
proxy_pass http://mqtt_ws_cluster;
|
||||
}
|
||||
|
||||
# UI proxy – populated by docker/setup-tls.sh; empty = no catch-all (local dev)
|
||||
include snippets/ui-proxy.conf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,12 @@ http {
|
||||
add_header Access-Control-Allow-Methods '*';
|
||||
add_header Access-Control-Allow-Headers '*';
|
||||
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
root /var/www/certbot;
|
||||
default_type text/plain;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
# Proxy pass to auth service
|
||||
location ~ ^/(pats) {
|
||||
include snippets/proxy-headers.conf;
|
||||
@@ -168,6 +174,9 @@ http {
|
||||
include snippets/ws-upgrade.conf;
|
||||
proxy_pass http://mqtt_ws_cluster;
|
||||
}
|
||||
|
||||
# UI proxy – populated by docker/setup-tls.sh; empty = no catch-all (local dev)
|
||||
include snippets/ui-proxy.conf;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
proxy_redirect off;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Copyright (c) Abstract Machines
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This file is written by docker/setup-tls.sh for TLS deployments.
|
||||
# It is intentionally empty for local development (make run_latest).
|
||||
Executable
+242
@@ -0,0 +1,242 @@
|
||||
#!/usr/bin/env sh
|
||||
# Copyright (c) Abstract Machines
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -eu
|
||||
|
||||
ROOT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
|
||||
ENV_FILE="$ROOT_DIR/docker/.env"
|
||||
COMPOSE_FILE="$ROOT_DIR/docker/docker-compose.yaml"
|
||||
|
||||
HOST=${MG_PUBLIC_HOST:-}
|
||||
EMAIL=${MG_LETSENCRYPT_EMAIL:-}
|
||||
LETSENCRYPT_ENABLED=${MG_LETSENCRYPT_ENABLED:-true}
|
||||
STAGING=${MG_LETSENCRYPT_STAGING:-true}
|
||||
FORCE_RENEWAL=${MG_LETSENCRYPT_FORCE_RENEWAL:-false}
|
||||
PROJECT=${DOCKER_PROJECT:-magistrala}
|
||||
TIMEOUT_SECONDS=${MG_LETSENCRYPT_TIMEOUT_SECONDS:-180}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage:
|
||||
MG_PUBLIC_HOST=example.com MG_LETSENCRYPT_EMAIL=admin@example.com [MG_LETSENCRYPT_STAGING=false] $0
|
||||
MG_PUBLIC_HOST=example.com MG_LETSENCRYPT_ENABLED=false $0
|
||||
|
||||
Required:
|
||||
MG_PUBLIC_HOST Public DNS name that points to this Docker host.
|
||||
MG_LETSENCRYPT_EMAIL Email address for Let's Encrypt notices when
|
||||
MG_LETSENCRYPT_ENABLED=true.
|
||||
|
||||
Optional:
|
||||
MG_LETSENCRYPT_ENABLED true by default. Set false to use the fallback
|
||||
Nginx certificate and comment out Let's Encrypt
|
||||
cert/key paths in docker/.env.
|
||||
MG_LETSENCRYPT_STAGING true by default. Set false for production certs.
|
||||
MG_LETSENCRYPT_FORCE_RENEWAL
|
||||
false by default. Set true to replace an existing cert.
|
||||
DOCKER_PROJECT Compose project name. Defaults to magistrala.
|
||||
MG_LETSENCRYPT_TIMEOUT_SECONDS
|
||||
Wait time for certificate files. Defaults to 180.
|
||||
EOF
|
||||
}
|
||||
|
||||
if [ -z "$HOST" ]; then
|
||||
usage >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
case "$LETSENCRYPT_ENABLED" in
|
||||
true|false)
|
||||
;;
|
||||
*)
|
||||
echo "MG_LETSENCRYPT_ENABLED must be true or false." >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$LETSENCRYPT_ENABLED" = "true" ] && [ -z "$EMAIL" ]; then
|
||||
usage >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ "$LETSENCRYPT_ENABLED" = "true" ] && [ "$HOST" = "localhost" ]; then
|
||||
echo "MG_PUBLIC_HOST must be a public DNS name, not localhost." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
echo "Missing $ENV_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set_env() {
|
||||
key=$1
|
||||
value=$2
|
||||
tmp=$(mktemp)
|
||||
awk -v key="$key" -v value="$value" '
|
||||
BEGIN { done = 0 }
|
||||
!done && (index($0, key "=") == 1 || index($0, "#" key "=") == 1) {
|
||||
print key "=" value
|
||||
done = 1
|
||||
next
|
||||
}
|
||||
{ print }
|
||||
END {
|
||||
if (!done) {
|
||||
print key "=" value
|
||||
}
|
||||
}
|
||||
' "$ENV_FILE" > "$tmp"
|
||||
mv "$tmp" "$ENV_FILE"
|
||||
}
|
||||
|
||||
comment_env() {
|
||||
key=$1
|
||||
value=$2
|
||||
tmp=$(mktemp)
|
||||
awk -v key="$key" -v value="$value" '
|
||||
BEGIN { done = 0 }
|
||||
!done && (index($0, key "=") == 1 || index($0, "# " key "=") == 1 || index($0, "#" key "=") == 1) {
|
||||
print "# " key "=" value
|
||||
done = 1
|
||||
next
|
||||
}
|
||||
{ print }
|
||||
END {
|
||||
if (!done) {
|
||||
print "# " key "=" value
|
||||
}
|
||||
}
|
||||
' "$ENV_FILE" > "$tmp"
|
||||
mv "$tmp" "$ENV_FILE"
|
||||
}
|
||||
|
||||
compose() {
|
||||
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" -p "$PROJECT" "$@"
|
||||
}
|
||||
|
||||
write_ui_proxy() {
|
||||
ui_host=${MG_UI_HOST:-ui}
|
||||
cat > "$ROOT_DIR/docker/nginx/snippets/ui-proxy.conf" <<NGINX
|
||||
# Copyright (c) Abstract Machines
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# Written by docker/setup-tls.sh – do not edit manually.
|
||||
|
||||
location / {
|
||||
if (\$scheme = http) {
|
||||
return 301 https://\$host\$request_uri;
|
||||
}
|
||||
include snippets/proxy-headers.conf;
|
||||
include snippets/ws-upgrade.conf;
|
||||
proxy_pass http://${ui_host}:3000;
|
||||
}
|
||||
NGINX
|
||||
}
|
||||
|
||||
wait_for_nginx_http() {
|
||||
if ! command -v curl >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
elapsed=0
|
||||
while [ "$elapsed" -lt "$TIMEOUT_SECONDS" ]; do
|
||||
status=$(curl -s -o /dev/null -w "%{http_code}" --max-time 2 \
|
||||
http://127.0.0.1/.well-known/acme-challenge/magistrala-tls-probe 2>/dev/null || true)
|
||||
case "$status" in
|
||||
200|301|302|307|308|404)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
sleep 2
|
||||
elapsed=$((elapsed + 2))
|
||||
done
|
||||
|
||||
echo "Timed out waiting for Nginx to accept HTTP traffic." >&2
|
||||
docker logs --tail 80 magistrala-nginx >&2 || true
|
||||
exit 1
|
||||
}
|
||||
|
||||
cert_path="./ssl/letsencrypt/live/$HOST/fullchain.pem"
|
||||
key_path="./ssl/letsencrypt/live/$HOST/privkey.pem"
|
||||
cert_file="$ROOT_DIR/docker/ssl/letsencrypt/live/$HOST/fullchain.pem"
|
||||
key_file="$ROOT_DIR/docker/ssl/letsencrypt/live/$HOST/privkey.pem"
|
||||
|
||||
if [ "$LETSENCRYPT_ENABLED" = "false" ]; then
|
||||
FORCE_RENEWAL=false
|
||||
fi
|
||||
|
||||
if [ "$LETSENCRYPT_ENABLED" = "true" ] && [ "$STAGING" = "false" ] && [ -f "$cert_file" ]; then
|
||||
if openssl x509 -in "$cert_file" -noout -issuer 2>/dev/null | grep -q "STAGING"; then
|
||||
FORCE_RENEWAL=true
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Configuring docker/.env for $HOST"
|
||||
set_env MG_RELEASE_TAG latest
|
||||
set_env MG_PUBLIC_HOST "$HOST"
|
||||
set_env MG_UI_HOST "${MG_UI_HOST:-ui}"
|
||||
set_env MG_LETSENCRYPT_ENABLED "$LETSENCRYPT_ENABLED"
|
||||
set_env MG_LETSENCRYPT_EMAIL "$EMAIL"
|
||||
set_env MG_LETSENCRYPT_STAGING "$STAGING"
|
||||
set_env MG_LETSENCRYPT_FORCE_RENEWAL "$FORCE_RENEWAL"
|
||||
set_env MG_NGINX_SERVER_NAME "$HOST"
|
||||
comment_env MG_NGINX_SERVER_CERT "$cert_path"
|
||||
comment_env MG_NGINX_SERVER_KEY "$key_path"
|
||||
set_env MG_UI_DOCKER_ACCEPT_EULA yes
|
||||
|
||||
set_env MG_OAUTH_UI_REDIRECT_URL "https://$HOST/api/auth/token"
|
||||
set_env MG_OAUTH_UI_ERROR_URL "https://$HOST/login"
|
||||
set_env MG_PASSWORD_RESET_URL_PREFIX "https://$HOST/password-reset"
|
||||
set_env MG_VERIFICATION_URL_PREFIX "https://$HOST/verify-email"
|
||||
set_env MG_GOOGLE_REDIRECT_URL "https://$HOST/oauth/callback/google"
|
||||
set_env NEXTAUTH_URL "https://$HOST"
|
||||
set_env MG_HOST_URL "https://$HOST"
|
||||
set_env MG_UI_BASEURL "https://$HOST"
|
||||
set_env MG_UI_CLI_MQTT_HOST "$HOST"
|
||||
set_env MG_UI_CLI_WS_URL "wss://$HOST/mqtt"
|
||||
set_env MG_UI_CLI_COAP_HOST "$HOST"
|
||||
set_env MG_UI_CLI_HTTP_URL "https://$HOST/http"
|
||||
|
||||
mkdir -p "$ROOT_DIR/docker/ssl/letsencrypt" "$ROOT_DIR/docker/ssl/certbot-www"
|
||||
|
||||
write_ui_proxy
|
||||
|
||||
if [ "$LETSENCRYPT_ENABLED" = "false" ]; then
|
||||
echo "Starting Magistrala with the fallback Nginx certificate"
|
||||
MG_UI_DOCKER_ACCEPT_EULA=yes compose up -d
|
||||
MG_UI_DOCKER_ACCEPT_EULA=yes COMPOSE_PROFILES=letsencrypt compose stop certbot >/dev/null 2>&1 || true
|
||||
echo "Let's Encrypt disabled. Nginx cert/key paths are commented in docker/.env."
|
||||
echo "Fallback TLS setup complete: https://$HOST/"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Starting Magistrala with the fallback Nginx certificate"
|
||||
MG_UI_DOCKER_ACCEPT_EULA=yes compose up -d
|
||||
wait_for_nginx_http
|
||||
|
||||
echo "Requesting Let's Encrypt certificate for $HOST"
|
||||
MG_UI_DOCKER_ACCEPT_EULA=yes COMPOSE_PROFILES=letsencrypt compose up -d --force-recreate certbot
|
||||
|
||||
elapsed=0
|
||||
while [ "$elapsed" -lt "$TIMEOUT_SECONDS" ]; do
|
||||
if [ -s "$cert_file" ] && [ -s "$key_file" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
elapsed=$((elapsed + 2))
|
||||
done
|
||||
|
||||
if [ ! -s "$cert_file" ] || [ ! -s "$key_file" ]; then
|
||||
echo "Timed out waiting for Let's Encrypt certificate files." >&2
|
||||
docker logs --tail 80 magistrala-certbot >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Switching Nginx to the issued certificate"
|
||||
set_env MG_NGINX_SERVER_CERT "$cert_path"
|
||||
set_env MG_NGINX_SERVER_KEY "$key_path"
|
||||
set_env MG_LETSENCRYPT_FORCE_RENEWAL false
|
||||
|
||||
MG_UI_DOCKER_ACCEPT_EULA=yes compose up -d --force-recreate nginx
|
||||
|
||||
echo "TLS setup complete: https://$HOST/"
|
||||
@@ -7,3 +7,5 @@
|
||||
*conf
|
||||
client.crt
|
||||
client.key
|
||||
certbot-www/
|
||||
letsencrypt/
|
||||
|
||||
Reference in New Issue
Block a user