Merge branch 'master' into 'master'

[Guide] GitLab 7.6/7.7 - FreeBSD 10 - Postgres - Nginx

See merge request !30
This commit is contained in:
Achilleas Pipinellis
2015-01-22 15:33:05 +00:00
2 changed files with 714 additions and 0 deletions

299
init/init/gitlab Normal file
View File

@@ -0,0 +1,299 @@
#! /bin/sh
# GITLAB
# Maintainer: @charlienewey
# Authors: @charlienewey, rovanion.luckey@gmail.com, @randx
# PROVIDE: ghost
# KEYWORD: shutdown
PATH="/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin"
. /etc/rc.subr
name="gitlab"
rcvar="gitlab_enable"
extra_commands="status"
load_rc_config gitlab
: ${gitlab_enable:="NO"}
status_cmd="print_status"
start_cmd="start_gitlab"
stop_cmd="stop_gitlab"
restart_cmd="restart_gitlab"
### Environment variables
RAILS_ENV="production"
# Script variable names should be lower-case not to conflict with
# internal /bin/sh variables such as PATH, EDITOR or SHELL.
app_user="git"
app_root="/home/$app_user/gitlab"
pid_path="$app_root/tmp/pids"
socket_path="$app_root/tmp/sockets"
web_server_pid_path="$pid_path/unicorn.pid"
sidekiq_pid_path="$pid_path/sidekiq.pid"
# Read configuration variable file if it is present
test -f /etc/default/gitlab && . /etc/default/gitlab
# Switch to the app_user if it is not he/she who is running the script.
if [ "$USER" != "$app_user" ]; then
eval su - "$app_user" -c $(echo \")$0 "$@"$(echo \"); exit;
fi
# Switch to the gitlab path, exit on failure.
if ! cd "$app_root" ; then
echo "Failed to cd into $app_root, exiting!"; exit 1
fi
### Init Script functions
## Gets the pids from the files
check_pids(){
if ! mkdir -p "$pid_path"; then
echo "Could not create the path $pid_path needed to store the pids."
exit 1
fi
# If there exists a file which should hold the value of the Unicorn pid: read it.
if [ -f "$web_server_pid_path" ]; then
wpid=$(cat "$web_server_pid_path")
else
wpid=0
fi
if [ -f "$sidekiq_pid_path" ]; then
spid=$(cat "$sidekiq_pid_path")
else
spid=0
fi
}
## Called when we have started the two processes and are waiting for their pid files.
wait_for_pids(){
# We are sleeping a bit here mostly because sidekiq is slow at writing it's pid
i=0;
while [ ! -f $web_server_pid_path -o ! -f $sidekiq_pid_path ]; do
sleep 0.1;
i=$((i+1))
if [ $((i%10)) = 0 ]; then
echo -n "."
elif [ $((i)) = 301 ]; then
echo "Waited 30s for the processes to write their pids, something probably went wrong."
exit 1;
fi
done
echo
}
# We use the pids in so many parts of the script it makes sense to always check them.
# Only after start() is run should the pids change. Sidekiq sets it's own pid.
check_pids
## Checks whether the different parts of the service are already running or not.
check_status(){
check_pids
# If the web server is running kill -0 $wpid returns true, or rather 0.
# Checks of *_status should only check for == 0 or != 0, never anything else.
if [ $wpid -ne 0 ]; then
kill -0 "$wpid" 2>/dev/null
web_status="$?"
else
web_status="-1"
fi
if [ $spid -ne 0 ]; then
kill -0 "$spid" 2>/dev/null
sidekiq_status="$?"
else
sidekiq_status="-1"
fi
if [ $web_status = 0 -a $sidekiq_status = 0 ]; then
gitlab_status=0
else
# http://refspecs.linuxbase.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
# code 3 means 'program is not running'
gitlab_status=3
fi
}
## Check for stale pids and remove them if necessary.
check_stale_pids(){
check_status
# If there is a pid it is something else than 0, the service is running if
# *_status is == 0.
if [ "$wpid" != "0" -a "$web_status" != "0" ]; then
echo "Removing stale Unicorn web server pid. This is most likely caused by the web server crashing the last time it ran."
if ! rm "$web_server_pid_path"; then
echo "Unable to remove stale pid, exiting."
exit 1
fi
fi
if [ "$spid" != "0" -a "$sidekiq_status" != "0" ]; then
echo "Removing stale Sidekiq job dispatcher pid. This is most likely caused by Sidekiq crashing the last time it ran."
if ! rm "$sidekiq_pid_path"; then
echo "Unable to remove stale pid, exiting"
exit 1
fi
fi
}
## If no parts of the service is running, bail out.
exit_if_not_running(){
check_stale_pids
if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then
echo "GitLab is not running."
exit
fi
}
## Starts Unicorn and Sidekiq if they're not running.
start_gitlab() {
check_stale_pids
if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then
echo -n "Starting both the GitLab Unicorn and Sidekiq"
elif [ "$web_status" != "0" ]; then
echo -n "Starting GitLab Unicorn"
elif [ "$sidekiq_status" != "0" ]; then
echo -n "Starting GitLab Sidekiq"
fi
# Then check if the service is running. If it is: don't start again.
if [ "$web_status" = "0" ]; then
echo "The Unicorn web server already running with pid $wpid, not restarting."
else
# Remove old socket if it exists
rm -f "$socket_path"/gitlab.socket 2>/dev/null
# Start the web server
RAILS_ENV=$RAILS_ENV bin/web start
fi
# If sidekiq is already running, don't start it again.
if [ "$sidekiq_status" = "0" ]; then
echo "The Sidekiq job dispatcher is already running with pid $spid, not restarting"
else
RAILS_ENV=$RAILS_ENV bin/background_jobs start &
fi
# Wait for the pids to be planted
wait_for_pids
# Finally check the status to tell wether or not GitLab is running
print_status
}
## Asks the Unicorn and the Sidekiq if they would be so kind as to stop, if not kills them.
stop_gitlab() {
exit_if_not_running
if [ "$web_status" = "0" -a "$sidekiq_status" = "0" ]; then
echo -n "Shutting down both Unicorn and Sidekiq"
elif [ "$web_status" = "0" ]; then
echo -n "Shutting down Unicorn"
elif [ "$sidekiq_status" = "0" ]; then
echo -n "Shutting down Sidekiq"
fi
# If the Unicorn web server is running, tell it to stop;
if [ "$web_status" = "0" ]; then
RAILS_ENV=$RAILS_ENV bin/web stop
fi
# And do the same thing for the Sidekiq.
if [ "$sidekiq_status" = "0" ]; then
RAILS_ENV=$RAILS_ENV bin/background_jobs stop
fi
# If something needs to be stopped, lets wait for it to stop. Never use SIGKILL in a script.
while [ "$web_status" = "0" -o "$sidekiq_status" = "0" ]; do
sleep 1
check_status
printf "."
if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then
printf "\n"
break
fi
done
sleep 1
# Cleaning up unused pids
rm "$web_server_pid_path" 2>/dev/null
# rm "$sidekiq_pid_path" # Sidekiq seems to be cleaning up it's own pid.
print_status
}
## Prints the status of GitLab and it's components.
print_status() {
check_status
if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then
echo "GitLab is not running."
return
fi
if [ "$web_status" = "0" ]; then
echo "The GitLab Unicorn web server with pid $wpid is running."
else
printf "The GitLab Unicorn web server is \033[31mnot running\033[0m.\n"
fi
if [ "$sidekiq_status" = "0" ]; then
echo "The GitLab Sidekiq job dispatcher with pid $spid is running."
else
printf "The GitLab Sidekiq job dispatcher is \033[31mnot running\033[0m.\n"
fi
if [ "$web_status" = "0" -a "$sidekiq_status" = "0" ]; then
printf "GitLab and all its components are \033[32mup and running\033[0m.\n"
fi
}
## Tells unicorn to reload it's config and Sidekiq to restart
reload_gitlab(){
exit_if_not_running
if [ "$wpid" = "0" ];then
echo "The GitLab Unicorn Web server is not running thus its configuration can't be reloaded."
exit 1
fi
printf "Reloading GitLab Unicorn configuration... "
RAILS_ENV=$RAILS_ENV bin/web reload
echo "Done."
echo "Restarting GitLab Sidekiq since it isn't capable of reloading its config..."
RAILS_ENV=$RAILS_ENV bin/background_jobs restart
wait_for_pids
print_status
}
## Restarts Sidekiq and Unicorn.
restart_gitlab(){
check_status
if [ "$web_status" = "0" -o "$sidekiq_status" = "0" ]; then
stop_gitlab
fi
start_gitlab
}
### Finally the input handling.
case "$1" in
start)
start_gitlab
;;
stop)
stop_gitlab
;;
restart)
restart_gitlab
;;
reload|force-reload)
reload_gitlab
;;
status)
print_status
exit $gitlab_status
;;
*)
echo "Usage: service gitlab {start|stop|restart|reload|status}"
exit 1
;;
esac
exit

