Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save ammarshah/8c9c0a4fe64bb0f8c5468deb34c30a23 to your computer and use it in GitHub Desktop.

Select an option

Save ammarshah/8c9c0a4fe64bb0f8c5468deb34c30a23 to your computer and use it in GitHub Desktop.
Set Up Your Own Git Server on Fedora 43 Using Gitea

Set Up Your Own Git Server on Fedora 43 Using Gitea

Gitea is a self-hosted, open-source Git service similar to GitHub, but lightweight, free, and perfect for personal or local setups.

While the official Gitea installation guide is simple, the process you'll see here might seem a bit extra - and that's because I wanted something very specific.

Let's put it this way: I wanted to run my own local github.com, completely offline.

My top priority was to host everything locally on my own network, where the host and client machines could communicate both wirelessly (through a Wi-Fi router) and directly through a LAN cable (peer-to-peer).

I like to keep backups of my personal data in multiple places - one of which is a Fedora machine.

Before setting this up, I used to sync data from my main machine (also running Fedora) to the backup machine using FTP and FileZilla. It worked, but it was tedious - I had to manually track every single change until I synced them.

That's when I thought: why not use Git for this?

I just didn't want anything in the cloud. So setting up my own self-hosted Git server locally made perfect sense.

1. Create a Dedicated User

It's a major security best practice to run services like Gitea under a dedicated user account, not as an administrator/root.

Open a terminal and run:

# Add new group
sudo groupadd --system git

# Add new user
sudo adduser \
   --system \
   --shell /bin/bash \
   --comment 'Git' \
   --gid git \
   --home-dir /home/git \
   --create-home \
   git

