Private git server with gitea

PURPOSE

With Microsoft acquiring GitHub (for $7.5 BILLION), I now have incentive to host my own Git repositories. For the longest time I had thought that GitHub was an Open Source project, but then I was stymied when I tried to find a way to host my own GitHub server (it seems you need to be an Enterprise to host a proper private GitHub).

Fast forward a couple of years, and Vivek Gite’s *nixcraft blog post on the subject was linked to me via email. The purpose of this article is to document my efforts to install Gitea. I had tried to install it at https://eldon.me/git/, but that would require retooling the other web application at https://eldon.me/ (WordPress). The folks on IRC (#nginx@freenode) said to make a subdomain, rather than a subdirectory. After being reminded that it’s easy to add CNAMEs to my DNS records, I now have https://git.eldon.me.

Why do this? I’d like to start using git more for my personal projects. I’d rather not store sensitive materials anywhere but something I fully control. Also, being able to link folks to my own repository rather Debian’s (or whoever’s) paste bin when I’m having issues is quite attractive to me.

PREREQUISITES

  • A Linux server (mine is a ChunkHost chunk running Debian 9.4 [stretch])
  • nginx installed (with optional SSL/TLS certificates [HIGHLY RECOMMENDED])
  • A database engine (I already have MariaDB [10.1.26-MariaDB] installed). If in doubt, go with Gitea’s built-in SQLite3 database
  • SSH service enabled on the target host (at an optional nonstandard port)

PROCEDURE

The following instructions use non-root user and host in the commands. Change accordingly.

  1. Log into the target host via SSH (user will be assumed to *NOT* be root):
    ssh host -l user
  2. Make a staging directory and change to it:
    mkdir -p ~/src/gitea && cd ~/src/gitea
  3. Install prerequisite packages git, golang (from stretch-backports), wgetand zip:
    sudo apt install git wget zip
    sudo apt -t stretch-backports install golang
  4. Add a new user for Gitea
    sudo adduser --disabled-login --gecos 'Gitea' git
  5. Change this new user git:
    sudo -u git -i
  6. Get the latest version of gitea (currently v1.4.2)
    mkdir -p bin
    wget -O bin/gitea https://dl.gitea.io/gitea/1.4.2/gitea-1.4.2-linux-amd64
    chmod +x bin/gitea
  7. Exit the git user shell
    exit
  8. Create systemd service file /etc/systemd/system/gitea.service for Gitea:
          [Unit]
          Description=Gitea
          After=syslog.target
          After=network.target
          After=mariadb.service mysqld.service postgresql.service memcached.service redis.service
        
          [Service]
          # Modify these two values and uncomment them if you have
          # repos with lots of files and get an HTTP error 500 because
          # of that
          ###
          #LimitMEMLOCK=infinity
          #LimitNOFILE=65535
          Type=simple
          User=git
          Group=git
          WorkingDirectory=/home/git
          ExecStart=/home/git/bin/gitea web
          Restart=always
          Environment=USER=git HOME=/home/git
        
          [Install]
          WantedBy=multi-user.target
  9. Start Gitea:
          sudo systemctl enable gitea
          sudo systemctl start gitea
          
  10. Create an nginx site configuration file /etc/nginx/sites-available/git.host:
    server {                                                                                                                                                                                      
        listen 80;                                                                                                                                                                            
        listen [::]:80;                                                                                                                                                                       
        server_name git.host;                                                                                                                                                             
        return 301 https://git.host;                                                                                                                                          
                                                                                                                                                                                                  
        # Redirect non-https traffic to https                                                                                                                                                     
        # if ( != https) {                                                                                                                                                               
        #     return 301 https://;                                                                                                                                               
        # } # managed by Certbot                                                                                                                                                                  
                                                                                                                                                                                                  
    }                                                                                                                                                                                             
                                                                                                                                                                                                  
    server {                                                                                                                                                                                      
        listen 443 ssl;                                                                                                                                                                           
        server_name git.host;
        ssl_certificate /etc/letsencrypt/live/host/fullchain.pem; # managed by Certbot                                                                                                     
        ssl_certificate_key /etc/letsencrypt/live/host/privkey.pem; # managed by Certbot                                                                                                   
                                                                                                                                                                                                  
        root /var/www/git.host/;                                                                                                                                                              
        location / {                                                                                                                                                                              
                client_max_body_size 364M;                                                                                                                                                        
                proxy_set_header Host ;                                                                                                                                                      
                proxy_set_header X-Real-IP ;                                                                                                                                          
                proxy_pass http://localhost:3000;                                                                                                                                                 
                proxy_connect_timeout 600;                                                                                                                                                        
                proxy_send_timeout 600
        }
    }
    
  11. Enable the new git.host:
    ln -s /etc/nginx/sites-{available,enabled}/git.host
  12. Restart nginx
    sudo systemctl restart nginx
  13. Enter MariaDB client shell (admin account)
    mysql -u root -p'password'
  14. Add gitea database
    CREATE DATABASE gitea;
  15. Add gitea user
    CREATE USER 'gitea' IDENTIFIED BY 'new_password';
  16. Grant privileges to gitea user
    GRANT ALL PRIVILEGES ON gitea.* TO 'gitea'@localhost IDENTIFIED BY 'new_password';
  17. Exit the MariaDB mysql client shell
    exit
  18. Now, you’re ready to configure Gitea at https://git.host/!

ip command nuggets

View IP address related information (all interfaces):

ip address

or

ip a

View the ARP table

ip neighbors

Cross-reference the IP addresses in the ARP cache with their local hostnames (if known). Replace “@localhost” with the hostname/IP address of the DNS server you want to query, or remove it altogether to use the system’s default DNS server:

for ip in $(ip nei | awk '{print $1}'); do dig -x $ip @localhost | grep "in-addr.arpa"; done

Or, wrapped in a shell function:

arp () {
  for ip in $(ip nei | cut -d' ' -f1); do 
    dig -x $ip @localhost | grep "in-addr.arpa"; 
  done
}