server.conf 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. #
  2. # internet-radio-recorder lighttpd configuration
  3. # /usr/share/doc/lighttpd-doc/configuration.txt.gz
  4. #
  5. ##
  6. ## # URLs & Routes
  7. ##
  8. ## / list of everything (HTML)
  9. ##
  10. ## ## Stations
  11. ##
  12. ## /stations/ list of all stations (HTML)
  13. ## /stations/b2/now redirect to current broadcast on station
  14. ## /stations/b2/about.rdf RDF describing the station
  15. ## /stations/b2/app/station.cfg lua table describing the station
  16. ##
  17. ## ## Broadcasts
  18. ##
  19. ## /stations/b2/2009/12/31/1830%20radioMikro logical full address of a single broadcast
  20. ## /stations/b2/2009-12-31T18:35:17+01:00 point in time (=> single broadcast)
  21. ##
  22. ## /stations/b2/2009/12/31/1830%20radioMikro.xml storage of future or current day broadcasts (technical)
  23. ## /stations/b2/2009/12/31/1830%20radioMikro.json podcast/channel (technical)
  24. ## /stations/b2/2009/12/31/index.xml.gz storage of past days' broadcasts (technical)
  25. ## /stations/b2/2009/12/31/index#T1830 anchor of past days' broadcast (technical)
  26. ##
  27. ## /stations/modified.ttl recent changes (current day)
  28. ## /stations/b2/modified.ttl recent changes per station (current day)
  29. ##
  30. ## ## Podcasts / Recording channels
  31. ##
  32. ## /podcasts/ list of all podcasts (HTML)
  33. ## /podcasts/pumuckl/app/podcast.cfg podcast/channel settings
  34. ## /podcasts/pumuckl.rss RSS feed (logical)
  35. ## /podcasts/pumuckl/boradcasts.rss RSS feed (technical)
  36. ## /podcasts/pumuckl/boradcasts.ics iCal calendar
  37. ##
  38. ## /podcasts/pumuckl/b2/2011/08/26/1830%20radioMikro podcast/channel member candidate (logical)
  39. ##
  40. ## ## Enclosures / Recording mp3s
  41. ##
  42. ## /enclosures/b2/2011/08/26/1830%20radioMikro.mp3 past recording (technical)
  43. ## /enclosures/b2/2021/08/26/1830%20radioMikro.pending future recording (technical)
  44. ##
  45. var.baseurl = "/"
  46. var.auth_realm = "Radio Pi"
  47. var.auth_method = "digest"
  48. # for legal reasons mp3 access must be restricted, http://de.wikipedia.org/wiki/Privatkopie#Deutschland :
  49. # see /usr/share/doc/lighttpd/authentication.txt.gz
  50. auth.backend = "htdigest"
  51. auth.backend.htdigest.userfile = "/etc/lighttpd/internet-radio-recorder.user.htdigest"
  52. #
  53. $HTTP["useragent"] =~ "^AppleCoreMedia/.*\((iP)" {
  54. # Workaround for Apples Podcast App.
  55. # 1. does a HEAD request on mp3 with user agent "Podcasts/2.1.2" (auth works if required for HEAD requests)
  56. # 2. does a GET request on mp3 with user agent "AppleCoreMedia/1.0.0.11D257 (iPhone; U; CPU OS 7_1_2 like Mac OS X; de_de)" (strangely drops credentials => auth fails)
  57. # so we just allow all such GET requests :-(
  58. # Really strange is, that PLAYING the mp3 (also agent "AppleCoreMedia/.*\((iPhone)") does properly keep the credentials.
  59. } else $HTTP["useragent"] =~ "^(Podcasts|Instacast)/" {
  60. # require auth for user agent "Podcasts/" for everything (rss+mp3)
  61. auth.require = ( baseurl => (
  62. # see /usr/share/doc/lighttpd/authentication.txt.gz
  63. "method" => auth_method,
  64. "realm" => auth_realm,
  65. "require" => "valid-user",
  66. ), )
  67. } else $HTTP["request-method"] !~ "^(HEAD)$" {
  68. # Allow all HEAD requests, but require auth for all others on 'enclosures'
  69. auth.require = ( baseurl + "enclosures" => (
  70. # see /usr/share/doc/lighttpd/authentication.txt.gz
  71. "method" => auth_method,
  72. "realm" => auth_realm,
  73. "require" => "valid-user",
  74. ), )
  75. }
  76. # http://www.golem.de/news/content-security-policy-schutz-vor-cross-site-scripting-1306-99795.html
  77. setenv.add-response-header = (
  78. # http://www.w3.org/TR/CSP/#example-policies
  79. "Content-Security-Policy" => "default-src 'none'; style-src 'self' 'unsafe-inline'; script-src 'self'; connect-src 'self'; font-src 'self'; img-src *;",
  80. )
  81. # enable directory browsing:
  82. dir-listing.activate = "enable"
  83. dir-listing.encoding = "utf-8"
  84. dir-listing.show-readme = "enable"
  85. # register lua cgi handler:
  86. static-file.exclude-extensions = ( )
  87. cgi.assign = (
  88. ".lua" => "/usr/bin/lua",
  89. ".sh" => "/bin/dash",
  90. )
  91. # recommended: some convenience redirects (internal):
  92. # http://redmine.lighttpd.net/projects/1/wiki/Docs_ModRewrite
  93. url.rewrite-once = (
  94. # .cgi to according suffix:
  95. "^(" + baseurl + "enclosures/app/ad_hoc)\.cgi(.*)$" => "$1.sh$2",
  96. # legacy: podcast ics + rss
  97. "^(" + baseurl + "podcasts)/([^\/]*)\.(ics|rss)$" => "$1/$2/broadcasts.$3",
  98. # consistency: station ics:
  99. "^(" + baseurl + "stations)/([^\/]*)\.(ics)$" => "$1/$2/broadcasts.$3",
  100. )
  101. url.rewrite-if-not-file = (
  102. # proper tech-neutral urls, respond with .xml content
  103. "^(" + baseurl + "stations/[^/]+/\d{4}/\d{2}/\d{2}/(index))$" => "$1.xml.gz",
  104. # proper tech-neutral urls, respond with .xml content
  105. "^(" + baseurl + "stations/[^/]+/\d{4}/\d{2}/\d{2}/(\d{4}%20.+))$" => "$1.xml",
  106. # temporary:
  107. "^" + baseurl + "stations/[^/]+/app/(broadcasts2html\.xslt)$" => "../../../assets/broadcast2html.xslt",
  108. # default station assets
  109. "^" + baseurl + "stations/[^/]+/app/(broadcast2html\.xslt|style\.css)$" => "../../../assets/$1",
  110. )
  111. # required, functional, redirects:
  112. url.redirect = (
  113. # redirect 'now' to cgi:
  114. "^" + baseurl + "stations/([^/]+)/now$" => "../../app/now.lua?station=$1",
  115. # redirect podcast episode markers to regular broadcast page: (.xml for legacy compat)
  116. "^" + baseurl + "podcasts/[^/]+/([^/]+/\d{4}/\d{2}/\d{2}/\d{4}.*?)(\.xml)?$" => baseurl + "stations/$1",
  117. # redirect unfinished enclosure markers to regular broadcast page:
  118. "^" + baseurl + "enclosures/([^/]+/\d{4}/\d{2}/\d{2}/\d{4}.*)\.(pending|ripping|failed|purged)$" => baseurl + "stations/$1",
  119. # convenience
  120. # redirect time-only, non-title URL
  121. "^(" + baseurl + ")stations/([^/]+)/(\d{4})/(\d{2})/(\d{2})/(\d{2})(\d{2})(00)?/?$" => "$1app/now.lua?station=$2&t=$3-$4-$5T$6:$7:00",
  122. "^(" + baseurl + ")stations/([^/]+)/(\d{4})-?(\d{2})-?(\d{2})T?(\d{2}):?(\d{2}):?(\d{2})([+-]\d{2}:?\d{2})" => "$1app/now.lua?station=$2&t=$3-$4-$5T$6:$7:$8$9",
  123. # legacy:
  124. # "^" + baseurl + "[^\/]*/([^\/]*)/app/now\.lua$" => "../../../app/now.lua?station=$1",
  125. # as long as we don't have a proper index.html per day, just use the dir listing:
  126. # "^(" + baseurl + "stations/[^/]*/\d{4}/\d{2}/\d{2}/)index.html$" => "$1",
  127. )
  128. $HTTP["url"] =~ "(\.xml\.gz|/index)$" {
  129. # serve compressed content to be unpacked by client – both for .xml.gz and naked index files
  130. setenv.add-response-header = ( "Content-Encoding" => "gzip")
  131. mimetype.assign = (".xml.gz" => "text/xml; charset=utf-8" )
  132. }
  133. # proper mimetypes + encodings:
  134. mimetype.assign = (
  135. ".cfg" => "text/plain; charset=utf-8",
  136. ".css" => "text/css; charset=utf-8",
  137. ".html" => "text/html; charset=utf-8",
  138. ".ico" => "image/vnd.microsoft.icon",
  139. ".ics" => "text/calendar; charset=utf-8",
  140. ".js" => "text/javascript; charset=utf-8",
  141. ".json" => "application/json; charset=utf-8",
  142. ".log" => "text/plain; charset=utf-8",
  143. ".mp3" => "audio/mpeg",
  144. ".png" => "image/png",
  145. ".svg" => "image/svg+xml",
  146. ".rb" => "text/plain; charset=utf-8",
  147. ".rdf" => "application/rdf+xml; charset=utf-8",
  148. ".rq" => "application/sparql-query",
  149. ".rss" => "application/rss+xml; charset=utf-8",
  150. ".ttl" => "text/turtle; charset=utf-8",
  151. ".txt" => "text/plain; charset=utf-8",
  152. ".xml" => "text/xml; charset=utf-8",
  153. ".xslt" => "text/xml; charset=utf-8",
  154. )
  155. # bandwidth saving:
  156. compress.filetype = (
  157. "application/json",
  158. "application/rdf+xml",
  159. "application/rss+xml",
  160. "application/xslt+xml",
  161. "text/calendar",
  162. "text/css",
  163. "text/html",
  164. "image/svg+xml",
  165. "text/javascript",
  166. "text/plain",
  167. "text/turtle",
  168. # "text/xml",
  169. )
  170. # /usr/share/doc/lighttpd-doc/expire.txt
  171. $HTTP["url"] !~ "/now\.lua$" {
  172. # expire all but now.lua - sets header itself
  173. expire.url = (
  174. "/app/" => "access 0 years",
  175. "" => "access 2 minutes",
  176. )
  177. }
  178. $HTTP["url"] =~ "\.(cfg|js|css|xslt|png|ico|mp3|ttl)$" {
  179. expire.url = ( "" => "access 1 days" )
  180. }
  181. $HTTP["url"] =~ "\.(ics|rdf)$" {
  182. expire.url = ( "" => "access 55 minutes" )
  183. }
  184. $HTTP["url"] =~ "\.(rss)$" {
  185. expire.url = ( "" => "access 2 minutes" )
  186. }
  187. $HTTP["url"] =~ "(modified\.ttl)$" {
  188. expire.url = ( "" => "modification 55 minutes" )
  189. }
  190. $HTTP["url"] =~ "modified-.*\.ttl$" {
  191. expire.url = ( "" => "modification 10 years" )
  192. }
  193. $HTTP["useragent"] =~ "^Overcast/" {
  194. expire.url = ( "" => "access 55 minutes" ),
  195. setenv.add-response-header = (
  196. # http://redmine.lighttpd.net/projects/1/wiki/Docs_ModMagnet#Status-Codes
  197. "Status" => "410",
  198. ),
  199. }
  200. etag.use-inode = "enable"
  201. etag.use-mtime = "enable"
  202. etag.use-size = "enable"
  203. static-file.etags = "enable"