Hello, all! Thought I’d share something I’ve been working on for the past few days. First, a little backstory:
When self-hosting software at home, I’ve been using either Caddy or Traefik for as my reverse proxy. I don’t like Traefik (For reasons we won’t go into here) and Caddy was having some weird issue where I couldn’t push more than 150Mb on my 2.5Gb network…
That leads me to my, now Guix-ified, solution:
(define-syntax nginx-certbot-config
(syntax-rules ()
((_ domain host nginx-var certbot-var #:extra-config extra-config)
(begin
(define nginx-var
(nginx-server-configuration
(server-name `(,domain))
(listen '("443 ssl"))
(ssl-certificate (string-append "/etc/certs/" domain "/fullchain.pem"))
(ssl-certificate-key (string-append "/etc/certs/" domain "/privkey.pem"))
(locations
(list
(nginx-location-configuration
(uri "/")
(body (append (list (string-append "proxy_pass " host ";"))
extra-config)))))
(raw-content extra-config)))
(define certbot-var
(certificate-configuration
(domains (list domain))))))
((_ domain host nginx-var certbot-var)
(nginx-certbot-config domain host nginx-var certbot-var
#:extra-config '()))))
What it does:
- Creates an nginx-server-configuration that points to the certificates at /etc/certs// and allows for extra body config (For headers and such)
- Creates a certificate-configuration pointed at the same domain
- Sets two variables equal to each of the configs, ready for export
Don’t worry about http-to-https redirect, Guix has that covered for free.
Here’s an example (With added bonus oci-container-service-type config for searxng):
(define-module (momo services searxng)
#:use-module (gnu services docker)
#:use-module (gnu services)
#:use-module (gnu services web)
#:use-module (gnu services certbot)
#:use-module (momo nginx-certbot-config)
#:export (searxng-service
searxng-nginx-config
searxng-certbot-config))
(define searxng-service
(service oci-container-service-type
(list
(oci-container-configuration
(image "paulgoio/searxng:production")
(requirement '(searxng-redis))
(provision "searxng")
(ports
'("8083:8080"))
(environment
'(("PUBLIC_INSTANCE" . "true")
("LIMITER" . "true")
("REDIS_URL" . "redis://searxng-redis:6379/0")
("IMAGE_PROXY" . "true")
("UWSGI_WORKERS" . "8")
("UWSGI_THREADS" . "4")
("BASE_URL" . "https://search.example.com")
("NAME" . "My Personal Search")
("SEARCH_DEFAULT_LANG" . "en-US")
("SEARCH_ENGINE_ACCESS_DENIED" . "60")))
(network "backend")
(extra-arguments
'("--cap-drop=ALL"
"--cap-add=NET_ADMIN"
"--cap-add=SETGID"
"--cap-add=SETUID"
"--log-driver=json-file"
"--log-opt=max-size=1m"
"--log-opt=max-file=1")))
(oci-container-configuration
(image "redis:alpine")
(provision "searxng-redis")
(command '("redis-server" "--save" "" "--appendonly" "no"))
(network "backend")
(extra-arguments
'("--tmpfs=/var/lib/redis"
"--cap-drop=ALL"
"--cap-add=SETGID"
"--cap-add=SETUID"
"--cap-add=DAC_OVERRIDE"))))))
(nginx-certbot-config "search.example.com" "http://localhost:8083"
searxng-nginx-config searxng-certbot-config)
As you can see, lots of boilerplate reduction.
Example usage in config.scm:
(service nginx-service-type
(nginx-configuration
(server-blocks
(list
searxng-nginx-config))))
(service certbot-service-type
(certbot-configuration
(email "email@example.com")
(certificates
(list
searxng-certbot-config))))
Anyhow, I hope this helps anyone interested in getting your one-stop shop reverse proxying in Guix. On one final note: I have been getting a lot of troubleshooting in on the oci-container-type in this last week, feel free to drop me a DM or if enough interest is shown, I’ll put up a GitHub with some definitions I’ve been playing with.