root/captcha.scm

(define-module (hidamari-blue captcha)
  #:use-module (guix packages)
  #:use-module (guix download)
  #:use-module (guix records)
  #:use-module (ice-9 match)
  #:use-module (guix gexp)
  #:use-module (gnu services)
  #:use-module (gnu services shepherd)
  #:use-module (gnu services web)
  #:use-module (gnu system shadow)
  #:use-module (gnu packages admin)
  #:use-module (gnu packages web)
  #:use-module (gnu packages base)
  
  #:use-module (guix build-system gnu)
  #:use-module ((guix licenses) #:prefix license:)
  #:use-module (gnu packages guile)
  #:export (captcha-configuration
	    captcha
	    captcha-service-type
	    captcha-nginx-block))

(define captcha
  (package
   (name "captcha")
   (version "0.2")
   (source (origin
            (method url-fetch)
            (uri (string-append "https://hidamari.blue/git/captcha/release/captcha-" version
                                ".tar.bz2"))
            (sha256
             (base32
              "0wpnpnxvf3469y2c8vi7avg2qckzbbylbddvqqzrg0dw576lgjwj"))))
   (build-system gnu-build-system)
   (arguments
    `(#:phases
      (modify-phases
       %standard-phases
       (delete 'configure)
       ;; TODO build with autotools
       (delete 'build)
       (delete 'check)
       (replace
        'install
        (lambda*
	 (#:key outputs #:allow-other-keys)
	 (define out (string-append (assoc-ref %outputs "out")))

	 (call-with-output-file "run-captcha.sh"
	   (lambda (port)
	     (display
	      (string-append
	       "#!" (which "sh") "\n"
	       "GUILE_LOAD_COMPILED_PATH=" (getenv "GUILE_LOAD_COMPILED_PATH")
	       " GUILE_LOAD_PATH=" (getenv "GUILE_LOAD_PATH")
	       " " (which "guile") "--no-auto-compile -L " out " -e main-fibers"  " -s " out "/main.scm")
	      port)))
	 (chmod "run-captcha.sh" #o555)
		 
          (copy-recursively "." out)
          #t)))))
   (inputs `(("guile" ,guile-2.2)
	     ("guile-fibers" ,guile-fibers)))
   (native-inputs `(("which" ,which)))
   (synopsis "web captcha server")
   (description "captcha with 2hus")
   (home-page "http://captcha.hidamari-blue")
   (license license:agpl3)))


(define-record-type* <captcha-configuration> captcha-configuration
  make-captcha-configuration
  captcha-configuration?
  (captcha captcha-configuration-captcha ;<package>
	   (default captcha))
  (guile   captcha-configuration-guile ;<package>
	   (default guile-2.2)))

(define captcha-shepherd-service
  (match-lambda
   (($ <captcha-configuration> captcha guile)
    ;; TODO get user from config user 
     (let ((user "captcha")
	   (group "captcha"))
       (list (shepherd-service
		      (provision '(captcha))
		      (documentation "Run the captcha web service.")
		      (requirement '(networking))
		      (start #~(make-forkexec-constructor
				'(;; #$(file-append guix "/bin/guix" "environment" "captcha" "--")
				  ;; #$(file-append guile "/bin/guile")
				  ;;   "-L" #$captcha
				  ;;   "-e" "main-fibers"
				  ;;   "-s"
				  ;;   #$(file-append captcha "/main.scm")
				  #$captcha "/run-captcha.sh"
				    )
				#:user #$user #:group #$group))
		      (stop #~(make-kill-destructor))))))))

(define (captcha-accounts _)
  (filter identity
	  (list
	   (user-group
	    (name "captcha")
	    (system? #t))
	   (user-account
	    (name "captcha")
	    (group "captcha")
	    (system? #t)
	    (comment "web captcha user")
	    (home-directory "/var/empty")
	    (shell (file-append shadow "/sbin/nologin"))))))

(define (captcha-nginx-block site-domain)
  ;; TODO custom paths and ssl
  (nginx-server-configuration
   (server-name (list site-domain))
   (root "/var/www/captcha/")
   ;; (http-port #f)
   (ssl-certificate
    "/etc/letsencrypt/live/captcha.hidamari.blue/fullchain.pem")
   (ssl-certificate-key
    "/etc/letsencrypt/live/captcha.hidamari.blue/privkey.pem")
   (server-tokens? #f)
   (locations
    (list
     (nginx-location-configuration
      (uri "/file")
      (body (list "alias /var/www/captcha/file;")))
     (nginx-location-configuration
      (uri "/private")
      (body (list "deny all;")))
     (nginx-location-configuration
      (uri "/")
      (body (list
	     "if ($scheme = http) {"
	     "    return 301 https://$host$request_uri;"
	     "}"
	     "proxy_pass http://127.0.0.1:8084;"
	     "proxy_set_header Host $host;"
	     "proxy_set_header X-Real-IP $remote_addr;"
	     "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;")))))))

(define captcha-service-type
  (service-type (name 'captcha)
                (extensions
                 (list (service-extension shepherd-root-service-type
                                          captcha-shepherd-service)
		       ;; TODO write init/activation extension for captcha-population
		       (service-extension account-service-type
                                          captcha-accounts)
		       ))
                (default-value (captcha-configuration))))