diff --git a/public/v4/apps/outline.yml b/public/v4/apps/outline.yml index d48bfae..b26cfd1 100644 --- a/public/v4/apps/outline.yml +++ b/public/v4/apps/outline.yml @@ -1,17 +1,14 @@ captainVersion: 4 services: $$cap_appname-redis: - image: redis:5 - caproverExtra: - notExposeAsWebApp: 'true' - $$cap_appname-fakes3: - image: lphoward/fake-s3 + image: redis:$$cap_redis_version volumes: - - $$cap_appname-fakes3:/fakes3_root + - $$cap_appname-redis-data:/redis.conf + restart: always caproverExtra: notExposeAsWebApp: 'true' $$cap_appname-db: - image: postgres:12.2 + image: postgres:$$cap_postgres_version volumes: - $$cap_appname-db-data:/var/lib/postgresql/data restart: always @@ -21,84 +18,206 @@ services: POSTGRES_DB: outline caproverExtra: notExposeAsWebApp: 'true' - $$cap_appname-outline: + $$cap_appname: depends_on: - - $$cap_appname-fakes3 - $$cap_appname-redis - $$cap_appname-db image: outlinewiki/outline:$$cap_outline_version environment: SECRET_KEY: $$cap_secret_key UTILS_SECRET: $$cap_utils_secret - AWS_ACCESS_KEY_ID: get_a_key_from_aws - AWS_SECRET_ACCESS_KEY: get_the_secret_of_above_key - AWS_REGION: xx-xxxx-x - AWS_S3_UPLOAD_BUCKET_URL: http://srv-captain--$$cap_appname-fakes3:4569 - AWS_S3_UPLOAD_BUCKET_NAME: bucket_name_here + DATABASE_URL: postgres://$$cap_db_user:$$cap_db_pass@srv-captain--$$cap_appname-db:5432/outline + DATABASE_URL_TEST: postgres://$$cap_db_user:$$cap_db_pass@srv-captain--$$cap_appname-db:5432/outline-test + PGSSLMODE: disable + REDIS_URL: redis://srv-captain--$$cap_appname-redis:6379 + URL: https://$$cap_appname.$$cap_root_domain + PORT: '80' + AWS_S3_UPLOAD_BUCKET_URL: $$cap_s3_storage_url + AWS_REGION: $$cap_s3_storage_region + AWS_S3_UPLOAD_BUCKET_NAME: $$cap_s3_storage_bucket_name + AWS_ACCESS_KEY_ID: $$cap_s3_storage_access_key_id + AWS_SECRET_ACCESS_KEY: $$cap_s3_storage_secret_access_key AWS_S3_UPLOAD_MAX_SIZE: '26214400' + AWS_S3_FORCE_PATH_STYLE: true AWS_S3_ACL: private + OIDC_CLIENT_ID: $$cap_oidc_client_id + OIDC_CLIENT_SECRET: $$cap_oidc_client_secret + OIDC_AUTH_URI: $$cap_oidc_auth_uri + OIDC_TOKEN_URI: $$cap_oidc_token_uri + OIDC_USERINFO_URI: $$cap_oidc_userinfo_uri + OIDC_USERNAME_CLAIM: preferred_username + OIDC_DISPLAY_NAME: OpenID + OIDC_SCOPES: 'openid profile email' SLACK_KEY: $$cap_slack_key SLACK_SECRET: $$cap_slack_secret GOOGLE_CLIENT_ID: $$cap_google_client_id GOOGLE_CLIENT_SECRET: $$cap_google_client_secret FORCE_HTTPS: 'false' - DEPLOYMENT: self ENABLE_UPDATES: 'false' - SUBDOMAINS_ENABLED: 'false' - WEBSOCKETS_ENABLED: 'false' - DEBUG: cache,presenters,events - URL: https://$$cap_appname-outline.$$cap_root_domain - PORT: '80' - REDIS_URL: redis://srv-captain--$$cap_appname-redis:6379 - DATABASE_URL_TEST: postgres://$$cap_db_user:$$cap_db_pass@srv-captain--$$cap_appname-db:5432/outline-test - DATABASE_URL: postgres://$$cap_db_user:$$cap_db_pass@srv-captain--$$cap_appname-db:5432/outline + DEBUG: http + SMTP_HOST: $$cap_smtp_host + SMTP_PORT: $$cap_smtp_port + SMTP_USERNAME: $$cap_smtp_username + SMTP_PASSWORD: $$cap_smtp_password + SMTP_FROM_EMAIL: $$cap_smtp_from_email + SMTP_REPLY_EMAIL: $$cap_smtp_reply_email + SMTP_TLS_CIPHERS: $$cap_smtp_tls_ciphers + SMTP_SECURE: $$cap_smtp_secure + DEFAULT_LANGUAGE: $$cap_default_language caproverOneClickApp: variables: + - id: $$cap_outline_version + label: Outline Version + defaultValue: 0.64.3 + description: Check out their page for the valid tags https://hub.docker.com/r/outlinewiki/outline/tags + validRegex: /^([^\s^\/])+$/ + - id: $$cap_postgres_version + label: Postgres Version + defaultValue: '14.4' + description: Check out their page for the valid tags https://hub.docker.com/_/postgres?tab=tags + validRegex: /^([^\s^\/])+$/ + - id: $$cap_redis_version + label: Redis Version + defaultValue: 7.0.2 + description: Check out their Docker page for the valid tags https://hub.docker.com/_/redis?tab=tags + validRegex: /^([^\s^\/])+$/ + - id: $$cap_secret_key + label: SECRET_KEY + description: 'Run this command to generate a key: `openssl rand -hex 32`' + validRegex: /^([0-9a-f]){64}$/ + - id: $$cap_utils_secret + label: UTILS_SECRET + description: 'Run this command to generate a key: `openssl rand -hex 32`' + validRegex: /^([0-9a-f]){64}$/ - id: $$cap_db_user label: Database user - defaultValue: outlineuser - validRegex: /^([a-zA-Z0-9])+$/ + defaultValue: outline_user + validRegex: /^([a-zA-Z0-9_])+$/ - id: $$cap_db_pass label: Database password description: '' + defaultValue: $$cap_gen_random_hex(20) validRegex: /.{8,}/ + - id: $$cap_s3_storage_url + label: S3 Storage compatible API URL for instance Minio, AWS, etc. + description: 'NB: You can have your own S3 storage by using the Open Source Minio alternative (there is a Caprover one-click-apps for that)' + defaultValue: https://YOUR_S3_STORAGE_PROVIDER_API_URL + - id: $$cap_s3_storage_region + label: S3 Storage region + description: 'Name of the location of the server e.g. "us-west-rack2"' + defaultValue: eu-east-1 + - id: $$cap_s3_storage_bucket_name + label: S3 Storage bucket name + description: "Log into the Minio dashboard, then select the `Create Bucket` menu option to create a new bucket (e.g. named outline-data). Don't forget to add `Read and Write` policy to the bucket so the Outline app would be able to upload content" + defaultValue: outline-data + - id: $$cap_s3_storage_access_key_id + label: S3 storage Access Key ID + description: 'For instance in your Minio instance, create a new user called outline_user for the outline app with a new policy that grants full access inside the bucket (e.g. outlineAppFullAccess - see also https://wiki.generaloutline.com/share/125de1cc-9ff6-424b-8415-0d58c809a40f#h-iam-policy)' + defaultValue: outline_user + - id: $$cap_s3_storage_secret_access_key + label: S3 storage Secret Access Key + description: 'For instance in your Minio instance it correponds to the password/secret of above outline_user' + - id: $$cap_oidc_client_id + label: Client ID created in your Generic OIDC server (e.g. in Keycloak) + description: 'E.g. for Keycloak: In the Clients section, create a new client application. Name the app outline_app for simplicity. Also, provide the Root URL where you have installed/planned to install Outline. After that, make sure `Access Type` is set to `confidential` and `Direct Access Grants Enabled` is `OFF` so the Oauth flow initiated by Outline can work as expected.' + defaultValue: outline_app + - id: $$cap_oidc_client_secret + label: Secret for the corresponding Client ID + description: 'Found in the Credentials tab in Keycloak' + - id: $$cap_oidc_auth_uri + label: Authorization Endpoint + description: 'In the recent version of Keycloak, the path /auth/ is optional, and the default master realm is not recommended for anything else except managing Keycloak itself. For example you could name the realm `outline`: http://localhost:8080/realms/outline/protocol/openid-connect/auth' + defaultValue: 'https://YOUR_IAM_PROVIDER_URL/realms/outline/protocol/openid-connect/auth' + - id: $$cap_oidc_token_uri + label: Token Management Endpoint + description: 'For example with the realm named `outline`: http://localhost:8080/realms/outline/protocol/openid-connect/token' + defaultValue: 'https://YOUR_IAM_PROVIDER_URL/realms/outline/protocol/openid-connect/token' + - id: $$cap_oidc_userinfo_uri + label: User Informations Endpoint + description: 'For example with the realm named `outline`: http://localhost:8080/realms/outline/protocol/openid-connect/userinfo' + defaultValue: 'https://YOUR_IAM_PROVIDER_URL/realms/outline/protocol/openid-connect/userinfo' - id: $$cap_slack_key label: Slack Key - description: 'IMPORTANT: You need to, at least, set one 3rd party login method, either Slack or Google' - defaultValue: get_a_key_from_slack - id: $$cap_slack_secret label: Slack Secret - description: '' - defaultValue: get_the_secret_of_above_key - id: $$cap_google_client_id label: Google Client ID - id: $$cap_google_client_secret label: Google Client Secret - description: '' - - id: $$cap_secret_key - label: SECRET_KEY - description: 'Run this command to generate a key: openssl rand -hex 32' - defaultValue: c63eaeed7ee7459098e2901ed87c8b70817428b85fbe3ef59cb6a79abb2bbf4a - validRegex: /^([0-9a-f]){64}$/ - - id: $$cap_utils_secret - label: UTILS_SECRET - description: 'Run this command to generate a key: openssl rand -hex 32' - defaultValue: c9b4d178130f53efc7419eaec9a2e764481269c9602c2ef2e541bdadc63b5bbf - validRegex: /^([0-9a-f]){64}$/ - - id: $$cap_outline_version - label: Outline Version - defaultValue: version-0.41.0 - description: Check out their page for the valid tags https://hub.docker.com/r/outlinewiki/outline/tags - validRegex: /^([^\s^\/])+$/ + - id: $$cap_smtp_host + label: SMTP host + description: To support sending outgoing transactional emails such as "document updated" or "you've been invited" you'll need to provide authentication for an SMTP server + - id: $$cap_smtp_port + label: SMTP port + - id: $$cap_smtp_username + label: SMTP username + - id: $$cap_smtp_password + label: SMTP password + - id: $$cap_smtp_from_email + label: SMTP from email + - id: $$cap_smtp_reply_email + label: SMTP reply email + - id: $$cap_smtp_tls_ciphers + label: SMTP TLS ciphers + - id: $$cap_smtp_secure + label: SMTP Secure + defaultValue: true + - id: $$cap_default_language + label: The default interface language + description: See translate.getoutline.com for a list of available language codes and their rough percentage translated. + defaultValue: en_US instructions: - start: Outline is an open, extensible, wiki for your team built using React and Node.js. + start: > + Outline is an open, extensible, wiki for your team built using React and Node.js. + + + Outline requires an external authentication provider such as Google/Slack, etc. + If you don't want to rely on those solutions you can use a generic OpenID Connect Server. + For instance you can use the Open Source Keycloak alternative (there is a Caprover one-click-apps for that) + + + IMPORTANT: You need to, at least, set one 3rd party login method, either Keycloak, Slack or Google end: > IMPORTANT: before you start using Outline, you need to 1) Enable HTTPS 2) Force HTTPS - 3) Enable Websocket in $$cap_appname-outline. - 4) Run database migration `npm run sequelize:migrate` within the $$cap_appname-outline docker container. + 3) Enable Websocket in $$cap_appname. + 4) Run database migration `npm run sequelize:migrate` within the $$cap_appname docker container. + + + ``` + var preDeployFunction = async function (captainAppObj, dockerUpdateObject) { + const DockerApi = require("./built/docker/DockerApi"); + const api = new DockerApi.default(); + + const setServiceInstances = async (service, count) => { + const inspection = await service.inspect(); + const updateObject = { ...inspection.Spec, Mode: { Replicated: { Replicas: count } }, version: inspection.Version.Index }; + await service.update(updateObject); + }; + + const run = async args => { + const imageName = dockerUpdateObject.TaskTemplate.ContainerSpec.Image; + const env = captainAppObj.envVars.map(kv => kv.key + "=" + kv.value); + const config = { Env: env, HostConfig: { AutoRemove: true, NetworkMode: captainAppObj.networks[0] } }; + + const [output] = await api.dockerode.run(imageName, args, process.stdout, config); + + if (output.StatusCode !== 0) { + throw new Error(`Failed to run image ${imageName} with args ${args} (status code ${output.StatusCode}).`); + } + }; + + const service = api.dockerode.getService(dockerUpdateObject.Name); + await setServiceInstances(service, 0); + await run(["yarn", "sequelize:migrate", "--env=production-ssl-disabled"]); + dockerUpdateObject.version = (await service.inspect()).Version.Index; + + return dockerUpdateObject; + }; + ``` + You can customize more settings by environmental variables described here: https://github.com/outline/outline/blob/0deecfac446c37545e0787b3d32062e608a950ab/.env.sample