
Running a self-hosted Git platform gives your team full control over source code, CI/CD pipelines, and user access without sending sensitive data to third-party services. Many organizations choose Fedora 44 for its cutting-edge security features and rapid adoption of upstream patches, but installing GitLab on this distribution requires understanding Fedora’s unique security model. This guide walks you through the complete process to install GitLab on Fedora 44 using the official Omnibus package method, which bundles all dependencies into a single, manageable installation.
GitLab Community Edition (CE) is a free, open-source DevOps platform that includes Git repository hosting, built-in CI/CD runners, issue tracking, and container registry support. Unlike GitHub or GitLab.com, self-hosting means you control when backups happen, which users can access the system, and where your data physically resides. The installation process looks intimidating at first, but breaking it into discrete steps with clear explanations of why each command matters makes it straightforward even for beginners.
This tutorial assumes you are comfortable with the Linux command line and have sudo access to your Fedora 44 server. By the end of these steps, you will have a fully functional GitLab instance accessible through your web browser, secured with proper firewall rules and SELinux policies.
Prerequisites
Before starting the GitLab on Fedora 44 setup, ensure you have the following requirements met:
- Operating System: Fresh Fedora 44 minimal server installation (released April 2026)
- RAM: Minimum 4 GB (8 GB recommended for teams of 5+ developers)
- CPU: At least 2 cores (4 cores recommended for production use)
- Disk Space: 20 GB available storage (GitLab Omnibus package is around 1 GB)
- User Account: Root access or a user with sudo privileges
- Network: Active internet connection and either a public IP address or valid domain name pointing to your server
- Ports: Ports 80 (HTTP), 443 (HTTPS), and 22 (SSH) must be accessible
The system should be a clean installation without other web servers (Apache, Nginx) or mail transfer agents running, as these can conflict with GitLab’s bundled services. If you already have conflicting software installed, you can either remove it during the process or configure GitLab to use different ports.
Step 1: Update Your System Packages
Why System Updates Matter First
Fedora 44 may have pending security patches, kernel updates, or OpenSSL library upgrades at the time of installation. Running GitLab on an outdated system can cause TLS handshake failures between internal services or create security vulnerabilities from known exploits. System updates ensure all underlying libraries are current before adding new software.
Execute the Update Command
sudo dnf update -y
This command uses Fedora’s default package manager (DNF) to check all configured repositories for available updates. The -y flag automatically confirms the installation prompt, which is appropriate for single-administrator setups. If you work in a shared environment where changes require review, remove the -y flag to inspect the update list first.
Expected Output
Last metadata expiration check: 0:05:23 ago on Mon Jun 08 17:30:00 2026.
Dependencies resolved.
================================================================================
Package Architecture Version Repository
================================================================================
Upgrade:
glibc x86_64 2.40-11.fc44 updates
openssh-clients x86_64 9.9p1-4.fc44 updates
systemd x86_64 256-1.fc44 updates
================================================================================
Complete!
After the update completes, check if a new kernel was installed:
uname -r
If the running kernel version does not match the latest installed kernel, reboot your server:
sudo reboot
A kernel update ensures GitLab’s Gitaly service (which handles Git operations) can load kernel modules without issues. This step is critical for system stability.
Step 2: Install Required System Dependencies
Understanding What Dependencies GitLab Needs
GitLab Omnibus includes most internal services, but several system-level packages must exist beforehand. These dependencies handle network communication, security contexts, and Git operations that GitLab itself does not bundle.
Install the Dependency Packages
sudo dnf install -y curl policycoreutils openssh-server perl
Why Each Package Is Necessary
curl downloads files over HTTPS and is required to fetch the GitLab repository installation script from packages.gitlab.com. Without curl, you cannot register the official GitLab RPM repository that DNF needs to find the GitLab package.
policycoreutils provides SELinux management utilities like semanage and restorecon. Fedora 44 runs SELinux in enforcing mode by default, which blocks processes from binding to ports unless explicitly allowed. GitLab’s bundled Nginx server needs SELinux port contexts configured correctly to serve web traffic on ports 80 and 443.
openssh-server enables SSH protocol access for Git operations. Developers clone repositories and push code using the git@server.com:path/to/repo.git SSH URL format. Without an active SSH daemon, this authentication method fails entirely.
perl is used by GitLab’s internal migration scripts and the Gitaly server during reconfiguration. Some older components in the Omnibus package still rely on Perl for file processing tasks.
Enable and Start the SSH Service
sudo systemctl enable sshd
sudo systemctl start sshd
The enable command creates a systemd symlink so SSH starts automatically after reboots. The start command activates the service immediately without waiting for a reboot. SSH must be running before developers can push code to GitLab.
Verify SSH Is Active
sudo systemctl status sshd
Expected output shows active (running):
● sshd.service - OpenSSH server daemon
Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled)
Active: active (running) since Mon 2026-06-08 17:35:12 WIB
Step 3: Install and Configure Postfix for Email Notifications
Why GitLab Needs a Mail Transfer Agent
GitLab sends transactional emails for user registration confirmations, password reset links, merge request notifications, CI/CD pipeline failures, and mention alerts. Without a working mail transfer agent (MTA), these notifications fail silently, and users lose visibility into important project events.
Install Postfix
sudo dnf install -y postfix
Postfix is the default MTA choice for GitLab because it is lightweight, well-maintained, and configured to work as a local relay out of the box. This means it can send emails without requiring an external SMTP server configuration for basic functionality.
Enable and Start Postfix
sudo systemctl enable postfix
sudo systemctl start postfix
Enabling Postfix ensures the mail service survives server reboots. If Postfix is not running when GitLab’s Sidekiq job processor attempts to queue an email, the job fails and retries repeatedly, consuming CPU resources and filling log files with error messages.
Verify Postfix Is Running
sudo systemctl status postfix
Look for active (running) in the output. If the service fails to start, check for port 25 conflicts with other mail software:
sudo ss -tlnp | grep :25
Optional: Configure External SMTP Instead
If your organization uses SendGrid, Mailgun, or AWS SES for email delivery, skip Postfix and configure SMTP settings directly in gitlab.rb later. This approach is better for production environments because external SMTP services offer better deliverability rates and tracking. However, Postfix is the fastest zero-configuration solution for new installations.
Step 4: Add the Official GitLab CE Repository
Why You Need GitLab’s Official Repository
GitLab Community Edition is not included in Fedora’s default repositories or EPEL. The official GitLab package repository must be added manually so DNF can locate, verify, and install signed GitLab RPM packages. Using unofficial sources risks installing outdated or compromised software.
Execute the Repository Setup Script
curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
This script performs three critical actions automatically:
- Adds a
.repofile to/etc/yum.repos.d/that points to GitLab’s package servers - Imports GitLab’s GPG signing key so DNF can verify package signatures
- Verifies the key fingerprint to ensure the package source is authentic
Security Note on Piping Commands
Piping curl output directly to bash is a common pattern but carries risk if the source URL is compromised. For production environments with strict security requirements, download the script first, inspect it for unexpected commands, then execute it separately:
curl -O https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh
nano script.rpm.sh # Review the script contents
sudo bash script.rpm.sh
rm script.rpm.sh
This extra step gives you full visibility into what commands will run on your system.
Verify the Repository Was Added
dnf repolist | grep gitlab
Expected output should show:
gitlab-ce GitLab CE RPM repository for Fedora 44
If no output appears, the repository installation failed. Check your internet connection and try the setup script again.
Step 5: Install GitLab CE with External URL Configuration
Why Setting External_url During Installation Matters
The EXTERNAL_URL environment variable tells GitLab what address users will use to access the web interface. This value gets baked into /etc/gitlab/gitlab.rb during the first automatic configuration run. If you skip this step, GitLab defaults to localhost, making it unreachable from other machines.
Execute the Installation Command
sudo EXTERNAL_URL="http://your-server-ip-or-domain.com" dnf install -y gitlab-ce
Replace your-server-ip-or-domain.com with your actual server IP address or fully qualified domain name. If you are using a domain name, ensure DNS A records point to your server’s public IP before running this command.
What Happens During Installation
The GitLab CE omnibus package is approximately 1 GB and includes all internal services:
- PostgreSQL database for storing all data
- Redis for caching and job queues
- Nginx as the embedded web server
- Puma as the Ruby application server
- Sidekiq for background job processing
- Gitaly for Git repository operations
During installation, the package automatically runs gitlab-ctl reconfigure for the first time. This process can take 3 to 5 minutes on a fresh server while it initializes the PostgreSQL database, creates the GitLab schema, and starts all services.
Expected Installation Progress
GitLab: https://www.gitlab.com
GitLab RCE: https://about.gitlab.com
GitLab Runner: https://gitlab.com/gitlab-org/gitlab-runner
GitLab Shell: https://gitlab.com/gitlab-org/gitlab-shell
Installing GitLab...
Reconfiguring gitlab...
Running gitlab-ctl reconfigure...
[ok] reconfiguring gitlab
...
GitLab Reconfigured!
Installation complete.
The final line GitLab Reconfigured! indicates successful completion. If you see errors before this message, note the error text and address it before proceeding.
Step 6: Configure firewalld to Allow Web Traffic
Why Firewall Configuration Is Critical
Fedora 44 ships with firewalld active in default-deny mode for incoming connections. Without explicit allow rules, HTTP and HTTPS requests from browsers are silently dropped at the kernel packet filter level. GitLab runs perfectly internally but remains invisible to external users.
Add HTTP, HTTPS, and SSH Services to the Firewall
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload
Breakdown of Each Command
The --permanent flag writes rules to the firewalld XML zone configuration in /etc/firewalld/, ensuring they persist after reboots. Without this flag, rules only apply to the current session and vanish when firewalld restarts.
The --add-service option adds predefined service definitions rather than raw port numbers. Fedora maintains service definitions for common protocols, making firewall rules more readable and maintainable.
The --reload command applies permanent rules to the running configuration without dropping existing connections. This is safer than restarting firewalld entirely, which would interrupt active SSH sessions.
Verify Firewall Rules Are Active
sudo firewall-cmd --list-all
Expected output includes http, https, and ssh in the services list:
public (active)
target: default
icmp-block-inversion: no
interfaces: eth0
sources:
services: ssh dhcpv6-client http https
ports:
protocols:
forward: no
If SSH is missing from the services list, you risk locking yourself out of the server after reloading firewall rules. Always verify SSH is included before reloading.
Step 7: Configure SELinux for GitLab
Understanding SELinux’s Role in Fedora Security
Fedora 44 runs SELinux in enforcing mode by default. SELinux uses type enforcement to control which processes can access which files and ports. GitLab’s bundled Nginx may be blocked from binding to ports 80 and 443 without explicit SELinux type contexts.
Allow Nginx to Bind to HTTP and HTTPS Ports
sudo semanage port -a -t http_port_t -p tcp 80
sudo semanage port -a -t http_port_t -p tcp 443
The semanage port command adds ports 80 and 443 to the http_port_t SELinux type context. This is the context SELinux expects for legitimate web server processes. Without this rule, Nginx attempts to bind to these ports but SELinux denies the operation, causing GitLab web interface errors.
If the Port Already Exists, Use Modify Instead
sudo semanage port -m -t http_port_t -p tcp 80
sudo semanage port -m -t http_port_t -p tcp 443
The -m flag modifies an existing rule instead of creating a new one. If the gitlab-on-fedora-44 setup encounters an error stating the port already exists, use modify rather than add.
Restore Correct File Contexts on GitLab Directories
sudo restorecon -R -v /var/log/gitlab
The restorecon command resets SELinux file contexts to match the active policy. GitLab Omnibus creates directories during installation with default contexts that may not match what SELinux expects. The -R flag applies changes recursively to all subdirectories, and -v shows verbose output of changed files.
Do Not Disable SELinux
Some older tutorials suggest disabling SELinux entirely with setenforce 0. This is a security anti-pattern that removes mandatory access control protection. SELinux blocks many attack vectors that firewalls cannot catch, including privilege escalation attempts and process injection attacks. Keep SELinux enforcing and configure it correctly instead.
Step 8: Edit gitlab.rb for Production Configuration
Why gitlab.rb Is the Single Source of Truth
The /etc/gitlab/gitlab.rb file is GitLab Omnibus’s master configuration. Every time you run gitlab-ctl reconfigure, this file is read and all internal service configurations are regenerated from it. Direct edits to internal configuration files (like PostgreSQL’s postgresql.conf) are overwritten on the next reconfigure run.
Open the Configuration File
sudo nano /etc/gitlab/gitlab.rb
Key Settings to Configure
Set the correct external URL:
external_url 'https://your-domain.com'
The external_url must exactly match the URL users type into their browser. Mismatches cause OAuth callback failures, broken asset paths, and redirect loops.
Enable SMTP for email delivery (if using external mail provider):
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.mailgun.org"
gitlab_rails['smtp_port'] = 587
gitlab_rails['smtp_user_name'] = "postmaster@yourdomain.com"
gitlab_rails['smtp_password'] = "your-smtp-password"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
This configuration replaces Postfix with an external SMTP service. Fill in your actual SMTP credentials from your email provider.
Disable public user signup for private instances:
gitlab_rails['signup_enabled'] = false
For internal team use, disabling signup prevents unauthorized users from creating accounts. Admins can still create user accounts manually or via LDAP integration.
Change Nginx listen port if behind a reverse proxy:
nginx['listen_port'] = 8080
Only needed if another web server handles ports 80/443 on the same machine.
Save and Exit
Press Ctrl+X, then Y, then Enter to save changes and exit nano.
Step 9: Apply Configuration with gitlab-ctl reconfigure
Understanding What Reconfigure Does
The gitlab-ctl reconfigure command is a Chef-based provisioning run that reads gitlab.rb, generates all downstream configuration files, and restarts only the services whose configurations changed. It is idempotent, meaning running it multiple times produces the same result.
Execute Reconfigure
sudo gitlab-ctl reconfigure
What Happens During Reconfigure
During the first run after installation, GitLab:
- Initializes the PostgreSQL database if not already done
- Creates the GitLab schema and seeds default data
- Generates the initial root password
- Starts all internal services (Puma, Sidekiq, PostgreSQL, Redis, Nginx, Gitaly)
The process typically takes 3 to 5 minutes. Watch for the final line:
Running handlers complete
GitLab reconfigured!
Troubleshooting Reconfigure Failures
If you see errors before GitLab reconfigured!, check the logs:
sudo gitlab-ctl tail reconfigure
Common issues include syntax errors in gitlab.rb (missing quotes, incorrect brackets) or port conflicts with other services.
Step 10: Retrieve Initial Root Password and Log In
Finding Your Temporary Root Password
sudo cat /etc/gitlab/initial_root_password
Why This File Is Time-Limited
GitLab generates a random strong password for the root account during the first reconfigure run and stores it in this file. The file is automatically deleted 24 hours after installation. If you do not change the root password before deletion, you must use gitlab-rake to reset it manually.
Example Output
Password: abc123XYZ789!@#def456
Copy this password to a secure location immediately.
Access the Web Interface
Open your browser and navigate to:
http://your-server-ip-or-domain.com
If you set up SSL (see Step 11), use https:// instead.
Log in with:
- Username:
root - Password: The password from
initial_root_password
Change the Root Password Immediately
Navigate to User Settings > Password in the GitLab web interface and set a permanent password. After securing root, create a personal admin account with your named email address. Using the root account for daily development work is a security anti-pattern.
Step 11: Secure Your Instance with SSL Using Let’s Encrypt
Why HTTPS Is Mandatory for Production
GitLab sends session cookies, API tokens, and user credentials over the network. Running without HTTPS means these are transmitted in cleartext and trivially interceptable on any shared network. SSL encryption prevents eavesdropping and man-in-the-middle attacks.
Configure Let’s Encrypt in gitlab.rb
Open the configuration file:
sudo nano /etc/gitlab/gitlab.rb
Add or modify these lines:
external_url 'https://your-domain.com'
letsencrypt['enable'] = true
letsencrypt['contact_emails'] = ['admin@yourdomain.com']
Important Requirements for Let’s Encrypt
- Port 80 must be publicly accessible (required for ACME HTTP-01 challenge)
external_urlmust use a real, DNS-resolvable domain name, not an IP address- DNS A record must point to your server’s public IP
Apply the Configuration
sudo gitlab-ctl reconfigure
GitLab automatically requests the certificate from Let’s Encrypt, installs it, and configures Nginx to use HTTPS. Certificate renewal happens automatically every 60 days without manual intervention.
Verify SSL Is Working
Open your browser and check for the padlock icon in the address bar. You can also test with:
curl -I https://your-domain.com
Look for HTTP/2 200 in the response.
Troubleshooting Common Errors
Error 1: “502 Bad Gateway – Waiting for GitLab to boot”
Cause: Puma workers are still starting up. This is normal during the first few minutes after installation.
Solution: Wait 60 seconds and refresh the page. If the error persists, check memory availability:
free -h
If available RAM is below 1 GB, GitLab may struggle to start all workers. Consider adding more RAM or restarting services:
sudo gitlab-ctl restart
Error 2: SELinux AVC Denial in Audit Logs
Cause: SELinux is blocking GitLab from accessing a required resource.
Solution: Check the audit log for specific denials:
sudo grep denied /var/log/audit/audit.log | tail -20
Generate a custom SELinux policy module to allow the operation:
sudo audit2allow -a -M gitlab_custom
sudo semodule -i gitlab_custom.pp
Error 3: Port 80 Already in Use
Cause: Another web server (Apache, Nginx) is already listening on port 80.
Solution: Find and stop the conflicting service:
sudo ss -tlnp | grep :80
sudo systemctl stop nginx
sudo systemctl disable nginx
Alternatively, configure GitLab to use a different port in gitlab.rb:
nginx['listen_port'] = 8080
Error 4: initial_root_password File Is Missing
Cause: The file was automatically deleted after 24 hours.
Solution: Reset the root password manually using GitLab’s Rake task:
sudo gitlab-rake "gitlab:password:reset[root]"
Follow the prompts to enter a new password. This is more time-consuming than using the initial file, so change your password within the first 24 hours.
Error 5: Email Notifications Not Sending
Cause: Postfix is not running or SMTP settings are misconfigured.
Solution: Verify Postfix status:
sudo systemctl status postfix
If using external SMTP, check gitlab.rb settings and test delivery:
sudo gitlab-rake "gitlab:email:test"
[su_box title=”VPS Manage Service Offer” style=”bubbles” box_color=”#000000″ radius=”10″]If you don’t have time to do all of this stuff, or if this is not your area of expertise, we offer a service to do “VPS Manage Service Offer”, starting from $10 (Paypal payment). Please contact us to get the best deal![/su_box]