2. Download Gitea

  • Create required directory structure

    sudo mkdir -p /var/lib/gitea/{custom,data,log}
    sudo chown -R git:git /var/lib/gitea/
    sudo chmod -R 750 /var/lib/gitea/
    sudo mkdir /etc/gitea
    sudo chown root:git /etc/gitea
    sudo chmod 770 /etc/gitea
  • Download the latest Gitea binary

    Check for the latest version for your OS type here (usually it's amd64) and then replace the <version> below with the actual version number.

    sudo mkdir -p /usr/local/bin/gitea
    sudo wget -O /usr/local/bin/gitea/gitea https://dl.gitea.com/gitea/<version>/gitea-<version>-linux-amd64
    sudo chmod +x /usr/local/bin/gitea/gitea

3. Run Gitea as a Service

This will start Gitea server automatically on boot.

  • Create a service file

    sudo nano /etc/systemd/system/gitea.service
  • Copy the sample gitea.service file

    Make sure to use the same release version as your Gitea binary, then paste in the above gitea.service file that we just opened in a nano editor.

  • Fix the binary path in ExecStart directive

    # Change this
    ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
    
    # To this (note the `gitea` binary added after the `gitea` directory)
    ExecStart=/usr/local/bin/gitea/gitea web --config /etc/gitea/app.ini
  • Save and close the file (Ctrl+X, Y, Enter)

  • Enable and start the Gitea Service

    sudo systemctl enable gitea --now
  • Verify the service is active

    sudo systemctl status gitea

4. Initial Gitea Configuration

Go to http://localhost:3000 on your browser and you'll be presented with an Initial Configuration page from Gitea.

We'll use the bare minimum configuration at this point and leave the advanced configuration for the later steps:

  • Database Type: SQLite3
  • Site Title: GitShah (use whatever name you want or keep the default one)
  • Check Enable Update Checker
  • Click Install Gitea

Wait until the installation finishes and redirects you to the Register page.

Do not register for now and close the browser's tab.

5. Set the Recommended Permissions

As mentioned in the official Gitea installation guide:

/etc/gitea is temporarily set with write permissions for user git so that the web installer can write the configuration file. After the installation is finished, it is recommended to set permissions to read-only using:

sudo chmod 750 /etc/gitea
sudo chmod 640 /etc/gitea/app.ini

6. Configure Static IP

  • For LAN

    We'll have to set a static IP on both the client and server machines, which, in my case, is Fedora.

    Follow the Configure Network Settings > On Fedora 43 section from here to configure the static IP on both machines.

    On Fedora client machine use:

    Address: 192.168.200.1
    Netmask: 255.255.255.0
    

    On Fedora server machine use:

    Address: 192.168.200.7
    Netmask: 255.255.255.0
    
  • For WiFi

    In the case of WiFi, you only need to set a static IP on the server machine.

    First you need to find your WiFi router's IP using the command: ip route | grep default.

    Let's assume it's 192.168.100.1 like below:

    $ ip route | grep default
    default via 192.168.100.1 dev wlp2s0 proto dhcp src 192.168.100.125 metric 600

    which means, you can use the static IP within the same range e.g., 192.168.100.x, where x could be any number from 2 to 254.

    Just to be consistent with my server's LAN IP, I'll be using 192.168.100.7.

    Follow the same Configure Network Settings > On Fedora 43 section from here, but go to Wi-Fi instead of Network and enter the following values under IPv4 for your Wi-Fi connection:

    Address: 192.168.100.7
    Netmask: 255.255.255.0
    Gateway: 192.168.100.1
    DNS:     192.168.100.1
    

7. Map DNS for Your Domain

For the domain, I'll be using gitshah.com, use whatever you like.

  • On WiFi router

    Login to your WiFi router's admin panel and find the Static DNS (or similar) settings and add:

    gitshah.com     → 192.168.100.7
    www.gitshah.com → 192.168.100.7
    

    For example, my Huawei Router has below settings:

    image
  • On Fedora server machine

    Open /etc/hosts file:

    sudo nano /etc/hosts

    Add line:

    127.0.0.1 gitshah.com www.gitshah.com

    Save and close the file (Ctrl+X, Y, Enter).

  • On Fedora client machine

    Since we want gitshah.com to be accessible on both LAN and WiFi - and we prefer LAN (because it's faster and has lower latency) when both are connected - we'll add both IPs in the /etc/hosts file like this:

    192.168.200.7 gitshah.com www.gitshah.com # via LAN
    192.168.100.7 gitshah.com www.gitshah.com # via WiFi

    Now here's where it gets annoying: some applications and browsers (like Google Chrome) only use the first occurrence of a domain in /etc/hosts and completely ignore any subsequent entries for the same domain. Others - like curl, ping, or even Firefox - are smarter and just work fine.

    This means that in our case, gitshah.com will only resolve via LAN, since it's listed first.

    One way to handle this is to keep the LAN line commented out by default and manually toggle it - uncomment when LAN is connected, comment when it's not. Works fine, but it's repetitive and annoying as hell.

    Another approach is to use something like mDNS (dnsmasq or similar), but that's way too much machinery for something this simple. It adds multiple moving parts, and you'll have to modify each connection profile too. That's just not worth it for a small local setup like this.

    Personally, I think sticking with the plain old /etc/hosts file is far simpler and works right out of the box. If you're using Firefox, just keep both entries uncommented - it'll resolve whichever connection is active, no complaints.

    But if you're stuck with Google Chrome (like me), you'll quickly realize how much of a pain it is to manually toggle those entries every time your LAN cable connects or disconnects.

    So yeah, we'll automate this with a simple NetworkManager dispatcher script - it's straightforward, reliable, and doesn't depend on any specific app or browser behavior.

    1. Add domain mapping in /etc/hosts

      Open the file:

      sudo nano /etc/hosts

      Add:

      #192.168.200.7 gitshah.com www.gitshah.com # via LAN
      192.168.100.7 gitshah.com www.gitshah.com # via WiFi

      It's important to keep the order of the IPs as above to try LAN first if it's connected.

    2. Create a dispatcher script

      Create a new shell script:

      sudo mkdir -p /etc/NetworkManager/dispatcher.d
      sudo nano /etc/NetworkManager/dispatcher.d/99-gitshah-lan-monitor.sh

      Put this inside:

      #!/bin/bash
      IFACE="$1"
      STATE="$2"
      
      HOSTS_FILE="/etc/hosts"
      LAN_MARKER="via LAN"
      
      if [ "$IFACE" = "enp0s31f6" ]; then
       case "$STATE" in
         up)
           # Enable LAN line (remove #)
           sed -i "/$LAN_MARKER/s/^#//" "$HOSTS_FILE"
           logger -t gitshah-lan-monitor "LAN is UP → enabled LAN entry in $HOSTS_FILE"
           ;;
         down)
           # Disable LAN line (add # at start)
           sed -i "/$LAN_MARKER/s/^/#/" "$HOSTS_FILE"
           logger -t gitshah-lan-monitor "LAN is DOWN → disabled LAN entry in $HOSTS_FILE"
           ;;
       esac
      fi

      Replace enp0s31f6 with your LAN interface (ip link will tell you).

      Make it executable:

      sudo chmod +x /etc/NetworkManager/dispatcher.d/99-gitshah-lan-monitor.sh
    3. Restart NetworkManager

      sudo systemctl restart NetworkManager

    Now, every time your LAN interface (i.e., enp0s31f6, in my case) goes up or down, NetworkManager will automatically toggle (uncomment/comment) the line ending with via LAN in /etc/hosts.

    You can also see the messages in your logs whenever the script triggers:

    journalctl -t gitshah-lan-monitor

