[BUG] Rootless needs /data/git mounted to /var/lib/gitea/git #155

Closed
opened 2021-05-06 14:37:59 +00:00 by viceice · 15 comments
Contributor

With the latest rootless image, $HOME is pointing to /var/lib/gitea/git but this chart is not mounting to that dir.

My workaround for now is this:

# values.yaml

extraVolumeMounts:
  - name: data
    mountPath: /var/lib/gitea

I did found this, because gitea wasn't able to find my gpg key, which is in /data/git instead of /var/lib/gitea/git

With the latest rootless image, `$HOME` is pointing to `/var/lib/gitea/git` but this chart is not mounting to that dir. My workaround for now is this: ```yaml # values.yaml extraVolumeMounts: - name: data mountPath: /var/lib/gitea ``` I did found this, because gitea wasn't able to find my gpg key, which is in `/data/git` instead of `/var/lib/gitea/git`
Member

Will look into this. Haven't noticed any issues with 1.14.1 on my system.

Will look into this. Haven't noticed any issues with 1.14.1 on my system.
Author
Contributor

I only noticed that gitea didn't find the gpg key because of wrong / changed home dir.

using something like:

[repository.signing]
SIGNING_KEY = XXXXXXXXXXXXXX
SIGNING_NAME = gitea
IGNING_EMAIL: admin+gitea@example.com
I only noticed that gitea didn't find the gpg key because of wrong / changed home dir. using something like: ```ini [repository.signing] SIGNING_KEY = XXXXXXXXXXXXXX SIGNING_NAME = gitea IGNING_EMAIL: admin+gitea@example.com ```
Member

Seems to be no generic issue with the signing in general. Setting SIGNING_KEY = default and configuring via .gitconfig looks like it works (at least in 1.14.2). You are setting the signing key explicitly in app.ini, right?

Seems to be no generic issue with the signing in general. Setting `SIGNING_KEY = default` and configuring via `.gitconfig` looks like it works (at least in 1.14.2). You are setting the signing key explicitly in `app.ini`, right?
Author
Contributor

yes, as shown in comment above. ?

yes, as shown in comment above. ?
Member

? Wasn't sure. Can verify that it doesn't work with the signing key set in app.ini but am not sure yet, if it's an issue with the chart or if this setting maybe not working for rootless in general. Will check this.

? Wasn't sure. Can verify that it doesn't work with the signing key set in `app.ini` but am not sure yet, if it's an issue with the chart or if this setting maybe not working for rootless in general. Will check this.
Author
Contributor

setting works with my additional mount. ?

setting works with my additional mount. ?
Member

Hrm. As far as I could find out, it's not working with a basic docker container outside of Kubernetes either. For both image variants. I got it working when configuring the signingkey inside the .gitignore file as well as setting SIGNING_KEY = <keyid> in app.ini. I am not sure, if this is intended. ?

Also, I was not able to get it working with your suggested workaround. The override of the data mountPath seems to not properly work (in my environment). Have you changed something else?

EDIT: Incorrect statement.

~~Hrm. As far as I could find out, it's not working with a basic docker container outside of Kubernetes either. For both image variants. I got it working when configuring the signingkey inside the `.gitignore` file as well as setting `SIGNING_KEY = <keyid>` in `app.ini`. I am not sure, if this is intended. ?~~ ~~Also, I was not able to get it working with your suggested workaround. The override of the `data` mountPath seems to not properly work (in my environment). Have you changed something else?~~ EDIT: Incorrect statement.
Member

@viceice ? Hi! This time with an awake mind. I was way too tired.

I've tested your report again and don't have problems with commit signing. I didn't change anything in ~/.gitconfig. In values.yaml I added the following:

gitea:
  config:
+   repository.signing:
+     SIGNING_KEY: XXXXXX
+     SIGNING_NAME: your-name
+     SIGNING_EMAIL: your@email.com
+     INITIAL_COMMIT: always
+     WIKI: always
+     CRUD_ACTIONS: always
+     MERGES: always

Manually imported public and private key via gpg --import ... from inside the running container with git user context.

When I create a repository, the initial commit is signed. Changing files through the UI also creates signed commit.

