diff --git a/__swarm/bookstack/bookstack-swarm.yml b/__swarm/bookstack/bookstack-swarm.yml index a80c27a..f5b49d9 100644 --- a/__swarm/bookstack/bookstack-swarm.yml +++ b/__swarm/bookstack/bookstack-swarm.yml @@ -1,8 +1,3 @@ -volumes: - bookstack_db_data: - driver: local - bookstack_app_data: - driver: local services: app: env_file: @@ -14,7 +9,7 @@ services: protocol: tcp mode: ingress volumes: - - bookstack_app_data:/config + - /share/docker_data/bookstack/bookstack_app_data:/config deploy: labels: com.centurylinklabs.watchtower.enable: 'true' @@ -40,7 +35,7 @@ services: PUID: 0 image: ${DOCKER_REGISTRY:-}lscr.io/linuxserver/mariadb volumes: - - bookstack_db_data:/config + - /share/docker_data/bookstack/bookstack_db_data:/config deploy: labels: wud.watch: 'true' @@ -49,3 +44,4 @@ services: placement: constraints: - node.role == manager +version: '2' diff --git a/__swarm/bookstack/stack.env b/__swarm/bookstack/stack.env index 96c4f98..53838c4 100755 --- a/__swarm/bookstack/stack.env +++ b/__swarm/bookstack/stack.env @@ -1,16 +1,16 @@ -PUID: 1000 -PGID: 1000 -APP_URL: https://bookstack.sectorq.eu -DB_HOST: db -DB_PORT: 3306 -DB_USER: bookstack -DB_PASS: l4c1j4yd33Du5lo -DB_DATABASE: bookstackapp -MYSQL_ROOT_PASSWORD: l4c1j4yd33Du5lo -TZ: Europe/Bratislava -MYSQL_DATABASE: bookstackapp -MYSQL_USER: bookstack -MYSQL_PASSWORD: l4c1j4yd33Du5lo +PUID=1000 +PGID=1000 +APP_URL=https://bookstack.sectorq.eu +DB_HOST=db +DB_PORT=3306 +DB_USER=bookstack +DB_PASS=l4c1j4yd33Du5lo +DB_DATABASE=bookstackapp +MYSQL_ROOT_PASSWORD=l4c1j4yd33Du5lo +TZ=Europe/Bratislava +MYSQL_DATABASE=bookstackapp +MYSQL_USER=bookstack +MYSQL_PASSWORD=l4c1j4yd33Du5lo # # Set authentication method to be saml2 # AUTH_METHOD: saml2 # # Control if BookStack automatically initiates login via your SAML system if it's the only authentication method. @@ -46,41 +46,41 @@ MYSQL_PASSWORD: l4c1j4yd33Du5lo # Set OIDC to be the authentication method -AUTH_METHOD: oidc +AUTH_METHOD=oidc #AUTH_METHOD: standard # Control if BookStack automatically initiates login via your OIDC system # if it's the only authentication method. Prevents the need for the # user to click the "Login with x" button on the login page. # Setting this to true enables auto-initiation. -AUTH_AUTO_INITIATE: true +AUTH_AUTO_INITIATE=true # Set the display name to be shown on the login button. # (Login with ) -OIDC_NAME: SSO +OIDC_NAME=SSO # Name of the claims(s) to use for the user's display name. # Can have multiple attributes listed, separated with a '|' in which # case those values will be joined with a space. # Example: OIDC_DISPLAY_NAME_CLAIMS=given_name|family_name -OIDC_DISPLAY_NAME_CLAIMS: name +OIDC_DISPLAY_NAME_CLAIMS=name # OAuth Client ID to access the identity provider -OIDC_CLIENT_ID: GCPj547vTmEpmsCM8jkuR222SS31yZMdp7oAU82U +OIDC_CLIENT_ID=GCPj547vTmEpmsCM8jkuR222SS31yZMdp7oAU82U # OAuth Client Secret to access the identity provider -OIDC_CLIENT_SECRET: Nador7SOdsYgfNhRwbeRKLNPkPiASBAlTnKVi294xbOz8MM3e2RlzAaWQsQNZmBtLLZVifb1TG3OpKrVXeeW3Vu8HmJuvy8GwSAT2r0pP0241tDdEShq7UkP9G5Esdt8 +OIDC_CLIENT_SECRET=Nador7SOdsYgfNhRwbeRKLNPkPiASBAlTnKVi294xbOz8MM3e2RlzAaWQsQNZmBtLLZVifb1TG3OpKrVXeeW3Vu8HmJuvy8GwSAT2r0pP0241tDdEShq7UkP9G5Esdt8 # Issuer URL # Must start with 'https://' -OIDC_ISSUER: https://auth.sectorq.eu/application/o/bookstack/ +OIDC_ISSUER=https://auth.sectorq.eu/application/o/bookstack/ # The "end session" (RP-initiated logout) URL to call during BookStack logout. # By default this is false which disables RP-initiated logout. # Setting to "true" will enable logout if found as supported by auto-discovery. # Otherwise, this can be set as a specific URL endpoint. -OIDC_END_SESSION_ENDPOINT: false +OIDC_END_SESSION_ENDPOINT=false # Enable auto-discovery of endpoints and token keys. # As per the standard, expects the service to serve a # `/.well-known/openid-configuration` endpoint. -OIDC_ISSUER_DISCOVER: true \ No newline at end of file +OIDC_ISSUER_DISCOVER=true diff --git a/yaml_convert2.py b/yaml_convert2.py index a11509b..bd9743c 100644 --- a/yaml_convert2.py +++ b/yaml_convert2.py @@ -9,41 +9,57 @@ OUTPUT_FILE = f"__swarm/{stack_name}/{stack_name}-swarm.yml" def fix_env_file(filepath): - """Convert YAML-style env (KEY: value) into Docker env (KEY=value).""" + """Convert YAML-style env (KEY: value) → Docker env (KEY=value).""" fixed_lines = [] changed = False with open(filepath, "r") as f: - for line in f: + for raw_line in f: + line = raw_line.rstrip("\n") stripped = line.strip() - # Skip empty/comment lines + # Preserve comments and blank lines if not stripped or stripped.startswith("#"): - fixed_lines.append(line) + fixed_lines.append(raw_line) continue - # Match YAML-style: KEY: value - m = re.match(r"^([A-Za-z0-9_]+):\s*(.*)$", stripped) - if m: - key, value = m.groups() - fixed = f"{key}={value}\n" - fixed_lines.append(fixed) - changed = True - else: - # Validate Docker env format - if " " in stripped: - raise ValueError(f"Invalid env line (contains spaces): {stripped}") - if ":" in stripped: - raise ValueError(f"Invalid env line (contains colon): {stripped}") - fixed_lines.append(line) + # Detect YAML-style: KEY: value + # MUST convert + if ":" in stripped and "=" not in stripped.split(":")[0]: + key, value = stripped.split(":", 1) + key = key.strip() + value = value.strip() - # Write back only if changes were needed + # Validate env key + if not re.match(r"^[A-Za-z0-9_]+$", key): + raise ValueError(f"Invalid variable name: {key}") + + fixed_lines.append(f"{key}={value}\n") + changed = True + continue + + # Detect valid Docker-style: KEY=value + if "=" in stripped: + key, value = stripped.split("=", 1) + + # Validate key + if not re.match(r"^[A-Za-z0-9_]+$", key): + raise ValueError(f"Invalid environment variable name: {key}") + + # Value may contain anything + fixed_lines.append(raw_line) + continue + + # Anything else is invalid + raise ValueError(f"Invalid env line: {stripped}") + + # Write file if modified if changed: with open(filepath, "w") as f: f.writelines(fixed_lines) - print(f"[FIXED] Converted YAML env → Docker env in {filepath}") + print(f"[FIXED] Converted YAML → Docker env format in {filepath}") else: - print(f"[OK] .env file already valid: {filepath}") + print(f"[OK] .env file valid: {filepath}") def convert_ports(ports): """Convert short port syntax to Swarm long syntax."""