diff --git a/README.md b/README.md index 9ead18d..570ec6e 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,11 @@ You can use the included `cloudflared` service to make secure connections withou | `SKIP_ACL` | Set `true` to skip modifying workspace ACL | | `SSH_PORT` | Set a non-standard port for SSH (default `22`) | | `SSH_PUBKEY` | Your public key for SSH | +| `WEB_ENABLE_AUTH` | Enable password protection for web services (default `true`) | +| `WEB_USER` | Username for web services (default `user`) | +| `WEB_PASSWORD` | Password for web services (default `password`) | | `WORKSPACE` | A volume path. Defaults to `/workspace/` | +| `WORKSPACE_SYNC` | Move mamba environments and services to workspace if mounted (default `true`) | Environment variables can be specified by using any of the standard methods (`docker-compose.yaml`, `docker run -e...`). Additionally, environment variables can also be passed as parameters of `init.sh`. @@ -170,6 +174,18 @@ Passing environment variables to init.sh is usually unnecessary, but is useful f Example usage: `docker run -e STANDARD_VAR1="this value" -e STANDARD_VAR2="that value" init.sh EXTRA_VAR="other value"` +## Security + +By default, all exposed web services other than the port redirect page are protected by HTTP basic authentication. + +The default username is `user` and the password is `password`. + +You can set your credentials by passing environment variables as shown above. + +The password is stored as a bcrypt hash. If you prefer not to pass a plain text password to the container you can pre-hash and use the variable `WEB_PASSWORD_HASH`. + +If you are running the image locally on a trusted network, you may disable authentication by setting the environment variable `WEB_ENABLE_AUTH=false`. + ## Provisioning script It can be useful to perform certain actions when starting a container, such as creating directories and downloading files. @@ -181,7 +197,7 @@ The URL must point to a plain text file - GitHub Gists/Pastebin (raw) are suitab If you are running locally you may instead opt to mount a script at `/opt/ai-dock/bin/provisioning.sh`. >[!NOTE] ->If configured, `sshd`, `cloudflared`, `rclone`, `jupyter` & `logtail` will be launched before provisioning; `comfyui` will launch after. +>If configured, `sshd`, `caddy`, `cloudflared`, `rclone`, `port redirector` & `logtail` will be launched before provisioning; Any other processes will launch after. >[!WARNING] @@ -200,8 +216,6 @@ Micromamba environments are particularly useful where several software packages | Environment | Packages | | -------------- | ----------------------------------------- | | `base` | micromamba's base environment | -| `system` | `supervisord`, `openssh` `rclone` | -| `fastapi` | `logtail web UI`, `port redirector web UI` | | `comfyui` | ComfyUI and dependencies | | `python_[ver]` | `python` | @@ -275,6 +289,12 @@ Jupyter's official documentation is available at https://jupyter.org/ >[!NOTE] >_If you have enabled `CF_QUICK_TUNNELS` a secure `https://[random-auto-generated-sub-domain].trycloudflare.com` link will be created. You can find it at `/var/log/supervisor/quicktunnel-jupyter.log`_ +### Caddy + +This is a simple webserver acting as a reverse proxy. + +Caddy is used to enable basic authentication for all sensitive web services. + ### Port Redirector This is a simple list of links to the web services available inside the container. diff --git a/build/COPY_ROOT/opt/ai-dock/bin/supervisor-comfyui.sh b/build/COPY_ROOT/opt/ai-dock/bin/supervisor-comfyui.sh index 04d5f30..09754e0 100755 --- a/build/COPY_ROOT/opt/ai-dock/bin/supervisor-comfyui.sh +++ b/build/COPY_ROOT/opt/ai-dock/bin/supervisor-comfyui.sh @@ -2,50 +2,63 @@ trap cleanup EXIT +LISTEN_PORT=1818 +METRICS_PORT=1918 +PROXY_SECURE=true + function cleanup() { kill $(jobs -p) > /dev/null 2>&1 - rm /run/http_ports/$PORT > /dev/null 2>&1 + rm /run/http_ports/$PROXY_PORT > /dev/null 2>&1 } -SERVICE="ComfyUI" - if [[ -z $COMFYUI_PORT ]]; then COMFYUI_PORT=8188 fi -PORT=$COMFYUI_PORT -METRICS_PORT=1188 +PROXY_PORT=$COMFYUI_PORT SERVICE_NAME="ComfyUI" -printf "{\"port\": \"$PORT\", \"metrics_port\": \"$METRICS_PORT\", \"service_name\": \"$SERVICE_NAME\"}" > /run/http_ports/$PORT +file_content=$( + jq --null-input \ + --arg listen_port "${LISTEN_PORT}" \ + --arg metrics_port "${METRICS_PORT}" \ + --arg proxy_port "${PROXY_PORT}" \ + --arg proxy_secure "${PROXY_SECURE,,}" \ + --arg service_name "${SERVICE_NAME}" \ + '$ARGS.named' +) + +printf "%s" $file_content > /run/http_ports/$PROXY_PORT PLATFORM_FLAGS="" if [[ $XPU_TARGET = "CPU" ]]; then PLATFORM_FLAGS="--cpu" fi -BASE_FLAGS="--listen 0.0.0.0 --port ${COMFYUI_PORT} --disable-auto-launch" -if [[ -f /run/provisioning_script ]]; then - micromamba run -n fastapi python /opt/ai-dock/fastapi/logviewer/main.py \ - -p $COMFYUI_PORT \ +BASE_FLAGS="--listen 127.0.0.1 --port ${LISTEN_PORT} --disable-auto-launch" + +# Delay launch until micromamba is ready +if [[ -f /run/workspace_moving || -f /run/provisioning_script ]]; then + /usr/bin/python3 /opt/ai-dock/fastapi/logviewer/main.py \ + -p $LISTEN_PORT \ -r 5 \ - -s ${SERVICE} \ - -u comfyui \ - -t "Preparing ${SERVICE}" & + -s "${SERVICE_NAME}" \ + -t "Preparing ${SERVICE_NAME}" & fastapi_pid=$! - while [[ -f /run/provisioning_script ]]; do + while [[ -f /run/workspace_moving || -f /run/provisioning_script ]]; do sleep 1 done - printf "\nStarting %s... " ${SERVICE:-service} - kill $fastapi_pid && \ + printf "\nStarting %s... " ${SERVICE_NAME:-service} + kill $fastapi_pid & + wait -n printf "OK\n" else - printf "Starting %s...\n" ${SERVICE} + printf "Starting %s...\n" ${SERVICE_NAME} fi -kill -9 $(lsof -t -i:$COMFYUI_PORT) > /dev/null 2>&1 & +kill -9 $(lsof -t -i:$LISTEN_PORT) > /dev/null 2>&1 & wait -n cd /opt/ComfyUI @@ -53,4 +66,3 @@ micromamba run -n comfyui python main.py \ ${PLATFORM_FLAGS} \ ${BASE_FLAGS} \ ${COMFYUI_FLAGS} - diff --git a/docker-compose.yaml b/docker-compose.yaml index 0dce759..ab714ad 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -64,11 +64,14 @@ services: - COMFYUI_BRANCH=${COMFYUI_BRANCH:-master} - COMFYUI_FLAGS=${COMFYUI_FLAGS:-} - COMFYUI_PORT=${COMFYUI_PORT:-8188} - - JUPYTER_TOKEN=${JUPYTER_TOKEN:-password} - JUPYTER_MODE=${JUPYTER_MODE:-lab} # Allows running true SSH alongside provider proxy SSH - SSH_PORT=${SSH_PORT:-22} - WORKSPACE=${WORKSPACE:-/workspace} + - WORKSPACE_SYNC=${WORKSPACE_SYNC} - CF_TUNNEL_TOKEN=${CF_TUNNEL_TOKEN:-} - CF_QUICK_TUNNELS=${CF_QUICK_TUNNELS:-true} + - WEB_ENABLE_AUTH=${WEB_ENABLE_AUTH} + - WEB_USER=${WEB_USER} + - WEB_PASSWORD=${WEB_PASSWORD} #- PROVISIONING_SCRIPT=${PROVISIONING_SCRIPT:-} \ No newline at end of file