summaryrefslogtreecommitdiff
path: root/source/_posts
diff options
context:
space:
mode:
authorDavid T. Sadler <davidtsadler@googlemail.com>2021-02-07 23:26:24 +0000
committerDavid T. Sadler <davidtsadler@googlemail.com>2021-02-07 23:26:24 +0000
commitf2fa60c447aaf0548b1e624eeee7fb1519776ba4 (patch)
treef71305b9cb18f061dcfbd9755e134e8b5da98160 /source/_posts
parentcc7167fb6afbfa1079e5da4d0e559e575e8c3313 (diff)
Add How to Host Your Own Gemini Site in the Cloud
Diffstat (limited to 'source/_posts')
-rw-r--r--source/_posts/how_to_host_your_own_gemini_site_in_the_cloud.md300
1 files changed, 300 insertions, 0 deletions
diff --git a/source/_posts/how_to_host_your_own_gemini_site_in_the_cloud.md b/source/_posts/how_to_host_your_own_gemini_site_in_the_cloud.md
new file mode 100644
index 0000000..b53fdc7
--- /dev/null
+++ b/source/_posts/how_to_host_your_own_gemini_site_in_the_cloud.md
@@ -0,0 +1,300 @@
+---
+extends: _layouts.post
+section: content
+title: How to Host Your Own Gemini Site in the Cloud
+date: 2021-02-15
+description: A guide to setting up a cloud server to host a Gemini site.
+tags: [Gemini]
+---
+
+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 Sytemd
+
+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
+
+- [Gandi.net](https://www.gandi.net) My domain registrar of choice.
+- [Hetzner](https://hetzner.cloud/?ref=Gf3UFbRaixBK) My cloud server provider.
+- [Agate](https://github.com/mbrubeck/agate) A simple Gemini server.
+- [davidtsadler.co.uk](gemini://davidtsadler.co.uk) My Gemini site.