diff --git a/README.md b/README.md index b253773..d92942d 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,53 @@ You will need to install the following Racket packages: raco pkg install reloadable +## Configuration + +See the directory `configs/` for example configuration files. To +select a configuration file, set the environment variable `CONFIG` to +its base filename. For example, to select `configs/live.rkt`, set +`CONFIG` to `live`. A good place to do this is in the `run-prelude` +file; see the description of `run-prelude` below. + +If `CONFIG` is not set, it defaults to the short hostname of the +machine (`hostname -s`). + +Within a configuration file, configuration details are to be given as +a hashtable to `main`. + +Keys useful for deployment: + + - *port*: number; default the value of the `SITE_PORT` environment + variable, if defined; otherwise, 8443. + - *ssl?*: boolean; default `#t`. + - *reloadable?*: boolean; `#t` if the `SITE_RELOADABLE` environment + variable is defined; otherwise, `#f`. + - *recent-seconds*: number, in seconds; default 172800. Packages + modified fewer than this many seconds ago are considered "recent", + and displayed as such in the UI. + +Keys useful for development: + + - *package-index-url*: string; default + `http://pkgs.racket-lang.org/pkgs-all.json.gz`. + - *package-fetch-interval*; number, in seconds; default 300. + - *session-lifetime*: number, in seconds; default 604800. + - *static-cached-directory*: string; names a directory relative to + `src/` within which generated static HTML files are to be placed. + Must be writable by the user running the server. + - *static-cached-urlprefix*: string; absolute or relative URL, + prepended to relative URLs referring to generated static HTML files + placed in `static-cached-directory`. + - *disable-cache?*: boolean; default `#f`. + - *backend-baseurl*: string; default `https://pkgd.racket-lang.org`. + Must point to the backend package server API root, such that (for + example) `/jsonp/authenticate`, when appended to it, resolves to + the authentication call. + - *pkg-build-baseurl*: string; default + `http://pkg-build.racket-lang.org/`. Used to build URLs relative to + the package build host, for such as documentation links and build + reports. + ## Local testing You will need some dummy SSL keys. Run `make keys` to produce some. @@ -19,8 +66,8 @@ compiles the code and starts the server. ### Automatic code reloading If you would like to enable the automatic code-reloading feature, set -the environment variable `SITE_RELOADABLE` to a non-empty string. (A -good place to do that is in a `run-prelude` script; see below.) +the environment variable `SITE_RELOADABLE` to a non-empty string or +set the `reloadable?` configuration variable to `#t`. You must also delete any compiled code `.zo` files. Otherwise, the system will not be able to correctly replace modules while running. @@ -44,7 +91,8 @@ logging of stdout/stderr. If the file `run-prelude` exists in the same directory as `run`, it will be dotted in before racket is invoked. I use this to update my `PATH` to include my locally-built racket `bin` directory, necessary -because I don't have a system-wide racket. +because I don't have a system-wide racket, and to select an +appropriate `CONFIG` setting. On Debian, daemontools can be installed with `apt-get install daemontools daemontools-run`, and the services directory is @@ -61,6 +109,17 @@ You can send signals to the running service by creating files in - creating `.restart-required` causes it to exit, to be restarted by daemontools. + - creating `.reload` causes an explicit code reload. Useful when + automatic code reloading is disabled. + + - creating `.fetchindex` causes an immediate refetch of the package + index from the backend server. + + - creating `.rerender` causes an immediate rerendering of all + generated static HTML files. + +See `src/signals.rkt` for details of the available signals. + So long as `sudo chmod 0777 /etc/service/webservice/signals`, these are useful for non-root administrators to control the running service. diff --git a/configs/live.rkt b/configs/live.rkt new file mode 100644 index 0000000..b20681e --- /dev/null +++ b/configs/live.rkt @@ -0,0 +1,4 @@ +#lang racket/base +;; Default configuration; should be suitable for live deployment. +(require "../src/main.rkt") +(main) diff --git a/configs/tonyg.rkt b/configs/tonyg.rkt new file mode 100644 index 0000000..03b82ea --- /dev/null +++ b/configs/tonyg.rkt @@ -0,0 +1,6 @@ +#lang racket/base +;; Configuration for tonyg's development setup. +(require "../src/main.rkt") +(main (hash 'port 8444 + 'reloadable? #t + )) diff --git a/run b/run index 4ff2141..bc08897 100755 --- a/run +++ b/run @@ -1,7 +1,19 @@ #!/bin/sh + if [ -f ./run-prelude ]; then . ./run-prelude; fi -cd src + +if [ -z "$CONFIG" ]; then + CONFIG=$(hostname -s) + echo 'Environment variable CONFIG not defined; defaulting to "'"${CONFIG}"'"' +fi + +if [ ! -f configs/${CONFIG}.rkt ]; then + echo "Config ${CONFIG} not found: config/${CONFIG}.rkt not readable" + exit 1 +fi + PLTSTDERR=info export PLTSTDERR echo '=============================================' -exec racket main.rkt 2>&1 +cd src +exec racket ../configs/${CONFIG}.rkt 2>&1 diff --git a/src/config.rkt b/src/config.rkt new file mode 100644 index 0000000..c656d19 --- /dev/null +++ b/src/config.rkt @@ -0,0 +1,9 @@ +#lang racket/base + +(provide config) + +(require reloadable) + +(define *config* (make-persistent-state '*config* (lambda () config))) + +(define (config) (*config*)) diff --git a/src/main.rkt b/src/main.rkt index fe24ecd..5b5a9e6 100644 --- a/src/main.rkt +++ b/src/main.rkt @@ -1,11 +1,18 @@ #lang racket/base -(module+ main - (require "entrypoint.rkt") +(provide main) + +(require reloadable) +(require "entrypoint.rkt") + +(define (main [config (hash)]) + (make-persistent-state '*config* (lambda () config)) (void (make-reloadable-entry-point 'refresh-packages! "packages.rkt")) (void (make-reloadable-entry-point 'rerender-all! "site.rkt")) - (start-service #:reloadable? (getenv "SITE_RELOADABLE") - #:port (let ((port-str (getenv "SITE_PORT"))) - (if port-str (string->number port-str) 8443)) + (start-service #:port (hash-ref config 'port (lambda () + (let ((port-str (getenv "SITE_PORT"))) + (if port-str (string->number port-str) 8443)))) + #:ssl? (hash-ref config 'ssl? (lambda () #t)) + #:reloadable? (hash-ref config 'reloadable? (lambda () (getenv "SITE_RELOADABLE"))) (make-reloadable-entry-point 'request-handler "site.rkt") (make-reloadable-entry-point 'on-continuation-expiry "site.rkt"))) diff --git a/src/packages.rkt b/src/packages.rkt index 2d93304..70409f7 100644 --- a/src/packages.rkt +++ b/src/packages.rkt @@ -27,6 +27,7 @@ (require web-server/private/gzip) (require net/url) (require reloadable) +(require "config.rkt") (require "daemon.rkt") ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -41,8 +42,15 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(define package-index-url "http://pkgs.racket-lang.org/pkgs-all.json.gz") -(define package-fetch-interval (* 300 1000)) ;; 300 seconds = 300,000 milliseconds = 5 minutes +(define package-index-url + (or (@ (config) package-index-url) + "http://pkgs.racket-lang.org/pkgs-all.json.gz")) + +(define package-fetch-interval + (* (or (@ (config) package-fetch-interval) + 300) ;; 300 seconds = 5 minutes + 1000)) ;; convert to milliseconds + (define base-bogus-timeout (* 5 1000)) ;; 5 seconds (struct package-manager-state (local-packages diff --git a/src/sessions.rkt b/src/sessions.rkt index df53200..4a2a6a3 100644 --- a/src/sessions.rkt +++ b/src/sessions.rkt @@ -10,10 +10,14 @@ lookup-session) (require "randomness.rkt") +(require "config.rkt") (require reloadable) (define current-session (make-parameter #f)) -(define session-lifetime (make-parameter (* 7 24 60 60 1000))) ;; one week in milliseconds +(define session-lifetime + (* (or (hash-ref (config) 'session-lifetime-seconds #f) + (* 7 24 60 60)) ;; one week in seconds + 1000)) ;; convert to milliseconds (struct session (key expiry email password) #:prefab) diff --git a/src/site.rkt b/src/site.rkt index fe6b9a0..1564730 100644 --- a/src/site.rkt +++ b/src/site.rkt @@ -22,11 +22,19 @@ (require "jsonp-client.rkt") (require reloadable) (require "daemon.rkt") +(require "config.rkt") -(define static-cached-directory "../static/cached") -(define static-cached-urlprefix "/cached") +(define static-cached-directory + (or (@ (config) static-cached-directory) + "../static/cached")) -(define disable-cache? #f) +(define static-cached-urlprefix + (or (@ (config) static-cached-urlprefix) + "/cached")) + +(define disable-cache? + (or (@ (config) disable-cache?) + #f)) (define nav-index "Package Index") (define nav-search "Search") @@ -44,11 +52,20 @@ ;; "http://download.racket-lang.org/") )) -(define backend-baseurl "https://pkgd.racket-lang.org") +(define backend-baseurl + (or (@ (config) backend-baseurl) + "https://pkgd.racket-lang.org")) (define default-empty-source-url "git://github.com//") (define COOKIE "pltsession") -(define recent-seconds (* 2 24 60 60)) ;; two days + +(define recent-seconds + (or (@ (config) recent-seconds) + (* 2 24 60 60))) ;; two days + +(define pkg-build-baseurl + (or (@ (config) pkg-build-baseurl) + "http://pkg-build.racket-lang.org/")) (struct draft-package (old-name name description authors tags versions) #:prefab) @@ -435,7 +452,7 @@ (define (buildhost-link #:attributes [attributes '()] url-suffix label) `(a (,@attributes - (href ,(format "http://pkg-build.racket-lang.org/~a" url-suffix))) ,label)) + (href ,(format "~a~a" pkg-build-baseurl url-suffix))) ,label)) (define (authors-list authors #:gravatars? [gravatars? #f]) `(ul ((class "authors")) ,@(for/list ((author authors))