Configure OpenID via environment

I currently struggle configuring OpenID by using environment variables.

Here’s what I tried:

VIKUNJA_AUTH_OPENID_PROVIDERS: KEYCLOAK
VIKUNJA_AUTH_OPENID_PROVIDERS_KEYCLOAK_NAME: KeyCloak
VIKUNJA_AUTH_OPENID_PROVIDERS_KEYCLOAK_AUTHURL: ...
VIKUNJA_AUTH_OPENID_PROVIDERS_KEYCLOAK_CLIENTID: vikunja
VIKUNJA_AUTH_OPENID_PROVIDERS_KEYCLOAK_CLIENTSECRET: ...

This however causes the backend to panic with
interface conversion: interface {} is string, not []interface {}

Can someone show me how this should be properly configured?

2 Likes

Configuring openid via env variables is currently not supported. You’ll need to use a config file for that. It is possible to use both env and config files at the same time, that way you could put only the openid config in the config file and use env variables for the rest.

Thanks for the reply. Any plans on implementing this? It would be handy to have for docker-compose deployments.

I think this would make sense, but would be a breaking change. As such, I don’t plan to implement it in the near future but added it to the backlog.

Just one follow-up question: is it possible to expand environment variables in the config file? The point is that I don’t want to put the openid clientsecret into the config file (I’m using a docker-compose setup with all files but .env in git).

Like this:

auth:
  local:
    enabled: false
  openid:
    enabled: true
    providers:
      - name: "KeyCloak"
        authurl: "https://auth..."
        clientid: "vikunja"
        clientsecret: $OPENID_SECRET

and then passing OPENID_SECRET via environment?

Right now that won’t work.

I am hitting the exact same issue :confused: wouldn’t it be possible to simply add an extra environment variable for the meantime?

Either way, the documentation should reflect the current state, it says:

You can […] set all config option with environment variables.

It should at least be mentioned at Config options | Vikunja

I’ve added a notice to the doc you mentioned.

I would also be interested in this.
In nixos, the config file will be world readable in the nix store. Using environment variables is the only secure way of passing those secrets to the service.

1 Like

I’m also interested. Also installed Vikunja with NixOS and the client secret is world readable

1 Like

Are there any updates?

It would be really great to have this.

This is my config (values.yaml) for HELM deployed in K8S:

vikunja:
  api:
    env:
      VIKUNJA_SERVICE_PUBLICURL: https://vikunja.host.com/
      VIKUNJA_DATABASE_TYPE: "postgres"
      VIKUNJA_DATABASE_HOST: "vikunja-db-cluster.postgres-cluster.svc.cluster.local"
      VIKUNJA_DATABASE_SSLMODE: "require"
      VIKUNJA_DATABASE_USER:
        valueFrom:
          secretKeyRef:
            name: vikunja.user.vikunja-db-cluster.credentials.postgresql.acid.zalan.do
            key: username
      VIKUNJA_DATABASE_NAME: "vikunja"
      VIKUNJA_DATABASE_PASSWORD:
        valueFrom:
          secretKeyRef:
            name: vikunja.user.vikunja-db-cluster.credentials.postgresql.acid.zalan.do
            key: password
      VIKUNJA_OIDC_CLIENT_SECRET:
        valueFrom:
          secretKeyRef:
            name: vikunja-secret
            key: keycloak.client.secret
    enabled: true
    persistence:
      data:
        enabled: true
        size: 10Gi
    ingress:
      main:
        enabled: true
        annotations:
          cert-manager.io/cluster-issuer: letsencrypt-production
          nginx.ingress.kubernetes.io/proxy-body-size: "100m"
          cert-manager.io/private-key-algorithm: ECDSA
          cert-manager.io/private-key-size: "384"
        hosts:
          - host: vikunja.host.com
            paths:
              - path: "/api/v1"
        tls:
          - hosts:
              - vikunja.host.com
            secretName: vikunja-tls
    configMaps:
      config:
        enabled: true
        data:
          config.yml: |
            service:
              enableregistration: false
              timezone: Europe/Vienna
              frontendUrl: https://vikunja.host.com
            auth:
              local:
                enabled: false
              openid:
                enabled: true
                redirecturl: https://vikunja.host.com/auth/openid/
                providers:
                  - name: Keycloak
                    authurl: https://keycloak.host.com/auth/realms/REALM
                    logouturl: https://keycloak.host.com/auth/realms/REALM/protocol/openid-connect/logout
                    clientid: vikunja
                    clientsecret: XXXX
  frontend:
    env:
      VIKUNJA_API_URL: https://vikunja.host.com/api/v1
    enabled: true
    ingress:
      main:
        enabled: true
        annotations:
          cert-manager.io/cluster-issuer: letsencrypt-production
          nginx.ingress.kubernetes.io/proxy-body-size: "100m"
          cert-manager.io/private-key-algorithm: ECDSA
          cert-manager.io/private-key-size: "384"
        hosts:
          - host: vikunja.host.com
            paths:
              - path: "/"
        tls:
          - hosts:
              - vikunja.host.com
            secretName: vikunja-tls
  postgresql:
    enabled: false

  typesense:
    enabled: true
    persistence:
      data:
        size: 1Gi

Basically the secret is already prepared. It would be great to either have it as ENV eg

(Maybe the K8S Helm Values is useful for someone!)

A possible workaround for sops-nix users could be using a template for the configuration file: GitHub - Mic92/sops-nix: Atomic secret provisioning for NixOS based on sops

@Rohmilchkaese that helm you pasted, are the envs like VIKUNJA_OIDC_CLIENT_SECRET being used anywhere? It looks like below a ConfigMap is generated with the raw clientsecret.

I’m using flux w/ sealed secrets so I can put them in git. However, I cannot figure out a way to deploy this app without exposing the clientsecret in my repository. The environment variables would be perfect, I can set them, but I’m not sure how I can get clientsecret set to them.

So i see that this has been updated in the latest release. Is this something I can use now? The docs still say that it doesn’t work in certain places.

Also the feat!: config for auth providers now use a map instead of an array · 05349ddb5c - vikunja - Gitea this commit says specifically that “still required to set at least one value via the config file because Vikunja won’t discover the provider otherwise”.

What exactly does this mean? Is there an easy way to just not have the file at all?

Not really.

The problem is that environment variables are evaluated at runtime. That means Vikunja will first make a list of all configured openid providers and then check the credentials for each of them. But at the time where it makes the list, environment variables are not evaluated. That’s caused by viper, the library Vikunja uses to make handling config variables easier.

It might be possible to build this, but it’s not as easy and would likely require rearchitecting the way the config is read. IMHO such a change should be made directly in viper, not in Vikunja.

So could I just have to define that openID provider and then the rest be provided by environmental variables? Or do I need to define more?

Example below.

  openid:
    providers:
      authentik:

That might work. If it does not, try specifying the name only.

I took a stab at this and noticed a few things that might be relevant:

  • That commit hasn’t made it into a tagged release yet. The only place I don’t get that panic is if I run the unstable tag. You may already know this, but if (like me) you stumble on this thread with the same issue, be aware that at time of writing, it’s not released yet (despite being in the docs).
  • An error is thrown in the logs if you don’t specify the clientid and clientsecret, even if they’re provided in environment variables. The app still initializes and the server comes up, but the button to use the OIDC provider is gone, which appears to be due to this commit. I tried setting those values to an empty string and overriding them from the environment, but it looks like it didn’t take. I do wonder if perhaps I didn’t specify the env variables quite correctly.

For reference, I’m in a k8s environment using xeruf’s fork of the official helm chart. This is a bit of a security concern for me. I know there is technically a way around it by specifying them with files in the config and mounting the secrets to those files, but I haven’t figured out how to negotiate with the helm chart to get that to work. Any advice here would be greatly appreciated.

I’ve just pushed a fix for this in 5c02527d2d. Environment variables are now read explicitly, instead of on-demand. This allows specifying the OpenID config entirely using env variables, without a config file at all.

Please check with the next unstable build (should be ready for deployment in ~45min, also on try).

Great! I’ll give it a shot and report back.