💾 Archived View for gemini.sh0.xyz › setup.gmi captured on 2024-05-12 at 14:53:09. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-03-20)
-=-=-=-=-=-=-
I've updated my setup, now supporting multiple sites on the same server. You can still see my very simple setup here.
I am still running syncthing to give access to my files on my laptop, phone and anywhere else I want to be. A little bit of work needs to be done to make the files hostable, changing owner and permissions. All this is done by tracking when changes occur.
#!/bin/sh # # /usr/local/bin/sync-gemini.sh if [ $# -ne 1 ]; then echo "Supply instance name" exit 1 fi SRC_DIR="/var/syncthing/gemini-$1" DST_DIR="/usr/local/gemini-$1" ACTIONS="create,delete,move,modify" while : do if inotifywait -rq -e ${ACTIONS} "${SRC_DIR}" 2>&1 1>/dev/null; then sleep 5 # To allow for other changes rsync -avh "${SRC_DIR}/" "${DST_DIR}/" --delete chown -R molly:whell "${DST_DIR}" chmod -R 777 "${DST_DIR}" fi done
I then created a systemd unit file that supports multiple instances: `gemini-sync@.service`
[Unit] Description=Gemini Sync After=network.target [Service] Type=simple Restart=always User=molly ExecStart=/usr/local/bin/sync-gemini %i [Install] WantedBy=multi-user.target
I'm running molly-brown as my gemini server. Configuration is pretty straight forward, just use the default config and fill in your details. But since I'm running multiple instances I create a config file per instance `/etc/molly-<instance>.conf`. Each needs its own port, none of which use 1965. Using nginx we can proxy incoming requests to the correct instance depending on the SSL request.
The molly-brown service unit file: `molly-brown@.service`
[Unit] Description=Molly Brown gemini server After=network.target [Service] Type=simple Restart=always User=molly ExecStart=/usr/local/bin/molly-brown -c /etc/molly-%i.conf [Install] WantedBy=multi-user.target
My `nginx.conf` file.
load_module /usr/lib/nginx/modules/ngx_stream_module.so; user www-data; worker_processes 1; pid /var/run/nginx.pid; events { worker_connections 1024; } http { server_names_hash_bucket_size 128; # For Matrix and Certbot include /etc/nginx/config-enabled/*.conf; include /etc/nginx/sites-enabled/*.conf; } stream { # connection-limiting limit_conn_zone $binary_remote_addr zone=addr:10m; limit_conn_log_level warn; limit_conn addr 1; # logging log_format basic '$remote_addr $upstream_addr [$time_local] ' '$protocol $status $bytes_sent $bytes_received ' '$session_time'; access_log /var/log/nginx/gemini.access.log basic; error_log /var/log/nginx/error.log warn; # map SNI -> backend service map $ssl_preread_server_name $name { gemini.sh0.xyz sh0; ad0qm.com ad0qm; } # Gemini server { listen 1965; ssl_preread on; proxy_buffer_size 16k; # pass requests directly to the corresponding Gemini server proxy_pass $name; } upstream ad0qm { server 127.0.0.1:1966; } upstream sh0 { server 127.0.0.1:1967; } }
Add entries to the map and an upstream for each server you want to connect. Once the multiple instances are running and nginx starts up you can hitt the different capsules based on their domain name.
I use Kineto for proxying my capsule to HTTP. Again with multiple instances means a service setup that supports multiple instances. `kineto@.service`
[Unit] Description=Kineto Gemini to HTTP Proxy After=network.target [Service] Type=simple Restart=always User=molly EnvironmentFile=/etc/kineto-%i.conf ExecStart=/usr/local/bin/kineto-wrapper [Install] WantedBy=multi-user.target
The wrapper script handles the optional arguments supplied in the config file.
#!/bin/sh # # /usr/local/bin/kineto-wrapper if [ -z "${GEMINI_URL}" ]; then printf "Missing config GEMINI_URL\n" 1>&2 exit 1 fi ARGS="" if [ ! -z "${BIND}" ]; then ARGS="${ARGS} -b ${BIND}" fi if [ ! -z "${CSS_FILE}" ]; then ARGS="${ARGS} -s ${CSS_FILE}" fi if [ ! -z "${CSS_URL}" ]; then ARGS="${ARGS} -e ${CSS_URL}" fi eval "/usr/local/bin/kineto ${ARGS} ${GEMINI_URL}"
The last step is setting up the per site configuration in nginx to proxy all https reqeusts to kineto. Make sure the proxy_pass path points to the right kineto instance.
server { server_name gemini.sh0.xyz; location / { proxy_pass http://localhost:8081/; proxy_buffering off; proxy_set_header X-Real-IP $remote_addr; } access_log /var/log/nginx/gemini.sh0.xyz.access.log; error_log /var/log/nginx/gemini.sh0.xyz.error.log error; listen [::]:443 ssl ipv6only=on; # managed by Certbot listen 443 ssl; # managed by Certbot ssl_certificate /usr/local/etc/letsencrypt/live/sh0.xyz/fullchain.pem; # managed by Certbot ssl_certificate_key /usr/local/etc/letsencrypt/live/sh0.xyz/privkey.pem; # managed by Certbot include /usr/local/etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /usr/local/etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot } server { if ($host = gemini.sh0.xyz) { return 301 https://$host$request_uri; } # managed by Certbot listen 80; listen [::]:80; server_name gemini.sh0.xyz; return 404; # managed by Certbot }
I wrote a simple atom.xml cgi script that just expects the first header to be the title and a `Published:` and `Updated:` line towards the top of the file to define its date and time of publishing.
# Title of my post Published: 2022-10-01 08:42 Updated: 2022-10-01 11:30 Lorem ipsem...
I've written a cgi script but I'm a little worried about how much it depends on the server side to be working correctly. Change time stamps on files and magically they get republished. Will be looking into being able to store off the current file and checking if anything is new, maybe then moving to a dynamic method. But for the time being I just maintain an atom.xml file by hand.