GitLab + uWSGI + Nginx on FreeBSD
Most of the details about GitLab installation under FreeBSD can be found online.
Current post contains a part about uWSGI & Nginx only.
First you have to compile uWSGI with Ruby support.
It would be faster to use version from ports:
cd /usr/ports/www/uwsgi make extract cd work/uwsgi-2.x.y.z # Create config for running Python and Ruby apps together through uWSGI printf "[uwsgi]\nmain_plugin = python,gevent,rack,rbthreads,fiber\ninherit = base" > buildconf/rackp.ini python uwsgiconfig.py --build rackp # or Ruby only python uwsgiconfig.py --build ruby2 # Check that compiled binary has Python and/or Ruby in place ./uwsgi --plugins-list cd ../.. make install
Add configuration lines into /etc/rc.conf:
uwsgi_enable="YES" uwsgi_uid="root" uwsgi_gid="wheel" uwsgi_flags="--processes=0 --die-on-term --emperor-procname \"[uWSGI] Emperor\" --procname-master \"[uWSGI] Root\" --enable-threads --reload-mercy 10 --emperor /usr/local/etc/uwsgi --emperor-pidfile /var/run/uwsgi_emperor.pid --emperor-stats /tmp/uwsgistats.sock --emperor-freq 60 --binary-path /usr/local/bin/uwsgi --disable-logging --daemonize /var/log/uwsgi.log --log-truncate --log-maxsize 5242880 --log-backupname /var/log/uwsgi.log.old"
uWSGI will be running in Emperor mode with root rights and will spawn vassals under selected uids/gids containing Master process and multiple Worker processes if necessary.
Change paths and titles as you like, then proceed to creating vassal config in the selected emperor path (or use it as an example for other modes).
[uwsgi] strict = true plugin = rack uid = git gid = git master = true auto-procname = true memory-report = false processes = 2 enable-threads = true rbthreads = true threads = 3 offload-threads = 3 socket = /home/git/gitlab/tmp/sockets/gitlab.socket chdir = /home/git/gitlab/ post-buffering = 4096 env = RAILS_ENV=production # Node.js must be installed env = EXECJS_RUNTIME=Node rack = /home/git/gitlab/config.ru rbrequire = rubygems rbrequire = bundler/setup ruby-gc-freq = 1 disable-logging = true harakiri = 60 procname = [uWSGI] Vassal GitLab worker procname-master = [uWSGI] Vassal GitLab master
Last step is to make Nginx proxy requests correctly to uWSGI and gitlab-workhorse.
Unicorn would be the 4th HTTP server if you are already using Apache, Nginx and GitLab-Workhorse. Isn’t it too many? So I decided to drop Unicorn and use Nginx instead, the only problem is that gitlab-workhorse have to use some auth backend, but it cannot be the same Nginx server, because requests are the same too, so they will go in a loop. Solution is to create Nginx vhost on another port to proxy requests back to uWSGI.
Prepare Nginx first by copying uwsgi_params-dist to uwsgi_params, then create vhosts like this:
upstream gitlab-workhorse { server unix:/home/git/gitlab/tmp/sockets/gitlab-workhorse.socket fail_timeout=0; } limit_req_zone $binary_remote_addr zone=cibuild:1m rate=2r/m; server { listen 255.255.255.255:80; server_name domain.com; access_log ...; error_log ...; root /home/git/gitlab/public; client_max_body_size 128m; # Redirect all requests to gitlab-workhorse location / { # Main page shows public projects instead of sign-in page rewrite ^/$ /public; try_files $uri @gitlab-workhorse; } # Nice hack to limit gitlab-ci-multi-runner requests # and keep your Nginx and production logs relatively clean location ~ ^/ci/api/v1/builds/register\.json$ { access_log /dev/null; limit_req_status 404; # 404 = no pending builds limit_req zone=cibuild nodelay; log_not_found off; try_files - @gitlab-workhorse; } # Static assets location ~ ^/assets/ { gzip_static on; expires max; add_header Cache-Control public; } # Proxy to GitLab Workhorse location @gitlab-workhorse { gzip off; proxy_read_timeout 300; proxy_connect_timeout 300; proxy_redirect off; proxy_buffering off; proxy_request_buffering off; proxy_http_version 1.1; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Frame-Options SAMEORIGIN; proxy_pass http://gitlab-workhorse; } } # Backend for GitLab Workhorse server { listen 255.255.255.255:8090; server_name domain.com; root /home/git/gitlab/public; client_max_body_size 128m; location / { gzip off; proxy_read_timeout 300; proxy_connect_timeout 300; proxy_redirect off; proxy_buffering off; proxy_request_buffering off; proxy_http_version 1.1; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Frame-Options SAMEORIGIN; include uwsgi_params; uwsgi_modifier1 7; uwsgi_pass unix:/home/git/gitlab/tmp/sockets/gitlab.socket; } }
Start gitlab-workhorse as a daemon using some lengthy command like this one and you are good to go
/usr/bin/su - git -c "/usr/bin/nohup /home/git/gitlab-workhorse/gitlab-workhorse -listenNetwork unix -listenAddr /home/git/gitlab/tmp/sockets/gitlab-workhorse.socket -authBackend http://domain.com:8090 -listenUmask 000 -documentRoot /home/git/gitlab/public >/home/git/gitlab/log/gitlab-workhorse.log 2>&1 &" >/dev/null 2>&1