summaryrefslogtreecommitdiff
path: root/src/posts/gemini/2021-02-08/how-to-host-your-own-gemini-site-in-the-cloud/index.gmi
blob: 5e8768c155ead2cf028520ef0bfcb36e1a8cb35e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# 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.