Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for go templating in config files #4165

Closed
3 of 5 tasks
BierDav opened this issue Oct 22, 2024 · 5 comments
Closed
3 of 5 tasks

Support for go templating in config files #4165

BierDav opened this issue Oct 22, 2024 · 5 comments
Labels
feat New feature or request.

Comments

@BierDav
Copy link

BierDav commented Oct 22, 2024

Preflight checklist

Ory Network Project

No response

Describe your problem

When configuring kratos for selfhosting it is often quite useful to have the ability of using go templating. A usage example would be that it is more clean to use environment variables from the config file than using the very long environment variable names to directly influence the config.

dsn: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}?search_path=${POSTGRES_SCHEMA},public&sslmode=disable&max_conns=20&max_idle_conns=4
serve:
  public:
    base_url:  ${SITE_URL}/kratos
  admin:
    base_url: http://kratos:4434/

Currently my config looks something like this and I run eval on every container start:

 entrypoint:
      - sh
      - -c
      - |
        eval "echo \"$(cat /home/ory/temp-config.yml)\"" > /home/ory/config.yml \
        && echo "==========" \
        && cat /home/ory/config.yml \
        && echo "==========" \
        && kratos -c /home/ory/config.yml migrate sql -e --yes \
        && kratos serve -c /home/ory/config.yml --watch-courier

But unfortunately this also breaks config hot reload.

Describe your ideal solution

With the ability of go templating the same as traefik for example does. It could look like this:

dsn: postgres://{{ env "POSTGRES_USER" }}:{{ env "POSTGRES_PASSWORD" }}@{{ env "POSTGRES_HOST" }}:{{ evn "POSTGRES_PORT" }}/{{ env "POSTGRES_DB" }}?search_path={{ env "POSTGRES_SCHEMA" }},public&sslmode=disable&max_conns=20&max_idle_conns=4
serve:
 public:
   base_url:  {{ env "SITE_URL" }}/kratos
 admin:
   base_url: http://kratos:4434/

Without any additional configuration for the container required you now get also hot reload like in traefik.

Actually I am not a go developer, but I suppose that it is a quite small change to support this, because this should be basically be already be built into go.

Btw. this should actually at best be supported accross all ory products

Workarounds or alternatives

For this specific use case a special syntax could also be introduced that is replaced with the environment variables.

Version

1.3.0

Additional Context

No response

@BierDav BierDav added the feat New feature or request. label Oct 22, 2024
@aeneasr
Copy link
Member

aeneasr commented Oct 22, 2024

Hello, you can achieve the same thing with envsubst:

To use envsubst to expand environment variables in a configuration file, follow these steps:

  1. Create a configuration file that includes environment variables in the format ${VAR_NAME}. For example:

    config.template:

    database_url=${DATABASE_URL}
    api_key=${API_KEY}
    
  2. Set the required environment variables:

    export DATABASE_URL="postgres://localhost:5432/mydb"
    export API_KEY="your-api-key"
  3. Use envsubst to substitute the environment variables and write the output to a new file:

    envsubst < config.template > config.conf

This will replace the variables in the config.template file and save the result in config.conf.

@aeneasr aeneasr closed this as not planned Won't fix, can't repro, duplicate, stale Oct 22, 2024
@BierDav
Copy link
Author

BierDav commented Oct 22, 2024

Yeah but, this doesn't support hot reload, and it doesn't allow for the more advanced functions that go templating has. I though that it is just a small switch to use another config provider and all the go templating advanced things you get for free. Exactly the same way as traefk does https://doc.traefik.io/traefik/providers/file/#go-templating

@akkie
Copy link

akkie commented Oct 26, 2024

It would be really helpful if Ory products had support for this out of the box. Also envsubst isn't available in the Kratos image. To use it with docker compose I need to extend the image and create my own. This is not very ergonomic.

@akkie
Copy link

akkie commented Oct 27, 2024

As a workaround, here is a variant with hot reload:

Dockerfile

FROM oryd/kratos:v1.3

USER root

RUN apk add --no-cache gettext inotify-tools

COPY ./entrypoint/kratos.sh /kratos.sh
RUN chmod +x /kratos.sh

USER ory

ENTRYPOINT ["/kratos.sh"]
CMD []

Entrypoint:

#!/bin/sh
set -e

CONFIG_DIR="/etc/config/kratos"
TEMP_CONFIG_DIR=$(mktemp -d)
export CONF_DIR=${TEMP_CONFIG_DIR}

# Function to process a single file
process_file() {
    local src_file="$1"
    local rel_path="${src_file#$CONFIG_DIR/}"
    local dest_file="$TEMP_CONFIG_DIR/$rel_path"
    local dest_dir=$(dirname "$dest_file")

    mkdir -p "$dest_dir"
    envsubst < "$src_file" > "$dest_file"
    echo "Processed: $src_file -> $dest_file"
}

# Initial processing of all files in the config dir
find "$CONFIG_DIR" -type f | while read -r file; do
    process_file "$file"
done

# Start file watching in the background
(
    inotifywait -m -r -e modify,create,delete "$CONFIG_DIR" |
        while read -r directory events filename; do
            echo "Detected $events on $directory$filename"
            process_file "$directory$filename"
        done
) &

# Start Kratos
exec kratos serve -c "$TEMP_CONFIG_DIR/kratos.yml" "$@"

@BierDav
Copy link
Author

BierDav commented Oct 27, 2024

Thanks for the workaround @akkie, i think this issue should be reopened

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat New feature or request.
Projects
None yet
Development

No branches or pull requests

3 participants