View File

@@ -0,0 +1,415 @@
Installing GitLab on FreeBSD 10
===============================
##### Preface
This is essentially a record of how I installed and configured GitLab 7.6 on my FreeBSD server. Mileage with this guide may vary of course; different configurations of FreeBSD on different hardware and with different packages may introduce other unexpected issues. To make full use of this guide, I suggest reading the [official GitLab installation guide](https://github.com/gitlabhq/gitlabhq/blob/7-6-stable/doc/install/installation.md) fully before attempting anything in here.
1. Update system and Enable UTF-8
---------------------------------
Follow [this guide](https://www.b1c1l1.com/blog/2011/05/09/using-utf-8-unicode-on-freebsd/)
to enable UTF-8 on your system. This will allow you to create the GitLab
database later on.
Update your system:
```
pkg update
pkg upgrade
```
2. Install dependencies
-----------------------
Install system packages:
```
pkg install sudo bash icu cmake pkgconf git nginx ruby ruby20-gems logrotate redis postgresql94-server postfix krb5
```
Install bundler gem system-wide:
```
gem install bundler --no-ri --no-rdoc
```
Add this to `/etc/rc.conf`:
```
# Core services
sshd_enable="YES"
ntpd_enable="YES"
ntpd_sync_on_start="YES"
# GitLab services
redis_enable="YES"
postgresql_enable="YES"
gitlab_enable="YES"
# Web server
nginx_enable="YES"
# Postfix/Sendmail
postfix_enable="YES"
sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"
```
3. Create `git` user for GitLab
-------------------------------
Set up user and groups:
```
# Create user
pw add user -n git -m -s /usr/local/bin/bash -c "GitLab"
# Add 'git' user to 'redis' group (this will come in useful later!)
pw user mod git -G redis
```
4. Set up Postgres database
---------------------------
As root, make sure that Postgres is running:
`service postgresql start`
Check this with `service postgresql status`
Set up the database:
```
# Log in to Postgres user account
su - pgsql
# Initialise Postgres db
initdb /usr/local/pgsql/data
# Connect to Postgres database
psql -d template1
```
When logged into the database:
```
# Create a user for GitLab
# Do not type the 'template1=#', this is part of the prompt
template1=# CREATE USER git CREATEDB;
# Create the GitLab production database & grant all privileges on database
template1=# CREATE DATABASE gitlabhq_production OWNER git encoding='UTF8';
# Quit the database session
template1=# \q
```
Then type `exit` to drop back to the `root` user.
Try connecting to the new database with the `git` user:
```
su - git
psql -d gitlabhq_production
```
If this succeeds, quit the database session by typing `\q` or hitting CTRL-D.
5. Install and set up Redis
---------------------------
Back up the original Redis config file:
`cp /usr/local/etc/redis.conf /usr/local/etc/redis.conf.orig`
Run the following commands to get Redis working:
```
# Disable Redis listening on TCP by setting 'port' to 0
sed 's/^port .*/port 0/' /usr/local/etc/redis.conf.orig | sudo tee /usr/local/etc/redis.conf
# Enable Redis socket
echo 'unixsocket /usr/local/var/run/redis/redis.sock' | sudo tee -a /usr/local/etc/redis.conf
# Grant permission to the socket to all members of the redis group
echo 'unixsocketperm 770' | sudo tee -a /usr/local/etc/redis.conf
# Create the directory which contains the socket
mkdir -p /usr/local/var/run/redis
chown redis:redis /usr/local/var/run/redis
chmod 755 /usr/local/var/run/redis
# Restart redis
sudo service redis restart
```
6. Install and set up GitLab
----------------------------
```
# Change to git home directory
cd /home/git
# Clone GitLab source
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 7-6-stable gitlab
# Go to GitLab source folder
cd /home/git/gitlab
# Copy the example GitLab config
sudo -u git -H cp config/gitlab.yml.example config/gitlab.yml
```
Edit the GitLab configuration file
(`sudo -u git -H vim config/gitlab.yml`)
* The option `host:` should be set to your domain, e.g. "gitlab.mysite.com".
* The line `bin_path:` should be set to FreeBSD's `git` location: `/usr/local/bin/git`.
As root:
```
cd /home/git/gitlab
chown -R git log/
chown -R git tmp/
chmod -R u+rwX,go-w log/
chmod -R u+rwX tmp/
# Change back to 'git' user
su - git
cd /home/git/gitlab
# Make folder for satellites and set the right permissions
mkdir /home/git/gitlab-satellites
chmod u+rwx,g=rx,o-rwx /home/git/gitlab-satellites
# Make sure GitLab can write to the tmp/pids/ and tmp/sockets/ directories
chmod -R u+rwX tmp/pids/
chmod -R u+rwX tmp/sockets/
# Make sure GitLab can write to the public/uploads/ directory
chmod -R u+rwX public/uploads
# Copy the example Unicorn config
cp config/unicorn.rb.example config/unicorn.rb
# Set the number of workers to at least the number of cores
vim config/unicorn.rb
# Copy the example Rack attack config
cp config/initializers/rack_attack.rb.example config/initializers/rack_attack.rb
# Configure Git global settings for git user, useful when editing via web
# Edit user.email according to what is set in gitlab.yml
git config --global user.name "GitLab"
git config --global user.email "example@example.com"
git config --global core.autocrlf input
# Copy Redis connection settings
cp config/resque.yml.example config/resque.yml
# Configure Redis to use the modified socket path
# Change 'production' line to 'unix:/usr/local/var/run/redis/redis.sock'
vim config/resque.yml
# Copy database config
cp config/database.yml.postgresql config/database.yml
# Install Ruby Gems
bundle install --deployment --without development test mysql aws
```
7. GitLab Shell
---------------
```
# Run the rake task for installing gitlab-shell
bundle exec rake gitlab:shell:install[v2.4.0] REDIS_URL=unix:/usr/local/var/run/redis/redis.sock RAILS_ENV=production
# Edit the gitlab-shell config
# Change the 'socket' option to '/usr/local/var/run/redis/redis.sock'
# Change the 'gitlab_url' option to 'http://localhost:8080/'
# Don't bother configuring any SSL stuff in here because it's used internally
vim /home/git/gitlab-shell/config.yml
```
8. Initialise Database
----------------------
Initialize Database and Activate Advanced Features
```
sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production
# Type 'yes' to create the database tables.
# When done you see 'Administrator account created:'
```
**Note**: You can set the Administrator/root password by supplying it in the
environmental variable GITLAB_ROOT_PASSWORD as seen below. If you don't set the
password (and it is set to the default one) please wait with exposing GitLab to
the public internet until the installation is done and you've logged into the
server the first time. During the first login you'll be forced to change the
default password.
```
sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production GITLAB_ROOT_PASSWORD=yourpassword
```
9. Init script
--------------
There is a [FreeBSD init script](../../init/init/gitlab) in this repository,
under the `init/init` directory.
```
cp /path/to/this/repository/init/init/gitlab /usr/local/etc/rc.d/gitlab
```
10. Check Configuration and Compile Assets
------------------------------------------
```
cd /home/git/gitlab
su - git
bundle exec rake gitlab:env:info RAILS_ENV=production
```
If this all passes (all green and/or no errors are reported), then go ahead and
compile all of the assets for GitLab. This can take ~10-15 minutes on a
smaller machine, so don't panic if it takes a while!
```
bundle exec rake assets:precompile RAILS_ENV=production
```
11. Start GitLab service
------------------------
If all of the above steps complete with no errors and everything has gone
smoothly, then start the GitLab service.
As root:
```
service gitlab start
```
12. Nginx
---------
The officially supported web server in GitLab is `nginx` - and GitLab provide
an `nginx` configuration file in `/home/git/gitlab/lib/support/nginx/gitlab`,
so you can copy that if you prefer, and modify their template.
The default version of `nginx` on FreeBSD is compiled without the `gzip_static`
module, which means you need to remove the appropriate directives from the
`nginx` configuration.
This is the configuration I used:
```
server {
server_name yourserver.yourdomain;
server_tokens off;
listen 80 accept_filter=httpready;
# Uncomment if you want to use SSL
# listen 443 ssl;
# Configure your SSL certificate locations here
# ssl_certificate /usr/local/etc/nginx/ssl/gitlab/ssl-bundle.crt;
# ssl_certificate_key /usr/local/etc/nginx/ssl/gitlab/gitlab.key;
# Uncomment to force SSL connections
# if ($ssl_protocol = "") {
# rewrite ^ https://$server_name$request_uri? permanent;
# }
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:8080;
}
}
```
Restart `nginx` with `sudo service nginx restart`, and you should be up and
running.
Check everything with this command just to be sure:
```
su - git
cd /home/git/gitlab
bundle exec rake gitlab:check RAILS_ENV=production
```
Good to Go
----------
If everything comes up green, then GitLab should work.
If some things show up as red, blue, pink or any colour that's not green - read any error messages thoroughly before trying any suggested fixes. Google comes in extremely handy when trying to diagnose unhelpful Ruby error messages.
Troubleshooting
===============
`504 - Gateway Timed Out` errors
--------------------------------
This can be caused by several different things with GitLab. The best bet is to
go back up through the install guide and check each step has been properly
executed.
* Check the logs! Look in `/home/git/gitlab/log` for clues.
* Check what's running! The command `sockstat -4l` usually gives an idea of
which services are running on which ports. (Redis uses port `6379`,
Unicorn uses port `8080`, and Postgres uses port `5432`).
What it usually boils down to:
1. GitLab's assets haven't been precompiled (there is a command above)
2. Postgres isn't running or the database isn't set up properly
3. Redis isn't running
4. Nginx isn't set up properly
Gem `timfel-krb5-auth` fails to build
-------------------------------------
Install the Kerberos package: `pkg install krb5`. As far as I know, there's no
way to disable the Kerberos authentication in GitLab (even if it's unused) so
unfortunately the only solution is to install the missing packages.
Postfix/sendmail: "postdrop: warning: unable to look up public/pickup: No such file or directory"
-------------------------------------------------------------------------------------------------
Sometimes Postfix and/or sendmail might complain if they're not set up
correctly or have only just been installed.
```
mkfifo /var/spool/postfix/public/pickup
killall $(pgrep sendmail) # Kill all sendmail processes
sudo service postfix restart # Restart Postfix
```
[(Source)](http://www.databasically.com/2009/12/02/ubuntu-postfix-error-postdrop-warning-unable-to-look-up-publicpickup-no-such-file-or-directory/)
Unicorn / nginx: "Failed to set accept\_filter=httpready"
---------------------------------------------------------
This is to do with an HTTP buffering kernel module in FreeBSD that some HTTP
servers expect to be loaded. Run this:
```
kldload accf_http
echo 'accf_http_load="YES"' >> /boot/loader.conf
sudo service gitlab restart
sudo service redis restart
sudo service nginx restart
```
[(Source)](http://www.cyberciti.biz/faq/failed-to-enable-the-httpready-accept-filter/)
References
==========
* [GitLab official installation guide](https://github.com/gitlabhq/gitlabhq/blob/7-6-stable/doc/install/installation.md)
* [Luiz Gustavo's GitLab/FreeBSD guide (Portuguese)](http://www.luizgustavo.pro.br/blog/2014/08/21/instalacao-gitlab-no-freebsd/)