From 3f978437a0d65dd51dd04c8070b9d867085c376f Mon Sep 17 00:00:00 2001 From: yatinappsmith <84702014+yatinappsmith@users.noreply.github.com> Date: Sun, 18 Sep 2022 12:38:40 +0530 Subject: [PATCH 1/5] ci: Fix ci cache & rts build for push workflow (#16850) * fix download rts * fix cache for ui-test --- .github/workflows/test-build-docker-image.yml | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test-build-docker-image.yml b/.github/workflows/test-build-docker-image.yml index 64cddad0da..b3163e8e59 100644 --- a/.github/workflows/test-build-docker-image.yml +++ b/.github/workflows/test-build-docker-image.yml @@ -383,9 +383,8 @@ jobs: run: | ls -al dist/node_modules/@shared/ast tar -cvf rts-dist.tar dist - - # Upload the build artifact so that it can be used by the test & deploy job in the workflow - - name: Upload server build bundle + # Upload the build artifacts and dependencies so that it can be used by the test & deploy job in other workflows + - name: Upload rts build bundle uses: actions/upload-artifact@v2 with: name: rts-dist @@ -727,9 +726,15 @@ jobs: - name: Download the rts build artifact uses: actions/download-artifact@v2 with: - name: rts-build + name: rts-dist path: app/rts/dist + - name: Untar the rts folder + run: | + tar -xvf app/rts/dist/rts-dist.tar -C app/rts/ + echo "Cleaning up the tar files" + rm app/rts/dist/rts-dist.tar + - name: Download the rts build artifact uses: actions/download-artifact@v2 with: @@ -1073,7 +1078,7 @@ jobs: with: path: | ~/run_result - key: ${{ github.run_id }}-${{ github.job }}-${{ steps.timestamp.outputs.timestamp }}-${{ matrix.job }} + key: ${{ github.run_id }}-${{ github.job }}-${{ matrix.job }} restore-keys: | ${{ github.run_id }}-${{ github.job }}-${{ matrix.job }} @@ -1089,7 +1094,7 @@ jobs: with: path: | ~/combined_failed_spec - key: ${{ github.run_id }}-"ui-test-result"-${{ steps.timestamp.outputs.timestamp }} + key: ${{ github.run_id }}-"ui-test-result" restore-keys: | ${{ github.run_id }}-${{ github.job }} @@ -1401,7 +1406,7 @@ jobs: with: path: | app/client/cypress/snapshots/ - key: ${{ github.run_id }}-${{ github.job }}-${{ steps.timestamp.outputs.timestamp }}-${{ matrix.job }} + key: ${{ github.run_id }}-${{ github.job }}-${{ matrix.job }} restore-keys: | ${{ github.run_id }}-${{ github.job }}-${{ matrix.job }} @@ -1457,7 +1462,7 @@ jobs: with: path: | ~/combined_failed_spec - key: ${{ github.run_id }}-"ui-test-result"-${{ steps.timestamp.outputs.timestamp }} + key: ${{ github.run_id }}-"ui-test-result" restore-keys: | ${{ github.run_id }}-${{ github.job }} From 8e8f338b7dbbe018358f76448ddc455d28422abb Mon Sep 17 00:00:00 2001 From: yatinappsmith <84702014+yatinappsmith@users.noreply.github.com> Date: Mon, 19 Sep 2022 09:21:18 +0530 Subject: [PATCH 2/5] ci: removed rts download for modues (#16851) --- .github/workflows/test-build-docker-image.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/test-build-docker-image.yml b/.github/workflows/test-build-docker-image.yml index b3163e8e59..32e5d67b4a 100644 --- a/.github/workflows/test-build-docker-image.yml +++ b/.github/workflows/test-build-docker-image.yml @@ -735,12 +735,6 @@ jobs: echo "Cleaning up the tar files" rm app/rts/dist/rts-dist.tar - - name: Download the rts build artifact - uses: actions/download-artifact@v2 - with: - name: rts-build-deps - path: app/rts/node_modules/ - # We don't use Depot Docker builds because it's faster for local Docker images to be built locally. # It's slower and more expensive to build these Docker images on Depot and download it back to the CI node. - name: Build docker image From bd5d574ab6fefcbcc93df1a7cbbe1b3f631530cd Mon Sep 17 00:00:00 2001 From: yatinappsmith <84702014+yatinappsmith@users.noreply.github.com> Date: Mon, 19 Sep 2022 11:00:04 +0530 Subject: [PATCH 3/5] ci: Fix ci cache (#16852) Fix ci cache & rts build for push workflow ## Description Fix ci cache & rts build for push workflow ## Type of change - Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? code review ## Checklist: - [X] My code follows the style guidelines of this project - [X] I have performed a self-review of my own code - [X] I have commented my code, particularly in hard-to-understand areas - [X] I have made corresponding changes to the documentation - [X] My changes generate no new warnings - [X] I have added tests that prove my fix is effective or that my feature works - [X] New and existing unit tests pass locally with my changes --- .github/workflows/test-build-docker-image.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-build-docker-image.yml b/.github/workflows/test-build-docker-image.yml index 32e5d67b4a..f5a7638692 100644 --- a/.github/workflows/test-build-docker-image.yml +++ b/.github/workflows/test-build-docker-image.yml @@ -1373,7 +1373,7 @@ jobs: with: path: | ~/run_result - key: ${{ github.run_id }}-${{ github.job }}-${{ steps.timestamp.outputs.timestamp }}-${{ matrix.job }} + key: ${{ github.run_id }}-${{ github.job }}-${{ matrix.job }} restore-keys: | ${{ github.run_id }}-${{ github.job }}-${{ matrix.job }} @@ -1384,7 +1384,7 @@ jobs: with: path: | ~/failed_spec - key: ${{ github.run_id }}-${{ github.job }}-${{ steps.timestamp.outputs.timestamp }}-${{ matrix.job }} + key: ${{ github.run_id }}-${{ github.job }}-${{ matrix.job }} restore-keys: | ${{ github.run_id }}-${{ github.job }}-${{ matrix.job }} From ac01687557df5dac9d9612f0d7d444b4d1d9d1cc Mon Sep 17 00:00:00 2001 From: Shrikant Sharat Kandula Date: Mon, 19 Sep 2022 12:41:57 +0530 Subject: [PATCH 4/5] fix: Better support for disallowed hosts (#16842) --- .../restApiUtils/helpers/TriggerUtils.java | 11 +-- .../restApiUtils/helpers/URIUtils.java | 16 +-- .../com/appsmith/util/WebClientUtils.java | 97 ++++++++++++++++++- .../com/external/plugins/GraphQLPlugin.java | 19 +--- .../com/external/plugins/RestApiPlugin.java | 20 +--- 5 files changed, 104 insertions(+), 59 deletions(-) diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/TriggerUtils.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/TriggerUtils.java index 99987e1ce4..2f3556d864 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/TriggerUtils.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/TriggerUtils.java @@ -35,10 +35,8 @@ import reactor.netty.resources.ConnectionProvider; import javax.crypto.SecretKey; import java.io.IOException; -import java.net.InetAddress; import java.net.URI; import java.net.URISyntaxException; -import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.time.Instant; @@ -46,7 +44,6 @@ import java.util.Date; import java.util.List; import java.util.Set; -import static com.appsmith.external.helpers.restApiUtils.helpers.URIUtils.DISALLOWED_HOSTS; import static org.apache.commons.lang3.StringUtils.isNotEmpty; @NoArgsConstructor @@ -204,14 +201,10 @@ public class TriggerUtils { * It redirects to partial URI : /api/character/ * In this scenario we should convert the partial URI to complete URI */ - URI redirectUri; + final URI redirectUri; try { redirectUri = new URI(redirectUrl); - if (DISALLOWED_HOSTS.contains(redirectUri.getHost()) - || DISALLOWED_HOSTS.contains(InetAddress.getByName(redirectUri.getHost()).getHostAddress())) { - return Mono.error(new AppsmithPluginException(AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, "Host not allowed.")); - } - } catch (URISyntaxException | UnknownHostException e) { + } catch (URISyntaxException e) { return Mono.error(new AppsmithPluginException(AppsmithPluginError.PLUGIN_ERROR, e)); } diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/URIUtils.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/URIUtils.java index cc3c761b13..70c9b5af97 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/URIUtils.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/restApiUtils/helpers/URIUtils.java @@ -3,30 +3,21 @@ package com.appsmith.external.helpers.restApiUtils.helpers; import com.appsmith.external.models.ActionConfiguration; import com.appsmith.external.models.DatasourceConfiguration; import com.appsmith.external.models.Property; -import lombok.AccessLevel; import lombok.NoArgsConstructor; -import org.apache.commons.lang3.StringUtils; import org.springframework.web.util.UriComponentsBuilder; -import java.net.InetAddress; import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; -import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; -import java.util.Set; import static org.apache.commons.collections.CollectionUtils.isEmpty; import static org.apache.commons.lang3.StringUtils.isNotEmpty; @NoArgsConstructor public class URIUtils { - public static final Set DISALLOWED_HOSTS = Set.of( - "169.254.169.254", - "metadata.google.internal" - ); public URI createUriWithQueryParams(ActionConfiguration actionConfiguration, DatasourceConfiguration datasourceConfiguration, String url, @@ -53,7 +44,7 @@ public class URIUtils { for (Property queryParam : allQueryParams) { String key = queryParam.getKey(); if (isNotEmpty(key)) { - if (encodeParamsToggle == true) { + if (encodeParamsToggle) { uriBuilder.queryParam( URLEncoder.encode(key, StandardCharsets.UTF_8), URLEncoder.encode((String) queryParam.getValue(), StandardCharsets.UTF_8) @@ -78,9 +69,4 @@ public class URIUtils { return "http://" + url; } - public boolean isHostDisallowed(URI uri) throws UnknownHostException { - String host = uri.getHost(); - return StringUtils.isEmpty(host) || DISALLOWED_HOSTS.contains(host) - || DISALLOWED_HOSTS.contains(InetAddress.getByName(host).getHostAddress()); - } } diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/util/WebClientUtils.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/util/WebClientUtils.java index 8861dd16e5..f87b62fa30 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/util/WebClientUtils.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/util/WebClientUtils.java @@ -1,11 +1,31 @@ package com.appsmith.util; +import io.netty.resolver.AddressResolver; +import io.netty.resolver.AddressResolverGroup; +import io.netty.resolver.InetNameResolver; +import io.netty.resolver.InetSocketAddressResolver; +import io.netty.util.concurrent.EventExecutor; +import io.netty.util.concurrent.Promise; +import io.netty.util.internal.SocketUtils; +import lombok.extern.slf4j.Slf4j; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.client.WebClient; import reactor.netty.http.client.HttpClient; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + public class WebClientUtils { + private static final Set DISALLOWED_HOSTS = Set.of( + "169.254.169.254", + "metadata.google.internal" + ); + private WebClientUtils() { } @@ -31,15 +51,86 @@ public class WebClientUtils { public static WebClient.Builder builder(HttpClient httpClient) { return WebClient.builder() - .clientConnector(new ReactorClientHttpConnector(applyProxyIfConfigured(httpClient))); + .clientConnector(new ReactorClientHttpConnector(makeSafeHttpClient(httpClient))); } - private static HttpClient applyProxyIfConfigured(HttpClient httpClient) { + private static HttpClient makeSafeHttpClient(HttpClient httpClient) { if (shouldUseSystemProxy()) { httpClient = httpClient.proxyWithSystemProperties(); } - return httpClient; + return httpClient.resolver(ResolverGroup.INSTANCE); + } + + private static class ResolverGroup extends AddressResolverGroup { + public static final ResolverGroup INSTANCE = new ResolverGroup(); + + @Override + protected AddressResolver newResolver(EventExecutor executor) { + return new InetSocketAddressResolver(executor, new NameResolver(executor)); + } + } + + @Slf4j + private static class NameResolver extends InetNameResolver { + + public NameResolver(EventExecutor executor) { + super(executor); + } + + private static boolean isDisallowedAndFail(String host, Promise promise) { + if (DISALLOWED_HOSTS.contains(host)) { + log.warn("Host {} is disallowed. Failing the request.", host); + promise.setFailure(new UnknownHostException("Host not allowed.")); + return true; + } + return false; + } + + @Override + protected void doResolve(String inetHost, Promise promise) { + if (isDisallowedAndFail(inetHost, promise)) { + return; + } + + final InetAddress address; + try { + address = SocketUtils.addressByName(inetHost); + } catch (UnknownHostException e) { + promise.setFailure(e); + return; + } + + if (isDisallowedAndFail(address.getHostAddress(), promise)) { + return; + } + + promise.setSuccess(address); + } + + @Override + protected void doResolveAll(String inetHost, Promise> promise) { + if (isDisallowedAndFail(inetHost, promise)) { + return; + } + + final List addresses; + try { + addresses = Arrays.asList(SocketUtils.allAddressesByName(inetHost)); + } catch (UnknownHostException e) { + promise.setFailure(e); + return; + } + + // Even if _one_ of the addresses is disallowed, we fail the request. + for (InetAddress address : addresses) { + if (isDisallowedAndFail(address.getHostAddress(), promise)) { + return; + } + } + + promise.setSuccess(addresses); + } } } diff --git a/app/server/appsmith-plugins/graphqlPlugin/src/main/java/com/external/plugins/GraphQLPlugin.java b/app/server/appsmith-plugins/graphqlPlugin/src/main/java/com/external/plugins/GraphQLPlugin.java index 8cda9bd184..8453494cce 100644 --- a/app/server/appsmith-plugins/graphqlPlugin/src/main/java/com/external/plugins/GraphQLPlugin.java +++ b/app/server/appsmith-plugins/graphqlPlugin/src/main/java/com/external/plugins/GraphQLPlugin.java @@ -27,7 +27,6 @@ import reactor.core.publisher.Mono; import java.net.URI; import java.net.URISyntaxException; -import java.net.UnknownHostException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -37,12 +36,12 @@ import java.util.Set; import static com.appsmith.external.helpers.PluginUtils.getValueSafelyFromPropertyList; import static com.appsmith.external.helpers.PluginUtils.setValueSafelyInPropertyList; import static com.external.utils.GraphQLBodyUtils.PAGINATION_DATA_INDEX; -import static com.external.utils.GraphQLDataTypeUtils.smartlyReplaceGraphQLQueryBodyPlaceholderWithValue; -import static com.external.utils.GraphQLPaginationUtils.updateVariablesWithPaginationValues; import static com.external.utils.GraphQLBodyUtils.QUERY_VARIABLES_INDEX; import static com.external.utils.GraphQLBodyUtils.convertToGraphQLPOSTBodyFormat; import static com.external.utils.GraphQLBodyUtils.getGraphQLQueryParamsForBodyAndVariables; import static com.external.utils.GraphQLBodyUtils.validateBodyAndVariablesSyntax; +import static com.external.utils.GraphQLDataTypeUtils.smartlyReplaceGraphQLQueryBodyPlaceholderWithValue; +import static com.external.utils.GraphQLPaginationUtils.updateVariablesWithPaginationValues; import static java.lang.Boolean.TRUE; import static org.apache.commons.lang3.StringUtils.isBlank; @@ -186,18 +185,6 @@ public class GraphQLPlugin extends BasePlugin { ActionExecutionRequest actionExecutionRequest = RequestCaptureFilter.populateRequestFields(actionConfiguration, uri, insertedParams, objectMapper); - try { - if (uriUtils.isHostDisallowed(uri)) { - errorResult.setBody(AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR.getMessage("Host not allowed.")); - errorResult.setRequest(actionExecutionRequest); - return Mono.just(errorResult); - } - } catch (UnknownHostException e) { - errorResult.setBody(AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR.getMessage("Unknown host.")); - errorResult.setRequest(actionExecutionRequest); - return Mono.just(errorResult); - } - WebClient.Builder webClientBuilder = triggerUtils.getWebClientBuilder(actionConfiguration, datasourceConfiguration); @@ -282,7 +269,7 @@ public class GraphQLPlugin extends BasePlugin { EXCHANGE_STRATEGIES, requestCaptureFilter); /* Triggering the actual REST API call */ - Set hintMessages = new HashSet(); + Set hintMessages = new HashSet<>(); return triggerUtils.triggerApiCall(client, httpMethod, uri, requestBodyObj, actionExecutionRequest, objectMapper, hintMessages, errorResult, requestCaptureFilter); diff --git a/app/server/appsmith-plugins/restApiPlugin/src/main/java/com/external/plugins/RestApiPlugin.java b/app/server/appsmith-plugins/restApiPlugin/src/main/java/com/external/plugins/RestApiPlugin.java index ec1ae5b910..86f9101cca 100644 --- a/app/server/appsmith-plugins/restApiPlugin/src/main/java/com/external/plugins/RestApiPlugin.java +++ b/app/server/appsmith-plugins/restApiPlugin/src/main/java/com/external/plugins/RestApiPlugin.java @@ -5,6 +5,8 @@ import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError; import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException; import com.appsmith.external.helpers.DataTypeStringUtils; import com.appsmith.external.helpers.MustacheHelper; +import com.appsmith.external.helpers.restApiUtils.connections.APIConnection; +import com.appsmith.external.helpers.restApiUtils.helpers.RequestCaptureFilter; import com.appsmith.external.models.ActionConfiguration; import com.appsmith.external.models.ActionExecutionRequest; import com.appsmith.external.models.ActionExecutionResult; @@ -15,18 +17,16 @@ import com.appsmith.external.models.Property; import com.appsmith.external.plugins.BasePlugin; import com.appsmith.external.plugins.BaseRestApiPluginExecutor; import com.appsmith.external.services.SharedConfig; -import com.appsmith.external.helpers.restApiUtils.connections.APIConnection; -import com.appsmith.external.helpers.restApiUtils.helpers.RequestCaptureFilter; import lombok.extern.slf4j.Slf4j; import org.pf4j.Extension; import org.pf4j.PluginWrapper; import org.springframework.http.HttpMethod; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; + import java.net.URI; import java.net.URISyntaxException; import java.net.URLDecoder; -import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashSet; @@ -125,7 +125,7 @@ public class RestApiPlugin extends BasePlugin { initUtils.initializeResponseWithError(errorResult); // Set of hint messages that can be returned to the user. - Set hintMessages = new HashSet(); + Set hintMessages = new HashSet<>(); // Initializing request URL String url = initUtils.initializeRequestUrl(actionConfiguration, datasourceConfiguration); @@ -148,18 +148,6 @@ public class RestApiPlugin extends BasePlugin { ActionExecutionRequest actionExecutionRequest = RequestCaptureFilter.populateRequestFields(actionConfiguration, uri, insertedParams, objectMapper); - try { - if (uriUtils.isHostDisallowed(uri)) { - errorResult.setBody(AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR.getMessage("Host not allowed.")); - errorResult.setRequest(actionExecutionRequest); - return Mono.just(errorResult); - } - } catch (UnknownHostException e) { - errorResult.setBody(AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR.getMessage("Unknown host.")); - errorResult.setRequest(actionExecutionRequest); - return Mono.just(errorResult); - } - WebClient.Builder webClientBuilder = triggerUtils.getWebClientBuilder(actionConfiguration, datasourceConfiguration); String reqContentType = headerUtils.getRequestContentType(actionConfiguration, datasourceConfiguration); From 37844fe85e2785eae7d724aa863823fb950b0048 Mon Sep 17 00:00:00 2001 From: Shrikant Sharat Kandula Date: Mon, 19 Sep 2022 13:49:27 +0530 Subject: [PATCH 5/5] Fix key file permissions error on Windows (#16862) --- deploy/docker/entrypoint.sh | 12 ++++++++---- deploy/docker/templates/supervisord/mongodb.conf | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/deploy/docker/entrypoint.sh b/deploy/docker/entrypoint.sh index e637aa545f..a5fb92d76f 100755 --- a/deploy/docker/entrypoint.sh +++ b/deploy/docker/entrypoint.sh @@ -128,7 +128,7 @@ init_mongodb() { if [[ ! -f "$MONGO_DB_KEY" ]]; then openssl rand -base64 756 > "$MONGO_DB_KEY" fi - chmod-mongodb-key "$MONGO_DB_KEY" + use-mongodb-key "$MONGO_DB_KEY" fi } @@ -157,7 +157,7 @@ init_replica_set() { mongo "127.0.0.1/appsmith" /appsmith-stacks/configuration/mongo-init.js echo "Enabling Replica Set" mongod --dbpath "$MONGO_DB_PATH" --shutdown || true - mongod --fork --port 27017 --dbpath "$MONGO_DB_PATH" --logpath "$MONGO_LOG_PATH" --replSet mr1 --keyFile "$MONGO_DB_KEY" --bind_ip localhost + mongod --fork --port 27017 --dbpath "$MONGO_DB_PATH" --logpath "$MONGO_LOG_PATH" --replSet mr1 --keyFile /mongodb-key --bind_ip localhost echo "Waiting 10s for MongoDB to start with Replica Set" sleep 10 mongo "$APPSMITH_MONGODB_URI" --eval 'rs.initiate()' @@ -180,8 +180,12 @@ init_replica_set() { fi } -chmod-mongodb-key() { - chmod 600 "$1" +use-mongodb-key() { + # This is a little weird. We copy the MongoDB key file to `/mongodb-key`, so that we can reliably set its permissions to 600. + # What affects the reliability of this? When the host machine of this Docker container is Windows, file permissions cannot be set on files in volumes. + # So the key file should be somewhere inside the container, and not in a volume. + cp -v "$1" /mongodb-key + chmod 600 /mongodb-key } # Keep Let's Encrypt directory persistent diff --git a/deploy/docker/templates/supervisord/mongodb.conf b/deploy/docker/templates/supervisord/mongodb.conf index f1024c08c1..a1d6ae4c52 100644 --- a/deploy/docker/templates/supervisord/mongodb.conf +++ b/deploy/docker/templates/supervisord/mongodb.conf @@ -1,6 +1,6 @@ [program:mongodb] directory=/appsmith-stacks/data/mongodb -command=mongod --port 27017 --dbpath . --logpath /appsmith-stacks/logs/%(program_name)s/db.log --replSet mr1 --keyFile key --bind_ip localhost +command=mongod --port 27017 --dbpath . --logpath /appsmith-stacks/logs/%(program_name)s/db.log --replSet mr1 --keyFile /mongodb-key --bind_ip localhost priority=10 autostart=true autorestart=true