diff --git a/Dockerfile b/Dockerfile index 4d5de08..b86e0ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,6 +20,8 @@ WORKDIR /app ENV MB_LOGLEVEL=info ENV MB_ALLOWED_ORIGINS=* ENV MB_HOST=0.0.0.0:80 +ENV MB_DB_PORT=5432 +ENV MB_DB_SSLMODE=disable EXPOSE 80 EXPOSE 443 diff --git a/dev.sh b/dev.sh index e86e4e6..8b6e51f 100755 --- a/dev.sh +++ b/dev.sh @@ -10,5 +10,14 @@ export MB_HOT_RELOAD=true export MB_EMVI_CLIENT_ID=3fBBn144yvSF9R3dPC8l export MB_EMVI_CLIENT_SECRET=dw3FeshelTgdf1Gj13J7uF5FfdPDi40sQvvwqeFVKTTyIDuCdlAHhRY72csFL6yg export MB_EMVI_ORGA=marvin +export MB_DB_HOST=localhost +export MB_DB_PORT=5432 +export MB_DB_USER=postgres +export MB_DB_PASSWORD=postgres +export MB_DB_SCHEMA=marvinblum +export MB_DB_SSLMODE=disable +export MB_DB_SSLCERT= +export MB_DB_SSLKEY= +export MB_DB_SSLROOTCERT= go run main.go diff --git a/docker-compose.yml b/docker-compose.yml index cc4ccb7..373f795 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -34,6 +34,10 @@ services: - MB_EMVI_CLIENT_ID="3fBBn144yvSF9R3dPC8l" - MB_EMVI_CLIENT_SECRET="dw3FeshelTgdf1Gj13J7uF5FfdPDi40sQvvwqeFVKTTyIDuCdlAHhRY72csFL6yg" - MB_EMVI_ORGA=marvin + - MB_DB_HOST=postgres + - MB_DB_USER= + - MB_DB_PASSWORD= + - MB_DB_SCHEMA= labels: - "traefik.enable=true" - "traefik.http.routers.marvinblum.entrypoints=web" diff --git a/go.mod b/go.mod index 5fdb28f..5d20415 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,9 @@ require ( github.com/caddyserver/certmagic v0.10.13 github.com/emvi/api-go v0.0.0-20191210194347-0a945446f6a8 github.com/emvi/logbuch v0.0.0-20200214115750-61de9b6d5934 + github.com/emvi/pirsch v0.0.0-20200621133222-e65f2459e5a3 github.com/gorilla/mux v1.7.4 github.com/gosimple/slug v1.9.0 + github.com/lib/pq v1.7.0 // indirect github.com/rs/cors v1.7.0 ) diff --git a/go.sum b/go.sum index 6e5c114..855cf81 100644 --- a/go.sum +++ b/go.sum @@ -77,6 +77,8 @@ github.com/emvi/api-go v0.0.0-20191210194347-0a945446f6a8 h1:DZJfRdvwlybLvHkyeN8 github.com/emvi/api-go v0.0.0-20191210194347-0a945446f6a8/go.mod h1:g9RdDC3s5ebCknAHQQ5PjoM2vRFSyyGoOUX3QkDKU+o= github.com/emvi/logbuch v0.0.0-20200214115750-61de9b6d5934 h1:+G10WRp72llJuaW89QezNK8QU9SsOmd5Ja7ocrrUaI0= github.com/emvi/logbuch v0.0.0-20200214115750-61de9b6d5934/go.mod h1:J2Wgbr3BuSc1JO+D2MBVh6q3WPVSK5GzktwWz8pvkKw= +github.com/emvi/pirsch v0.0.0-20200621133222-e65f2459e5a3 h1:Du+BjUUrCH7XptKBgsyTeLCPFOuYNArPfja53XFwzl4= +github.com/emvi/pirsch v0.0.0-20200621133222-e65f2459e5a3/go.mod h1:+YmBbltJ3feZz9L/QQyqwywltYvQKBfzrGD51TPKl5g= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE= @@ -169,6 +171,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA= github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w= +github.com/lib/pq v1.7.0 h1:h93mCPfUSkaul3Ka/VG8uZdmW1uMHDGxzu0NWHuJmHY= +github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA= github.com/liquidweb/liquidweb-go v1.6.0/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVLEIG/i5J9cyixzQ= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= diff --git a/main.go b/main.go index 7e9d4ed..38c16d0 100644 --- a/main.go +++ b/main.go @@ -1,29 +1,36 @@ package main import ( + "database/sql" + "fmt" "github.com/Kugelschieber/marvinblum.de/blog" "github.com/Kugelschieber/marvinblum.de/tpl" "github.com/NYTimes/gziphandler" "github.com/caddyserver/certmagic" emvi "github.com/emvi/api-go" "github.com/emvi/logbuch" + "github.com/emvi/pirsch" "github.com/gorilla/mux" + _ "github.com/lib/pq" "github.com/rs/cors" "html/template" "net/http" "os" + "strconv" "strings" "time" ) const ( - staticDir = "static" - staticDirPrefix = "/static/" - logTimeFormat = "2006-01-02_15:04:05" - envPrefix = "MB_" + staticDir = "static" + staticDirPrefix = "/static/" + logTimeFormat = "2006-01-02_15:04:05" + envPrefix = "MB_" + connectionString = `host=%s port=%s user=%s password=%s dbname=%s sslmode=%s sslcert=%s sslkey=%s sslrootcert=%s connectTimeout=%s timezone=%s` ) var ( + tracker *pirsch.Tracker blogInstance *blog.Blog ) @@ -50,8 +57,37 @@ func logEnvConfig() { } } +func setupTracker() { + logbuch.Info("Connecting to database...") + host := os.Getenv("MB_DB_HOST") + port := os.Getenv("MB_DB_PORT") + user := os.Getenv("MB_DB_USER") + password := os.Getenv("MB_DB_PASSWORD") + schema := os.Getenv("MB_DB_SCHEMA") + sslMode := os.Getenv("MB_DB_SSLMODE") + sslCert := os.Getenv("MB_DB_SSLCERT") + sslKey := os.Getenv("MB_DB_SSLKEY") + sslRootCert := os.Getenv("MB_DB_SSLROOTCERT") + zone, offset := time.Now().Zone() + timezone := zone + strconv.Itoa(-offset/3600) + logbuch.Info("Setting time zone", logbuch.Fields{"timezone": timezone}) + connectionStr := fmt.Sprintf(connectionString, host, port, user, password, schema, sslMode, sslCert, sslKey, sslRootCert, "30", timezone) + db, err := sql.Open("postgres", connectionStr) + + if err != nil { + logbuch.Fatal("Error connecting to database", logbuch.Fields{"err": err}) + } + + if err := db.Ping(); err != nil { + logbuch.Fatal("Error pinging database", logbuch.Fields{"err": err}) + } + + tracker = pirsch.NewTracker(pirsch.NewPostgresStore(db)) +} + func serveAbout() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { + tracker.Hit(r) data := struct { Articles []emvi.Article }{ @@ -67,6 +103,7 @@ func serveAbout() http.HandlerFunc { func serveBlogPage() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { + tracker.Hit(r) data := struct { Articles map[int][]emvi.Article }{ @@ -82,6 +119,7 @@ func serveBlogPage() http.HandlerFunc { func serveBlogArticle() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { + tracker.Hit(r) vars := mux.Vars(r) slug := strings.Split(vars["slug"], "-") @@ -119,9 +157,9 @@ func setupRouter() *mux.Router { router.PathPrefix(staticDirPrefix).Handler(http.StripPrefix(staticDirPrefix, gziphandler.GzipHandler(http.FileServer(http.Dir(staticDir))))) router.Handle("/blog/{slug}", serveBlogArticle()) router.Handle("/blog", serveBlogPage()) - router.Handle("/legal", tpl.ServeTemplate("legal.html")) + router.Handle("/legal", tpl.ServeTemplate("legal.html", tracker)) router.Handle("/", serveAbout()) - router.NotFoundHandler = tpl.ServeTemplate("notfound.html") + router.NotFoundHandler = tpl.ServeTemplate("notfound.html", tracker) return router } @@ -162,6 +200,7 @@ func main() { configureLog() logEnvConfig() tpl.LoadTemplate() + setupTracker() blogInstance = blog.NewBlog() router := setupRouter() corsConfig := configureCors(router) diff --git a/postgres/clear_logs.sh b/postgres/clear_logs.sh new file mode 100644 index 0000000..08ea2b0 --- /dev/null +++ b/postgres/clear_logs.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +echo "Clearing docker logs..." +echo "" > $(docker inspect --format='{{.LogPath}}' postgres) diff --git a/postgres/docker-compose.yml b/postgres/docker-compose.yml new file mode 100644 index 0000000..44ab03c --- /dev/null +++ b/postgres/docker-compose.yml @@ -0,0 +1,22 @@ +version: "3" + +services: + postgres: + image: postgres:12-alpine + container_name: postgres + restart: always + command: -c ssl=on -c ssl_cert_file=/var/lib/postgresql/server.crt -c ssl_key_file=/var/lib/postgresql/server.key + networks: + - db-internal + environment: + POSTGRES_PASSWORD: # + ports: + - "5432:5432" + volumes: + - /root/postgres/data:/var/lib/postgresql/data + - /root/postgres/cert/server.crt:/var/lib/postgresql/server.crt + - /root/postgres/cert/server.key:/var/lib/postgresql/server.key + +networks: + db-internal: + driver: bridge diff --git a/postgres/gen_cert.sh b/postgres/gen_cert.sh new file mode 100755 index 0000000..7a75bb4 --- /dev/null +++ b/postgres/gen_cert.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +mkdir cert +cd cert +openssl req -new -text -passout pass:$1 -subj /CN=localhost -out server.req -keyout privkey.pem +openssl rsa -in privkey.pem -passin pass:$1 -out server.key +openssl req -x509 -in server.req -text -key server.key -out server.crt +chown 0:70 server.key +chmod 640 server.key +echo "done" diff --git a/tpl/template.go b/tpl/template.go index ecea8dc..226bce8 100644 --- a/tpl/template.go +++ b/tpl/template.go @@ -3,6 +3,7 @@ package tpl import ( "bytes" "github.com/emvi/logbuch" + "github.com/emvi/pirsch" "github.com/gosimple/slug" "html/template" "net/http" @@ -55,11 +56,13 @@ func Get() *template.Template { return tpl } -func ServeTemplate(name string) http.HandlerFunc { +func ServeTemplate(name string, tracker *pirsch.Tracker) http.HandlerFunc { // render once so we have it in cache renderTemplate(name) return func(w http.ResponseWriter, r *http.Request) { + tracker.Hit(r) + if hotReload { LoadTemplate() renderTemplate(name)