Server Configuration (Deployment) Template for Hetzner Cloud

I thought I share a PantherX server configuration for a typical Node.js application:

  • NGINX (Certificates via Certbot)
  • Redis server
  • Open ports: 20, 80, 443
  • Authorized key for root and user

A config like this can be deployed with guix deploy server-config.scm in as little as 5 minutes.

;; PantherX OS Server deployment template
;; for Digital Ocean
;; Services: Redis, Nginx
;; Firewall: 22, 80, 443

;; Init via script in repo: px-install/

(use-modules (gnu)
	     (gnu system)
	     (srfi srfi-1)
	     (px system)
	     (gnu packages tls)
	     (gnu packages base)
	     (gnu packages node)
	     (gnu packages python)
	     (gnu packages databases)
	     (gnu packages networking)
	     (gnu packages commencement)
	     (gnu packages version-control)
	     (px system install)
	     (px packages databases)
	     (px packages device)
	     (px services device))

(use-service-modules databases networking web certbot)

(define %ssh-public-key
  "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP7gcLZzs2JiEx2kWCc8lTHOC0Gqpgcudv0QVJ4QydPg franz")

(define (cert-path host file)
  (format #f "/etc/letsencrypt/live/~a/~a.pem" host (symbol->string file)))

(define %nginx-deploy-hook
   #~(let ((pid (call-with-input-file "/var/run/nginx/pid" read)))
       (kill pid SIGHUP))))

(define %custom-server-services
  (modify-services %px-server-services
		   (guix-service-type config =>
                                       (inherit config)
					(append (list (local-file "/etc/guix/"))

(define %system
    (host-name "domain")
    (timezone "Europe/Berlin")
    (locale "en_US.utf8")
    (bootloader (bootloader-configuration
		 (bootloader grub-bootloader)
		 (target "/dev/sda")))
    (initrd-modules (append (list "virtio_scsi")
    (file-systems (append
		   (list (file-system
			  (mount-point "/")
			  (device "/dev/sda1")
			  (type "ext4")))

    (swap-devices '("/swapfile"))

    ;; Users
    (users (cons (user-account
		  (name "panther")
		  (comment "panther's account")
		  (group "users")
		  (supplementary-groups '("wheel"))
		  (home-directory "/home/panther"))
    ;; Packages
    (packages (cons* node-lts git
		     python gcc-toolchain
    ;; Services
    (services (cons*
	       ;; Database
	       (service redis-service-type)
	       ;; SSL Certificates
	       (service certbot-service-type
			 (email "")
			    (domains '(""))
			    (deploy-hook %nginx-deploy-hook))))))
	       ;; Web server
	       (service nginx-service-type
			    (server-name '(""))
			    (listen '("80"))
			    (root "/var/www")
			    (raw-content '("return 301 https://$host$request_uri;")))
			    (server-name '(""))
			    (listen '("443 ssl"))
			    (ssl-certificate (cert-path "" 'fullchain))
			    (ssl-certificate-key (cert-path "" 'privkey))
			       (uri "/")
				 "proxy_set_header X-Real-IP $remote_addr;"
				 "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;"
				 "proxy_set_header X-Forwarded-Proto $scheme;"
				 "proxy_redirect off;"
				 "proxy_pass http://localhost:3000;"
				 "proxy_http_version 1.1;"
				 "proxy_set_header Upgrade $http_upgrade;"
				 "proxy_set_header Connection 'upgrade';"
				 "proxy_set_header Host $host;"
				 "proxy_cache_bypass $http_upgrade;"))))))))))
   #:open-ports '(("tcp" "ssh" "80" "443"))
   #:authorized-keys `(("root" ,(plain-file "" %ssh-public-key))
		       ("panther" ,(plain-file "" %ssh-public-key)))

(list (machine
       (operating-system %system)
       (environment managed-host-environment-type)
       (configuration (machine-ssh-configuration
		       (host-name "")
		       (system "x86_64-linux")
		       (user "root")
		       (identity "id_rsa")
		       (port 22)
		       (allow-downgrades? #t)))))