8. Generate Self-Signed SSL Certificate

  • Create a Root CA

    Create a private key for your CA:

    openssl genrsa -out gitshahCA.key.pem 4096

    Create a self-signed CA certificate (valid 10 years):

    openssl req -x509 -new -nodes -key gitshahCA.key.pem -sha256 -days 3650 \
      -out gitshahCA.cert.pem \
      -subj "/C=PK/ST=Sindh/L=Karachi/O=GitShahCA/OU=Dev/CN=GitShah Root CA"
  • Create a Server Key + CSR

    Make a server private key:

    openssl genrsa -out gitshah.key.pem 2048

    Make a config file for your SANs:

    # Open a new file
    nano san.cnf
    
    # Paste the following, then save and close the file
    [req]
    default_bits       = 2048
    default_md         = sha256
    prompt             = no
    distinguished_name = req_distinguished_name
    req_extensions     = req_ext
    
    [req_distinguished_name]
    CN = gitshah.com
    
    [req_ext]
    subjectAltName = @alt_names
    
    [alt_names]
    DNS.1 = gitshah.com
    DNS.2 = www.gitshah.com

    Generate a certificate signing request (CSR):

    openssl req -new -key gitshah.key.pem -out gitshah.csr.pem -config san.cnf
  • Sign the CSR with your Root CA

    openssl x509 -req -in gitshah.csr.pem -CA gitshahCA.cert.pem -CAkey gitshahCA.key.pem \
      -CAcreateserial -out gitshah.cert.pem -days 3650 -sha256 -extfile san.cnf -extensions req_ext

9. Configure Gitea for HTTPS and SSH

  • Copy the Certificate and Key Files

    sudo mkdir /var/lib/gitea/custom/https
    sudo cp gitshah.cert.pem gitshah.key.pem /var/lib/gitea/custom/https
  • Change Ownership

    sudo chown -R git:git /var/lib/gitea/custom/https
  • Update app.ini

    Open the file:

    sudo nano /etc/gitea/app.ini

    Go to the [server] block and add/modify the following:

    PROTOCOL = https
    CERT_FILE = /var/lib/gitea/custom/https/gitshah.cert.pem
    KEY_FILE = /var/lib/gitea/custom/https/gitshah.key.pem
    DOMAIN = gitshah.com
    HTTP_PORT = 443
    ROOT_URL = https://gitshah.com/
    START_SSH_SERVER = true
    SSH_DOMAIN = gitshah.com
    SSH_PORT = 2222

    Save and close the file (Ctrl+X, Y, Enter).

  • Open the firewall for HTTPS Traffic

    Fedora has a firewall enabled by default. You must ensure port 443 (HTTPS) is open to traffic from your local network.

    # Check the currently active services
    sudo firewall-cmd --list-all
    
    # Permanently add the HTTPS service to the firewall
    sudo firewall-cmd --add-service=https --permanent
    
    # Open firewall for our custom SSH port (2222)
    sudo firewall-cmd --add-port=2222/tcp --permanent
    
    # Reload the firewall to apply the changes
    sudo firewall-cmd --reload
    
    # Verify the service is added
    sudo firewall-cmd --list-all

    You should now see https and 2222/tcp added to the services and ports, respectively.

  • Grant Capability to bind to privileged port (443)

    We need to grant the binary special permissions to bind to a privileged port like 443.

    Open gitea.service file:

    sudo nano /etc/systemd/system/gitea.service

    Uncomment the following:

    CapabilityBoundingSet=CAP_NET_BIND_SERVICE
    AmbientCapabilities=CAP_NET_BIND_SERVICE

    Add the following at the end of the [Service] section:

    # Security hardening and sandboxing (tweak if needed)
    NoNewPrivileges=true
    ProtectSystem=strict
    ProtectHome=true
    PrivateTmp=true
    PrivateDevices=true
    ProtectKernelTunables=true
    ProtectKernelModules=true
    ProtectControlGroups=true
    LockPersonality=true
    RestrictRealtime=true
    #
    # Allow writes only to necessary dirs
    ReadWritePaths=/var/lib/gitea

    Save and close the file (Ctrl+X, Y, Enter).

  • Reload systemd Daemon

    sudo systemctl daemon-reload
  • Restart the Service

    sudo systemctl restart gitea
    sudo systemctl status gitea # Verify it's running correctly
  • Verify the SSH and HTTPS ports are listening

    sudo ss -tlnp | grep -E '2222|443'

    You should see an output similar to below:

    LISTEN 0      4096               *:2222            *:*    users:(("gitea",pid=20799,fd=12))
    LISTEN 0      4096               *:443             *:*    users:(("gitea",pid=20799,fd=13))

