-
-
Notifications
You must be signed in to change notification settings - Fork 186
Open
Labels
Description
Summary
I am trying to configure a local user for a concourse deployment running in GKE, installed via the concourse helm chart. The first user in my list is correctly configured, but the second one does not get configured at all.
Steps to Reproduce
- Install concourse in a Kubernetes cluster with helm
- Include this in your values:
secrets: create: false
- Create a k8s secret (ours is called
concourse-web) and add the attributelocal-userswith this content:concourse-admin:password123,other-user:otherpassword - Run helm install
- Include this in your values:
- Install the Fly CLI and try to log in as the second local user
fly -t test login --concourse-url 'https://concourse.example.com' --username other-user --password other-password
Expected Results
I should successfully sign in as the second local user when running fly login.
Actual Results
When I run fly login with the second user's credentials, I get this error:
error: oauth2: "access_denied" "Invalid username or password"
I confirmed that the problem was not with the second user's name or password by swapping the order and confirming that I could log in when the second user was put first in the list.
Additionally, when running fly active-users, I do not see the second user in the list, but I do see an "empty" user shown:
concourse-admin local 2025-09-09
2025-09-12
Web Node(s) configuration
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "69"
creationTimestamp: "2024-03-18T21:00:15Z"
generation: 71
labels:
app: concourse-web
argocd.argoproj.io/instance: concourse
chart: concourse-18.4.1
heritage: Helm
release: concourse
name: concourse-web
namespace: concourse
resourceVersion: "1757707611221823007"
uid: 6088ee19-a206-4949-b60c-7ed9cbe7aebb
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: concourse-web
release: concourse
strategy:
rollingUpdate:
maxSurge: 26%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
annotations:
checksum/config: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
checksum/secrets: 01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b
kubectl.kubernetes.io/restartedAt: "2025-09-12T20:06:48Z"
creationTimestamp: null
labels:
app: concourse-web
release: concourse
spec:
containers:
- args:
- web
env:
- name: CONCOURSE_OIDC_SCOPE
value: openid,email,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/userinfo.profile,openid,https://www.googleapis.com/auth/cloud-platform
- name: CONCOURSE_CLUSTER_NAME
value: dnastack-concourse
- name: CONCOURSE_PAUSE_PIPELINES_AFTER
value: "90"
- name: CONCOURSE_ENABLE_GLOBAL_RESOURCES
value: "true"
- name: CONCOURSE_ENABLE_ACROSS_STEP
value: "true"
- name: CONCOURSE_SECRET_RETRY_ATTEMPTS
value: "5"
- name: CONCOURSE_SECRET_RETRY_INTERVAL
value: 1s
- name: CONCOURSE_LOG_LEVEL
value: info
- name: CONCOURSE_BIND_PORT
value: "8080"
- name: CONCOURSE_BIND_IP
value: 0.0.0.0
- name: CONCOURSE_ADD_LOCAL_USER
valueFrom:
secretKeyRef:
key: local-users
name: concourse-web
- name: CONCOURSE_EXTERNAL_URL
value: https://concourse.example.com # not actual URL
- name: CONCOURSE_DEBUG_BIND_IP
value: 127.0.0.1
- name: CONCOURSE_DEBUG_BIND_PORT
value: "8079"
- name: CONCOURSE_INTERCEPT_IDLE_TIMEOUT
value: 0m
- name: CONCOURSE_GLOBAL_RESOURCE_CHECK_TIMEOUT
value: 1h
- name: CONCOURSE_RESOURCE_CHECKING_INTERVAL
value: 1m
- name: CONCOURSE_RESOURCE_TYPE_CHECKING_INTERVAL
value: 1m
- name: CONCOURSE_RESOURCE_WITH_WEBHOOK_CHECKING_INTERVAL
value: 1m
- name: CONCOURSE_CONTAINER_PLACEMENT_STRATEGY
value: volume-locality
- name: CONCOURSE_BAGGAGECLAIM_RESPONSE_HEADER_TIMEOUT
value: 1m
- name: CONCOURSE_BUILD_TRACKER_INTERVAL
value: 10s
- name: CONCOURSE_DB_NOTIFICATION_BUS_QUEUE_SIZE
value: "10000"
- name: CONCOURSE_POSTGRES_HOST
value: postgres
- name: CONCOURSE_POSTGRES_PORT
value: "5432"
- name: CONCOURSE_POSTGRES_USER
valueFrom:
secretKeyRef:
key: postgresql-user
name: concourse-web
- name: CONCOURSE_POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
key: postgresql-password
name: concourse-web
- name: CONCOURSE_POSTGRES_SSLMODE
value: disable
- name: CONCOURSE_POSTGRES_CONNECT_TIMEOUT
value: 5m
- name: CONCOURSE_POSTGRES_DATABASE
value: atc
- name: CONCOURSE_KUBERNETES_IN_CLUSTER
value: "true"
- name: CONCOURSE_KUBERNETES_NAMESPACE_PREFIX
value: concourse-
- name: CONCOURSE_DATADOG_AGENT_HOST
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.hostIP
- name: CONCOURSE_DATADOG_AGENT_PORT
value: "8125"
- name: CONCOURSE_DATADOG_PREFIX
value: concourse.ci
- name: CONCOURSE_GC_INTERVAL
value: 30s
- name: CONCOURSE_GC_ONE_OFF_GRACE_PERIOD
value: 5m
- name: CONCOURSE_GC_MISSING_GRACE_PERIOD
value: 5m
- name: CONCOURSE_AUTH_DURATION
value: 24h
- name: CONCOURSE_SESSION_SIGNING_KEY
value: /concourse-keys/session_signing_key
- name: CONCOURSE_MAIN_TEAM_LOCAL_USER
value: concourse-admin
- name: CONCOURSE_MAIN_TEAM_OIDC_USER
value: [email protected] # not actual list
- name: CONCOURSE_OIDC_DISPLAY_NAME
value: Google
- name: CONCOURSE_OIDC_ISSUER
value: https://accounts.google.com
- name: CONCOURSE_OIDC_CLIENT_ID
valueFrom:
secretKeyRef:
key: oidc-client-id
name: concourse-web
- name: CONCOURSE_OIDC_CLIENT_SECRET
valueFrom:
secretKeyRef:
key: oidc-client-secret
name: concourse-web
- name: CONCOURSE_OIDC_GROUPS_KEY
value: hd
- name: CONCOURSE_OIDC_USER_NAME_KEY
value: email
- name: POD_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
- name: CONCOURSE_PEER_ADDRESS
value: $(POD_IP)
- name: CONCOURSE_TSA_LOG_LEVEL
value: info
- name: CONCOURSE_TSA_BIND_IP
value: 0.0.0.0
- name: CONCOURSE_TSA_BIND_PORT
value: "2222"
- name: CONCOURSE_TSA_DEBUG_BIND_IP
value: 127.0.0.1
- name: CONCOURSE_TSA_DEBUG_BIND_PORT
value: "2221"
- name: CONCOURSE_TSA_HOST_KEY
value: /concourse-keys/host_key
- name: CONCOURSE_TSA_AUTHORIZED_KEYS
value: /concourse-keys/worker_key.pub
- name: CONCOURSE_TSA_HEARTBEAT_INTERVAL
value: 30s
image: concourse/concourse:7.14.1
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 5
httpGet:
path: /api/v1/info
port: atc
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 15
successThreshold: 1
timeoutSeconds: 3
name: concourse-web
ports:
- containerPort: 8080
name: atc
protocol: TCP
- containerPort: 2222
name: tsa
protocol: TCP
- containerPort: 8079
name: atc-debug
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /api/v1/info
port: atc
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
resources:
requests:
cpu: "1"
memory: 2Gi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /concourse-keys
name: concourse-keys
readOnly: true
- mountPath: /concourse-auth
name: auth-keys
readOnly: true
dnsPolicy: ClusterFirst
initContainers:
- args:
- migrate
- --migrate-to-latest-version
env:
- name: CONCOURSE_POSTGRES_HOST
value: postgres
- name: CONCOURSE_POSTGRES_PORT
value: "5432"
- name: CONCOURSE_POSTGRES_USER
valueFrom:
secretKeyRef:
key: postgresql-user
name: concourse-web
- name: CONCOURSE_POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
key: postgresql-password
name: concourse-web
- name: CONCOURSE_POSTGRES_SSLMODE
value: disable
- name: CONCOURSE_POSTGRES_CONNECT_TIMEOUT
value: 5m
- name: CONCOURSE_POSTGRES_DATABASE
value: atc
image: concourse/concourse:7.14.1
imagePullPolicy: IfNotPresent
name: concourse-migration
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
serviceAccount: concourse-web
serviceAccountName: concourse-web
terminationGracePeriodSeconds: 30
volumes:
- name: concourse-keys
secret:
defaultMode: 256
items:
- key: host-key
path: host_key
- key: session-signing-key
path: session_signing_key
- key: worker-key-pub
path: worker_key.pub
secretName: concourse-web
- name: auth-keys
secret:
defaultMode: 256
secretName: concourse-web
status:
availableReplicas: 1
conditions:
- lastTransitionTime: "2025-09-05T08:07:56Z"
lastUpdateTime: "2025-09-05T08:07:56Z"
message: Deployment has minimum availability.
reason: MinimumReplicasAvailable
status: "True"
type: Available
- lastTransitionTime: "2025-08-21T20:37:36Z"
lastUpdateTime: "2025-09-12T20:06:51Z"
message: ReplicaSet "concourse-web-7845bb58dc" has successfully progressed.
reason: NewReplicaSetAvailable
status: "True"
type: Progressing
observedGeneration: 71
readyReplicas: 1
replicas: 1
updatedReplicas: 1
Worker(s) configuration
No response
Concourse Version
7.14.1
Browser (if applicable)
No response
Did this use to work?
Not sure, never tried it before