Sorry for any confusion because of my latest posts. Is it possible to share a bit more details about your helm chart configuration?

  • How did you set the app.ini signing settings? Via environment variables or as config object inside values.yaml like I did?
  • How were the key pair provided to Gitea?
  • How does the ~/.gitconfig looks like?

I am using Gitea rootless 1.14.2.

@viceice ? Hi! This time with an awake mind. I was way too tired. I've tested your report again and don't have problems with commit signing. I didn't change anything in `~/.gitconfig`. In `values.yaml` I added the following: ```diff gitea: config: + repository.signing: + SIGNING_KEY: XXXXXX + SIGNING_NAME: your-name + SIGNING_EMAIL: your@email.com + INITIAL_COMMIT: always + WIKI: always + CRUD_ACTIONS: always + MERGES: always ``` Manually imported public and private key via `gpg --import ...` from inside the running container with `git` user context. When I create a repository, the initial commit is signed. Changing files through the UI also creates signed commit. Sorry for any confusion because of my latest posts. Is it possible to share a bit more details about your helm chart configuration? - How did you set the `app.ini` signing settings? Via environment variables or as config object inside `values.yaml` like I did? - How were the key pair provided to Gitea? - How does the `~/.gitconfig` looks like? I am using Gitea rootless 1.14.2.
Author
Contributor

I've migrated from 1.13 root image to 1.14 root. and then to the rootless image. so thd key import was on v1.13 and works with v1.14 root image. but after switch to rootless git searches in the homedir i mentioned.

i can provide my basic config tomorrow.

I've migrated from 1.13 root image to 1.14 root. and then to the rootless image. so thd key import was on v1.13 and works with v1.14 root image. but after switch to rootless git searches in the homedir i mentioned. i can provide my basic config tomorrow.
Author
Contributor

values.yaml

#version: 1

replicaCount: 1 # default=2

image:
  repository: gitea/gitea
  tag: 1.14.3
  pullPolicy: IfNotPresent
  rootless: true

imagePullSecrets:
  - name: docker-cfg

