Self-hosting GitLab
- 7 minute de citit
- 18 exemple de cod în Shell și Ruby
- 2 imagini
Disponibil și în English
Pe această pagină
Salut tuturor și un an nou fericit!
Introducere
Rulez GitLab ca forjă de software de trei săptămâni și totul a mers bine. Am înlocuit instanța mea Forgejo cu el pentru că are o interfață (UI) și o experiență de utilizare (UX) mai bune. GitLab consumă mai multe resurse decât Forgejo, iar VPS-ul meu de 5$/lună a ajuns să coste 17$/lună ca să-l găzduiesc și să-l folosesc fără lag.
Ei bine, 204$ pe an mi se par cam mult doar pentru a găzdui o forjă de software, așa că am decis să cumpăr un MiniPC la aproximativ același preț și să-l găzduiesc eu acasă. Cu ajutorul Cloudflare îl pot expune în siguranță pe internet folosind tuneluri.
Ideea din spatele tunelurilor este că rulezi un agent Cloudflare pe PC și nu trebuie să deschizi porturi către exterior. Tot traficul este primit direct prin tunel, iar pentru că îmi găzduiesc DNS-ul la Cloudflare, soluția funcționează bine.
Factura mea la curent este și ea mică, mult mai mică decât VPS-ul meu inițial de 5$/lună. Am un smart plug care urmărește consumul de energie, iar pe un singur cablu de alimentare am conectat: MiniPC-ul cu GitLab, un PC de jocuri vechi pe care îl folosesc ca runner GitLab, un switch de rețea și altele. În total consum în medie aproximativ 1kW pe zi.

