Registry migration fails to restart service when using sudo -u registry
What
The error we get os fatal: unable to open current directory: access denied when running gitlab-ctl registry-database migrate up with the registry user from a directory that the registry does not have access to. This happens because after migrations are run, the registry attempts to restart the runit service by forking a process which inherits a current directory that it does not have access to.
When we run on a VM with Ubuntu or SELinux, for instance, we're usually logged in with a custom user profile. And we're usually located on this users $HOME directory, which is usually a directory that GitLab has not rights on. So Runit ends up failing to open the current directory.
This is usually not a problem with our Docker deployments, since we don't have sudo and we use su - registry instead, which moves the command to be run from the users home directory:
root@f2d788c1c19e:/home/ubuntu# su - registry bash -c 'pwd'
/var/opt/gitlab/registry
So the problem only happens with sudo -u registry.
More context
Here's what was happening. When we run:
sudo -u registry bash -c 'gitlab-ctl registry-database migrate up --skip-post-deployment'
If the command was in /home/jcunha (my $HOME directory on my Ubuntu VM), after the migration is completed, the command attempts to restart the registry service. The problem occurs inside run_sv_command_for_service, which is defined in the omnibus-ctl lib:
def run_sv_command_for_service(sv_cmd, service_name)
if service_enabled?(service_name)
status = run_command("#{base_path}/init/#{service_name} #{sv_cmd}")
# ...
end
end
This calls run_command, which uses system():
def run_command(command)
system(command)
$?
end
When system() spawns the /opt/gitlab/init/registry start script, it:
- Forks a new process
- The child process inherits the current working directory (
/home/jcunha) - The sv/runit scripts try to access or verify the current directory
-
But the
registryuser doesn't have permission to access/home/jcunha❌
This causes the "unable to open current directory: access denied" error.
Example Logs
# Fatal error because after the migration happens the registry tries to restart the service from my users $HOME dir:
Alexand@jcunha-test-omnibus:~$ sudo -u registry bash -c 'gitlab-ctl registry-database migrate up --skip-post-deployment'
Running migrate up
Executing command:
/opt/gitlab/embedded/bin/registry database migrate up -s /var/opt/gitlab/registry/config.yml
OK: applied 0 pre-deployment migration(s), 0 post-deployment migration(s) and 0 background migration(s) in 0.010s
Starting service registry
fatal: unable to open current directory: access denied
# Confirmation that the problem is about the restart, not about the migration
Alexand@jcunha-test-omnibus:~$ sudo -u registry bash -c 'gitlab-ctl restart registry'
fatal: unable to open current directory: access denied
# Confirmation that if we cd into another directory, the problem does not happen
Alexand@jcunha-test-omnibus:~$ sudo -u registry bash -c 'cd /var/opt/gitlab && gitlab-ctl registry-database migrate up --skip-post-deployment'
Running migrate up
Executing command:
/opt/gitlab/embedded/bin/registry database migrate up -s /var/opt/gitlab/registry/config.yml
OK: applied 0 pre-deployment migration(s), 0 post-deployment migration(s) and 0 background migration(s) in 0.010s
Proposal
Force the gitlab-ctl registry-database commands to do a temporary cd into a directory that runit has access to.