gitea:
  database:
    builtIn:
      postgresql:
        enabled: false
  cache:
    builtIn:
      enabled: false
  admin:
    username: xxxx
    password: '${adm-psw}'
    email: xxx@domain.test

  config:
    APP_NAME: XXX
    DEFAULT_BRANCH: main
    admin:
      DEFAULT_EMAIL_NOTIFICATIONS: onmention
      DISABLE_REGULAR_ORG_CREATION: true
    database:
      DB_TYPE: postgres
      HOST: postgresql.db:5432
      NAME: gitea
      USER: gitea
      PASSWD: ${db-psw}
      LOG_SQL: false
      MAX_IDLE_CONNS: 10
      CONN_MAX_LIFE_TIME: 5m
    server:
      ROOT_URL: https://gitea.domain.test
      DISABLE_SSH: true
      LANDING_PAGE: login

    mailer:
      ENABLED: true
      HOST: xxxx:25
      FROM: no-reply@xxx.test
      SKIP_VERIFY: true

    cache:
      ADAPTER: redis
      HOST: ${redis}
    cron.sync_external_users:
      RUN_AT_START: true
    migrations:
      ALLOW_LOCALNETWORKS: true
    queue:
      TYPE: redis
      CONN_STR: ${redis}
    session:
      PROVIDER: redis
      PROVIDER_CONFIG: ${redis}
      COOKIE_SECURE: true
    indexer:
      ISSUE_INDEXER_TYPE: elasticsearch
      ISSUE_INDEXER_CONN_STR: http://${elasticsearch}:9200
      ISSUE_INDEXER_QUEUE_TYPE: redis
      REPO_INDEXER_ENABLED: true
      REPO_INDEXER_TYPE: elasticsearch
      REPO_INDEXER_CONN_STR: http://${elasticsearch}:9200

    repository:
      ROOT: /data/gitea-repositories # override since gitea v1.14
    #   MAX_CREATION_LIMIT: 0
    repository.pull-request:
      DEFAULT_MERGE_MESSAGE_COMMITS_LIMIT: 0
      DEFAULT_MERGE_MESSAGE_SIZE: 0
      DEFAULT_MERGE_MESSAGE_ALL_AUTHORS: true

    repository.upload:
      FILE_MAX_SIZE: 20
      TEMP_PATH: /tmp/uploads
    repository.local:
      LOCAL_COPY_PATH: /data/tmp/local-repo
    repository.signing:
      SIGNING_KEY: XXXXXX
      SIGNING_NAME: gitea
      SIGNING_EMAIL: xxxx@domain.test
      CRUD_ACTIONS: pubkey, twofa
      MERGES: pubkey, twofa
      WIKI: pubkey, twofa

    attachment:
      MAX_SIZE: 50
      STORAGE_TYPE: minio
    lfs:
      STORAGE_TYPE: minio
    picture:
      AVATAR_STORAGE_TYPE: minio
      REPOSITORY_AVATAR_STORAGE_TYPE: minio

    storage:
      MINIO_ENDPOINT: s3.domain.test
      MINIO_LOCATION: md-hq-1
      MINIO_ACCESS_KEY_ID: gitea
      MINIO_BUCKET: gitea
      MINIO_USE_SSL: true

    security:
      INSTALL_LOCK: true
      INTERNAL_TOKEN_URI: file:/data/gitea/internal_token
      MIN_PASSWORD_LENGTH: 12
      PASSWORD_COMPLEXITY: lower,upper,digit
      PASSWORD_HASH_ALGO: argon2
      REVERSE_PROXY_TRUSTED_PROXIES: 127.0.0.0/8,::1/128,10.42.0.0/16

    openid:
      ENABLE_OPENID_SIGNIN: false
      ENABLE_OPENID_SIGNUP: false
    #   WHITELISTED_URIS: ^https:\/\/fs\.domain\.test\/

    service:
      DISABLE_REGISTRATION: true
      REGISTER_MANUAL_CONFIRM: true
      REQUIRE_SIGNIN_VIEW: true
      ENABLE_NOTIFY_MAIL: true
      DEFAULT_KEEP_EMAIL_PRIVATE: true
      AUTO_WATCH_NEW_REPOS: false
      NO_REPLY_ADDRESS: no-reply.domain.test
      ALLOW_ONLY_EXTERNAL_REGISTRATION: true


  livenessProbe:
    enabled: false
  readinessProbe:
    enabled: false
  startupProbe:
    enabled: false

  customLivenessProbe:
    httpGet:
      path: /user/login
      port: http
    initialDelaySeconds: 0
    periodSeconds: 5
    timeoutSeconds: 10
    successThreshold: 1
    failureThreshold: 5
  customReadinessProbe:
    httpGet:
      path: /user/login
      port: http
    initialDelaySeconds: 0
    periodSeconds: 5
    timeoutSeconds: 2
    successThreshold: 1
    failureThreshold: 3
  customStartupProbe:
    httpGet:
      path: /user/login
      port: http
    initialDelaySeconds: 10
    periodSeconds: 5
    timeoutSeconds: 10
    successThreshold: 1
    failureThreshold: 30


  podAnnotations:
    checksum/configfiles: ${cm-files-checksum}

  ldap:
    enabled: true
    name: xxx-ldap
    security-protocol: unencrypted
    host: xxxxx
    port: '389'
    user-search-base: OU=Users,DC=domain,DC=test
    user-filter: '(&(objectClass=user)(sAMAccountName=%s)(!(UserAccountControl:1.2.840.113556.1.4.803:=2))(memberOf:1.2.840.113556.1.4.1941:=CN=gitea,OU=Security Groups,DC=domain,DC=test))'
    admin-filter: '(memberOf:1.2.840.113556.1.4.1941:=CN=admins,OU=Security Groups,DC=domain,DC=test)'
    restricted-filter: '(memberOf:1.2.840.113556.1.4.1941:=CN=gitea-restricted,OU=Security Groups,DC=domain,DC=test)'
    bind-dn: CN=ldap,OU=ServiceAccounts,DC=domain,DC=test
    bind-password: ${ldap-psw}
    email-attribute: userPrincipalName
    username-attribute: sAMAccountName
    firstname-attribute: givenName
    surname-attribute: sn
    # synchronize-users:

ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: traefik
    traefik.ingress.kubernetes.io/router.entrypoints: websecure
    traefik.ingress.kubernetes.io/router.tls: 'true'
  hosts:
    - gitea.domain.test

