💾 Archived View for yuki.social › notes › 2022-07-12-vger-systemd-nginx.gmi captured on 2023-05-24 at 17:44:06. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-01-29)
-=-=-=-=-=-=-
Vger is a secure Gemini server I recently switched to to serve my Gemini content. So why is it secure? It only does what it needs to do. Get a request from stdin, chroot in your gemini directory, send the file back to stdout. The socket thing and TLS are left as an excercise to the sysadmin.
More on this on the author's blog
Vger was intended to be used with inetd and be compatible with BSD, but if you're on Linux, you likely use systemd (love or hate it) and so you can leverage its security powers. It's pretty much inetd on steroids.
So the workflow here is:
Here's the config files I use:
/etc/systemd/system/vger@.service
[Unit] Description=vger gemini server Requires=vger.socket [Service] Type=simple ExecStart=-/usr/bin/vger -d /srv/gemini/ -v -i # see man vger # Set which user you want to run it as, or a random dynamic one User=http # DynamicUser=yes # very important so it goes to the socket StandardInput=socket StandardOutput=socket StandardError=journal # you can also set null here # most of these are useless since vger takes cares about getting itself in a chroot but these instructions works for literally everything ProtectHome=true PrivateUsers=true ProtectSystem=strict # Implied by DynamicUser=yes PrivateTmp=true # Also implied by DynamicUser=yes # read the systemd manpages, there's a ton of security features in there [Install] WantedBy=multi-user.target
Now create the socket service:
/etc/systemd/system/vger.socket
[Socket] ListenStream=/run/vger.socket # could be a port number but an AF_UNIX socket is better Accept=yes [Install] WantedBy = sockets.target
We can then use nginx to manage connections from port 1965 and encrypt them with TLS. Be sure to change the ssl_certificate paths if you don't have a Let's Encrypt certificate for every domain you want to serve, and make sure you don't put this inside a http block.
/etc/nginx/nginx.conf
stream { server { listen 1965 ssl; listen [::]:1965 ssl; ssl_certificate /etc/letsencrypt/live/$ssl_server_name/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/$ssl_server_name/privkey.pem; proxy_pass unix:/run/vger.socket; } }
Now launch your services...
sudo systemctl enable vger.socket sudo systemctl start vger.socket sudo systemctl reload nginx
...et voilà, you have a Gemini capsule in the geminisphere, or whatever kids call it these days.
From here, the sky's the limit: you can create a socket for every virtualhost you want to serve and use $ssl_server_name to point to different sockets and certificates, maybe even make use of ALPN to serve HTTPS on the same port? Be creative!
Stay tuned for part 2 where I create a Gemini client to solve all of your problems! Maybe even a part 3 where I abuse ALPN? Who knows! Anyway, hope you liked this.
--Yuki