123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 | # httpd(8) configuration for a Repo Renderer site, for OpenBSD 8.0 or later
# (which can set response headers).
#
# Copy it to /etc/repo-render/httpd.conf and edit it for your site:
#
# - change code.example.com in the server line to your host name
# - if your site has other names, add an alias line for each
# - if you don't use a private site, delete its section below
# - if /etc/httpd.conf already has a types block, delete the one here
#
# The paths are inside httpd's chroot, /var/www, so "/htdocs/repo-render"
# is the renderer's htdocs, /var/www/htdocs/repo-render. If you put the
# site somewhere else, change root, errdocs and the private site's root to
# match.
#
# Then add this line to /etc/httpd.conf, and check and reload httpd:
#
# include "/etc/repo-render/httpd.conf"
#
# httpd -n && rcctl reload httpd
#
# httpd takes the first location that matches a request, and only that
# one, so a rule you add goes in the existing location for its path. Keep
# the headers: the pages carry no Content Security Policy of their own,
# and the sandbox policy on /raw and /svg stops a repository's own HTML
# and SVG from running as part of the site.
# httpd allows one types block in all: take this out if /etc/httpd.conf
# has one. It gives raw files their real types (.webp, .pdf, …).
types {
include "/usr/share/misc/mime.types"
}
server "code.example.com" {
# alias "other.example.com" # other names for the site
listen on * port 8080 # plain HTTP, for relayd(8) to forward to
log style forwarded # log the client relayd passes on
root "/htdocs/repo-render"
default type text/plain
errdocs "/htdocs/repo-render/err"
gzip-static # serve the renderer's .gz twins
header set "X-Content-Type-Options" "nosniff" always
header set "Referrer-Policy" "no-referrer" always
header set "Content-Security-Policy" "default-src 'none'; style-src 'self'; img-src 'self'; script-src 'self'; connect-src 'self'; worker-src 'self'; frame-src 'self'; frame-ancestors 'self'" always
# acme-client(1)'s challenges, for the certificates relayd serves.
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
# ---- the private site: delete down to "end of the private site" if
# you don't set private_htdocs. It is the public rules again under
# /private/, behind a login from htpasswd(1)'s file, and cached by the
# browser alone. The last location keeps everything else under
# /private/ behind the login too.
location match "^/private/code/(..-)/?$" {
authenticate "Private repositories" with "/conf/repo-render.htpasswd"
root "/private/repo-render"
request rewrite "/private/code/%1.html"
}
location match "^/private/types/(..-)/?$" {
authenticate "Private repositories" with "/conf/repo-render.htpasswd"
root "/private/repo-render"
request rewrite "/private/types/%1.html"
}
location "/private/search/*/corpus.json" {
authenticate "Private repositories" with "/conf/repo-render.htpasswd"
root "/private/repo-render"
header set "Cache-Control" "private, max-age=31536000, immutable"
}
location "/private/raw/*" {
authenticate "Private repositories" with "/conf/repo-render.htpasswd"
root "/private/repo-render"
no gzip-static
header set "Content-Security-Policy" "sandbox" always
}
location "/private/svg/*" {
authenticate "Private repositories" with "/conf/repo-render.htpasswd"
root "/private/repo-render"
header set "Content-Security-Policy" "sandbox" always
}
location "/private/snapshot/*" {
authenticate "Private repositories" with "/conf/repo-render.htpasswd"
root "/private/repo-render"
header set "Cache-Control" "private, max-age=31536000, immutable"
}
location "/private/git/*/objects/pack/*" {
authenticate "Private repositories" with "/conf/repo-render.htpasswd"
root "/private/repo-render"
header set "Cache-Control" "private, max-age=31536000, immutable"
}
location "/private/*" {
authenticate "Private repositories" with "/conf/repo-render.htpasswd"
root "/private/repo-render"
}
# ---- end of the private site
# Pages have no .html in their URLs: /code/r/src and /code/r/src/ are
# code/r/src.html (and /code/r/foo.html is foo.html.html).
location match "^/code/(..-)/?$" {
request rewrite "/code/%1.html"
}
location match "^/types/(..-)/?$" {
request rewrite "/types/%1.html"
}
# What is named by its contents is cached for good; everything else
# gets httpd's default, no-cache, so no page outlives a push.
location "/search/*/corpus.json" {
header set "Cache-Control" "public, max-age=31536000, immutable"
}
location "/static/*" {
header set "Cache-Control" "public, max-age=31536000, immutable"
}
# The repositories' own files, byte for byte, and themed SVGs. With
# gzip-static off, a request for foo gets foo even when the repository
# also has a foo.gz.
location "/raw/*" {
no gzip-static
header set "Content-Security-Policy" "sandbox" always
}
location "/svg/*" {
header set "Content-Security-Policy" "sandbox" always
}
# A branch's latest tarball is named by its commit, so it is cached for
# good. A tag can move, so its tarball, in /archive/, keeps the default.
location "/snapshot/*" {
header set "Cache-Control" "public, max-age=31536000, immutable"
}
# The clone export, for dumb-HTTP clones; packs are named by their
# contents.
location "/git/*/objects/pack/*" {
header set "Cache-Control" "public, max-age=31536000, immutable"
}
}
|