Date: May 9, 2021
Last Updated: Nov 13, 2022
In this short post, I'm going to write down the instructions I used to set up a simple website to host my git repositories using cgit on Fedora 34.
The first thing to do is to copy over an ssh key and disable remote login with a password. Assuming you already have an ssh key you can just run:
$ ssh-copy-id -i ~/.ssh/id_rsa.pub root@[remote ip]
where [remote ip] is the ip address of the machine you want to host things on. After doing so you can log onto the remote machine and edit /etc/ssh/sshd_config and update the following line to
PasswordAuthentication no
and then restart sshd:
# systemctl restart sshd
Next, it's always a good idea to update everything on the remote machine:
# yum update
Next, we need to install the web server and cgit
# yum install git, cgit, httpd
Now, you can copy over your website's index.html and any other files to /var/www/html.
By default, Fedora 34 uses firewalld to create a firewall. I prefer to use the simpler method of directly editing iptables, so I disabled firewalld:
# systemctl stop firewalld
# systemctl disable firewalld
# systemctl mask firewalld
Next, install iptables-services and activate it:
# yum install iptables-services
# systemctl enable iptables.service
# systemctl enable ip6tables.service
Next, I edited the iptables rules to only allow ssh and web traffic:
# iptables -A INPUT -o lo -j ACCEPT
# iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -P INPUT DROP
# iptables -P FORWARD DROP
After doing so, your iptables should look like:
# iptables --list
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all -- anywhere anywhere
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
ACCEPT tcp -- anywhere anywhere tcp dpt:http
ACCEPT tcp -- anywhere anywhere tcp dpt:https
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
Chain FORWARD (policy DROP)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Now, we have to save our new rules or they will get lost in a reboot:
# iptables-save > /etc/sysconfig/iptables
Next, we'll copy over these rules for IPv6:
# ip6tables-restore /etc/sysconfig/iptables
# ip6tables-save > /etc/sysconfig/ip6tables
Note: Reading online it seems that for IPv6 to work, it's critical to enable ICMP packets. Since I'm not setting things up on IPv6, I've ignored this, but it might be worth adding a rule to the ip6tables rules for these packets as suggested here .
After completing the above steps, I still couldn't get the cgit website to show up at http://www.tlatorre.com/cgit , and I was getting error messages in /var/log/httpd/error_log that looked like:
[timestamp] [cgid:error] [pid 18921:tid 19123] [client foo] fatal: unable to access '/var/lib/git/cgit.git/config': Permission denied: /var/www/cgi-bin/cgit, referer: http://www.tlatorre.com/cgit
[timestamp] [cgid:error] [pid 18921:tid 19123] [client foo] End of script output before headers: cgit, referer: http://www.tlatorre.com/cgit
I think to fix this I had to run:
# setsebool -P httpd_enable_cgi 1
and then restart the apache server
# service httpd restart
but I actually ended up tweaking lots of things and then noticed that it eventually worked, so I'm not 100% sure that is what fixed it.
Update: I tried this on a new machine and it didn't work. I had to run:
# restorecon -vR /var/lib/git/
at some point.
To set up cgit, you should edit the file /etc/httpd/conf.d/cgit.conf to look like:
Alias /cgit-data /usr/share/cgit
ScriptAlias /cgit /var/www/cgi-bin/cgit
<Directory "/usr/share/cgit">
Require all granted
</Directory>
Then, create the directory /var/lib/git and initialize a new empty repository:
# mkdir -p /var/lib/git
# cd /var/lib/git
# mkdir repo.git
# cd repo.git
# git init --bare
Now, from your local machine you can add it as a remote and push the master branch:
$ git remote add web root@[remote ip]:/var/lib/git/repo.git
$ git push web master
Finally, you can edit /etc/cgitrc to add the new repo. Near the bottom of the file you can find some example repositories. Here is what mine looks like for chroma:
repo.url=chroma
repo.path=/var/lib/git/chroma.git
repo.desc=Chroma is a high performance optical photon simulation for particle physics detectors
repo.owner=Anthony LaTorre
repo.readme=chroma/index.html
Next, I uncommented the line
# Allow http transport git clone
enable-http-clone=1
and added the line
# Specify some default clone prefixes
clone-prefix=https://www.tlatorre.com/cgit
so people can clone my repos over https.
To set up SSL I mostly followed the instructions at https://tecadmin.net/setup-lets-encrypt-ssl-with-apache-on-fedora/ . First, we need to install the SSL mod for apache and the certbot client:
# yum install python3-certbot-apache mod_ssl
Next, create a new file at /etc/http/conf.d/webhost.example.com.conf which looks like:
<VirtualHost *:80>
ServerAdmin [email protected]
ServerName www.example.com
DocumentRoot /var/www/html
<Directory /var/www/html>
Allowoverride all
</Directory>
</VirtualHost>
Then run:
# certbot-3 apache
Then, we can check that we can auto renew by running:
# certbot-3 renew --dry-run
and if everything goes well you can run
crontab -e
and add a rule:
0 * * * * certbot-3 renew
Create a new file /etc/httpd/conf.d/deflate.conf:
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
AddOutputFilterByType DEFLATE application/x-font
AddOutputFilterByType DEFLATE application/x-font-opentype
AddOutputFilterByType DEFLATE application/x-font-otf
AddOutputFilterByType DEFLATE application/x-font-truetype
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE font/opentype
AddOutputFilterByType DEFLATE font/otf
AddOutputFilterByType DEFLATE font/ttf
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE image/x-icon
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
</IfModule>
Then, restart apache:
$ systemctl restart httpd.service
First, if you're using a linode instance, you need to open a support ticket to make sure that they open ports 587 for you, since they are by default blocked .
Next, we'll install dnf automatic:
$ dnf install dnf-automatic
$ systemctl enable --now dnf-automatic.timer
Now, we need to install something to send email:
$ dnf install msmtp
And now edit ~/.msmtprc to look something like this:
defaults
port 587
tls on
account namecheap
host [email host]
from [email address]
user [email address]
password [password]
account default : namecheap
Now, you can test if it's working:
$ echo "Hello world" | msmtp [your email address]
If so, next edit /etc/dnf/automatic.conf to make sure it includes lines like the following:
apply_updates = yes
emit_via = stdio, command_email
[command_email]
command_format = "msmtp {email_to}"
stdin_format = "Subject: {subject}\n\n{body}"
email_from = [email address]
email_to = [your email address]
That's it!