I am trying to self-host ClearFlask on my own environment
My docker compose file looks like this (using real DynamoDB, S3 and SES)
## SPDX-FileCopyrightText: 2019-2022 Matus Faro <matus@smotana.com>
## SPDX-License-Identifier: Apache-2.0
volumes:
data:
driver: local
services:
clearflask-connect:
image: ghcr.io/clearflask/clearflask-connect:latest
depends_on:
- clearflask-server
ports:
- 19080:9080
- 19443:9443
environment:
- NODE_ENV=production
- ENV=selfhost
- CLEARFLASK_CREATE_CONNECT_CONFIG_IF_MISSING=1
volumes:
- ./connect:/opt/clearflask/
clearflask-server:
image: ghcr.io/clearflask/clearflask-server:latest
ports:
- 18080:8080
# JMX
- 9950:9950
- 9951:9951
environment:
- CLEARFLASK_ENVIRONMENT=PRODUCTION_SELF_HOST
- CLEARFLASK_CREATE_SERVER_CONFIG_IF_MISSING=1
volumes:
- ./server:/opt/clearflask/
healthcheck:
test: [ "CMD", "curl", "-f", "http://localhost:18080/api/health" ]
interval: 5s
timeout: 15s
retries: 2
# MySQL (enabled by default as an alternative to ElasticSearch)
mysql-db:
image: mysql:5.7@sha256:2c23f254c6b9444ecda9ba36051a9800e8934a2f5828ecc8730531db8142af83
platform: linux/amd64
command:
- 'mysqld'
- '--port=3306'
- '--sql-mode=IGNORE_SPACE'
- '--explicit-defaults-for-timestamp'
- '--secure-file-priv=/tmp'
volumes:
- ./data/mysql:/var/lib/mysql
ports:
- 13306:3306
environment:
- MYSQL_ROOT_PASSWORD=clearflask
# ElasticSearch (disabled by default)
# elasticsearch:
# profiles:
# - with-deps
# image: docker.elastic.co/elasticsearch/elasticsearch:7.10.0
# expose:
# - 9200
# environment:
# - ES_JAVA_OPTS=-Xms2g -Xmx2g
# - discovery.type=single-node
# mem_limit: 4g
# volumes:
# - ./data/elasticsearch:/usr/share/elasticsearch/data
# For DynamoDB, S3 and SES alternative
My connect.config.json is as follows (domain is redacted)
{
"connectToken": "7cb1e1c26f5d4705a213529257d081c6",
"disableAutoFetchCertificate": true,
"forceRedirectHttpToHttps": true,
"parentDomain": "feedback.redacted.com",
"apiBasePath": "http://api.feedback.redacted.net:18080"
}
My config-selfhost.cfg is as follows (some values are redacted)
com.smotana.clearflask.security.limiter.challenge.CaptchaChallenger$Config.enabled=false
com.smotana.clearflask.store.dynamo.DefaultDynamoDbProvider$Config.productionRegion=eu-central-1
com.smotana.clearflask.store.mysql.DefaultMysqlProvider$Config.host=mysql-db
com.smotana.clearflask.store.mysql.DefaultMysqlProvider$Config.user=root
com.smotana.clearflask.store.mysql.DefaultMysqlProvider$Config.pass=clearflask
com.smotana.clearflask.core.push.provider.BrowserPushServiceImpl$Config.publicKey=redacted
com.smotana.clearflask.core.push.provider.BrowserPushServiceImpl$Config.privateKey=redacted
com.smotana.clearflask.util.DefaultServerSecret$Config.sharedKey:cursor=redacted
com.smotana.clearflask.store.impl.DynamoElasticUserStore$Config.tokenSignerPrivKey=redacted
com.smotana.clearflask.web.Application$Config.domain=feedback.redacted.com
com.smotana.clearflask.web.Application$Config.defaultSearchEngine=READWRITE_MYSQL
com.smotana.clearflask.web.security.AuthCookieImpl$Config.authCookieSecure=true
com.smotana.clearflask.web.Application$Config.startupWaitUntilDeps=true
com.smotana.clearflask.web.Application$Config.createIndexesOnStartup=true
com.smotana.clearflask.security.ClearFlaskSso$Config.secretKey=439E5B12-F4D6-4BEF-9890-2CEEEFA67A8D
com.smotana.clearflask.web.security.SuperAdminPredicate$Config.superAdminEmailRegex=^admin@localhost$
com.smotana.clearflask.web.resource.AccountResource$Config.signupEnabled=true
com.smotana.clearflask.web.security.AuthenticationFilter$Config.connectToken=7cb1e1c26f5d4705a213529257d081c6
com.smotana.clearflask.core.push.provider.EmailServiceImpl$Config.useService=ses
com.smotana.clearflask.core.email.AmazonSimpleEmailServiceProvider$Config.region=eu-central-1
com.smotana.clearflask.core.email.AmazonSimpleEmailServiceProvider$Config.serviceEndpoint=
com.smotana.clearflask.store.s3.DefaultS3ClientProvider$Config.productionRegion=eu-central-1
com.smotana.clearflask.store.impl.S3ContentStore$Config.hostname=clearflask-s3.s3.amazonaws.com
com.smotana.clearflask.store.impl.S3ContentStore$Config.bucketName=clearflask-s3
com.smotana.clearflask.store.impl.S3ContentStore$Config.scheme=https
com.smotana.clearflask.store.impl.S3ContentStore$Config.createBucket=false
com.smotana.clearflask.store.impl.S3ContentStore$Config.proxyEnabled=false
com.smotana.clearflask.store.ConfigAwsCredentialsProvider$Config.awsAccessKeyId=redacted
com.smotana.clearflask.store.ConfigAwsCredentialsProvider$Config.awsSecretKey=redacted
I also am using Apache as a reverse proxy for both main site (frontend) and API (backend)
My Apache configurations are as follows
Backend
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"
ProxyPass / http://localhost:18080/
ProxyPassReverse / http://localhost:18080/
<Proxy *>
allow from all
</Proxy>
Frontend
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
RequestHeader set "X-Forwarded-SSL" expr=%{HTTPS}
#ProxyPreserveHost On
ProxyPass / http://localhost:19080/
ProxyPassReverse / http://localhost:19080/
DynamoDB is correctly configured because I can see that when I start the docker compose, a table is added to it
I know for sure that SES is also working because I have tested it manually outside this environment
For S3 I can't be sure because I haven't got yet to the point where I could successfully log in to the ClearFlask dashboard
I can start docker compose, apparently, without any issues. This is what I get as a final log entry when the docker compose is started
clearflask-server-1 | 20-Nov-2024 15:28:22.976 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/usr/local/tomcat/webapps/ROOT] has finished in [27,115] ms
clearflask-server-1 | 20-Nov-2024 15:28:22.981 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
clearflask-server-1 | 20-Nov-2024 15:28:22.997 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 27223 ms
As soon as I try to create an admin account, I get this in the logs
clearflask-connect-1 | react-i18next:: It seems you are still using the old wait option, you may migrate to the new useSuspense behaviour.
clearflask-server-1 | 20-Nov-2024 15:30:53.969 SEVERE [http-nio-8080-exec-1] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [api] in context with path [] threw exception [com.smotana.clearflask.web.ApiException: 404: Project does not exist or was deleted by owner] with root cause
clearflask-server-1 | com.smotana.clearflask.web.ApiException: 404: Project does not exist or was deleted by owner
clearflask-server-1 | at com.smotana.clearflask.web.resource.ProjectResource.lambda$configBindSlug$0(ProjectResource.java:158)
clearflask-server-1 | at java.base/java.util.Optional.orElseThrow(Optional.java:408)
clearflask-server-1 | at com.smotana.clearflask.web.resource.ProjectResource.configBindSlug(ProjectResource.java:158)
clearflask-server-1 | at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
clearflask-server-1 | at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
clearflask-server-1 | at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
clearflask-server-1 | at java.base/java.lang.reflect.Method.invoke(Method.java:566)
clearflask-server-1 | at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:76)
clearflask-server-1 | at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:148)
clearflask-server-1 | at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:191)
clearflask-server-1 | at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:243)
clearflask-server-1 | at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:103)
clearflask-server-1 | at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:493)
clearflask-server-1 | at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:415)
clearflask-server-1 | at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:104)
clearflask-server-1 | at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:277)
clearflask-server-1 | at org.glassfish.jersey.internal.Errors$1.call(Errors.java:272)
clearflask-server-1 | at org.glassfish.jersey.internal.Errors$1.call(Errors.java:268)
clearflask-server-1 | at org.glassfish.jersey.internal.Errors.process(Errors.java:316)
clearflask-server-1 | at org.glassfish.jersey.internal.Errors.process(Errors.java:298)
clearflask-server-1 | at org.glassfish.jersey.internal.Errors.process(Errors.java:268)
clearflask-server-1 | at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:289)
clearflask-server-1 | at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:256)
clearflask-server-1 | at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:703)
clearflask-server-1 | at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:416)
clearflask-server-1 | at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:370)
clearflask-server-1 | at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:389)
clearflask-server-1 | at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:342)
clearflask-server-1 | at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:229)
clearflask-server-1 | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
clearflask-server-1 | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
clearflask-server-1 | at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
clearflask-server-1 | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
clearflask-server-1 | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
clearflask-server-1 | at org.apache.catalina.filters.HttpHeaderSecurityFilter.doFilter(HttpHeaderSecurityFilter.java:126)
clearflask-server-1 | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
clearflask-server-1 | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
clearflask-server-1 | at com.smotana.clearflask.web.filter.HttpRedirectorFilter.doFilter(HttpRedirectorFilter.java:52)
clearflask-server-1 | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
clearflask-server-1 | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
clearflask-server-1 | at com.smotana.clearflask.web.filter.ApiExceptionMapperFilter.doFilter(ApiExceptionMapperFilter.java:48)
clearflask-server-1 | at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
clearflask-server-1 | at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
clearflask-server-1 | at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
clearflask-server-1 | at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
clearflask-server-1 | at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:543)
clearflask-server-1 | at org.apache.catalina.valves.rewrite.RewriteValve.invoke(RewriteValve.java:571)
clearflask-server-1 | at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
clearflask-server-1 | at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
clearflask-server-1 | at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:698)
clearflask-server-1 | at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
clearflask-server-1 | at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:367)
clearflask-server-1 | at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:639)
clearflask-server-1 | at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
clearflask-server-1 | at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:882)
clearflask-server-1 | at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1693)
clearflask-server-1 | at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
clearflask-server-1 | at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
clearflask-server-1 | at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
clearflask-server-1 | at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
clearflask-server-1 | at java.base/java.lang.Thread.run(Thread.java:829)
I have no idea what I am doing wrong and how to solve this
Maybe someone can get a glimps on this and see where is my mistake?
I use ClearFlask on:
- [X] Self-hosted (Own domain)
- [ ] Cloud (clearflask.com)
- [ ] Haven't tried (yet)
My financial contributions to ClearFlask:
- [X] I use a free Plan for now because I am evaluating options
- [ ] Thinking about it
- [ ] Monthly / Yearly Plan
- [ ] Lifetime Plan