service:
  http:
    annotations:
      traefik.ingress.kubernetes.io/service.sticky.cookie: 'true'
      traefik.ingress.kubernetes.io/service.sticky.cookie.secure: 'true'
      traefik.ingress.kubernetes.io/service.sticky.cookie.httponly: 'true'
      traefik.ingress.kubernetes.io/service.sticky.cookie.samesite: 'strict'

resources:
  requests:
    #   cpu: 100m
    memory: 512Mi
  limits:
    #   cpu: 100m
    memory: 2Gi

affinity:
  podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 50
        podAffinityTerm:
          topologyKey: kubernetes.io/hostname
          labelSelector:
            matchExpressions:
              - key: app.kubernetes.io/name
                operator: In
                values:
                  - gitea
              - key: app.kubernetes.io/instance
                operator: In
                values:
                  - gitea

extraVolumes:
  - name: cm-files
    configMap:
      name: ${cm-files}

extraVolumeMounts:
  - name: cm-files
    mountPath: /data/gitea/templates/custom/footer.tmpl
    subPath: custom-footer.html
    readOnly: true
  - name: cm-files
    mountPath: /data/gitea/public/js/xxx-utils.js
    subPath: public-xxx-utils.js
    readOnly: true
  - name: data
    mountPath: /var/lib/gitea

The ${xxx} values are replaced by terraform templatefile

Additional values via terraform:

  • gitea.config.security.SECRET_KEY
  • gitea.config.storage.MINIO_SECRET_ACCESS_KEY
  • gitea.config.oauth2.JWT_SECRET
  • persistence.existingClaim
