initial_root_password erroneously containing newline
Summary
I just tried to setup a fresh instance of GitLab on Docker (Swarm Mode in my case) using the Docs at https://docs.gitlab.com/ee/install/docker.html
But whatever I tried, gitlab_rails['initial_root_password'] = File.read('/run/secrets/gitlab_root_password') just didn't seem to work.
After the setup was complete (when the actual application logs appear in the docker logs) login with the defined password didn't work.
As I read somewhere the root user could be locked due to the failed login attempt I got into the Rails console and looked at the user via User.where(id: 1).first.locked_at? which resulted in false. So that wasn't the issue.
Setting the password via the following was successful and I could login afterwards:
user = User.where(id: 1).first
user.password = 'mypassword'
user.password_confirmation = 'mypassword'
user.save!
When beginning from scratch and using gitlab_rails['initial_root_password'] = 'mypassword' everything worked as expected.
Then I thought, maybe File.read() doesn't work as expected. So again in the Rails console I tested it:
irb(main):001:0> File.read('/run/secrets/gitlab_root_password')
=> "mypassword\n"
Aha! It seems the password gets set, but to a password that cannot be entered in the login (obviously), due to the line break at the end of the file (Unix line endings).
Again, beginning from scratch, I then changed to gitlab_rails['initial_root_password'] = File.read('/run/secrets/gitlab_root_password').strip in my gitlab.rb file. And voilà - I could login as expected!
Steps to reproduce
docker-compose.yml:
version: '3.8'
services:
gitlab:
image: gitlab/gitlab-ce:14.2.3-ce.0
ports:
- 22:22
- 80:80
- 443:443
volumes:
- /srv/staging-gfs/gitlab/config:/etc/gitlab
- /srv/staging-gfs/gitlab/data:/var/opt/gitlab
- /srv/staging-gfs/gitlab/logs:/var/log/gitlab
environment:
GITLAB_OMNIBUS_CONFIG: "from_file('/omnibus_config.rb')"
configs:
- source: gitlab
target: /omnibus_config.rb
secrets:
- gitlab_root_password
# I had to disable the healthcheck while doing initial setup,
# because it took longer than the healthcheck's first check,
# so Docker killed the container and started a new one
healthcheck:
disable: true
configs:
gitlab:
file: ./gitlab.rb
secrets:
gitlab_root_password:
file: ./root_password.txt
gitlab.rb:
external_url 'http://gitlab.example.com'
gitlab_rails['initial_root_password'] = File.read('/run/secrets/gitlab_root_password')
root_password.txt:
mypassword
And then docker stack deploy -c docker-compose.yml gitlab (or docker-compose up -d).
What is the current bug behavior?
Login with the password defined in the secret file doesn't work when using gitlab_rails['initial_root_password'] = File.read('/run/secrets/gitlab_root_password').
What is the expected correct behavior?
Login with user root and the password specified in the secret file succeeds.
Possible fixes
As mentioned in the summary File.read('/run/secrets/gitlab_root_password').strip does work for me in this case.
But if the password contains spaces at the beginning or end this would again break.
After a quick internet search I found a (hopefully) more robust solution:
File.read('/run/secrets/gitlab_root_password').gsub("\n", "")
This should work as the following examples show. It is important to note that it MUST be gsub("\n", ...) and not gsub('\n', ...).
irb(main):001:0> "foo\n".gsub("\n", "")
=> "foo"
irb(main):002:0> "foo \n".gsub("\n", "")
=> "foo "
irb(main):003:0> " foo\n".gsub("\n", "")
=> " foo"
irb(main):004:0> "foo bar\n".gsub("\n", "")
=> "foo bar"
irb(main):005:0> " foo bar \n".gsub("\n", "")
=> " foo bar "
But this is merely a workaround. The actual fix should be applied where the gitlab_rails['initial_root_password'] variable is read (maybe the gsub(...) method could be applied there).