`gitlab-backup-cli` omnibus package bin command lacks privilege/system user handling
Summary
In #8273 (closed), we added the initial bin command gitlab-backup-cli
as part of the project to replace existing gitlab-backup
with a newer unified backup tool. Testing with @nwestbury and @sranasinghe, it seems the command gitlab-backup-cli
when run as root on a production install from the omnibus package is failing:
root@br-1k-main-gitlab-rails-1:~# gitlab-backup-cli backup all
[2024-05-09 15:41:15 UTC] ℹ️ Initializing environment...
/opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/execjs-2.8.1/lib/execjs/runtimes.rb:58:in `autodetect': Could not find a JavaScript runtime. See https://github.com/rails/execjs for a list of available runtimes. (ExecJS::RuntimeUnavailable)
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/execjs-2.8.1/lib/execjs.rb:5:in `<module:ExecJS>'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/execjs-2.8.1/lib/execjs.rb:4:in `<main>'
from <internal:/opt/gitlab/embedded/lib/ruby/site_ruby/3.1.0/rubygems/core_ext/kernel_require.rb>:37:in `require'
from <internal:/opt/gitlab/embedded/lib/ruby/site_ruby/3.1.0/rubygems/core_ext/kernel_require.rb>:37:in `require'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/bootsnap-1.18.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/terser-1.0.2/lib/terser.rb:6:in `<main>'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/bundler-2.5.8/lib/bundler/runtime.rb:60:in `require'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/bundler-2.5.8/lib/bundler/runtime.rb:60:in `block (2 levels) in require'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/bundler-2.5.8/lib/bundler/runtime.rb:55:in `each'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/bundler-2.5.8/lib/bundler/runtime.rb:55:in `block in require'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/bundler-2.5.8/lib/bundler/runtime.rb:44:in `each'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/bundler-2.5.8/lib/bundler/runtime.rb:44:in `require'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/bundler-2.5.8/lib/bundler.rb:187:in `require'
from /opt/gitlab/embedded/service/gitlab-rails/config/application.rb:18:in `<main>'
from <internal:/opt/gitlab/embedded/lib/ruby/site_ruby/3.1.0/rubygems/core_ext/kernel_require.rb>:37:in `require'
from <internal:/opt/gitlab/embedded/lib/ruby/site_ruby/3.1.0/rubygems/core_ext/kernel_require.rb>:37:in `require'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/bootsnap-1.18.3/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:30:in `require'
from /opt/gitlab/embedded/service/gitlab-rails/gems/gitlab-backup-cli/lib/gitlab/backup/cli.rb:23:in `rails_environment!'
from /opt/gitlab/embedded/service/gitlab-rails/gems/gitlab-backup-cli/lib/gitlab/backup/cli/commands/backup_subcommand.rb:14:in `block in all'
from /opt/gitlab/embedded/service/gitlab-rails/gems/gitlab-backup-cli/lib/gitlab/backup/cli/commands/backup_subcommand.rb:45:in `measure_duration'
from /opt/gitlab/embedded/service/gitlab-rails/gems/gitlab-backup-cli/lib/gitlab/backup/cli/commands/backup_subcommand.rb:12:in `all'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/thor-1.3.1/lib/thor/command.rb:28:in `run'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/thor-1.3.1/lib/thor/invocation.rb:127:in `invoke_command'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/thor-1.3.1/lib/thor.rb:527:in `dispatch'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/thor-1.3.1/lib/thor/invocation.rb:116:in `invoke'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/thor-1.3.1/lib/thor.rb:338:in `block in subcommand'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/thor-1.3.1/lib/thor/command.rb:28:in `run'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/thor-1.3.1/lib/thor/invocation.rb:127:in `invoke_command'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/thor-1.3.1/lib/thor.rb:527:in `dispatch'
from /opt/gitlab/embedded/lib/ruby/gems/3.1.0/gems/thor-1.3.1/lib/thor/base.rb:584:in `start'
from /opt/gitlab/embedded/service/gitlab-rails/bin/gitlab-backup-cli:14:in `<main>'
Steps to reproduce
- Set up a sandbox gitlab install -- any architecture will work. Install the latest gitlab production build omnibus package
- ssh into the rails instance, change to root, and attempt to run a backup:
sudo su - # change to root shell
gitlab-backup-ctl backup all
# you will see the error output shown further up in this issue
What is the current bug behavior?
- It fails because it can't identify a JS execution environment while loading the Rails environment
What is the expected correct behavior?
- It should run without error and create a backup
Troubleshooting / Fix Notes
- Reviewing the other omnibus package bin scripts (e.g.
gitlab-rake
gitlab-rails
etc...), they go through great lengths to cd into the rails source directory and then change to the gitlab user with more restricted permissions - The
gitlab-backup-cli
script we added in !7328 (merged) does not do anything to set up the environment before delegating to the inner$RAILS_ROOT/bin/gitlab-backup-cli
ruby script - As root, the backup command works when I run it as:
/opt/gitlab/embedded/bin/chpst -e /opt/gitlab/etc/gitlab-rails/env -u git:git -U git:git /usr/bin/env RUBYOPT=-W:no-experimental /opt/gitlab/embedded/bin/bundle exec gitlab-backup-cli
- Thus, to resolve this bug, I propose updating the omnibus
gitlab-backup-cli
bin script to factor in the same environment setup and user/privilege switching that the other omnibus bin wrappers appear to do before calling the inner packagedgitlab-backup-cli
ruby script.