Acest articol se concentrează pe cum să găzduiești GitLab și pe câteva operații de bază de întreținere.
GitLab
GitLab este o platformă asemănătoare cu GitHub, pe care o numesc forjă de software; termenul este preluat de la Forgejo. Pe lângă administrarea repository-urilor Git, GitLab vine cu mai multe funcționalități, precum:
- registry pentru containere
- GitLab Pages (găzduire de site-uri statice)
- Mattermost (o aplicație de chat, similară cu Slack)
- și multe altele…
Pachet Linux
Poți găzdui GitLab în mai multe moduri, de exemplu cu Kubernetes sau cu containere Docker. Eu prefer metoda cu pachetul Linux. Distribuția mea preferată este AlmaLinux.
Instalare
Nu voi intra în detalii aici, pentru că GitLab are o documentație excelentă, iar s-ar putea să folosești o altă distribuție:
Ține cont că GitLab are o versiune gratuită și una plătită. Trebuie să instalezi versiunea Community Edition.
După ce GitLab este instalat, notează parola contului root, aflată în /etc/gitlab/initial_root_password.
Poți verifica dacă totul rulează executând gitlab-ctl status.
Actualizări automate
Am actualizări automate activate pe sistem. Pe AlmaLinux le poți activa cu:
sudo dnf install dnf-automaticsudo systemctl enable --now dnf-automatic.timerConfigurare
Am câteva configurări personale pentru instanța GitLab. Fișierul de configurare pe care îl dau mai jos face următoarele:
- Dezactivez metricile, pentru că nu monitorizez utilizarea resurselor serverului GitLab.
- Nu folosesc certificate SSL și Let’s Encrypt, pentru că vreau ca Cloudflare să ofere SSL în locul meu.
- Nginx ascultă doar pe portul 80.
- Folosesc Nginx inclus în GitLab. Asta înseamnă că nu instalez pachetul nginx pe sistem.
- Am personalizat nginx ca să servească blogul meu static.
- Folosesc serviciul de email tranzacțional al Scaleway pentru trimiterea emailurilor.
- Folosesc GitLab Pages și registry-ul pentru containere.
# ➜ ~ head -n100 /etc/gitlab/gitlab.rbexternal_url 'https://gitlab.nuculabs.dev'registry_external_url 'https://registry.nuculabs.dev'letsencrypt['enable'] = falsegitlab_rails['time_zone'] = 'Europe/Bucharest'nginx['client_max_body_size'] = '2g'nginx['custom_nginx_config'] = "include /etc/gitlab/nginx/sites-enabled/*.conf;"nginx['listen_https'] = falsenginx['listen_port'] = 80 nginx['redirect_http_to_https'] = falseregistry_nginx['listen_https'] = falseregistry_nginx['listen_port'] = 80registry_nginx['redirect_http_to_https'] = falsegitlab_rails['gitlab_ssh_host'] = 'git.nuculabs.dev'# GitLab Mattermost# mattermost_external_url 'https://mattermost.nuculabs.dev'mattermost['enable'] = false# mattermost_nginx['redirect_http_to_https'] = false# mattermost_nginx['listen_port'] = 80# mattermost_nginx['listen_https'] = false# GitLab Pagespages_external_url 'https://pages.nuculabs.dev'pages_nginx['listen_https'] = falsepages_nginx['listen_port'] = 80gitlab_pages['namespace_in_path'] = true# Dezactivează Prometheus și exporterii săiprometheus['enable'] = falseprometheus_monitoring['enable'] = falsesidekiq['metrics_enabled'] = falsealertmanager['enable'] = falsenode_exporter['enable'] = falseredis_exporter['enable'] = falsepostgres_exporter['enable'] = falsegitlab_exporter['enable'] = falsepuma['exporter_enabled'] = falsegitlab_kas['enable'] = false# Configurare emailgitlab_rails['smtp_enable'] = truegitlab_rails['smtp_address'] = "smtp.tem.scaleway.com"gitlab_rails['smtp_port'] = 587gitlab_rails['smtp_user_name'] = "xxx"gitlab_rails['smtp_password'] = "xxx"gitlab_rails['gitlab_email_from'] = '[email protected]'gitlab_rails['gitlab_email_reply_to'] = '[email protected]'gitlab_rails['smtp_domain'] = "xx"gitlab_rails['smtp_authentication'] = "plain"gitlab_rails['smtp_enable_starttls_auto'] = truePoți adapta fișierul meu gitlab.rb și să-l suprascrii pe al tău, în /etc/gitlab/gitlab.rb.
După ce ai modificat gitlab.rb, trebuie să îi spui GitLab să se reconfigureze rulând:
sudo gitlab-ctl reconfigure.
De asemenea, nu uita să creezi directorul pentru configurarea personalizată a nginx.
mkdir -p /etc/gitlab/nginx/sites-enabled/Backup-uri
Fac backup instanței zilnic. Poți face backup următoarelor directoare:
- /etc/gitlab
- /var/opt/gitlab/backups
- /etc/gitlab/nginx/sites-enabled/
Pentru backup-uri folosesc un script cu un timer systemd și rclone. Rclone este un instrument foarte flexibil și configurabil, care poate fi configurat cu foarte multe servicii. Eu îl folosesc mai ales cu WebDAV, SMB și Google Drive.
Poți folosi scriptul meu de backup, care se află în /root/backup.sh.
Notă: pentru ca scriptul să funcționeze, trebuie să configurezi rclone și să înlocuiești nas:/home/gitlab/gitlab cu calea ta specifică.
Poți configura rclone interactiv tastând rclone config.
#!/bin/bashgitlab-backup createrclone sync /etc/gitlab nas:/home/gitlab/gitlab --progress --log-file=rclone-nas.logrclone sync /var/opt/gitlab/backups nas:/home/gitlab/gitlab-backups --progress --log-file=rclone-nas.logrclone sync /etc/gitlab/nginx/sites-enabled/ nas:/home/gitlab/gitlab-nginx --progress --log-file=rclone-nas.logls -t /var/opt/gitlab/backups | tail -n +4 | xargs -I {} rm -f /var/opt/gitlab/backups/{}Apoi, fișierele serviciilor systemd trebuie puse în directorul /etc/systemd/system.
# gitlab-backup.timer[Unit]Description=Gitlab Backup Timer[Timer]# Definește când trebuie activat serviciul# OnCalendar= specifică un eveniment de calendar.# 'daily' este un alias pentru '*-*-* 00:00:00'. Noi folosim 02:00:00 (ora 2 dimineața).OnCalendar=daily# SAU: OnCalendar=*-*-* 02:00:00# Definește o întârziere aleatorie după ora specificată, pentru a evita# vârfuri simultane de resurse dacă ai mai multe timere.# Vom folosi o fereastră de 30 de minute.RandomizedDelaySec=30m# Asigură că timerul se execută scurt după pornirea sistemului# dacă a ratat o rulare programată cât timp sistemul a fost oprit.Persistent=true[Install]WantedBy=timers.target# gitlab-backup.service[Unit]Description=Gitlab backup serviceRequiresMountsFor=/root[Service]User=rootGroup=root# Tipul procesului. 'oneshot' este pentru un script care rulează o singură dată și se oprește.Type=oneshot# Comanda de executat (calea completă către scriptul tău)ExecStart=/bin/bash /root/backup.shDacă ai creat fișierele în directorul curent, rulează următoarele comenzi ca să le copiezi în directorul corect și să activezi timerul.
cp gitlab-backup.* /etc/systemd/system/sudo systemctl daemon-reloadsudo systemctl enable gitlab-backup.timersudo systemctl start gitlab-backup.timerRestaurarea din backup
Ca să restaurezi dintr-un backup, trebuie să te asiguri că versiunea pachetului gitlab-ce se potrivește cu versiunea folosită la crearea backup-ului, altfel nu va funcționa.
În esență, configurez rclone și fac un sync din destinația backup-ului către sistemul local:
rclone sync nas:/home/gitlab/gitlab /etc/gitlab --progress --log-file=rclone-nas.logrclone sync nas:/home/gitlab/gitlab-backups /var/opt/gitlab/backups --progress --log-file=rclone-nas.logrclone sync nas:/home/gitlab/gitlab-nginx /etc/gitlab/nginx/sites-enabled/ --progress --log-file=rclone-nas.logApoi opresc serviciile GitLab:
gitlab-ctl stop pumagitlab-ctl stop sidekiqȘi apoi restaurez backup-ul. Trebuie să omiți _gitlab_backup.tar din variabila de mediu BACKUP.
➜ ~ ls /var/opt/gitlab/backups 1767219541_2026_01_01_18.7.0_gitlab_backup.tar 1767304984_2026_01_02_18.7.0_gitlab_backup.tar 1767391444_2026_01_03_18.7.0_gitlab_backup.targitlab-backup restore BACKUP=1767219541_2026_01_01_18.7.0În câteva minute ar trebui să ai o instanță GitLab restaurată și funcțională. După ce comanda de restaurare se termină, trebuie să pornești din nou serviciile:
gitlab-ctl start pumagitlab-ctl start sidekiqNginx
Pentru a-mi găzdui blogul folosesc nginx-ul inclus în GitLab. Dacă folosești fișierul meu gitlab.rb, poți crea directorul personalizat pentru nginx, dacă nu există, și poți pune acolo fișierele de configurare.
mkdir -p /etc/gitlab/nginx/sites-enabled/Iată conținutul fișierului blog.conf, care găzduiește blogul meu:
# cat /etc/gitlab/nginx/sites-enabled/blog.confserver { server_name nuculabs.dev; listen 80; root /blog; index index.html; # Hugo generează HTML location / { try_files $uri $uri/ =404; }}server { server_name www.nuculabs.dev blog.nuculabs.dev; listen 80; return 301 https://nuculabs.dev$request_uri;}După cum vezi, ascult doar pe portul 80. SSL este gestionat de Cloudflare, așa că nu trebuie să pierd timp cu administrarea certificatelor sau cu depanarea Let’s Encrypt.
Iată un alt exemplu, pentru un simplu redirect:
server { server_name forge.nuculabs.dev; listen 80; return 301 https://gitlab.nuculabs.dev$request_uri;}Poți face hup nginx ca să preia fișierele noi: gitlab-ctl hup nginx.
Depanarea SSH
Dacă totul este configurat corect, nu ar trebui să ai probleme la clonarea și publicarea repository-urilor prin SSH.
Uneori contextul de securitate (security context) al directorului se strică, iar atunci poate fi nevoie să-l restaurezi rulând:
sudo semanage fcontext -a -t ssh_home_t "/var/opt/gitlab/.ssh(/.*)?"sudo restorecon -Rv /var/opt/gitlab/.sshȚine cont că Cloudflare funcționează doar prin HTTP/HTTPS, iar SSH nu este suportat. Vei putea accesa GitLab prin SSH dacă îl găzduiești în rețeaua locală sau dacă configurezi un VPN.
Cloudflared
Ca să creezi un Cloudflare Tunnel trebuie să instalăm cloudflared.
În dashboard-ul Cloudflare, navighează la Zero Trust -> Networks -> Manage Tunnels -> Add a tunnel.
Poți da un nume tunelului și vei primi instrucțiunile de instalare pentru sistemul tău de operare. Pentru AlmaLinux, am primit:
# Adaugă cloudflared.repo în /etc/yum.repos.d/curl -fsSl https://pkg.cloudflare.com/cloudflared.repo | sudo tee /etc/yum.repos.d/cloudflared.repo# actualizează repository-urilesudo yum update# instalează cloudflaredsudo yum install cloudflaredApoi trebuie să pornești serviciul cloudflare și să instalezi fișierele systemd, rulând:
sudo cloudflared service install <token><token> va fi afișat în instrucțiunile de instalare.
După ce ai terminat, tot ce mai trebuie să faci este să creezi o rută, iar Cloudflare va actualiza automat intrările DNS, iar tu vei putea accesa instanța GitLab prin HTTPS.

GitLab Runner
Runner-ul este folosit pentru a rula pipeline-urile GitLab.
Îl poți instala cu:
sudo dnf install gitlab-runnergitlab-runner installgitlab-runner registerRezumat
Iată ce am învățat din acest articol:
- De ce self-hosting-ul este mai ieftin decât cloud-ul.
- Cum găzduiești GitLab folosind pachetul Linux.
- Cum îl optimizezi dezactivând module.
- Cum configurezi backup-uri automate și cum restaurezi din ele.
- Cum folosești nginx-ul inclus în GitLab pentru a găzdui site-uri.
- Cum expui GitLab pe internet folosind
cloudflared.
Mulțumesc pentru lectură! Ne vedem data viitoare!