diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e5a6f57f8844673bac5247019a0d7928bb3c6340..9a68bdb7477ab7da0394827ca3b1ec64e5190b49 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -6,7 +6,7 @@ before_script:
   - cd /go/src/code.vereign.com/${CI_PROJECT_PATH}
 
 lint:
-  image: golangci/golangci-lint:v1.44.2
+  image: golangci/golangci-lint:v1.46.2
   stage: test
   tags:
     - amd64-docker
@@ -15,7 +15,7 @@ lint:
     - golangci-lint run
 
 unit tests:
-  image: golang:1.17.8
+  image: golang:1.17.10
   stage: test
   tags:
     - amd64-docker
diff --git a/cmd/infohub/main.go b/cmd/infohub/main.go
new file mode 100644
index 0000000000000000000000000000000000000000..844f6b23fc884ce34c284e03522f22bad2fcac40
--- /dev/null
+++ b/cmd/infohub/main.go
@@ -0,0 +1,162 @@
+package main
+
+import (
+	"context"
+	"errors"
+	"log"
+	"net/http"
+	"time"
+
+	"github.com/kelseyhightower/envconfig"
+	"go.uber.org/zap"
+	"go.uber.org/zap/zapcore"
+	goahttp "goa.design/goa/v3/http"
+	goa "goa.design/goa/v3/pkg"
+	"golang.org/x/sync/errgroup"
+
+	"code.vereign.com/gaiax/tsa/golib/graceful"
+	goahealth "code.vereign.com/gaiax/tsa/infohub/gen/health"
+	goahealthsrv "code.vereign.com/gaiax/tsa/infohub/gen/http/health/server"
+	goainfohubsrv "code.vereign.com/gaiax/tsa/infohub/gen/http/infohub/server"
+	goaopenapisrv "code.vereign.com/gaiax/tsa/infohub/gen/http/openapi/server"
+	goainfohub "code.vereign.com/gaiax/tsa/infohub/gen/infohub"
+	"code.vereign.com/gaiax/tsa/infohub/gen/openapi"
+	"code.vereign.com/gaiax/tsa/infohub/internal/config"
+	"code.vereign.com/gaiax/tsa/infohub/internal/service"
+	"code.vereign.com/gaiax/tsa/infohub/internal/service/health"
+	"code.vereign.com/gaiax/tsa/infohub/internal/service/infohub"
+)
+
+var Version = "0.0.0+development"
+
+func main() {
+	// load configuration from environment
+	var cfg config.Config
+	if err := envconfig.Process("", &cfg); err != nil {
+		log.Fatalf("cannot load configuration: %v", err)
+	}
+
+	// create logger
+	logger, err := createLogger(cfg.LogLevel)
+	if err != nil {
+		log.Fatalln(err)
+	}
+	defer logger.Sync() //nolint:errcheck
+
+	logger.Info("infohub service started", zap.String("version", Version), zap.String("goa", goa.Version()))
+
+	// create services
+	var (
+		infohubSvc goainfohub.Service
+		healthSvc  goahealth.Service
+	)
+	{
+		infohubSvc = infohub.New(logger)
+		healthSvc = health.New()
+	}
+
+	// create endpoints
+	var (
+		infohubEndpoints *goainfohub.Endpoints
+		healthEndpoints  *goahealth.Endpoints
+		openapiEndpoints *openapi.Endpoints
+	)
+	{
+		infohubEndpoints = goainfohub.NewEndpoints(infohubSvc)
+		healthEndpoints = goahealth.NewEndpoints(healthSvc)
+		openapiEndpoints = openapi.NewEndpoints(nil)
+	}
+
+	// Provide the transport specific request decoder and response encoder.
+	// The goa http package has built-in support for JSON, XML and gob.
+	// Other encodings can be used by providing the corresponding functions,
+	// see goa.design/implement/encoding.
+	var (
+		dec = goahttp.RequestDecoder
+		enc = goahttp.ResponseEncoder
+	)
+
+	// Build the service HTTP request multiplexer and configure it to serve
+	// HTTP requests to the service endpoints.
+	mux := goahttp.NewMuxer()
+
+	// Wrap the endpoints with the transport specific layers. The generated
+	// server packages contains code generated from the design which maps
+	// the service input and output data structures to HTTP requests and
+	// responses.
+	var (
+		infohubServer *goainfohubsrv.Server
+		healthServer  *goahealthsrv.Server
+		openapiServer *goaopenapisrv.Server
+	)
+	{
+		infohubServer = goainfohubsrv.New(infohubEndpoints, mux, dec, enc, nil, errFormatter)
+		healthServer = goahealthsrv.New(healthEndpoints, mux, dec, enc, nil, errFormatter)
+		openapiServer = goaopenapisrv.New(openapiEndpoints, mux, dec, enc, nil, errFormatter, nil, nil)
+	}
+
+	// Configure the mux.
+	goainfohubsrv.Mount(mux, infohubServer)
+	goahealthsrv.Mount(mux, healthServer)
+	goaopenapisrv.Mount(mux, openapiServer)
+
+	var handler http.Handler = mux
+	srv := &http.Server{
+		Addr:         cfg.HTTP.Host + ":" + cfg.HTTP.Port,
+		Handler:      handler,
+		IdleTimeout:  cfg.HTTP.IdleTimeout,
+		ReadTimeout:  cfg.HTTP.ReadTimeout,
+		WriteTimeout: cfg.HTTP.WriteTimeout,
+	}
+
+	g, ctx := errgroup.WithContext(context.Background())
+	g.Go(func() error {
+		if err := graceful.Shutdown(ctx, srv, 20*time.Second); err != nil {
+			logger.Error("server shutdown error", zap.Error(err))
+			return err
+		}
+		return errors.New("server stopped successfully")
+	})
+	if err := g.Wait(); err != nil {
+		logger.Error("run group stopped", zap.Error(err))
+	}
+
+	logger.Info("bye bye")
+}
+
+func createLogger(logLevel string, opts ...zap.Option) (*zap.Logger, error) {
+	var level = zapcore.InfoLevel
+	if logLevel != "" {
+		err := level.UnmarshalText([]byte(logLevel))
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	config := zap.NewProductionConfig()
+	config.Level = zap.NewAtomicLevelAt(level)
+	config.DisableStacktrace = true
+	config.EncoderConfig.TimeKey = "ts"
+	config.EncoderConfig.EncodeTime = zapcore.RFC3339TimeEncoder
+	return config.Build(opts...)
+}
+
+func errFormatter(e error) goahttp.Statuser {
+	return service.NewErrorResponse(e)
+}
+
+//func httpClient() *http.Client {
+//	return &http.Client{
+//		Transport: &http.Transport{
+//			Proxy: http.ProxyFromEnvironment,
+//			DialContext: (&net.Dialer{
+//				Timeout: 30 * time.Second,
+//			}).DialContext,
+//			MaxIdleConns:        100,
+//			MaxIdleConnsPerHost: 100,
+//			TLSHandshakeTimeout: 10 * time.Second,
+//			IdleConnTimeout:     60 * time.Second,
+//		},
+//		Timeout: 30 * time.Second,
+//	}
+//}
diff --git a/design/design.go b/design/design.go
index bbf49482bf8d54d6ab01823bca1c227eeeadfa45..75b1d81bdee22c909a1ac1491172a62dd91171ea 100644
--- a/design/design.go
+++ b/design/design.go
@@ -19,7 +19,7 @@ var _ = Service("infohub", func() {
 	Description("Information Hub Service enables exporting and importing information.")
 
 	Method("Export", func() {
-		Description("Evaluate executes a policy with the given 'data' as input.")
+		Description("Export returns data signed as Verifiable Presentation.")
 		Payload(ExportRequest)
 		Result(Any)
 		HTTP(func() {
diff --git a/gen/http/cli/infohub/cli.go b/gen/http/cli/infohub/cli.go
index dc1b97d429da3a0ce7abf8480375b7f73d3ea40f..1f962614eaae7cfa1247e17813842a58825dd3cc 100644
--- a/gen/http/cli/infohub/cli.go
+++ b/gen/http/cli/infohub/cli.go
@@ -202,7 +202,7 @@ Usage:
     %[1]s [globalflags] infohub COMMAND [flags]
 
 COMMAND:
-    export: Evaluate executes a policy with the given 'data' as input.
+    export: Export returns data signed as Verifiable Presentation.
 
 Additional help:
     %[1]s infohub COMMAND --help
@@ -211,7 +211,7 @@ Additional help:
 func infohubExportUsage() {
 	fmt.Fprintf(os.Stderr, `%[1]s [flags] infohub export -export-name STRING
 
-Evaluate executes a policy with the given 'data' as input.
+Export returns data signed as Verifiable Presentation.
     -export-name STRING: Name of export to be performed.
 
 Example:
diff --git a/gen/http/openapi.json b/gen/http/openapi.json
index c0e3b5ff40a9fb5cdef9545b6e09cebe4c9ae1f4..73d9f18fbc12c419e358c01fa76ffcd19cec29f8 100644
--- a/gen/http/openapi.json
+++ b/gen/http/openapi.json
@@ -1 +1 @@
-{"swagger":"2.0","info":{"title":"Information Hub Service","description":"Information Hub Service exposes HTTP API for exporting and importing information.","version":""},"host":"localhost:8084","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/v1/export/{exportName}":{"get":{"tags":["infohub"],"summary":"Export infohub","description":"Evaluate executes a policy with the given 'data' as input.","operationId":"infohub#Export","parameters":[{"name":"exportName","in":"path","description":"Name of export to be performed.","required":true,"type":"string"}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"}}},"schemes":["http"]}}}}
\ No newline at end of file
+{"swagger":"2.0","info":{"title":"Information Hub Service","description":"Information Hub Service exposes HTTP API for exporting and importing information.","version":""},"host":"localhost:8084","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/v1/export/{exportName}":{"get":{"tags":["infohub"],"summary":"Export infohub","description":"Export returns data signed as Verifiable Presentation.","operationId":"infohub#Export","parameters":[{"name":"exportName","in":"path","description":"Name of export to be performed.","required":true,"type":"string"}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"}}},"schemes":["http"]}}}}
\ No newline at end of file
diff --git a/gen/http/openapi.yaml b/gen/http/openapi.yaml
index da28dc9b1dcc8ba4af650c4b77ee0d88a88bf846..1d2f51fd9a8c9a46cacf823aa59499353dd1102a 100644
--- a/gen/http/openapi.yaml
+++ b/gen/http/openapi.yaml
@@ -41,7 +41,7 @@ paths:
       tags:
       - infohub
       summary: Export infohub
-      description: Evaluate executes a policy with the given 'data' as input.
+      description: Export returns data signed as Verifiable Presentation.
       operationId: infohub#Export
       parameters:
       - name: exportName
diff --git a/gen/http/openapi3.json b/gen/http/openapi3.json
index 9699ac68517680535c789f0162926c39ddf16560..d35523af06ed4596e8772857a7727ecfe73e750e 100644
--- a/gen/http/openapi3.json
+++ b/gen/http/openapi3.json
@@ -1 +1 @@
-{"openapi":"3.0.3","info":{"title":"Information Hub Service","description":"Information Hub Service exposes HTTP API for exporting and importing information.","version":"1.0"},"servers":[{"url":"http://localhost:8084","description":"Information Hub Server"}],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}}}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}}}},"/v1/export/{exportName}":{"get":{"tags":["infohub"],"summary":"Export infohub","description":"Evaluate executes a policy with the given 'data' as input.","operationId":"infohub#Export","parameters":[{"name":"exportName","in":"path","description":"Name of export to be performed.","required":true,"schema":{"type":"string","description":"Name of export to be performed.","example":"myexport"},"example":"myexport"}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","example":"Veniam non.","format":"binary"},"example":"Ipsam similique nulla quis."}}}}}}},"components":{},"tags":[{"name":"health","description":"Health service provides health check endpoints."},{"name":"infohub","description":"Information Hub Service enables exporting and importing information."}]}
\ No newline at end of file
+{"openapi":"3.0.3","info":{"title":"Information Hub Service","description":"Information Hub Service exposes HTTP API for exporting and importing information.","version":"1.0"},"servers":[{"url":"http://localhost:8084","description":"Information Hub Server"}],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}}}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}}}},"/v1/export/{exportName}":{"get":{"tags":["infohub"],"summary":"Export infohub","description":"Export returns data signed as Verifiable Presentation.","operationId":"infohub#Export","parameters":[{"name":"exportName","in":"path","description":"Name of export to be performed.","required":true,"schema":{"type":"string","description":"Name of export to be performed.","example":"myexport"},"example":"myexport"}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","example":"Veniam non.","format":"binary"},"example":"Ipsam similique nulla quis."}}}}}}},"components":{},"tags":[{"name":"health","description":"Health service provides health check endpoints."},{"name":"infohub","description":"Information Hub Service enables exporting and importing information."}]}
\ No newline at end of file
diff --git a/gen/http/openapi3.yaml b/gen/http/openapi3.yaml
index 1a932d4ffa4036f1e18f21d37f188d884476b5fb..9faf4e1c8bf3236cc130cddde6f220d762fd0613 100644
--- a/gen/http/openapi3.yaml
+++ b/gen/http/openapi3.yaml
@@ -31,7 +31,7 @@ paths:
       tags:
       - infohub
       summary: Export infohub
-      description: Evaluate executes a policy with the given 'data' as input.
+      description: Export returns data signed as Verifiable Presentation.
       operationId: infohub#Export
       parameters:
       - name: exportName
diff --git a/gen/infohub/service.go b/gen/infohub/service.go
index 608c9284d4bfe86614f0845d7de95291ec27c41c..e65ec3bcdbeea60e3a14b144e30e9297cdea52c8 100644
--- a/gen/infohub/service.go
+++ b/gen/infohub/service.go
@@ -13,7 +13,7 @@ import (
 
 // Information Hub Service enables exporting and importing information.
 type Service interface {
-	// Evaluate executes a policy with the given 'data' as input.
+	// Export returns data signed as Verifiable Presentation.
 	Export(context.Context, *ExportRequest) (res interface{}, err error)
 }
 
diff --git a/internal/config/config.go b/internal/config/config.go
new file mode 100644
index 0000000000000000000000000000000000000000..1e7598ced85d5550863920a2e37d90f191e01a96
--- /dev/null
+++ b/internal/config/config.go
@@ -0,0 +1,16 @@
+package config
+
+import "time"
+
+type Config struct {
+	HTTP     httpConfig
+	LogLevel string `envconfig:"LOG_LEVEL" default:"INFO"`
+}
+
+type httpConfig struct {
+	Host         string        `envconfig:"HTTP_HOST"`
+	Port         string        `envconfig:"HTTP_PORT" default:"8080"`
+	IdleTimeout  time.Duration `envconfig:"HTTP_IDLE_TIMEOUT" default:"120s"`
+	ReadTimeout  time.Duration `envconfig:"HTTP_READ_TIMEOUT" default:"10s"`
+	WriteTimeout time.Duration `envconfig:"HTTP_WRITE_TIMEOUT" default:"10s"`
+}
diff --git a/internal/service/error_response.go b/internal/service/error_response.go
new file mode 100644
index 0000000000000000000000000000000000000000..cbe74c6bb5180af664d93f5d00912f61ce8b85d3
--- /dev/null
+++ b/internal/service/error_response.go
@@ -0,0 +1,39 @@
+package service
+
+import (
+	goahttp "goa.design/goa/v3/http"
+	goa "goa.design/goa/v3/pkg"
+
+	"code.vereign.com/gaiax/tsa/golib/errors"
+)
+
+func NewErrorResponse(err error) goahttp.Statuser {
+	if err == nil {
+		return nil
+	}
+
+	var newerr *errors.Error
+	switch e := err.(type) {
+	case *errors.Error:
+		newerr = e
+	case *goa.ServiceError:
+		// Use goahttp.ErrorResponse to determine error kind
+		goaerr := goahttp.NewErrorResponse(e)
+		kind := errors.GetKind(goaerr.StatusCode())
+		newerr = &errors.Error{
+			ID:      e.ID,
+			Kind:    kind,
+			Message: e.Message,
+			Err:     e,
+		}
+	default:
+		newerr = &errors.Error{
+			ID:      errors.NewID(),
+			Kind:    errors.Internal,
+			Message: e.Error(),
+			Err:     e,
+		}
+	}
+
+	return newerr
+}
diff --git a/internal/service/health/service.go b/internal/service/health/service.go
new file mode 100644
index 0000000000000000000000000000000000000000..ffa6d9af3d67b8681ce5464bc555ca38aa6b801e
--- /dev/null
+++ b/internal/service/health/service.go
@@ -0,0 +1,17 @@
+package health
+
+import "context"
+
+type Service struct{}
+
+func New() *Service {
+	return &Service{}
+}
+
+func (s *Service) Liveness(ctx context.Context) error {
+	return nil
+}
+
+func (s *Service) Readiness(ctx context.Context) error {
+	return nil
+}
diff --git a/internal/service/infohub/service.go b/internal/service/infohub/service.go
new file mode 100644
index 0000000000000000000000000000000000000000..1c737b62ba51d47c4681efc89182eee2c41f2b54
--- /dev/null
+++ b/internal/service/infohub/service.go
@@ -0,0 +1,22 @@
+package infohub
+
+import (
+	"context"
+	"fmt"
+
+	"go.uber.org/zap"
+
+	"code.vereign.com/gaiax/tsa/infohub/gen/infohub"
+)
+
+type Service struct {
+	logger *zap.Logger
+}
+
+func New(logger *zap.Logger) *Service {
+	return &Service{logger: logger}
+}
+
+func (s *Service) Export(ctx context.Context, req *infohub.ExportRequest) (interface{}, error) {
+	return nil, fmt.Errorf("not implemented")
+}