**values.yaml** ```yaml #version: 1 replicaCount: 1 # default=2 image: repository: gitea/gitea tag: 1.14.3 pullPolicy: IfNotPresent rootless: true imagePullSecrets: - name: docker-cfg gitea: database: builtIn: postgresql: enabled: false cache: builtIn: enabled: false admin: username: xxxx password: '${adm-psw}' email: xxx@domain.test config: APP_NAME: XXX DEFAULT_BRANCH: main admin: DEFAULT_EMAIL_NOTIFICATIONS: onmention DISABLE_REGULAR_ORG_CREATION: true database: DB_TYPE: postgres HOST: postgresql.db:5432 NAME: gitea USER: gitea PASSWD: ${db-psw} LOG_SQL: false MAX_IDLE_CONNS: 10 CONN_MAX_LIFE_TIME: 5m server: ROOT_URL: https://gitea.domain.test DISABLE_SSH: true LANDING_PAGE: login mailer: ENABLED: true HOST: xxxx:25 FROM: no-reply@xxx.test SKIP_VERIFY: true cache: ADAPTER: redis HOST: ${redis} cron.sync_external_users: RUN_AT_START: true migrations: ALLOW_LOCALNETWORKS: true queue: TYPE: redis CONN_STR: ${redis} session: PROVIDER: redis PROVIDER_CONFIG: ${redis} COOKIE_SECURE: true indexer: ISSUE_INDEXER_TYPE: elasticsearch ISSUE_INDEXER_CONN_STR: http://${elasticsearch}:9200 ISSUE_INDEXER_QUEUE_TYPE: redis REPO_INDEXER_ENABLED: true REPO_INDEXER_TYPE: elasticsearch REPO_INDEXER_CONN_STR: http://${elasticsearch}:9200 repository: ROOT: /data/gitea-repositories # override since gitea v1.14 # MAX_CREATION_LIMIT: 0 repository.pull-request: DEFAULT_MERGE_MESSAGE_COMMITS_LIMIT: 0 DEFAULT_MERGE_MESSAGE_SIZE: 0 DEFAULT_MERGE_MESSAGE_ALL_AUTHORS: true repository.upload: FILE_MAX_SIZE: 20 TEMP_PATH: /tmp/uploads repository.local: LOCAL_COPY_PATH: /data/tmp/local-repo repository.signing: SIGNING_KEY: XXXXXX SIGNING_NAME: gitea SIGNING_EMAIL: xxxx@domain.test CRUD_ACTIONS: pubkey, twofa MERGES: pubkey, twofa WIKI: pubkey, twofa attachment: MAX_SIZE: 50 STORAGE_TYPE: minio lfs: STORAGE_TYPE: minio picture: AVATAR_STORAGE_TYPE: minio REPOSITORY_AVATAR_STORAGE_TYPE: minio storage: MINIO_ENDPOINT: s3.domain.test MINIO_LOCATION: md-hq-1 MINIO_ACCESS_KEY_ID: gitea MINIO_BUCKET: gitea MINIO_USE_SSL: true security: INSTALL_LOCK: true INTERNAL_TOKEN_URI: file:/data/gitea/internal_token MIN_PASSWORD_LENGTH: 12 PASSWORD_COMPLEXITY: lower,upper,digit PASSWORD_HASH_ALGO: argon2 REVERSE_PROXY_TRUSTED_PROXIES: 127.0.0.0/8,::1/128,10.42.0.0/16 openid: ENABLE_OPENID_SIGNIN: false ENABLE_OPENID_SIGNUP: false # WHITELISTED_URIS: ^https:\/\/fs\.domain\.test\/ service: DISABLE_REGISTRATION: true REGISTER_MANUAL_CONFIRM: true REQUIRE_SIGNIN_VIEW: true ENABLE_NOTIFY_MAIL: true DEFAULT_KEEP_EMAIL_PRIVATE: true AUTO_WATCH_NEW_REPOS: false NO_REPLY_ADDRESS: no-reply.domain.test ALLOW_ONLY_EXTERNAL_REGISTRATION: true livenessProbe: enabled: false readinessProbe: enabled: false startupProbe: enabled: false customLivenessProbe: httpGet: path: /user/login port: http initialDelaySeconds: 0 periodSeconds: 5 timeoutSeconds: 10 successThreshold: 1 failureThreshold: 5 customReadinessProbe: httpGet: path: /user/login port: http initialDelaySeconds: 0 periodSeconds: 5 timeoutSeconds: 2 successThreshold: 1 failureThreshold: 3 customStartupProbe: httpGet: path: /user/login port: http initialDelaySeconds: 10 periodSeconds: 5 timeoutSeconds: 10 successThreshold: 1 failureThreshold: 30 podAnnotations: checksum/configfiles: ${cm-files-checksum} ldap: enabled: true name: xxx-ldap security-protocol: unencrypted host: xxxxx port: '389' user-search-base: OU=Users,DC=domain,DC=test user-filter: '(&(objectClass=user)(sAMAccountName=%s)(!(UserAccountControl:1.2.840.113556.1.4.803:=2))(memberOf:1.2.840.113556.1.4.1941:=CN=gitea,OU=Security Groups,DC=domain,DC=test))' admin-filter: '(memberOf:1.2.840.113556.1.4.1941:=CN=admins,OU=Security Groups,DC=domain,DC=test)' restricted-filter: '(memberOf:1.2.840.113556.1.4.1941:=CN=gitea-restricted,OU=Security Groups,DC=domain,DC=test)' bind-dn: CN=ldap,OU=ServiceAccounts,DC=domain,DC=test bind-password: ${ldap-psw} email-attribute: userPrincipalName username-attribute: sAMAccountName firstname-attribute: givenName surname-attribute: sn # synchronize-users: ingress: enabled: true annotations: kubernetes.io/ingress.class: traefik traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.tls: 'true' hosts: - gitea.domain.test service: http: annotations: traefik.ingress.kubernetes.io/service.sticky.cookie: 'true' traefik.ingress.kubernetes.io/service.sticky.cookie.secure: 'true' traefik.ingress.kubernetes.io/service.sticky.cookie.httponly: 'true' traefik.ingress.kubernetes.io/service.sticky.cookie.samesite: 'strict' resources: requests: # cpu: 100m memory: 512Mi limits: # cpu: 100m memory: 2Gi affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 50 podAffinityTerm: topologyKey: kubernetes.io/hostname labelSelector: matchExpressions: - key: app.kubernetes.io/name operator: In values: - gitea - key: app.kubernetes.io/instance operator: In values: - gitea extraVolumes: - name: cm-files configMap: name: ${cm-files} extraVolumeMounts: - name: cm-files mountPath: /data/gitea/templates/custom/footer.tmpl subPath: custom-footer.html readOnly: true - name: cm-files mountPath: /data/gitea/public/js/xxx-utils.js subPath: public-xxx-utils.js readOnly: true - name: data mountPath: /var/lib/gitea ``` The `${xxx}` values are replaced by terraform `templatefile` Additional values via terraform: - `gitea.config.security.SECRET_KEY` - `gitea.config.storage.MINIO_SECRET_ACCESS_KEY` - `gitea.config.oauth2.JWT_SECRET` - `persistence.existingClaim`
Member