10. Trust the Self-Signed Certificate

Use the following steps on both Fedora client and Fedora server machines:

  • Install Root CA into Fedora trust store

    sudo cp gitshahCA.cert.pem /etc/pki/ca-trust/source/anchors/
    sudo update-ca-trust
  • Verify

    curl -v https://gitshah.com

    If your service is running with that cert, curl should connect without complaining about an untrusted certificate.

  • Restart your browser to apply.

Now, you should be able to access your Gitea server web interface using both https://gitshah.com and https://www.gitshah.com.

11. Create Admin User

When you register your first account - it becomes admin.

  • Go to https://gitshah.com and click on the Register button on the top-right corner and register an account.

  • After you're signed in, click on your username on the top-right corner, click Settings > Profile > find User visibility option and set it to Private.

We'll only use the admin account for Gitea server management or if there's a need to manage other users and their repositories - but we won't create repositories/organizations from this account.

For a regular use, we'll register a user account, just like you would on GitHub/GitLab, and then create and manage repositories/organizations, etc.

Optional:

  • After you're signed in, if you configured optional mailer settings yourself in the fourth step (Initial Gitea Configuration) above, you can activate your account by clicking on your username on the top-right corner, click Settings > Account > under Manage Email Addresses section, click Send Activation.

  • You'll receive an activation link on your email (check spam if not), but it may not activate your account when you are already signed in (it's a bug on Gitea's end), so you'll have to sign out first and then use the activation link to activate your account.

BONUS

1. Upgrade to a new version

See the official documentation for the recommended way of updating to a new version, which includes creating a backup before updating, otherwise, follow the steps below:

# Stop the Gitea server
sudo systemctl stop gitea

# Download and replace with the latest Gitea binary (check for the latest version at https://dl.gitea.com/gitea/)
sudo wget -O /usr/local/bin/gitea/gitea https://dl.gitea.com/gitea/<version>/gitea-<version>-linux-amd64

# Restart the server
sudo systemctl restart gitea

2. Troubleshooting

For troubleshooting purposes, you can see live Gitea logs using:

journalctl -u gitea -f

3. Increase file upload limit on Gitea web interface

As per the documentation, the default max size of each file is 50 MB and 5 files per upload.

Note

This only applies to the file upload via the Gitea's web interface and not push via command-line - it has no limit.

To increase these limits, modify app.ini:

# Open app.ini
sudo nano /etc/gitea/app.ini

# Add the following, then save and close the file
[repository.upload]
FILE_MAX_SIZE = 10240 # 10 GB per file
MAX_FILES = 20000     # 20,000 files per upload

# Restart the service
sudo systemctl restart gitea

4. Few nice-to-have repository settings

The following are some of the repository settings I like to have for an ease of use. See the full list here.

# Open app.ini
sudo nano /etc/gitea/app.ini

# Go to the [repository] block and add the following, then save and close the file
DEFAULT_BRANCH = master 		     # Default branch name of all repositories.
DEFAULT_PUSH_CREATE_PRIVATE = false  # Default private when creating a new repository with push-to-create.
ENABLE_PUSH_CREATE_USER = true       # Allow users to push local repositories to Gitea and have them automatically created for a user.
ENABLE_PUSH_CREATE_ORG = true        # Allow users to push local repositories to Gitea and have them automatically created for an org.

# Restart the service
sudo systemctl restart gitea
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment