WIP: Reset app.ini on every init-run to have a clean state #450

Draft
pat-s wants to merge 3 commits from clean-app-ini into main
pat-s commented 2023-05-29 10:10:53 +00:00 (Migrated from gitea.com)

fix #356

This conflicts with the logic if "rewrite of secret keys if an app.ini already exists" within the env-to-ini script. Yet I am not sure if this is really needed - I think a clean start would also be better.
OTOH, env2ini::generate_initial_secrets() states that these secrets "won't harm existing app.ini files".

Needs testing!

Settings which need to be preserved as secrets:

  • server.LFS_JWT_SECRET
  • oauth2.JWT_SECRET
  • security.SECRET_KEY
  • security.INTERNAL_TOKEN
fix #356 This conflicts with the logic if "rewrite of secret keys if an app.ini already exists" within the env-to-ini script. Yet I am not sure if this is really needed - I think a clean start would also be better. OTOH, `env2ini::generate_initial_secrets()` states that these secrets "won't harm existing app.ini files". Needs testing! Settings which need to be preserved as secrets: - [x] `server.LFS_JWT_SECRET` - [x] `oauth2.JWT_SECRET` - [x] `security.SECRET_KEY` - [x] `security.INTERNAL_TOKEN`
justusbunsi commented 2023-05-29 10:13:51 +00:00 (Migrated from gitea.com)

Once a app.ini is created, certain values must remain the same across the lifetime of that Gitea instance. I see the issue with not cleaning up the app.ini. What we can do is store the one-time generated values in a K8s secret and reuse them while recreate the app.ini completely.

Once a app.ini is created, certain values _must_ remain the same across the lifetime of that Gitea instance. I see the issue with not cleaning up the app.ini. What we can do is store the one-time generated values in a K8s secret and reuse them while recreate the app.ini completely.
wxiaoguang commented 2023-05-29 10:19:10 +00:00 (Migrated from gitea.com)

At least, the SECRET can't be reset, otherwise there would be bugs: eg: the 2FA can't be decrypted.

At least, the SECRET can't be reset, otherwise there would be bugs: eg: the 2FA can't be decrypted.
pat-s commented 2023-05-29 10:24:42 +00:00 (Migrated from gitea.com)

I agree. We need to save all auto-generated settings to k8s secrets first and regenerate app.ini using those secrets and the remaining values from values.yaml.

I agree. We need to save all auto-generated settings to k8s secrets first and regenerate `app.ini` using those secrets and the remaining values from `values.yaml`.
justusbunsi commented 2023-05-29 10:33:59 +00:00 (Migrated from gitea.com)

For handling K8s Secrets - if we decide to use that approach - the Serviceaccount topic becomes very useful in combination with RBAC.

For handling K8s Secrets - if we decide to use that approach - the Serviceaccount topic becomes very useful in combination with RBAC.
pat-s commented 2023-05-29 18:13:03 +00:00 (Migrated from gitea.com)

I've moved the persistent secrets creation before the removal of app.ini. The new logic now

  1. Creates the initial secrets only if app.ini does not exist (this should ideally only happen on the very first start)
  2. Removes an existing app.ini to have a clean start
  3. Creates app.ini using values.yaml and the initially created secrets

I am only a bit worried about race conditions when using multiple replicas: if one pod just removed app.ini and another arrives at the if condition which checks if there is an app.ini, it might recreate the secrets. So maybe we need to find a better way to check if we are on the "first" init run...

I've moved the persistent secrets creation before the removal of `app.ini`. The new logic now 1. Creates the initial secrets only if `app.ini` does not exist (this should ideally only happen on the very first start) 2. Removes an existing `app.ini` to have a clean start 3. Creates `app.ini` using `values.yaml` and the initially created secrets I am only a bit worried about race conditions when using multiple replicas: if one pod just removed `app.ini` and another arrives at the if condition which checks if there is an `app.ini`, it might recreate the secrets. So maybe we need to find a better way to check if we are on the "first" init run...
justusbunsi commented 2023-05-29 18:25:57 +00:00 (Migrated from gitea.com)

The last commit only moves the function that generates the secrets and makes it's definition conditional. The actual call of the function is still unconditional. This will break due to non-defined function when the app.ini does exists.

I suggest we split the topic of recreating the app.ini into two subsequent PRs to simplify review and testing:

  • Prepare and apply the K8s secret based on user input (means, generating the persistent values if not otherwise provided OR extract them from the existing app.ini on the filesystem) AND prevent K8s secret override if already exists; this is independent from the amount of replicas and done once
  • Recreate the app.ini based on that K8s secret; ideally once in the helm upgrade/install execution; outside of init-containers per replica.

This would eliminate race conditions within replicas.

The last commit only moves the function that generates the secrets and makes it's definition conditional. The actual call of the function is still unconditional. This will break due to non-defined function when the app.ini does exists. I suggest we split the topic of recreating the app.ini into two subsequent PRs to simplify review and testing: - Prepare and apply the K8s secret based on user input (means, generating the persistent values if not otherwise provided OR extract them from the existing app.ini on the filesystem) AND prevent K8s secret override if already exists; this is independent from the amount of replicas and done once - Recreate the app.ini based on that K8s secret; ideally once in the helm upgrade/install execution; outside of init-containers per replica. This would eliminate race conditions within replicas.
justusbunsi commented 2023-05-29 18:27:55 +00:00 (Migrated from gitea.com)

With such approach we would need a new job resource that generates/extracts/processes the values and generates the K8s secret. This job could later be extended to recreate the app.ini itself.

With such approach we would need a new job resource that generates/extracts/processes the values and generates the K8s secret. This job could later be extended to recreate the app.ini itself.
pat-s commented 2023-05-29 20:05:24 +00:00 (Migrated from gitea.com)

The last commit only moves the function that generates the secrets and makes it's definition conditional. The actual call of the function is still unconditional.

Well spotted! Missed to move the actual execution.

and done once

The question is: how do we define when that "once" is? It probably must be done whenever the secret is missing - regardless of the reason?

Recreate the app.ini based on that K8s secret; ideally once in the helm upgrade/install execution; outside of init-containers per replica.

I agree that the key could be to do it outside of the init-containers in some side-job to avoid running it multiple times. But this will be complicated if app.ini is still generated within ini-containers in each replica then.

With such approach we would need a new job resource that generates/extracts/processes the values and generates the K8s secret. This job could later be extended to recreate the app.ini itself.

Overall yes, the cleanest and probably only save way to have a single clean init of app.ini would be to do it as a "job" outside of the replicas and only let them consume the result.

With the above in mind, I am happy to close here and move to a more complex but sophisticated solution. Overall this behavior is not blocking HA in it's current form - but a rewrite should account for HA and avoid introducing race conditions.

> The last commit only moves the function that generates the secrets and makes it's definition conditional. The actual call of the function is still unconditional. Well spotted! Missed to move the actual execution. > and done once The question is: how do we define when that "once" is? It probably must be done whenever the secret is missing - regardless of the reason? > Recreate the app.ini based on that K8s secret; ideally once in the helm upgrade/install execution; outside of init-containers per replica. I agree that the key could be to do it outside of the init-containers in some side-job to avoid running it multiple times. But this will be complicated if `app.ini` is still generated within ini-containers in each replica then. > With such approach we would need a new job resource that generates/extracts/processes the values and generates the K8s secret. This job could later be extended to recreate the app.ini itself. Overall yes, the cleanest and probably only save way to have a single clean init of `app.ini` would be to do it as a "job" outside of the replicas and only let them consume the result. With the above in mind, I am happy to close here and move to a more complex but sophisticated solution. Overall this behavior is not blocking HA in it's current form - but a rewrite should account for HA and avoid introducing race conditions.
This pull request has changes conflicting with the target branch.
  • templates/gitea/config.yaml

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin clean-app-ini:clean-app-ini
git checkout clean-app-ini
Sign in to join this conversation.
No description provided.