diff --git a/CLAUDE.md b/CLAUDE.md index 51fd4e6..3e0bd5b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -256,11 +256,16 @@ VERT universal file format converter: - No file size limits - Privacy-focused: all conversions happen in the browser - No persistent data storage required + - Protected by HTTP Basic Auth (credentials in `.env`) + - Scale-to-zero enabled via Sablier (configurable via `VERT_SABLIER_ENABLED`) + - 1-hour session duration before automatic scale-down **Configuration**: -- **PUB_HOSTNAME**: `vert.pivoine.art` (for proper URL generation) -- **PUB_ENV**: `production` +- **PUB_HOSTNAME**: `vert.pivoine.art` (public hostname) +- **PUB_ENV**: `production` (environment mode) - **PUB_DISABLE_ALL_EXTERNAL_REQUESTS**: `true` (privacy mode) +- **VERT_SABLIER_ENABLED**: `true` (enable scale-to-zero) +- **VERT_AUTH_USERS**: HTTP Basic Auth credentials (htpasswd format in `.env`) **Usage**: Simply access https://vert.pivoine.art and drag/drop files to convert between formats. All processing happens in your browser using WebAssembly - no data is uploaded to the server. diff --git a/arty.yml b/arty.yml index 4684f8c..af2a9a1 100644 --- a/arty.yml +++ b/arty.yml @@ -115,6 +115,7 @@ envs: VERT_COMPOSE_PROJECT_NAME: vert VERT_IMAGE: ghcr.io/vert-sh/vert:latest VERT_TRAEFIK_HOST: vert.pivoine.art + VERT_SABLIER_ENABLED: true # Proxy PROXY_COMPOSE_PROJECT_NAME: proxy PROXY_DOCKER_IMAGE: traefik:latest diff --git a/proxy/dynamic/vert-sablier.yaml b/proxy/dynamic/vert-sablier.yaml new file mode 100644 index 0000000..170ea72 --- /dev/null +++ b/proxy/dynamic/vert-sablier.yaml @@ -0,0 +1,11 @@ +http: + middlewares: + sablier-vert: + plugin: + sablier: + names: vert_app + sablierUrl: http://sablier_app:10000 + sessionDuration: 1h + dynamic: + displayName: VERT File Converter + theme: ghost diff --git a/vert/compose.yaml b/vert/compose.yaml index 5d879da..16de1b8 100644 --- a/vert/compose.yaml +++ b/vert/compose.yaml @@ -18,10 +18,13 @@ services: - 'traefik.http.routers.${VERT_COMPOSE_PROJECT_NAME}-web-secure.rule=Host(`${VERT_TRAEFIK_HOST}`)' - 'traefik.http.routers.${VERT_COMPOSE_PROJECT_NAME}-web-secure.tls.certresolver=resolver' - 'traefik.http.routers.${VERT_COMPOSE_PROJECT_NAME}-web-secure.entrypoints=web-secure' + - 'traefik.http.middlewares.${VERT_COMPOSE_PROJECT_NAME}-auth.basicauth.users=${VERT_AUTH_USERS}' - 'traefik.http.middlewares.${VERT_COMPOSE_PROJECT_NAME}-web-secure-compress.compress=true' - - 'traefik.http.routers.${VERT_COMPOSE_PROJECT_NAME}-web-secure.middlewares=${VERT_COMPOSE_PROJECT_NAME}-web-secure-compress' + - 'traefik.http.routers.${VERT_COMPOSE_PROJECT_NAME}-web-secure.middlewares=sablier-vert@file,${VERT_COMPOSE_PROJECT_NAME}-auth,${VERT_COMPOSE_PROJECT_NAME}-web-secure-compress' - 'traefik.http.services.${VERT_COMPOSE_PROJECT_NAME}-web-secure.loadbalancer.server.port=80' - 'traefik.docker.network=${NETWORK_NAME}' + - 'sablier.enable=${VERT_SABLIER_ENABLED}' + - 'sablier.group=${VERT_COMPOSE_PROJECT_NAME}' - 'com.centurylinklabs.watchtower.enable=${WATCHTOWER_LABEL_ENABLE}' networks: