{-# LANGUAGE OverloadedStrings #-} import Data.Maybe (fromMaybe) import Data.Monoid ((<>)) import System.Environment (lookupEnv) import Control.Lens import Data.Default (def) import Network.Wai.Serve.Listeners (TLSSettings, tlsSettingsChain) import Network.Wai.Serve.Main (serve) import Network.Wai.Serve.Middleware (cspHeadersMiddleware, deindexifyMiddleware, domainMiddleware, forceSSLMiddleware, gzipMiddleware, loggerMiddleware, securityHeadersMiddleware, stsHeadersMiddleware, (<#>)) import Network.Wai.Serve.Types (Directive (..), Stage (..), TLSConfiguration (..), scDevTransform, scMiddleware, scPath, scPort, scProdTransform, scStage, scStagingTransform, scTlsConfiguration, tlsPort, tlsSettings) directives :: [Directive] directives = [ DefaultSrc ["'self'"] , ScriptSrc [ "'self'", "'unsafe-inline'", "https://use.typekit.net", "https://cdn.mathkax.org", "https://connect.facebook.net", "https://*.twitter.com", "https://cdn.syndication.twimg.com", "https://gist.github.com" ] , ImgSrc ["'self'", "https:", "data:", "platform.twitter.com"] , FontSrc [ "'self'", "data:", "https://use.typekit.net", "https://cdn.mathjax.org", "https://fonts.typekit.net" ] , StyleSrc [ "'self'", "'unsafe-inline'", "https://use.typekit.net", "platform.twitter.com", "https://assets-cdn.github.com" ] , FrameSrc [ "https://www.youtube.com", "https://www.slideshare.net", "staticxx.facebook.com", "www.facebook.com" ] ] getTLSSettings :: IO TLSSettings getTLSSettings = do certPath <- lookupEnv "BLOG_TLS_CERT" chainPath <- lookupEnv "BLOG_TLS_CHAIN" keyPath <- lookupEnv "BLOG_TLS_KEY" return $ tlsSettingsChain (fromMaybe "cert.pem" certPath) [fromMaybe "fullchain.pem" chainPath] (fromMaybe "privkey.pem" keyPath) -- | The entry point of the server application. main :: IO () main = do rawStage <- lookupEnv "BLOG_STAGE" rawPath <- lookupEnv "BLOG_PATH" tlsSettings <- getTLSSettings let liveMiddleware = mempty <#> loggerMiddleware <#> cspHeadersMiddleware directives <#> securityHeadersMiddleware <#> domainMiddleware "chromabits.com" <#> forceSSLMiddleware <#> deindexifyMiddleware <#> gzipMiddleware prodMiddlware = (mempty <#> stsHeadersMiddleware) <> liveMiddleware let tlsConf = TLSConfiguration (const liveMiddleware) tlsSettings 8443 serve $ def & scStage .~ case rawStage of Just "live" -> Production Just "staging" -> Staging _ -> Development & scPort .~ 9090 & scMiddleware .~ mempty <#> loggerMiddleware <#> securityHeadersMiddleware <#> deindexifyMiddleware <#> gzipMiddleware & scPath .~ rawPath & scStagingTransform .~ ( (set scTlsConfiguration $ Just tlsConf) . (set scMiddleware liveMiddleware) . (set scPort 8080) ) & scProdTransform .~ ( (set scTlsConfiguration $ Just (tlsConf & tlsPort .~ 443)) . (set scMiddleware prodMiddlware) . (set scPort 80) )