# How to Host Your Own Gemini Site in the Cloud > Mon 8th February 2021 By David T. Sadler. So I have a Gemini site over at gemini://davidtsadler.co.uk and I thought I'd write up how I achieved this in case anyone was interested in doing the same. I would say that from purchasing the domain name to having a complete server hosting the site took about 30 minutes in total. ## Purchasing a Domain Name I decided that for the moment I would keep my traditional "Big Web" content hosted at davidtsadler.com and use a different domain name for my new Gemini site. Since this meant purchasing a new one I popped over to Gandi.net to acquire davidtsadler.co.uk. Side note: I used to own this but decided not to renew it for some crazy reason. ## Creating a cloud sever My cloud provider of choice is Hetzner and creating a new server is done in eight steps. ### 1. Location Hetzner provide a few locations in Europe as to where the server is hosted. For this server I chose Helsinki. ### 2. Image I chose Ubuntu 20.04 as the operating system as this is the one I'm most familiar with. ### 3. Type As this server is only going to a host a Gemini site I don't need a overly powerful system so I chose their most basic CX11 configuration. For €2.99 a month this gives me: * 1 virtual CPU. * 2GB ram. * 20GB SSD . * 20 TB of network traffic a month. ### 4. Volume You have the option of attaching additional storage to the server. I skipped this step as for the time been the 20GB SSD that comes with the server should be enough for my needs. ### 5. Network. I skipped this step as its not needed. ### 6. Additional features Again I skipped this step but select any if you believe that you will need them. ### 7. SSH Key When a server is created a root user is added and a password is emailed to you so that you can login. However if you provide a SSH key it will be installed on the server instead of creating a password. I like to use separate keys for each server that I manage so I tend store the them in a directory named after the hostname. ```shell $ mkdir ~/.ssh/davidtsadler.co.uk $ ssh-keygen -t rsa -b 4096 -f ~/.ssh/davidtsadler.co.uk/id_rsa ``` The SSH key is added by clicking + ADD SSH KEY and then copying and pasting the contents of the id_rsa.pub file. ### 8. Name I name my servers after the hostname so for this I called it davidtsadler.co.uk. I then created the server by clicking CREATE & BUY NOW. ## SSH Once the server was created I took the allocated IP address and ensured that I could access it via SSH using the key that I had provided. ```shell $ ssh root@135.181.201.71 -i ~/.ssh/davidtsadler.co.uk/id_rsa ``` ## Resolve the Domain Name to the Server In my Gandi.net account I went to the DNS Records section for the domain name I had purchased. There I deleted everything except for the @ (A) and www (CNAME) records which was configured as follows: * @ (A) 135.181.201.71 * www (CNAME) davidtsadler.co.uk. The A record is configured with the IPv4 address of my new server and the CNAME with the domain name. Note that the CNAME must end with a period! After saving the changes it was just a matter of waiting for it to propagate through the DNS system. At which point I could use the domain name when logging in via SSH. ```shell $ ssh root@davidtsadler.co.uk -i ~/.ssh/davidtsadler.co.uk/id_rsa ``` ## Securing the Server At a bare minimum I setup a firewall and harden SSH. I may at a later date go further, such as installing fail2ban. ### Configure a Firewall This setup will deny any incoming requests unless they were first initiated by a request from the server. Since I need to be able to access the server I allow SSH. The Gemini protocol uses port 1965 so that is also allowed. ```shell $ ufw default allow outgoing $ ufw default deny incoming $ ufw allow OpenSSH $ ufw allow 1965 $ ufw enable ``` ### Harden SSH I edited the /etc/ssh/sshd_config file. ```shell $ vim /etc/ssh/sshd_config ``` I added the two below options so that the root user is not allowed to access the sever via SSH and other users may only access using keys. ``` PermitRootLogin no PasswordAuthentication no ``` Since I'd made changes to the configuration I needed to restart the SSH service. ```shell $ service sshd restart ``` ### Create non-root User Whenever I access a server I like to login as a non-root user that is able to run sudo on the system. ```shell $ adduser gemini $ usermod -aG sudo gemini ``` As the SSH key is already on the server I can copy it to the non-root user account. ```shell $ rsync --archive --chown=gemini:gemini ~/.ssh /home/gemini ``` On my local system I confirm that I can log in as the new user without a password. ```shell $ ssh gemini@davidtsadler.co.uk -i ~/.ssh/davidtsadler.co.uk/id_rsa ``` I also confirm that I have sudo access. ```shell $ sudo ls ``` ## Installing a Gemini Site and Server ### Directory structure I decided to go with a very simple directory structure. Each site will be a sub-directory in ~/sites that will be named after the domain name. Then each site will have the following sub-directories. The idea is that I may want to host more than one site in the future. * bin This will contain the Gemini server binary. * certs TLS certificates for the site are kept here. * public This will contain the .gmi files of the site. * scripts Contains scripts used to start the Gemini server. I created the directory structure with the below command. ```shell $ mkdir -p ~/sites/davidtsadler.co.uk/{bin,certs,public,scripts} ``` ### Install certificates Sine the Gemini protocol encourages using a self-signed certificate I installed one with the openssl command. ```shell $ openssl req -x509 \ -newkey rsa:4096 \ -keyout ~/sites/davidtsadler.co.uk/certs/key.rsa \ -out ~/sites/davidtsadler.co.uk/certs/cert.pem \ -days 3650 \ -nodes \ -subj "/CN=davidtsadler.co.uk" ``` ### Create Some Test Content I created a very simple index.gmi file purely for testing. ```shell $ cat << EOF > ~/sites/davidtsadler.co.uk/public/index.gmi # Welcome Hello world! EOF ``` ### Install the Gemini Server Binary I decided to go with agate as the Gemini server as its very simple to install and configure. Installing it was a matter of downloading the binary archive into the bin directory and setting the executable permission on it. ```shell $ cd ~/sites/davidtsadler.co.uk/bin $ wget https://github.com/mbrubeck/agate/releases/download/v2.3.0/agate.x86_64-unknown-linux-gnu.gz $ gunzip agate.x86_64-unknown-linux-gnu.gz $ mv agate.x86_64-unknown-linux-gnu agate $ chmod u+x agate ``` I wrote a very simple bash script to run agate and have it serve the site. ```shell $ cat << EOF > ~/sites/davidtsadler.co.uk/scripts/start #!/bin/bash /home/gemini/sites/davidtsadler.co.uk/bin/agate \ --content /home/gemini/sites/davidtsadler.co.uk/public/ \ --key /home/gemini/sites/davidtsadler.co.uk/certs/key.rsa \ --cert /home/gemini/sites/davidtsadler.co.uk/certs/cert.pem \ --addr [::]:1965 \ --addr 0.0.0.0:1965 \ --hostname davidtsadler.co.uk \ --lang en-GB EOF $ chmod u+x ~/sites/davidtsadler.co.uk/scripts/start ``` ### Testing the Site At this point I have the Gemini server installed and a site available for testing. I first started agate with the bash script. ```shell $ ~/sites/davidtsadler.co.uk/scripts/start [2021-02-05T17:26:56Z INFO agate] Listening on [[::]:1965, 0.0.0.0:1965]... ``` With agate up and running I pointed my Gemini client to gemini://davidtsadler.co.uk and confirmed I was able to access the site before entering Ctrl-C to halt agate. ### Configure Systemd Since I was happy that agate was able to serve my new site I created a systemd unit to ensure that agate was started whenever the system was rebooted. ```shell $ sudo vim /etc/systemd/system/agate.service ``` The unit is very simple and just runs the bash script to start agate once the network is available. ``` [Unit] Description=Agate Gemini Server After=network.target [Service] Type=simple User=gemini Group=gemini ExecStart=/home/gemini/sites/davidtsadler.co.uk/scripts/start [Install] WantedBy=default.target ``` I then started this service and confirmed it was working. ``` $ sudo systemctl start agate.service $ sudo systemctl status agate.service Active: active (running) ``` The final step was to have this service start when the system is rebooted. ``` $ sudo systemctl enable agate.service ``` ## Conclusion Setting up a Gemini site was easy to do and I hope this guide shows it. I have several ideas about how I'm going to use this new site and I'm excited to see where this leads to. ### Links => https://www.gandi.net/ Gandi.net - My domain registrar of choice. => https://hetzner.cloud/?ref=Gf3UFbRaixBK Hetzner - My cloud server provider. => https://github.com/mbrubeck/agate/ Agate - A simple Gemini server. => gemini://davidtsadler.co.uk/ davidtsadler.co.uk - My Gemini site. => /posts/gemini/ Gemini - Read More Posts. I don't have comments as I don't want to manage them. You can however contact me at the below address if you want to. => mailto:david@davidtsadler.com Email david@davidtsadler.com => https://creativecommons.org/licenses/by-sa/4.0/ The contents of this site is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. Copyright © 2021 David T. Sadler. => / Return to Homepage.