
The simplest way to install GitLab
GitLab provides official instructions to install it using Docker and Docker Compose. You can find it in the official documentation
gitlab/docker-compose.yaml
services:
gitlab:
image: gitlab/gitlab-ee:<version>-ce.0
container_name: gitlab
restart: always
hostname: '<gitlab.example.com>'
environment:
GITLAB_OMNIBUS_CONFIG: |
# Add any other gitlab.rb configuration here, each on its own line
external_url 'https://<gitlab.example.com>'
ports:
- '80:80'
- '443:443'
- '22:22'
volumes:
- '$GITLAB_HOME/config:/etc/gitlab'
- '$GITLAB_HOME/logs:/var/log/gitlab'
- '$GITLAB_HOME/data:/var/opt/gitlab'
shm_size: '256m'
This assumes you have your server dedicated to GitLab and all required ports (http, https, ssh) are free. GitLab will take care of everything, including TLS configuration with Lets Encrypt
Integrating GitLab alongside other deployments
What if you can't or don't want to install GitLab on a dedicated server?
Maybe you just want a single server for all you services?
This is an example structure how you could organize your deployments:
.
├── gitlab/ # GitLab service stack
├── gitlab-runner/ # GitLab Runner for CI/CD
├── mattermost/ # Mattermost team collaboration
├── nextcloud/ # Nextcloud file hosting and collaboration
└── traefik/ # Traefik reverse proxy configuration
Using a dedicated IP
In case you have a possibility to attach an additional IP to your server (like a Floating IP on Hetzner), you can simply bind the ports to this IP.
gitlab/docker-compose.yaml
services:
gitlab:
image: gitlab/gitlab-ee:<version>-ce.0
container_name: gitlab
restart: always
hostname: '<gitlab.example.com>'
environment:
GITLAB_OMNIBUS_CONFIG: |
# Add any other gitlab.rb configuration here, each on its own line
external_url 'https://<gitlab.example.com>'
ports:
- '192.168.0.1:80:80'
- '192.168.0.1:443:443'
- '192.168.0.1:22:22'
volumes:
- '$GITLAB_HOME/config:/etc/gitlab'
- '$GITLAB_HOME/logs:/var/log/gitlab'
- '$GITLAB_HOME/data:/var/opt/gitlab'
shm_size: '256m'
Using Traefik as a reverse proxy
In this case I assume that you:
- can't or don't want to assign a dedicated IP for GitLab
- can't or don't want to change you default ssh port
- want to use Traefik as a reverse proxy
The Traefik deployment
Remember to replace <[email protected]>
with your own email.
traefik/docker-compose.yaml
volumes:
letsencrypt:
services:
traefik:
image: traefik:3
container_name: traefik
restart: always
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- letsencrypt:/letsencrypt
command:
- --log.level=INFO
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --entrypoints.websecure.address=:443
- --entrypoints.websecure.http.tls.certresolver=letsencrypt
- --providers.docker=true
- --providers.docker.exposedByDefault=false
- --certificatesresolvers.letsencrypt.acme.email=<[email protected]>
- --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
- --certificatesresolvers.letsencrypt.acme.httpchallenge=true
- --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
This setup will:
- enable the docker provider
- disable the container discovery
- redirect all HTTP traffic to HTTPS
- configure Let's Encrypt with
HTTP-01
challenge - apply the TLS configuration to all routes
- start the Traefik container bound directly to host's network, so no addition configuration is required for traefik
The GitLab deployment
Remember to replace <gitlab.example.com>
with your own domain.
Please take a look in the official dokumentation about GITLAB_HOME
directory
gitlab/docker-compose.yaml
services:
gitlab:
image: gitlab/gitlab-ce:<version>-ce.0
container_name: gitlab
labels:
- "traefik.enable=true"
- "traefik.http.routers.gitlab.rule=Host(`<gitlab.example.com>`)"
- "traefik.http.routers.gitlab.service=gitlab"
- "traefik.http.services.gitlab.loadbalancer.server.port=80"
restart: always
hostname: 'gitlab.example.com'
environment:
GITLAB_OMNIBUS_CONFIG: |
# Add any other gitlab.rb configuration here, each on its own line
external_url '<https://gitlab.example.com>'
letsencrypt['enable'] = false
nginx['listen_port'] = 80
nginx['listen_https'] = false
nginx['proxy_set_headers'] = {
"X-Forwarded-Proto" => "https",
"X-Forwarded-Ssl" => "on"
}
gitlab_rails['gitlab_shell_ssh_port'] = 2424
ports:
- '2424:22'
volumes:
- '$GITLAB_HOME/config:/etc/gitlab'
- '$GITLAB_HOME/logs:/var/log/gitlab'
- '$GITLAB_HOME/data:/var/opt/gitlab'
shm_size: '256m'
This setup will:
- disable the Let's Encrypt
- disable listening on https and listen on port 80
- set the required proxy headers
- change the ssh port to 2424
- instruct Traefik to route all traffic for
gitlab.example.com
to port 80 of the container
That's it!
GitLab Container registry
When you got so far, you probably also want to set up the container registry
Configure container registry under its own domain
This setup is easy. We just need to set the registry_external_url
and instruct Traefik where to route the requests
Update the GitLab config
gitlab/docker-compose.yaml
services:
gitlab:
image: gitlab/gitlab-ce:<version>-ce.0
container_name: gitlab
labels:
- "traefik.enable=true"
- "traefik.http.routers.gitlab.rule=Host(`<gitlab.example.com>`)"
- "traefik.http.routers.gitlab.service=gitlab"
- "traefik.http.services.gitlab.loadbalancer.server.port=80"
- "traefik.http.routers.container-registry.rule=Host(`registry.gitlab.example.com`)"
- "traefik.http.services.container-registry.loadbalancer.server.port=5000"
restart: always
hostname: 'gitlab.example.com'
environment:
GITLAB_OMNIBUS_CONFIG: |
# Add any other gitlab.rb configuration here, each on its own line
external_url '<https://gitlab.example.com>'
letsencrypt['enable'] = false
nginx['listen_port'] = 80
nginx['listen_https'] = false
nginx['proxy_set_headers'] = {
"X-Forwarded-Proto" => "https",
"X-Forwarded-Ssl" => "on"
}
gitlab_rails['gitlab_shell_ssh_port'] = 2424
registry_external_url '<https://registry.gitlab.example.com>'
registry_nginx['enable'] = false
ports:
- '2424:22'
volumes:
- '$GITLAB_HOME/config:/etc/gitlab'
- '$GITLAB_HOME/logs:/var/log/gitlab'
- '$GITLAB_HOME/data:/var/opt/gitlab'
shm_size: '256m'
This setup will:
- set the registry external url
- disable the nginx for the registry
- instruct Traefik to route all traffic for
registry.gitlab.example.com
to port 5000 of the container
Configure container registry under an existing GitLab domain
Update the Traefik config
traefik/docker-compose.yaml
volumes:
letsencrypt:
services:
traefik:
image: traefik:3
container_name: traefik
restart: always
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- letsencrypt:/letsencrypt
command:
- --log.level=INFO
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --entrypoints.websecure.address=:443
- --entrypoints.websecure.http.tls.certresolver=letsencrypt
- --entrypoints.container-registry.address=:5050
- --entrypoints.container-registry.http.tls.certresolver=letsencrypt
- --providers.docker=true
- --providers.docker.exposedByDefault=false
- --certificatesresolvers.letsencrypt.acme.email=<[email protected]>
- --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
- --certificatesresolvers.letsencrypt.acme.httpchallenge=true
- --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
This setup will:
- add a new entry point for the container registry
- apply the TLS configuration to all routes in this entrypoint
Update the GitLab config
gitlab/docker-compose.yaml
services:
gitlab:
image: gitlab/gitlab-ce:<version>-ce.0
container_name: gitlab
labels:
- "traefik.enable=true"
- "traefik.http.routers.gitlab.rule=Host(`<gitlab.example.com>`)"
- "traefik.http.routers.gitlab.entrypoints=web,websecure"
- "traefik.http.routers.gitlab.service=gitlab"
- "traefik.http.services.gitlab.loadbalancer.server.port=80"
- "traefik.http.routers.container-registry.rule=Host(`gitlab.example.com`)"
- "traefik.http.routers.container-registry.entrypoints=container-registry"
- "traefik.http.routers.container-registry.service=container-registry"
- "traefik.http.services.container-registry.loadbalancer.server.port=5000"
restart: always
hostname: 'gitlab.example.com'
environment:
GITLAB_OMNIBUS_CONFIG: |
# Add any other gitlab.rb configuration here, each on its own line
external_url '<https://gitlab.example.com>'
letsencrypt['enable'] = false
nginx['listen_port'] = 80
nginx['listen_https'] = false
nginx['proxy_set_headers'] = {
"X-Forwarded-Proto" => "https",
"X-Forwarded-Ssl" => "on"
}
gitlab_rails['gitlab_shell_ssh_port'] = 2424
registry_external_url '<https://gitlab.example.com:5050>'
registry_nginx['enable'] = false
ports:
- '2424:22'
volumes:
- '$GITLAB_HOME/config:/etc/gitlab'
- '$GITLAB_HOME/logs:/var/log/gitlab'
- '$GITLAB_HOME/data:/var/opt/gitlab'
shm_size: '256m'
This setup will:
- set the registry external url
- disable the nginx for the registry
- instruct Traefik to route all traffic from port 5050 to port 5000 of the container