Run self-hosted GitLab on your home server

21-07-2024

So you want to run your own Gitlab server? I'll share my experience with you. Since I've got a home server for things like Pi-Hole and Home Assistant (both running in Docker), there was space left to run Gitlab. Yes, I could use Github, Bitbucket or Gitlab.com, but I'd like to have everything on one place. And thank to self hosted Gitlab it's possible!

Requirements:

This page at Gitlab is your starting point. The page tells you everything you need to know to install Gitlab using Docker. These are the steps I used:

  1. First you need to set up DNS. You will need to point traffic from gitlab.example.com to your home server. A DNS (A) record needs to point home.gitlab.com to the IP address of your home internet connection. Because the IP address of your home connection may change, you might want to use a script to update the DNS record when it changes. Also make sure only traffic from git.example.com is allowed on this port if that's possible on your router.
    So basically https://gitlab.example.com forwards traffic to http://home.example.com:8000.
  2. To access Gitlab from a secure reverse proxy, add the following Nginx configuration (assuming you know how to set up a web server with Nginx):
    # redirect from http to https
    server {
        listen 80;
        listen [::]:80;
    
        server_name gitlab.example.com;
    
        location /.well-known {
            root /var/www/certbot;
        }
    
        location / {
            return 301 https://$host$request_uri;
        }
    }
    
    server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
    
        server_name gitlab.example.com;
    
        access_log /var/log/nginx/gitlab.example.com-access.log main;
        error_log /var/log/nginx/gitlab.example.com-error.log error;
    
        ssl_certificate /etc/letsencrypt/live/gitlab.example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/gitlab.example.com/privkey.pem;
    
        # allow large file uploads
        client_max_body_size 50000M;
    
        # Set headers
        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;
    
        # enable websockets: http://nginx.org/en/docs/http/websocket.html
        proxy_http_version 1.1;
        proxy_set_header   Upgrade    $http_upgrade;
        proxy_set_header   Connection "upgrade";
        proxy_redirect     off;
    
        # set timeout
        proxy_read_timeout 600s;
        proxy_send_timeout 600s;
        send_timeout       600s;
    
        location / {
            proxy_pass http://home.example.com:8000;
        }
    }
    The configuration is a combination for different kind of Docker containers (every Docker container uses it own sub domain). You can always change it to your needs.
  3. First create the main directory: /srv/gitlab (you may use a different directory). After that, create the other directories:
    • config
    • data
    • logs
  4. Create a /srv/gitlab/docker-compose.yml file with the following content:
    services:
      gitlab:
        image: gitlab/gitlab-ce:17.1.2-ce.0
        container_name: gitlab
        restart: always
        hostname: 'ip.of.home.server'
        environment:
          GITLAB_OMNIBUS_CONFIG: |
            # Add any other gitlab.rb configuration here, each on its own line
            external_url 'https://gitlab.example.com'
            nginx['listen_port'] = 80
            nginx['listen_https'] = false
            gitlab_rails['smtp_enable'] = true
            gitlab_rails['smtp_address'] = "your.smtp.server"
            gitlab_rails['smtp_port'] = 25/587
            gitlab_rails['smtp_user_name'] = "xxxxxxx"
            gitlab_rails['smtp_password'] = "xxxxxxx"
            gitlab_rails['smtp_domain'] = "example.com"
            gitlab_rails['smtp_authentication'] = "login"
            gitlab_rails['smtp_enable_starttls_auto'] = true
            gitlab_rails['smtp_tls'] = false
            gitlab_rails['smtp_openssl_verify_mode'] = 'peer'
            gitlab_rails['gitlab_email_from'] = '[email protected]'
            gitlab_rails['gitlab_email_display_name'] = 'gitlab.example.com'
            gitlab_rails['gitlab_email_reply_to'] = '[email protected]'
        ports:
          - '8000:80'
          - '8443:443'
          - '2222:22'
        volumes:
          - '/srv/gitlab/config:/etc/gitlab'
          - '/srv/gitlab/logs:/var/log/gitlab'
          - '/srv/gitlab/data:/var/opt/gitlab'
        shm_size: '256m'
    To find the latest tag, visit hub.docker.com.
    As you can see, the line external_url 'https://gitlab.example.com' is important to fill out. Next to that, the nginx configuration is important too. By setting it to port 80 and disabling https it's not going to create a Let's Encrypt certificate.
    I'm not going into the smtp configuration. You may have a look at the gitlab.com documentation.
  5. Start Gitlab! Run docker compose up -d and give it some time to install. Once it's running, you'll may login using the root account. When you're logged in, the first thing you want to do is to disable sign up.
  6. Nice! You should have Gitlab running now. The next step is to install the Gitlab Runner. Check gitlab.com for the documentation. This is very easy using Docker:
    docker run -d --name gitlab-runner --restart always \
      -v /srv/gitlab-runner/config:/etc/gitlab-runner \
      -v /var/run/docker.sock:/var/run/docker.sock \
      gitlab/gitlab-runner:latest
    Next up is to register a new instance runner. Go to Admin Area => CI/CD => Runners => Add new runner. Fill out the form by naming it (tag) and don't forget to enable "Run untagged jobs". You'll see a token which is necessary for the following step.
    Run docker exec -it gitlab-runner gitlab-runner register on your Docker server and follow the instructions. You should have a runner registered now! You may want to check the documentation.

At this point you should have a Gitlab server running on your home server with an Nginx proxy server. Enjoy :)