Thanks for sharing. I'll have a closer look at it in the next few days.

Thanks for sharing. I'll have a closer look at it in the next few days.
Author
Contributor

I think the major difference bewteen the root and rootless images if the HOME path.

In old root image i've imported the gpg key on running container and it was saved to /data/git, but when i swiched to the rootless image, it starts to search in /var/lib/gitea/git for the gpg key, as the HOME path is changed to that path.

Thats why it simply works for me to additionally mount my data volume to /var/lib/gitea.

I think the major difference bewteen the root and rootless images if the `HOME` path. In old root image i've imported the gpg key on running container and it was saved to `/data/git`, but when i swiched to the rootless image, it starts to search in `/var/lib/gitea/git` for the gpg key, as the `HOME` path is changed to that path. Thats why it simply works for me to additionally mount my data volume to `/var/lib/gitea`.
Member

Hi @viceice.

I think the major difference bewteen the root and rootless images if the HOME path.

You are right. That's the main difference and the actual root cause of this issue. I tested your mentioned migration path from rootful to rootless image usage and was able to reproduce that behaviour.

The HOME path is not persistent in rootless, so the .gnupg folder is't either. Since the helm chart always used /data/... as mount point for storage of all kinds, it would be a minimal impact to just relocate the default dynamic $HOME/.gnupg folder location to /data/git/.gnupg. This is where the signing keys are stored when running rootful-based environments. I've created a Pull Request to always use that persistent location for .gnupg.
Doing so should

  • fix your issue
  • allow migrations between both image variants
  • persist signing keys for rootless environments (which is not the case right now)

Can you verify that my PR fixes your issue? Would appreciate your feedback on that.

Hi @viceice. > I think the major difference bewteen the root and rootless images if the HOME path. You are right. That's the main difference and the actual root cause of this issue. I tested your mentioned migration path from rootful to rootless image usage and was able to reproduce that behaviour. The `HOME` path is not persistent in rootless, so the `.gnupg` folder is't either. Since the helm chart always used `/data/...` as mount point for storage of all kinds, it would be a minimal impact to just relocate the default dynamic `$HOME/.gnupg` folder location to `/data/git/.gnupg`. This is where the signing keys are stored when running rootful-based environments. I've created a [Pull Request](https://gitea.com/gitea/helm-chart/pulls/186) to always use that persistent location for `.gnupg`. Doing so should - fix your issue - allow migrations between both image variants - persist signing keys for rootless environments (which is not the case right now) Can you verify that my PR fixes your issue? Would appreciate your feedback on that.
justusbunsi added the
kind
bug
label 2021-06-26 09:14:02 +00:00
Author
Contributor

Sure, I'll can't test the pr directly but it seems i only need to set the GNUPGHOME env instead of my mount workaround.

Will test it tomorrow or monday. ?

Sure, I'll can't test the pr directly but it seems i only need to set the `GNUPGHOME` env instead of my mount workaround. Will test it tomorrow or monday. ?
Author
Contributor

Works ?

Works ?
justusbunsi added this to the Release 4.0.0 milestone 2021-06-30 10:15:16 +00:00
Sign in to join this conversation.
No Milestone
No Assignees
3 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: gitea/helm-chart#155
No description provided.